+
    Dfjh                       R t ^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	H
t ^ RIHt ^ RIHtHtHt ^ RIHt ^ RIHt ^ RIHt ^ R	IHtHtHtHt ^ R
IHt ]! R4      t ! R R]4      t  ! R R]4      t! ! R R]PD                  4      t#Rt$R R lt%R R lt& ! R R]4      t' ! R R]PD                  4      t( ! R R]PD                  4      t) ! R R]PD                  4      t*R# )z"
Tests for Twisted plugin system.
)annotationsN)invalidate_caches)
ModuleType)Callable	TypedDictTypeVar)	Interface)plugin)FilePath)	EventDictaddObserverremoveObservertextFromEventDict)unittest_Tc                      ] tR t^tRtRtR# )ITestPluginzG
A plugin for use by the plugin system's unit tests.

Do not use this.
 N__name__
__module____qualname____firstlineno____doc____static_attributes__r       :/usr/lib/python3/dist-packages/twisted/test/test_plugin.pyr   r      s    r   r   c                      ] tR t^&tRtRtR# )ITestPlugin2z
See L{ITestPlugin}.
r   Nr   r   r   r   r   r   &   s    r   r   c                     ] tR t^,tRtR R ltR R ltR R R lltR R	 ltR
 R lt	]	R R l4       t
R R lt]	R R l4       t]	R R l4       t]	R R l4       t]	R R l4       t]	R R l4       t]	R R l4       tR R ltRtR# )!PluginTestszS
Tests which verify the behavior of the current, active Twisted plugins
directory.
c                   V ^8  d   QhRR/#    returnNoner   )formats   "r   __annotate__PluginTests.__annotate__2   s        t  r   c                   \         P                  R,          V n        \         P                  P	                  4       V n        \        V P                  4       4      V n        V P                  P                  4        V P                  P                  R4      V n        V P                  P                  4        V P                  P                  R4      P                  R4       \        \        4      P                  R4      P                  V P                  P                  R4      4       RV n        \         P                  P#                  ^ V P                  P                  4       ^ RIpWn        R# )	zF
Save C{sys.path} and C{sys.modules}, and create a package for tests.
NNN	mypackage__init__.pyr   zplugin_basic.pyztestplugin.py
testpluginN)syspathoriginalPathmodulescopysavedModulesr
   mktemprootcreateDirectorychildpackage
