»Core Development>Code coverage>Lib/test/test_pathlib.py

Python code coverage for Lib/test/test_pathlib.py

#countcontent
1n/aimport collections
2n/aimport io
3n/aimport os
4n/aimport errno
5n/aimport pathlib
6n/aimport pickle
7n/aimport socket
8n/aimport stat
9n/aimport tempfile
10n/aimport unittest
11n/a
12n/afrom test import support
13n/aandroid_not_root = support.android_not_root
14n/aTESTFN = support.TESTFN
15n/a
16n/atry:
17n/a import grp, pwd
18n/aexcept ImportError:
19n/a grp = pwd = None
20n/a
21n/a
22n/aclass _BaseFlavourTest(object):
23n/a
24n/a def _check_parse_parts(self, arg, expected):
25n/a f = self.flavour.parse_parts
26n/a sep = self.flavour.sep
27n/a altsep = self.flavour.altsep
28n/a actual = f([x.replace('/', sep) for x in arg])
29n/a self.assertEqual(actual, expected)
30n/a if altsep:
31n/a actual = f([x.replace('/', altsep) for x in arg])
32n/a self.assertEqual(actual, expected)
33n/a
34n/a def test_parse_parts_common(self):
35n/a check = self._check_parse_parts
36n/a sep = self.flavour.sep
37n/a # Unanchored parts
38n/a check([], ('', '', []))
39n/a check(['a'], ('', '', ['a']))
40n/a check(['a/'], ('', '', ['a']))
41n/a check(['a', 'b'], ('', '', ['a', 'b']))
42n/a # Expansion
43n/a check(['a/b'], ('', '', ['a', 'b']))
44n/a check(['a/b/'], ('', '', ['a', 'b']))
45n/a check(['a', 'b/c', 'd'], ('', '', ['a', 'b', 'c', 'd']))
46n/a # Collapsing and stripping excess slashes
47n/a check(['a', 'b//c', 'd'], ('', '', ['a', 'b', 'c', 'd']))
48n/a check(['a', 'b/c/', 'd'], ('', '', ['a', 'b', 'c', 'd']))
49n/a # Eliminating standalone dots
50n/a check(['.'], ('', '', []))
51n/a check(['.', '.', 'b'], ('', '', ['b']))
52n/a check(['a', '.', 'b'], ('', '', ['a', 'b']))
53n/a check(['a', '.', '.'], ('', '', ['a']))
54n/a # The first part is anchored
55n/a check(['/a/b'], ('', sep, [sep, 'a', 'b']))
56n/a check(['/a', 'b'], ('', sep, [sep, 'a', 'b']))
57n/a check(['/a/', 'b'], ('', sep, [sep, 'a', 'b']))
58n/a # Ignoring parts before an anchored part
59n/a check(['a', '/b', 'c'], ('', sep, [sep, 'b', 'c']))
60n/a check(['a', '/b', '/c'], ('', sep, [sep, 'c']))
61n/a
62n/a
63n/aclass PosixFlavourTest(_BaseFlavourTest, unittest.TestCase):
64n/a flavour = pathlib._posix_flavour
65n/a
66n/a def test_parse_parts(self):
67n/a check = self._check_parse_parts
68n/a # Collapsing of excess leading slashes, except for the double-slash
69n/a # special case.
70n/a check(['//a', 'b'], ('', '//', ['//', 'a', 'b']))
71n/a check(['///a', 'b'], ('', '/', ['/', 'a', 'b']))
72n/a check(['////a', 'b'], ('', '/', ['/', 'a', 'b']))
73n/a # Paths which look like NT paths aren't treated specially
74n/a check(['c:a'], ('', '', ['c:a']))
75n/a check(['c:\\a'], ('', '', ['c:\\a']))
76n/a check(['\\a'], ('', '', ['\\a']))
77n/a
78n/a def test_splitroot(self):
79n/a f = self.flavour.splitroot
80n/a self.assertEqual(f(''), ('', '', ''))
81n/a self.assertEqual(f('a'), ('', '', 'a'))
82n/a self.assertEqual(f('a/b'), ('', '', 'a/b'))
83n/a self.assertEqual(f('a/b/'), ('', '', 'a/b/'))
84n/a self.assertEqual(f('/a'), ('', '/', 'a'))
85n/a self.assertEqual(f('/a/b'), ('', '/', 'a/b'))
86n/a self.assertEqual(f('/a/b/'), ('', '/', 'a/b/'))
87n/a # The root is collapsed when there are redundant slashes
88n/a # except when there are exactly two leading slashes, which
89n/a # is a special case in POSIX.
90n/a self.assertEqual(f('//a'), ('', '//', 'a'))
91n/a self.assertEqual(f('///a'), ('', '/', 'a'))
92n/a self.assertEqual(f('///a/b'), ('', '/', 'a/b'))
93n/a # Paths which look like NT paths aren't treated specially
94n/a self.assertEqual(f('c:/a/b'), ('', '', 'c:/a/b'))
95n/a self.assertEqual(f('\\/a/b'), ('', '', '\\/a/b'))
96n/a self.assertEqual(f('\\a\\b'), ('', '', '\\a\\b'))
97n/a
98n/a
99n/aclass NTFlavourTest(_BaseFlavourTest, unittest.TestCase):
100n/a flavour = pathlib._windows_flavour
101n/a
102n/a def test_parse_parts(self):
103n/a check = self._check_parse_parts
104n/a # First part is anchored
105n/a check(['c:'], ('c:', '', ['c:']))
106n/a check(['c:/'], ('c:', '\\', ['c:\\']))
107n/a check(['/'], ('', '\\', ['\\']))
108n/a check(['c:a'], ('c:', '', ['c:', 'a']))
109n/a check(['c:/a'], ('c:', '\\', ['c:\\', 'a']))
110n/a check(['/a'], ('', '\\', ['\\', 'a']))
111n/a # UNC paths
112n/a check(['//a/b'], ('\\\\a\\b', '\\', ['\\\\a\\b\\']))
113n/a check(['//a/b/'], ('\\\\a\\b', '\\', ['\\\\a\\b\\']))
114n/a check(['//a/b/c'], ('\\\\a\\b', '\\', ['\\\\a\\b\\', 'c']))
115n/a # Second part is anchored, so that the first part is ignored
116n/a check(['a', 'Z:b', 'c'], ('Z:', '', ['Z:', 'b', 'c']))
117n/a check(['a', 'Z:/b', 'c'], ('Z:', '\\', ['Z:\\', 'b', 'c']))
118n/a # UNC paths
119n/a check(['a', '//b/c', 'd'], ('\\\\b\\c', '\\', ['\\\\b\\c\\', 'd']))
120n/a # Collapsing and stripping excess slashes
121n/a check(['a', 'Z://b//c/', 'd/'], ('Z:', '\\', ['Z:\\', 'b', 'c', 'd']))
122n/a # UNC paths
123n/a check(['a', '//b/c//', 'd'], ('\\\\b\\c', '\\', ['\\\\b\\c\\', 'd']))
124n/a # Extended paths
125n/a check(['//?/c:/'], ('\\\\?\\c:', '\\', ['\\\\?\\c:\\']))
126n/a check(['//?/c:/a'], ('\\\\?\\c:', '\\', ['\\\\?\\c:\\', 'a']))
127n/a check(['//?/c:/a', '/b'], ('\\\\?\\c:', '\\', ['\\\\?\\c:\\', 'b']))
128n/a # Extended UNC paths (format is "\\?\UNC\server\share")
129n/a check(['//?/UNC/b/c'], ('\\\\?\\UNC\\b\\c', '\\', ['\\\\?\\UNC\\b\\c\\']))
130n/a check(['//?/UNC/b/c/d'], ('\\\\?\\UNC\\b\\c', '\\', ['\\\\?\\UNC\\b\\c\\', 'd']))
131n/a # Second part has a root but not drive
132n/a check(['a', '/b', 'c'], ('', '\\', ['\\', 'b', 'c']))
133n/a check(['Z:/a', '/b', 'c'], ('Z:', '\\', ['Z:\\', 'b', 'c']))
134n/a check(['//?/Z:/a', '/b', 'c'], ('\\\\?\\Z:', '\\', ['\\\\?\\Z:\\', 'b', 'c']))
135n/a
136n/a def test_splitroot(self):
137n/a f = self.flavour.splitroot
138n/a self.assertEqual(f(''), ('', '', ''))
139n/a self.assertEqual(f('a'), ('', '', 'a'))
140n/a self.assertEqual(f('a\\b'), ('', '', 'a\\b'))
141n/a self.assertEqual(f('\\a'), ('', '\\', 'a'))
142n/a self.assertEqual(f('\\a\\b'), ('', '\\', 'a\\b'))
143n/a self.assertEqual(f('c:a\\b'), ('c:', '', 'a\\b'))
144n/a self.assertEqual(f('c:\\a\\b'), ('c:', '\\', 'a\\b'))
145n/a # Redundant slashes in the root are collapsed
146n/a self.assertEqual(f('\\\\a'), ('', '\\', 'a'))
147n/a self.assertEqual(f('\\\\\\a/b'), ('', '\\', 'a/b'))
148n/a self.assertEqual(f('c:\\\\a'), ('c:', '\\', 'a'))
149n/a self.assertEqual(f('c:\\\\\\a/b'), ('c:', '\\', 'a/b'))
150n/a # Valid UNC paths
151n/a self.assertEqual(f('\\\\a\\b'), ('\\\\a\\b', '\\', ''))
152n/a self.assertEqual(f('\\\\a\\b\\'), ('\\\\a\\b', '\\', ''))
153n/a self.assertEqual(f('\\\\a\\b\\c\\d'), ('\\\\a\\b', '\\', 'c\\d'))
154n/a # These are non-UNC paths (according to ntpath.py and test_ntpath)
155n/a # However, command.com says such paths are invalid, so it's
156n/a # difficult to know what the right semantics are
157n/a self.assertEqual(f('\\\\\\a\\b'), ('', '\\', 'a\\b'))
158n/a self.assertEqual(f('\\\\a'), ('', '\\', 'a'))
159n/a
160n/a
161n/a#
162n/a# Tests for the pure classes
163n/a#
164n/a
165n/aclass _BasePurePathTest(object):
166n/a
167n/a # keys are canonical paths, values are list of tuples of arguments
168n/a # supposed to produce equal paths
169n/a equivalences = {
170n/a 'a/b': [
171n/a ('a', 'b'), ('a/', 'b'), ('a', 'b/'), ('a/', 'b/'),
172n/a ('a/b/',), ('a//b',), ('a//b//',),
173n/a # empty components get removed
174n/a ('', 'a', 'b'), ('a', '', 'b'), ('a', 'b', ''),
175n/a ],
176n/a '/b/c/d': [
177n/a ('a', '/b/c', 'd'), ('a', '///b//c', 'd/'),
178n/a ('/a', '/b/c', 'd'),
179n/a # empty components get removed
180n/a ('/', 'b', '', 'c/d'), ('/', '', 'b/c/d'), ('', '/b/c/d'),
181n/a ],
182n/a }
183n/a
184n/a def setUp(self):
185n/a p = self.cls('a')
186n/a self.flavour = p._flavour
187n/a self.sep = self.flavour.sep
188n/a self.altsep = self.flavour.altsep
189n/a
190n/a def test_constructor_common(self):
191n/a P = self.cls
192n/a p = P('a')
193n/a self.assertIsInstance(p, P)
194n/a class PathLike:
195n/a def __fspath__(self):
196n/a return "a/b/c"
197n/a P('a', 'b', 'c')
198n/a P('/a', 'b', 'c')
199n/a P('a/b/c')
200n/a P('/a/b/c')
201n/a P(PathLike())
202n/a self.assertEqual(P(P('a')), P('a'))
203n/a self.assertEqual(P(P('a'), 'b'), P('a/b'))
204n/a self.assertEqual(P(P('a'), P('b')), P('a/b'))
205n/a self.assertEqual(P(P('a'), P('b'), P('c')), P(PathLike()))
206n/a
207n/a def _check_str_subclass(self, *args):
208n/a # Issue #21127: it should be possible to construct a PurePath object
209n/a # from a str subclass instance, and it then gets converted to
210n/a # a pure str object.
211n/a class StrSubclass(str):
212n/a pass
213n/a P = self.cls
214n/a p = P(*(StrSubclass(x) for x in args))
215n/a self.assertEqual(p, P(*args))
216n/a for part in p.parts:
217n/a self.assertIs(type(part), str)
218n/a
219n/a def test_str_subclass_common(self):
220n/a self._check_str_subclass('')
221n/a self._check_str_subclass('.')
222n/a self._check_str_subclass('a')
223n/a self._check_str_subclass('a/b.txt')
224n/a self._check_str_subclass('/a/b.txt')
225n/a
226n/a def test_join_common(self):
227n/a P = self.cls
228n/a p = P('a/b')
229n/a pp = p.joinpath('c')
230n/a self.assertEqual(pp, P('a/b/c'))
231n/a self.assertIs(type(pp), type(p))
232n/a pp = p.joinpath('c', 'd')
233n/a self.assertEqual(pp, P('a/b/c/d'))
234n/a pp = p.joinpath(P('c'))
235n/a self.assertEqual(pp, P('a/b/c'))
236n/a pp = p.joinpath('/c')
237n/a self.assertEqual(pp, P('/c'))
238n/a
239n/a def test_div_common(self):
240n/a # Basically the same as joinpath()
241n/a P = self.cls
242n/a p = P('a/b')
243n/a pp = p / 'c'
244n/a self.assertEqual(pp, P('a/b/c'))
245n/a self.assertIs(type(pp), type(p))
246n/a pp = p / 'c/d'
247n/a self.assertEqual(pp, P('a/b/c/d'))
248n/a pp = p / 'c' / 'd'
249n/a self.assertEqual(pp, P('a/b/c/d'))
250n/a pp = 'c' / p / 'd'
251n/a self.assertEqual(pp, P('c/a/b/d'))
252n/a pp = p / P('c')
253n/a self.assertEqual(pp, P('a/b/c'))
254n/a pp = p/ '/c'
255n/a self.assertEqual(pp, P('/c'))
256n/a
257n/a def _check_str(self, expected, args):
258n/a p = self.cls(*args)
259n/a self.assertEqual(str(p), expected.replace('/', self.sep))
260n/a
261n/a def test_str_common(self):
262n/a # Canonicalized paths roundtrip
263n/a for pathstr in ('a', 'a/b', 'a/b/c', '/', '/a/b', '/a/b/c'):
264n/a self._check_str(pathstr, (pathstr,))
265n/a # Special case for the empty path
266n/a self._check_str('.', ('',))
267n/a # Other tests for str() are in test_equivalences()
268n/a
269n/a def test_as_posix_common(self):
270n/a P = self.cls
271n/a for pathstr in ('a', 'a/b', 'a/b/c', '/', '/a/b', '/a/b/c'):
272n/a self.assertEqual(P(pathstr).as_posix(), pathstr)
273n/a # Other tests for as_posix() are in test_equivalences()
274n/a
275n/a def test_as_bytes_common(self):
276n/a sep = os.fsencode(self.sep)
277n/a P = self.cls
278n/a self.assertEqual(bytes(P('a/b')), b'a' + sep + b'b')
279n/a
280n/a def test_as_uri_common(self):
281n/a P = self.cls
282n/a with self.assertRaises(ValueError):
283n/a P('a').as_uri()
284n/a with self.assertRaises(ValueError):
285n/a P().as_uri()
286n/a
287n/a def test_repr_common(self):
288n/a for pathstr in ('a', 'a/b', 'a/b/c', '/', '/a/b', '/a/b/c'):
289n/a p = self.cls(pathstr)
290n/a clsname = p.__class__.__name__
291n/a r = repr(p)
292n/a # The repr() is in the form ClassName("forward-slashes path")
293n/a self.assertTrue(r.startswith(clsname + '('), r)
294n/a self.assertTrue(r.endswith(')'), r)
295n/a inner = r[len(clsname) + 1 : -1]
296n/a self.assertEqual(eval(inner), p.as_posix())
297n/a # The repr() roundtrips
298n/a q = eval(r, pathlib.__dict__)
299n/a self.assertIs(q.__class__, p.__class__)
300n/a self.assertEqual(q, p)
301n/a self.assertEqual(repr(q), r)
302n/a
303n/a def test_eq_common(self):
304n/a P = self.cls
305n/a self.assertEqual(P('a/b'), P('a/b'))
306n/a self.assertEqual(P('a/b'), P('a', 'b'))
307n/a self.assertNotEqual(P('a/b'), P('a'))
308n/a self.assertNotEqual(P('a/b'), P('/a/b'))
309n/a self.assertNotEqual(P('a/b'), P())
310n/a self.assertNotEqual(P('/a/b'), P('/'))
311n/a self.assertNotEqual(P(), P('/'))
312n/a self.assertNotEqual(P(), "")
313n/a self.assertNotEqual(P(), {})
314n/a self.assertNotEqual(P(), int)
315n/a
316n/a def test_match_common(self):
317n/a P = self.cls
318n/a self.assertRaises(ValueError, P('a').match, '')
319n/a self.assertRaises(ValueError, P('a').match, '.')
320n/a # Simple relative pattern
321n/a self.assertTrue(P('b.py').match('b.py'))
322n/a self.assertTrue(P('a/b.py').match('b.py'))
323n/a self.assertTrue(P('/a/b.py').match('b.py'))
324n/a self.assertFalse(P('a.py').match('b.py'))
325n/a self.assertFalse(P('b/py').match('b.py'))
326n/a self.assertFalse(P('/a.py').match('b.py'))
327n/a self.assertFalse(P('b.py/c').match('b.py'))
328n/a # Wilcard relative pattern
329n/a self.assertTrue(P('b.py').match('*.py'))
330n/a self.assertTrue(P('a/b.py').match('*.py'))
331n/a self.assertTrue(P('/a/b.py').match('*.py'))
332n/a self.assertFalse(P('b.pyc').match('*.py'))
333n/a self.assertFalse(P('b./py').match('*.py'))
334n/a self.assertFalse(P('b.py/c').match('*.py'))
335n/a # Multi-part relative pattern
336n/a self.assertTrue(P('ab/c.py').match('a*/*.py'))
337n/a self.assertTrue(P('/d/ab/c.py').match('a*/*.py'))
338n/a self.assertFalse(P('a.py').match('a*/*.py'))
339n/a self.assertFalse(P('/dab/c.py').match('a*/*.py'))
340n/a self.assertFalse(P('ab/c.py/d').match('a*/*.py'))
341n/a # Absolute pattern
342n/a self.assertTrue(P('/b.py').match('/*.py'))
343n/a self.assertFalse(P('b.py').match('/*.py'))
344n/a self.assertFalse(P('a/b.py').match('/*.py'))
345n/a self.assertFalse(P('/a/b.py').match('/*.py'))
346n/a # Multi-part absolute pattern
347n/a self.assertTrue(P('/a/b.py').match('/a/*.py'))
348n/a self.assertFalse(P('/ab.py').match('/a/*.py'))
349n/a self.assertFalse(P('/a/b/c.py').match('/a/*.py'))
350n/a
351n/a def test_ordering_common(self):
352n/a # Ordering is tuple-alike
353n/a def assertLess(a, b):
354n/a self.assertLess(a, b)
355n/a self.assertGreater(b, a)
356n/a P = self.cls
357n/a a = P('a')
358n/a b = P('a/b')
359n/a c = P('abc')
360n/a d = P('b')
361n/a assertLess(a, b)
362n/a assertLess(a, c)
363n/a assertLess(a, d)
364n/a assertLess(b, c)
365n/a assertLess(c, d)
366n/a P = self.cls
367n/a a = P('/a')
368n/a b = P('/a/b')
369n/a c = P('/abc')
370n/a d = P('/b')
371n/a assertLess(a, b)
372n/a assertLess(a, c)
373n/a assertLess(a, d)
374n/a assertLess(b, c)
375n/a assertLess(c, d)
376n/a with self.assertRaises(TypeError):
377n/a P() < {}
378n/a
379n/a def test_parts_common(self):
380n/a # `parts` returns a tuple
381n/a sep = self.sep
382n/a P = self.cls
383n/a p = P('a/b')
384n/a parts = p.parts
385n/a self.assertEqual(parts, ('a', 'b'))
386n/a # The object gets reused
387n/a self.assertIs(parts, p.parts)
388n/a # When the path is absolute, the anchor is a separate part
389n/a p = P('/a/b')
390n/a parts = p.parts
391n/a self.assertEqual(parts, (sep, 'a', 'b'))
392n/a
393n/a def test_fspath_common(self):
394n/a P = self.cls
395n/a p = P('a/b')
396n/a self._check_str(p.__fspath__(), ('a/b',))
397n/a self._check_str(os.fspath(p), ('a/b',))
398n/a
399n/a def test_equivalences(self):
400n/a for k, tuples in self.equivalences.items():
401n/a canon = k.replace('/', self.sep)
402n/a posix = k.replace(self.sep, '/')
403n/a if canon != posix:
404n/a tuples = tuples + [
405n/a tuple(part.replace('/', self.sep) for part in t)
406n/a for t in tuples
407n/a ]
408n/a tuples.append((posix, ))
409n/a pcanon = self.cls(canon)
410n/a for t in tuples:
411n/a p = self.cls(*t)
412n/a self.assertEqual(p, pcanon, "failed with args {}".format(t))
413n/a self.assertEqual(hash(p), hash(pcanon))
414n/a self.assertEqual(str(p), canon)
415n/a self.assertEqual(p.as_posix(), posix)
416n/a
417n/a def test_parent_common(self):
418n/a # Relative
419n/a P = self.cls
420n/a p = P('a/b/c')
421n/a self.assertEqual(p.parent, P('a/b'))
422n/a self.assertEqual(p.parent.parent, P('a'))
423n/a self.assertEqual(p.parent.parent.parent, P())
424n/a self.assertEqual(p.parent.parent.parent.parent, P())
425n/a # Anchored
426n/a p = P('/a/b/c')
427n/a self.assertEqual(p.parent, P('/a/b'))
428n/a self.assertEqual(p.parent.parent, P('/a'))
429n/a self.assertEqual(p.parent.parent.parent, P('/'))
430n/a self.assertEqual(p.parent.parent.parent.parent, P('/'))
431n/a
432n/a def test_parents_common(self):
433n/a # Relative
434n/a P = self.cls
435n/a p = P('a/b/c')
436n/a par = p.parents
437n/a self.assertEqual(len(par), 3)
438n/a self.assertEqual(par[0], P('a/b'))
439n/a self.assertEqual(par[1], P('a'))
440n/a self.assertEqual(par[2], P('.'))
441n/a self.assertEqual(list(par), [P('a/b'), P('a'), P('.')])
442n/a with self.assertRaises(IndexError):
443n/a par[-1]
444n/a with self.assertRaises(IndexError):
445n/a par[3]
446n/a with self.assertRaises(TypeError):
447n/a par[0] = p
448n/a # Anchored
449n/a p = P('/a/b/c')
450n/a par = p.parents
451n/a self.assertEqual(len(par), 3)
452n/a self.assertEqual(par[0], P('/a/b'))
453n/a self.assertEqual(par[1], P('/a'))
454n/a self.assertEqual(par[2], P('/'))
455n/a self.assertEqual(list(par), [P('/a/b'), P('/a'), P('/')])
456n/a with self.assertRaises(IndexError):
457n/a par[3]
458n/a
459n/a def test_drive_common(self):
460n/a P = self.cls
461n/a self.assertEqual(P('a/b').drive, '')
462n/a self.assertEqual(P('/a/b').drive, '')
463n/a self.assertEqual(P('').drive, '')
464n/a
465n/a def test_root_common(self):
466n/a P = self.cls
467n/a sep = self.sep
468n/a self.assertEqual(P('').root, '')
469n/a self.assertEqual(P('a/b').root, '')
470n/a self.assertEqual(P('/').root, sep)
471n/a self.assertEqual(P('/a/b').root, sep)
472n/a
473n/a def test_anchor_common(self):
474n/a P = self.cls
475n/a sep = self.sep
476n/a self.assertEqual(P('').anchor, '')
477n/a self.assertEqual(P('a/b').anchor, '')
478n/a self.assertEqual(P('/').anchor, sep)
479n/a self.assertEqual(P('/a/b').anchor, sep)
480n/a
481n/a def test_name_common(self):
482n/a P = self.cls
483n/a self.assertEqual(P('').name, '')
484n/a self.assertEqual(P('.').name, '')
485n/a self.assertEqual(P('/').name, '')
486n/a self.assertEqual(P('a/b').name, 'b')
487n/a self.assertEqual(P('/a/b').name, 'b')
488n/a self.assertEqual(P('/a/b/.').name, 'b')
489n/a self.assertEqual(P('a/b.py').name, 'b.py')
490n/a self.assertEqual(P('/a/b.py').name, 'b.py')
491n/a
492n/a def test_suffix_common(self):
493n/a P = self.cls
494n/a self.assertEqual(P('').suffix, '')
495n/a self.assertEqual(P('.').suffix, '')
496n/a self.assertEqual(P('..').suffix, '')
497n/a self.assertEqual(P('/').suffix, '')
498n/a self.assertEqual(P('a/b').suffix, '')
499n/a self.assertEqual(P('/a/b').suffix, '')
500n/a self.assertEqual(P('/a/b/.').suffix, '')
501n/a self.assertEqual(P('a/b.py').suffix, '.py')
502n/a self.assertEqual(P('/a/b.py').suffix, '.py')
503n/a self.assertEqual(P('a/.hgrc').suffix, '')
504n/a self.assertEqual(P('/a/.hgrc').suffix, '')
505n/a self.assertEqual(P('a/.hg.rc').suffix, '.rc')
506n/a self.assertEqual(P('/a/.hg.rc').suffix, '.rc')
507n/a self.assertEqual(P('a/b.tar.gz').suffix, '.gz')
508n/a self.assertEqual(P('/a/b.tar.gz').suffix, '.gz')
509n/a self.assertEqual(P('a/Some name. Ending with a dot.').suffix, '')
510n/a self.assertEqual(P('/a/Some name. Ending with a dot.').suffix, '')
511n/a
512n/a def test_suffixes_common(self):
513n/a P = self.cls
514n/a self.assertEqual(P('').suffixes, [])
515n/a self.assertEqual(P('.').suffixes, [])
516n/a self.assertEqual(P('/').suffixes, [])
517n/a self.assertEqual(P('a/b').suffixes, [])
518n/a self.assertEqual(P('/a/b').suffixes, [])
519n/a self.assertEqual(P('/a/b/.').suffixes, [])
520n/a self.assertEqual(P('a/b.py').suffixes, ['.py'])
521n/a self.assertEqual(P('/a/b.py').suffixes, ['.py'])
522n/a self.assertEqual(P('a/.hgrc').suffixes, [])
523n/a self.assertEqual(P('/a/.hgrc').suffixes, [])
524n/a self.assertEqual(P('a/.hg.rc').suffixes, ['.rc'])
525n/a self.assertEqual(P('/a/.hg.rc').suffixes, ['.rc'])
526n/a self.assertEqual(P('a/b.tar.gz').suffixes, ['.tar', '.gz'])
527n/a self.assertEqual(P('/a/b.tar.gz').suffixes, ['.tar', '.gz'])
528n/a self.assertEqual(P('a/Some name. Ending with a dot.').suffixes, [])
529n/a self.assertEqual(P('/a/Some name. Ending with a dot.').suffixes, [])
530n/a
531n/a def test_stem_common(self):
532n/a P = self.cls
533n/a self.assertEqual(P('').stem, '')
534n/a self.assertEqual(P('.').stem, '')
535n/a self.assertEqual(P('..').stem, '..')
536n/a self.assertEqual(P('/').stem, '')
537n/a self.assertEqual(P('a/b').stem, 'b')
538n/a self.assertEqual(P('a/b.py').stem, 'b')
539n/a self.assertEqual(P('a/.hgrc').stem, '.hgrc')
540n/a self.assertEqual(P('a/.hg.rc').stem, '.hg')
541n/a self.assertEqual(P('a/b.tar.gz').stem, 'b.tar')
542n/a self.assertEqual(P('a/Some name. Ending with a dot.').stem,
543n/a 'Some name. Ending with a dot.')
544n/a
545n/a def test_with_name_common(self):
546n/a P = self.cls
547n/a self.assertEqual(P('a/b').with_name('d.xml'), P('a/d.xml'))
548n/a self.assertEqual(P('/a/b').with_name('d.xml'), P('/a/d.xml'))
549n/a self.assertEqual(P('a/b.py').with_name('d.xml'), P('a/d.xml'))
550n/a self.assertEqual(P('/a/b.py').with_name('d.xml'), P('/a/d.xml'))
551n/a self.assertEqual(P('a/Dot ending.').with_name('d.xml'), P('a/d.xml'))
552n/a self.assertEqual(P('/a/Dot ending.').with_name('d.xml'), P('/a/d.xml'))
553n/a self.assertRaises(ValueError, P('').with_name, 'd.xml')
554n/a self.assertRaises(ValueError, P('.').with_name, 'd.xml')
555n/a self.assertRaises(ValueError, P('/').with_name, 'd.xml')
556n/a self.assertRaises(ValueError, P('a/b').with_name, '')
557n/a self.assertRaises(ValueError, P('a/b').with_name, '/c')
558n/a self.assertRaises(ValueError, P('a/b').with_name, 'c/')
559n/a self.assertRaises(ValueError, P('a/b').with_name, 'c/d')
560n/a
561n/a def test_with_suffix_common(self):
562n/a P = self.cls
563n/a self.assertEqual(P('a/b').with_suffix('.gz'), P('a/b.gz'))
564n/a self.assertEqual(P('/a/b').with_suffix('.gz'), P('/a/b.gz'))
565n/a self.assertEqual(P('a/b.py').with_suffix('.gz'), P('a/b.gz'))
566n/a self.assertEqual(P('/a/b.py').with_suffix('.gz'), P('/a/b.gz'))
567n/a # Stripping suffix
568n/a self.assertEqual(P('a/b.py').with_suffix(''), P('a/b'))
569n/a self.assertEqual(P('/a/b').with_suffix(''), P('/a/b'))
570n/a # Path doesn't have a "filename" component
571n/a self.assertRaises(ValueError, P('').with_suffix, '.gz')
572n/a self.assertRaises(ValueError, P('.').with_suffix, '.gz')
573n/a self.assertRaises(ValueError, P('/').with_suffix, '.gz')
574n/a # Invalid suffix
575n/a self.assertRaises(ValueError, P('a/b').with_suffix, 'gz')
576n/a self.assertRaises(ValueError, P('a/b').with_suffix, '/')
577n/a self.assertRaises(ValueError, P('a/b').with_suffix, '.')
578n/a self.assertRaises(ValueError, P('a/b').with_suffix, '/.gz')
579n/a self.assertRaises(ValueError, P('a/b').with_suffix, 'c/d')
580n/a self.assertRaises(ValueError, P('a/b').with_suffix, '.c/.d')
581n/a self.assertRaises(ValueError, P('a/b').with_suffix, './.d')
582n/a self.assertRaises(ValueError, P('a/b').with_suffix, '.d/.')
583n/a
584n/a def test_relative_to_common(self):
585n/a P = self.cls
586n/a p = P('a/b')
587n/a self.assertRaises(TypeError, p.relative_to)
588n/a self.assertRaises(TypeError, p.relative_to, b'a')
589n/a self.assertEqual(p.relative_to(P()), P('a/b'))
590n/a self.assertEqual(p.relative_to(''), P('a/b'))
591n/a self.assertEqual(p.relative_to(P('a')), P('b'))
592n/a self.assertEqual(p.relative_to('a'), P('b'))
593n/a self.assertEqual(p.relative_to('a/'), P('b'))
594n/a self.assertEqual(p.relative_to(P('a/b')), P())
595n/a self.assertEqual(p.relative_to('a/b'), P())
596n/a # With several args
597n/a self.assertEqual(p.relative_to('a', 'b'), P())
598n/a # Unrelated paths
599n/a self.assertRaises(ValueError, p.relative_to, P('c'))
600n/a self.assertRaises(ValueError, p.relative_to, P('a/b/c'))
601n/a self.assertRaises(ValueError, p.relative_to, P('a/c'))
602n/a self.assertRaises(ValueError, p.relative_to, P('/a'))
603n/a p = P('/a/b')
604n/a self.assertEqual(p.relative_to(P('/')), P('a/b'))
605n/a self.assertEqual(p.relative_to('/'), P('a/b'))
606n/a self.assertEqual(p.relative_to(P('/a')), P('b'))
607n/a self.assertEqual(p.relative_to('/a'), P('b'))
608n/a self.assertEqual(p.relative_to('/a/'), P('b'))
609n/a self.assertEqual(p.relative_to(P('/a/b')), P())
610n/a self.assertEqual(p.relative_to('/a/b'), P())
611n/a # Unrelated paths
612n/a self.assertRaises(ValueError, p.relative_to, P('/c'))
613n/a self.assertRaises(ValueError, p.relative_to, P('/a/b/c'))
614n/a self.assertRaises(ValueError, p.relative_to, P('/a/c'))
615n/a self.assertRaises(ValueError, p.relative_to, P())
616n/a self.assertRaises(ValueError, p.relative_to, '')
617n/a self.assertRaises(ValueError, p.relative_to, P('a'))
618n/a
619n/a def test_pickling_common(self):
620n/a P = self.cls
621n/a p = P('/a/b')
622n/a for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
623n/a dumped = pickle.dumps(p, proto)
624n/a pp = pickle.loads(dumped)
625n/a self.assertIs(pp.__class__, p.__class__)
626n/a self.assertEqual(pp, p)
627n/a self.assertEqual(hash(pp), hash(p))
628n/a self.assertEqual(str(pp), str(p))
629n/a
630n/a
631n/aclass PurePosixPathTest(_BasePurePathTest, unittest.TestCase):
632n/a cls = pathlib.PurePosixPath
633n/a
634n/a def test_root(self):
635n/a P = self.cls
636n/a self.assertEqual(P('/a/b').root, '/')
637n/a self.assertEqual(P('///a/b').root, '/')
638n/a # POSIX special case for two leading slashes
639n/a self.assertEqual(P('//a/b').root, '//')
640n/a
641n/a def test_eq(self):
642n/a P = self.cls
643n/a self.assertNotEqual(P('a/b'), P('A/b'))
644n/a self.assertEqual(P('/a'), P('///a'))
645n/a self.assertNotEqual(P('/a'), P('//a'))
646n/a
647n/a def test_as_uri(self):
648n/a P = self.cls
649n/a self.assertEqual(P('/').as_uri(), 'file:///')
650n/a self.assertEqual(P('/a/b.c').as_uri(), 'file:///a/b.c')
651n/a self.assertEqual(P('/a/b%#c').as_uri(), 'file:///a/b%25%23c')
652n/a
653n/a def test_as_uri_non_ascii(self):
654n/a from urllib.parse import quote_from_bytes
655n/a P = self.cls
656n/a try:
657n/a os.fsencode('\xe9')
658n/a except UnicodeEncodeError:
659n/a self.skipTest("\\xe9 cannot be encoded to the filesystem encoding")
660n/a self.assertEqual(P('/a/b\xe9').as_uri(),
661n/a 'file:///a/b' + quote_from_bytes(os.fsencode('\xe9')))
662n/a
663n/a def test_match(self):
664n/a P = self.cls
665n/a self.assertFalse(P('A.py').match('a.PY'))
666n/a
667n/a def test_is_absolute(self):
668n/a P = self.cls
669n/a self.assertFalse(P().is_absolute())
670n/a self.assertFalse(P('a').is_absolute())
671n/a self.assertFalse(P('a/b/').is_absolute())
672n/a self.assertTrue(P('/').is_absolute())
673n/a self.assertTrue(P('/a').is_absolute())
674n/a self.assertTrue(P('/a/b/').is_absolute())
675n/a self.assertTrue(P('//a').is_absolute())
676n/a self.assertTrue(P('//a/b').is_absolute())
677n/a
678n/a def test_is_reserved(self):
679n/a P = self.cls
680n/a self.assertIs(False, P('').is_reserved())
681n/a self.assertIs(False, P('/').is_reserved())
682n/a self.assertIs(False, P('/foo/bar').is_reserved())
683n/a self.assertIs(False, P('/dev/con/PRN/NUL').is_reserved())
684n/a
685n/a def test_join(self):
686n/a P = self.cls
687n/a p = P('//a')
688n/a pp = p.joinpath('b')
689n/a self.assertEqual(pp, P('//a/b'))
690n/a pp = P('/a').joinpath('//c')
691n/a self.assertEqual(pp, P('//c'))
692n/a pp = P('//a').joinpath('/c')
693n/a self.assertEqual(pp, P('/c'))
694n/a
695n/a def test_div(self):
696n/a # Basically the same as joinpath()
697n/a P = self.cls
698n/a p = P('//a')
699n/a pp = p / 'b'
700n/a self.assertEqual(pp, P('//a/b'))
701n/a pp = P('/a') / '//c'
702n/a self.assertEqual(pp, P('//c'))
703n/a pp = P('//a') / '/c'
704n/a self.assertEqual(pp, P('/c'))
705n/a
706n/a
707n/aclass PureWindowsPathTest(_BasePurePathTest, unittest.TestCase):
708n/a cls = pathlib.PureWindowsPath
709n/a
710n/a equivalences = _BasePurePathTest.equivalences.copy()
711n/a equivalences.update({
712n/a 'c:a': [ ('c:', 'a'), ('c:', 'a/'), ('/', 'c:', 'a') ],
713n/a 'c:/a': [
714n/a ('c:/', 'a'), ('c:', '/', 'a'), ('c:', '/a'),
715n/a ('/z', 'c:/', 'a'), ('//x/y', 'c:/', 'a'),
716n/a ],
717n/a '//a/b/': [ ('//a/b',) ],
718n/a '//a/b/c': [
719n/a ('//a/b', 'c'), ('//a/b/', 'c'),
720n/a ],
721n/a })
722n/a
723n/a def test_str(self):
724n/a p = self.cls('a/b/c')
725n/a self.assertEqual(str(p), 'a\\b\\c')
726n/a p = self.cls('c:/a/b/c')
727n/a self.assertEqual(str(p), 'c:\\a\\b\\c')
728n/a p = self.cls('//a/b')
729n/a self.assertEqual(str(p), '\\\\a\\b\\')
730n/a p = self.cls('//a/b/c')
731n/a self.assertEqual(str(p), '\\\\a\\b\\c')
732n/a p = self.cls('//a/b/c/d')
733n/a self.assertEqual(str(p), '\\\\a\\b\\c\\d')
734n/a
735n/a def test_str_subclass(self):
736n/a self._check_str_subclass('c:')
737n/a self._check_str_subclass('c:a')
738n/a self._check_str_subclass('c:a\\b.txt')
739n/a self._check_str_subclass('c:\\')
740n/a self._check_str_subclass('c:\\a')
741n/a self._check_str_subclass('c:\\a\\b.txt')
742n/a self._check_str_subclass('\\\\some\\share')
743n/a self._check_str_subclass('\\\\some\\share\\a')
744n/a self._check_str_subclass('\\\\some\\share\\a\\b.txt')
745n/a
746n/a def test_eq(self):
747n/a P = self.cls
748n/a self.assertEqual(P('c:a/b'), P('c:a/b'))
749n/a self.assertEqual(P('c:a/b'), P('c:', 'a', 'b'))
750n/a self.assertNotEqual(P('c:a/b'), P('d:a/b'))
751n/a self.assertNotEqual(P('c:a/b'), P('c:/a/b'))
752n/a self.assertNotEqual(P('/a/b'), P('c:/a/b'))
753n/a # Case-insensitivity
754n/a self.assertEqual(P('a/B'), P('A/b'))
755n/a self.assertEqual(P('C:a/B'), P('c:A/b'))
756n/a self.assertEqual(P('//Some/SHARE/a/B'), P('//somE/share/A/b'))
757n/a
758n/a def test_as_uri(self):
759n/a P = self.cls
760n/a with self.assertRaises(ValueError):
761n/a P('/a/b').as_uri()
762n/a with self.assertRaises(ValueError):
763n/a P('c:a/b').as_uri()
764n/a self.assertEqual(P('c:/').as_uri(), 'file:///c:/')
765n/a self.assertEqual(P('c:/a/b.c').as_uri(), 'file:///c:/a/b.c')
766n/a self.assertEqual(P('c:/a/b%#c').as_uri(), 'file:///c:/a/b%25%23c')
767n/a self.assertEqual(P('c:/a/b\xe9').as_uri(), 'file:///c:/a/b%C3%A9')
768n/a self.assertEqual(P('//some/share/').as_uri(), 'file://some/share/')
769n/a self.assertEqual(P('//some/share/a/b.c').as_uri(),
770n/a 'file://some/share/a/b.c')
771n/a self.assertEqual(P('//some/share/a/b%#c\xe9').as_uri(),
772n/a 'file://some/share/a/b%25%23c%C3%A9')
773n/a
774n/a def test_match_common(self):
775n/a P = self.cls
776n/a # Absolute patterns
777n/a self.assertTrue(P('c:/b.py').match('/*.py'))
778n/a self.assertTrue(P('c:/b.py').match('c:*.py'))
779n/a self.assertTrue(P('c:/b.py').match('c:/*.py'))
780n/a self.assertFalse(P('d:/b.py').match('c:/*.py')) # wrong drive
781n/a self.assertFalse(P('b.py').match('/*.py'))
782n/a self.assertFalse(P('b.py').match('c:*.py'))
783n/a self.assertFalse(P('b.py').match('c:/*.py'))
784n/a self.assertFalse(P('c:b.py').match('/*.py'))
785n/a self.assertFalse(P('c:b.py').match('c:/*.py'))
786n/a self.assertFalse(P('/b.py').match('c:*.py'))
787n/a self.assertFalse(P('/b.py').match('c:/*.py'))
788n/a # UNC patterns
789n/a self.assertTrue(P('//some/share/a.py').match('/*.py'))
790n/a self.assertTrue(P('//some/share/a.py').match('//some/share/*.py'))
791n/a self.assertFalse(P('//other/share/a.py').match('//some/share/*.py'))
792n/a self.assertFalse(P('//some/share/a/b.py').match('//some/share/*.py'))
793n/a # Case-insensitivity
794n/a self.assertTrue(P('B.py').match('b.PY'))
795n/a self.assertTrue(P('c:/a/B.Py').match('C:/A/*.pY'))
796n/a self.assertTrue(P('//Some/Share/B.Py').match('//somE/sharE/*.pY'))
797n/a
798n/a def test_ordering_common(self):
799n/a # Case-insensitivity
800n/a def assertOrderedEqual(a, b):
801n/a self.assertLessEqual(a, b)
802n/a self.assertGreaterEqual(b, a)
803n/a P = self.cls
804n/a p = P('c:A/b')
805n/a q = P('C:a/B')
806n/a assertOrderedEqual(p, q)
807n/a self.assertFalse(p < q)
808n/a self.assertFalse(p > q)
809n/a p = P('//some/Share/A/b')
810n/a q = P('//Some/SHARE/a/B')
811n/a assertOrderedEqual(p, q)
812n/a self.assertFalse(p < q)
813n/a self.assertFalse(p > q)
814n/a
815n/a def test_parts(self):
816n/a P = self.cls
817n/a p = P('c:a/b')
818n/a parts = p.parts
819n/a self.assertEqual(parts, ('c:', 'a', 'b'))
820n/a p = P('c:/a/b')
821n/a parts = p.parts
822n/a self.assertEqual(parts, ('c:\\', 'a', 'b'))
823n/a p = P('//a/b/c/d')
824n/a parts = p.parts
825n/a self.assertEqual(parts, ('\\\\a\\b\\', 'c', 'd'))
826n/a
827n/a def test_parent(self):
828n/a # Anchored
829n/a P = self.cls
830n/a p = P('z:a/b/c')
831n/a self.assertEqual(p.parent, P('z:a/b'))
832n/a self.assertEqual(p.parent.parent, P('z:a'))
833n/a self.assertEqual(p.parent.parent.parent, P('z:'))
834n/a self.assertEqual(p.parent.parent.parent.parent, P('z:'))
835n/a p = P('z:/a/b/c')
836n/a self.assertEqual(p.parent, P('z:/a/b'))
837n/a self.assertEqual(p.parent.parent, P('z:/a'))
838n/a self.assertEqual(p.parent.parent.parent, P('z:/'))
839n/a self.assertEqual(p.parent.parent.parent.parent, P('z:/'))
840n/a p = P('//a/b/c/d')
841n/a self.assertEqual(p.parent, P('//a/b/c'))
842n/a self.assertEqual(p.parent.parent, P('//a/b'))
843n/a self.assertEqual(p.parent.parent.parent, P('//a/b'))
844n/a
845n/a def test_parents(self):
846n/a # Anchored
847n/a P = self.cls
848n/a p = P('z:a/b/')
849n/a par = p.parents
850n/a self.assertEqual(len(par), 2)
851n/a self.assertEqual(par[0], P('z:a'))
852n/a self.assertEqual(par[1], P('z:'))
853n/a self.assertEqual(list(par), [P('z:a'), P('z:')])
854n/a with self.assertRaises(IndexError):
855n/a par[2]
856n/a p = P('z:/a/b/')
857n/a par = p.parents
858n/a self.assertEqual(len(par), 2)
859n/a self.assertEqual(par[0], P('z:/a'))
860n/a self.assertEqual(par[1], P('z:/'))
861n/a self.assertEqual(list(par), [P('z:/a'), P('z:/')])
862n/a with self.assertRaises(IndexError):
863n/a par[2]
864n/a p = P('//a/b/c/d')
865n/a par = p.parents
866n/a self.assertEqual(len(par), 2)
867n/a self.assertEqual(par[0], P('//a/b/c'))
868n/a self.assertEqual(par[1], P('//a/b'))
869n/a self.assertEqual(list(par), [P('//a/b/c'), P('//a/b')])
870n/a with self.assertRaises(IndexError):
871n/a par[2]
872n/a
873n/a def test_drive(self):
874n/a P = self.cls
875n/a self.assertEqual(P('c:').drive, 'c:')
876n/a self.assertEqual(P('c:a/b').drive, 'c:')
877n/a self.assertEqual(P('c:/').drive, 'c:')
878n/a self.assertEqual(P('c:/a/b/').drive, 'c:')
879n/a self.assertEqual(P('//a/b').drive, '\\\\a\\b')
880n/a self.assertEqual(P('//a/b/').drive, '\\\\a\\b')
881n/a self.assertEqual(P('//a/b/c/d').drive, '\\\\a\\b')
882n/a
883n/a def test_root(self):
884n/a P = self.cls
885n/a self.assertEqual(P('c:').root, '')
886n/a self.assertEqual(P('c:a/b').root, '')
887n/a self.assertEqual(P('c:/').root, '\\')
888n/a self.assertEqual(P('c:/a/b/').root, '\\')
889n/a self.assertEqual(P('//a/b').root, '\\')
890n/a self.assertEqual(P('//a/b/').root, '\\')
891n/a self.assertEqual(P('//a/b/c/d').root, '\\')
892n/a
893n/a def test_anchor(self):
894n/a P = self.cls
895n/a self.assertEqual(P('c:').anchor, 'c:')
896n/a self.assertEqual(P('c:a/b').anchor, 'c:')
897n/a self.assertEqual(P('c:/').anchor, 'c:\\')
898n/a self.assertEqual(P('c:/a/b/').anchor, 'c:\\')
899n/a self.assertEqual(P('//a/b').anchor, '\\\\a\\b\\')
900n/a self.assertEqual(P('//a/b/').anchor, '\\\\a\\b\\')
901n/a self.assertEqual(P('//a/b/c/d').anchor, '\\\\a\\b\\')
902n/a
903n/a def test_name(self):
904n/a P = self.cls
905n/a self.assertEqual(P('c:').name, '')
906n/a self.assertEqual(P('c:/').name, '')
907n/a self.assertEqual(P('c:a/b').name, 'b')
908n/a self.assertEqual(P('c:/a/b').name, 'b')
909n/a self.assertEqual(P('c:a/b.py').name, 'b.py')
910n/a self.assertEqual(P('c:/a/b.py').name, 'b.py')
911n/a self.assertEqual(P('//My.py/Share.php').name, '')
912n/a self.assertEqual(P('//My.py/Share.php/a/b').name, 'b')
913n/a
914n/a def test_suffix(self):
915n/a P = self.cls
916n/a self.assertEqual(P('c:').suffix, '')
917n/a self.assertEqual(P('c:/').suffix, '')
918n/a self.assertEqual(P('c:a/b').suffix, '')
919n/a self.assertEqual(P('c:/a/b').suffix, '')
920n/a self.assertEqual(P('c:a/b.py').suffix, '.py')
921n/a self.assertEqual(P('c:/a/b.py').suffix, '.py')
922n/a self.assertEqual(P('c:a/.hgrc').suffix, '')
923n/a self.assertEqual(P('c:/a/.hgrc').suffix, '')
924n/a self.assertEqual(P('c:a/.hg.rc').suffix, '.rc')
925n/a self.assertEqual(P('c:/a/.hg.rc').suffix, '.rc')
926n/a self.assertEqual(P('c:a/b.tar.gz').suffix, '.gz')
927n/a self.assertEqual(P('c:/a/b.tar.gz').suffix, '.gz')
928n/a self.assertEqual(P('c:a/Some name. Ending with a dot.').suffix, '')
929n/a self.assertEqual(P('c:/a/Some name. Ending with a dot.').suffix, '')
930n/a self.assertEqual(P('//My.py/Share.php').suffix, '')
931n/a self.assertEqual(P('//My.py/Share.php/a/b').suffix, '')
932n/a
933n/a def test_suffixes(self):
934n/a P = self.cls
935n/a self.assertEqual(P('c:').suffixes, [])
936n/a self.assertEqual(P('c:/').suffixes, [])
937n/a self.assertEqual(P('c:a/b').suffixes, [])
938n/a self.assertEqual(P('c:/a/b').suffixes, [])
939n/a self.assertEqual(P('c:a/b.py').suffixes, ['.py'])
940n/a self.assertEqual(P('c:/a/b.py').suffixes, ['.py'])
941n/a self.assertEqual(P('c:a/.hgrc').suffixes, [])
942n/a self.assertEqual(P('c:/a/.hgrc').suffixes, [])
943n/a self.assertEqual(P('c:a/.hg.rc').suffixes, ['.rc'])
944n/a self.assertEqual(P('c:/a/.hg.rc').suffixes, ['.rc'])
945n/a self.assertEqual(P('c:a/b.tar.gz').suffixes, ['.tar', '.gz'])
946n/a self.assertEqual(P('c:/a/b.tar.gz').suffixes, ['.tar', '.gz'])
947n/a self.assertEqual(P('//My.py/Share.php').suffixes, [])
948n/a self.assertEqual(P('//My.py/Share.php/a/b').suffixes, [])
949n/a self.assertEqual(P('c:a/Some name. Ending with a dot.').suffixes, [])
950n/a self.assertEqual(P('c:/a/Some name. Ending with a dot.').suffixes, [])
951n/a
952n/a def test_stem(self):
953n/a P = self.cls
954n/a self.assertEqual(P('c:').stem, '')
955n/a self.assertEqual(P('c:.').stem, '')
956n/a self.assertEqual(P('c:..').stem, '..')
957n/a self.assertEqual(P('c:/').stem, '')
958n/a self.assertEqual(P('c:a/b').stem, 'b')
959n/a self.assertEqual(P('c:a/b.py').stem, 'b')
960n/a self.assertEqual(P('c:a/.hgrc').stem, '.hgrc')
961n/a self.assertEqual(P('c:a/.hg.rc').stem, '.hg')
962n/a self.assertEqual(P('c:a/b.tar.gz').stem, 'b.tar')
963n/a self.assertEqual(P('c:a/Some name. Ending with a dot.').stem,
964n/a 'Some name. Ending with a dot.')
965n/a
966n/a def test_with_name(self):
967n/a P = self.cls
968n/a self.assertEqual(P('c:a/b').with_name('d.xml'), P('c:a/d.xml'))
969n/a self.assertEqual(P('c:/a/b').with_name('d.xml'), P('c:/a/d.xml'))
970n/a self.assertEqual(P('c:a/Dot ending.').with_name('d.xml'), P('c:a/d.xml'))
971n/a self.assertEqual(P('c:/a/Dot ending.').with_name('d.xml'), P('c:/a/d.xml'))
972n/a self.assertRaises(ValueError, P('c:').with_name, 'd.xml')
973n/a self.assertRaises(ValueError, P('c:/').with_name, 'd.xml')
974n/a self.assertRaises(ValueError, P('//My/Share').with_name, 'd.xml')
975n/a self.assertRaises(ValueError, P('c:a/b').with_name, 'd:')
976n/a self.assertRaises(ValueError, P('c:a/b').with_name, 'd:e')
977n/a self.assertRaises(ValueError, P('c:a/b').with_name, 'd:/e')
978n/a self.assertRaises(ValueError, P('c:a/b').with_name, '//My/Share')
979n/a
980n/a def test_with_suffix(self):
981n/a P = self.cls
982n/a self.assertEqual(P('c:a/b').with_suffix('.gz'), P('c:a/b.gz'))
983n/a self.assertEqual(P('c:/a/b').with_suffix('.gz'), P('c:/a/b.gz'))
984n/a self.assertEqual(P('c:a/b.py').with_suffix('.gz'), P('c:a/b.gz'))
985n/a self.assertEqual(P('c:/a/b.py').with_suffix('.gz'), P('c:/a/b.gz'))
986n/a # Path doesn't have a "filename" component
987n/a self.assertRaises(ValueError, P('').with_suffix, '.gz')
988n/a self.assertRaises(ValueError, P('.').with_suffix, '.gz')
989n/a self.assertRaises(ValueError, P('/').with_suffix, '.gz')
990n/a self.assertRaises(ValueError, P('//My/Share').with_suffix, '.gz')
991n/a # Invalid suffix
992n/a self.assertRaises(ValueError, P('c:a/b').with_suffix, 'gz')
993n/a self.assertRaises(ValueError, P('c:a/b').with_suffix, '/')
994n/a self.assertRaises(ValueError, P('c:a/b').with_suffix, '\\')
995n/a self.assertRaises(ValueError, P('c:a/b').with_suffix, 'c:')
996n/a self.assertRaises(ValueError, P('c:a/b').with_suffix, '/.gz')
997n/a self.assertRaises(ValueError, P('c:a/b').with_suffix, '\\.gz')
998n/a self.assertRaises(ValueError, P('c:a/b').with_suffix, 'c:.gz')
999n/a self.assertRaises(ValueError, P('c:a/b').with_suffix, 'c/d')
1000n/a self.assertRaises(ValueError, P('c:a/b').with_suffix, 'c\\d')
1001n/a self.assertRaises(ValueError, P('c:a/b').with_suffix, '.c/d')
1002n/a self.assertRaises(ValueError, P('c:a/b').with_suffix, '.c\\d')
1003n/a
1004n/a def test_relative_to(self):
1005n/a P = self.cls
1006n/a p = P('C:Foo/Bar')
1007n/a self.assertEqual(p.relative_to(P('c:')), P('Foo/Bar'))
1008n/a self.assertEqual(p.relative_to('c:'), P('Foo/Bar'))
1009n/a self.assertEqual(p.relative_to(P('c:foO')), P('Bar'))
1010n/a self.assertEqual(p.relative_to('c:foO'), P('Bar'))
1011n/a self.assertEqual(p.relative_to('c:foO/'), P('Bar'))
1012n/a self.assertEqual(p.relative_to(P('c:foO/baR')), P())
1013n/a self.assertEqual(p.relative_to('c:foO/baR'), P())
1014n/a # Unrelated paths
1015n/a self.assertRaises(ValueError, p.relative_to, P())
1016n/a self.assertRaises(ValueError, p.relative_to, '')
1017n/a self.assertRaises(ValueError, p.relative_to, P('d:'))
1018n/a self.assertRaises(ValueError, p.relative_to, P('/'))
1019n/a self.assertRaises(ValueError, p.relative_to, P('Foo'))
1020n/a self.assertRaises(ValueError, p.relative_to, P('/Foo'))
1021n/a self.assertRaises(ValueError, p.relative_to, P('C:/Foo'))
1022n/a self.assertRaises(ValueError, p.relative_to, P('C:Foo/Bar/Baz'))
1023n/a self.assertRaises(ValueError, p.relative_to, P('C:Foo/Baz'))
1024n/a p = P('C:/Foo/Bar')
1025n/a self.assertEqual(p.relative_to(P('c:')), P('/Foo/Bar'))
1026n/a self.assertEqual(p.relative_to('c:'), P('/Foo/Bar'))
1027n/a self.assertEqual(str(p.relative_to(P('c:'))), '\\Foo\\Bar')
1028n/a self.assertEqual(str(p.relative_to('c:')), '\\Foo\\Bar')
1029n/a self.assertEqual(p.relative_to(P('c:/')), P('Foo/Bar'))
1030n/a self.assertEqual(p.relative_to('c:/'), P('Foo/Bar'))
1031n/a self.assertEqual(p.relative_to(P('c:/foO')), P('Bar'))
1032n/a self.assertEqual(p.relative_to('c:/foO'), P('Bar'))
1033n/a self.assertEqual(p.relative_to('c:/foO/'), P('Bar'))
1034n/a self.assertEqual(p.relative_to(P('c:/foO/baR')), P())
1035n/a self.assertEqual(p.relative_to('c:/foO/baR'), P())
1036n/a # Unrelated paths
1037n/a self.assertRaises(ValueError, p.relative_to, P('C:/Baz'))
1038n/a self.assertRaises(ValueError, p.relative_to, P('C:/Foo/Bar/Baz'))
1039n/a self.assertRaises(ValueError, p.relative_to, P('C:/Foo/Baz'))
1040n/a self.assertRaises(ValueError, p.relative_to, P('C:Foo'))
1041n/a self.assertRaises(ValueError, p.relative_to, P('d:'))
1042n/a self.assertRaises(ValueError, p.relative_to, P('d:/'))
1043n/a self.assertRaises(ValueError, p.relative_to, P('/'))
1044n/a self.assertRaises(ValueError, p.relative_to, P('/Foo'))
1045n/a self.assertRaises(ValueError, p.relative_to, P('//C/Foo'))
1046n/a # UNC paths
1047n/a p = P('//Server/Share/Foo/Bar')
1048n/a self.assertEqual(p.relative_to(P('//sErver/sHare')), P('Foo/Bar'))
1049n/a self.assertEqual(p.relative_to('//sErver/sHare'), P('Foo/Bar'))
1050n/a self.assertEqual(p.relative_to('//sErver/sHare/'), P('Foo/Bar'))
1051n/a self.assertEqual(p.relative_to(P('//sErver/sHare/Foo')), P('Bar'))
1052n/a self.assertEqual(p.relative_to('//sErver/sHare/Foo'), P('Bar'))
1053n/a self.assertEqual(p.relative_to('//sErver/sHare/Foo/'), P('Bar'))
1054n/a self.assertEqual(p.relative_to(P('//sErver/sHare/Foo/Bar')), P())
1055n/a self.assertEqual(p.relative_to('//sErver/sHare/Foo/Bar'), P())
1056n/a # Unrelated paths
1057n/a self.assertRaises(ValueError, p.relative_to, P('/Server/Share/Foo'))
1058n/a self.assertRaises(ValueError, p.relative_to, P('c:/Server/Share/Foo'))
1059n/a self.assertRaises(ValueError, p.relative_to, P('//z/Share/Foo'))
1060n/a self.assertRaises(ValueError, p.relative_to, P('//Server/z/Foo'))
1061n/a
1062n/a def test_is_absolute(self):
1063n/a P = self.cls
1064n/a # Under NT, only paths with both a drive and a root are absolute
1065n/a self.assertFalse(P().is_absolute())
1066n/a self.assertFalse(P('a').is_absolute())
1067n/a self.assertFalse(P('a/b/').is_absolute())
1068n/a self.assertFalse(P('/').is_absolute())
1069n/a self.assertFalse(P('/a').is_absolute())
1070n/a self.assertFalse(P('/a/b/').is_absolute())
1071n/a self.assertFalse(P('c:').is_absolute())
1072n/a self.assertFalse(P('c:a').is_absolute())
1073n/a self.assertFalse(P('c:a/b/').is_absolute())
1074n/a self.assertTrue(P('c:/').is_absolute())
1075n/a self.assertTrue(P('c:/a').is_absolute())
1076n/a self.assertTrue(P('c:/a/b/').is_absolute())
1077n/a # UNC paths are absolute by definition
1078n/a self.assertTrue(P('//a/b').is_absolute())
1079n/a self.assertTrue(P('//a/b/').is_absolute())
1080n/a self.assertTrue(P('//a/b/c').is_absolute())
1081n/a self.assertTrue(P('//a/b/c/d').is_absolute())
1082n/a
1083n/a def test_join(self):
1084n/a P = self.cls
1085n/a p = P('C:/a/b')
1086n/a pp = p.joinpath('x/y')
1087n/a self.assertEqual(pp, P('C:/a/b/x/y'))
1088n/a pp = p.joinpath('/x/y')
1089n/a self.assertEqual(pp, P('C:/x/y'))
1090n/a # Joining with a different drive => the first path is ignored, even
1091n/a # if the second path is relative.
1092n/a pp = p.joinpath('D:x/y')
1093n/a self.assertEqual(pp, P('D:x/y'))
1094n/a pp = p.joinpath('D:/x/y')
1095n/a self.assertEqual(pp, P('D:/x/y'))
1096n/a pp = p.joinpath('//host/share/x/y')
1097n/a self.assertEqual(pp, P('//host/share/x/y'))
1098n/a # Joining with the same drive => the first path is appended to if
1099n/a # the second path is relative.
1100n/a pp = p.joinpath('c:x/y')
1101n/a self.assertEqual(pp, P('C:/a/b/x/y'))
1102n/a pp = p.joinpath('c:/x/y')
1103n/a self.assertEqual(pp, P('C:/x/y'))
1104n/a
1105n/a def test_div(self):
1106n/a # Basically the same as joinpath()
1107n/a P = self.cls
1108n/a p = P('C:/a/b')
1109n/a self.assertEqual(p / 'x/y', P('C:/a/b/x/y'))
1110n/a self.assertEqual(p / 'x' / 'y', P('C:/a/b/x/y'))
1111n/a self.assertEqual(p / '/x/y', P('C:/x/y'))
1112n/a self.assertEqual(p / '/x' / 'y', P('C:/x/y'))
1113n/a # Joining with a different drive => the first path is ignored, even
1114n/a # if the second path is relative.
1115n/a self.assertEqual(p / 'D:x/y', P('D:x/y'))
1116n/a self.assertEqual(p / 'D:' / 'x/y', P('D:x/y'))
1117n/a self.assertEqual(p / 'D:/x/y', P('D:/x/y'))
1118n/a self.assertEqual(p / 'D:' / '/x/y', P('D:/x/y'))
1119n/a self.assertEqual(p / '//host/share/x/y', P('//host/share/x/y'))
1120n/a # Joining with the same drive => the first path is appended to if
1121n/a # the second path is relative.
1122n/a self.assertEqual(p / 'c:x/y', P('C:/a/b/x/y'))
1123n/a self.assertEqual(p / 'c:/x/y', P('C:/x/y'))
1124n/a
1125n/a def test_is_reserved(self):
1126n/a P = self.cls
1127n/a self.assertIs(False, P('').is_reserved())
1128n/a self.assertIs(False, P('/').is_reserved())
1129n/a self.assertIs(False, P('/foo/bar').is_reserved())
1130n/a self.assertIs(True, P('con').is_reserved())
1131n/a self.assertIs(True, P('NUL').is_reserved())
1132n/a self.assertIs(True, P('NUL.txt').is_reserved())
1133n/a self.assertIs(True, P('com1').is_reserved())
1134n/a self.assertIs(True, P('com9.bar').is_reserved())
1135n/a self.assertIs(False, P('bar.com9').is_reserved())
1136n/a self.assertIs(True, P('lpt1').is_reserved())
1137n/a self.assertIs(True, P('lpt9.bar').is_reserved())
1138n/a self.assertIs(False, P('bar.lpt9').is_reserved())
1139n/a # Only the last component matters
1140n/a self.assertIs(False, P('c:/NUL/con/baz').is_reserved())
1141n/a # UNC paths are never reserved
1142n/a self.assertIs(False, P('//my/share/nul/con/aux').is_reserved())
1143n/a
1144n/aclass PurePathTest(_BasePurePathTest, unittest.TestCase):
1145n/a cls = pathlib.PurePath
1146n/a
1147n/a def test_concrete_class(self):
1148n/a p = self.cls('a')
1149n/a self.assertIs(type(p),
1150n/a pathlib.PureWindowsPath if os.name == 'nt' else pathlib.PurePosixPath)
1151n/a
1152n/a def test_different_flavours_unequal(self):
1153n/a p = pathlib.PurePosixPath('a')
1154n/a q = pathlib.PureWindowsPath('a')
1155n/a self.assertNotEqual(p, q)
1156n/a
1157n/a def test_different_flavours_unordered(self):
1158n/a p = pathlib.PurePosixPath('a')
1159n/a q = pathlib.PureWindowsPath('a')
1160n/a with self.assertRaises(TypeError):
1161n/a p < q
1162n/a with self.assertRaises(TypeError):
1163n/a p <= q
1164n/a with self.assertRaises(TypeError):
1165n/a p > q
1166n/a with self.assertRaises(TypeError):
1167n/a p >= q
1168n/a
1169n/a
1170n/a#
1171n/a# Tests for the concrete classes
1172n/a#
1173n/a
1174n/a# Make sure any symbolic links in the base test path are resolved
1175n/aBASE = os.path.realpath(TESTFN)
1176n/ajoin = lambda *x: os.path.join(BASE, *x)
1177n/arel_join = lambda *x: os.path.join(TESTFN, *x)
1178n/a
1179n/adef symlink_skip_reason():
1180n/a if not pathlib.supports_symlinks:
1181n/a return "no system support for symlinks"
1182n/a try:
1183n/a os.symlink(__file__, BASE)
1184n/a except OSError as e:
1185n/a return str(e)
1186n/a else:
1187n/a support.unlink(BASE)
1188n/a return None
1189n/a
1190n/asymlink_skip_reason = symlink_skip_reason()
1191n/a
1192n/aonly_nt = unittest.skipIf(os.name != 'nt',
1193n/a 'test requires a Windows-compatible system')
1194n/aonly_posix = unittest.skipIf(os.name == 'nt',
1195n/a 'test requires a POSIX-compatible system')
1196n/awith_symlinks = unittest.skipIf(symlink_skip_reason, symlink_skip_reason)
1197n/a
1198n/a
1199n/a@only_posix
1200n/aclass PosixPathAsPureTest(PurePosixPathTest):
1201n/a cls = pathlib.PosixPath
1202n/a
1203n/a@only_nt
1204n/aclass WindowsPathAsPureTest(PureWindowsPathTest):
1205n/a cls = pathlib.WindowsPath
1206n/a
1207n/a def test_owner(self):
1208n/a P = self.cls
1209n/a with self.assertRaises(NotImplementedError):
1210n/a P('c:/').owner()
1211n/a
1212n/a def test_group(self):
1213n/a P = self.cls
1214n/a with self.assertRaises(NotImplementedError):
1215n/a P('c:/').group()
1216n/a
1217n/a
1218n/aclass _BasePathTest(object):
1219n/a """Tests for the FS-accessing functionalities of the Path classes."""
1220n/a
1221n/a # (BASE)
1222n/a # |
1223n/a # |-- brokenLink -> non-existing
1224n/a # |-- dirA
1225n/a # | `-- linkC -> ../dirB
1226n/a # |-- dirB
1227n/a # | |-- fileB
1228n/a # | `-- linkD -> ../dirB
1229n/a # |-- dirC
1230n/a # | |-- dirD
1231n/a # | | `-- fileD
1232n/a # | `-- fileC
1233n/a # |-- dirE # No permissions
1234n/a # |-- fileA
1235n/a # |-- linkA -> fileA
1236n/a # `-- linkB -> dirB
1237n/a #
1238n/a
1239n/a def setUp(self):
1240n/a def cleanup():
1241n/a os.chmod(join('dirE'), 0o777)
1242n/a support.rmtree(BASE)
1243n/a self.addCleanup(cleanup)
1244n/a os.mkdir(BASE)
1245n/a os.mkdir(join('dirA'))
1246n/a os.mkdir(join('dirB'))
1247n/a os.mkdir(join('dirC'))
1248n/a os.mkdir(join('dirC', 'dirD'))
1249n/a os.mkdir(join('dirE'))
1250n/a with open(join('fileA'), 'wb') as f:
1251n/a f.write(b"this is file A\n")
1252n/a with open(join('dirB', 'fileB'), 'wb') as f:
1253n/a f.write(b"this is file B\n")
1254n/a with open(join('dirC', 'fileC'), 'wb') as f:
1255n/a f.write(b"this is file C\n")
1256n/a with open(join('dirC', 'dirD', 'fileD'), 'wb') as f:
1257n/a f.write(b"this is file D\n")
1258n/a os.chmod(join('dirE'), 0)
1259n/a if not symlink_skip_reason:
1260n/a # Relative symlinks
1261n/a os.symlink('fileA', join('linkA'))
1262n/a os.symlink('non-existing', join('brokenLink'))
1263n/a self.dirlink('dirB', join('linkB'))
1264n/a self.dirlink(os.path.join('..', 'dirB'), join('dirA', 'linkC'))
1265n/a # This one goes upwards, creating a loop
1266n/a self.dirlink(os.path.join('..', 'dirB'), join('dirB', 'linkD'))
1267n/a
1268n/a if os.name == 'nt':
1269n/a # Workaround for http://bugs.python.org/issue13772
1270n/a def dirlink(self, src, dest):
1271n/a os.symlink(src, dest, target_is_directory=True)
1272n/a else:
1273n/a def dirlink(self, src, dest):
1274n/a os.symlink(src, dest)
1275n/a
1276n/a def assertSame(self, path_a, path_b):
1277n/a self.assertTrue(os.path.samefile(str(path_a), str(path_b)),
1278n/a "%r and %r don't point to the same file" %
1279n/a (path_a, path_b))
1280n/a
1281n/a def assertFileNotFound(self, func, *args, **kwargs):
1282n/a with self.assertRaises(FileNotFoundError) as cm:
1283n/a func(*args, **kwargs)
1284n/a self.assertEqual(cm.exception.errno, errno.ENOENT)
1285n/a
1286n/a def _test_cwd(self, p):
1287n/a q = self.cls(os.getcwd())
1288n/a self.assertEqual(p, q)
1289n/a self.assertEqual(str(p), str(q))
1290n/a self.assertIs(type(p), type(q))
1291n/a self.assertTrue(p.is_absolute())
1292n/a
1293n/a def test_cwd(self):
1294n/a p = self.cls.cwd()
1295n/a self._test_cwd(p)
1296n/a
1297n/a def _test_home(self, p):
1298n/a q = self.cls(os.path.expanduser('~'))
1299n/a self.assertEqual(p, q)
1300n/a self.assertEqual(str(p), str(q))
1301n/a self.assertIs(type(p), type(q))
1302n/a self.assertTrue(p.is_absolute())
1303n/a
1304n/a def test_home(self):
1305n/a p = self.cls.home()
1306n/a self._test_home(p)
1307n/a
1308n/a def test_samefile(self):
1309n/a fileA_path = os.path.join(BASE, 'fileA')
1310n/a fileB_path = os.path.join(BASE, 'dirB', 'fileB')
1311n/a p = self.cls(fileA_path)
1312n/a pp = self.cls(fileA_path)
1313n/a q = self.cls(fileB_path)
1314n/a self.assertTrue(p.samefile(fileA_path))
1315n/a self.assertTrue(p.samefile(pp))
1316n/a self.assertFalse(p.samefile(fileB_path))
1317n/a self.assertFalse(p.samefile(q))
1318n/a # Test the non-existent file case
1319n/a non_existent = os.path.join(BASE, 'foo')
1320n/a r = self.cls(non_existent)
1321n/a self.assertRaises(FileNotFoundError, p.samefile, r)
1322n/a self.assertRaises(FileNotFoundError, p.samefile, non_existent)
1323n/a self.assertRaises(FileNotFoundError, r.samefile, p)
1324n/a self.assertRaises(FileNotFoundError, r.samefile, non_existent)
1325n/a self.assertRaises(FileNotFoundError, r.samefile, r)
1326n/a self.assertRaises(FileNotFoundError, r.samefile, non_existent)
1327n/a
1328n/a def test_empty_path(self):
1329n/a # The empty path points to '.'
1330n/a p = self.cls('')
1331n/a self.assertEqual(p.stat(), os.stat('.'))
1332n/a
1333n/a def test_expanduser_common(self):
1334n/a P = self.cls
1335n/a p = P('~')
1336n/a self.assertEqual(p.expanduser(), P(os.path.expanduser('~')))
1337n/a p = P('foo')
1338n/a self.assertEqual(p.expanduser(), p)
1339n/a p = P('/~')
1340n/a self.assertEqual(p.expanduser(), p)
1341n/a p = P('../~')
1342n/a self.assertEqual(p.expanduser(), p)
1343n/a p = P(P('').absolute().anchor) / '~'
1344n/a self.assertEqual(p.expanduser(), p)
1345n/a
1346n/a def test_exists(self):
1347n/a P = self.cls
1348n/a p = P(BASE)
1349n/a self.assertIs(True, p.exists())
1350n/a self.assertIs(True, (p / 'dirA').exists())
1351n/a self.assertIs(True, (p / 'fileA').exists())
1352n/a self.assertIs(False, (p / 'fileA' / 'bah').exists())
1353n/a if not symlink_skip_reason:
1354n/a self.assertIs(True, (p / 'linkA').exists())
1355n/a self.assertIs(True, (p / 'linkB').exists())
1356n/a self.assertIs(True, (p / 'linkB' / 'fileB').exists())
1357n/a self.assertIs(False, (p / 'linkA' / 'bah').exists())
1358n/a self.assertIs(False, (p / 'foo').exists())
1359n/a self.assertIs(False, P('/xyzzy').exists())
1360n/a
1361n/a def test_open_common(self):
1362n/a p = self.cls(BASE)
1363n/a with (p / 'fileA').open('r') as f:
1364n/a self.assertIsInstance(f, io.TextIOBase)
1365n/a self.assertEqual(f.read(), "this is file A\n")
1366n/a with (p / 'fileA').open('rb') as f:
1367n/a self.assertIsInstance(f, io.BufferedIOBase)
1368n/a self.assertEqual(f.read().strip(), b"this is file A")
1369n/a with (p / 'fileA').open('rb', buffering=0) as f:
1370n/a self.assertIsInstance(f, io.RawIOBase)
1371n/a self.assertEqual(f.read().strip(), b"this is file A")
1372n/a
1373n/a def test_read_write_bytes(self):
1374n/a p = self.cls(BASE)
1375n/a (p / 'fileA').write_bytes(b'abcdefg')
1376n/a self.assertEqual((p / 'fileA').read_bytes(), b'abcdefg')
1377n/a # check that trying to write str does not truncate the file
1378n/a self.assertRaises(TypeError, (p / 'fileA').write_bytes, 'somestr')
1379n/a self.assertEqual((p / 'fileA').read_bytes(), b'abcdefg')
1380n/a
1381n/a def test_read_write_text(self):
1382n/a p = self.cls(BASE)
1383n/a (p / 'fileA').write_text('äbcdefg', encoding='latin-1')
1384n/a self.assertEqual((p / 'fileA').read_text(
1385n/a encoding='utf-8', errors='ignore'), 'bcdefg')
1386n/a # check that trying to write bytes does not truncate the file
1387n/a self.assertRaises(TypeError, (p / 'fileA').write_text, b'somebytes')
1388n/a self.assertEqual((p / 'fileA').read_text(encoding='latin-1'), 'äbcdefg')
1389n/a
1390n/a def test_iterdir(self):
1391n/a P = self.cls
1392n/a p = P(BASE)
1393n/a it = p.iterdir()
1394n/a paths = set(it)
1395n/a expected = ['dirA', 'dirB', 'dirC', 'dirE', 'fileA']
1396n/a if not symlink_skip_reason:
1397n/a expected += ['linkA', 'linkB', 'brokenLink']
1398n/a self.assertEqual(paths, { P(BASE, q) for q in expected })
1399n/a
1400n/a @with_symlinks
1401n/a def test_iterdir_symlink(self):
1402n/a # __iter__ on a symlink to a directory
1403n/a P = self.cls
1404n/a p = P(BASE, 'linkB')
1405n/a paths = set(p.iterdir())
1406n/a expected = { P(BASE, 'linkB', q) for q in ['fileB', 'linkD'] }
1407n/a self.assertEqual(paths, expected)
1408n/a
1409n/a def test_iterdir_nodir(self):
1410n/a # __iter__ on something that is not a directory
1411n/a p = self.cls(BASE, 'fileA')
1412n/a with self.assertRaises(OSError) as cm:
1413n/a next(p.iterdir())
1414n/a # ENOENT or EINVAL under Windows, ENOTDIR otherwise
1415n/a # (see issue #12802)
1416n/a self.assertIn(cm.exception.errno, (errno.ENOTDIR,
1417n/a errno.ENOENT, errno.EINVAL))
1418n/a
1419n/a def test_glob_common(self):
1420n/a def _check(glob, expected):
1421n/a self.assertEqual(set(glob), { P(BASE, q) for q in expected })
1422n/a P = self.cls
1423n/a p = P(BASE)
1424n/a it = p.glob("fileA")
1425n/a self.assertIsInstance(it, collections.Iterator)
1426n/a _check(it, ["fileA"])
1427n/a _check(p.glob("fileB"), [])
1428n/a _check(p.glob("dir*/file*"), ["dirB/fileB", "dirC/fileC"])
1429n/a if symlink_skip_reason:
1430n/a _check(p.glob("*A"), ['dirA', 'fileA'])
1431n/a else:
1432n/a _check(p.glob("*A"), ['dirA', 'fileA', 'linkA'])
1433n/a if symlink_skip_reason:
1434n/a _check(p.glob("*B/*"), ['dirB/fileB'])
1435n/a else:
1436n/a _check(p.glob("*B/*"), ['dirB/fileB', 'dirB/linkD',
1437n/a 'linkB/fileB', 'linkB/linkD'])
1438n/a if symlink_skip_reason:
1439n/a _check(p.glob("*/fileB"), ['dirB/fileB'])
1440n/a else:
1441n/a _check(p.glob("*/fileB"), ['dirB/fileB', 'linkB/fileB'])
1442n/a
1443n/a def test_rglob_common(self):
1444n/a def _check(glob, expected):
1445n/a self.assertEqual(set(glob), { P(BASE, q) for q in expected })
1446n/a P = self.cls
1447n/a p = P(BASE)
1448n/a it = p.rglob("fileA")
1449n/a self.assertIsInstance(it, collections.Iterator)
1450n/a _check(it, ["fileA"])
1451n/a _check(p.rglob("fileB"), ["dirB/fileB"])
1452n/a _check(p.rglob("*/fileA"), [])
1453n/a if symlink_skip_reason:
1454n/a _check(p.rglob("*/fileB"), ["dirB/fileB"])
1455n/a else:
1456n/a _check(p.rglob("*/fileB"), ["dirB/fileB", "dirB/linkD/fileB",
1457n/a "linkB/fileB", "dirA/linkC/fileB"])
1458n/a _check(p.rglob("file*"), ["fileA", "dirB/fileB",
1459n/a "dirC/fileC", "dirC/dirD/fileD"])
1460n/a p = P(BASE, "dirC")
1461n/a _check(p.rglob("file*"), ["dirC/fileC", "dirC/dirD/fileD"])
1462n/a _check(p.rglob("*/*"), ["dirC/dirD/fileD"])
1463n/a
1464n/a @with_symlinks
1465n/a def test_rglob_symlink_loop(self):
1466n/a # Don't get fooled by symlink loops (Issue #26012)
1467n/a P = self.cls
1468n/a p = P(BASE)
1469n/a given = set(p.rglob('*'))
1470n/a expect = {'brokenLink',
1471n/a 'dirA', 'dirA/linkC',
1472n/a 'dirB', 'dirB/fileB', 'dirB/linkD',
1473n/a 'dirC', 'dirC/dirD', 'dirC/dirD/fileD', 'dirC/fileC',
1474n/a 'dirE',
1475n/a 'fileA',
1476n/a 'linkA',
1477n/a 'linkB',
1478n/a }
1479n/a self.assertEqual(given, {p / x for x in expect})
1480n/a
1481n/a def test_glob_dotdot(self):
1482n/a # ".." is not special in globs
1483n/a P = self.cls
1484n/a p = P(BASE)
1485n/a self.assertEqual(set(p.glob("..")), { P(BASE, "..") })
1486n/a self.assertEqual(set(p.glob("dirA/../file*")), { P(BASE, "dirA/../fileA") })
1487n/a self.assertEqual(set(p.glob("../xyzzy")), set())
1488n/a
1489n/a
1490n/a def _check_resolve(self, p, expected, strict=True):
1491n/a q = p.resolve(strict)
1492n/a self.assertEqual(q, expected)
1493n/a
1494n/a # this can be used to check both relative and absolute resolutions
1495n/a _check_resolve_relative = _check_resolve_absolute = _check_resolve
1496n/a
1497n/a @with_symlinks
1498n/a def test_resolve_common(self):
1499n/a P = self.cls
1500n/a p = P(BASE, 'foo')
1501n/a with self.assertRaises(OSError) as cm:
1502n/a p.resolve(strict=True)
1503n/a self.assertEqual(cm.exception.errno, errno.ENOENT)
1504n/a # Non-strict
1505n/a self.assertEqual(str(p.resolve(strict=False)),
1506n/a os.path.join(BASE, 'foo'))
1507n/a p = P(BASE, 'foo', 'in', 'spam')
1508n/a self.assertEqual(str(p.resolve(strict=False)),
1509n/a os.path.join(BASE, 'foo'))
1510n/a p = P(BASE, '..', 'foo', 'in', 'spam')
1511n/a self.assertEqual(str(p.resolve(strict=False)),
1512n/a os.path.abspath(os.path.join('foo')))
1513n/a # These are all relative symlinks
1514n/a p = P(BASE, 'dirB', 'fileB')
1515n/a self._check_resolve_relative(p, p)
1516n/a p = P(BASE, 'linkA')
1517n/a self._check_resolve_relative(p, P(BASE, 'fileA'))
1518n/a p = P(BASE, 'dirA', 'linkC', 'fileB')
1519n/a self._check_resolve_relative(p, P(BASE, 'dirB', 'fileB'))
1520n/a p = P(BASE, 'dirB', 'linkD', 'fileB')
1521n/a self._check_resolve_relative(p, P(BASE, 'dirB', 'fileB'))
1522n/a # Non-strict
1523n/a p = P(BASE, 'dirA', 'linkC', 'fileB', 'foo', 'in', 'spam')
1524n/a self._check_resolve_relative(p, P(BASE, 'dirB', 'fileB', 'foo'), False)
1525n/a p = P(BASE, 'dirA', 'linkC', '..', 'foo', 'in', 'spam')
1526n/a if os.name == 'nt':
1527n/a # In Windows, if linkY points to dirB, 'dirA\linkY\..'
1528n/a # resolves to 'dirA' without resolving linkY first.
1529n/a self._check_resolve_relative(p, P(BASE, 'dirA', 'foo'), False)
1530n/a else:
1531n/a # In Posix, if linkY points to dirB, 'dirA/linkY/..'
1532n/a # resolves to 'dirB/..' first before resolving to parent of dirB.
1533n/a self._check_resolve_relative(p, P(BASE, 'foo'), False)
1534n/a # Now create absolute symlinks
1535n/a d = tempfile.mkdtemp(suffix='-dirD')
1536n/a self.addCleanup(support.rmtree, d)
1537n/a os.symlink(os.path.join(d), join('dirA', 'linkX'))
1538n/a os.symlink(join('dirB'), os.path.join(d, 'linkY'))
1539n/a p = P(BASE, 'dirA', 'linkX', 'linkY', 'fileB')
1540n/a self._check_resolve_absolute(p, P(BASE, 'dirB', 'fileB'))
1541n/a # Non-strict
1542n/a p = P(BASE, 'dirA', 'linkX', 'linkY', 'foo', 'in', 'spam')
1543n/a self._check_resolve_relative(p, P(BASE, 'dirB', 'foo'), False)
1544n/a p = P(BASE, 'dirA', 'linkX', 'linkY', '..', 'foo', 'in', 'spam')
1545n/a if os.name == 'nt':
1546n/a # In Windows, if linkY points to dirB, 'dirA\linkY\..'
1547n/a # resolves to 'dirA' without resolving linkY first.
1548n/a self._check_resolve_relative(p, P(d, 'foo'), False)
1549n/a else:
1550n/a # In Posix, if linkY points to dirB, 'dirA/linkY/..'
1551n/a # resolves to 'dirB/..' first before resolving to parent of dirB.
1552n/a self._check_resolve_relative(p, P(BASE, 'foo'), False)
1553n/a
1554n/a @with_symlinks
1555n/a def test_resolve_dot(self):
1556n/a # See https://bitbucket.org/pitrou/pathlib/issue/9/pathresolve-fails-on-complex-symlinks
1557n/a p = self.cls(BASE)
1558n/a self.dirlink('.', join('0'))
1559n/a self.dirlink(os.path.join('0', '0'), join('1'))
1560n/a self.dirlink(os.path.join('1', '1'), join('2'))
1561n/a q = p / '2'
1562n/a self.assertEqual(q.resolve(strict=True), p)
1563n/a r = q / '3' / '4'
1564n/a self.assertRaises(FileNotFoundError, r.resolve, strict=True)
1565n/a # Non-strict
1566n/a self.assertEqual(r.resolve(strict=False), p / '3')
1567n/a
1568n/a def test_with(self):
1569n/a p = self.cls(BASE)
1570n/a it = p.iterdir()
1571n/a it2 = p.iterdir()
1572n/a next(it2)
1573n/a with p:
1574n/a pass
1575n/a # I/O operation on closed path
1576n/a self.assertRaises(ValueError, next, it)
1577n/a self.assertRaises(ValueError, next, it2)
1578n/a self.assertRaises(ValueError, p.open)
1579n/a self.assertRaises(ValueError, p.resolve)
1580n/a self.assertRaises(ValueError, p.absolute)
1581n/a self.assertRaises(ValueError, p.__enter__)
1582n/a
1583n/a def test_chmod(self):
1584n/a p = self.cls(BASE) / 'fileA'
1585n/a mode = p.stat().st_mode
1586n/a # Clear writable bit
1587n/a new_mode = mode & ~0o222
1588n/a p.chmod(new_mode)
1589n/a self.assertEqual(p.stat().st_mode, new_mode)
1590n/a # Set writable bit
1591n/a new_mode = mode | 0o222
1592n/a p.chmod(new_mode)
1593n/a self.assertEqual(p.stat().st_mode, new_mode)
1594n/a
1595n/a # XXX also need a test for lchmod
1596n/a
1597n/a def test_stat(self):
1598n/a p = self.cls(BASE) / 'fileA'
1599n/a st = p.stat()
1600n/a self.assertEqual(p.stat(), st)
1601n/a # Change file mode by flipping write bit
1602n/a p.chmod(st.st_mode ^ 0o222)
1603n/a self.addCleanup(p.chmod, st.st_mode)
1604n/a self.assertNotEqual(p.stat(), st)
1605n/a
1606n/a @with_symlinks
1607n/a def test_lstat(self):
1608n/a p = self.cls(BASE)/ 'linkA'
1609n/a st = p.stat()
1610n/a self.assertNotEqual(st, p.lstat())
1611n/a
1612n/a def test_lstat_nosymlink(self):
1613n/a p = self.cls(BASE) / 'fileA'
1614n/a st = p.stat()
1615n/a self.assertEqual(st, p.lstat())
1616n/a
1617n/a @unittest.skipUnless(pwd, "the pwd module is needed for this test")
1618n/a def test_owner(self):
1619n/a p = self.cls(BASE) / 'fileA'
1620n/a uid = p.stat().st_uid
1621n/a try:
1622n/a name = pwd.getpwuid(uid).pw_name
1623n/a except KeyError:
1624n/a self.skipTest(
1625n/a "user %d doesn't have an entry in the system database" % uid)
1626n/a self.assertEqual(name, p.owner())
1627n/a
1628n/a @unittest.skipUnless(grp, "the grp module is needed for this test")
1629n/a def test_group(self):
1630n/a p = self.cls(BASE) / 'fileA'
1631n/a gid = p.stat().st_gid
1632n/a try:
1633n/a name = grp.getgrgid(gid).gr_name
1634n/a except KeyError:
1635n/a self.skipTest(
1636n/a "group %d doesn't have an entry in the system database" % gid)
1637n/a self.assertEqual(name, p.group())
1638n/a
1639n/a def test_unlink(self):
1640n/a p = self.cls(BASE) / 'fileA'
1641n/a p.unlink()
1642n/a self.assertFileNotFound(p.stat)
1643n/a self.assertFileNotFound(p.unlink)
1644n/a
1645n/a def test_rmdir(self):
1646n/a p = self.cls(BASE) / 'dirA'
1647n/a for q in p.iterdir():
1648n/a q.unlink()
1649n/a p.rmdir()
1650n/a self.assertFileNotFound(p.stat)
1651n/a self.assertFileNotFound(p.unlink)
1652n/a
1653n/a def test_rename(self):
1654n/a P = self.cls(BASE)
1655n/a p = P / 'fileA'
1656n/a size = p.stat().st_size
1657n/a # Renaming to another path
1658n/a q = P / 'dirA' / 'fileAA'
1659n/a p.rename(q)
1660n/a self.assertEqual(q.stat().st_size, size)
1661n/a self.assertFileNotFound(p.stat)
1662n/a # Renaming to a str of a relative path
1663n/a r = rel_join('fileAAA')
1664n/a q.rename(r)
1665n/a self.assertEqual(os.stat(r).st_size, size)
1666n/a self.assertFileNotFound(q.stat)
1667n/a
1668n/a def test_replace(self):
1669n/a P = self.cls(BASE)
1670n/a p = P / 'fileA'
1671n/a size = p.stat().st_size
1672n/a # Replacing a non-existing path
1673n/a q = P / 'dirA' / 'fileAA'
1674n/a p.replace(q)
1675n/a self.assertEqual(q.stat().st_size, size)
1676n/a self.assertFileNotFound(p.stat)
1677n/a # Replacing another (existing) path
1678n/a r = rel_join('dirB', 'fileB')
1679n/a q.replace(r)
1680n/a self.assertEqual(os.stat(r).st_size, size)
1681n/a self.assertFileNotFound(q.stat)
1682n/a
1683n/a def test_touch_common(self):
1684n/a P = self.cls(BASE)
1685n/a p = P / 'newfileA'
1686n/a self.assertFalse(p.exists())
1687n/a p.touch()
1688n/a self.assertTrue(p.exists())
1689n/a st = p.stat()
1690n/a old_mtime = st.st_mtime
1691n/a old_mtime_ns = st.st_mtime_ns
1692n/a # Rewind the mtime sufficiently far in the past to work around
1693n/a # filesystem-specific timestamp granularity.
1694n/a os.utime(str(p), (old_mtime - 10, old_mtime - 10))
1695n/a # The file mtime should be refreshed by calling touch() again
1696n/a p.touch()
1697n/a st = p.stat()
1698n/a self.assertGreaterEqual(st.st_mtime_ns, old_mtime_ns)
1699n/a self.assertGreaterEqual(st.st_mtime, old_mtime)
1700n/a # Now with exist_ok=False
1701n/a p = P / 'newfileB'
1702n/a self.assertFalse(p.exists())
1703n/a p.touch(mode=0o700, exist_ok=False)
1704n/a self.assertTrue(p.exists())
1705n/a self.assertRaises(OSError, p.touch, exist_ok=False)
1706n/a
1707n/a def test_touch_nochange(self):
1708n/a P = self.cls(BASE)
1709n/a p = P / 'fileA'
1710n/a p.touch()
1711n/a with p.open('rb') as f:
1712n/a self.assertEqual(f.read().strip(), b"this is file A")
1713n/a
1714n/a def test_mkdir(self):
1715n/a P = self.cls(BASE)
1716n/a p = P / 'newdirA'
1717n/a self.assertFalse(p.exists())
1718n/a p.mkdir()
1719n/a self.assertTrue(p.exists())
1720n/a self.assertTrue(p.is_dir())
1721n/a with self.assertRaises(OSError) as cm:
1722n/a p.mkdir()
1723n/a self.assertEqual(cm.exception.errno, errno.EEXIST)
1724n/a
1725n/a def test_mkdir_parents(self):
1726n/a # Creating a chain of directories
1727n/a p = self.cls(BASE, 'newdirB', 'newdirC')
1728n/a self.assertFalse(p.exists())
1729n/a with self.assertRaises(OSError) as cm:
1730n/a p.mkdir()
1731n/a self.assertEqual(cm.exception.errno, errno.ENOENT)
1732n/a p.mkdir(parents=True)
1733n/a self.assertTrue(p.exists())
1734n/a self.assertTrue(p.is_dir())
1735n/a with self.assertRaises(OSError) as cm:
1736n/a p.mkdir(parents=True)
1737n/a self.assertEqual(cm.exception.errno, errno.EEXIST)
1738n/a # test `mode` arg
1739n/a mode = stat.S_IMODE(p.stat().st_mode) # default mode
1740n/a p = self.cls(BASE, 'newdirD', 'newdirE')
1741n/a p.mkdir(0o555, parents=True)
1742n/a self.assertTrue(p.exists())
1743n/a self.assertTrue(p.is_dir())
1744n/a if os.name != 'nt':
1745n/a # the directory's permissions follow the mode argument
1746n/a self.assertEqual(stat.S_IMODE(p.stat().st_mode), 0o7555 & mode)
1747n/a # the parent's permissions follow the default process settings
1748n/a self.assertEqual(stat.S_IMODE(p.parent.stat().st_mode), mode)
1749n/a
1750n/a def test_mkdir_exist_ok(self):
1751n/a p = self.cls(BASE, 'dirB')
1752n/a st_ctime_first = p.stat().st_ctime
1753n/a self.assertTrue(p.exists())
1754n/a self.assertTrue(p.is_dir())
1755n/a with self.assertRaises(FileExistsError) as cm:
1756n/a p.mkdir()
1757n/a self.assertEqual(cm.exception.errno, errno.EEXIST)
1758n/a p.mkdir(exist_ok=True)
1759n/a self.assertTrue(p.exists())
1760n/a self.assertEqual(p.stat().st_ctime, st_ctime_first)
1761n/a
1762n/a def test_mkdir_exist_ok_with_parent(self):
1763n/a p = self.cls(BASE, 'dirC')
1764n/a self.assertTrue(p.exists())
1765n/a with self.assertRaises(FileExistsError) as cm:
1766n/a p.mkdir()
1767n/a self.assertEqual(cm.exception.errno, errno.EEXIST)
1768n/a p = p / 'newdirC'
1769n/a p.mkdir(parents=True)
1770n/a st_ctime_first = p.stat().st_ctime
1771n/a self.assertTrue(p.exists())
1772n/a with self.assertRaises(FileExistsError) as cm:
1773n/a p.mkdir(parents=True)
1774n/a self.assertEqual(cm.exception.errno, errno.EEXIST)
1775n/a p.mkdir(parents=True, exist_ok=True)
1776n/a self.assertTrue(p.exists())
1777n/a self.assertEqual(p.stat().st_ctime, st_ctime_first)
1778n/a
1779n/a @only_nt # XXX: not sure how to test this on POSIX
1780n/a def test_mkdir_with_unknown_drive(self):
1781n/a for d in 'ZYXWVUTSRQPONMLKJIHGFEDCBA':
1782n/a p = self.cls(d + ':\\')
1783n/a if not p.is_dir():
1784n/a break
1785n/a else:
1786n/a self.skipTest("cannot find a drive that doesn't exist")
1787n/a with self.assertRaises(OSError):
1788n/a (p / 'child' / 'path').mkdir(parents=True)
1789n/a
1790n/a def test_mkdir_with_child_file(self):
1791n/a p = self.cls(BASE, 'dirB', 'fileB')
1792n/a self.assertTrue(p.exists())
1793n/a # An exception is raised when the last path component is an existing
1794n/a # regular file, regardless of whether exist_ok is true or not.
1795n/a with self.assertRaises(FileExistsError) as cm:
1796n/a p.mkdir(parents=True)
1797n/a self.assertEqual(cm.exception.errno, errno.EEXIST)
1798n/a with self.assertRaises(FileExistsError) as cm:
1799n/a p.mkdir(parents=True, exist_ok=True)
1800n/a self.assertEqual(cm.exception.errno, errno.EEXIST)
1801n/a
1802n/a def test_mkdir_no_parents_file(self):
1803n/a p = self.cls(BASE, 'fileA')
1804n/a self.assertTrue(p.exists())
1805n/a # An exception is raised when the last path component is an existing
1806n/a # regular file, regardless of whether exist_ok is true or not.
1807n/a with self.assertRaises(FileExistsError) as cm:
1808n/a p.mkdir()
1809n/a self.assertEqual(cm.exception.errno, errno.EEXIST)
1810n/a with self.assertRaises(FileExistsError) as cm:
1811n/a p.mkdir(exist_ok=True)
1812n/a self.assertEqual(cm.exception.errno, errno.EEXIST)
1813n/a
1814n/a @with_symlinks
1815n/a def test_symlink_to(self):
1816n/a P = self.cls(BASE)
1817n/a target = P / 'fileA'
1818n/a # Symlinking a path target
1819n/a link = P / 'dirA' / 'linkAA'
1820n/a link.symlink_to(target)
1821n/a self.assertEqual(link.stat(), target.stat())
1822n/a self.assertNotEqual(link.lstat(), target.stat())
1823n/a # Symlinking a str target
1824n/a link = P / 'dirA' / 'linkAAA'
1825n/a link.symlink_to(str(target))
1826n/a self.assertEqual(link.stat(), target.stat())
1827n/a self.assertNotEqual(link.lstat(), target.stat())
1828n/a self.assertFalse(link.is_dir())
1829n/a # Symlinking to a directory
1830n/a target = P / 'dirB'
1831n/a link = P / 'dirA' / 'linkAAAA'
1832n/a link.symlink_to(target, target_is_directory=True)
1833n/a self.assertEqual(link.stat(), target.stat())
1834n/a self.assertNotEqual(link.lstat(), target.stat())
1835n/a self.assertTrue(link.is_dir())
1836n/a self.assertTrue(list(link.iterdir()))
1837n/a
1838n/a def test_is_dir(self):
1839n/a P = self.cls(BASE)
1840n/a self.assertTrue((P / 'dirA').is_dir())
1841n/a self.assertFalse((P / 'fileA').is_dir())
1842n/a self.assertFalse((P / 'non-existing').is_dir())
1843n/a self.assertFalse((P / 'fileA' / 'bah').is_dir())
1844n/a if not symlink_skip_reason:
1845n/a self.assertFalse((P / 'linkA').is_dir())
1846n/a self.assertTrue((P / 'linkB').is_dir())
1847n/a self.assertFalse((P/ 'brokenLink').is_dir())
1848n/a
1849n/a def test_is_file(self):
1850n/a P = self.cls(BASE)
1851n/a self.assertTrue((P / 'fileA').is_file())
1852n/a self.assertFalse((P / 'dirA').is_file())
1853n/a self.assertFalse((P / 'non-existing').is_file())
1854n/a self.assertFalse((P / 'fileA' / 'bah').is_file())
1855n/a if not symlink_skip_reason:
1856n/a self.assertTrue((P / 'linkA').is_file())
1857n/a self.assertFalse((P / 'linkB').is_file())
1858n/a self.assertFalse((P/ 'brokenLink').is_file())
1859n/a
1860n/a def test_is_symlink(self):
1861n/a P = self.cls(BASE)
1862n/a self.assertFalse((P / 'fileA').is_symlink())
1863n/a self.assertFalse((P / 'dirA').is_symlink())
1864n/a self.assertFalse((P / 'non-existing').is_symlink())
1865n/a self.assertFalse((P / 'fileA' / 'bah').is_symlink())
1866n/a if not symlink_skip_reason:
1867n/a self.assertTrue((P / 'linkA').is_symlink())
1868n/a self.assertTrue((P / 'linkB').is_symlink())
1869n/a self.assertTrue((P/ 'brokenLink').is_symlink())
1870n/a
1871n/a def test_is_fifo_false(self):
1872n/a P = self.cls(BASE)
1873n/a self.assertFalse((P / 'fileA').is_fifo())
1874n/a self.assertFalse((P / 'dirA').is_fifo())
1875n/a self.assertFalse((P / 'non-existing').is_fifo())
1876n/a self.assertFalse((P / 'fileA' / 'bah').is_fifo())
1877n/a
1878n/a @unittest.skipUnless(hasattr(os, "mkfifo"), "os.mkfifo() required")
1879n/a @unittest.skipIf(android_not_root, "mkfifo not allowed, non root user")
1880n/a def test_is_fifo_true(self):
1881n/a P = self.cls(BASE, 'myfifo')
1882n/a os.mkfifo(str(P))
1883n/a self.assertTrue(P.is_fifo())
1884n/a self.assertFalse(P.is_socket())
1885n/a self.assertFalse(P.is_file())
1886n/a
1887n/a def test_is_socket_false(self):
1888n/a P = self.cls(BASE)
1889n/a self.assertFalse((P / 'fileA').is_socket())
1890n/a self.assertFalse((P / 'dirA').is_socket())
1891n/a self.assertFalse((P / 'non-existing').is_socket())
1892n/a self.assertFalse((P / 'fileA' / 'bah').is_socket())
1893n/a
1894n/a @unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required")
1895n/a def test_is_socket_true(self):
1896n/a P = self.cls(BASE, 'mysock')
1897n/a sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
1898n/a self.addCleanup(sock.close)
1899n/a try:
1900n/a sock.bind(str(P))
1901n/a except OSError as e:
1902n/a if (isinstance(e, PermissionError) or
1903n/a "AF_UNIX path too long" in str(e)):
1904n/a self.skipTest("cannot bind Unix socket: " + str(e))
1905n/a self.assertTrue(P.is_socket())
1906n/a self.assertFalse(P.is_fifo())
1907n/a self.assertFalse(P.is_file())
1908n/a
1909n/a def test_is_block_device_false(self):
1910n/a P = self.cls(BASE)
1911n/a self.assertFalse((P / 'fileA').is_block_device())
1912n/a self.assertFalse((P / 'dirA').is_block_device())
1913n/a self.assertFalse((P / 'non-existing').is_block_device())
1914n/a self.assertFalse((P / 'fileA' / 'bah').is_block_device())
1915n/a
1916n/a def test_is_char_device_false(self):
1917n/a P = self.cls(BASE)
1918n/a self.assertFalse((P / 'fileA').is_char_device())
1919n/a self.assertFalse((P / 'dirA').is_char_device())
1920n/a self.assertFalse((P / 'non-existing').is_char_device())
1921n/a self.assertFalse((P / 'fileA' / 'bah').is_char_device())
1922n/a
1923n/a def test_is_char_device_true(self):
1924n/a # Under Unix, /dev/null should generally be a char device
1925n/a P = self.cls('/dev/null')
1926n/a if not P.exists():
1927n/a self.skipTest("/dev/null required")
1928n/a self.assertTrue(P.is_char_device())
1929n/a self.assertFalse(P.is_block_device())
1930n/a self.assertFalse(P.is_file())
1931n/a
1932n/a def test_pickling_common(self):
1933n/a p = self.cls(BASE, 'fileA')
1934n/a for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
1935n/a dumped = pickle.dumps(p, proto)
1936n/a pp = pickle.loads(dumped)
1937n/a self.assertEqual(pp.stat(), p.stat())
1938n/a
1939n/a def test_parts_interning(self):
1940n/a P = self.cls
1941n/a p = P('/usr/bin/foo')
1942n/a q = P('/usr/local/bin')
1943n/a # 'usr'
1944n/a self.assertIs(p.parts[1], q.parts[1])
1945n/a # 'bin'
1946n/a self.assertIs(p.parts[2], q.parts[3])
1947n/a
1948n/a def _check_complex_symlinks(self, link0_target):
1949n/a # Test solving a non-looping chain of symlinks (issue #19887)
1950n/a P = self.cls(BASE)
1951n/a self.dirlink(os.path.join('link0', 'link0'), join('link1'))
1952n/a self.dirlink(os.path.join('link1', 'link1'), join('link2'))
1953n/a self.dirlink(os.path.join('link2', 'link2'), join('link3'))
1954n/a self.dirlink(link0_target, join('link0'))
1955n/a
1956n/a # Resolve absolute paths
1957n/a p = (P / 'link0').resolve()
1958n/a self.assertEqual(p, P)
1959n/a self.assertEqual(str(p), BASE)
1960n/a p = (P / 'link1').resolve()
1961n/a self.assertEqual(p, P)
1962n/a self.assertEqual(str(p), BASE)
1963n/a p = (P / 'link2').resolve()
1964n/a self.assertEqual(p, P)
1965n/a self.assertEqual(str(p), BASE)
1966n/a p = (P / 'link3').resolve()
1967n/a self.assertEqual(p, P)
1968n/a self.assertEqual(str(p), BASE)
1969n/a
1970n/a # Resolve relative paths
1971n/a old_path = os.getcwd()
1972n/a os.chdir(BASE)
1973n/a try:
1974n/a p = self.cls('link0').resolve()
1975n/a self.assertEqual(p, P)
1976n/a self.assertEqual(str(p), BASE)
1977n/a p = self.cls('link1').resolve()
1978n/a self.assertEqual(p, P)
1979n/a self.assertEqual(str(p), BASE)
1980n/a p = self.cls('link2').resolve()
1981n/a self.assertEqual(p, P)
1982n/a self.assertEqual(str(p), BASE)
1983n/a p = self.cls('link3').resolve()
1984n/a self.assertEqual(p, P)
1985n/a self.assertEqual(str(p), BASE)
1986n/a finally:
1987n/a os.chdir(old_path)
1988n/a
1989n/a @with_symlinks
1990n/a def test_complex_symlinks_absolute(self):
1991n/a self._check_complex_symlinks(BASE)
1992n/a
1993n/a @with_symlinks
1994n/a def test_complex_symlinks_relative(self):
1995n/a self._check_complex_symlinks('.')
1996n/a
1997n/a @with_symlinks
1998n/a def test_complex_symlinks_relative_dot_dot(self):
1999n/a self._check_complex_symlinks(os.path.join('dirA', '..'))
2000n/a
2001n/a
2002n/aclass PathTest(_BasePathTest, unittest.TestCase):
2003n/a cls = pathlib.Path
2004n/a
2005n/a def test_concrete_class(self):
2006n/a p = self.cls('a')
2007n/a self.assertIs(type(p),
2008n/a pathlib.WindowsPath if os.name == 'nt' else pathlib.PosixPath)
2009n/a
2010n/a def test_unsupported_flavour(self):
2011n/a if os.name == 'nt':
2012n/a self.assertRaises(NotImplementedError, pathlib.PosixPath)
2013n/a else:
2014n/a self.assertRaises(NotImplementedError, pathlib.WindowsPath)
2015n/a
2016n/a def test_glob_empty_pattern(self):
2017n/a p = self.cls()
2018n/a with self.assertRaisesRegex(ValueError, 'Unacceptable pattern'):
2019n/a list(p.glob(''))
2020n/a
2021n/a
2022n/a@only_posix
2023n/aclass PosixPathTest(_BasePathTest, unittest.TestCase):
2024n/a cls = pathlib.PosixPath
2025n/a
2026n/a def _check_symlink_loop(self, *args, strict=True):
2027n/a path = self.cls(*args)
2028n/a with self.assertRaises(RuntimeError):
2029n/a print(path.resolve(strict))
2030n/a
2031n/a def test_open_mode(self):
2032n/a old_mask = os.umask(0)
2033n/a self.addCleanup(os.umask, old_mask)
2034n/a p = self.cls(BASE)
2035n/a with (p / 'new_file').open('wb'):
2036n/a pass
2037n/a st = os.stat(join('new_file'))
2038n/a self.assertEqual(stat.S_IMODE(st.st_mode), 0o666)
2039n/a os.umask(0o022)
2040n/a with (p / 'other_new_file').open('wb'):
2041n/a pass
2042n/a st = os.stat(join('other_new_file'))
2043n/a self.assertEqual(stat.S_IMODE(st.st_mode), 0o644)
2044n/a
2045n/a def test_touch_mode(self):
2046n/a old_mask = os.umask(0)
2047n/a self.addCleanup(os.umask, old_mask)
2048n/a p = self.cls(BASE)
2049n/a (p / 'new_file').touch()
2050n/a st = os.stat(join('new_file'))
2051n/a self.assertEqual(stat.S_IMODE(st.st_mode), 0o666)
2052n/a os.umask(0o022)
2053n/a (p / 'other_new_file').touch()
2054n/a st = os.stat(join('other_new_file'))
2055n/a self.assertEqual(stat.S_IMODE(st.st_mode), 0o644)
2056n/a (p / 'masked_new_file').touch(mode=0o750)
2057n/a st = os.stat(join('masked_new_file'))
2058n/a self.assertEqual(stat.S_IMODE(st.st_mode), 0o750)
2059n/a
2060n/a @with_symlinks
2061n/a def test_resolve_loop(self):
2062n/a # Loops with relative symlinks
2063n/a os.symlink('linkX/inside', join('linkX'))
2064n/a self._check_symlink_loop(BASE, 'linkX')
2065n/a os.symlink('linkY', join('linkY'))
2066n/a self._check_symlink_loop(BASE, 'linkY')
2067n/a os.symlink('linkZ/../linkZ', join('linkZ'))
2068n/a self._check_symlink_loop(BASE, 'linkZ')
2069n/a # Non-strict
2070n/a self._check_symlink_loop(BASE, 'linkZ', 'foo', strict=False)
2071n/a # Loops with absolute symlinks
2072n/a os.symlink(join('linkU/inside'), join('linkU'))
2073n/a self._check_symlink_loop(BASE, 'linkU')
2074n/a os.symlink(join('linkV'), join('linkV'))
2075n/a self._check_symlink_loop(BASE, 'linkV')
2076n/a os.symlink(join('linkW/../linkW'), join('linkW'))
2077n/a self._check_symlink_loop(BASE, 'linkW')
2078n/a # Non-strict
2079n/a self._check_symlink_loop(BASE, 'linkW', 'foo', strict=False)
2080n/a
2081n/a def test_glob(self):
2082n/a P = self.cls
2083n/a p = P(BASE)
2084n/a given = set(p.glob("FILEa"))
2085n/a expect = set() if not support.fs_is_case_insensitive(BASE) else given
2086n/a self.assertEqual(given, expect)
2087n/a self.assertEqual(set(p.glob("FILEa*")), set())
2088n/a
2089n/a def test_rglob(self):
2090n/a P = self.cls
2091n/a p = P(BASE, "dirC")
2092n/a given = set(p.rglob("FILEd"))
2093n/a expect = set() if not support.fs_is_case_insensitive(BASE) else given
2094n/a self.assertEqual(given, expect)
2095n/a self.assertEqual(set(p.rglob("FILEd*")), set())
2096n/a
2097n/a @unittest.skipUnless(hasattr(pwd, 'getpwall'),
2098n/a 'pwd module does not expose getpwall()')
2099n/a def test_expanduser(self):
2100n/a P = self.cls
2101n/a support.import_module('pwd')
2102n/a import pwd
2103n/a pwdent = pwd.getpwuid(os.getuid())
2104n/a username = pwdent.pw_name
2105n/a userhome = pwdent.pw_dir.rstrip('/') or '/'
2106n/a # find arbitrary different user (if exists)
2107n/a for pwdent in pwd.getpwall():
2108n/a othername = pwdent.pw_name
2109n/a otherhome = pwdent.pw_dir.rstrip('/')
2110n/a if othername != username and otherhome:
2111n/a break
2112n/a
2113n/a p1 = P('~/Documents')
2114n/a p2 = P('~' + username + '/Documents')
2115n/a p3 = P('~' + othername + '/Documents')
2116n/a p4 = P('../~' + username + '/Documents')
2117n/a p5 = P('/~' + username + '/Documents')
2118n/a p6 = P('')
2119n/a p7 = P('~fakeuser/Documents')
2120n/a
2121n/a with support.EnvironmentVarGuard() as env:
2122n/a env.pop('HOME', None)
2123n/a
2124n/a self.assertEqual(p1.expanduser(), P(userhome) / 'Documents')
2125n/a self.assertEqual(p2.expanduser(), P(userhome) / 'Documents')
2126n/a self.assertEqual(p3.expanduser(), P(otherhome) / 'Documents')
2127n/a self.assertEqual(p4.expanduser(), p4)
2128n/a self.assertEqual(p5.expanduser(), p5)
2129n/a self.assertEqual(p6.expanduser(), p6)
2130n/a self.assertRaises(RuntimeError, p7.expanduser)
2131n/a
2132n/a env['HOME'] = '/tmp'
2133n/a self.assertEqual(p1.expanduser(), P('/tmp/Documents'))
2134n/a self.assertEqual(p2.expanduser(), P(userhome) / 'Documents')
2135n/a self.assertEqual(p3.expanduser(), P(otherhome) / 'Documents')
2136n/a self.assertEqual(p4.expanduser(), p4)
2137n/a self.assertEqual(p5.expanduser(), p5)
2138n/a self.assertEqual(p6.expanduser(), p6)
2139n/a self.assertRaises(RuntimeError, p7.expanduser)
2140n/a
2141n/a
2142n/a@only_nt
2143n/aclass WindowsPathTest(_BasePathTest, unittest.TestCase):
2144n/a cls = pathlib.WindowsPath
2145n/a
2146n/a def test_glob(self):
2147n/a P = self.cls
2148n/a p = P(BASE)
2149n/a self.assertEqual(set(p.glob("FILEa")), { P(BASE, "fileA") })
2150n/a
2151n/a def test_rglob(self):
2152n/a P = self.cls
2153n/a p = P(BASE, "dirC")
2154n/a self.assertEqual(set(p.rglob("FILEd")), { P(BASE, "dirC/dirD/fileD") })
2155n/a
2156n/a def test_expanduser(self):
2157n/a P = self.cls
2158n/a with support.EnvironmentVarGuard() as env:
2159n/a env.pop('HOME', None)
2160n/a env.pop('USERPROFILE', None)
2161n/a env.pop('HOMEPATH', None)
2162n/a env.pop('HOMEDRIVE', None)
2163n/a env['USERNAME'] = 'alice'
2164n/a
2165n/a # test that the path returns unchanged
2166n/a p1 = P('~/My Documents')
2167n/a p2 = P('~alice/My Documents')
2168n/a p3 = P('~bob/My Documents')
2169n/a p4 = P('/~/My Documents')
2170n/a p5 = P('d:~/My Documents')
2171n/a p6 = P('')
2172n/a self.assertRaises(RuntimeError, p1.expanduser)
2173n/a self.assertRaises(RuntimeError, p2.expanduser)
2174n/a self.assertRaises(RuntimeError, p3.expanduser)
2175n/a self.assertEqual(p4.expanduser(), p4)
2176n/a self.assertEqual(p5.expanduser(), p5)
2177n/a self.assertEqual(p6.expanduser(), p6)
2178n/a
2179n/a def check():
2180n/a env.pop('USERNAME', None)
2181n/a self.assertEqual(p1.expanduser(),
2182n/a P('C:/Users/alice/My Documents'))
2183n/a self.assertRaises(KeyError, p2.expanduser)
2184n/a env['USERNAME'] = 'alice'
2185n/a self.assertEqual(p2.expanduser(),
2186n/a P('C:/Users/alice/My Documents'))
2187n/a self.assertEqual(p3.expanduser(),
2188n/a P('C:/Users/bob/My Documents'))
2189n/a self.assertEqual(p4.expanduser(), p4)
2190n/a self.assertEqual(p5.expanduser(), p5)
2191n/a self.assertEqual(p6.expanduser(), p6)
2192n/a
2193n/a # test the first lookup key in the env vars
2194n/a env['HOME'] = 'C:\\Users\\alice'
2195n/a check()
2196n/a
2197n/a # test that HOMEPATH is available instead
2198n/a env.pop('HOME', None)
2199n/a env['HOMEPATH'] = 'C:\\Users\\alice'
2200n/a check()
2201n/a
2202n/a env['HOMEDRIVE'] = 'C:\\'
2203n/a env['HOMEPATH'] = 'Users\\alice'
2204n/a check()
2205n/a
2206n/a env.pop('HOMEDRIVE', None)
2207n/a env.pop('HOMEPATH', None)
2208n/a env['USERPROFILE'] = 'C:\\Users\\alice'
2209n/a check()
2210n/a
2211n/a
2212n/aif __name__ == "__main__":
2213n/a unittest.main()