o
    q+WZ                     @   s   d dl Z d dlZd dlmZ d dlmZmZ dd Zdd ZG dd	 d	e	Z
G d
d de
ZG dd de
Zdd Zdd ZdS )    N)MethodicalMachine)PythonModule	getModulec                 C   sD   t |  }|du rdS | }t|ts|j}t|tr|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   onObjectname__name__)attrsourceModulecurrentModule r   3/usr/lib/python3/dist-packages/automat/_discover.pyisOriginalLocation   s   

r   c                 c   s    t | g}t }|rc| }| }t|tr)||vr)|| |j|fV  n6t	
|rCt|rC||vrC|| ||  nt|tr_||vr_|| ||  ||  |sdS 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   addr
   r   isclassr   
extendleftiterAttributesr   iterModules)withinqueuevisitedr   valuer   r   r   findMachinesViaWrapper   s&   


r   c                   @      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!   >       r!   c                   @   r    )NoModulezG
    A prefix of the FQPN was not an importable module or package.
    Nr"   r   r   r   r   r'   D   r&   r'   c                   @   r    )NoObjectz;
    A suffix of the FQPN was not an accessible object
    Nr"   r   r   r   r   r(   J   r&   r(   c              	      s   | st dt| d}d|v rt d| f |  zt }W n ty.   t w |rP|  z|  }W n tyI   |  Y n	w |	  |s1|S |}|D ]! zt
 fdd| D }W qV tyw   td|j w |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)      N)r
   rsplit).0child	componentr   r   	<genexpr>y   s    zwrapFQPN.<locals>.<genexpr>z{}.{})r!   r   r   splitpopleftr   KeyErrorr'   
appendleftr   nextr   StopIterationr(   formatr
   )fqpn
componentsmodule	attributer   r0   r   wrapFQPNP   sD   

r>   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.

    @type within: an FQPN
    @param within: Where to start the search.

    @return: a generator which yields FQPN, L{MethodicalMachine} pairs.
    )r   r>   )r:   r   r   r   findMachines   s   r?   )r   r   automatr   twisted.python.modulesr   r   r   r   	Exceptionr!   r'   r(   r>   r?   r   r   r   r   <module>   s    &1