@@ -1731,17 +1731,21 @@ def iterdir(self):
17311731 raise FileNotFoundError (errno .ENOENT , "File not found" , path )
17321732
17331733 def mkdir (self , mode = 0o777 , parents = False , exist_ok = False ):
1734+ path = str (self .resolve ())
1735+ if path in self ._directories :
1736+ if exist_ok :
1737+ return
1738+ else :
1739+ raise FileExistsError (errno .EEXIST , "File exists" , path )
17341740 try :
1735- self ._directories [str (self .parent )].add (self .name )
1736- self ._directories [str (self )] = set ()
1741+ if self .name :
1742+ self ._directories [str (self .parent )].add (self .name )
1743+ self ._directories [path ] = set ()
17371744 except KeyError :
1738- if not parents or self . parent == self :
1745+ if not parents :
17391746 raise FileNotFoundError (errno .ENOENT , "File not found" , str (self .parent )) from None
17401747 self .parent .mkdir (parents = True , exist_ok = True )
17411748 self .mkdir (mode , parents = False , exist_ok = exist_ok )
1742- except FileExistsError :
1743- if not exist_ok :
1744- raise
17451749
17461750
17471751class DummyPathTest (unittest .TestCase ):
@@ -1771,33 +1775,37 @@ class DummyPathTest(unittest.TestCase):
17711775 #
17721776
17731777 def setUp (self ):
1774- # note: this must be kept in sync with `PathTest.setUp()`
1778+ pathmod = self .cls .pathmod
1779+ p = self .cls (BASE )
1780+ p .mkdir (parents = True )
1781+ p .joinpath ('dirA' ).mkdir ()
1782+ p .joinpath ('dirB' ).mkdir ()
1783+ p .joinpath ('dirC' ).mkdir ()
1784+ p .joinpath ('dirC' , 'dirD' ).mkdir ()
1785+ p .joinpath ('dirE' ).mkdir ()
1786+ with p .joinpath ('fileA' ).open ('wb' ) as f :
1787+ f .write (b"this is file A\n " )
1788+ with p .joinpath ('dirB' , 'fileB' ).open ('wb' ) as f :
1789+ f .write (b"this is file B\n " )
1790+ with p .joinpath ('dirC' , 'fileC' ).open ('wb' ) as f :
1791+ f .write (b"this is file C\n " )
1792+ with p .joinpath ('dirC' , 'novel.txt' ).open ('wb' ) as f :
1793+ f .write (b"this is a novel\n " )
1794+ with p .joinpath ('dirC' , 'dirD' , 'fileD' ).open ('wb' ) as f :
1795+ f .write (b"this is file D\n " )
1796+ if self .can_symlink :
1797+ p .joinpath ('linkA' ).symlink_to ('fileA' )
1798+ p .joinpath ('brokenLink' ).symlink_to ('non-existing' )
1799+ p .joinpath ('linkB' ).symlink_to ('dirB' )
1800+ p .joinpath ('dirA' , 'linkC' ).symlink_to (pathmod .join ('..' , 'dirB' ))
1801+ p .joinpath ('dirB' , 'linkD' ).symlink_to (pathmod .join ('..' , 'dirB' ))
1802+ p .joinpath ('brokenLinkLoop' ).symlink_to ('brokenLinkLoop' )
1803+
1804+ def tearDown (self ):
17751805 cls = self .cls
17761806 cls ._files .clear ()
17771807 cls ._directories .clear ()
17781808 cls ._symlinks .clear ()
1779- join = cls .pathmod .join
1780- cls ._files .update ({
1781- join (BASE , 'fileA' ): b'this is file A\n ' ,
1782- join (BASE , 'dirB' , 'fileB' ): b'this is file B\n ' ,
1783- join (BASE , 'dirC' , 'fileC' ): b'this is file C\n ' ,
1784- join (BASE , 'dirC' , 'dirD' , 'fileD' ): b'this is file D\n ' ,
1785- join (BASE , 'dirC' , 'novel.txt' ): b'this is a novel\n ' ,
1786- })
1787- cls ._directories .update ({
1788- BASE : {'dirA' , 'dirB' , 'dirC' , 'dirE' , 'fileA' },
1789- join (BASE , 'dirA' ): set (),
1790- join (BASE , 'dirB' ): {'fileB' },
1791- join (BASE , 'dirC' ): {'dirD' , 'fileC' , 'novel.txt' },
1792- join (BASE , 'dirC' , 'dirD' ): {'fileD' },
1793- join (BASE , 'dirE' ): {},
1794- })
1795- dirname = BASE
1796- while True :
1797- dirname , basename = cls .pathmod .split (dirname )
1798- if not basename :
1799- break
1800- cls ._directories [dirname ] = {basename }
18011809
18021810 def tempdir (self ):
18031811 path = self .cls (BASE ).with_name ('tmp-dirD' )
@@ -2626,22 +2634,6 @@ class DummyPathWithSymlinksTest(DummyPathTest):
26262634 cls = DummyPathWithSymlinks
26272635 can_symlink = True
26282636
2629- def setUp (self ):
2630- super ().setUp ()
2631- cls = self .cls
2632- join = cls .pathmod .join
2633- cls ._symlinks .update ({
2634- join (BASE , 'linkA' ): 'fileA' ,
2635- join (BASE , 'linkB' ): 'dirB' ,
2636- join (BASE , 'dirA' , 'linkC' ): join ('..' , 'dirB' ),
2637- join (BASE , 'dirB' , 'linkD' ): join ('..' , 'dirB' ),
2638- join (BASE , 'brokenLink' ): 'non-existing' ,
2639- join (BASE , 'brokenLinkLoop' ): 'brokenLinkLoop' ,
2640- })
2641- cls ._directories [BASE ].update ({'linkA' , 'linkB' , 'brokenLink' , 'brokenLinkLoop' })
2642- cls ._directories [join (BASE , 'dirA' )].add ('linkC' )
2643- cls ._directories [join (BASE , 'dirB' )].add ('linkD' )
2644-
26452637
26462638#
26472639# Tests for the concrete classes.
@@ -2653,38 +2645,12 @@ class PathTest(DummyPathTest):
26532645 can_symlink = os_helper .can_symlink ()
26542646
26552647 def setUp (self ):
2656- # note: this must be kept in sync with `DummyPathTest.setUp()`
2657- def cleanup ():
2658- os .chmod (join ('dirE' ), 0o777 )
2659- os_helper .rmtree (BASE )
2660- self .addCleanup (cleanup )
2661- os .mkdir (BASE )
2662- os .mkdir (join ('dirA' ))
2663- os .mkdir (join ('dirB' ))
2664- os .mkdir (join ('dirC' ))
2665- os .mkdir (join ('dirC' , 'dirD' ))
2666- os .mkdir (join ('dirE' ))
2667- with open (join ('fileA' ), 'wb' ) as f :
2668- f .write (b"this is file A\n " )
2669- with open (join ('dirB' , 'fileB' ), 'wb' ) as f :
2670- f .write (b"this is file B\n " )
2671- with open (join ('dirC' , 'fileC' ), 'wb' ) as f :
2672- f .write (b"this is file C\n " )
2673- with open (join ('dirC' , 'novel.txt' ), 'wb' ) as f :
2674- f .write (b"this is a novel\n " )
2675- with open (join ('dirC' , 'dirD' , 'fileD' ), 'wb' ) as f :
2676- f .write (b"this is file D\n " )
2648+ super ().setUp ()
26772649 os .chmod (join ('dirE' ), 0 )
2678- if self .can_symlink :
2679- # Relative symlinks.
2680- os .symlink ('fileA' , join ('linkA' ))
2681- os .symlink ('non-existing' , join ('brokenLink' ))
2682- os .symlink ('dirB' , join ('linkB' ), target_is_directory = True )
2683- os .symlink (os .path .join ('..' , 'dirB' ), join ('dirA' , 'linkC' ), target_is_directory = True )
2684- # This one goes upwards, creating a loop.
2685- os .symlink (os .path .join ('..' , 'dirB' ), join ('dirB' , 'linkD' ), target_is_directory = True )
2686- # Broken symlink (pointing to itself).
2687- os .symlink ('brokenLinkLoop' , join ('brokenLinkLoop' ))
2650+
2651+ def tearDown (self ):
2652+ os .chmod (join ('dirE' ), 0o777 )
2653+ os_helper .rmtree (BASE )
26882654
26892655 def tempdir (self ):
26902656 d = os_helper ._longpath (tempfile .mkdtemp (suffix = '-dirD' ,
0 commit comments