U
    u1‘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)ÚDevices©ÚDeviceNotFoundErrorc                    s   t  ˆ ¡‡ fdd„ƒ}|S )z\
    Allow Device discovery methods to return None instead of raising an
    exception.
    c                     s(   zˆ | |ŽW S  t k
r"   Y dS X dS )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_func1   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   s
   t ƒ ‚dS )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
        N©ÚNotImplementedError©ÚclsÚvaluer   r   r   ÚmatchD   s    zHypothesis.matchc                 C   s
   t ƒ ‚dS )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`
        Nr   )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k	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¡}| |¡}|o6t 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   Z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+)$Znumber)r+   r,   r   r/   r0   )r   r   Z	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
        )r1   r2   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
        Zdev)Úsys_pathr-   ÚlistdirÚpathÚjoin)r   r   r3   r   r   r   Úfind_subsystems¬   s    	z&DeviceNumberHypothesis.find_subsystemsc                    s8   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   s   | ]}ˆˆ |ˆƒV  qd S ©Nr   ©Ú.0Ús©r   r   r   r   r   Ú	<genexpr>Ã   s     z0DeviceNumberHypothesis.lookup.<locals>.<genexpr>c                 s   s   | ]}|d k	r|V  qd S r8   r   ©r:   Úrr   r   r   r=   Ä   s      )r   r   Zfrom_device_numberr7   r   ©r   r   r   Úresr   r<   r   r   ¸   s    

zDeviceNumberHypothesis.lookupN)
r!   r"   r#   r$   r%   r1   r2   r   r7   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   |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   Ì   s    zDevicePathHypothesis.matchc                 C   s(   t tjƒ||ƒ}|dk	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   Z	from_pathr   r@   r   r   r   r   Ö   s    
zDevicePathHypothesis.lookupN)r!   r"   r#   r$   r%   r   r   r   r   r   r   rB   Ç   s
   
	rB   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
        )ZbusÚclassZ	subsystemc                 3   s   | ]}t j ˆ |¡V  qd S r8   ©r-   r5   r6   )r:   Úname©r3   r   r   r=   ö   s     z7DeviceNameHypothesis.find_subsystems.<locals>.<genexpr>c                 s   s   | ]}t j |¡r|V  qd S r8   )r-   r5   Úisdir©r:   Údr   r   r   r=   ÷   s      c                 s   s"   | ]}t  |¡D ]
}|V  qqd S r8   )r-   r4   )r:   rK   Únr   r   r   r=   ø   s       )r3   r   )r   r   ZdirnamesZabsnamesZ	realnamesr   rH   r   r7   ë   s
    	z$DeviceNameHypothesis.find_subsystemsc                 C   s   |S )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   ú   s    zDeviceNameHypothesis.matchc                    s8   t tjƒ‰‡ ‡‡fdd„|  ˆ ¡D ƒ}tdd„ |D ƒƒS )rC   c                 3   s   | ]}ˆˆ |ˆƒV  qd S r8   r   r9   r<   r   r   r=     s     z.DeviceNameHypothesis.lookup.<locals>.<genexpr>c                 s   s   | ]}|d k	r|V  qd S r8   r   r>   r   r   r   r=     s      )r   r   Ú	from_namer7   r   r@   r   r<   r   r     s    

zDeviceNameHypothesis.lookupN)r!   r"   r#   r$   r%   r7   r   r   r   r   r   r   rD   ä   s   

	rD   c                   @   sZ   e Zd ZdZdddddddd	d
ddg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 r8   )ÚlistÚdevice_linksrJ   r   r   r   r=   5  s     
 z5DeviceFileHypothesis.get_link_dirs.<locals>.<genexpr>c                 s   s   | ]}|j D ]
}|V  qqd S r8   )rP   )r:   rK   Úlr   r   r   r=   6  s       c                 s   s   | ]}t j |¡V  qd S r8   )r-   r5   Údirname)r:   rQ   r   r   r   r=   7  s     )Zlist_devicesÚsortedÚset)r   r   ÚdevicesZdevices_with_linksZ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)rV   Ú
_LINK_DIRSr   r   r   r   r   9  s    	zDeviceFileHypothesis.setupc                 C   s   |S r8   r   r   r   r   r   r   D  s    zDeviceFileHypothesis.matchc                    sr   t tjƒ‰dˆkr4ˆˆ ˆƒ}|dk	r.t|fƒS tƒ S ‡fdd„| jD ƒ}‡ ‡fdd„|D ƒ}tdd„ |D ƒƒS 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 r8   rF   )r:   Zld)r   r   r   r=   [  s     z.DeviceFileHypothesis.lookup.<locals>.<genexpr>c                 3   s   | ]}ˆˆ |ƒV  qd S r8   r   )r:   Úf)r   r   r   r   r=   \  s     c                 s   s   | ]}|d k	r|V  qd S r8   r   rJ   r   r   r   r=   ]  s      )r   r   Zfrom_device_filer   rW   )r   r   r   ZdeviceÚfilesrU   r   r<   r   r   H  s    

zDeviceFileHypothesis.lookupN)
r!   r"   r#   r$   rW   r%   rV   r   r   r   r   r   r   r   rN     s*   õ



rN   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 r8   )Ú_HYPOTHESESÚ_hypotheses)Úselfr   r   r   Ú__init__m  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)r]   r   )r^   r   Zhypr   r   r   r   p  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 r8   )r    )r:   ÚhrK   ©r   r   r   r   r=   „  s      z(Discovery.get_devices.<locals>.<genexpr>)r   r]   )r^   r   r   r   ra   r   r    {  s    	ÿzDiscovery.get_devicesN)r!   r"   r#   r$   rN   rD   r(   rB   r\   r_   r   r    r   r   r   r   r[   `  s   ür[   )r$   Z
__future__r   r   r   r   r&   r   r-   r+   ZsixZpyudev.devicer   r   r   Zadd_metaclassÚABCMetaÚobjectr   r(   rB   rD   rN   r[   r   r   r   r   Ú<module>   s&   	
=K/M