mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	GH-130614: pathlib ABCs: revise test suite for Windows path joining (#131016)
Test Windows-flavoured `pathlib.types._JoinablePath` in a dedicated test module. These tests cover `LexicalWindowsPath`, `PureWindowsPath` and `WindowsPath`, where `LexicalWindowsPath` is a simple implementation of `_JoinablePath` for use in tests.
This commit is contained in:
		
							parent
							
								
									e0bc9d2a0c
								
							
						
					
					
						commit
						3569e4a670
					
				
					 4 changed files with 320 additions and 279 deletions
				
			
		|  | @ -2,6 +2,7 @@ | ||||||
| Simple implementation of JoinablePath, for use in pathlib tests. | Simple implementation of JoinablePath, for use in pathlib tests. | ||||||
| """ | """ | ||||||
| 
 | 
 | ||||||
|  | import ntpath | ||||||
| import os.path | import os.path | ||||||
| import pathlib.types | import pathlib.types | ||||||
| import posixpath | import posixpath | ||||||
|  | @ -37,3 +38,8 @@ def with_segments(self, *pathsegments): | ||||||
| class LexicalPosixPath(LexicalPath): | class LexicalPosixPath(LexicalPath): | ||||||
|     __slots__ = () |     __slots__ = () | ||||||
|     parser = posixpath |     parser = posixpath | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class LexicalWindowsPath(LexicalPath): | ||||||
|  |     __slots__ = () | ||||||
|  |     parser = ntpath | ||||||
|  |  | ||||||
							
								
								
									
										290
									
								
								Lib/test/test_pathlib/test_join_windows.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										290
									
								
								Lib/test/test_pathlib/test_join_windows.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,290 @@ | ||||||
|  | """ | ||||||
|  | Tests for Windows-flavoured pathlib.types._JoinablePath | ||||||
|  | """ | ||||||
|  | 
 | ||||||
|  | import os | ||||||
|  | import unittest | ||||||
|  | 
 | ||||||
|  | from pathlib import PureWindowsPath, WindowsPath | ||||||
|  | from test.test_pathlib.support.lexical_path import LexicalWindowsPath | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class JoinTestBase: | ||||||
|  |     def test_join(self): | ||||||
|  |         P = self.cls | ||||||
|  |         p = P('C:/a/b') | ||||||
|  |         pp = p.joinpath('x/y') | ||||||
|  |         self.assertEqual(pp, P(r'C:/a/b\x/y')) | ||||||
|  |         pp = p.joinpath('/x/y') | ||||||
|  |         self.assertEqual(pp, P('C:/x/y')) | ||||||
|  |         # Joining with a different drive => the first path is ignored, even | ||||||
|  |         # if the second path is relative. | ||||||
|  |         pp = p.joinpath('D:x/y') | ||||||
|  |         self.assertEqual(pp, P('D:x/y')) | ||||||
|  |         pp = p.joinpath('D:/x/y') | ||||||
|  |         self.assertEqual(pp, P('D:/x/y')) | ||||||
|  |         pp = p.joinpath('//host/share/x/y') | ||||||
|  |         self.assertEqual(pp, P('//host/share/x/y')) | ||||||
|  |         # Joining with the same drive => the first path is appended to if | ||||||
|  |         # the second path is relative. | ||||||
|  |         pp = p.joinpath('c:x/y') | ||||||
|  |         self.assertEqual(pp, P(r'c:/a/b\x/y')) | ||||||
|  |         pp = p.joinpath('c:/x/y') | ||||||
|  |         self.assertEqual(pp, P('c:/x/y')) | ||||||
|  |         # Joining with files with NTFS data streams => the filename should | ||||||
|  |         # not be parsed as a drive letter | ||||||
|  |         pp = p.joinpath('./d:s') | ||||||
|  |         self.assertEqual(pp, P(r'C:/a/b\./d:s')) | ||||||
|  |         pp = p.joinpath('./dd:s') | ||||||
|  |         self.assertEqual(pp, P(r'C:/a/b\./dd:s')) | ||||||
|  |         pp = p.joinpath('E:d:s') | ||||||
|  |         self.assertEqual(pp, P('E:d:s')) | ||||||
|  |         # Joining onto a UNC path with no root | ||||||
|  |         pp = P('//').joinpath('server') | ||||||
|  |         self.assertEqual(pp, P('//server')) | ||||||
|  |         pp = P('//server').joinpath('share') | ||||||
|  |         self.assertEqual(pp, P(r'//server\share')) | ||||||
|  |         pp = P('//./BootPartition').joinpath('Windows') | ||||||
|  |         self.assertEqual(pp, P(r'//./BootPartition\Windows')) | ||||||
|  | 
 | ||||||
|  |     def test_div(self): | ||||||
|  |         # Basically the same as joinpath(). | ||||||
|  |         P = self.cls | ||||||
|  |         p = P('C:/a/b') | ||||||
|  |         self.assertEqual(p / 'x/y', P(r'C:/a/b\x/y')) | ||||||
|  |         self.assertEqual(p / 'x' / 'y', P(r'C:/a/b\x\y')) | ||||||
|  |         self.assertEqual(p / '/x/y', P('C:/x/y')) | ||||||
|  |         self.assertEqual(p / '/x' / 'y', P('C:/x\y')) | ||||||
|  |         # Joining with a different drive => the first path is ignored, even | ||||||
|  |         # if the second path is relative. | ||||||
|  |         self.assertEqual(p / 'D:x/y', P('D:x/y')) | ||||||
|  |         self.assertEqual(p / 'D:' / 'x/y', P('D:x/y')) | ||||||
|  |         self.assertEqual(p / 'D:/x/y', P('D:/x/y')) | ||||||
|  |         self.assertEqual(p / 'D:' / '/x/y', P('D:/x/y')) | ||||||
|  |         self.assertEqual(p / '//host/share/x/y', P('//host/share/x/y')) | ||||||
|  |         # Joining with the same drive => the first path is appended to if | ||||||
|  |         # the second path is relative. | ||||||
|  |         self.assertEqual(p / 'c:x/y', P(r'c:/a/b\x/y')) | ||||||
|  |         self.assertEqual(p / 'c:/x/y', P('c:/x/y')) | ||||||
|  |         # Joining with files with NTFS data streams => the filename should | ||||||
|  |         # not be parsed as a drive letter | ||||||
|  |         self.assertEqual(p / './d:s', P(r'C:/a/b\./d:s')) | ||||||
|  |         self.assertEqual(p / './dd:s', P(r'C:/a/b\./dd:s')) | ||||||
|  |         self.assertEqual(p / 'E:d:s', P('E:d:s')) | ||||||
|  | 
 | ||||||
|  |     def test_str(self): | ||||||
|  |         p = self.cls(r'a\b\c') | ||||||
|  |         self.assertEqual(str(p), 'a\\b\\c') | ||||||
|  |         p = self.cls(r'c:\a\b\c') | ||||||
|  |         self.assertEqual(str(p), 'c:\\a\\b\\c') | ||||||
|  |         p = self.cls('\\\\a\\b\\') | ||||||
|  |         self.assertEqual(str(p), '\\\\a\\b\\') | ||||||
|  |         p = self.cls(r'\\a\b\c') | ||||||
|  |         self.assertEqual(str(p), '\\\\a\\b\\c') | ||||||
|  |         p = self.cls(r'\\a\b\c\d') | ||||||
|  |         self.assertEqual(str(p), '\\\\a\\b\\c\\d') | ||||||
|  | 
 | ||||||
|  |     def test_parts(self): | ||||||
|  |         P = self.cls | ||||||
|  |         p = P(r'c:a\b') | ||||||
|  |         parts = p.parts | ||||||
|  |         self.assertEqual(parts, ('c:', 'a', 'b')) | ||||||
|  |         p = P(r'c:\a\b') | ||||||
|  |         parts = p.parts | ||||||
|  |         self.assertEqual(parts, ('c:\\', 'a', 'b')) | ||||||
|  |         p = P(r'\\a\b\c\d') | ||||||
|  |         parts = p.parts | ||||||
|  |         self.assertEqual(parts, ('\\\\a\\b\\', 'c', 'd')) | ||||||
|  | 
 | ||||||
|  |     def test_parent(self): | ||||||
|  |         # Anchored | ||||||
|  |         P = self.cls | ||||||
|  |         p = P('z:a/b/c') | ||||||
|  |         self.assertEqual(p.parent, P('z:a/b')) | ||||||
|  |         self.assertEqual(p.parent.parent, P('z:a')) | ||||||
|  |         self.assertEqual(p.parent.parent.parent, P('z:')) | ||||||
|  |         self.assertEqual(p.parent.parent.parent.parent, P('z:')) | ||||||
|  |         p = P('z:/a/b/c') | ||||||
|  |         self.assertEqual(p.parent, P('z:/a/b')) | ||||||
|  |         self.assertEqual(p.parent.parent, P('z:/a')) | ||||||
|  |         self.assertEqual(p.parent.parent.parent, P('z:/')) | ||||||
|  |         self.assertEqual(p.parent.parent.parent.parent, P('z:/')) | ||||||
|  |         p = P('//a/b/c/d') | ||||||
|  |         self.assertEqual(p.parent, P('//a/b/c')) | ||||||
|  |         self.assertEqual(p.parent.parent, P('//a/b/')) | ||||||
|  |         self.assertEqual(p.parent.parent.parent, P('//a/b/')) | ||||||
|  | 
 | ||||||
|  |     def test_parents(self): | ||||||
|  |         # Anchored | ||||||
|  |         P = self.cls | ||||||
|  |         p = P('z:a/b') | ||||||
|  |         par = p.parents | ||||||
|  |         self.assertEqual(len(par), 2) | ||||||
|  |         self.assertEqual(par[0], P('z:a')) | ||||||
|  |         self.assertEqual(par[1], P('z:')) | ||||||
|  |         self.assertEqual(par[0:1], (P('z:a'),)) | ||||||
|  |         self.assertEqual(par[:-1], (P('z:a'),)) | ||||||
|  |         self.assertEqual(par[:2], (P('z:a'), P('z:'))) | ||||||
|  |         self.assertEqual(par[1:], (P('z:'),)) | ||||||
|  |         self.assertEqual(par[::2], (P('z:a'),)) | ||||||
|  |         self.assertEqual(par[::-1], (P('z:'), P('z:a'))) | ||||||
|  |         self.assertEqual(list(par), [P('z:a'), P('z:')]) | ||||||
|  |         with self.assertRaises(IndexError): | ||||||
|  |             par[2] | ||||||
|  |         p = P('z:/a/b') | ||||||
|  |         par = p.parents | ||||||
|  |         self.assertEqual(len(par), 2) | ||||||
|  |         self.assertEqual(par[0], P('z:/a')) | ||||||
|  |         self.assertEqual(par[1], P('z:/')) | ||||||
|  |         self.assertEqual(par[0:1], (P('z:/a'),)) | ||||||
|  |         self.assertEqual(par[0:-1], (P('z:/a'),)) | ||||||
|  |         self.assertEqual(par[:2], (P('z:/a'), P('z:/'))) | ||||||
|  |         self.assertEqual(par[1:], (P('z:/'),)) | ||||||
|  |         self.assertEqual(par[::2], (P('z:/a'),)) | ||||||
|  |         self.assertEqual(par[::-1], (P('z:/'), P('z:/a'),)) | ||||||
|  |         self.assertEqual(list(par), [P('z:/a'), P('z:/')]) | ||||||
|  |         with self.assertRaises(IndexError): | ||||||
|  |             par[2] | ||||||
|  |         p = P('//a/b/c/d') | ||||||
|  |         par = p.parents | ||||||
|  |         self.assertEqual(len(par), 2) | ||||||
|  |         self.assertEqual(par[0], P('//a/b/c')) | ||||||
|  |         self.assertEqual(par[1], P('//a/b/')) | ||||||
|  |         self.assertEqual(par[0:1], (P('//a/b/c'),)) | ||||||
|  |         self.assertEqual(par[0:-1], (P('//a/b/c'),)) | ||||||
|  |         self.assertEqual(par[:2], (P('//a/b/c'), P('//a/b/'))) | ||||||
|  |         self.assertEqual(par[1:], (P('//a/b/'),)) | ||||||
|  |         self.assertEqual(par[::2], (P('//a/b/c'),)) | ||||||
|  |         self.assertEqual(par[::-1], (P('//a/b/'), P('//a/b/c'))) | ||||||
|  |         self.assertEqual(list(par), [P('//a/b/c'), P('//a/b/')]) | ||||||
|  |         with self.assertRaises(IndexError): | ||||||
|  |             par[2] | ||||||
|  | 
 | ||||||
|  |     def test_anchor(self): | ||||||
|  |         P = self.cls | ||||||
|  |         self.assertEqual(P('c:').anchor, 'c:') | ||||||
|  |         self.assertEqual(P('c:a/b').anchor, 'c:') | ||||||
|  |         self.assertEqual(P('c:\\').anchor, 'c:\\') | ||||||
|  |         self.assertEqual(P('c:\\a\\b\\').anchor, 'c:\\') | ||||||
|  |         self.assertEqual(P('\\\\a\\b\\').anchor, '\\\\a\\b\\') | ||||||
|  |         self.assertEqual(P('\\\\a\\b\\c\\d').anchor, '\\\\a\\b\\') | ||||||
|  | 
 | ||||||
|  |     def test_name(self): | ||||||
|  |         P = self.cls | ||||||
|  |         self.assertEqual(P('c:').name, '') | ||||||
|  |         self.assertEqual(P('c:/').name, '') | ||||||
|  |         self.assertEqual(P('c:a/b').name, 'b') | ||||||
|  |         self.assertEqual(P('c:/a/b').name, 'b') | ||||||
|  |         self.assertEqual(P('c:a/b.py').name, 'b.py') | ||||||
|  |         self.assertEqual(P('c:/a/b.py').name, 'b.py') | ||||||
|  |         self.assertEqual(P('//My.py/Share.php').name, '') | ||||||
|  |         self.assertEqual(P('//My.py/Share.php/a/b').name, 'b') | ||||||
|  | 
 | ||||||
|  |     def test_stem(self): | ||||||
|  |         P = self.cls | ||||||
|  |         self.assertEqual(P('c:').stem, '') | ||||||
|  |         self.assertEqual(P('c:..').stem, '..') | ||||||
|  |         self.assertEqual(P('c:/').stem, '') | ||||||
|  |         self.assertEqual(P('c:a/b').stem, 'b') | ||||||
|  |         self.assertEqual(P('c:a/b.py').stem, 'b') | ||||||
|  |         self.assertEqual(P('c:a/.hgrc').stem, '.hgrc') | ||||||
|  |         self.assertEqual(P('c:a/.hg.rc').stem, '.hg') | ||||||
|  |         self.assertEqual(P('c:a/b.tar.gz').stem, 'b.tar') | ||||||
|  |         self.assertEqual(P('c:a/trailing.dot.').stem, 'trailing.dot') | ||||||
|  | 
 | ||||||
|  |     def test_suffix(self): | ||||||
|  |         P = self.cls | ||||||
|  |         self.assertEqual(P('c:').suffix, '') | ||||||
|  |         self.assertEqual(P('c:/').suffix, '') | ||||||
|  |         self.assertEqual(P('c:a/b').suffix, '') | ||||||
|  |         self.assertEqual(P('c:/a/b').suffix, '') | ||||||
|  |         self.assertEqual(P('c:a/b.py').suffix, '.py') | ||||||
|  |         self.assertEqual(P('c:/a/b.py').suffix, '.py') | ||||||
|  |         self.assertEqual(P('c:a/.hgrc').suffix, '') | ||||||
|  |         self.assertEqual(P('c:/a/.hgrc').suffix, '') | ||||||
|  |         self.assertEqual(P('c:a/.hg.rc').suffix, '.rc') | ||||||
|  |         self.assertEqual(P('c:/a/.hg.rc').suffix, '.rc') | ||||||
|  |         self.assertEqual(P('c:a/b.tar.gz').suffix, '.gz') | ||||||
|  |         self.assertEqual(P('c:/a/b.tar.gz').suffix, '.gz') | ||||||
|  |         self.assertEqual(P('c:a/trailing.dot.').suffix, '.') | ||||||
|  |         self.assertEqual(P('c:/a/trailing.dot.').suffix, '.') | ||||||
|  |         self.assertEqual(P('//My.py/Share.php').suffix, '') | ||||||
|  |         self.assertEqual(P('//My.py/Share.php/a/b').suffix, '') | ||||||
|  | 
 | ||||||
|  |     def test_suffixes(self): | ||||||
|  |         P = self.cls | ||||||
|  |         self.assertEqual(P('c:').suffixes, []) | ||||||
|  |         self.assertEqual(P('c:/').suffixes, []) | ||||||
|  |         self.assertEqual(P('c:a/b').suffixes, []) | ||||||
|  |         self.assertEqual(P('c:/a/b').suffixes, []) | ||||||
|  |         self.assertEqual(P('c:a/b.py').suffixes, ['.py']) | ||||||
|  |         self.assertEqual(P('c:/a/b.py').suffixes, ['.py']) | ||||||
|  |         self.assertEqual(P('c:a/.hgrc').suffixes, []) | ||||||
|  |         self.assertEqual(P('c:/a/.hgrc').suffixes, []) | ||||||
|  |         self.assertEqual(P('c:a/.hg.rc').suffixes, ['.rc']) | ||||||
|  |         self.assertEqual(P('c:/a/.hg.rc').suffixes, ['.rc']) | ||||||
|  |         self.assertEqual(P('c:a/b.tar.gz').suffixes, ['.tar', '.gz']) | ||||||
|  |         self.assertEqual(P('c:/a/b.tar.gz').suffixes, ['.tar', '.gz']) | ||||||
|  |         self.assertEqual(P('//My.py/Share.php').suffixes, []) | ||||||
|  |         self.assertEqual(P('//My.py/Share.php/a/b').suffixes, []) | ||||||
|  |         self.assertEqual(P('c:a/trailing.dot.').suffixes, ['.dot', '.']) | ||||||
|  |         self.assertEqual(P('c:/a/trailing.dot.').suffixes, ['.dot', '.']) | ||||||
|  | 
 | ||||||
|  |     def test_with_name(self): | ||||||
|  |         P = self.cls | ||||||
|  |         self.assertEqual(P(r'c:a\b').with_name('d.xml'), P(r'c:a\d.xml')) | ||||||
|  |         self.assertEqual(P(r'c:\a\b').with_name('d.xml'), P(r'c:\a\d.xml')) | ||||||
|  |         self.assertEqual(P(r'c:a\Dot ending.').with_name('d.xml'), P(r'c:a\d.xml')) | ||||||
|  |         self.assertEqual(P(r'c:\a\Dot ending.').with_name('d.xml'), P(r'c:\a\d.xml')) | ||||||
|  |         self.assertRaises(ValueError, P(r'c:a\b').with_name, r'd:\e') | ||||||
|  |         self.assertRaises(ValueError, P(r'c:a\b').with_name, r'\\My\Share') | ||||||
|  | 
 | ||||||
|  |     def test_with_stem(self): | ||||||
|  |         P = self.cls | ||||||
|  |         self.assertEqual(P('c:a/b').with_stem('d'), P('c:a/d')) | ||||||
|  |         self.assertEqual(P('c:/a/b').with_stem('d'), P('c:/a/d')) | ||||||
|  |         self.assertEqual(P('c:a/Dot ending.').with_stem('d'), P('c:a/d.')) | ||||||
|  |         self.assertEqual(P('c:/a/Dot ending.').with_stem('d'), P('c:/a/d.')) | ||||||
|  |         self.assertRaises(ValueError, P('c:a/b').with_stem, 'd:/e') | ||||||
|  |         self.assertRaises(ValueError, P('c:a/b').with_stem, '//My/Share') | ||||||
|  | 
 | ||||||
|  |     def test_with_suffix(self): | ||||||
|  |         P = self.cls | ||||||
|  |         self.assertEqual(P('c:a/b').with_suffix('.gz'), P('c:a/b.gz')) | ||||||
|  |         self.assertEqual(P('c:/a/b').with_suffix('.gz'), P('c:/a/b.gz')) | ||||||
|  |         self.assertEqual(P('c:a/b.py').with_suffix('.gz'), P('c:a/b.gz')) | ||||||
|  |         self.assertEqual(P('c:/a/b.py').with_suffix('.gz'), P('c:/a/b.gz')) | ||||||
|  |         # Path doesn't have a "filename" component. | ||||||
|  |         self.assertRaises(ValueError, P('').with_suffix, '.gz') | ||||||
|  |         self.assertRaises(ValueError, P('/').with_suffix, '.gz') | ||||||
|  |         self.assertRaises(ValueError, P('//My/Share').with_suffix, '.gz') | ||||||
|  |         # Invalid suffix. | ||||||
|  |         self.assertRaises(ValueError, P('c:a/b').with_suffix, 'gz') | ||||||
|  |         self.assertRaises(ValueError, P('c:a/b').with_suffix, '/') | ||||||
|  |         self.assertRaises(ValueError, P('c:a/b').with_suffix, '\\') | ||||||
|  |         self.assertRaises(ValueError, P('c:a/b').with_suffix, 'c:') | ||||||
|  |         self.assertRaises(ValueError, P('c:a/b').with_suffix, '/.gz') | ||||||
|  |         self.assertRaises(ValueError, P('c:a/b').with_suffix, '\\.gz') | ||||||
|  |         self.assertRaises(ValueError, P('c:a/b').with_suffix, 'c:.gz') | ||||||
|  |         self.assertRaises(ValueError, P('c:a/b').with_suffix, 'c/d') | ||||||
|  |         self.assertRaises(ValueError, P('c:a/b').with_suffix, 'c\\d') | ||||||
|  |         self.assertRaises(ValueError, P('c:a/b').with_suffix, '.c/d') | ||||||
|  |         self.assertRaises(ValueError, P('c:a/b').with_suffix, '.c\\d') | ||||||
|  |         self.assertRaises(TypeError, P('c:a/b').with_suffix, None) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class LexicalWindowsPathJoinTest(JoinTestBase, unittest.TestCase): | ||||||
|  |     cls = LexicalWindowsPath | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class PureWindowsPathJoinTest(JoinTestBase, unittest.TestCase): | ||||||
|  |     cls = PureWindowsPath | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | if os.name == 'nt': | ||||||
|  |     class WindowsPathJoinTest(JoinTestBase, unittest.TestCase): | ||||||
|  |         cls = WindowsPath | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | if __name__ == "__main__": | ||||||
|  |     unittest.main() | ||||||
|  | @ -411,6 +411,18 @@ def test_stem_empty(self): | ||||||
|         self.assertEqual(P('').stem, '') |         self.assertEqual(P('').stem, '') | ||||||
|         self.assertEqual(P('.').stem, '') |         self.assertEqual(P('.').stem, '') | ||||||
| 
 | 
 | ||||||
|  |     @needs_windows | ||||||
|  |     def test_with_name_windows(self): | ||||||
|  |         P = self.cls | ||||||
|  |         self.assertRaises(ValueError, P(r'c:').with_name, 'd.xml') | ||||||
|  |         self.assertRaises(ValueError, P(r'c:\\').with_name, 'd.xml') | ||||||
|  |         self.assertRaises(ValueError, P(r'\\My\Share').with_name, 'd.xml') | ||||||
|  |         # NTFS alternate data streams | ||||||
|  |         self.assertEqual(str(P('a').with_name('d:')), '.\\d:') | ||||||
|  |         self.assertEqual(str(P('a').with_name('d:e')), '.\\d:e') | ||||||
|  |         self.assertEqual(P(r'c:a\b').with_name('d:'), P(r'c:a\d:')) | ||||||
|  |         self.assertEqual(P(r'c:a\b').with_name('d:e'), P(r'c:a\d:e')) | ||||||
|  | 
 | ||||||
|     def test_with_name_empty(self): |     def test_with_name_empty(self): | ||||||
|         P = self.cls |         P = self.cls | ||||||
|         self.assertRaises(ValueError, P('').with_name, 'd.xml') |         self.assertRaises(ValueError, P('').with_name, 'd.xml') | ||||||
|  | @ -419,6 +431,18 @@ def test_with_name_empty(self): | ||||||
|         self.assertRaises(ValueError, P('a/b').with_name, '') |         self.assertRaises(ValueError, P('a/b').with_name, '') | ||||||
|         self.assertRaises(ValueError, P('a/b').with_name, '.') |         self.assertRaises(ValueError, P('a/b').with_name, '.') | ||||||
| 
 | 
 | ||||||
|  |     @needs_windows | ||||||
|  |     def test_with_stem_windows(self): | ||||||
|  |         P = self.cls | ||||||
|  |         self.assertRaises(ValueError, P('c:').with_stem, 'd') | ||||||
|  |         self.assertRaises(ValueError, P('c:/').with_stem, 'd') | ||||||
|  |         self.assertRaises(ValueError, P('//My/Share').with_stem, 'd') | ||||||
|  |         # NTFS alternate data streams | ||||||
|  |         self.assertEqual(str(P('a').with_stem('d:')), '.\\d:') | ||||||
|  |         self.assertEqual(str(P('a').with_stem('d:e')), '.\\d:e') | ||||||
|  |         self.assertEqual(P('c:a/b').with_stem('d:'), P('c:a/d:')) | ||||||
|  |         self.assertEqual(P('c:a/b').with_stem('d:e'), P('c:a/d:e')) | ||||||
|  | 
 | ||||||
|     def test_with_stem_empty(self): |     def test_with_stem_empty(self): | ||||||
|         P = self.cls |         P = self.cls | ||||||
|         self.assertRaises(ValueError, P('').with_stem, 'd') |         self.assertRaises(ValueError, P('').with_stem, 'd') | ||||||
|  |  | ||||||
|  | @ -108,70 +108,6 @@ def test_str_subclass_windows(self): | ||||||
|         self._check_str_subclass('\\\\some\\share\\a') |         self._check_str_subclass('\\\\some\\share\\a') | ||||||
|         self._check_str_subclass('\\\\some\\share\\a\\b.txt') |         self._check_str_subclass('\\\\some\\share\\a\\b.txt') | ||||||
| 
 | 
 | ||||||
|     @needs_windows |  | ||||||
|     def test_join_windows(self): |  | ||||||
|         P = self.cls |  | ||||||
|         p = P('C:/a/b') |  | ||||||
|         pp = p.joinpath('x/y') |  | ||||||
|         self.assertEqual(pp, P('C:/a/b/x/y')) |  | ||||||
|         pp = p.joinpath('/x/y') |  | ||||||
|         self.assertEqual(pp, P('C:/x/y')) |  | ||||||
|         # Joining with a different drive => the first path is ignored, even |  | ||||||
|         # if the second path is relative. |  | ||||||
|         pp = p.joinpath('D:x/y') |  | ||||||
|         self.assertEqual(pp, P('D:x/y')) |  | ||||||
|         pp = p.joinpath('D:/x/y') |  | ||||||
|         self.assertEqual(pp, P('D:/x/y')) |  | ||||||
|         pp = p.joinpath('//host/share/x/y') |  | ||||||
|         self.assertEqual(pp, P('//host/share/x/y')) |  | ||||||
|         # Joining with the same drive => the first path is appended to if |  | ||||||
|         # the second path is relative. |  | ||||||
|         pp = p.joinpath('c:x/y') |  | ||||||
|         self.assertEqual(pp, P('C:/a/b/x/y')) |  | ||||||
|         pp = p.joinpath('c:/x/y') |  | ||||||
|         self.assertEqual(pp, P('C:/x/y')) |  | ||||||
|         # Joining with files with NTFS data streams => the filename should |  | ||||||
|         # not be parsed as a drive letter |  | ||||||
|         pp = p.joinpath(P('./d:s')) |  | ||||||
|         self.assertEqual(pp, P('C:/a/b/d:s')) |  | ||||||
|         pp = p.joinpath(P('./dd:s')) |  | ||||||
|         self.assertEqual(pp, P('C:/a/b/dd:s')) |  | ||||||
|         pp = p.joinpath(P('E:d:s')) |  | ||||||
|         self.assertEqual(pp, P('E:d:s')) |  | ||||||
|         # Joining onto a UNC path with no root |  | ||||||
|         pp = P('//').joinpath('server') |  | ||||||
|         self.assertEqual(pp, P('//server')) |  | ||||||
|         pp = P('//server').joinpath('share') |  | ||||||
|         self.assertEqual(pp, P('//server/share')) |  | ||||||
|         pp = P('//./BootPartition').joinpath('Windows') |  | ||||||
|         self.assertEqual(pp, P('//./BootPartition/Windows')) |  | ||||||
| 
 |  | ||||||
|     @needs_windows |  | ||||||
|     def test_div_windows(self): |  | ||||||
|         # Basically the same as joinpath(). |  | ||||||
|         P = self.cls |  | ||||||
|         p = P('C:/a/b') |  | ||||||
|         self.assertEqual(p / 'x/y', P('C:/a/b/x/y')) |  | ||||||
|         self.assertEqual(p / 'x' / 'y', P('C:/a/b/x/y')) |  | ||||||
|         self.assertEqual(p / '/x/y', P('C:/x/y')) |  | ||||||
|         self.assertEqual(p / '/x' / 'y', P('C:/x/y')) |  | ||||||
|         # Joining with a different drive => the first path is ignored, even |  | ||||||
|         # if the second path is relative. |  | ||||||
|         self.assertEqual(p / 'D:x/y', P('D:x/y')) |  | ||||||
|         self.assertEqual(p / 'D:' / 'x/y', P('D:x/y')) |  | ||||||
|         self.assertEqual(p / 'D:/x/y', P('D:/x/y')) |  | ||||||
|         self.assertEqual(p / 'D:' / '/x/y', P('D:/x/y')) |  | ||||||
|         self.assertEqual(p / '//host/share/x/y', P('//host/share/x/y')) |  | ||||||
|         # Joining with the same drive => the first path is appended to if |  | ||||||
|         # the second path is relative. |  | ||||||
|         self.assertEqual(p / 'c:x/y', P('C:/a/b/x/y')) |  | ||||||
|         self.assertEqual(p / 'c:/x/y', P('C:/x/y')) |  | ||||||
|         # Joining with files with NTFS data streams => the filename should |  | ||||||
|         # not be parsed as a drive letter |  | ||||||
|         self.assertEqual(p / P('./d:s'), P('C:/a/b/d:s')) |  | ||||||
|         self.assertEqual(p / P('./dd:s'), P('C:/a/b/dd:s')) |  | ||||||
|         self.assertEqual(p / P('E:d:s'), P('E:d:s')) |  | ||||||
| 
 |  | ||||||
|     def _check_str(self, expected, args): |     def _check_str(self, expected, args): | ||||||
|         p = self.cls(*args) |         p = self.cls(*args) | ||||||
|         self.assertEqual(str(p), expected.replace('/', self.sep)) |         self.assertEqual(str(p), expected.replace('/', self.sep)) | ||||||
|  | @ -195,221 +131,6 @@ def test_str_windows(self): | ||||||
|         p = self.cls('//a/b/c/d') |         p = self.cls('//a/b/c/d') | ||||||
|         self.assertEqual(str(p), '\\\\a\\b\\c\\d') |         self.assertEqual(str(p), '\\\\a\\b\\c\\d') | ||||||
| 
 | 
 | ||||||
|     @needs_windows |  | ||||||
|     def test_parts_windows(self): |  | ||||||
|         P = self.cls |  | ||||||
|         p = P('c:a/b') |  | ||||||
|         parts = p.parts |  | ||||||
|         self.assertEqual(parts, ('c:', 'a', 'b')) |  | ||||||
|         p = P('c:/a/b') |  | ||||||
|         parts = p.parts |  | ||||||
|         self.assertEqual(parts, ('c:\\', 'a', 'b')) |  | ||||||
|         p = P('//a/b/c/d') |  | ||||||
|         parts = p.parts |  | ||||||
|         self.assertEqual(parts, ('\\\\a\\b\\', 'c', 'd')) |  | ||||||
| 
 |  | ||||||
|     @needs_windows |  | ||||||
|     def test_parent_windows(self): |  | ||||||
|         # Anchored |  | ||||||
|         P = self.cls |  | ||||||
|         p = P('z:a/b/c') |  | ||||||
|         self.assertEqual(p.parent, P('z:a/b')) |  | ||||||
|         self.assertEqual(p.parent.parent, P('z:a')) |  | ||||||
|         self.assertEqual(p.parent.parent.parent, P('z:')) |  | ||||||
|         self.assertEqual(p.parent.parent.parent.parent, P('z:')) |  | ||||||
|         p = P('z:/a/b/c') |  | ||||||
|         self.assertEqual(p.parent, P('z:/a/b')) |  | ||||||
|         self.assertEqual(p.parent.parent, P('z:/a')) |  | ||||||
|         self.assertEqual(p.parent.parent.parent, P('z:/')) |  | ||||||
|         self.assertEqual(p.parent.parent.parent.parent, P('z:/')) |  | ||||||
|         p = P('//a/b/c/d') |  | ||||||
|         self.assertEqual(p.parent, P('//a/b/c')) |  | ||||||
|         self.assertEqual(p.parent.parent, P('//a/b')) |  | ||||||
|         self.assertEqual(p.parent.parent.parent, P('//a/b')) |  | ||||||
| 
 |  | ||||||
|     @needs_windows |  | ||||||
|     def test_parents_windows(self): |  | ||||||
|         # Anchored |  | ||||||
|         P = self.cls |  | ||||||
|         p = P('z:a/b/') |  | ||||||
|         par = p.parents |  | ||||||
|         self.assertEqual(len(par), 2) |  | ||||||
|         self.assertEqual(par[0], P('z:a')) |  | ||||||
|         self.assertEqual(par[1], P('z:')) |  | ||||||
|         self.assertEqual(par[0:1], (P('z:a'),)) |  | ||||||
|         self.assertEqual(par[:-1], (P('z:a'),)) |  | ||||||
|         self.assertEqual(par[:2], (P('z:a'), P('z:'))) |  | ||||||
|         self.assertEqual(par[1:], (P('z:'),)) |  | ||||||
|         self.assertEqual(par[::2], (P('z:a'),)) |  | ||||||
|         self.assertEqual(par[::-1], (P('z:'), P('z:a'))) |  | ||||||
|         self.assertEqual(list(par), [P('z:a'), P('z:')]) |  | ||||||
|         with self.assertRaises(IndexError): |  | ||||||
|             par[2] |  | ||||||
|         p = P('z:/a/b/') |  | ||||||
|         par = p.parents |  | ||||||
|         self.assertEqual(len(par), 2) |  | ||||||
|         self.assertEqual(par[0], P('z:/a')) |  | ||||||
|         self.assertEqual(par[1], P('z:/')) |  | ||||||
|         self.assertEqual(par[0:1], (P('z:/a'),)) |  | ||||||
|         self.assertEqual(par[0:-1], (P('z:/a'),)) |  | ||||||
|         self.assertEqual(par[:2], (P('z:/a'), P('z:/'))) |  | ||||||
|         self.assertEqual(par[1:], (P('z:/'),)) |  | ||||||
|         self.assertEqual(par[::2], (P('z:/a'),)) |  | ||||||
|         self.assertEqual(par[::-1], (P('z:/'), P('z:/a'),)) |  | ||||||
|         self.assertEqual(list(par), [P('z:/a'), P('z:/')]) |  | ||||||
|         with self.assertRaises(IndexError): |  | ||||||
|             par[2] |  | ||||||
|         p = P('//a/b/c/d') |  | ||||||
|         par = p.parents |  | ||||||
|         self.assertEqual(len(par), 2) |  | ||||||
|         self.assertEqual(par[0], P('//a/b/c')) |  | ||||||
|         self.assertEqual(par[1], P('//a/b')) |  | ||||||
|         self.assertEqual(par[0:1], (P('//a/b/c'),)) |  | ||||||
|         self.assertEqual(par[0:-1], (P('//a/b/c'),)) |  | ||||||
|         self.assertEqual(par[:2], (P('//a/b/c'), P('//a/b'))) |  | ||||||
|         self.assertEqual(par[1:], (P('//a/b'),)) |  | ||||||
|         self.assertEqual(par[::2], (P('//a/b/c'),)) |  | ||||||
|         self.assertEqual(par[::-1], (P('//a/b'), P('//a/b/c'))) |  | ||||||
|         self.assertEqual(list(par), [P('//a/b/c'), P('//a/b')]) |  | ||||||
|         with self.assertRaises(IndexError): |  | ||||||
|             par[2] |  | ||||||
| 
 |  | ||||||
|     @needs_windows |  | ||||||
|     def test_anchor_windows(self): |  | ||||||
|         P = self.cls |  | ||||||
|         self.assertEqual(P('c:').anchor, 'c:') |  | ||||||
|         self.assertEqual(P('c:a/b').anchor, 'c:') |  | ||||||
|         self.assertEqual(P('c:/').anchor, 'c:\\') |  | ||||||
|         self.assertEqual(P('c:/a/b/').anchor, 'c:\\') |  | ||||||
|         self.assertEqual(P('//a/b').anchor, '\\\\a\\b\\') |  | ||||||
|         self.assertEqual(P('//a/b/').anchor, '\\\\a\\b\\') |  | ||||||
|         self.assertEqual(P('//a/b/c/d').anchor, '\\\\a\\b\\') |  | ||||||
| 
 |  | ||||||
|     @needs_windows |  | ||||||
|     def test_name_windows(self): |  | ||||||
|         P = self.cls |  | ||||||
|         self.assertEqual(P('c:').name, '') |  | ||||||
|         self.assertEqual(P('c:/').name, '') |  | ||||||
|         self.assertEqual(P('c:a/b').name, 'b') |  | ||||||
|         self.assertEqual(P('c:/a/b').name, 'b') |  | ||||||
|         self.assertEqual(P('c:a/b.py').name, 'b.py') |  | ||||||
|         self.assertEqual(P('c:/a/b.py').name, 'b.py') |  | ||||||
|         self.assertEqual(P('//My.py/Share.php').name, '') |  | ||||||
|         self.assertEqual(P('//My.py/Share.php/a/b').name, 'b') |  | ||||||
| 
 |  | ||||||
|     @needs_windows |  | ||||||
|     def test_suffix_windows(self): |  | ||||||
|         P = self.cls |  | ||||||
|         self.assertEqual(P('c:').suffix, '') |  | ||||||
|         self.assertEqual(P('c:/').suffix, '') |  | ||||||
|         self.assertEqual(P('c:a/b').suffix, '') |  | ||||||
|         self.assertEqual(P('c:/a/b').suffix, '') |  | ||||||
|         self.assertEqual(P('c:a/b.py').suffix, '.py') |  | ||||||
|         self.assertEqual(P('c:/a/b.py').suffix, '.py') |  | ||||||
|         self.assertEqual(P('c:a/.hgrc').suffix, '') |  | ||||||
|         self.assertEqual(P('c:/a/.hgrc').suffix, '') |  | ||||||
|         self.assertEqual(P('c:a/.hg.rc').suffix, '.rc') |  | ||||||
|         self.assertEqual(P('c:/a/.hg.rc').suffix, '.rc') |  | ||||||
|         self.assertEqual(P('c:a/b.tar.gz').suffix, '.gz') |  | ||||||
|         self.assertEqual(P('c:/a/b.tar.gz').suffix, '.gz') |  | ||||||
|         self.assertEqual(P('c:a/trailing.dot.').suffix, '.') |  | ||||||
|         self.assertEqual(P('c:/a/trailing.dot.').suffix, '.') |  | ||||||
|         self.assertEqual(P('//My.py/Share.php').suffix, '') |  | ||||||
|         self.assertEqual(P('//My.py/Share.php/a/b').suffix, '') |  | ||||||
| 
 |  | ||||||
|     @needs_windows |  | ||||||
|     def test_suffixes_windows(self): |  | ||||||
|         P = self.cls |  | ||||||
|         self.assertEqual(P('c:').suffixes, []) |  | ||||||
|         self.assertEqual(P('c:/').suffixes, []) |  | ||||||
|         self.assertEqual(P('c:a/b').suffixes, []) |  | ||||||
|         self.assertEqual(P('c:/a/b').suffixes, []) |  | ||||||
|         self.assertEqual(P('c:a/b.py').suffixes, ['.py']) |  | ||||||
|         self.assertEqual(P('c:/a/b.py').suffixes, ['.py']) |  | ||||||
|         self.assertEqual(P('c:a/.hgrc').suffixes, []) |  | ||||||
|         self.assertEqual(P('c:/a/.hgrc').suffixes, []) |  | ||||||
|         self.assertEqual(P('c:a/.hg.rc').suffixes, ['.rc']) |  | ||||||
|         self.assertEqual(P('c:/a/.hg.rc').suffixes, ['.rc']) |  | ||||||
|         self.assertEqual(P('c:a/b.tar.gz').suffixes, ['.tar', '.gz']) |  | ||||||
|         self.assertEqual(P('c:/a/b.tar.gz').suffixes, ['.tar', '.gz']) |  | ||||||
|         self.assertEqual(P('//My.py/Share.php').suffixes, []) |  | ||||||
|         self.assertEqual(P('//My.py/Share.php/a/b').suffixes, []) |  | ||||||
|         self.assertEqual(P('c:a/trailing.dot.').suffixes, ['.dot', '.']) |  | ||||||
|         self.assertEqual(P('c:/a/trailing.dot.').suffixes, ['.dot', '.']) |  | ||||||
| 
 |  | ||||||
|     @needs_windows |  | ||||||
|     def test_stem_windows(self): |  | ||||||
|         P = self.cls |  | ||||||
|         self.assertEqual(P('c:').stem, '') |  | ||||||
|         self.assertEqual(P('c:.').stem, '') |  | ||||||
|         self.assertEqual(P('c:..').stem, '..') |  | ||||||
|         self.assertEqual(P('c:/').stem, '') |  | ||||||
|         self.assertEqual(P('c:a/b').stem, 'b') |  | ||||||
|         self.assertEqual(P('c:a/b.py').stem, 'b') |  | ||||||
|         self.assertEqual(P('c:a/.hgrc').stem, '.hgrc') |  | ||||||
|         self.assertEqual(P('c:a/.hg.rc').stem, '.hg') |  | ||||||
|         self.assertEqual(P('c:a/b.tar.gz').stem, 'b.tar') |  | ||||||
|         self.assertEqual(P('c:a/trailing.dot.').stem, 'trailing.dot') |  | ||||||
| 
 |  | ||||||
|     @needs_windows |  | ||||||
|     def test_with_name_windows(self): |  | ||||||
|         P = self.cls |  | ||||||
|         self.assertEqual(P('c:a/b').with_name('d.xml'), P('c:a/d.xml')) |  | ||||||
|         self.assertEqual(P('c:/a/b').with_name('d.xml'), P('c:/a/d.xml')) |  | ||||||
|         self.assertEqual(P('c:a/Dot ending.').with_name('d.xml'), P('c:a/d.xml')) |  | ||||||
|         self.assertEqual(P('c:/a/Dot ending.').with_name('d.xml'), P('c:/a/d.xml')) |  | ||||||
|         self.assertRaises(ValueError, P('c:').with_name, 'd.xml') |  | ||||||
|         self.assertRaises(ValueError, P('c:/').with_name, 'd.xml') |  | ||||||
|         self.assertRaises(ValueError, P('//My/Share').with_name, 'd.xml') |  | ||||||
|         self.assertEqual(str(P('a').with_name('d:')), '.\\d:') |  | ||||||
|         self.assertEqual(str(P('a').with_name('d:e')), '.\\d:e') |  | ||||||
|         self.assertEqual(P('c:a/b').with_name('d:'), P('c:a/d:')) |  | ||||||
|         self.assertEqual(P('c:a/b').with_name('d:e'), P('c:a/d:e')) |  | ||||||
|         self.assertRaises(ValueError, P('c:a/b').with_name, 'd:/e') |  | ||||||
|         self.assertRaises(ValueError, P('c:a/b').with_name, '//My/Share') |  | ||||||
| 
 |  | ||||||
|     @needs_windows |  | ||||||
|     def test_with_stem_windows(self): |  | ||||||
|         P = self.cls |  | ||||||
|         self.assertEqual(P('c:a/b').with_stem('d'), P('c:a/d')) |  | ||||||
|         self.assertEqual(P('c:/a/b').with_stem('d'), P('c:/a/d')) |  | ||||||
|         self.assertEqual(P('c:a/Dot ending.').with_stem('d'), P('c:a/d.')) |  | ||||||
|         self.assertEqual(P('c:/a/Dot ending.').with_stem('d'), P('c:/a/d.')) |  | ||||||
|         self.assertRaises(ValueError, P('c:').with_stem, 'd') |  | ||||||
|         self.assertRaises(ValueError, P('c:/').with_stem, 'd') |  | ||||||
|         self.assertRaises(ValueError, P('//My/Share').with_stem, 'd') |  | ||||||
|         self.assertEqual(str(P('a').with_stem('d:')), '.\\d:') |  | ||||||
|         self.assertEqual(str(P('a').with_stem('d:e')), '.\\d:e') |  | ||||||
|         self.assertEqual(P('c:a/b').with_stem('d:'), P('c:a/d:')) |  | ||||||
|         self.assertEqual(P('c:a/b').with_stem('d:e'), P('c:a/d:e')) |  | ||||||
|         self.assertRaises(ValueError, P('c:a/b').with_stem, 'd:/e') |  | ||||||
|         self.assertRaises(ValueError, P('c:a/b').with_stem, '//My/Share') |  | ||||||
| 
 |  | ||||||
|     @needs_windows |  | ||||||
|     def test_with_suffix_windows(self): |  | ||||||
|         P = self.cls |  | ||||||
|         self.assertEqual(P('c:a/b').with_suffix('.gz'), P('c:a/b.gz')) |  | ||||||
|         self.assertEqual(P('c:/a/b').with_suffix('.gz'), P('c:/a/b.gz')) |  | ||||||
|         self.assertEqual(P('c:a/b.py').with_suffix('.gz'), P('c:a/b.gz')) |  | ||||||
|         self.assertEqual(P('c:/a/b.py').with_suffix('.gz'), P('c:/a/b.gz')) |  | ||||||
|         # Path doesn't have a "filename" component. |  | ||||||
|         self.assertRaises(ValueError, P('').with_suffix, '.gz') |  | ||||||
|         self.assertRaises(ValueError, P('.').with_suffix, '.gz') |  | ||||||
|         self.assertRaises(ValueError, P('/').with_suffix, '.gz') |  | ||||||
|         self.assertRaises(ValueError, P('//My/Share').with_suffix, '.gz') |  | ||||||
|         # Invalid suffix. |  | ||||||
|         self.assertRaises(ValueError, P('c:a/b').with_suffix, 'gz') |  | ||||||
|         self.assertRaises(ValueError, P('c:a/b').with_suffix, '/') |  | ||||||
|         self.assertRaises(ValueError, P('c:a/b').with_suffix, '\\') |  | ||||||
|         self.assertRaises(ValueError, P('c:a/b').with_suffix, 'c:') |  | ||||||
|         self.assertRaises(ValueError, P('c:a/b').with_suffix, '/.gz') |  | ||||||
|         self.assertRaises(ValueError, P('c:a/b').with_suffix, '\\.gz') |  | ||||||
|         self.assertRaises(ValueError, P('c:a/b').with_suffix, 'c:.gz') |  | ||||||
|         self.assertRaises(ValueError, P('c:a/b').with_suffix, 'c/d') |  | ||||||
|         self.assertRaises(ValueError, P('c:a/b').with_suffix, 'c\\d') |  | ||||||
|         self.assertRaises(ValueError, P('c:a/b').with_suffix, '.c/d') |  | ||||||
|         self.assertRaises(ValueError, P('c:a/b').with_suffix, '.c\\d') |  | ||||||
|         self.assertRaises(TypeError, P('c:a/b').with_suffix, None) |  | ||||||
| 
 | 
 | ||||||
| # | # | ||||||
| # Tests for the virtual classes. | # Tests for the virtual classes. | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Barney Gale
						Barney Gale