
    \d(c                     v   d 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 ddlmZ ddlmZ ddlmZmZmZ dd	lmZ  G d
 de          Z G d de          Z G d dej                  ZdZd Zd Z G d dej                  Z G d dej                  Z  G d dej                  Z!dS )z"
Tests for Twisted plugin system.
    N)invalidate_caches)Callable)	Interface)plugin)FilePath)addObserverremoveObservertextFromEventDict)unittestc                       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__     8lib/python3.11/site-packages/twisted/test/test_plugin.pyr   r      s           r   r   c                       e Zd ZdZdS )ITestPlugin2z
    See L{ITestPlugin}.
    Nr   r   r   r   r   r   #   s           r   r   c                       e Zd ZdZd Zd ZddZd ZdefdZ	e	d	             Z
d
 Ze	d             Ze	d             Ze	d             Ze	d             Ze	d             Ze	d             Zd ZdS )PluginTestsz_
    Tests which verify the behavior of the current, active Twisted plugins
    directory.
    c                    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__.pyr   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   s     r   setUpzPluginTests.setUp/   s!     HQQQKK,,..T[[]]++		!!###y{33$$&&&=))44S999""#455<<L//	
 	
 	
 +49>***r   c                     | 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#   r0   s    r   tearDownzPluginTests.tearDownG   I     '4,-----r   Fc                    |j                             d          }d                    |d d                   }|d         }t          t          j        |         |           t          j        |j         = ddg|rdgpg z   D ]L}	 t          j        |j        |z               # t          $ r }|j
        t          j        k    r Y d }~Ed }~ww xY wd S )N.co )r   splitjoindelattrr   r!   osremover*   OSErrorerrnoENOENT)r0   r/   deleteSource
modulePathpackageName
moduleNameextoses           r   _unimportPythonModulez!PluginTests._unimportPythonModuleO   s    _**3//
hhz#2#//^
K(*555K(:!62$!<"= 	 	C	&/C/0000   9,, -,,,,	 	s   B
C(CCc                 ^    | j                             d                                           dS )z;
        Remove the plugins B{droping.cache} file.
        dropin.cacheN)r(   r'   rD   r7   s    r   _clearCachezPluginTests._clearCache]   s,     	>**1133333r   methc                 F     t          j                    f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                      |             |            |                                    |             |            d S )N)rQ   )r0   rR   s    r   wrappedz+PluginTests._withCacheness.<locals>.wrappedk   sM    DJJJDJJJDJJJDJJJJJr   )	functoolswraps)rR   rU   s   ` r   _withCachenesszPluginTests._withCachenessc   s:     
			 	 	 	 
		 r   c                    t          j        | j                  }|| j                 }|                     |j        d| j                    |                     d|j                   d |j        D             d         }| 	                    |j
        |           |                     |j        d           |                     |j                                        d           |                     |j        t          t           j        g           |                                }| 	                    |t"          j        d| j                  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.zI'm a test drop-in.c                 .    g | ]}t           |j        v |S r   )r   provided.0ps     r   
<listcomp>z*PluginTests.test_cache.<locals>.<listcomp>   s$    EEEA;!*+D+Da+D+D+Dr   r   
TestPluginz*A plugin used solely for testing purposes.N)r   getCacher/   r-   assertEqualrK   assertIndescriptionpluginsassertIsdropinnamestripr[   r   IPluginloadr   r!   r`   mypackage.testpluginr   )r0   cacherg   p1
realPlugintps         r   
test_cachezPluginTests.test_cacheu   sh    ,,t*+*,N9L,N,NOOO+V-?@@@ FEEEEaHbi(((,/// 	N  ""$P	
 	
 	
 	{FN&CDDDWWYY
K:T%8::;F	
 	
 	
 	*)))))j"-00000r   c                     t          j        | j                  | j                 }t	          d |j        D                       d         }|                     t          |          d           dS )zm
        L{CachedPlugin} has a helpful C{repr} which contains relevant
        information about it.
        c              3   0   K   | ]}|j         d k    |V  dS )r`   Nrh   r\   s     r   	<genexpr>z-PluginTests.test_cacheRepr.<locals>.<genexpr>   s.      VV!qv?U?UA?U?U?U?UVVr   r   zT<CachedPlugin 'TestPlugin'/'mypackage.testplugin' (provides 'ITestPlugin, IPlugin')>N)r   ra   r/   r-   listre   rb   repr)r0   cachedDropincachedPlugins      r   test_cacheReprzPluginTests.test_cacheRepr   sx    
 t{33D4GHVV|';VVVVV
 	1	
 	
 	
 	
 	
r   c                    t          t          j        t          | j                            }|                     t          |          d           ddg}|D ]0}|                    |j                   |	                                 1d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.
           AnotherTestPluginThirdTestPluginN)
