o
    b(                     @   s  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mZ zddl	m
Z
 W n ey3   dZ
Y nw ddlmZ ddlmZ ddlmZmZmZmZmZmZmZmZmZmZmZ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' G dd dZ(G dd de'Z)G dd de'Z*G dd de%e'Z+G dd de'Z,dd Z-dd Z.G dd de'Z/eeddd d!G d"d# d#Z0G d$d% d%Z1eedd&d dd'd2d(d)Z2G d*d+ d+e'Z3G d,d- d-e'Z4G d.d/ d/e'Z5G d0d1 d1e'Z6dS )3zI
Tests for Twisted's deprecation framework, L{twisted.python.deprecate}.
    N)normcase)catch_warningssimplefilter)invalidate_caches)Version)	deprecate)DEPRECATION_WARNING_FORMAT_appendToDocstring_fullyQualifiedName_getDeprecationDocstring_getDeprecationWarningString_mutuallyExclusiveArguments_passedArgSpec_passedSignature
deprecateddeprecatedKeywordParameterdeprecatedPropertygetDeprecationWarningString)FilePath)platform)deprecatedattributes)TwistedModulesMixin)SynchronousTestCasec                   @       e Zd ZdZdd Zdd ZdS )_MockDeprecatedAttributezq
    Mock of L{twisted.python.deprecate._DeprecatedAttribute}.

    @ivar value: The value of the attribute.
    c                 C   
   || _ d S Nvalueselfr    r!   D/usr/lib/python3/dist-packages/twisted/python/test/test_deprecate.py__init__8      
z!_MockDeprecatedAttribute.__init__c                 C      | j S )z$
        Get a known value.
        r   r    r!   r!   r"   get;   s   z_MockDeprecatedAttribute.getN)__name__
__module____qualname____doc__r#   r'   r!   r!   r!   r"   r   1   s    r   c                   @   s@   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dS )ModuleProxyTestsz
    Tests for L{twisted.python.deprecate._ModuleProxy}, which proxies
    access to module-level attributes, intercepting access to deprecated
    attributes and passing through access to normal attributes.
    c                 K   s2   t d}| D ]
\}}t||| q	t|S )z
        Create a temporary module proxy object.

        @param **kw: Attributes to initialise on the temporary module object

        @rtype: L{twistd.python.deprecate._ModuleProxy}
        foo)types
ModuleTypeitemssetattrr   _ModuleProxy)r    attrsmodkeyr   r!   r!   r"   
_makeProxyI   s   

zModuleProxyTests._makeProxyc                 C   s.   | j dd}| |jd | tt|d dS )z
        Getting a normal attribute on a L{twisted.python.deprecate._ModuleProxy}
        retrieves the underlying attribute's value, and raises C{AttributeError}
        if a non-existent attribute is accessed.
        hello)SOME_ATTRIBUTEDOES_NOT_EXISTN)r6   assertIsr8   assertRaisesAttributeErrorgetattrr    proxyr!   r!   r"   test_getattrPassthroughV   s   z(ModuleProxyTests.test_getattrPassthroughc                 C   s2   |   }t|d}td|d< | |jd dS )z
        Getting an attribute marked as being deprecated on
        L{twisted.python.deprecate._ModuleProxy} results in calling the
        deprecated wrapper's C{get} method.
        _deprecatedAttributes*   r-   N)r6   object__getattribute__r   assertEqualr-   )r    r?   rA   r!   r!   r"   test_getattrIntercept`   s   z&ModuleProxyTests.test_getattrInterceptc                 C   s,   |   }| tt|d | tt|d dS )z
        Private attributes of L{twisted.python.deprecate._ModuleProxy} are
        inaccessible when regular attribute access is used.
        _modulerA   N)r6   r;   r<   r=   r>   r!   r!   r"   test_privateAttributesk   s   z'ModuleProxyTests.test_privateAttributesc                 C   s4   |   }d|_| t|dd | |jd dS )z
        Setting attributes on L{twisted.python.deprecate._ModuleProxy} proxies
        them through to the wrapped module.
           rG   N)r6   rG   assertNotEqualrC   rD   rE   r>   r!   r!   r"   test_setattrt   s   zModuleProxyTests.test_setattrc                 C   s<   |   }t|d}| t|dt|j d|d dS )z
        L{twisted.python.deprecated._ModuleProxy.__repr__} produces a string
        containing the proxy type and a representation of the wrapped module
        object.
        rG   <z module=>N)r6   rC   rD   rE   reprtyper(   )r    r?   
realModuler!   r!   r"   	test_repr~   s   (zModuleProxyTests.test_reprN)
r(   r)   r*   r+   r6   r@   rF   rH   rK   rQ   r!   r!   r!   r"   r,   B   s    
	
