B
    `2                 @   sd  d 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l	m
Z
 ddl	mZ ddl	mZ ddl	mZ dd	l	mZ dd
l	mZ ddl	mZ ddl	mZ ddl	mZ ddlmZ ddlmZ ddlmZ edZedZedZeed dddZeedddZ eeeedddZ!ee"eeef ddd Z#G d!d" d"Z$e$ Z%eG d#d$ d$Z&dS )%z)Monkeypatching and mocking functionality.    N)contextmanager)Path)Any)	Generator)List)MutableMapping)Optional)overload)Tuple)TypeVar)Union)final)fixture)PytestWarningz^No module named (.*)$KV)MonkeyPatchNN)returnc              c   s   t  } | V  |   dS )a  A convenient fixture for monkey-patching.

    The fixture provides these methods to modify objects, dictionaries or
    os.environ::

        monkeypatch.setattr(obj, name, value, raising=True)
        monkeypatch.delattr(obj, name, raising=True)
        monkeypatch.setitem(mapping, name, value)
        monkeypatch.delitem(obj, name, raising=True)
        monkeypatch.setenv(name, value, prepend=False)
        monkeypatch.delenv(name, raising=True)
        monkeypatch.syspath_prepend(path)
        monkeypatch.chdir(path)

    All modifications will be undone after the requesting test function or
    fixture has finished. The ``raising`` parameter determines if a KeyError
    or AttributeError will be raised if the set/deletion operation has no target.
    N)r   undo)Zmpatch r   [/home/kop/projects/devel/pgwui/test_venv/lib/python3.7/site-packages/_pytest/monkeypatch.pymonkeypatch   s    r   )namer   c             C   s   |  d}|d}t|}x|D ]}|d| 7 }yt||}W q" tk
rT   Y nX q"yt| W nT tk
r } z6t|  d }||kr ntd| d| |W d d }~X Y nX t|||}q"W |S )N.r   zimport error in z: )splitpop
__import__getattrAttributeErrorImportErrorstrannotated_getattr)r   partsusedfoundpartexexpectedr   r   r   resolve6   s&    


(r)   )objr   annr   c          
   C   sP   yt | |} W n< tk
rJ } ztdt| j|||W d d }~X Y nX | S )Nz'{!r} object at {} has no attribute {!r})r   r   formattype__name__)r*   r   r+   er   r   r   r"   R   s    r"   )import_pathraisingr   c             C   sR   t | trd| kr td| | dd\}}t|}|rJt|||d ||fS )Nr   z)must be absolute import path string, not    )r+   )
isinstancer!   	TypeErrorrsplitr)   r"   )r0   r1   moduleattrtargetr   r   r   derive_importpath^   s    r9   c               @   s   e Zd ZedddZdS )Notset)r   c             C   s   dS )Nz<notset>r   )selfr   r   r   __repr__i   s    zNotset.__repr__N)r.   
__module____qualname__r!   r<   r   r   r   r   r:   h   s   r:   c               @   sX  e Zd ZdZddddZeeed dddZe	d%e
eeedd
ddZe	d&ee
eedd
ddZedfee
ef eee
f eedd
ddZedfeee
f ee
ef eddddZeeef eeddddZd'eeef eeddddZd(e
e
ee
 ddddZd)e
eddddZdddd Zddd!d"Zddd#d$ZdS )*r   a  Helper to conveniently monkeypatch attributes/items/environment
    variables/syspath.

    Returned by the :fixture:`monkeypatch` fixture.

    :versionchanged:: 6.2
        Can now also be used directly as `pytest.MonkeyPatch()`, for when
        the fixture is not available. In this case, use
        :meth:`with MonkeyPatch.context() as mp: <context>` or remember to call
        :meth:`undo` explicitly.
    N)r   c             C   s   g | _ g | _d | _d | _d S )N)_setattr_setitem_cwd_savesyspath)r;   r   r   r   __init__~   s    zMonkeyPatch.__init__)r   NNc             c   s    |  }z
|V  W d|   X dS )a  Context manager that returns a new :class:`MonkeyPatch` object
        which undoes any patching done inside the ``with`` block upon exit.

        Example:

        .. code-block:: python

            import functools


            def test_partial(monkeypatch):
                with monkeypatch.context() as m:
                    m.setattr(functools, "partial", 3)

        Useful in situations where it is desired to undo some patches before the test ends,
        such as mocking ``stdlib`` functions that might break pytest itself if mocked (for examples
        of this see `#3290 <https://github.com/pytest-dev/pytest/issues/3290>`_.
        N)r   )clsmr   r   r   context   s    