rv   r   
getPluginsr   r/   rb   lenrD   r   test)r0   re   namesr^   s       r   test_pluginszPluginTests.test_plugins   s     v(t{CCDDWq)))$&78 	 	ALL$$$FFHHHH	 	r   c                    t          t                                        d                              | j                            d                     	 |                     dt          j                   | 	                    t          t          j        d         d          d           t          t          j        t          | j                            }|                     t#          |          d           dd	g}|D ]0}|                    |j                   |                                 1	 |                     t          j        d         d
           dS # |                     t          j        d         d
           w xY w)ze
        Check that L{plugin.getPlugins} is able to detect plugins added at
        runtime.
        plugin_extra1.pypluginextra.pymypackage.pluginextrar   pluginextraz&mypackage still has pluginextra moduler|   r`   FourthTestPluginTN)r   r*   r+   r,   r(   r'   failIfInr   r!   assertFalsehasattrrv   r   r   r   r/   rb   r   rD   r   test1rN   r0   plgsr   r^   s       r   test_detectNewFileszPluginTests.test_detectNewFiles   s[    	""#566==L/00	
 	
 	
	SMM13;???K0-@@8  
 )+t{CCDDD SYY***!#56E  QZ(((				 &&s{3J'KTRRRRRD&&s{3J'KTRRRRs   CE (E?c                    t          t                                        d                              | j                            d                     	 t          t          j        t          | j
                            }|                     t          |          d           t          t                                        d                              | j                            d                     |                     t          j        d                    t          t          j        t          | j
                            }|                     t          |          d           g d}|D ]0}|                    |j                   |                                 1	 |                     t          j        d         d           d	S # |                     t          j        d         d           w xY w)
z
        Check that if the content of a plugin change, L{plugin.getPlugins} is
        able to detect the new plugins added.
        r   r   r|   zplugin_extra2.pyr      )r`   r   FifthTestPluginTN)r   r*   r+   r,   r(   r'   rv   r   r   r   r/   rb   r   rN   r   r!   rD   r   r   r   s       r   test_detectFilesChangedz#PluginTests.test_detectFilesChanged   s    	""#566==L/00	
 	
 	
	S)+t{CCDDDSYY***X&&'9::AA""#344  
 &&s{3J'KLLL )+t{CCDDDSYY***IIIE  QZ(((				 &&s{3J'KTRRRRRD&&s{3J'KTRRRRs   EG	 	(G1c                 F   t          t                                        d                              | j                            d                     	 t          t          j        t          | j
                             |                     t          j        d         d           n+# |                     t          j        d         d           w xY wt          t          j        t          | j
                            }|                     dt          |                     dS )zs
        Check that when a dropin file is removed, L{plugin.getPlugins} doesn't
        return it anymore.
        r   r   r   T   N)r   r*   r+   r,   r(   r'   rv   r   r   r   r/   rN   r   r!   rb   r   )r0   r   s     r   test_detectFilesRemovedz#PluginTests.test_detectFilesRemoved   s     	""#566==L/00	
 	
 	
	S";<<=== &&s{3J'KTRRRRD&&s{3J'KTRRRRF%k4;??@@CII&&&&&s   ,B' '(Cc                    |                                  }|                     t          j                            |                     | j        j                            |           	 t          t          j
        t          | j                            }|                     t          |          d           | j        j                            |           dS # | j        j                            |           w xY w)zy
        Test that getCache skips over any entries in a plugin package's
        C{__path__} which do not exist.
        r   N)r$   r   rC   r   existsr/   __path__appendrv   r   r   r   rb   r   rD   )r0   r   r   s      r   test_nonexistentPathEntryz%PluginTests.test_nonexistentPathEntry  s     {{}}--...##D)))	.)+t{CCDDDSYY***K ''-----DK ''----s   'AC !C8c                 V   t          |                                           }|                     |                                           |                                 |                    d          j        }| j        j        	                    |           	 t          t          j        t          | j                            }|                     t          |          d           | j        j                            |           dS # | j        j                            |           w xY w)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.
        test_packager   N)r   r$   r   r   touchr'   r   r/   r   r   rv   r   r   r   rb   r   rD   )r0   r   r'   r   s       r   test_nonDirectoryChildEntryz'PluginTests.test_nonDirectoryChildEntry  s     &&'''