r,   c                   @   s8   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdS )DeprecatedAttributeTestsz
    Tests for L{twisted.python.deprecate._DeprecatedAttribute} and
    L{twisted.python.deprecate.deprecatedModuleAttribute}, which issue
    warnings for deprecated module-level attributes.
    c                 C   s   t j| _t j| _td | _d S )Nz.foo)r   versionmessager(   _testModuleNamer&   r!   r!   r"   setUp   s   zDeprecatedAttributeTests.setUpc                 C   s"   t tjd | tjtd tj S )zJ
        Create the warning string used by deprecated attributes.
        .z: )r   r   r(   rS   r   rT   )r    attrr!   r!   r"   _getWarningString   s
   z*DeprecatedAttributeTests._getWarningStringc                    s   d}t t|d tt|| j| j |  j|  fdd}|  | | j	g}| 
|d d t | |d d | | | t|d d	S )
z
        L{twisted.python.deprecate._DeprecatedAttribute} correctly sets its
        __name__ to match that of the deprecated attribute and emits a warning
        when the original attribute value is accessed.
        ANOTHER_DEPRECATED_ATTRIBUTErB   c                      s       d S r   )r'   r!   rX   r!   r"   addStackLevel   s   zNDeprecatedAttributeTests.test_deprecatedAttributeHelper.<locals>.addStackLevelr   categoryrT   rI   N)r1   r   r   _DeprecatedAttributerS   rT   rE   r(   flushWarningstest_deprecatedAttributeHelperr:   DeprecationWarningrY   len)r    namer\   warningsShownr!   r[   r"   r`      s   z7DeprecatedAttributeTests.test_deprecatedAttributeHelperc                 C   s   t j | | jg}| t|d d}tt | | | jg}| t|d | |d d t | |d d | 	| dS )a  
        L{twisted.python.deprecate.deprecatedModuleAttribute} wraps a
        module-level attribute in an object that emits a deprecation warning
        when it is accessed the first time only, while leaving other unrelated
        attributes alone.
        r   DEPRECATED_ATTRIBUTErI   r]   rT   N)
r   ANOTHER_ATTRIBUTEr_   test_deprecatedAttributerE   rb   r=   r:   ra   rY   )r    rd   rc   r!   r!   r"   rg      s   
z1DeprecatedAttributeTests.test_deprecatedAttributec                 C   s   t d tj| j< }| tjj| j t|dd t|dd t	t
ddddd	| jd tj| j }| || t	t
ddddd	| jd | |tj| j  d
S )z
        Deprecating an attribute in a module replaces and wraps that module
        instance, in C{sys.modules}, with a
        L{twisted.python.deprecate._ModuleProxy} instance but only if it hasn't
        already been wrapped.
        r-   firstrI   second   Twisted   r   rT   N)r.   r/   sysmodulesrU   
addCleanuppopr1   r   deprecatedModuleAttributer   rJ   r:   )r    r4   r?   r!   r!   r"   test_wrappedModule   s   z+DeprecatedAttributeTests.test_wrappedModuleN)	r(   r)   r*   r+   rV   rY   r`   rg   rr   r!   r!   r!   r"   rR      s    
rR   c                   @   s<   e Zd ZdZdZdd Zdd Zdd Zd	d
 Zdd Z	dS )ImportedModuleAttributeTestsza
    Tests for L{deprecatedModuleAttribute} which involve loading a module via
    'import'.
    zfrom twisted.python.deprecate import deprecatedModuleAttribute
from incremental import Version

deprecatedModuleAttribute(
    Version('Package', 1, 2, 3), 'message', __name__, 'module')
c                    s^    fdd t |  d}|   ||}| |jdgtj  | tj	
  |S )a_  
        Create some files in a hierarchy, based on a dictionary describing those
        files.  The resulting hierarchy will be placed onto sys.path for the
        duration of the test.

        @param tree: A dictionary representing a directory structure.  Keys are
            strings, representing filenames, dictionary values represent
            directories, string values represent file contents.

        @return: another dictionary similar to the input, with file content
            strings replaced with L{FilePath} objects pointing at where those
            contents are now stored.
        c                    sj   i }|  D ],\}}| |}t|tr|||< || qt|tr/|   ||||< qtd|S )Nz(only strings and dicts allowed as values)r0   child
isinstancebytes
setContentdictcreateDirectory
ValueError)pathobjdirdictpathdictr5   r   rt   makeSomeFilesr!   r"   r     s   


zAImportedModuleAttributeTests.pathEntryTree.<locals>.makeSomeFilesutf-8)r   mktempencodemakedirsreplaceSysPathpathdecoderm   replaceSysModulesrn   copy)r    treebaseresultr!   r~   r"   pathEntryTree   s   
z*ImportedModuleAttributeTests.pathEntryTreec                 C   s(   |  d| jdddi}|d d S )z
        Add a sample module and package to the path, returning a L{FilePath}
        pointing at the module which will be loadable as C{package.module}.
        s   packager       )s   __init__.py	   module.pyr   )r   _packageInitr   )r    pathsr!   r!   r"   simpleModuleEntry  s   
z.ImportedModuleAttributeTests.simpleModuleEntryc                 C   sn   ddl m} | t|jd| | | jg}| t|d | |d d d | |d d t	 dS )	zB
        Verification logic for L{test_deprecatedModule}.
        r   moduler   rI   rT   z7package.module was deprecated in Package 1.2.3: messager]   N)