setContent__file__siblingcopyTooriginalPlugininsertr+   module)selfr+   s   & r   setUpPluginTests.setUp2   s      HHQKKK,,.T[[]+			!!#yy{3$$&=)44S9""#45<<LL/	
 +499>>*r   c                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   r(   J        . .$ .r   c                    V P                   \        P                  R&   \        P                  P	                  4        \        P                  P                  V P                  4       R# zB
Restore C{sys.path} and C{sys.modules} to their original values.
r*   Nr0   r.   r/   r1   clearupdater3   r@   s   &r   tearDownPluginTests.tearDownJ   ?     ''4,,-r   c               $    V ^8  d   QhRRRRRR/# )r#   r?   r   deleteSourceboolr$   r%   r   )r&   s   "r   r'   r(   R   s$       04	r   c                	   VP                   f   Q hVP                  P                  R4      pRP                  VR R 4      pVR,          p\	        \
        P                  V,          V4       \
        P                  VP                   RR.T;'       d    R.;'       g    . ,            F+  p \        P                  ! VP                   V,           4       K-  	  R #   \         d     K?  i ; i)N.co )
r:   r   splitjoindelattrr.   r1   osremoveFileNotFoundError)r@   r?   rO   
modulePathpackageName
moduleNameexts   &&&    r   _unimportPythonModule!PluginTests._unimportPythonModuleR   s     ***__**3/
hhz#2/^
K(*5KK(:!6!62$!<!<"==C		&//C/0 > % s   )'CC%$C%c                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   r(   b   s     4 4T 4r   c                X    V P                   P                  R4      P                  4        R# )z+
Remove the plugins B{droping.cache} file.
dropin.cacheN)r8   r7   r[   rJ   s   &r   _clearCachePluginTests._clearCacheb   s     	>*113r   c                    V ^8  d   QhRRRR/# )r#   methzCallable[[PluginTests], object]r$   zCallable[[PluginTests], None]r   )r&   s   "r   r'   r(   h   s      -	&r   c                L   a  \         P                  ! S 4      R V 3R ll4       pV# )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                    V ^8  d   QhRRRR/# )r#   r@   r    r$   r%   r   )r&   s   "r   r'   0PluginTests._withCacheness.<locals>.__annotate__s   s     	 	+ 	$ 	r   c                h   < S! V 4       S! V 4       V P                  4        S! V 4       S! V 4       R # )N)rf   )r@   ri   s   &r   wrapped+PluginTests._withCacheness.<locals>.wrappedr   s+    JJJJr   )	functoolswraps)ri   rn   s   f r   _withCachenessPluginTests._withCachenessh   s'     
		 
	 r   c                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   r(   }   s     "1 "1D "1r   c                t   \         P                  ! V P                  4      pWP                  ,          pV P	                  VP
                  RV P                   24       V P                  RVP                  4       VP                   Uu. uF  p\        VP                  9   g   K  VNK  	  up^ ,          pV P                  VP                  V4       V P	                  VP                  R4       V P	                  VP                  P                  4       R4       V P	                  VP                  \        \         P                  .4       VP!                  4       pV P                  V\"        P$                  RV P                   2,          P&                  4       ^ RIHp V P                  WVP&                  4       R# u upi )z
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.
TestPluginz*A plugin used solely for testing purposes.N)r	   getCacher?   r=   assertEqualr_   assertIndescriptionpluginsr   providedassertIsdropinnamestripIPluginloadr.   r1   rv   mypackage.testpluginr-   )r@   cacher~   pp1
realPlugintps   &      r   
test_cachePluginTests.test_cache|   sF    ,**+**j9L9L8M,NO+V-?-?@  EA;!**+DaaEaHbii(,/ 	NN  "$P	
 	{FNN&CDWWY
KK*T%8%8$9:;FF	
 	*j--0) Fs   F5"F5c                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   r(      s     
 
 
r   c                    \         P                  ! V P                  4      V P                  ,          p\	        R VP
                   4       4      ^ ,          pV P                  \        V4      R4       R# )zU
L{CachedPlugin} has a helpful C{repr} which contains relevant
information about it.
c              3  J   "   T F  qP                   R 8X  g   K  Vx  K  	  R# 5i)rv   Nr   ).0r   s   & r   	<genexpr>-PluginTests.test_cacheRepr.<locals>.<genexpr>   s     V';!vv?UAA';s   #
#zT<CachedPlugin 'TestPlugin'/'mypackage.testplugin' (provides 'ITestPlugin, IPlugin')>N)r	   rw   r?   r=   listr{   rx   repr)r@   cachedDropincachedPlugins   &  r   test_cacheReprPluginTests.test_cacheRepr   s\    
 t{{3D4G4GHV|';';VV
 	1	
r   c                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   r(      s      d r   c                   \        \        P                  ! \        V P                  4      4      pV P                  \        V4      ^4       RR.pV F.  pVP                  VP                  4       VP                  4        K0  	  R# )z
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)
r   r	   
getPluginsr   r?   rx   lenr[   r   test)r@   r{   namesr   s   &   r   test_pluginsPluginTests.test_plugins   sa     v((t{{CDWq)$&78ALL$FFH r   c                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   r(      s     S ST Sr   c                   \        \        4      P                  R4      P                  V P                  P                  R4      4        V P                  R\        P                  4       V P                  \        \        P                  R,          R4      R4       \        \        P                  ! \        V P                  4      4      pV P!                  \#        V4      ^4       RR.pV F.  pVP%                  VP&                  4       VP)                  4        K0  	  V P+                  \        P                  R,          R	4       R
#   T P+                  \        P                  R,          R	4       i ; i)zM
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 modulerv   FourthTestPluginTN)r
   r:   r;   r<   r8   r7   failIfInr.   r1   assertFalsehasattrr   r	   r   r   r?   rx   r   r[   r   test1ra   r@   plgsr   r   s   &   r   test_detectNewFilesPluginTests.test_detectNewFiles   s    	""#56==LL/0	
	SMM13;;?K0-@8
 ))+t{{CDD SY*!#56EQZZ(	  &&s{{3J'KTRD&&s{{3J'KTRs   CE )E,c                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   r(      s     S S Sr   c                   \        \        4      P                  R4      P                  V P                  P                  R4      4        \        \        P                  ! \        V P                  4      4      pV P                  \        V4      ^4       \        \        4      P                  R4      P                  V P                  P                  R4      4       V P                  \        P                  R,          4       \        \        P                  ! \        V P                  4      4      pV P                  \        V4      ^4       . ROpV F.  pVP!                  VP"                  4       VP%                  4        K0  	  V P                  \        P                  R,          R4       R#   T P                  \        P                  R,          R4       i ; i)zm
Check that if the content of a plugin change, L{plugin.getPlugins} is
able to detect the new plugins added.
r   r   zplugin_extra2.pyr   TN)rv   r   FifthTestPlugin)r
   r:   r;   r<   r8   r7   r   r	   r   r   r?   rx   r   ra   r.   r1   r[   r   r   r   s   &   r   test_detectFilesChanged#PluginTests.test_detectFilesChanged   sG    	""#56==LL/0	
	S))+t{{CDDSY*X&&'9:AA""#34
 &&s{{3J'KL ))+t{{CDDSY*IEQZZ(	  &&s{{3J'KTRD&&s{{3J'KTRs   D6F' ')Gc                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   r(     s     ' ' 'r   c                (   \        \        4      P                  R4      P                  V P                  P                  R4      4        \        \        P                  ! \        V P                  4      4       V P                  \        P                  R,          R4       \        \        P                  ! \        V P                  4      4      pV P                  ^\        V4      4       R#   T P                  \        P                  R,          R4       i ; i)z[
Check that when a dropin file is removed, L{plugin.getPlugins} doesn't
return it anymore.
r   r   r   TN)r
   r:   r;   r<   r8   r7   r   r	   r   r   r?   ra   r.   r1   rx   r   )r@   r   s   & r   test_detectFilesRemoved#PluginTests.test_detectFilesRemoved   s     	""#56==LL/0	
	S"";<= &&s{{3J'KTRF%%k4;;?@CI& &&s{{3J'KTRs   .C( ()Dc                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   r(     s     . .4 .r   c                   V P                  4       pV P                  \        P                  P	                  V4      4       V P
                  P                  P                  V4        \        \        P                  ! \        V P
                  4      4      pV P                  \        V4      ^4       V P
                  P                  P                  V4       R#   T P
                  P                  P                  T4       i ; i)za
Test that getCache skips over any entries in a plugin package's
C{__path__} which do not exist.
N)r4   r   rZ   r/   existsr?   __path__appendr   r	   r   r   rx   r   r[   )r@   r/   r   s   &  r   test_nonexistentPathEntry%PluginTests.test_nonexistentPathEntry  s     {{}-.##D)	.))+t{{CDDSY*KK  ''-DKK  ''-s   %A	C 'C<c                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   r(   #  s     / /T /r   c                H   \        V P                  4       4      pV P                  VP                  4       4       VP	                  4        VP                  R4      P                  pV P                  P                  P                  V4        \        \        P                  ! \        V P                  4      4      pV P                  \        V4      ^4       V P                  P                  P!                  V4       R#   T P                  P                  P!                  T4       i ; i)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_packageN)r
   r4   r   r   touchr7   r/   r?   r   r   r   r	   r   r   rx   r   r[   )r@   r/   r7   r   s   &   r   test_nonDirectoryChildEntry'PluginTests.test_nonDirectoryChildEntry"  s     &'



>*//##E*	/))+t{{CDDSY*KK  ''.DKK  ''.s   
A	C: :'D!c                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   r(   3  s     / /4 /r   c                4   \         P                  ! V P                  4       V P                  P	                  R4      p\        \        4      P                  R4      P                  V P                  P	                  R4      4       \        4        \        P                  ! V P                  P                  R4       \        P                  ! VP                  R4       V P                  \        P                  V P                  P                  R4       V P                  \        P                  VP                  R4       . p\        VP                  4       V P                  \         VP                  4       \         P                  ! V P                  4      pV P#                  RV4       V P#                  V P$                  V4       RVP                  \&        P(                  3,          pV F  p\+        V4      pVf   Q hWF9   g   K   R	# 	  V P-                  R
V: 24       R	# )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   r   r   i@     i  r   3Unable to write to plugin cache %s: error number %dN9Did not observe unwriteable cache warning in log events: )r	   rw   r?   r8   r7   r
   r:   r;   r<   invalidateImportCachesrZ   chmodr/   
addCleanupr   r   r   ry   r=   errnoEPERMr   fail)r@   	cachepatheventsr   expectedevent	maybeTexts   &      r   test_deployedModePluginTests.test_deployedMode3  s    	$LL&&~6	 	""#56==LL/0	
 	 
""E*
'$,,"3"3U;)..%8 #%FMM"6,mU+d))51 INNKKL
 
 E)%0I((($	  II &)r   )r?   r0   r=   r8   r5   r3   N)F)r   r   r   r   r   rA   rK   ra   rf   rr   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r    ,   s    
 0. 4( "1 "1H
    S S: S S@ ' '" . . / / / /r   r    sj   
from twisted.plugin import pluginPackagePaths
__path__.extend(pluginPackagePaths(__name__))
__all__ = []
c                    V ^8  d   QhRRRR/# )r#   r   strr$   bytesr   )r&   s   "r   r'   r'   m  s      S U r   c                B    R P                  V 4      P                  R4      # )zfrom zope.interface import provider
from twisted.plugin import IPlugin
from twisted.test.test_plugin import ITestPlugin

@provider(IPlugin, ITestPlugin)
class {}:
    pass
ascii)r&   encoder   s   &r   pluginFileContentsr   m  s      
	r   c          
     ,    V ^8  d   QhRRRRRRRRR	R/# )
r#   	entrypathFilePath[str]pluginContentr   realrP   pluginModuler   r$   r   )r&   s   "r   r'   r'   }  s4      -2:>NQr   c                   V P                  4        V P                  R4      pVP                  4        V'       d!   VP                  R4      P                  R4       VP                  R4      pVP                  4        V'       d%   VP                  R4      P                  \        4       VP                  VR,           4      P                  V4       V# )z
Create a plugindummy package.
plugindummyr,   r   r{   .py)r6   r7   r9   pluginInitFile)r   r   r   r   pkgplugss   &&&&  r   _createPluginDummyr   }  s     
//-
(C		- ++C0IIi E	M"--n=	KKu$%00?Lr   c                  "    ] tR tRt$ R]R&   RtR# )_HasBoolLegacyKeyi  rP   legacyr   N)r   r   r   r   __annotations__r   r   r   r   r   r     s    Lr   r   c                      ] tR tRtRtR R ltR R ltR R ltR	 R
 ltR R lt	R R lt
R R ltR R ltR R ltR R ltRtR# )DeveloperSetupTestsi  z
These tests verify things about the plugin system without actually
interacting with the deployed 'twisted.plugins' package, instead creating a
temporary package.
c                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'    DeveloperSetupTests.__annotate__  s     (  ( t ( r   c                l   \         P                  R,          V n        \         P                  P	                  4       V n        \        V P                  4       4      V n        V P                  P                  4        V P                  P                  R4      V n        V P                  P                  R4      V n        V P                  P                  R4      V n        \        V P                  \        R4      RR4      V n        \        V P                  \        R4      RR4      V n        \        V P                  \        R	4      R
R4      V n        \         P                  P'                  V P                  V P                  3 Uu. uF  qP                  NK  	  up4       V P)                  4        V P                  P                  R4      P                  R4      V n        V P*                  P                  R4      V n        \.        P.                  ! 4       p\0        P2                  ! V P*                  P                  R4      P                  VR,
          3^,          4       \0        P2                  ! V P,                  P                  VR,
          3^,          4       V P5                  4        V P7                  4        R# u upi )a  
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.
r*   system_pathdevelopment_pathapplication_pathsystemTplugindummy_builtindevappFplugindummy_appr   r{   re   zplugindummy_builtin.pyi  i  N)r.   r/   	savedPathr1   r2   r3   r
   r4   fakeRootr6   r7   
systemPathdevPathappPathr   r   systemPackage
devPackage
appPackageextendgetAllPluginssysplugsyscachetimerZ   utime
lockSystemresetEnvironment)r@   xnows   &  r   rA   DeveloperSetupTests.setUp  s    !KK,,. /%%'----m<}}**+=>}}**+=>/OO/94AV
 -LL,U3T;P
 -LL,U3U<M

 	$//4<<)HI)HA)HIJ 	,,];AA)L**>: iik
##$<=BBS4ZMTUDUV
##cDj]Q%67 	 Js   =J1c                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   r     s     , ,D ,r   c                    \         P                  ! V P                  P                  R4       \         P                  ! V P                  P                  R4       R# )zG
Lock the system directories, as if they were unwritable by this user.
im  NrZ   r   r  r/   r	  rJ   s   &r   r  DeveloperSetupTests.lockSystem  4     	""E*
##U+r   c                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   r     s     , ,d ,r   c                    \         P                  ! V P                  P                  R4       \         P                  ! V P                  P                  R4       R# )zG
Unlock the system directories, as if they were writable by this user.
i  Nr  rJ   s   &r   unlockSystem DeveloperSetupTests.unlockSystem  r  r   c                   V ^8  d   QhRR/# )r#   r$   z	list[str]r   )r&   s   "r   r'   r     s     
- 
-y 
-r   c                    ^ RI p\        \        P                  ! \        VP
                  4      4      pV Uu. uF  q3P                  NK  	  up# u upi )zT
Get all the plugins loadable from our dummy package, and return their
short names.
N)plugindummy.pluginsr   r	   r   r   r{   r   )r@   r   r  plugs   &   r   r  !DeveloperSetupTests.getAllPlugins  s>     	#"";0C0CDE*+,!$!,,,s   Ac                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   r     s     Y Y$ Yr   c                    V P                  4        \        P                  P                  V P                  V P
                  V P                  3 Uu. uF  qP                  NK  	  up4       R# u upi )zK
Change the environment to what it should be just as the test is
starting.
N)unsetEnvironmentr.   r/   r  r  r   r  )r@   r  s   & r   r  $DeveloperSetupTests.resetEnvironment  sI    
 	$,,)VW)VA)VWXWs   A,c                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   r     s     % %$ %r   c                    \        4        \        P                  P                  4        \        P                  P	                  V P
                  4       V P                  \        P                  R&   R# )zP
Change the Python environment back to what it was before the test was
started.
r*   N)r   r.   r1   rH   rI   r3   r   r/   rJ   s   &r   r!  $DeveloperSetupTests.unsetEnvironment  sC    
 	 4,,-nnr   c                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   r     s      $ r   c                F    V P                  4        V P                  4        R# )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  rJ   s   &r   rK   DeveloperSetupTests.tearDown  s     	
 	r   c                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   r     s     4 4D 4r   c                    \        ^4       F7  pV P                  4       pVP                  4        V P                  VRR.4       K9  	  R# )z
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   N)ranger  sortrx   )r@   r  r   s   &  r   "test_developmentPluginAvailability6DeveloperSetupTests.test_developmentPluginAvailability  s=     qA&&(EJJLUUEN3 r   c                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   r     s     3 3d 3r   c                X   V P                   P                  R4      pVP                  \        R4      4       \        P                  ! 4       R,
          p\
        P                  ! VP                  W"34       VP                  R4      p\        RR7      p\        P                  ! V P                   P                  3R^/VB  \
        P                  ! VP                  W"34       VP                  4        V P                  4        V P                  RV P                  4       4       V P!                  RV P                  4       4       V P                  4        VP                  \        R4      4       V P!                  RV P                  4       4       V P                  RV P                  4       4       R	# )
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)r   quiettwoN)r  r7   r9   r   r
  rZ   r  r/   r;   r   