>**/##E***	/)+t{CCDDDSYY***K ''.....DK ''....s   AD !D(c                    t          j        | j                   | j                            d          }t          t                                        d                              | j                            d                     t                       t          j        | j        j        d           t          j        |j        d           |                     t          j        | j        j        d           |                     t          j        |j        d           g }t          |j                   |                     t           |j                   t          j        | j                  }|                     d|           |                     | j        |           d|j        t&          j        fz  }|D ]}|t+          |          v r d
S |                     d	|           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.
        rP   r   r   i@     i  r   3Unable to write to plugin cache %s: error number %d9Did not observe unwriteable cache warning in log events: N)r   ra   r/   r(   r'   r   r*   r+   r,   invalidateImportCachesrC   chmodr   
addCleanupr   r   r	   rc   r-   rF   EPERMr
   fail)r0   	cachepatheventsrm   expectedevents         r   test_deployedModezPluginTests.test_deployedMode,  s    	$$$L&&~66	 	""#566==L/00	
 	
 	
 	   
"E***
'''$,"3U;;;).%888 FM"""666,,mU+++d)5111 INKL
 
  	 	E,U3333 4 III &)    r   N)F)r   r   r   r   r1   r8   rN   rQ   r   rX   rq   rz   r   r   r   r   r   r   r   r   r   r   r   r   )   s]        
     0. . .   4 4 4X    $ "1 "1 ^"1H
 
 
   ^  S S ^S: S S ^S@ ' ' ^'" . . ^. / / ^/ - - - - -r   r   sj   
from twisted.plugin import pluginPackagePaths
__path__.extend(pluginPackagePaths(__name__))
__all__ = []
c                 R    d                     |                               d          S )Nzfrom zope.interface import provider
from twisted.plugin import IPlugin
from twisted.test.test_plugin import ITestPlugin

@provider(IPlugin, ITestPlugin)
class {}:
    pass
ascii)formatencodert   s    r   pluginFileContentsr   d  s$     
	r   c                    |                                   |                     d          }|                                  |r(|                    d                              d           |                    d          }|                                  |r-|                    d                              t                     |                    |dz                                 |           |S )z'
    Create a plugindummy package.
    plugindummyr   r   re   .py)r&   r'   r)   pluginInitFile)	entrypathpluginContentrealpluginModulepkgplugss         r   _createPluginDummyr   t  s     
//-
(
(C 1		-  ++C000IIi  E	 >M""--n===	KKu$%%00???Lr   c                   N    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Z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                    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 | j        | j        fD                        |                                  | j        
                    d          
                    d          | _        | j        
                    d          | _        t/          j                    }t1          j        | j        
                    d          j        |dz
  fdz             t1          j        | j        j        |dz
  fdz             |                                  |                                  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.
        Nsystem_pathdevelopment_pathapplication_pathsystemTplugindummy_builtindevappFplugindummy_appc                     g | ]	}|j         
S r   r   r]   xs     r   r_   z-DeveloperSetupTests.setUp.<locals>.<listcomp>  s    IIIAIIIr   r   re   rP   zplugindummy_builtin.pyi  r|   i  )r   r   	savedPathr!   r"   r#   r   r$   fakeRootr&   r'   
systemPathdevPathappPathr   r   systemPackage
devPackage
appPackageextendgetAllPluginssysplugsyscachetimerC   utime
lockSystemresetEnvironment)r0   nows     r   r1   zDeveloperSetupTests.setUp  s    !!!K,,.. //%%'''---m<<}**+=>>}**+=>>/O/994AV
 
 -L,U33T;P
 
 -L,U33U<M
 

 	II$/4<)HIIIJJJ 	,,];;AA)LL**>:: ikk
