o
    8g+^w,                     @   s   d Z ddlmZ ddlmZ ddlmZ ddlmZ ddlZddlZddlZddl	Z	ddl
Z
ddlmZ ddlmZ d	d
 Ze
ejG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZdS )z
    pyudev.discover
    ===============

    Tools to discover a device given limited information.

    .. moduleauthor::  mulhern <amulhern@redhat.com>
    )absolute_import)division)print_function)unicode_literalsNDeviceNotFoundError)Devicesc                    s   t   fdd}|S )z\
    Allow Device discovery methods to return None instead of raising an
    exception.
    c                     s&   z | i |W S  t y   Y dS w )z
        Returns result of calling ``func`` on ``args``, ``kwargs``.
        Returns None if ``func`` raises :exc:`DeviceNotFoundError`.
        Nr   )argskwargsfunc 1/usr/lib/python3/dist-packages/pyudev/discover.pythe_func0   s
   z wrap_exception.<locals>.the_func)	functoolswraps)r   r   r   r   r   wrap_exception*   s   
r   c                   @   sL   e Zd ZdZeejdd Zeejdd Zedd Z	edd	 Z
d
S )
HypothesiszM
    Represents a hypothesis about the meaning of the device identifier.
    c                 C      t  )a  
        Match the given string according to the hypothesis.

        The purpose of this method is to obtain a value corresponding to
        ``value`` if that is possible. It may use a regular expression, but
        in general it should just return ``value`` and let the lookup method
        sort out the rest.

        :param str value: the string to inspect
        :returns: the matched thing or None if unmatched
        :rtype: the type of lookup's key parameter or NoneType
        NotImplementedErrorclsvaluer   r   r   matchD   s   zHypothesis.matchc                 C   r   )aN  
        Lookup the given string according to the hypothesis.

        :param Context context: the pyudev context
        :param key: a key with which to lookup the device
        :type key: the type of match's return value if not None
        :returns: a list of Devices obtained
        :rtype: frozenset of :class:`Device`
        r   )r   contextkeyr   r   r   lookupU   s   zHypothesis.lookupc                 C   s   dS )z
        A potentially expensive method that may allow an :class:`Hypothesis`
        to find devices more rapidly or to find a device that it would
        otherwise miss.

        :param Context context: the pyudev context
        Nr   r   r   r   r   r   setupc   s   	zHypothesis.setupc                 C   s$   |  |}|dur| ||S t S )a  
        Get any devices that may correspond to the given string.

        :param Context context: the pyudev context
        :param str value: the value to look for
        :returns: a list of devices obtained
        :rtype: set of :class:`Device`
        N)r   r   	frozenset)r   r   r   r   r   r   r   get_devicesn   s   

zHypothesis.get_devicesN)__name__
__module____qualname____doc__classmethodabcabstractmethodr   r   r   r!   r   r   r   r   r   >   s    

r   c                   @   sL   e Zd ZdZedd Zedd Zedd Zedd	 Zed
d Z	dS )DeviceNumberHypothesisz
    Represents the hypothesis that the device is a device number.

    The device may be separated into major/minor number or a composite number.
    c                 C   s8   t d}||}|ott|dt|dS )z
        Match the number under the assumption that it is a major,minor pair.

        :param str value: value to match
        :returns: the device number or None
        :rtype: int or NoneType
        z#^(?P<major>\d+)(\D+)(?P<minor>\d+)$majorminor)recompiler   osmakedevintgroup)r   r   major_minor_rer   r   r   r   _match_major_minor   s
   
	
z)DeviceNumberHypothesis._match_major_minorc                 C   s&   t d}||}|ot|dS )z
        Match the number under the assumption that it is a single number.

        :param str value: value to match
        :returns: the device number or None
        :rtype: int or NoneType
        z^(?P<number>\d+)$number)r,   r-   r   r0   r1   )r   r   	number_rer   r   r   r   _match_number   s   
	