compileallcompile_dirr[   r  ry   r  r   )r@   mypathr  pycextras   &    r   test_freshPyReplacesStalePyc0DeveloperSetupTests.test_freshPyReplacesStalePyc  s1    &&z2,U34IIK$
qf%nn[) ".t33F1FF
A6"eT//12eT//12,U34eT//12eT//12r   c                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   r   ,  s     & &t &r   c                   V P                  4        V P                  P                  R4      P                  \	        R4      4       V P                  4        \        P                  P                  V P                  P                  4       . p\        VP                  4       V P                  \        VP                  4       V P                  RV P                  4       4       RV P                   P                  \"        P$                  3,          pV F  p\'        V4      pVf   Q hW$9   g   K   R# 	  V P)                  RV: 24       R# )a  
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.pyr1  r   Nr   )r  r  r7   r9   r   r  r.   r/   r[   r  r   r   r   r   ry   r  r	  r   r   r   r   )r@   r   r   r   r   s   &    r   test_newPluginsOnReadOnlyPath1DeveloperSetupTests.test_newPluginsOnReadOnlyPath,  s     	=)445G5NO 	))* #%FMM"6eT//12 IMMKKL
 
 E)%0I((($	  II &)r   )r  r  r  r  r   r3   r   r	  r  r  r   N)r   r   r   r   r   rA   r  r  r  r  r!  rK   r-  r9  r=  r   r   r   r   r   r     sA    ( T,,
-Y%43@& &r   r   c                  V    ] tR tRtRtR R ltR R ltR R ltR	 R
 ltR R lt	Rt