packager   rE   r   __file__r   r_   checkOneWarningrb   ra   )r    
modulePathr   emittedr!   r!   r"   r   .  s   
z,ImportedModuleAttributeTests.checkOneWarningc                 C   s   |  |   dS )z
        If L{deprecatedModuleAttribute} is used to deprecate a module attribute
        of a package, only one deprecation warning is emitted when the
        deprecated module is imported.
        N)r   r   r&   r!   r!   r"   test_deprecatedModule=  s   z2ImportedModuleAttributeTests.test_deprecatedModulec                 C   s8   |   }| | | | tdD ]}| | qdS )z
        If L{deprecatedModuleAttribute} is used to deprecate a module attribute
        of a package, only one deprecation warning is emitted when the
        deprecated module is subsequently imported.
        rj   N)r   r   range)r    mpxr!   r!   r"   "test_deprecatedModuleMultipleTimesE  s   

z?ImportedModuleAttributeTests.test_deprecatedModuleMultipleTimesN)
r(   r)   r*   r+   r   r   r   r   r   r   r!   r!   r!   r"   rs      s    &rs   c                   @   sP   e Zd Z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S )WarnAboutFunctionTestsz
    Tests for L{twisted.python.deprecate.warnAboutFunction} which allows the
    callers of a function to issue a C{DeprecationWarning} about that function.
    c                    s   t |  d| _| j  | jdd | jdd | jdd | j j}tj	d| | 
tjj| tj  | 
 fd	d
 t rW|   dS dS )zY
        Create a file that will have known line numbers when emitting warnings.
        twisted_private_helperz__init__.pyr   z	module.pys  
"A module string"

from twisted.python import deprecate

def testFunction():
    "A doc string"
    a = 1 + 2
    return a

def callTestFunction():
    b = testFunction()
    if b == 3:
        deprecate.warnAboutFunction(testFunction, "A Warning String")
z	pep626.pysQ  
"A module string"

from twisted.python import deprecate

def noop():
    pass

def testFunction(a=1, b=1):
    "A doc string"
    if a:
        if b:
            noop()
        else:
            pass

def callTestFunction():
    b = testFunction()
    if b is None:
        deprecate.warnAboutFunction(testFunction, "A Warning String")
