U
    
W[f  ã                   @   s2  d Z ddlmZmZ ddlZddl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mZ ddlmZmZmZ ddlmZ dd	lmZ erªdd
lmZ ndd„ ZG dd„ deƒZG dd„ deƒZG dd„ dejƒZdZ dd„ Z!dd„ Z"G dd„ dejƒZ#G dd„ dejƒZ$G dd„ dejƒZ%dS )z"
Tests for Twisted plugin system.
é    )Úabsolute_importÚdivisionN)Ú	Interface)Úunittest)Ú_PY3Ú_PYPY)ÚtextFromEventDictÚaddObserverÚremoveObserver)ÚFilePath)Úplugin)Úinvalidate_cachesc                   C   s   dS )zJ
        On python 2, import caches don't need to be invalidated.
        N© r   r   r   ú:/usr/lib/python3/dist-packages/twisted/test/test_plugin.pyÚinvalidateImportCaches   s    r   c                   @   s   e Zd ZdZdS )ÚITestPluginzS
    A plugin for use by the plugin system's unit tests.

    Do not use this.
    N©Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   r   "   s   r   c                   @   s   e Zd ZdZdS )ÚITestPlugin2z
    See L{ITestPlugin}.
    Nr   r   r   r   r   r   +   s   r   c                   @   sº   e Zd ZdZdd„ Zdd„ Zd dd„Zd	d
„ Zdd„ Zdd„ Z	ee	ƒZ	dd„ Z
dd„ ZeeƒZdd„ ZeeƒZdd„ ZeeƒZdd„ ZeeƒZdd„ ZeeƒZdd„ ZeeƒZdd„ ZdS )!ÚPluginTestsz_
    Tests which verify the behavior of the current, active Twisted plugins
    directory.
    c                 C   s¤   t jdd… | _t j ¡ | _t|  ¡ ƒ| _| j 	¡  | j 
d¡| _| j 	¡  | j 
d¡ d¡ ttƒ d¡ | j 
d¡¡ d| _t j d| jj¡ ddl}|| _dS )	zV
        Save C{sys.path} and C{sys.modules}, and create a package for tests.
        NÚ	mypackageú__init__.pyó    zplugin_basic.pyztestplugin.pyÚ
testpluginr   )ÚsysÚpathÚoriginalPathÚmodulesÚcopyÚsavedModulesr   ÚmktempÚrootÚcreateDirectoryÚchildÚpackageÚ
setContentÚ__file__ÚsiblingÚcopyToÚoriginalPluginÚinsertr   Úmodule)Úselfr   r   r   r   ÚsetUp8   s    


ÿzPluginTests.setUpc                 C   s,   | j tjdd…< tj ¡  tj | j¡ dS ©zR
        Restore C{sys.path} and C{sys.modules} to their original values.
        N©r   r   r   r    ÚclearÚupdater"   ©r/   r   r   r   ÚtearDownO   s    
zPluginTests.tearDownFc                 C   s¦   |j  d¡}d |d d… ¡}|d }ttj| |ƒ tj|j = ddg|rPdgpRg  D ]J}zt |j| ¡ W qV t	k
rž } z|j
t
jkrŽ‚ W 5 d }~X Y qVX qVd S )NÚ.éÿÿÿÿÚcÚoÚ )r   ÚsplitÚjoinÚdelattrr   r    ÚosÚremover)   ÚOSErrorÚerrnoZENOENT)r/   r.   ZdeleteSourceZ
modulePathZpackageNameÚ
moduleNameZextZoser   r   r   Ú_unimportPythonModuleX   s    
z!PluginTests._unimportPythonModulec                 C   s   | j  d¡ ¡  dS )z;
        Remove the plugins B{droping.cache} file.
        údropin.cacheN)r'   r&   r@   r5   r   r   r   Ú_clearCacheg   s    zPluginTests._clearCachec                    s   t  ˆ ¡‡ fdd„ƒ}|S )zþ
        This is a paranoid test wrapper, that calls C{meth} 2 times, clear the
        cache, and calls it 2 other times. It's supposed to ensure that the
        plugin system behaves correctly no matter what the state of the cache
        is.
        c                    s,   ˆ | ƒ ˆ | ƒ |   ¡  ˆ | ƒ ˆ | ƒ d S )N)rF   r5   ©Úmethr   r   Úwrappedu   s
    z+PluginTests._withCacheness.<locals>.wrapped)Ú	functoolsÚwraps)rH   rI   r   rG   r   Ú_withCachenessn   s    zPluginTests._withCachenessc                 C   sÒ   t  | j¡}|| j }|  |jd| jf ¡ |  d|j¡ dd„ |jD ƒd }|  	|j