R# )AdjacentPackageTestsiU  z
Tests for the behavior of the plugin system when there are multiple
installed copies of the package containing the plugins being loaded.
c                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   !AdjacentPackageTests.__annotate__[  s     / /t /r   c                    \         P                  R,          V n        \         P                  P	                  4       V n        R# )zC
Save the elements of C{sys.path} and the items of C{sys.modules}.
r*   N)r.   r/   r0   r1   r2   r3   rJ   s   &r   rA   AdjacentPackageTests.setUp[  s)      HHQKKK,,.r   c                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   rB  b  rD   r   c                    V P                   \        P                  R&   \        P                  P	                  4        \        P                  P                  V P                  4       R# rF   rG   rJ   s   &r   rK   AdjacentPackageTests.tearDownb  rM   r   c               (    V ^8  d   QhRRRRRRRR/# )r#   r5   r   r   r   
pluginNamer$   r   )r&   s   "r   r'   rB  j  s,      !),:=	r   c                   VP                  V4      pVP                  R4      pVP                  4        VP                  R4      P                  R4       VP                  R4      pVP                  4        VP                  R4      P                  \        4       VP                  VR,           4      pVP                  \	        V4      4       V# )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   r{   r   )r7   makedirsr9   r   r   )r@   r5   r   rI  	directoryr8   r{   r   s   &&&&    r   createDummyPackage'AdjacentPackageTests.createDummyPackagej  s    , JJt$	//'*m$//4--	*m$//?}}Z%%78 24 89r   c                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   rB    s     C C Cr   c                   \        V P                  4       4      pVP                  4        V P                  VRR4      pV P                  VRR4      p\        P
                  P                  VP
                  4       \        P
                  P                  VP
                  4       ^ RIp\        \        P                  ! \        VP                  4      4      pT P                  R.V Uu. uF  qfP                  NK  	  up4       R# u upi )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secondNr
   r4   rL  rN  r.   r/   r   dummy.pluginsr   r	   r   r   r{   rx   r   r@   r5   firstDirectorysecondDirectoryrK  r{   r   s   &      r   .test_hiddenPackageSamePluginModuleNameObscuredCAdjacentPackageTests.test_hiddenPackageSamePluginModuleNameObscured       &00wM11$,O++,,,-v((emmDE'$AAZZ$AB$A   %D
c                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   rB    s     C CT Cr   c                   \        V P                  4       4      pVP                  4        V P                  VRR4      pV P                  VRR4      p\        P
                  P                  VP
                  4       \        P
                  P                  VP
                  4       ^ RIp\        \        P                  ! \        VP                  4      4      pT P                  R.V Uu. uF  qfP                  NK  	  up4       R# u upi )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.
rR  
thispluginrT  
thatpluginNrU  rW  s   &      r   3test_hiddenPackageDifferentPluginModuleNameObscuredHAdjacentPackageTests.test_hiddenPackageDifferentPluginModuleNameObscured  r\  r]  )r0   r3   N)r   r   r   r   r   rA   rK   rN  rZ  rb  r   r   r   r   r@  r@  U  s)    
/.BC(C Cr   r@  c                  J    ] tR tRtRtR R ltR R ltR R ltR	 R
 ltRt	R# )PackagePathTestsi  z[
