
    h1>                        S r SSKJr  SSKrSSKrSSKJrJr  SSKJ	r	  SSK
Jr  SSKJr  SSKJr  SS	KJr  S
rSr\R(                  " 5       (       a  \" S5      c  \" S5      c  SrSr " S S\5      r " S S\5      rg)z'
Tests for L{twisted.python.lockfile}.
    )annotationsN)skipIf
skipUnless)NoReturn)lockfile)requireModule)platform)TestCaseF zwin32api.OpenProcess
pywintypesTzZOn windows, lockfile.kill is not implemented in the absence of win32api and/or pywintypes.c                      \ rS rSrSrSS jr\" \R                  " 5       S5      SS j5       r	SS jr
\" \R                  " 5       S5      SS j5       r\" \\5      SS	 j5       r\" \\5      SS
 j5       rSS jrSrg)	UtilTests#   zE
Tests for the helper functions used to implement L{FilesystemLock}.
c                    U R                  5       n[        R                  " SU5        U R                  [        [        R                  SU5      nU R                  UR                  [        R                  5        g)z
L{lockfile.symlink} raises L{OSError} with C{errno} set to L{EEXIST}
when an attempt is made to create a symlink which already exists.
fooN)mktempr   symlinkassertRaisesOSErrorassertEqualerrnoEEXISTselfnameexcs      a/root/1688_scrapy/alibaba-scraper/venv/lib/python3.13/site-packages/twisted/test/test_lockfile.pytest_symlinkEEXISTUtilTests.test_symlinkEEXIST(   sS    
 {{}%)9)95$GELL1    Bspecial rename EIO handling only necessary and correct on Windows.c                    U R                  5       nSS jnU R                  [        SU5        U R                  [        [        R
                  US5      nU R                  UR                  [        R                  5        g)a  
L{lockfile.symlink} raises L{OSError} with C{errno} set to L{EIO} when
the underlying L{rename} call fails with L{EIO}.

Renaming a file on Windows may fail if the target of the rename is in
the process of being deleted (directory deletion appears not to be
atomic).
c                6    [        [        R                  S 5      eNr   r   EIOsrcdsts     r   
fakeRename4UtilTests.test_symlinkEIOWindows.<locals>.fakeRenameA   s    %))T**r    renamer   Nr(   strr)   r.   returnr   )	r   patchr   r   IOErrorr   r   r   r&   )r   r   r*   r   s       r   test_symlinkEIOWindows UtilTests.test_symlinkEIOWindows2   sZ     {{}	+ 	

8Xz2)9)94GEII.r    c                    U R                  5       nU R                  [        [        R                  U5      nU R                  UR                  [        R                  5        g)z
L{lockfile.readlink} raises L{OSError} with C{errno} set to L{ENOENT}
when an attempt is made to read a symlink which does not exist.
N)r   r   r   r   readlinkr   r   ENOENTr   s      r   test_readlinkENOENTUtilTests.test_readlinkENOENTH   sA    
 {{}):):DAELL1r    Gspecial readlink EACCES handling only necessary and correct on Windows.c                    U R                  5       nSS jnU R                  [        SU5        U R                  [        [        R
                  U5      nU R                  UR                  [        R                  5        g)a,  
L{lockfile.readlink} raises L{OSError} with C{errno} set to L{EACCES}
on Windows when the underlying file open attempt fails with C{EACCES}.

Opening a file on Windows may fail if the path is inside a directory
which is in the process of being deleted (directory deletion appears
not to be atomic).
c                6    [        [        R                  S 5      er$   r   r   EACCES)pathmodes     r   fakeOpen6UtilTests.test_readlinkEACCESWindows.<locals>.fakeOpen`       %,,--r    _openN)r>   r.   r?   r.   r/   r   )	r   r0   r   r   r1   r5   r   r   r=   )r   r   r@   r   s       r   test_readlinkEACCESWindows$UtilTests.test_readlinkEACCESWindowsQ   sX     {{}	. 	

8Wh/):):DAELL1r    c                X    [         R                  " [        R                  " 5       S5        g)ze
L{lockfile.kill} returns without error if passed the PID of a
process which exists and signal C{0}.
r   N)r   killosgetpidr   s    r   	test_killUtilTests.test_killg   s     	biik1%r    c                    U R                  [        [        R                  SS5      nU R	                  UR
                  [
        R                  5        g)zu
L{lockfile.kill} raises L{OSError} with errno of L{ESRCH} if
passed a PID which does not correspond to any process.
ir   N)r   r   r   rG   r   r   ESRCH)r   r   s     r   test_killESRCHUtilTests.test_killESRCHo   s6     	1EEKK0r    c                    U R                  [        SS5        [        R                  " U R                  5       5      nUR	                  5         U R                  UR	                  5       5        g)z
Verify that when L{lockfile.kill} does end up as None (e.g. on Windows
without pywin32), it doesn't end up being called and raising a
L{TypeError}.
rG   N)r0   r   FilesystemLockr   lockassertFalse)r   fls     r   test_noKillCallUtilTests.test_noKillCally   sG     	

8VT*$$T[[]3
	#r     Nr/   None)__name__
__module____qualname____firstlineno____doc__r   r   r	   	isWindowsr2   r7   rD   r   skipKillskipKillReasonrK   rO   rV   __static_attributes__rX   r    r   r   r   #   s    2 O/	/$2 T2	2$ Hn%& && Hn%1 &1	$r    r   c                     \ rS rSrSS jrSS jr\" \R                  " 5       S5      SS j5       r	SS jr
SS jrSS jrSS	 jrSS
 jr\" \R                  " 5       S5      SS j5       r\" \R                  " 5       S5      SS j5       r      SS jrSS jr\" \R                  " 5       S5      SS j5       rSS jrSS jrSS jrSS jrSS jrSrg)LockingTests   c                  ^ SU4S jjnU R                  [        SU5        U R                  5       n[        R                  " U5      nU R	                  [
        UR                  5      nU R                  UR                  T5        g )Nc                   > [        TS 5      er$   )r   )sourcedestr   s     r   fakeSymlink3LockingTests._symlinkErrorTest.<locals>.fakeSymlink   s    %&&r    r   )ri   r.   rj   r.   r/   r   )	r0   r   r   rR   r   r   rS   r   r   )r   r   rk   lockfrS   r   s    `    r   _symlinkErrorTestLockingTests._symlinkErrorTest   s_    	' 	

8Y4&&u-3E*r    c                B    U R                  [        R                  5        g)zn
An exception raised by C{symlink} other than C{EEXIST} is passed up to
the caller of L{FilesystemLock.lock}.
N)rn   r   ENOSYSrJ   s    r   test_symlinkErrorLockingTests.test_symlinkError   s    
 	u||,r    z9POSIX-specific error propagation not expected on Windows.c                    U R                  [        R                  5        U R                  [        R                  5        g)z
An L{OSError} raised by C{symlink} on a POSIX platform with an errno of
C{EACCES} or C{EIO} is passed to the caller of L{FilesystemLock.lock}.

On POSIX, unlike on Windows, these are unexpected errors which cannot
be handled by L{FilesystemLock}.
N)rn   r   r=   r&   rJ   s    r   test_symlinkErrorPOSIX#LockingTests.test_symlinkErrorPOSIX   s(     	u||,uyy)r    c                    U R                  5       n[        R                  " U5      nU R                  UR	                  5       5        U R                  UR
                  5        U R                  UR                  5        g)zs
If the lock has never been held, it can be acquired and the C{clean}
and C{locked} attributes are set to C{True}.
N)r   r   rR   
assertTruerS   cleanlockedr   rm   rS   s      r   test_cleanlyAcquire LockingTests.test_cleanlyAcquire   sQ    
 &&u-		$

#$r    c                   U R                  5       n[        R                  " U5      nU R                  UR	                  5       5        UR                  5         U R                  UR                  5        [        R                  " U5      nU R                  UR	                  5       5        U R                  UR                  5        U R                  UR                  5        g)zt
If a lock is released cleanly, it can be re-acquired and the C{clean}
and C{locked} attributes are set to C{True}.
N)	r   r   rR   rx   rS   unlockrT   rz   ry   r{   s      r   test_cleanlyRelease LockingTests.test_cleanlyRelease   s    
 &&u-		$%&&u-		$

#$r    c                .   U R                  5       n[        R                  " U5      nU R                  UR	                  5       5        [        R                  " U5      nU R                  UR	                  5       5        U R                  UR                  5        g)z;
If a lock is currently locked, it cannot be locked again.
N)r   r   rR   rx   rS   rT   rz   )r   rm   	firstLock
secondLocks       r   test_cannotLockLocked"LockingTests.test_cannotLockLocked   sk     ++E2		(),,U3
*+**+r    c                  ^ SmSU4S jjnU R                  5       nU R                  [        SU5        [        R                  " [	        T5      U5        [        R
                  " U5      nU R                  UR                  5       5        U R                  UR                  5        U R                  UR                  5        U R                  [        R                  " U5      [	        [        R                  " 5       5      5        g)z
If a lock was held by a process which no longer exists, it can be
acquired, the C{clean} attribute is set to C{False}, and the
C{locked} attribute is set to C{True}.
i90  c                   > US:w  a  [        [        R                  S 5      eU T:X  a  [        [        R                  S 5      eg )Nr   r   r   EPERMrN   )pidsignalowners     r   fakeKill4LockingTests.test_uncleanlyAcquire.<locals>.fakeKill   s8    {ekk400e|ekk400 r    rG   Nr   intr   r   r/   rZ   )r   r0   r   r   r.   rR   rx   rS   rT   ry   rz   r   r5   rH   rI   )r   r   rm   rS   r   s       @r   test_uncleanlyAcquire"LockingTests.test_uncleanlyAcquire   s     	1 

8VX.UU+&&u-		$$$**513ryy{3CDr    c                  ^^ SUU4S jjnU R                  [        SU5      mSS jnU R                  [        SU5        U R                  5       m[        R                  " T5      n[        R                  " [        S5      T5        U R                  UR                  5       5        U R                  UR                  5        U R                  UR                  5        g)	z
If the lock is initially held but then released before it can be
examined to determine if the process which held it still exists, it is
acquired and the C{clean} and C{locked} attributes are set to C{True}.
c                |   > [         R                  " T5        TR                  5         [         R                  " U 5      $ r$   )r   rmlinkrestorer5   )r   rm   readlinkPatchs    r   fakeReadlink?LockingTests.test_lockReleasedBeforeCheck.<locals>.fakeReadlink   s,    OOE"!!#$$T**r    r5   c                    US:w  a  [        [        R                  S 5      eU S:X  a  [        [        R                  S 5      eg Nr   u  r   r   r   s     r   r   ;LockingTests.test_lockReleasedBeforeCheck.<locals>.fakeKill   7    {ekk400e|ekk400 r    rG   r   N)r   r.   r/   r.   r   
r0   r   r   rR   r   r.   rx   rS   ry   rz   )r   r   r   rS   rm   r   s       @@r   test_lockReleasedBeforeCheck)LockingTests.test_lockReleasedBeforeCheck   s    	+ 	+ 

8ZF	1 	

8VX.&&u-UU+		$

#$r    r!   c                    SS jnU R                  [        SU5        U R                  5       n[        R                  " U5      nU R	                  UR                  5       5        U R	                  UR                  5        g)a[  
If the lock is released while an attempt is made to acquire
it, the lock attempt fails and C{FilesystemLock.lock} returns
C{False}.  This can happen on Windows when L{lockfile.symlink}
fails with L{IOError} of C{EIO} because another process is in
the middle of a call to L{os.rmdir} (implemented in terms of
RemoveDirectory) which is not atomic.
c                6    [        [        R                  S 5      er$   r%   r'   s     r   rk   GLockingTests.test_lockReleasedDuringAcquireSymlink.<locals>.fakeSymlink  s     %))T**r    r   Nr-   )r0   r   r   rR   rT   rS   rz   )r   rk   rm   rS   s       r   %test_lockReleasedDuringAcquireSymlink2LockingTests.test_lockReleasedDuringAcquireSymlink  sZ    	+
 	

8Y4&&u-%%r    r9   c                <   SS jnU R                  [        SU5        U R                  5       n[        R                  " U5      n[        R                  " [        S5      U5        U R                  UR                  5       5        U R                  UR                  5        g)z
If the lock is initially held but is released while an attempt
is made to acquire it, the lock attempt fails and
L{FilesystemLock.lock} returns C{False}.
c                6    [        [        R                  S 5      er$   r<   r   s    r   r   ILockingTests.test_lockReleasedDuringAcquireReadlink.<locals>.fakeReadlink+  s     %,,--r    r5   r   Nr   r.   r/   r   )	r0   r   r   rR   r   r.   rT   rS   rz   )r   r   rm   rS   s       r   &test_lockReleasedDuringAcquireReadlink3LockingTests.test_lockReleasedDuringAcquireReadlink   sn    	. 	

8Z6&&u-UU+%%r    c                z  ^^ SUU4S jjnU R                  [        SU5        U R                  5       n[        R                  " [	        S5      U5        [        R
                  " U5      nU R                  TUR                  5      nU R                  UR                  T5        U R                  UR                  5        g )Nc                   > T" TS 5      er$   rX   )r   r   exceptionTypes    r   r   5LockingTests._readlinkErrorTest.<locals>.fakeReadlink<  s    t,,r    r5   r   r   )r0   r   r   r   r.   rR   r   rS   r   r   rT   rz   )r   r   r   r   rm   rS   r   s    ``    r   _readlinkErrorTestLockingTests._readlinkErrorTest9  s    	- 	- 	

8Z6 	UU+&&u-tyy9E*%r    c                    U R                  [        [        R                  5        U R                  [        [        R                  5        g)zo
An exception raised by C{readlink} other than C{ENOENT} is passed up to
the caller of L{FilesystemLock.lock}.
N)r   r   r   rq   r1   rJ   s    r   test_readlinkErrorLockingTests.test_readlinkErrorK  s,    
 	66r    c                    U R                  [        [        R                  5        U R                  [        [        R                  5        g)z
Any L{IOError} raised by C{readlink} on a POSIX platform passed to the
caller of L{FilesystemLock.lock}.

On POSIX, unlike on Windows, these are unexpected errors which cannot
be handled by L{FilesystemLock}.
N)r   r1   r   rq   r=   rJ   s    r   test_readlinkErrorPOSIX$LockingTests.test_readlinkErrorPOSIXS  s,     	66r    c                  ^^ SUU4S jjnU R                  [        SU5      mSS jnU R                  [        SU5        U R                  5       m[        R                  " T5      n[        R                  " [        S5      T5        U R                  UR                  5       5        U R                  UR                  5        U R                  UR                  5        g)	z
If a second process cleans up the lock after a first one checks the
lock and finds that no process is holding it, the first process does
not fail when it tries to clean up the lock.
c                |   > TR                  5         [        R                  " T5        [        R                  " U 5      $ r$   )r   r   r   )r   rm   rmlinkPatchs    r   
fakeRmlink?LockingTests.test_lockCleanedUpConcurrently.<locals>.fakeRmlinki  s*    !OOE"??4((r    r   c                    US:w  a  [        [        R                  S 5      eU S:X  a  [        [        R                  S 5      eg r   r   r   s     r   r   =LockingTests.test_lockCleanedUpConcurrently.<locals>.fakeKillr  r   r    rG   r   N)r   r.   r/   rZ   r   r   )r   r   r   rS   rm   r   s       @@r   test_lockCleanedUpConcurrently+LockingTests.test_lockCleanedUpConcurrentlyb  s    	) 	) jj8Z@	1 	

8VX.&&u-UU+		$

#$r    c                   SS jnU R                  [        SU5        SS jnU R                  [        SU5        U R                  5       n[        R                  " [	        S5      U5        [        R
                  " U5      nU R                  [        UR                  5      nU R                  UR                  [        R                  5        U R                  UR                  5        g)	zm
An exception raised by L{rmlink} other than C{ENOENT} is passed up
to the caller of L{FilesystemLock.lock}.
c                6    [        [        R                  S 5      er$   )r   r   rq   r   s    r   r   1LockingTests.test_rmlinkError.<locals>.fakeRmlink  rB   r    r   c                    US:w  a  [        [        R                  S 5      eU S:X  a  [        [        R                  S 5      eg r   r   r   s     r   r   /LockingTests.test_rmlinkError.<locals>.fakeKill  r   r    rG   r   Nr   r   )r0   r   r   r   r.   rR   r   r   rS   r   r   rq   rT   rz   )r   r   r   rm   rS   r   s         r   test_rmlinkErrorLockingTests.test_rmlinkError  s    	. 	

8Xz2	1 	

8VX. 	UU+&&u-3ELL1%r    c                   SS jnU R                  [        SU5        U R                  5       n[        R                  " [	        S5      U5        [        R
                  " U5      nU R                  [        UR                  5      nU R                  UR                  [        R                  5        U R                  UR                  5        g)z
If L{kill} raises an exception other than L{OSError} with errno set to
C{ESRCH}, the exception is passed up to the caller of
L{FilesystemLock.lock}.
c                6    [        [        R                  S 5      er$   )r   r   r   r   s     r   r   -LockingTests.test_killError.<locals>.fakeKill  s    %++t,,r    rG   r   N)r   r   r   r   r/   r   )r0   r   r   r   r.   rR   r   r   rS   r   r   r   rT   rz   )r   r   rm   rS   r   s        r   test_killErrorLockingTests.test_killError  s    	- 	

8VX. 	UU+&&u-3EKK0%r    c                    U R                  5       n[        R                  " [        [        R
                  " 5       S-   5      U5        [        R                  " U5      nU R                  [        UR                  5        g)zj
L{FilesystemLock.unlock} raises L{ValueError} if called for a lock
which is held by a different process.
   N)
r   r   r   r.   rH   rI   rR   r   
ValueErrorr   r{   s      r   test_unlockOtherLockingTests.test_unlockOther  sR    
 RYY[1_-u5&&u-*dkk2r    c                   U R                  5       nU R                  [        R                  " U5      5        [        R                  " U5      nU R                  UR                  5       5        U R                  [        R                  " U5      5        UR                  5         U R                  [        R                  " U5      5        g)zX
L{isLocked} returns C{True} if the named lock is currently locked,
C{False} otherwise.
N)r   rT   r   isLockedrR   rx   rS   r   r{   s      r   test_isLockedLockingTests.test_isLocked  s    
 **512&&u-		$))%01**512r    rX   N)r   r   r/   rZ   rY   )r   ztype[OSError] | type[IOError]r   r   r/   rZ   )r[   r\   r]   r^   rn   rr   r   r	   r`   ru   r|   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rc   rX   r    r   re   re      s   	+- C	*		*	%% 
,E2%> O&	&, T&	&*&:&CF&	&$7 C	7		7%>&:&,33r    re   )r_   
__future__r   r   rH   unittestr   r   typing_extensionsr   twisted.pythonr   twisted.python.reflectr   twisted.python.runtimer	   twisted.trial.unittestr
   ra   rb   r`   r   re   rX   r    r   <module>r      s   
 #  	 ' & # 0 + +,-5,'/< 	_$ _$DD38 D3r    