|¡ |  |jd¡ |  |j ¡ d¡ |  |jtt jg¡ | ¡ }|  	|tjd| jf  j¡ ddlm} |  	||j¡ dS )	a	  
        Check that the cache returned by L{plugin.getCache} hold the plugin
        B{testplugin}, and that this plugin has the properties we expect:
        provide L{TestPlugin}, has the good name and description, and can be
        loaded successfully.
        zmypackage.%szI'm a test drop-in.c                 S   s   g | ]}t |jkr|‘qS r   )r   Úprovided©Ú.0Úpr   r   r   Ú
<listcomp>   s     
 z*PluginTests.test_cache.<locals>.<listcomp>r   Ú
TestPluginz*A plugin used solely for testing purposes.N)r   ÚgetCacher.   r,   ÚassertEqualrC   ÚassertInZdescriptionÚpluginsZassertIsÚdropinÚnameÚstriprM   r   ZIPluginÚloadr   r    rR   Zmypackage.testpluginr   )r/   ÚcacherW   Zp1Z
realPluginÚtpr   r   r   Ú
test_cache€   s*    

ÿþþzPluginTests.test_cachec                 C   s>   t  | j¡| j }tdd„ |jD ƒƒd }|  t|ƒd¡ dS )zm
        L{CachedPlugin} has a helpful C{repr} which contains relevant
        information about it.
        c                 s   s   | ]}|j d kr|V  qdS )rR   N©rX   rN   r   r   r   Ú	<genexpr>¬   s    
ÿz-PluginTests.test_cacheRepr.<locals>.<genexpr>r   zT<CachedPlugin 'TestPlugin'/'mypackage.testplugin' (provides 'ITestPlugin, IPlugin')>N)r   rS   r.   r,   ÚlistrV   rT   Úrepr)r/   ZcachedDropinZcachedPluginr   r   r   Útest_cacheRepr¦   s    ÿþzPluginTests.test_cacheReprc                 C   sL   t t t| j¡ƒ}|  t|ƒd¡ ddg}|D ]}| |j¡ | 	¡  q.dS )a  
        L{plugin.getPlugins} should return the list of plugins matching the
        specified interface (here, L{ITestPlugin2}), and these plugins
        should be instances of classes with a C{test} method, to be sure
        L{plugin.getPlugins} load classes correctly.
        é   ZAnotherTestPluginZThirdTestPluginN)
r`   r   Ú
getPluginsr   r.   rT   Úlenr@   r   Ztest)r/   rV   ÚnamesrP   r   r   r   Útest_pluginsµ   s    zPluginTests.test_pluginsc              
   C   s¨   t tƒ d¡ | j d¡¡ zr|  	dtj¡ |  
ttjd dƒd¡ tt t| j¡ƒ}|  t|ƒd¡ d	d
g}|D ]}| |j¡ | ¡  qrW 5 |  tjd d¡ X dS )ze
        Check that L{plugin.getPlugins} is able to detect plugins added at
        runtime.
        úplugin_extra1.pyúpluginextra.pyúmypackage.pluginextraTr   Úpluginextraz&mypackage still has pluginextra modulerc   rR   ÚFourthTestPluginN)r   r)   r*   r+   r'   r&   rD   r   r    ÚfailIfInÚassertFalseÚhasattrr`   r   rd   r   r.   rT   re   r@   r   Útest1©r/   Úplgsrf   rP   r   r   r   Útest_detectNewFilesÈ   s$    
ÿÿþzPluginTests.test_detectNewFilesc              
   C   sÒ   t tƒ d¡ | j d¡¡ zœt	t
 t| j¡ƒ}|  t|ƒd¡ t tƒ d¡ | j d¡¡ |  tjd ¡ t	t
 t| j¡ƒ}|  t|ƒd¡ dd	d
g}|D ]}| |j¡ | ¡  qœW 5 |  tjd d¡ X dS )z…
        Check that if the content of a plugin change, L{plugin.getPlugins} is
        able to detect the new plugins added.
        rh   ri   rj   Trc   zplugin_extra2.pyé   rR   rl   ZFifthTestPluginN)r   r)   r*   r+   r'   r&   rD   r   r    r`   r   rd   r   r.   rT   re   r@   r   rp   rq   r   r   r   Útest_detectFilesChangedç   s(    