Tests for L{plugin.pluginPackagePaths} which constructs search paths for
plugin packages.
c                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   PackagePathTests.__annotate__  s     ( (t (r   c                >    \         P                  R,          V n        R# )z#
Save the elements of C{sys.path}.
r*   N)r.   r/   r0   rJ   s   &r   rA   PackagePathTests.setUp  s      HHQKr   c                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   rg    s     ( ($ (r   c                @    V P                   \        P                  R&   R# )z,
Restore C{sys.path} to its original value.
r*   N)r0   r.   r/   rJ   s   &r   rK   PackagePathTests.tearDown  s     ''r   c                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   rg    s     
 
 
r   c                d   \        R4      p\        R4      pVP                  VP                  .\        n        V P                  \        P
                  ! R4      VP                  R4      P                  R4      P                  VP                  R4      P                  R4      P                  .4       R# )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.pluginsrK  r{   N)r
   r/   r.   rx   r	   pluginPackagePathsr7   )r@   ro  rp  s   &  r   test_pluginDirectories'PackagePathTests.test_pluginDirectories  s     uouoHHchh'%%o6		'"((388		'"((388	
r   c                   V ^8  d   QhRR/# r"   r   )r&   s   "r   r'   rg    s     
 
T 
r   c                0   \        V P                  4       4      pVP                  R4      P                  R4      P                  R4      pVP                  4        VP                  R4      P	                  R4       VP                  R4      P
                  VP                  R4      P
                  .\        n        V P                  \        P                  ! R4      VP                  R4      P                  R4      P                  R4      P
                  .4       R# )	aa  
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.
ro  rK  r{   r,   r   rp  rq  N)
r
   r4   r7   rL  r9   r/   r.   rx   r	   rr  )r@   r5   ro  s   &  r   test_pluginPackagesExcluded,PackagePathTests.test_pluginPackagesExcluded  s     &jj%%g.44Y?		- ++C0JJu%**DJJu,=,B,BC%%o6ZZ$$W-33I>CCD	
r   )r0   N)
r   r   r   r   r   rA   rK   rs  rw  r   r   r   r   re  re    s     
((
"
 
r   re  )+r   
__future__r   r4  r   rp   rZ   r.   r
  	importlibr   r   typesr   typingr   r   r   zope.interfacer   twistedr	   twisted.python.filepathr
   twisted.python.logr   r   r   r   twisted.trialr   r   r   r   TestCaser    r   r   r   r   r   r@  re  r   r   r   <module>r     s   
 #    	 
  A  / / $  , X X "T]) 9 v(## vt	 &	 ~(++ ~B\C8,, \C~4
x(( 4
r   