z$DeviceNumberHypothesis._match_numberc                 C   s   |  |p	| |S )z
        Match the number under the assumption that it is a device number.

        :returns: the device number or None
        :rtype: int or NoneType
        )r3   r6   r   r   r   r   r      s   zDeviceNumberHypothesis.matchc                 C   s   |j }ttj|dS )z
        Find subsystems in /sys/dev.

        :param Context context: the context
        :returns: a lis of available subsystems
        :rtype: list of str
        dev)sys_pathr.   listdirpathjoin)r   r   r8   r   r   r   find_subsystems   s   	z&DeviceNumberHypothesis.find_subsystemsc                    8   t tj fdd|  D }tdd |D S )z
        Lookup by the device number.

        :param Context context: the context
        :param int key: the device number
        :returns: a list of matching devices
        :rtype: frozenset of :class:`Device`
        c                 3       | ]	} |V  qd S Nr   .0sr   r   r   r   r   	<genexpr>       z0DeviceNumberHypothesis.lookup.<locals>.<genexpr>c                 s       | ]	}|d ur|V  qd S r?   r   rA   rr   r   r   rD      rE   )r   r   from_device_numberr<   r    r   r   r   resr   rC   r   r         

zDeviceNumberHypothesis.lookupN)
r"   r#   r$   r%   r&   r3   r6   r   r<   r   r   r   r   r   r)   |   s    


	
r)   c                   @   s(   e Zd ZdZedd Zedd ZdS )DevicePathHypothesiszG
    Discover the device assuming the identifier is a device path.
    c                 C      |S )z
        Match ``value`` under the assumption that it is a device path.

        :returns: the device path or None
        :rtype: str or NoneType
        r   r   r   r   r   r         zDevicePathHypothesis.matchc                 C   s(   t tj||}|durt|fS t S )
        Lookup by the path.

        :param Context context: the context
        :param str key: the device path
        :returns: a list of matching devices
        :rtype: frozenset of :class:`Device`
        N)r   r   	from_pathr    rJ   r   r   r   r      s   
zDevicePathHypothesis.lookupN)r"   r#   r$   r%   r&   r   r   r   r   r   r   rM      s    
	rM   c                   @   s4   e Zd ZdZedd Zedd Zedd ZdS )	DeviceNameHypothesiszf
    Discover the device assuming the input is a device name.

    Try every available subsystem.
    c                    s<   |j  d} fdd|D }dd |D }tdd |D S )z
        Find all subsystems in sysfs.

        :param Context context: the context
        :rtype: frozenset
        :returns: subsystems in sysfs
        )busclass	subsystemc                 3   s    | ]
}t j |V  qd S r?   r.   r:   r;   )rA   namer8   r   r   rD          z7DeviceNameHypothesis.find_subsystems.<locals>.<genexpr>c                 s   s     | ]}t j|r|V  qd S r?   )r.   r:   isdirrA   dr   r   r   rD          c                 s   s$    | ]}t |D ]}|V  q	qd S r?   )r.   r9   )rA   r\   nr   r   r   rD      s   " )r8   r    )r   r   dirnamesabsnames	realnamesr   rX   r   r<      s
   	z$DeviceNameHypothesis.find_subsystemsc                 C   rN   )z
        Match ``value`` under the assumption that it is a device name.

        :returns: the device path or None
        :rtype: str or NoneType
        r   r   r   r   r   r      rO   zDeviceNameHypothesis.matchc                    r=   )rP   c                 3   r>   r?   r   r@   rC   r   r   rD     rE   z.DeviceNameHypothesis.lookup.<locals>.<genexpr>c                 s   rF   r?   r   rG   r   r   r   rD     rE   )r   r   	from_namer<   r    rJ   r   rC   r   r      rL   zDeviceNameHypothesis.lookupN)r"   r#   r$   r%   r&   r<   r   r   r   r   r   r   rR      s    

	rR   c                   @   sH   e Zd ZdZg dZedd Zedd Zedd Zed	d
 Z	dS )DeviceFileHypothesisz
    Discover the device assuming the value is some portion of a device file.

    The device file may be a link to a device node.
    )z/devz/dev/disk/by-idz/dev/disk/by-labelz/dev/disk/by-partlabelz/dev/disk/by-partuuidz/dev/disk/by-pathz/dev/disk/by-uuidz/dev/input/by-pathz/dev/mapperz/dev/mdz/dev/vgc                 C   s:   |  }dd |D }dd |D }ttdd |D S )a7  
        Get all directories that may contain links to device nodes.

        This method checks the device links of every device, so it is very
        expensive.

        :param Context context: the context
        :returns: a sorted list of directories that contain device links
        :rtype: list
        c                 s   s    | ]
}t |jr|V  qd S r?   )listdevice_linksr[   r   r   r   rD   *  rY   z5DeviceFileHypothesis.get_link_dirs.<locals>.<genexpr>c                 s   s     | ]}|j D ]}|V  qqd S r?   )re   )rA   r\   lr   r   r   rD   +  r]   c                 s   s    | ]	}t j|V  qd S r?   )r.   r:   dirname)rA   rf   r   r   r   rD   ,  rE   )list_devicessortedset)r   r   devicesdevices_with_linkslinksr   r   r   get_link_dirs  s   z"DeviceFileHypothesis.get_link_dirsc                 C   s   |  || _dS )z
        Set the link directories to be used when discovering by file.

        Uses `get_link_dirs`, so is as expensive as it is.

        :param Context context: the context
        N)rn   
