@@ -1501,19 +1501,20 @@ def iterdir(self):
15011501 raise FileNotFoundError (errno .ENOENT , "File not found" , path )
15021502
15031503 def mkdir (self , mode = 0o777 , parents = False , exist_ok = False ):
1504- path = str (self .resolve ())
1505- if path in self ._directories :
1504+ path = str (self .parent .resolve () / self .name )
1505+ parent = str (self .parent .resolve ())
1506+ if path in self ._directories or path in self ._symlinks :
15061507 if exist_ok :
15071508 return
15081509 else :
15091510 raise FileExistsError (errno .EEXIST , "File exists" , path )
15101511 try :
15111512 if self .name :
1512- self ._directories [str ( self . parent ) ].add (self .name )
1513+ self ._directories [parent ].add (self .name )
15131514 self ._directories [path ] = set ()
15141515 except KeyError :
15151516 if not parents :
1516- raise FileNotFoundError (errno .ENOENT , "File not found" , str ( self . parent ) ) from None
1517+ raise FileNotFoundError (errno .ENOENT , "File not found" , parent ) from None
15171518 self .parent .mkdir (parents = True , exist_ok = True )
15181519 self .mkdir (mode , parents = False , exist_ok = exist_ok )
15191520
@@ -1758,6 +1759,32 @@ def test_copy_symlink_follow_symlinks_false(self):
17581759 self .assertTrue (target .is_symlink ())
17591760 self .assertEqual (source .readlink (), target .readlink ())
17601761
1762+ @needs_symlinks
1763+ def test_copy_symlink_to_itself (self ):
1764+ base = self .cls (self .base )
1765+ source = base / 'linkA'
1766+ self .assertRaises (OSError , source .copy , source )
1767+
1768+ @needs_symlinks
1769+ def test_copy_symlink_to_existing_symlink (self ):
1770+ base = self .cls (self .base )
1771+ source = base / 'copySource'
1772+ target = base / 'copyTarget'
1773+ source .symlink_to (base / 'fileA' )
1774+ target .symlink_to (base / 'dirC' )
1775+ self .assertRaises (OSError , source .copy , target )
1776+ self .assertRaises (OSError , source .copy , target , follow_symlinks = False )
1777+
1778+ @needs_symlinks
1779+ def test_copy_symlink_to_existing_directory_symlink (self ):
1780+ base = self .cls (self .base )
1781+ source = base / 'copySource'
1782+ target = base / 'copyTarget'
1783+ source .symlink_to (base / 'fileA' )
1784+ target .symlink_to (base / 'dirC' )
1785+ self .assertRaises (OSError , source .copy , target )
1786+ self .assertRaises (OSError , source .copy , target , follow_symlinks = False )
1787+
17611788 @needs_symlinks
17621789 def test_copy_directory_symlink_follow_symlinks_false (self ):
17631790 base = self .cls (self .base )
@@ -1769,6 +1796,42 @@ def test_copy_directory_symlink_follow_symlinks_false(self):
17691796 self .assertTrue (target .is_symlink ())
17701797 self .assertEqual (source .readlink (), target .readlink ())
17711798
1799+ @needs_symlinks
1800+ def test_copy_directory_symlink_to_itself (self ):
1801+ base = self .cls (self .base )
1802+ source = base / 'linkB'
1803+ self .assertRaises (OSError , source .copy , source )
1804+ self .assertRaises (OSError , source .copy , source , follow_symlinks = False )
1805+
1806+ @needs_symlinks
1807+ def test_copy_directory_symlink_into_itself (self ):
1808+ base = self .cls (self .base )
1809+ source = base / 'linkB'
1810+ target = base / 'linkB' / 'copyB'
1811+ self .assertRaises (OSError , source .copy , target )
1812+ self .assertRaises (OSError , source .copy , target , follow_symlinks = False )
1813+ self .assertFalse (target .exists ())
1814+
1815+ @needs_symlinks
1816+ def test_copy_directory_symlink_to_existing_symlink (self ):
1817+ base = self .cls (self .base )
1818+ source = base / 'copySource'
1819+ target = base / 'copyTarget'
1820+ source .symlink_to (base / 'dirC' )
1821+ target .symlink_to (base / 'fileA' )
1822+ self .assertRaises (FileExistsError , source .copy , target )
1823+ self .assertRaises (FileExistsError , source .copy , target , follow_symlinks = False )
1824+
1825+ @needs_symlinks
1826+ def test_copy_directory_symlink_to_existing_directory_symlink (self ):
1827+ base = self .cls (self .base )
1828+ source = base / 'copySource'
1829+ target = base / 'copyTarget'
1830+ source .symlink_to (base / 'dirC' / 'dirD' )
1831+ target .symlink_to (base / 'dirC' )
1832+ self .assertRaises (FileExistsError , source .copy , target )
1833+ self .assertRaises (FileExistsError , source .copy , target , follow_symlinks = False )
1834+
17721835 def test_copy_file_to_existing_file (self ):
17731836 base = self .cls (self .base )
17741837 source = base / 'fileA'
@@ -1782,8 +1845,7 @@ def test_copy_file_to_existing_directory(self):
17821845 base = self .cls (self .base )
17831846 source = base / 'fileA'
17841847 target = base / 'dirA'
1785- with self .assertRaises (OSError ):
1786- source .copy (target )
1848+ self .assertRaises (OSError , source .copy , target )
17871849
17881850 @needs_symlinks
17891851 def test_copy_file_to_existing_symlink (self ):
@@ -1823,6 +1885,13 @@ def test_copy_file_empty(self):
18231885 self .assertTrue (target .exists ())
18241886 self .assertEqual (target .read_bytes (), b'' )
18251887
1888+ def test_copy_file_to_itself (self ):
1889+ base = self .cls (self .base )
1890+ source = base / 'empty'
1891+ source .write_bytes (b'' )
1892+ self .assertRaises (OSError , source .copy , source )
1893+ self .assertRaises (OSError , source .copy , source , follow_symlinks = False )
1894+
18261895 def test_copy_dir_simple (self ):
18271896 base = self .cls (self .base )
18281897 source = base / 'dirC'
@@ -1909,6 +1978,28 @@ def test_copy_dir_to_existing_directory_dirs_exist_ok(self):
19091978 self .assertTrue (target .joinpath ('fileC' ).read_text (),
19101979 "this is file C\n " )
19111980
1981+ def test_copy_dir_to_itself (self ):
1982+ base = self .cls (self .base )
1983+ source = base / 'dirC'
1984+ self .assertRaises (OSError , source .copy , source )
1985+ self .assertRaises (OSError , source .copy , source , follow_symlinks = False )
1986+
1987+ def test_copy_dir_to_itself_on_error (self ):
1988+ base = self .cls (self .base )
1989+ source = base / 'dirC'
1990+ errors = []
1991+ source .copy (source , on_error = errors .append )
1992+ self .assertEqual (len (errors ), 1 )
1993+ self .assertIsInstance (errors [0 ], OSError )
1994+
1995+ def test_copy_dir_into_itself (self ):
1996+ base = self .cls (self .base )
1997+ source = base / 'dirC'
1998+ target = base / 'dirC' / 'dirD' / 'copyC'
1999+ self .assertRaises (OSError , source .copy , target )
2000+ self .assertRaises (OSError , source .copy , target , follow_symlinks = False )
2001+ self .assertFalse (target .exists ())
2002+
19122003 def test_copy_missing_on_error (self ):
19132004 base = self .cls (self .base )
19142005 source = base / 'foo'
@@ -2876,8 +2967,12 @@ def readlink(self):
28762967 raise FileNotFoundError (errno .ENOENT , "File not found" , path )
28772968
28782969 def symlink_to (self , target , target_is_directory = False ):
2879- self ._directories [str (self .parent )].add (self .name )
2880- self ._symlinks [str (self )] = str (target )
2970+ path = str (self .parent .resolve () / self .name )
2971+ parent = str (self .parent .resolve ())
2972+ if path in self ._symlinks :
2973+ raise FileExistsError (errno .EEXIST , "File exists" , path )
2974+ self ._directories [parent ].add (self .name )
2975+ self ._symlinks [path ] = str (target )
28812976
28822977
28832978class DummyPathWithSymlinksTest (DummyPathTest ):
0 commit comments