ÿ
ÿ
þz#PluginTests.test_detectFilesChangedc              
   C   sn   t tƒ d¡ | j d¡¡ zt	t
 t| j¡ƒ W 5 |  tjd d¡ X t	t
 t| j¡ƒ}|  dt|ƒ¡ dS )zs
        Check that when a dropin file is removed, L{plugin.getPlugins} doesn't
        return it anymore.
        rh   ri   rj   Té   N)r   r)   r*   r+   r'   r&   rD   r   r    r`   r   rd   r   r.   rT   re   )r/   rr   r   r   r   Útest_detectFilesRemoved
  s    
ÿþz#PluginTests.test_detectFilesRemovedc              	   C   sd   |   ¡ }|  tj |¡¡ | jj |¡ z&t	t
 t| j¡ƒ}|  t|ƒd¡ W 5 | jj |¡ X dS )zy
        Test that getCache skips over any entries in a plugin package's
        C{__path__} which do not exist.
        rv   N)r#   rn   r?   r   Úexistsr.   Ú__path__Úappendr@   r`   r   rd   r   rT   re   )r/   r   rr   r   r   r   Útest_nonexistentPathEntry  s    z%PluginTests.test_nonexistentPathEntryc              	   C   sx   t |  ¡ ƒ}|  | ¡ ¡ | ¡  | d¡j}| jj 	|¡ z&tt t| j¡ƒ}|  t|ƒd¡ W 5 | jj 
|¡ X dS )z¡
        Test that getCache skips over any entries in a plugin package's
        C{__path__} which refer to children of paths which are not directories.
        Ztest_packagerv   N)r   r#   rn   rx   Ztouchr&   r   r.   ry   rz   r@   r`   r   rd   r   rT   re   )r/   r   r&   rr   r   r   r   Útest_nonDirectoryChildEntry1  s    z'PluginTests.test_nonDirectoryChildEntryc                 C   sþ   t  | j¡ | j d¡}ttƒ d¡ | j d¡¡ t	ƒ  t
 | jjd¡ t
 |jd¡ |  t
j| jjd¡ |  t
j|jd¡ g }t|jƒ |  t|j¡ t  | j¡}|  d|¡ |  | j|¡ d|jtjf }|D ]}|t|ƒkrÔ qúqÔ|  d	|f ¡ d
S )z¿
        The C{dropin.cache} file may not be writable: the cache should still be
        attainable, but an error should be logged to show that the cache
        couldn't be updated.
        rE   rh   ri   i@  é   iÀ  rk   ú3Unable to write to plugin cache %s: error number %dú;Did not observe unwriteable cache warning in log events: %rN)r   rS   r.   r'   r&   r   r)   r*   r+   r   r?   Úchmodr   Ú
addCleanupr	   rz   r
   rU   r,   rB   ÚEPERMr   Úfail)r/   Z	cachepathÚeventsr[   ÚexpectedÚeventr   r   r   Útest_deployedModeD  s8    
ÿ
 ÿÿÿzPluginTests.test_deployedModeN)F)r   r   r   r   r0   r6   rD   rF   rL   r]   rb   rg   rs   ru   rw   r{   r|   r‡   r   r   r   r   r   2   s,   	
# r   sj   
from twisted.plugin import pluginPackagePaths
__path__.extend(pluginPackagePaths(__name__))
__all__ = []
c                 C   s   d  | ¡ d¡S )Nzµfrom zope.interface import provider
from twisted.plugin import IPlugin
from twisted.test.test_plugin import ITestPlugin

@provider(IPlugin, ITestPlugin)
class {0}(object):
    pass
Úascii)ÚformatÚencoder^   r   r   r   ÚpluginFileContentsx  s    ÿøør‹   c                 C   sl   |   ¡  |  d¡}|  ¡  |r.| d¡ d¡ | d¡}|  ¡  |rT| d¡ t¡ | |d ¡ |¡ |S )z'
    Create a plugindummy package.
    Úplugindummyr   r   rV   ú.py)r%   r&   r(   ÚpluginInitFile)Z	entrypathZpluginContentÚrealÚpluginModuleÚpkgZplugsr   r   r   Ú_createPluginDummy„  s    