zMonkeyPatch.context.)r8   r   valuer1   r   c             C   s   d S )Nr   )r;   r8   r   rG   r1   r   r   r   setattr   s    zMonkeyPatch.setattrc             C   s   d S )Nr   )r;   r8   r   rG   r1   r   r   r   rH      s    Tc             C   s   d}ddl }t|tr<t|ts(td|}t||\}}nt|tsNtdt||t}|rx|tkrxt|d||	|r|j
|t}| j|||f t||| dS )a  Set attribute value on target, memorizing the old value.

        For convenience you can specify a string as ``target`` which
        will be interpreted as a dotted import path, with the last part
        being the attribute name. For example,
        ``monkeypatch.setattr("os.getcwd", lambda: "/")``
        would set the ``getcwd`` function of the ``os`` module.

        Raises AttributeError if the attribute does not exist, unless
        ``raising`` is set to False.
        Tr   Nzcuse setattr(target, name, value) or setattr(target, value) with target being a dotted import stringz|use setattr(target, name, value) with name being a string or setattr(target, value) with target being a dotted import stringz has no attribute )inspectr3   r:   r!   r4   r9   r   notsetr   isclass__dict__getr?   appendrH   )r;   r8   r   rG   r1   __tracebackhide__rI   oldvalr   r   r   rH      s$    



)r8   r   r1   r   c             C   s   d}ddl }t|tr6t|ts(tdt||\}}t||sN|rt|n@t||t	}|
|rr|j|t	}| j|||f t|| dS )aK  Delete attribute ``name`` from ``target``.

        If no ``name`` is specified and ``target`` is a string
        it will be interpreted as a dotted import path with the
        last part being the attribute name.

        Raises AttributeError it the attribute does not exist, unless
        ``raising`` is set to False.
        Tr   NzUuse delattr(target, name) or delattr(target) with target being a dotted import string)rI   r3   r:   r!   r4   r9   hasattrr   r   rJ   rK   rL   rM   r?   rN   delattr)r;   r8   r   r1   rO   rI   rP   r   r   r   rR      s    




zMonkeyPatch.delattr)dicr   rG   r   c             C   s&   | j ||||tf |||< dS )z'Set dictionary entry ``name`` to value.N)r@   rN   rM   rJ   )r;   rS   r   rG   r   r   r   setitem  s    zMonkeyPatch.setitem)rS   r   r1   r   c             C   s:   ||kr|r6t |n | j||||tf ||= dS )zDelete ``name`` from dict.

        Raises ``KeyError`` if it doesn't exist, unless ``raising`` is set to
        False.
        N)KeyErrorr@   rN   rM   rJ   )r;   rS   r   r1   r   r   r   delitem  s
    
zMonkeyPatch.delitem)r   rG   prependr   c             C   sj   t |ts6tjtdj||t|jddd t|}|rV|tj	krV|| tj	|  }| 
tj	|| dS )zSet environment variable ``name`` to ``value``.

        If ``prepend`` is a character, read the current environment variable
        value and prepend the ``value`` adjoined with the ``prepend``
        character.
        zvValue of environment variable {name} type should be str, but got {value!r} (type: {type}); converted to str implicitly)r   rG   r-      )
stacklevelN)r3   r!   warningswarnr   r,   r-   r.   osenvironrT   )r;   r   rG   rW   r   r   r   setenv  s    
zMonkeyPatch.setenv)r   r1   r   c             C   s   t j}| j|||d dS )zDelete ``name`` from the environment.

        Raises ``KeyError`` if it does not exist, unless ``raising`` is set to
        False.
        )r1   N)r\   r]   rV   )r;   r   r1   r]   r   r   r   delenv)  s    zMonkeyPatch.delenvc             C   sZ   ddl m} | jdkr&tjdd | _tjdt| |t| ddlm} |  dS )z:Prepend ``path`` to ``sys.path`` list of import locations.r   )fixup_namespace_packagesN)invalidate_caches)	pkg_resourcesr`   rB   syspathinsertr!   	importlibra   )r;   rd   r`   ra   r   r   r   syspath_prepend2  s    
	zMonkeyPatch.syspath_prependc             C   sP   | j dkrt | _ t|dr(|  n$t|trBtt| n
t| dS )z}Change the current working directory to the specified path.

        Path can be a string or a py.path.local object.
        Nchdir)rA   r\   getcwdrQ   rh   r3   r   r!   )r;   rd   r   r   r   rh   H  s    




zMonkeyPatch.chdirc          	   C   s   x8t | jD ]*\}}}|tk	r,t||| qt|| qW g | jdd< xJt | jD ]<\}}}|tkry
||= W q tk
r   Y qX qT|||< qTW g | jdd< | jdk	r| jtj	dd< d| _| j
dk	rt| j
 d| _
dS )aD  Undo previous changes.

        This call consumes the undo stack. Calling it a second time has no
        effect unless you do more monkeypatching after the undo call.

        There is generally no need to call `undo()`, since it is
        called automatically during tear-down.

        Note that the same `monkeypatch` fixture is used across a
        single test function invocation. If `monkeypatch` is used both by
        the test function itself and one of the test fixtures,
        calling `undo()` will undo all of the changes made in
        both functions.
        N)reversedr?   rJ   rH   rR   r@   rU   rB   rc   rd   rA   r\   rh   )r;   r*   r   rG   
dictionarykeyr   r   r   r   W  s&    


zMonkeyPatch.undo)..).)T)N)T)r.   r=   r>   __doc__rC   classmethodr   r   rF   r	   r!   objectr:   boolrH   rJ   r   rR   r   r   r   rT   rV   r   r^   r_   rg   rh   r   r   r   r   r   r   p   s0   

-!	r   )'rm   r\   rerc   rZ   
contextlibr   pathlibr   typingr   r   r   r   r   r	   r
   r   r   Z_pytest.compatr   Z_pytest.fixturesr   Z_pytest.warning_typesr   compileZRE_IMPORT_ERROR_NAMEr   r   r   r!   ro   r)   r"   rp   r9   r:   rJ   r   r   r   r   r   <module>   s:   

