B
    GFFb9                 @   s   d dl Z d dlZd dlZddlmZ ddlmZmZ ddlm	Z	m
Z
mZmZ ejdkrdd dlmZ nd dlZdd	 ZG d
d deZG dd dZG dd dZdd ZdS )    N   )_tracing)_Result
_multicall)HookImpl
_HookRelay_HookCallernormalize_hookimpl_opts)      )metadatac             C   s"   t j| t| |jj|jjd d S )N)linenofilename)warningswarn_explicittype__code__co_firstlinenoco_filename)Zwarningfunction r   .lib/python3.7/site-packages/pluggy/_manager.py_warn_for_function   s
    r   c                   s    e Zd ZdZ fddZ  ZS )PluginValidationErrorzplugin failed validation.

    :param object plugin: the plugin which failed validation,
        may be a module or an arbitrary object.
    c                s   || _ tt| | d S )N)pluginsuper	Exception__init__)selfr   message)	__class__r   r   r      s    zPluginValidationError.__init__)__name__
__module____qualname____doc__r   __classcell__r   r   )r    r   r      s   r   c               @   s6   e Zd ZdZdd Zedd ZdddZd	d
 ZdS )
DistFacadez$Emulate a pkg_resources Distributionc             C   s
   || _ d S )N)_dist)r   distr   r   r   r   '   s    zDistFacade.__init__c             C   s
   | j d S )Nname)r   )r   r   r   r   project_name*   s    zDistFacade.project_nameNc             C   s   t | j||S )N)getattrr'   )r   attrdefaultr   r   r   __getattr__.   s    zDistFacade.__getattr__c             C   s   t t| jddg S )Nr'   r*   )sorteddirr'   )r   r   r   r   __dir__1   s    zDistFacade.__dir__)N)	r!   r"   r#   r$   r   propertyr*   r.   r1   r   r   r   r   r&   $   s
   
r&   c               @   s   e Zd ZdZdd Zdd Zd3ddZd	d
 Zd4ddZdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd  Zd!d" Zd#d$ Zd5d%d&Zd'd( Zd)d* Zd+d, Zd-d. Zd/d0 Zd1d2 ZdS )6PluginManagera  Core :py:class:`.PluginManager` class which manages registration
    of plugin objects and 1:N hook calling.

    You can register new hooks by calling :py:meth:`add_hookspecs(module_or_class)
    <.PluginManager.add_hookspecs>`.
    You can register plugin objects (which contain hooks) by calling
    :py:meth:`register(plugin) <.PluginManager.register>`.  The :py:class:`.PluginManager`
    is initialized with a prefix that is searched for in the names of the dict
    of registered plugin objects.

    For debugging purposes you can call :py:meth:`.PluginManager.enable_tracing`
    which will subsequently send debug information to the trace helper.
    c             C   s:   || _ i | _i | _g | _t d| _t | _	t
| _d S )NZpluginmanage)r*   _name2plugin_plugin2hookcallers_plugin_distinfor   Z	TagTracergettracer   hookr   _inner_hookexec)r   r*   r   r   r   r   D   s    zPluginManager.__init__c             C   s   |  ||||S )N)r:   )r   	hook_namemethodskwargsfirstresultr   r   r   	_hookexecM   s    zPluginManager._hookexecNc       	      C   s"  |p|  |}|| jks"|| jkrL| j|ddkr8dS td||| jf || j|< g  | j|< }xt|D ]}| ||}|dk	rnt| t||}t	||||}|dp|}t| j
|d}|dkrt|| j}t| j
|| n | r| || || || || qnW |S )zRegister a plugin and return its canonical name or ``None`` if the name
        is blocked from registering.  Raise a :py:class:`ValueError` if the plugin
        is already registered.Nz#Plugin already registered: %s=%s
%sZspecname)get_canonical_namer4   r5   r7   
ValueErrorr0   parse_hookimpl_optsr	   r+   r   r9   r   r?   setattrhas_spec_verify_hookZ_maybe_apply_history_add_hookimplappend)	r   r   r)   plugin_nameZhookcallersZhookimpl_optsmethodhookimplr9   r   r   r   registerR   s4    




zPluginManager.registerc             C   sb   t ||}t|sd S yt || jd d }W n tk
rF   i }Y nX |d k	r^t|ts^d }|S )NZ_impl)r+   inspectZ	isroutiner*   r   
isinstancedict)r   r   r)   rJ   Zresr   r   r   rC   x   s    