r’   c                   @   sn   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erbesbde_dd„ ZdS )ÚDeveloperSetupTestsz³
    These tests verify things about the plugin system without actually
    interacting with the deployed 'twisted.plugins' package, instead creating a
    temporary package.
    c                 C   s>  t jdd… | _t j ¡ | _t|  ¡ ƒ| _| j 	¡  | j 
d¡| _| j 
d¡| _| j 
d¡| _t| jtdƒddƒ| _t| jtdƒddƒ| _t| jtd	ƒd
dƒ| _t j dd„ | j| jfD ƒ¡ |  ¡  | j 
d¡ 
d¡| _| j 
d¡| _t ¡ }t | j 
d¡j|d fd ¡ t | jj|d fd ¡ |  ¡  |  ¡  dS )a7  
        Create a complex environment with multiple entries on sys.path, akin to
        a developer's environment who has a development (trunk) checkout of
        Twisted, a system installed version of Twisted (for their operating
        system's tools) and a project which provides Twisted plugins.
        NZsystem_pathZdevelopment_pathZapplication_pathÚsystemTZplugindummy_builtinÚdevÚappFZplugindummy_appc                 S   s   g | ]
}|j ‘qS r   ©r   ©rO   Úxr   r   r   rQ   ¶  s     z-DeveloperSetupTests.setUp.<locals>.<listcomp>rŒ   rV   rE   zplugindummy_builtin.pyiˆ  rc   iÐ  )r   r   Ú	savedPathr    r!   r"   r   r#   ZfakeRootr%   r&   Ú
systemPathÚdevPathÚappPathr’   r‹   ZsystemPackageZ
devPackageÚ
appPackageÚextendÚgetAllPluginsÚsysplugÚsyscacheÚtimer?   ÚutimeÚ
lockSystemÚresetEnvironment)r/   Znowr   r   r   r0     sN    
  þ  þ  þÿ