r   c                      s   t j t j fS r   )rm   rn   clearupdater!   rn   r!   r"   <lambda>  s    z.WarnAboutFunctionTests.setUp.<locals>.<lambda>N)r   r   rt   r   r   rw   parentr   rm   insertro   removern   r   r   	isWindowsr_   )r    packagePathr!   r   r"   rV   `  s"   

zWarnAboutFunctionTests.setUpc                 C   sn   dd }t |d |  }t}| dr|dd }| t|d d t| | |d d	 d dS )
z
        L{deprecate.warnAboutFunction} emits a warning the file and line number
        of which point to the beginning of the implementation of the function
        passed to it.
        c                   S      d S r   r!   r!   r!   r!   r"   aFunc     z2WarnAboutFunctionTests.test_warning.<locals>.aFunczA Warning Messagez.pycNr   filenamerT   )	r   warnAboutFunctionr_   r   lowerendswithassertSamePathr   rE   )r    r   rd   r   r!   r!   r"   test_warning  s   z#WarnAboutFunctionTests.test_warningc                 C      ddl m} |  |  }| t|d d d| jd	d | 
|d d d | 
|d d	 d
 | 
t|d dS )z
        L{deprecate.warnAboutFunction} emits a C{DeprecationWarning} with the
        number of a line within the implementation of the function passed to it.
        r   r   r   r      twisted_private_helperr   lineno	   rT   A Warning StringrI   N)r   r   callTestFunctionr_   r   r   r   r   siblingrt   rE   rb   r    r   rd   r!   r!   r"   test_warningLineNumber  s   z-WarnAboutFunctionTests.test_warningLineNumberc                 C   r   )z
        L{deprecate.warnAboutFunction} emits a C{DeprecationWarning} with the
        number of a line within the implementation handling the case in which
        dis.findlinestarts returns the lines in random order.
        r   )pep626r   r   r   s	   pep626.pyr      rT   r   rI   N)r   r   r   r_   r   r   r   r   r   rt   rE   rb   )r    r   rd   r!   r!   r"   'test_warningLineNumberDisFindlinestarts  s   z>WarnAboutFunctionTests.test_warningLineNumberDisFindlinestartsc                 C   s*   |  t|jt|jk|d| dS )a  
        Assert that the two paths are the same, considering case normalization
        appropriate for the current platform.

        @type first: L{FilePath}
        @type second: L{FilePath}

        @raise C{self.failureType}: If the paths are not the same.
        z != N)
assertTruer   r   )r    rh   ri   r!   r!   r"   r     s   
z%WarnAboutFunctionTests.assertSamePathc                 C   s   ddl m} tjd= tj|j= | j| jd trt  ddl	m} | 
tjjd | 
tjj|j |  | |jg}t|d d d}| jdd}| || | |d d	 d
 | |d d d | t|d dS )a  
        Even if the implementation of a deprecated function is moved around on
        the filesystem, the line number in the warning emitted by
        L{deprecate.warnAboutFunction} points to a line in the implementation of
        the deprecated function.
        r   r   r   s   twisted_renamed_helpertwisted_renamed_helperr   r   r   r   r   rT   r   rI   N)r   r   rm   rn   r(   r   moveTor   r   r   ro   rp   r   r_   testFunctionr   r   rt   r   rE   rb   )r    r   rd   
warnedPathexpectedPathr!   r!   r"   test_renamedFile  s&   
z'WarnAboutFunctionTests.test_renamedFilec                 C   sJ   t jdd= t jddd ddlm} |  |  }| t|d dS )z
        L{deprecate.warnAboutFunction} emits a warning that will be filtered if
        L{warnings.filterwarning} is called with the module name of the
        deprecated function.
        Nignorer   actionr   r   r   )	warningsfiltersfilterwarningsr   r   r   r_   rE   rb   r   r!   r!   r"   test_filteredWarning  s   	z+WarnAboutFunctionTests.test_filteredWarningc                 C   s   t jdd= t jddd ddlm} |  |  |  }| t|d |d d }|d d	 }|d d
 }|d d }t 	||||}| 
|dd| dS )z
        L{deprecate.warnAboutFunction} emits a warning that will be filtered
        once if L{warnings.filterwarning} is called with the module name of the
        deprecated function and an action of once.
        Nr   r   r   r   r   rI   rT   r]   r   r   z=module.py:9: DeprecationWarning: A Warning String
  return a
zUnexpected warning string: )r   r   r   r   r   r   r_   rE   rb   formatwarningr   r   )r    r   rd   rT   r]   r   r   msgr!   r!   r"   test_filteredOnceWarning  s$   	z/WarnAboutFunctionTests.test_filteredOnceWarningN)r(   r)   r*   r+   rV   r   r   r   r   r   r   r   r!   r!   r!   r"   r   Z  s    =&r   c                   C      dS )zK
    Do nothing.

    This is used to test the deprecation decorators.
    Nr!   r!   r!   r!   r"   dummyCallable@      r   c                   C   r   )z[
    Do nothing.

    This is used to test the replacement parameter to L{deprecated}.
    Nr!   r!   r!   r!   r"   dummyReplacementMethodH  r   r   c                   @   sT   e Z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S )DeprecationWarningsTestsc                 C   s,   t dddd}| t| j|dtf  dS )z
        L{getDeprecationWarningString} returns a string that tells us that a
        callable was deprecated at a certain released version of Twisted.
        rk   rl   r   z\%s.DeprecationWarningsTests.test_getDeprecationWarningString was deprecated in Twisted 8.0.0N)r   rE   r    test_getDeprecationWarningStringr(   r    rS   r!   r!   r"   r   Q  s   
z9DeprecationWarningsTests.test_getDeprecationWarningStringc                 C   s6   t dddd}td }| t| j||dtf  dS )z
        L{getDeprecationWarningString} returns a string that tells us that a
        callable was deprecated at a certain released version of Twisted, with
        a message containing additional information about the deprecation.
        rk   rl   r   z: This is a messagezo%s.DeprecationWarningsTests.test_getDeprecationWarningString was deprecated in Twisted 8.0.0: This is a messageN)r   r   rE   r   r   r(   )r    rS   formatr!   r!   r"   *test_getDeprecationWarningStringWithFormat]  s   zCDeprecationWarningsTests.test_getDeprecationWarningStringWithFormatc                    s   t dddd}t|t  fdd}tdd6}td |  | |d jt | t|d j	t
t| | |d jd	td	 W d
   d
S 1 sQw   Y  d
S )zK
        Decorating a callable with L{deprecated} emits a warning.
        rk   rl   r   c                      s
      d S r   r!   r!   dummyr!   r"   r\   t  r$   zJDeprecationWarningsTests.test_deprecateEmitsWarning.<locals>.addStackLevelTrecordalwayscoN)r   r   r   r   r   rE   r]   ra   strrT   r   r   rstripr   )r    rS   r\   caughtr!   r   r"   test_deprecateEmitsWarningm  s    "z3DeprecationWarningsTests.test_deprecateEmitsWarningc                 C   sB   t dddd}t|t}| tj|j | ttt| dS )zK
        The decorated function has the same name as the original.
        rk   rl   r   N)r   r   r   rE   r(   fullyQualifiedNamer    rS   r   r!   r!   r"   test_deprecatedPreservesName  s   z5DeprecationWarningsTests.test_deprecatedPreservesNamec                 C   s$   t dddd}| dt|d dS )zr
        L{_getDeprecationDocstring} returns a note about the deprecation to go
        into a docstring.
        rk   rl   r   zDeprecated in Twisted 8.0.0. N)r   rE   r   r   r!   r!   r"   test_getDeprecationDocstring  s   
z5DeprecationWarningsTests.test_getDeprecationDocstringc                 C   sF   dd }t dddd}t||}t|t|d | |j|j dS )zv
        The docstring of the deprecated function is appended with information
        about the deprecation.
        c                   S   r   )zc
            Do nothing.

            This is used to test the deprecation decorators.
            Nr!   r!   r!   r!   r"   localDummyCallable  r   zTDeprecationWarningsTests.test_deprecatedUpdatesDocstring.<locals>.localDummyCallablerk   rl   r   r   N)r   r   r	   r   rE   r+   )r    r   rS   r   r!   r!   r"   test_deprecatedUpdatesDocstring  s
   z8DeprecationWarningsTests.test_deprecatedUpdatesDocstringc                 C   s,   t dddd}t|t}| ||j dS )zt
        Deprecating a function adds version information to the decorated
        version of that function.
        rk   rl   r   N)r   r   r   rE   deprecatedVersionr   r!   r!   r"   test_versionMetadata  s   z-DeprecationWarningsTests.test_versionMetadatac                 C   s:   t dddd}t| j|dd}| |dt| jf  dS )a  
        L{getDeprecationWarningString} takes an additional replacement parameter
        that can be used to add information to the deprecation.  If the
        replacement parameter is a string, it will be interpolated directly into
        the result.
        rk   rl   r   something.foobarreplacementzG%s was deprecated in Twisted 8.0.0; please use something.foobar insteadN)r   r   r   rE   r   r    rS   warningStringr!   r!   r"   +test_getDeprecationWarningStringReplacement  s   
zDDeprecationWarningsTests.test_getDeprecationWarningStringReplacementc                 C   s<   t dddd}t| j|td}| |dt| jtf  dS )a  
        L{getDeprecationWarningString} takes an additional replacement parameter
        that can be used to add information to the deprecation. If the
        replacement parameter is a callable, its fully qualified name will be
        interpolated into the result.
        rk   rl   r   r   zP%s was deprecated in Twisted 8.0.0; please use %s.dummyReplacementMethod insteadN)r   r   r   r   rE   r   r(   r   r!   r!   r"   7test_getDeprecationWarningStringReplacementWithCallable  s   zPDeprecationWarningsTests.test_getDeprecationWarningStringReplacementWithCallableN)r(   r)   r*   r   r   r   r   r   r   r   r   r   r!   r!   r!   r"   r   P  s    	
	r   rk   rI   rj      c                   @   s   e Zd ZdZdS )DeprecatedClasszJ
    Class which is entirely deprecated without having a replacement.
    N)r(   r)   r*   r+   r!   r!   r!   r"   r     s    r   c                   @   s<   e Zd ZdZdZeedddddd Zejd	d ZdS )
ClassWithDeprecatedPropertyz2
    Class with a single deprecated property.
    Nrk   rI   rj   r   c                 C   r%   )zC
        Getter docstring.

        @return: The property.
        _someProtectedValuer&   r!   r!   r"   someProperty  s   z(ClassWithDeprecatedProperty.somePropertyc                 C   s
   || _ dS )z#
        Setter docstring.
        Nr   r   r!   r!   r"   r     s   
)	r(   r)   r*   r+   r   r   r   r   setterr!   r!   r!   r"   r     s    
r      r-   c                 C   r   )z7
    Function with a deprecated keyword parameter.
    Nr!   )abcr-   barr!   r!   r"   functionWithDeprecatedParameter  r   r   c                   @   sH   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dS )DeprecatedDecoratorTestsz*
    Tests for deprecated decorators.
    c                 C   s    |  |dd |j D  dS )a8  
        Check that C{target} object has the C{expected} docstring lines.

        @param target: Object which is checked.
        @type target: C{anything}

        @param expected: List of lines, ignoring empty lines or leading or
            trailing spaces.
        @type expected: L{list} or L{str}
        c                 S   s   g | ]
}|  r|  qS r!   )strip).0r   r!   r!   r"   
<listcomp>  s    z<DeprecatedDecoratorTests.assertDocstring.<locals>.<listcomp>N)rE   r+   
splitlines)r    targetexpectedr!   r!   r"   assertDocstring  s   z(DeprecatedDecoratorTests.assertDocstringc                 C   s~   t  }|j | t jg d tddddt j_d}| | jg}| dt| | t	|d d  | ||d d	  d
S )a%  
        When L{deprecatedProperty} is used on a C{property}, accesses raise a
        L{DeprecationWarning} and getter docstring is updated to inform the
        version in which it was deprecated. C{deprecatedVersion} attribute is
        also set to inform the deprecation version.
        )zGetter docstring.z@return: The property.Deprecated in Twisted 1.2.3.rk   rI   rj   r   ktwisted.python.test.test_deprecate.ClassWithDeprecatedProperty.someProperty was deprecated in Twisted 1.2.3r   r]   rT   N)
r   r   r  r   r   r_   test_propertyGetterrE   rb   ra   )r    objrT   r   r!   r!   r"   r
    s   z,DeprecatedDecoratorTests.test_propertyGetterc                 C   sn   t  }t }||_| ||j d}| | jg}| dt| | t	|d d  | ||d d  dS )z}
        When L{deprecatedProperty} is used on a C{property}, setter accesses
        raise a L{DeprecationWarning}.
        r	  rI   r   r]   rT   N)
rC   r   r   r:   r   r_   test_propertySetterrE   rb   ra   )r    newValuer  rT   r   r!   r!   r"   r  4  s   z,DeprecatedDecoratorTests.test_propertySetterc                 C   st   t   | t ddg tddddt _d}| | jg}| dt| | t|d d	  | ||d d
  dS )a  
        When L{deprecated} is used on a class, instantiations raise a
        L{DeprecationWarning} and class's docstring is updated to inform the
        version in which it was deprecated. C{deprecatedVersion} attribute is
        also set to inform the deprecation version.
        z@Class which is entirely deprecated without having a replacement.r  rk   rI   rj   r   zRtwisted.python.test.test_deprecate.DeprecatedClass was deprecated in Twisted 1.2.3r   r]   rT   N)	r   r  r   r   r_   
test_classrE   rb   ra   )r    rT   r   r!   r!   r"   r  H  s   z#DeprecatedDecoratorTests.test_classc                 C   s.   t dddd}t|dt}| |jd dS )a  
        L{deprecated} takes an additional replacement parameter that can be used
        to indicate the new, non-deprecated method developers should use.  If
        the replacement parameter is a string, it will be interpolated directly
        into the warning message.
        rk   rl   r   r   z
    Do nothing.

    This is used to test the deprecation decorators.

    Deprecated in Twisted 8.0.0; please use something.foobar instead.
    N)r   r   r   rE   r+   r   r!   r!   r"   test_deprecatedReplacementc  s   z3DeprecatedDecoratorTests.test_deprecatedReplacementc                 C   s:   t dddd}t|td}|t}| |jdtf  dS )a)  
        L{deprecated} takes an additional replacement parameter that can be used
        to indicate the new, non-deprecated method developers should use.  If
        the replacement parameter is a callable, its fully qualified name will
        be interpolated into the warning message.
        rk   rl   r   r   z
    Do nothing.

    This is used to test the deprecation decorators.

    Deprecated in Twisted 8.0.0; please use %s.dummyReplacementMethod instead.
    N)r   r   r   r   rE   r+   r(   )r    rS   	decoratorr   r!   r!   r"   &test_deprecatedReplacementWithCallablew  s   z?DeprecatedDecoratorTests.test_deprecatedReplacementWithCallablec                 C   s  d}t dd{}td tdd | |g  tddd | |g  tdddd	 | t|d
 | |d jt | t|d j| |	  tdddd | |g  tdddd | t|d
 | |d jt | t|d j| W d    d S 1 sw   Y  d S )NzzThe 'foo' parameter to twisted.python.test.test_deprecate.functionWithDeprecatedParameter was deprecated in Twisted 19.2.0Tr   r   
         (   )r-   rI   r   2   )r   )
r   r   r   rE   rb   r]   ra   r   rT   r   )r    rT   wsr!   r!   r"   test_deprecatedKeywordParameter  s(   
"z8DeprecatedDecoratorTests.test_deprecatedKeywordParameterN)r(   r)   r*   r+   r  r
  r  r  r  r  r  r!   r!   r!   r"   r      s     r   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	AppendToDocstringTestszk
    Test the _appendToDocstring function.

    _appendToDocstring is used to add text to a docstring.
    c                 C   s$   dd }t |d | d|j dS )zP
        Appending to an empty docstring simply replaces the docstring.
        c                   S   r   r   r!   r!   r!   r!   r"   noDocstring  r   zGAppendToDocstringTests.test_appendToEmptyDocstring.<locals>.noDocstringAppended text.Nr	   rE   r+   )r    r  r!   r!   r"   test_appendToEmptyDocstring  s   
z2AppendToDocstringTests.test_appendToEmptyDocstringc                 C   s>   dd }t |d | g d|j  | |jd dS )a  
        Appending to a single line docstring places the message on a new line,
        with a blank line separating it from the rest of the docstring.

        The docstring ends with a newline, conforming to Twisted and PEP 8
        standards. Unfortunately, the indentation is incorrect, since the
        existing docstring doesn't have enough info to help us indent
        properly.
        c                   S   r   );This doesn't comply with standards, but is here for a test.Nr!   r!   r!   r!   r"   singleLineDocstring  r   zTAppendToDocstringTests.test_appendToSingleLineDocstring.<locals>.singleLineDocstringr  )r  r   r  
N)r	   rE   r+   r  r   r   )r    r  r!   r!   r"    test_appendToSingleLineDocstring  s   
z7AppendToDocstringTests.test_appendToSingleLineDocstringc                 C   s.   dd }dd }t |d | |j|j dS )z
        Appending to a multi-line docstring places the messade on a new line,
        with a blank line separating it from the rest of the docstring.

        Because we have multiple lines, we have enough information to do
        indentation.
        c                   S   r   )z9
            This is a multi-line docstring.
            Nr!   r!   r!   r!   r"   multiLineDocstring  r   zRAppendToDocstringTests.test_appendToMultilineDocstring.<locals>.multiLineDocstringc                   S   r   )zU
            This is a multi-line docstring.

            Appended text.
            Nr!   r!   r!   r!   r"   expectedDocstring  r   zQAppendToDocstringTests.test_appendToMultilineDocstring.<locals>.expectedDocstringr  Nr  )r    r"  r#  r!   r!   r"   test_appendToMultilineDocstring  s   	
z6AppendToDocstringTests.test_appendToMultilineDocstringN)r(   r)   r*   r+   r  r!  r$  r!   r!   r!   r"   r    s
    r  c                   @   sh   e Zd Z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S )MutualArgumentExclusionTestsz2
    Tests for L{mutuallyExclusiveArguments}.
    c                 O   s0   t tddrtt|||S tt|||S )a  
        Test an invocation of L{passed} with the given function, arguments, and
        keyword arguments.

        @param func: A function whose argspec will be inspected.
        @type func: A callable.

        @param args: The arguments which could be passed to C{func}.

        @param kw: The keyword arguments which could be passed to C{func}.

        @return: L{_passedSignature} or L{_passedArgSpec}'s return value
        @rtype: L{dict}
        	signatureN)r=   inspectr   r&  r   
getargspecr    funcargskwr!   r!   r"   checkPassed  s   z(MutualArgumentExclusionTests.checkPassedc                 C   s*   dd }|  | |ddtddd dS )z`
        L{passed} identifies the arguments passed by a simple
        positional test.
        c                 S   r   r   r!   r   r   r!   r!   r"   r*    r   zGMutualArgumentExclusionTests.test_passed_simplePositional.<locals>.funcrI   rj   r.  NrE   r-  rx   r    r*  r!   r!   r"   test_passed_simplePositional  s   "z9MutualArgumentExclusionTests.test_passed_simplePositionalc                 C   s"   dd }|  t| j|ddd dS )z[
        L{passed} raises a L{TypeError} if too many arguments are
        passed.
        c                 S   r   r   r!   r.  r!   r!   r"   r*    r   zBMutualArgumentExclusionTests.test_passed_tooManyArgs.<locals>.funcrI   rj   r   Nr;   	TypeErrorr-  r0  r!   r!   r"   test_passed_tooManyArgs     z4MutualArgumentExclusionTests.test_passed_tooManyArgsc                 C   "   dd }| j t| j|ddd dS )zs
        L{passed} raises a L{TypeError} if a argument is passed both
        positionally and by keyword.
        c                 S   r   r   r!   r   r!   r!   r"   r*  '  r   zHMutualArgumentExclusionTests.test_passed_doublePassKeyword.<locals>.funcrI   rj   r7  Nr2  r0  r!   r!   r"   test_passed_doublePassKeyword!  r5  z:MutualArgumentExclusionTests.test_passed_doublePassKeywordc                 C   r6  )z
        L{passed} raises a L{TypeError} if a keyword argument not
        present in the function's declaration is passed.
        c                 S   r   r   r!   r7  r!   r!   r"   r*  2  r   zIMutualArgumentExclusionTests.test_passed_unspecifiedKeyword.<locals>.funcrI   rj   )zNr2  r0  r!   r!   r"   test_passed_unspecifiedKeyword,  r5  z;MutualArgumentExclusionTests.test_passed_unspecifiedKeywordc                 C   s,   dd }|  | |dddtddd dS )	z|
        L{passed} places additional positional arguments into a tuple
        under the name of the star argument.
        c                 W   r   r   r!   r.  r!   r!   r"   r*  =  r   z;MutualArgumentExclusionTests.test_passed_star.<locals>.funcrI   rj   r   )rj   r   r.  Nr/  r0  r!   r!   r"   test_passed_star7  s   $z-MutualArgumentExclusionTests.test_passed_starc              
   C   s:   dd }|  | j|dddddtdtddddd d	S )