z!PluginManager.parse_hookimpl_optsc             C   sn   |dkr"|dk	st d| |}|dkr4| |}| j|rH| j|= x | j|g D ]}|| qXW |S )zlunregister a plugin object and all its contained hook implementations
        from internal data structures.Nz+one of name or plugin needs to be specified)AssertionErrorget_name
get_pluginr4   r7   r5   popZ_remove_plugin)r   r   r)   Z
hookcallerr   r   r   
unregister   s    

zPluginManager.unregisterc             C   s   | j |d d| j|< dS )zHblock registrations of the given name, unregister if already registered.)r)   N)rT   r4   )r   r)   r   r   r   set_blocked   s    zPluginManager.set_blockedc             C   s   || j ko| j | dkS )z4return ``True`` if the given plugin name is blocked.N)r4   )r   r)   r   r   r   
is_blocked   s    zPluginManager.is_blockedc             C   s   g }xt |D ]}| ||}|dk	rt| j|d}|dkr\t|| j||}t| j|| n*||| x| D ]}| 	|| qrW |
| qW |std| jd|dS )zadd new hook specifications defined in the given ``module_or_class``.
        Functions are recognized if they have been decorated accordingly.Nzdid not find any z
 hooks in )r0   parse_hookspec_optsr+   r9   r   r?   rD   Zset_specificationget_hookimplsrF   rH   rB   r*   )r   module_or_classnamesr)   Z	spec_optshcZhookfunctionr   r   r   add_hookspecs   s    zPluginManager.add_hookspecsc             C   s   t ||}t || jd d S )N_spec)r+   r*   )r   rY   r)   rJ   r   r   r   rW      s    
z!PluginManager.parse_hookspec_optsc             C   s
   t | jS )z%return the set of registered plugins.)setr5   )r   r   r   r   get_plugins   s    zPluginManager.get_pluginsc             C   s
   || j kS )z4Return ``True`` if the plugin is already registered.)r5   )r   r   r   r   r   is_registered   s    zPluginManager.is_registeredc             C   s   t |ddptt|S )aV  Return canonical name for a plugin object. Note that a plugin
        may be registered under a different name which was specified
        by the caller of :py:meth:`register(plugin, name) <.PluginManager.register>`.
        To obtain the name of an registered plugin use :py:meth:`get_name(plugin)
        <.PluginManager.get_name>` instead.r!   N)r+   strid)r   r   r   r   r   rA      s    z PluginManager.get_canonical_namec             C   s   | j |S )z/Return a plugin or ``None`` for the given name.)r4   r7   )r   r)   r   r   r   rR      s    zPluginManager.get_pluginc             C   s   |  |dk	S )z>Return ``True`` if a plugin with the given name is registered.N)rR   )r   r)   r   r   r   
has_plugin   s    zPluginManager.has_pluginc             C   s(   x"| j  D ]\}}||kr|S qW dS )z@Return name for registered plugin or ``None`` if not registered.N)r4   items)r   r   r)   valr   r   r   rQ      s    zPluginManager.get_namec             C   s   |  r&|jr&t|jd|j|jf |jjr>t|jj|j	 t
|jt
|jj }|rzt|jd|j|jt|j	|f |jrt|j	st|jd|j|jt|j	f d S )Nz6Plugin %r
hook %r
historic incompatible to hookwrapperz~Plugin %r for hook %r
hookimpl definition: %s
Argument(s) %s are declared in the hookimpl but can not be found in the hookspeczsPlugin %r for hook %r
hookimpl definition: %s
Declared as hookwrapper=True but function is not a generator function)Zis_historicZhookwrapperr   r   rI   r)   specZwarn_on_implr   r   r^   Zargnames
_formatdefrM   Zisgeneratorfunction)r   r9   rK   Z	notinspecr   r   r   rF      s*    
zPluginManager._verify_hookc             C   sd   x^| j jD ]R}|d dkr
t| j |}| s
x,| D ] }|js8t|jd||jf q8W q
W dS )zVerify that all hooks which have not been verified against
        a hook specification are optional, otherwise raise :py:class:`.PluginValidationError`.r   _zunknown hook %r in plugin %rN)r9   __dict__r+   rE   rX   Zoptionalhookr   r   )r   r)   r9   rK   r   r   r   check_pending   s    zPluginManager.check_pendingc             C   s   d}xt t D ]~}xx|jD ]n}|j|ks|dk	r>|j|ks| |js| |jrXq| }| j	||jd | j