##$<==BS4ZMTUDUVVV
#cDj]Q%6777 	r   c                     t          j        | j        j        d           t          j        | j        j        d           dS )zW
        Lock the system directories, as if they were unwritable by this user.
        im  NrC   r   r   r   r   r7   s    r   r   zDeveloperSetupTests.lockSystem  8     	"E***
#U+++++r   c                     t          j        | j        j        d           t          j        | j        j        d           dS )zW
        Unlock the system directories, as if they were writable by this user.
        i  Nr   r7   s    r   unlockSystemz DeveloperSetupTests.unlockSystem  r   r   c                 z    ddl }t          t          j        t          |j                            }d |D             S )zl
        Get all the plugins loadable from our dummy package, and return their
        short names.
        r   Nc                     g | ]	}|j         
S r   r   )r]   plugs     r   r_   z5DeveloperSetupTests.getAllPlugins.<locals>.<listcomp>  s    ,,,$,,,r   )plugindummy.pluginsrv   r   r   r   re   )r0   r   r   s      r   r   z!DeveloperSetupTests.getAllPlugins  sA     	#"""";0CDDEE,,!,,,,r   c                     |                                   t          j                            d | j        | j        | j        fD                        dS )zc
        Change the environment to what it should be just as the test is
        starting.
        c                     g | ]	}|j         
S r   r   r   s     r   r_   z8DeveloperSetupTests.resetEnvironment.<locals>.<listcomp>  s    WWWAWWWr   N)unsetEnvironmentr   r   r   r   r   r   r7   s    r   r   z$DeveloperSetupTests.resetEnvironment  sL    
 	WW$,)VWWWXXXXXr   c                     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!   r5   r6   r#   r   r   r7   s    r   r   z$DeveloperSetupTests.unsetEnvironment  sR    
 	   4,---nr   c                 V    |                                   |                                  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   r7   s    r   r8   zDeveloperSetupTests.tearDown  s0     	
 	r   c                     t          d          D ]B}|                                 }|                                 |                     |ddg           Cd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.
        r   r   r   N)ranger   sortrb   )r0   r   r   s      r   "test_developmentPluginAvailabilityz6DeveloperSetupTests.test_developmentPluginAvailability  s^     q 	4 	4A&&((EJJLLLUUEN3333	4 	4r   c                    | j                             d          }|                    t          d                     t	          j                    dz
  }t          j        |j        ||f           |                    d          }t          d          }t          j        | j         j        fddi| t          j        |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)legacyquietr   twoN)r   r'   r)   r   r   rC   r   r   r+   dict
