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