|t|f |d7 }qW qW |S )a*  Load modules from querying the specified setuptools ``group``.

        :param str group: entry point group to load plugins
        :param str name: if given, loads only plugins with the given ``name``.
        :rtype: int
        :return: return the number of loaded plugins by this call.
        r   N)r)   r   )listimportlib_metadataZdistributionsZentry_pointsgroupr)   rR   rV   loadrL   r6   rH   r&   )r   rm   r)   countr(   Zepr   r   r   r   load_setuptools_entrypoints  s    
z)PluginManager.load_setuptools_entrypointsc             C   s
   t | jS )zTreturn list of distinfo/plugin tuples for all setuptools registered
        plugins.)rk   r6   )r   r   r   r   list_plugin_distinfo%  s    z"PluginManager.list_plugin_distinfoc             C   s   t | j S )z!return list of name/plugin pairs.)rk   r4   rd   )r   r   r   r   list_name_plugin*  s    zPluginManager.list_name_pluginc             C   s   | j |S )z.get all hook callers for the specified plugin.)r5   r7   )r   r   r   r   r   get_hookcallers.  s    zPluginManager.get_hookcallersc                s.   j  fdd}|_ fdd}|S )aP  add before/after tracing functions for all hooks
        and return an undo function which, when called,
        will remove the added tracers.

        ``before(hook_name, hook_impls, kwargs)`` will be called ahead
        of all hook calls and receive a hookcaller instance, a list
        of HookImpl instances and the keyword arguments for the hook call.

        ``after(outcome, hook_name, hook_impls, kwargs)`` receives the
        same arguments as ``before`` but also a :py:class:`pluggy._callers._Result` object
        which represents the result of the overall hook call.
        c                s<    t  fdd}| | S )Nc                  s    S )Nr   r   )r>   
hook_implsr;   r=   oldcallr   r   <lambda>D      zPPluginManager.add_hookcall_monitoring.<locals>.traced_hookexec.<locals>.<lambda>)r   Z	from_call
get_result)r;   rt   r=   r>   outcome)afterbeforeru   )r>   rt   r;   r=   r   traced_hookexecA  s
    z>PluginManager.add_hookcall_monitoring.<locals>.traced_hookexecc                  s
    _ d S )N)r:   r   )ru   r   r   r   undoK  s    z3PluginManager.add_hookcall_monitoring.<locals>.undo)r:   )r   r{   rz   r|   r}   r   )rz   r{   ru   r   r   add_hookcall_monitoring2  s
    z%PluginManager.add_hookcall_monitoringc                s2   | j jd  fdd} fdd}| ||S )z9enable tracing of hook calls and return an undo function.r9   c                s    j  jd7  _ | | d S )Nr   )rootindent)r;   r<   r=   )	hooktracer   r   r{   T  s    z,PluginManager.enable_tracing.<locals>.beforec                s0   | j d kr d|d|    j jd8  _d S )NZfinishz-->r   )excinforx   r   r   )ry   r;   r<   r=   )r   r   r   rz   X  s    
z+PluginManager.enable_tracing.<locals>.after)r8   r   r7   r~   )r   r{   rz   r   )r   r   enable_tracingP  s    zPluginManager.enable_tracingc                s   t | j } fdd|D }|r~t|j|j|jj|jj}x<| D ]0}|j	}||krF|
| | j|g | qFW |S |S )zReturn a new :py:class:`._hooks._HookCaller` instance for the named method
        which manages calls to all registered plugins except the
        ones from remove_plugins.c                s   g | ]}t | r|qS r   )hasattr).0Zplug)r)   r   r   
<listcomp>d  s    z4PluginManager.subset_hook_caller.<locals>.<listcomp>)r+   r9   r   r)   r?   rf   	namespaceZoptsrX   r   rG   r5   
setdefaultrH   )r   r)   Zremove_pluginsZorigZplugins_to_remover[   rK   r   r   )r)   r   subset_hook_caller_  s    
z PluginManager.subset_hook_caller)N)NN)N)r!   r"   r#   r$   r   r?   rL   rC   rT   rU   rV   r\   rW   r_   r`   rA   rR   rc   rQ   rF   rj   rp   rq   rr   rs   r~   r   r   r   r   r   r   r3   5   s2   	
&
#
r3   c             C   s   | j  t|  S )N)r!   rM   Z	signature)funcr   r   r   rg   t  s    rg   )rM   sysr    r   Z_callersr   r   Z_hooksr   r   r   r	   version_info	importlibr   rl   r   r   r   r&   r3   rg   r   r   r   r   <module>   s   
	  A