zn
        Additional keyword arguments are passed as a dict to the star star
        keyword argument.
        c                 [   r   r   r!   r.  r!   r!   r"   r*  H  r   z?MutualArgumentExclusionTests.test_passed_starStar.<locals>.funcrI   rj   r      )r   yr9  r.  Nr/  r0  r!   r!   r"   test_passed_starStarB  s   &z1MutualArgumentExclusionTests.test_passed_starStarc                 C   s2   d
dd}|  | j|ddddtdddd d	S )zp
        The results of L{passed} only include arguments explicitly
        passed, not default values.
        rI   rj   r   c                 S   r   r   r!   r   r   r   der!   r!   r"   r*  U  r   zFMutualArgumentExclusionTests.test_passed_noDefaultValues.<locals>.func   )rA  )r   r   rA  NrI   rj   r   r/  r0  r!   r!   r"   test_passed_noDefaultValuesO  s   
(z8MutualArgumentExclusionTests.test_passed_noDefaultValuesc                 C   sT   t dgddd}| |ddd | |ddd	d
 | |ddd	dd dS )z
        L{mutuallyExclusiveArguments} does not interfere in its
        decoratee's operation, either its receipt of arguments or its return
        value.
        r.  r   r<  c                 S   s   | | | | S r   r!   )r   r=  r   r   r!   r!   r"   r*  a  s   zMMutualArgumentExclusionTests.test_mutualExclusionPrimeDirective.<locals>.funcrI   rj   r  rB     r      Nr   r<  )r   rE   r0  r!   r!   r"   "test_mutualExclusionPrimeDirectiveZ  s
   z?MutualArgumentExclusionTests.test_mutualExclusionPrimeDirectivec                 C   s.   t ddggd	dd}| jt|ddd dS )