compileallcompile_dirrD   r   rc   r   r   )r0   mypathr   pycextras        r   test_freshPyReplacesStalePycz0DeveloperSetupTests.test_freshPyReplacesStalePyc  s    &&z22,U33444IKK$
q!f%%%nn[)) D!!!t3FF1FFFF
Aq6"""eT//11222eT//11222,U33444eT//11222eT//1122222r   c                 p   |                                   | j                            d                              t	          d                     |                                  t          j                            | j	        j                   g }t          |j                   |                     t          |j                   |                     d|                                            d| j        j        t"          j        fz  }|D ]}|t'          |          v r dS |                     d|           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   rD   r   r   r   r   r	   rc   r   r   rF   r   r
   r   )r0   r   r   r   s       r   test_newPluginsOnReadOnlyPathz1DeveloperSetupTests.test_newPluginsOnReadOnlyPath  s:    	=))445G5N5NOOO 	)*** FM"""666eT//11222 IMKL
 
  	 	E,U3333 4 III &)    r   N)r   r   r   r   r1   r   r   r   r   r   r8   r   r   r   r   r   r   r   r     s         (  (  ( T, , ,, , ,
- 
- 
-Y Y Y% % %  4 4 43 3 3@$ $ $ $ $r   r   c                   0    e Zd ZdZd Zd Zd Zd Z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                 ~    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#   r7   s    r   r1   zAdjacentPackageTests.setUpJ  s2      HQQQKK,,..r   c                     | j         t          j        dd<   t          j                                         t          j                            | j                   dS r3   r4   r7   s    r   r8   zAdjacentPackageTests.tearDownQ  r9   r   c                    |                     |          }|                     d          }|                                 |                     d                              d           |                     d          }|                                 |                     d                              t                     |                     |dz             }|                    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   re   r   )r'   makedirsr)   r   r   )r0   r%   rh   
pluginName	directoryr(   re   r   s           r   createDummyPackagez'AdjacentPackageTests.createDummyPackageY  s    ( JJt$$	//'**m$$//444--	**m$$//???}}Z%%788 24 8 8999r   c                    t          |                                           }|                                 |                     |dd          }|                     |dd          }t          j                            |j                   t          j                            |j                   ddl}t          t          j
        t          |j                            }|                     dg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.
        first
somepluginsecondr   Nc                     g | ]	}|j         
S r   r   r\   s     r   r_   zWAdjacentPackageTests.test_hiddenPackageSamePluginModuleNameObscured.<locals>.<listcomp>      $A$A$AAQZ$A$A$Ar   r   r$   r  r	  r   r   r   dummy.pluginsrv   r   r   r   re   rb   r0   r%   firstDirectorysecondDirectoryr  re   s         r   .test_hiddenPackageSamePluginModuleNameObscuredzCAdjacentPackageTests.test_hiddenPackageSamePluginModuleNameObscuredx       &&00wMM11$,OO+,,,,---v(emDDEE'$A$A$A$A$ABBBBBr   c                    t          |                                           }|                                 |                     |dd          }|                     |dd          }t          j                            |j                   t          j                            |j                   ddl}t          t          j
        t          |j                            }|                     dg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  
thispluginr  
thatpluginr   Nc                     g | ]	}|j         
S r   r   r\   s     r   r_   z\AdjacentPackageTests.test_hiddenPackageDifferentPluginModuleNameObscured.<locals>.<listcomp>  r  r   r  r  s         r   3test_hiddenPackageDifferentPluginModuleNameObscuredzHAdjacentPackageTests.test_hiddenPackageDifferentPluginModuleNameObscured  r  r   N)	r   r   r   r   r1   r8   r	  r  r  r   r   r   r  r  D  sq         
/ / /. . .  >C C C(C C C C Cr   r  c                   *    e Zd ZdZd Zd Zd Zd ZdS )PackagePathTestszg
    Tests for L{plugin.pluginPackagePaths} which constructs search paths for
    plugin packages.
    c                 8    t           j        dd         | _        dS )z3
        Save the elements of C{sys.path}.
        N)r   r   r    r7   s    r   r1   zPackagePathTests.setUp  s      HQQQKr   c                 2    | j         t          j        dd<   dS )z<
        Restore C{sys.path} to its original value.
        N)r    r   r   r7   s    r   r8   zPackagePathTests.tearDown  s     'r   c                 r   t          d          }t          d          }|j        |j        gt          _        |                     t	          j        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  re   N)r   r   r   rb   r   pluginPackagePathsr'   )r0   r!  r"  s      r   test_pluginDirectoriesz'PackagePathTests.test_pluginDirectories  s     uoouooHch'%o66		'""((338		'""((338	
 	
 	
 	
 	
r   c                    t          |                                           }|                    d                              d                              d          }|                                 |                    d                              d           |                    d          j        |                    d          j        gt          _        |                     t          j	        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  re   r   r   r"  r#  N)
r   r$   r'   r  r)   r   r   rb   r   r$  )r0   r%   r!  s      r   test_pluginPackagesExcludedz,PackagePathTests.test_pluginPackagesExcluded  s     &&jj%%g..44Y??		-  ++C000JJu%%*DJJu,=,=,BC%o66ZZ$$W--33I>>CD	
 	
 	
 	
 	
r   N)r   r   r   r   r1   r8   r%  r'  r   r   r   r  r    sZ         
( ( (( ( (
 
 
"
 
 
 
 
r   r  )"r   r   rF   rV   rC   r   r   	importlibr   r   typingr   zope.interfacer   twistedr   twisted.python.filepathr   twisted.python.logr   r	   r
   twisted.trialr   r   r   TestCaser   r   r   r   r   r  r  r   r   r   <module>r0     s1  
 
          				 



  A A A A A A       $ $ $ $ $ $       , , , , , , M M M M M M M M M M " " " " " "    )       9   p p p p p(# p p ph	     "| | | | |(+ | | |~ZC ZC ZC ZC ZC8, ZC ZC ZCz4
 4
 4
 4
 4
x( 4
 4
 4
 4
 4
r   