þzDeveloperSetupTests.setUpc                 C   s$   t  | jjd¡ t  | jjd¡ dS )zW
        Lock the system directories, as if they were unwritable by this user.
        im  N©r?   r€   r¡   r   r¢   r5   r   r   r   r¥   Ë  s    zDeveloperSetupTests.lockSystemc                 C   s$   t  | jjd¡ t  | jjd¡ dS )zW
        Unlock the system directories, as if they were writable by this user.
        iÿ  Nr§   r5   r   r   r   ÚunlockSystemÓ  s    z DeveloperSetupTests.unlockSystemc                 C   s(   ddl }tt t|j¡ƒ}dd„ |D ƒS )zl
        Get all the plugins loadable from our dummy package, and return their
        short names.
        r   Nc                 S   s   g | ]
}|j ‘qS r   ©r   )rO   Zplugr   r   r   rQ   ä  s     z5DeveloperSetupTests.getAllPlugins.<locals>.<listcomp>)Zplugindummy.pluginsr`   r   rd   r   rV   )r/   rŒ   r™   r   r   r   r    Û  s    z!DeveloperSetupTests.getAllPluginsc                 C   s.   |   ¡  tj dd„ | j| j| jfD ƒ¡ dS )zc
        Change the environment to what it should be just as the test is
        starting.
        c                 S   s   g | ]
}|j ‘qS r   r—   r˜   r   r   r   rQ   í  s     z8DeveloperSetupTests.resetEnvironment.<locals>.<listcomp>N)ÚunsetEnvironmentr   r   rŸ   rœ   r›   r   r5   r   r   r   r¦   ç  s
    þz$DeveloperSetupTests.resetEnvironmentc                 C   s2   t ƒ  tj ¡  tj | j¡ | jtjdd…< dS )zh
        Change the Python environment back to what it was before the test was
        started.
        N)r   r   r    r3   r4   r"   rš   r   r5   r   r   r   rª   ñ  s    
z$DeveloperSetupTests.unsetEnvironmentc                 C   s   |   ¡  |  ¡  dS )zÑ
        Reset the Python environment to what it was before this test ran, and
        restore permissions on files which were marked read-only so that the
        directory may be cleanly cleaned up.
        N)rª   r¨   r5   r   r   r   r6   ü  s    zDeveloperSetupTests.tearDownc                 C   s2   t dƒD ]$}|  ¡ }| ¡  |  |ddg¡ qdS )a  
        Plugins added in the development path should be loadable, even when
        the (now non-importable) system path contains its own idea of the
        list of plugins for a package.  Inversely, plugins added in the
        system path should not be available.
        rt   r–   r•   N)Úranger    ÚsortrT   )r/   r™   rf   r   r   r   Ú"test_developmentPluginAvailability
  s    	z6DeveloperSetupTests.test_developmentPluginAvailabilityc                 C   sî   | j  d¡}| tdƒ¡ t ¡ d }t |j||f¡ | d¡}t	rRt
dd}nt
ƒ }tj| j jfddi|—Ž t |j||f¡ | ¡  |  ¡  |  d|  ¡ ¡ |  d	|  ¡ ¡ |  ¡  | td	ƒ¡ |  d|  ¡ ¡ |  d	|  ¡ ¡ d
S )zÜ
        Verify that if a stale .pyc file on the PYTHONPATH is replaced by a
        fresh .py file, the plugins in the new .py are picked up rather than
        the stale .pyc, even if the .pyc is still around.
        zstale.pyÚoneiè  z	stale.pycT)ZlegacyÚquietrv   ZtwoN)rž   r&   r(   r‹   r£   r?   r¤   r   r*   r   ÚdictÚ
compileallZcompile_dirr@   r¦   rU   r    rm   )r/   Zmypathr™   ZpycZextrar   r   r   Útest_freshPyReplacesStalePyc  s$    
z0DeveloperSetupTests.test_freshPyReplacesStalePycz/PyPy2 will not normally import lone .pyc files.c                 C   s¢   |   ¡  | j d¡ tdƒ¡ |  ¡  tj | j	j¡ g }t
|jƒ |  t|j¡ |  d|  ¡ ¡ d| jjtjf }|D ]}|t|ƒkrx qžqx|  d|f ¡ dS )aF  
        Verify that a failure to write the dropin.cache file on a read-only
        path will not affect the list of plugins returned.

        Note: this test should pass on both Linux and Windows, but may not
        provide useful coverage on Windows due to the different meaning of
        "read-only directory".
        znewstuff.pyr®   r~   r   N)r¨   r¡   r&   r(   r‹   r¥   r   r   r@   rœ   r	   rz   r   r
   rU   r    r¢   rB   r‚   r   rƒ   )r/   r„   r…   r†   r   r   r   Útest_newPluginsOnReadOnlyPathB  s(    	
 ÿÿÿz1DeveloperSetupTests.test_newPluginsOnReadOnlyPathN)r   r   r   r   r0   r¥   r¨   r    r¦   rª   r6   r­   r²   r   r   Úskipr³   r   r   r   r   r“   –  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 )ÚAdjacentPackageTestsz–
    Tests for the behavior of the plugin system when there are multiple
    installed copies of the package containing the plugins being loaded.
    c                 C   s    t jdd… | _t j ¡ | _dS )zS
        Save the elements of C{sys.path} and the items of C{sys.modules}.
        N)r   r   r   r    r!   r"   r5   r   r   r   r0   m  s    zAdjacentPackageTests.setUpc                 C   s,   | j tjdd…< tj ¡  tj | j¡ dS r1   r2   r5   r   r   r   r6   u  s    
zAdjacentPackageTests.tearDownc                 C   sn   |  |¡}|  d¡}| ¡  |  d¡ d¡ |  d¡}| ¡  |  d¡ t¡ |  |d ¡}| t|ƒ¡ |S )a`  
        Create a directory containing a Python package named I{dummy} with a
        I{plugins} subpackage.

        @type root: L{FilePath}
        @param root: The directory in which to create the hierarchy.

        @type name: C{str}
        @param name: The name of the directory to create which will contain
            the package.

        @type pluginName: C{str}
        @param pluginName: The name of a module to create in the
            I{dummy.plugins} package.

        @rtype: L{FilePath}
        @return: The directory which was created to contain the I{dummy}
            package.
        Údummyr   r   rV   r   )r&   Úmakedirsr(   rŽ   r‹   )r/   r$   rX   Z
pluginNameZ	directoryr'   rV   r   r   r   r   ÚcreateDummyPackage~  s    


z'AdjacentPackageTests.createDummyPackagec                 C   s‚   t |  ¡ ƒ}| ¡  |  |dd¡}|  |dd¡}tj |j¡ tj |j¡ ddl}tt	 
t|j¡ƒ}|  dgdd„ |D ƒ¡ dS )zê
        Only plugins from the first package in sys.path should be returned by
        getPlugins in the case where there are two Python packages by the same
        name installed, each with a plugin module by a single name.
        ÚfirstZ