z
        L{mutuallyExclusiveArguments} raises a L{TypeError}n if its
        decoratee is passed a pair of mutually exclusive arguments.
        r   r   r   r<  c                 S   s   | | S r   r!   r.  r!   r!   r"   r*  o  s   zPMutualArgumentExclusionTests.test_mutualExclusionExcludesByKeyword.<locals>.funcr.  NrH  )r   r;   r3  r0  r!   r!   r"   %test_mutualExclusionExcludesByKeywordi  s   zBMutualArgumentExclusionTests.test_mutualExclusionExcludesByKeywordc                 C   sn   G dd d}G dd d}dd }|dd t |j}| }|d	d	|d
< ||}| tt|di  dS )z
        Create a fake signature with an invalid parameter
        type to test error handling.  The valid parameter
        types are specified in L{inspect.Parameter}.
        c                   @      e Zd Zdd ZdS )zMMutualArgumentExclusionTests.test_invalidParameterType.<locals>.FakeSignaturec                 S   r   r   )
parameters)r    rL  r!   r!   r"   r#   }  r$   zVMutualArgumentExclusionTests.test_invalidParameterType.<locals>.FakeSignature.__init__Nr(   r)   r*   r#   r!   r!   r!   r"   FakeSignature|      rN  c                   @   rK  )zMMutualArgumentExclusionTests.test_invalidParameterType.<locals>.FakeParameterc                 S   s   || _ || _d S r   )rc   kind)r    rc   rP  r!   r!   r"   r#     s   
zVMutualArgumentExclusionTests.test_invalidParameterType.<locals>.FakeParameter.__init__NrM  r!   r!   r!   r"   FakeParameter  rO  rQ  c                 S   r   r   r!   r.  r!   r!   r"   r*    r   zDMutualArgumentExclusionTests.test_invalidParameterType.<locals>.funcrI   rj   faker   rI   rj   N)r'  r&  rL  r   r;   r3  r   )r    rN  rQ  r*  rL  dummyParametersfakeSigr!   r!   r"   test_invalidParameterTypeu  s   
z6MutualArgumentExclusionTests.test_invalidParameterTypeN)r(   r)   r*   r+   r-  r1  r4  r8  r:  r;  r>  rD  rI  rJ  rV  r!   r!   r!   r"   r%    s    r%  c                   @   r   )KeywordOnlyTestsz,
    Keyword only arguments (PEP 3102).
    c                 O   s   t t|||S )a  
        Test an invocation of L{passed} with the given function, arguments, and
        keyword arguments.

        @param func: A function whose argspec to pass to L{_passed}.
        @type func: A callable.

        @param args: The arguments which could be passed to L{func}.

        @param kw: The keyword arguments which could be passed to L{func}.

        @return: L{_passed}'s return value
        @rtype: L{dict}
        )r   r'  r&  r)  r!   r!   r"   r-    s   zKeywordOnlyTests.checkPassedc                 C   s   dddd}dddd}|  | |ddd	td
