U
    j5{iM  ã                   @  sÔ   d dl mZ d dlZd dlZd dlmZmZ d dlmZm	Z	m
Z
 d dlmZ ddlmZmZmZ dd	d
œdd„Zdddœdd„ZG dd„ deƒZG dd„ deƒZG dd„ deƒZdddœdd„Zdddœdd„ZdS )é    )ÚannotationsN)ÚAnyÚIterator)ÚPythonAttributeÚPythonModuleÚ	getModule)ÚMethodicalMachineé   )ÚTypeMachineÚInputProtocolÚCorezPythonAttribute | PythonModuleÚbool)ÚattrÚreturnc                 C  s<   t  |  ¡ ¡}|dkrdS | }t|tƒs0|j}q|j|jkS )z•
    Attempt to discover if this appearance of a PythonAttribute
    representing a class refers to the module where that class was
    defined.
    NF)ÚinspectÚ	getmoduleÚloadÚ
isinstancer   ZonObjectÚnameÚ__name__)r   ZsourceModuleZcurrentModule© r   ú5/tmp/pip-unpacked-wheel-9dyvm7t1/automat/_discover.pyÚisOriginalLocation   s    
r   zPythonModule | PythonAttributezJIterator[tuple[str, MethodicalMachine | TypeMachine[InputProtocol, Core]]])Úwithinr   c                 c  sÌ   t  | g¡}tƒ }|rÈ| ¡ }| ¡ }t|tƒs:t|tƒrZ||krZ| |¡ |j	|fV  qt
 |¡rŽt|ƒrŽ||krŽ| |¡ | | ¡ ¡ qt|tƒr||kr| |¡ | | ¡ ¡ | | ¡ ¡ qdS )aÁ  
    Recursively yield L{MethodicalMachine}s and their FQPNs within a
    L{PythonModule} or a L{twisted.python.modules.PythonAttribute}
    wrapper object.

    Note that L{PythonModule}s may refer to packages, as well.

    The discovery heuristic considers L{MethodicalMachine} instances
    that are module-level attributes or class-level attributes
    accessible from module scope.  Machines inside nested classes will
    be discovered, but those returned from functions or methods will not be.

    @type within: L{PythonModule} or L{twisted.python.modules.PythonAttribute}
    @param within: Where to start the search.

    @return: a generator which yields FQPN, L{MethodicalMachine} pairs.
    N)ÚcollectionsÚdequeÚsetÚpopr   r   r   r
   Úaddr   r   Úisclassr   Ú
extendleftÚiterAttributesr   ZiterModules)r   ÚqueueÚvisitedr   Úvaluer   r   r   ÚfindMachinesViaWrapper   s4    úÿÿþ
ÿÿÿ

r%   c                   @  s   e Zd ZdZdS )ÚInvalidFQPNzH
    The given FQPN was not a dot-separated list of Python objects.
    N©r   Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   r&   O   s   r&   c                   @  s   e Zd ZdZdS )ÚNoModulezG
    A prefix of the FQPN was not an importable module or package.
    Nr'   r   r   r   r   r+   U   s   r+   c                   @  s   e Zd ZdZdS )ÚNoObjectz;
    A suffix of the FQPN was not an accessible object
    Nr'   r   r   r   r   r,   [   s   r,   Ústr)Úfqpnr   c              	     s  | st dƒ‚t |  d¡¡}d|kr2t d| f ƒ‚| ¡ ‰ ztˆ ƒ}W n tk
rb   tˆ ƒ‚Y nX |rª| ¡ ‰ z|ˆ  }W n" tk
rž   | ˆ ¡ Y q®Y qdX | 	¡  qd|S |}|D ]J‰ zt
‡ fdd„| ¡ D ƒƒ}W q¶ tk
rþ   td |jˆ ¡ƒ‚Y q¶X q¶|S )z®
    Given an FQPN, retrieve the object via the global Python module
    namespace and wrap it with a L{PythonModule} or a
    L{twisted.python.modules.PythonAttribute}.
    zFQPN was emptyÚ.Ú zOname must be a string giving a '.'-separated list of Python identifiers, not %rc                 3  s(   | ] }|j  d d¡d ˆ kr|V  qdS )r/   r	   éÿÿÿÿN)r   Úrsplit)Ú.0Úchild©Ú	componentr   r   Ú	<genexpr>‹   s   þzwrapFQPN.<locals>.<genexpr>z{}.{})r&   r   r   ÚsplitÚpopleftr   ÚKeyErrorr+   Ú
appendleftr   Únextr!   ÚStopIterationr,   Úformatr   )r.   Ú
componentsÚmoduleÚ	attributer   r5   r   ÚwrapFQPNa   s@    ÿÿ


þrB   c                 C  s   t t| ƒƒS )a¸  
    Recursively yield L{MethodicalMachine}s and their FQPNs in and under the a
    Python object specified by an FQPN.

    The discovery heuristic considers L{MethodicalMachine} instances that are
    module-level attributes or class-level attributes accessible from module
    scope.  Machines inside nested classes will be discovered, but those
    returned from functions or methods will not be.

    @param fqpn: a fully-qualified Python identifier (i.e. the dotted
        identifier of an object defined at module or class scope, including the
        package and modele names); where to start the search.

    @return: a generator which yields (C{FQPN}, L{MethodicalMachine}) pairs.
    )r%   rB   )r.   r   r   r   ÚfindMachines–   s    rC   )Ú
__future__r   r   r   Útypingr   r   Ztwisted.python.modulesr   r   r   Zautomatr   Z_typedr
   r   r   r   r%   Ú	Exceptionr&   r+   r,   rB   rC   r   r   r   r   Ú<module>   s   05