2020from test .support import infinite_recursion
2121from test .support import os_helper
2222from test .support .os_helper import TESTFN , FakePath
23- from test .test_pathlib import test_pathlib_abc
24- from test .test_pathlib .test_pathlib_abc import needs_posix , needs_windows
25-
2623try :
2724 import fcntl
2825except ImportError :
@@ -56,7 +53,20 @@ def new_test(self):
5653 return new_test
5754
5855
56+ _tests_needing_posix = set ()
57+ _tests_needing_windows = set ()
5958_tests_needing_symlinks = set ()
59+
60+ def needs_posix (fn ):
61+ """Decorator that marks a test as requiring a POSIX-flavoured path class."""
62+ _tests_needing_posix .add (fn .__name__ )
63+ return fn
64+
65+ def needs_windows (fn ):
66+ """Decorator that marks a test as requiring a Windows-flavoured path class."""
67+ _tests_needing_windows .add (fn .__name__ )
68+ return fn
69+
6070def needs_symlinks (fn ):
6171 """Decorator that marks a test as requiring a path class that supports symlinks."""
6272 _tests_needing_symlinks .add (fn .__name__ )
@@ -74,7 +84,7 @@ def test_is_notimplemented(self):
7484# Tests for the pure classes.
7585#
7686
77- class PurePathTest (test_pathlib_abc . JoinablePathTest ):
87+ class PurePathTest (unittest . TestCase ):
7888 cls = pathlib .PurePath
7989
8090 # Make sure any symbolic links in the base test path are resolved.
@@ -96,6 +106,72 @@ class PurePathTest(test_pathlib_abc.JoinablePathTest):
96106 ],
97107 }
98108
109+ def setUp (self ):
110+ name = self .id ().split ('.' )[- 1 ]
111+ if name in _tests_needing_posix and self .cls .parser is not posixpath :
112+ self .skipTest ('requires POSIX-flavoured path class' )
113+ if name in _tests_needing_windows and self .cls .parser is posixpath :
114+ self .skipTest ('requires Windows-flavoured path class' )
115+ p = self .cls ('a' )
116+ self .parser = p .parser
117+ self .sep = self .parser .sep
118+ self .altsep = self .parser .altsep
119+
120+ def _check_str_subclass (self , * args ):
121+ # Issue #21127: it should be possible to construct a PurePath object
122+ # from a str subclass instance, and it then gets converted to
123+ # a pure str object.
124+ class StrSubclass (str ):
125+ pass
126+ P = self .cls
127+ p = P (* (StrSubclass (x ) for x in args ))
128+ self .assertEqual (p , P (* args ))
129+ for part in p .parts :
130+ self .assertIs (type (part ), str )
131+
132+ def test_str_subclass_common (self ):
133+ self ._check_str_subclass ('' )
134+ self ._check_str_subclass ('.' )
135+ self ._check_str_subclass ('a' )
136+ self ._check_str_subclass ('a/b.txt' )
137+ self ._check_str_subclass ('/a/b.txt' )
138+
139+ @needs_windows
140+ def test_str_subclass_windows (self ):
141+ self ._check_str_subclass ('.\\ a:b' )
142+ self ._check_str_subclass ('c:' )
143+ self ._check_str_subclass ('c:a' )
144+ self ._check_str_subclass ('c:a\\ b.txt' )
145+ self ._check_str_subclass ('c:\\ ' )
146+ self ._check_str_subclass ('c:\\ a' )
147+ self ._check_str_subclass ('c:\\ a\\ b.txt' )
148+ self ._check_str_subclass ('\\ \\ some\\ share' )
149+ self ._check_str_subclass ('\\ \\ some\\ share\\ a' )
150+ self ._check_str_subclass ('\\ \\ some\\ share\\ a\\ b.txt' )
151+
152+ def _check_str (self , expected , args ):
153+ p = self .cls (* args )
154+ self .assertEqual (str (p ), expected .replace ('/' , self .sep ))
155+
156+ def test_str_common (self ):
157+ # Canonicalized paths roundtrip.
158+ for pathstr in ('a' , 'a/b' , 'a/b/c' , '/' , '/a/b' , '/a/b/c' ):
159+ self ._check_str (pathstr , (pathstr ,))
160+ # Other tests for str() are in test_equivalences().
161+
162+ @needs_windows
163+ def test_str_windows (self ):
164+ p = self .cls ('a/b/c' )
165+ self .assertEqual (str (p ), 'a\\ b\\ c' )
166+ p = self .cls ('c:/a/b/c' )
167+ self .assertEqual (str (p ), 'c:\\ a\\ b\\ c' )
168+ p = self .cls ('//a/b' )
169+ self .assertEqual (str (p ), '\\ \\ a\\ b\\ ' )
170+ p = self .cls ('//a/b/c' )
171+ self .assertEqual (str (p ), '\\ \\ a\\ b\\ c' )
172+ p = self .cls ('//a/b/c/d' )
173+ self .assertEqual (str (p ), '\\ \\ a\\ b\\ c\\ d' )
174+
99175 def test_concrete_class (self ):
100176 if self .cls is pathlib .PurePath :
101177 expected = pathlib .PureWindowsPath if os .name == 'nt' else pathlib .PurePosixPath
@@ -1032,7 +1108,7 @@ class cls(pathlib.PurePath):
10321108# Tests for the concrete classes.
10331109#
10341110
1035- class PathTest (test_pathlib_abc . RWPathTest , PurePathTest ):
1111+ class PathTest (PurePathTest ):
10361112 """Tests for the FS-accessing functionalities of the Path classes."""
10371113 cls = pathlib .Path
10381114 can_symlink = os_helper .can_symlink ()
@@ -1042,8 +1118,6 @@ def setUp(self):
10421118 if name in _tests_needing_symlinks and not self .can_symlink :
10431119 self .skipTest ('requires symlinks' )
10441120 super ().setUp ()
1045-
1046- def createTestHierarchy (self ):
10471121 os .mkdir (self .base )
10481122 os .mkdir (os .path .join (self .base , 'dirA' ))
10491123 os .mkdir (os .path .join (self .base , 'dirB' ))
@@ -1082,6 +1156,15 @@ def tearDown(self):
10821156 os .chmod (os .path .join (self .base , 'dirE' ), 0o777 )
10831157 os_helper .rmtree (self .base )
10841158
1159+ def assertFileNotFound (self , func , * args , ** kwargs ):
1160+ with self .assertRaises (FileNotFoundError ) as cm :
1161+ func (* args , ** kwargs )
1162+ self .assertEqual (cm .exception .errno , errno .ENOENT )
1163+
1164+ def assertEqualNormCase (self , path_a , path_b ):
1165+ normcase = self .parser .normcase
1166+ self .assertEqual (normcase (path_a ), normcase (path_b ))
1167+
10851168 def tempdir (self ):
10861169 d = os_helper ._longpath (tempfile .mkdtemp (suffix = '-dirD' ,
10871170 dir = os .getcwd ()))
@@ -2747,6 +2830,24 @@ def test_iterdir_symlink(self):
27472830 expected = { P (self .base , 'linkB' , q ) for q in ['fileB' , 'linkD' ] }
27482831 self .assertEqual (paths , expected )
27492832
2833+ @needs_posix
2834+ def test_glob_posix (self ):
2835+ P = self .cls
2836+ p = P (self .base )
2837+ q = p / "FILEa"
2838+ given = set (p .glob ("FILEa" ))
2839+ expect = {q } if q .info .exists () else set ()
2840+ self .assertEqual (given , expect )
2841+ self .assertEqual (set (p .glob ("FILEa*" )), set ())
2842+
2843+ @needs_windows
2844+ def test_glob_windows (self ):
2845+ P = self .cls
2846+ p = P (self .base )
2847+ self .assertEqual (set (p .glob ("FILEa" )), { P (self .base , "fileA" ) })
2848+ self .assertEqual (set (p .glob ("*a\\ " )), { P (self .base , "dirA/" ) })
2849+ self .assertEqual (set (p .glob ("F*a" )), { P (self .base , "fileA" ) })
2850+
27502851 def test_glob_empty_pattern (self ):
27512852 p = self .cls ('' )
27522853 with self .assertRaisesRegex (ValueError , 'Unacceptable pattern' ):
@@ -3335,7 +3436,7 @@ def test_group_windows(self):
33353436 P ('c:/' ).group ()
33363437
33373438
3338- class PathWalkTest (test_pathlib_abc . ReadablePathWalkTest ):
3439+ class PathWalkTest (unittest . TestCase ):
33393440 cls = pathlib .Path
33403441 base = PathTest .base
33413442 can_symlink = PathTest .can_symlink
@@ -3344,9 +3445,13 @@ def setUp(self):
33443445 name = self .id ().split ('.' )[- 1 ]
33453446 if name in _tests_needing_symlinks and not self .can_symlink :
33463447 self .skipTest ('requires symlinks' )
3347- super ().setUp ()
3448+ self .walk_path = self .cls (self .base , "TEST1" )
3449+ self .sub1_path = self .walk_path / "SUB1"
3450+ self .sub11_path = self .sub1_path / "SUB11"
3451+ self .sub2_path = self .walk_path / "SUB2"
3452+ self .link_path = self .sub2_path / "link"
3453+ self .sub2_tree = (self .sub2_path , [], ["tmp3" ])
33483454
3349- def createTestHierarchy (self ):
33503455 # Build:
33513456 # TESTFN/
33523457 # TEST1/ a file kid and two directory kids
0 commit comments