@@ -1501,19 +1501,20 @@ def iterdir(self):
1501
1501
raise FileNotFoundError (errno .ENOENT , "File not found" , path )
1502
1502
1503
1503
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 :
1506
1507
if exist_ok :
1507
1508
return
1508
1509
else :
1509
1510
raise FileExistsError (errno .EEXIST , "File exists" , path )
1510
1511
try :
1511
1512
if self .name :
1512
- self ._directories [str ( self . parent ) ].add (self .name )
1513
+ self ._directories [parent ].add (self .name )
1513
1514
self ._directories [path ] = set ()
1514
1515
except KeyError :
1515
1516
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
1517
1518
self .parent .mkdir (parents = True , exist_ok = True )
1518
1519
self .mkdir (mode , parents = False , exist_ok = exist_ok )
1519
1520
@@ -1758,6 +1759,32 @@ def test_copy_symlink_follow_symlinks_false(self):
1758
1759
self .assertTrue (target .is_symlink ())
1759
1760
self .assertEqual (source .readlink (), target .readlink ())
1760
1761
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
+
1761
1788
@needs_symlinks
1762
1789
def test_copy_directory_symlink_follow_symlinks_false (self ):
1763
1790
base = self .cls (self .base )
@@ -1769,6 +1796,42 @@ def test_copy_directory_symlink_follow_symlinks_false(self):
1769
1796
self .assertTrue (target .is_symlink ())
1770
1797
self .assertEqual (source .readlink (), target .readlink ())
1771
1798
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
+
1772
1835
def test_copy_file_to_existing_file (self ):
1773
1836
base = self .cls (self .base )
1774
1837
source = base / 'fileA'
@@ -1782,8 +1845,7 @@ def test_copy_file_to_existing_directory(self):
1782
1845
base = self .cls (self .base )
1783
1846
source = base / 'fileA'
1784
1847
target = base / 'dirA'
1785
- with self .assertRaises (OSError ):
1786
- source .copy (target )
1848
+ self .assertRaises (OSError , source .copy , target )
1787
1849
1788
1850
@needs_symlinks
1789
1851
def test_copy_file_to_existing_symlink (self ):
@@ -1823,6 +1885,13 @@ def test_copy_file_empty(self):
1823
1885
self .assertTrue (target .exists ())
1824
1886
self .assertEqual (target .read_bytes (), b'' )
1825
1887
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
+
1826
1895
def test_copy_dir_simple (self ):
1827
1896
base = self .cls (self .base )
1828
1897
source = base / 'dirC'
@@ -1909,6 +1978,28 @@ def test_copy_dir_to_existing_directory_dirs_exist_ok(self):
1909
1978
self .assertTrue (target .joinpath ('fileC' ).read_text (),
1910
1979
"this is file C\n " )
1911
1980
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
+
1912
2003
def test_copy_missing_on_error (self ):
1913
2004
base = self .cls (self .base )
1914
2005
source = base / 'foo'
@@ -2876,8 +2967,12 @@ def readlink(self):
2876
2967
raise FileNotFoundError (errno .ENOENT , "File not found" , path )
2877
2968
2878
2969
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 )
2881
2976
2882
2977
2883
2978
class DummyPathWithSymlinksTest (DummyPathTest ):
0 commit comments