somepluginÚsecondr   Nc                 S   s   g | ]
}|j ‘qS r   r©   rN   r   r   r   rQ   °  s     zWAdjacentPackageTests.test_hiddenPackageSamePluginModuleNameObscured.<locals>.<listcomp>©r   r#   r·   r¸   r   r   rz   Zdummy.pluginsr`   r   rd   r   rV   rT   ©r/   r$   ZfirstDirectoryZsecondDirectoryr¶   rV   r   r   r   Ú.test_hiddenPackageSamePluginModuleNameObscuredž  s    zCAdjacentPackageTests.test_hiddenPackageSamePluginModuleNameObscuredc                 C   s‚   t |  ¡ ƒ}| ¡  |  |dd¡}|  |dd¡}tj |j¡ tj |j¡ ddl}tt	 
t|j¡ƒ}|  dgdd„ |D ƒ¡ dS )	zè
        Plugins from the first package in sys.path should be returned by
        getPlugins in the case where there are two Python packages by the same
        name installed, each with a plugin module by a different name.
        r¹   Z
thispluginrº   Z
thatpluginr   Nc                 S   s   g | ]
}|j ‘qS r   r©   rN   r   r   r   rQ   Å  s     z\AdjacentPackageTests.test_hiddenPackageDifferentPluginModuleNameObscured.<locals>.<listcomp>r»   r¼   r   r   r   Ú3test_hiddenPackageDifferentPluginModuleNameObscured³  s    zHAdjacentPackageTests.test_hiddenPackageDifferentPluginModuleNameObscuredN)	r   r   r   r   r0   r6   r¸   r½   r¾   r   r   r   r   rµ   g  s   	 rµ   c                   @   s0   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
S )ÚPackagePathTestszg
    Tests for L{plugin.pluginPackagePaths} which constructs search paths for
    plugin packages.
    c                 C   s   t jdd… | _dS )z3
        Save the elements of C{sys.path}.
        N)r   r   r   r5   r   r   r   r0   Ï  s    zPackagePathTests.setUpc                 C   s   | j tjdd…< dS )z<
        Restore C{sys.path} to its original value.
        N)r   r   r   r5   r   r   r   r6   Ö  s    zPackagePathTests.tearDownc                 C   sT   t dƒ}t dƒ}|j|jgt_|  t d¡| d¡ d¡j| d¡ d¡jg¡ dS )z®
        L{plugin.pluginPackagePaths} should return a list containing each
        directory in C{sys.path} with a suffix based on the supplied package
        name.
        ÚfooÚbarúdummy.pluginsr¶   rV   N)r   r   r   rT   r   ÚpluginPackagePathsr&   )r/   rÀ   rÁ   r   r   r   Útest_pluginDirectoriesÝ  s    ÿþz'PackagePathTests.test_pluginDirectoriesc                 C   s€   t |  ¡ ƒ}| d¡ d¡ d¡}| ¡  | d¡ d¡ | d¡j| d¡jgt_|  t 	d¡| d¡ d¡ d¡jg¡ dS )	a™  
        L{plugin.pluginPackagePaths} should exclude directories which are
        Python packages.  The only allowed plugin package (the only one
        associated with a I{dummy} package which Python will allow to be
        imported) will already be known to the caller of
        L{plugin.pluginPackagePaths} and will most commonly already be in
        the C{__path__} they are about to mutate.
        rÀ   r¶   rV   r   r   rÁ   rÂ   N)
r   r#   r&   r·   r(   r   r   rT   r   rÃ   )r/   r$   rÀ   r   r   r   Útest_pluginPackagesExcludedì  s    	þz,PackagePathTests.test_pluginPackagesExcludedN)r   r   r   r   r0   r6   rÄ   rÅ   r   r   r   r   r¿   É  s
   r¿   )&r   Z
__future__r   r   r   rB   r?   r£   r±   rJ   Zzope.interfacer   Ztwisted.trialr   Ztwisted.python.compatr   r   Ztwisted.python.logr   r	   r
   Ztwisted.python.filepathr   Ztwistedr   Ú	importlibr   r   r   r   ZTestCaser   rŽ   r‹   r’   r“   rµ   r¿   r   r   r   r   Ú<module>   s2    	  B Rb