dd |  | j|ddd	ddtd
dd |  | j|dddddd	dtddddd	d | jt| j|dddddd dS )z`
        Keyword only arguments follow varargs.
        They are specified in PEP 3102.
        TrF  c                 W   r   )zM
            b is a keyword-only argument, with a default value.
            Nr!   )r   r   r!   r!   r"   func1  r   z6KeywordOnlyTests.test_passedKeywordOnly.<locals>.func1c                 W   r   )zd
            b, c, d, e  are keyword-only arguments.
            b has a default value.
            Nr!   )r   r   r@  rA  r   r!   r!   r"   func2  r   z6KeywordOnlyTests.test_passedKeywordOnly.<locals>.func2rI   rj   r   rC  r.  F)r   r   r@  rA  rS  r?  )r   r   r@  N)rE   r-  rx   r;   r3  )r    rX  rY  r!   r!   r"   test_passedKeywordOnly  s     z'KeywordOnlyTests.test_passedKeywordOnlyN)r(   r)   r*   r+   r-  rZ  r!   r!   r!   r"   rW    s    rW  rC  )7r+   r'  rm   r.   r   os.pathr   r   r   	importlibr   ImportErrorincrementalr   twisted.pythonr   twisted.python.deprecater   r	   r
   r   r   r   r   r   r   r   r   r   r   twisted.python.filepathr   twisted.python.runtimer   twisted.python.testr   #twisted.python.test.modules_helpersr   twisted.trial.unittestr   r   r,   rR   rs   r   r   r   r   r   r   r   r   r  r%  rW  r!   r!   r!   r"   <module>   sR   8Gbo g  -D !