_LINK_DIRSr   r   r   r   r   .  s   	zDeviceFileHypothesis.setupc                 C   rN   r?   r   r   r   r   r   r   9  s   zDeviceFileHypothesis.matchc                    sn   t tjdv r }|durt|fS t S fdd| jD } fdd|D }tdd |D S )a  
        Lookup the device under the assumption that the key is part of
        the name of a device file.

        :param Context context: the context
        :param str key: a portion of the device file name

        It is assumed that either it is the whole name of the device file
        or it is the basename.

        A device file may be a device node or a device link.
        /Nc                 3   s    | ]
}t j| V  qd S r?   rV   )rA   ld)r   r   r   rD   P  rY   z.DeviceFileHypothesis.lookup.<locals>.<genexpr>c                 3   s    | ]} |V  qd S r?   r   )rA   f)r   r   r   r   rD   Q  s    c                 s   rF   r?   r   r[   r   r   r   rD   R  rE   )r   r   from_device_filer    ro   )r   r   r   devicefilesrk   r   rC   r   r   =  s   

zDeviceFileHypothesis.lookupN)
r"   r#   r$   r%   ro   r&   rn   r   r   r   r   r   r   r   rc     s    



rc   c                   @   s4   e Zd ZdZeeeegZdd Z	dd Z
dd ZdS )		Discoveryz1
    Provides discovery methods for devices.
    c                 C   s   | j | _d S r?   )_HYPOTHESES_hypotheses)selfr   r   r   __init__`  s   zDiscovery.__init__c                 C   s   | j D ]}|| qdS )z
        Set up individual hypotheses.

        May be an expensive call.

        :param Context context: the context
        N)rx   r   )ry   r   hypr   r   r   r   c  s   
zDiscovery.setupc                    s   t  fdd| jD S )z
        Get the devices corresponding to value.

        :param Context context: the context
        :param str value: some identifier of the device
        :returns: a list of corresponding devices
        :rtype: frozenset of :class:`Device`
        c                 3   s&    | ]}|  D ]}|V  q
qd S r?   )r!   )rA   hr\   r   r   r   r   rD   w  s    z(Discovery.get_devices.<locals>.<genexpr>)r    rx   )ry   r   r   r   r}   r   r!   n  s   	zDiscovery.get_devicesN)r"   r#   r$   r%   rc   rR   r)   rM   rw   rz   r   r!   r   r   r   r   rv   U  s    rv   )r%   
__future__r   r   r   r   r'   r   r.   r,   sixpyudev._errorsr   pyudev.devicer   r   add_metaclassABCMetaobjectr   r)   rM   rR   rc   rv   r   r   r   r   <module>   s(   	
=G/F