mirror of https://github.com/python/cpython.git
374 lines
16 KiB
Python
374 lines
16 KiB
Python
"""
|
|
Tests for pathlib.types._JoinablePath
|
|
"""
|
|
|
|
import unittest
|
|
|
|
from .support import is_pypi
|
|
from .support.lexical_path import LexicalPath
|
|
|
|
if is_pypi:
|
|
from pathlib_abc import _PathParser, _JoinablePath
|
|
else:
|
|
from pathlib.types import _PathParser, _JoinablePath
|
|
|
|
|
|
class JoinTestBase:
|
|
def test_is_joinable(self):
|
|
p = self.cls()
|
|
self.assertIsInstance(p, _JoinablePath)
|
|
|
|
def test_parser(self):
|
|
self.assertIsInstance(self.cls.parser, _PathParser)
|
|
|
|
def test_constructor(self):
|
|
P = self.cls
|
|
p = P('a')
|
|
self.assertIsInstance(p, P)
|
|
P()
|
|
P('a', 'b', 'c')
|
|
P('/a', 'b', 'c')
|
|
P('a/b/c')
|
|
P('/a/b/c')
|
|
|
|
def test_with_segments(self):
|
|
class P(self.cls):
|
|
def __init__(self, *pathsegments, session_id):
|
|
super().__init__(*pathsegments)
|
|
self.session_id = session_id
|
|
|
|
def with_segments(self, *pathsegments):
|
|
return type(self)(*pathsegments, session_id=self.session_id)
|
|
p = P('foo', 'bar', session_id=42)
|
|
self.assertEqual(42, (p / 'foo').session_id)
|
|
self.assertEqual(42, ('foo' / p).session_id)
|
|
self.assertEqual(42, p.joinpath('foo').session_id)
|
|
self.assertEqual(42, p.with_name('foo').session_id)
|
|
self.assertEqual(42, p.with_stem('foo').session_id)
|
|
self.assertEqual(42, p.with_suffix('.foo').session_id)
|
|
self.assertEqual(42, p.with_segments('foo').session_id)
|
|
self.assertEqual(42, p.parent.session_id)
|
|
for parent in p.parents:
|
|
self.assertEqual(42, parent.session_id)
|
|
|
|
def test_join(self):
|
|
P = self.cls
|
|
sep = self.cls.parser.sep
|
|
p = P(f'a{sep}b')
|
|
pp = p.joinpath('c')
|
|
self.assertEqual(pp, P(f'a{sep}b{sep}c'))
|
|
self.assertIs(type(pp), type(p))
|
|
pp = p.joinpath('c', 'd')
|
|
self.assertEqual(pp, P(f'a{sep}b{sep}c{sep}d'))
|
|
pp = p.joinpath(f'{sep}c')
|
|
self.assertEqual(pp, P(f'{sep}c'))
|
|
|
|
def test_div(self):
|
|
# Basically the same as joinpath().
|
|
P = self.cls
|
|
sep = self.cls.parser.sep
|
|
p = P(f'a{sep}b')
|
|
pp = p / 'c'
|
|
self.assertEqual(pp, P(f'a{sep}b{sep}c'))
|
|
self.assertIs(type(pp), type(p))
|
|
pp = p / f'c{sep}d'
|
|
self.assertEqual(pp, P(f'a{sep}b{sep}c{sep}d'))
|
|
pp = p / 'c' / 'd'
|
|
self.assertEqual(pp, P(f'a{sep}b{sep}c{sep}d'))
|
|
pp = 'c' / p / 'd'
|
|
self.assertEqual(pp, P(f'c{sep}a{sep}b{sep}d'))
|
|
pp = p/ f'{sep}c'
|
|
self.assertEqual(pp, P(f'{sep}c'))
|
|
|
|
def test_full_match(self):
|
|
P = self.cls
|
|
# Simple relative pattern.
|
|
self.assertTrue(P('b.py').full_match('b.py'))
|
|
self.assertFalse(P('a/b.py').full_match('b.py'))
|
|
self.assertFalse(P('/a/b.py').full_match('b.py'))
|
|
self.assertFalse(P('a.py').full_match('b.py'))
|
|
self.assertFalse(P('b/py').full_match('b.py'))
|
|
self.assertFalse(P('/a.py').full_match('b.py'))
|
|
self.assertFalse(P('b.py/c').full_match('b.py'))
|
|
# Wildcard relative pattern.
|
|
self.assertTrue(P('b.py').full_match('*.py'))
|
|
self.assertFalse(P('a/b.py').full_match('*.py'))
|
|
self.assertFalse(P('/a/b.py').full_match('*.py'))
|
|
self.assertFalse(P('b.pyc').full_match('*.py'))
|
|
self.assertFalse(P('b./py').full_match('*.py'))
|
|
self.assertFalse(P('b.py/c').full_match('*.py'))
|
|
# Multi-part relative pattern.
|
|
self.assertTrue(P('ab/c.py').full_match('a*/*.py'))
|
|
self.assertFalse(P('/d/ab/c.py').full_match('a*/*.py'))
|
|
self.assertFalse(P('a.py').full_match('a*/*.py'))
|
|
self.assertFalse(P('/dab/c.py').full_match('a*/*.py'))
|
|
self.assertFalse(P('ab/c.py/d').full_match('a*/*.py'))
|
|
# Absolute pattern.
|
|
self.assertTrue(P('/b.py').full_match('/*.py'))
|
|
self.assertFalse(P('b.py').full_match('/*.py'))
|
|
self.assertFalse(P('a/b.py').full_match('/*.py'))
|
|
self.assertFalse(P('/a/b.py').full_match('/*.py'))
|
|
# Multi-part absolute pattern.
|
|
self.assertTrue(P('/a/b.py').full_match('/a/*.py'))
|
|
self.assertFalse(P('/ab.py').full_match('/a/*.py'))
|
|
self.assertFalse(P('/a/b/c.py').full_match('/a/*.py'))
|
|
# Multi-part glob-style pattern.
|
|
self.assertTrue(P('a').full_match('**'))
|
|
self.assertTrue(P('c.py').full_match('**'))
|
|
self.assertTrue(P('a/b/c.py').full_match('**'))
|
|
self.assertTrue(P('/a/b/c.py').full_match('**'))
|
|
self.assertTrue(P('/a/b/c.py').full_match('/**'))
|
|
self.assertTrue(P('/a/b/c.py').full_match('/a/**'))
|
|
self.assertTrue(P('/a/b/c.py').full_match('**/*.py'))
|
|
self.assertTrue(P('/a/b/c.py').full_match('/**/*.py'))
|
|
self.assertTrue(P('/a/b/c.py').full_match('/a/**/*.py'))
|
|
self.assertTrue(P('/a/b/c.py').full_match('/a/b/**/*.py'))
|
|
self.assertTrue(P('/a/b/c.py').full_match('/**/**/**/**/*.py'))
|
|
self.assertFalse(P('c.py').full_match('**/a.py'))
|
|
self.assertFalse(P('c.py').full_match('c/**'))
|
|
self.assertFalse(P('a/b/c.py').full_match('**/a'))
|
|
self.assertFalse(P('a/b/c.py').full_match('**/a/b'))
|
|
self.assertFalse(P('a/b/c.py').full_match('**/a/b/c'))
|
|
self.assertFalse(P('a/b/c.py').full_match('**/a/b/c.'))
|
|
self.assertFalse(P('a/b/c.py').full_match('**/a/b/c./**'))
|
|
self.assertFalse(P('a/b/c.py').full_match('**/a/b/c./**'))
|
|
self.assertFalse(P('a/b/c.py').full_match('/a/b/c.py/**'))
|
|
self.assertFalse(P('a/b/c.py').full_match('/**/a/b/c.py'))
|
|
# Matching against empty path
|
|
self.assertFalse(P('').full_match('*'))
|
|
self.assertTrue(P('').full_match('**'))
|
|
self.assertFalse(P('').full_match('**/*'))
|
|
# Matching with empty pattern
|
|
self.assertTrue(P('').full_match(''))
|
|
self.assertTrue(P('.').full_match('.'))
|
|
self.assertFalse(P('/').full_match(''))
|
|
self.assertFalse(P('/').full_match('.'))
|
|
self.assertFalse(P('foo').full_match(''))
|
|
self.assertFalse(P('foo').full_match('.'))
|
|
|
|
def test_parts(self):
|
|
# `parts` returns a tuple.
|
|
sep = self.cls.parser.sep
|
|
P = self.cls
|
|
p = P(f'a{sep}b')
|
|
parts = p.parts
|
|
self.assertEqual(parts, ('a', 'b'))
|
|
# When the path is absolute, the anchor is a separate part.
|
|
p = P(f'{sep}a{sep}b')
|
|
parts = p.parts
|
|
self.assertEqual(parts, (sep, 'a', 'b'))
|
|
|
|
def test_parent(self):
|
|
# Relative
|
|
P = self.cls
|
|
p = P('a/b/c')
|
|
self.assertEqual(p.parent, P('a/b'))
|
|
self.assertEqual(p.parent.parent, P('a'))
|
|
self.assertEqual(p.parent.parent.parent, P(''))
|
|
self.assertEqual(p.parent.parent.parent.parent, P(''))
|
|
# Anchored
|
|
p = P('/a/b/c')
|
|
self.assertEqual(p.parent, P('/a/b'))
|
|
self.assertEqual(p.parent.parent, P('/a'))
|
|
self.assertEqual(p.parent.parent.parent, P('/'))
|
|
self.assertEqual(p.parent.parent.parent.parent, P('/'))
|
|
|
|
def test_parents(self):
|
|
# Relative
|
|
P = self.cls
|
|
p = P('a/b/c')
|
|
par = p.parents
|
|
self.assertEqual(len(par), 3)
|
|
self.assertEqual(par[0], P('a/b'))
|
|
self.assertEqual(par[1], P('a'))
|
|
self.assertEqual(par[2], P(''))
|
|
self.assertEqual(par[-1], P(''))
|
|
self.assertEqual(par[-2], P('a'))
|
|
self.assertEqual(par[-3], P('a/b'))
|
|
self.assertEqual(par[0:1], (P('a/b'),))
|
|
self.assertEqual(par[:2], (P('a/b'), P('a')))
|
|
self.assertEqual(par[:-1], (P('a/b'), P('a')))
|
|
self.assertEqual(par[1:], (P('a'), P('')))
|
|
self.assertEqual(par[::2], (P('a/b'), P('')))
|
|
self.assertEqual(par[::-1], (P(''), P('a'), P('a/b')))
|
|
self.assertEqual(list(par), [P('a/b'), P('a'), P('')])
|
|
with self.assertRaises(IndexError):
|
|
par[-4]
|
|
with self.assertRaises(IndexError):
|
|
par[3]
|
|
with self.assertRaises(TypeError):
|
|
par[0] = p
|
|
# Anchored
|
|
p = P('/a/b/c')
|
|
par = p.parents
|
|
self.assertEqual(len(par), 3)
|
|
self.assertEqual(par[0], P('/a/b'))
|
|
self.assertEqual(par[1], P('/a'))
|
|
self.assertEqual(par[2], P('/'))
|
|
self.assertEqual(par[-1], P('/'))
|
|
self.assertEqual(par[-2], P('/a'))
|
|
self.assertEqual(par[-3], P('/a/b'))
|
|
self.assertEqual(par[0:1], (P('/a/b'),))
|
|
self.assertEqual(par[:2], (P('/a/b'), P('/a')))
|
|
self.assertEqual(par[:-1], (P('/a/b'), P('/a')))
|
|
self.assertEqual(par[1:], (P('/a'), P('/')))
|
|
self.assertEqual(par[::2], (P('/a/b'), P('/')))
|
|
self.assertEqual(par[::-1], (P('/'), P('/a'), P('/a/b')))
|
|
self.assertEqual(list(par), [P('/a/b'), P('/a'), P('/')])
|
|
with self.assertRaises(IndexError):
|
|
par[-4]
|
|
with self.assertRaises(IndexError):
|
|
par[3]
|
|
|
|
def test_anchor(self):
|
|
P = self.cls
|
|
sep = self.cls.parser.sep
|
|
self.assertEqual(P('').anchor, '')
|
|
self.assertEqual(P(f'a{sep}b').anchor, '')
|
|
self.assertEqual(P(sep).anchor, sep)
|
|
self.assertEqual(P(f'{sep}a{sep}b').anchor, sep)
|
|
|
|
def test_name(self):
|
|
P = self.cls
|
|
self.assertEqual(P('').name, '')
|
|
self.assertEqual(P('/').name, '')
|
|
self.assertEqual(P('a/b').name, 'b')
|
|
self.assertEqual(P('/a/b').name, 'b')
|
|
self.assertEqual(P('a/b.py').name, 'b.py')
|
|
self.assertEqual(P('/a/b.py').name, 'b.py')
|
|
|
|
def test_suffix(self):
|
|
P = self.cls
|
|
self.assertEqual(P('').suffix, '')
|
|
self.assertEqual(P('.').suffix, '')
|
|
self.assertEqual(P('..').suffix, '')
|
|
self.assertEqual(P('/').suffix, '')
|
|
self.assertEqual(P('a/b').suffix, '')
|
|
self.assertEqual(P('/a/b').suffix, '')
|
|
self.assertEqual(P('/a/b/.').suffix, '')
|
|
self.assertEqual(P('a/b.py').suffix, '.py')
|
|
self.assertEqual(P('/a/b.py').suffix, '.py')
|
|
self.assertEqual(P('a/.hgrc').suffix, '')
|
|
self.assertEqual(P('/a/.hgrc').suffix, '')
|
|
self.assertEqual(P('a/.hg.rc').suffix, '.rc')
|
|
self.assertEqual(P('/a/.hg.rc').suffix, '.rc')
|
|
self.assertEqual(P('a/b.tar.gz').suffix, '.gz')
|
|
self.assertEqual(P('/a/b.tar.gz').suffix, '.gz')
|
|
self.assertEqual(P('a/trailing.dot.').suffix, '.')
|
|
self.assertEqual(P('/a/trailing.dot.').suffix, '.')
|
|
self.assertEqual(P('a/..d.o.t..').suffix, '.')
|
|
self.assertEqual(P('a/inn.er..dots').suffix, '.dots')
|
|
self.assertEqual(P('photo').suffix, '')
|
|
self.assertEqual(P('photo.jpg').suffix, '.jpg')
|
|
|
|
def test_suffixes(self):
|
|
P = self.cls
|
|
self.assertEqual(P('').suffixes, [])
|
|
self.assertEqual(P('.').suffixes, [])
|
|
self.assertEqual(P('/').suffixes, [])
|
|
self.assertEqual(P('a/b').suffixes, [])
|
|
self.assertEqual(P('/a/b').suffixes, [])
|
|
self.assertEqual(P('/a/b/.').suffixes, [])
|
|
self.assertEqual(P('a/b.py').suffixes, ['.py'])
|
|
self.assertEqual(P('/a/b.py').suffixes, ['.py'])
|
|
self.assertEqual(P('a/.hgrc').suffixes, [])
|
|
self.assertEqual(P('/a/.hgrc').suffixes, [])
|
|
self.assertEqual(P('a/.hg.rc').suffixes, ['.rc'])
|
|
self.assertEqual(P('/a/.hg.rc').suffixes, ['.rc'])
|
|
self.assertEqual(P('a/b.tar.gz').suffixes, ['.tar', '.gz'])
|
|
self.assertEqual(P('/a/b.tar.gz').suffixes, ['.tar', '.gz'])
|
|
self.assertEqual(P('a/trailing.dot.').suffixes, ['.dot', '.'])
|
|
self.assertEqual(P('/a/trailing.dot.').suffixes, ['.dot', '.'])
|
|
self.assertEqual(P('a/..d.o.t..').suffixes, ['.o', '.t', '.', '.'])
|
|
self.assertEqual(P('a/inn.er..dots').suffixes, ['.er', '.', '.dots'])
|
|
self.assertEqual(P('photo').suffixes, [])
|
|
self.assertEqual(P('photo.jpg').suffixes, ['.jpg'])
|
|
|
|
def test_stem(self):
|
|
P = self.cls
|
|
self.assertEqual(P('..').stem, '..')
|
|
self.assertEqual(P('').stem, '')
|
|
self.assertEqual(P('/').stem, '')
|
|
self.assertEqual(P('a/b').stem, 'b')
|
|
self.assertEqual(P('a/b.py').stem, 'b')
|
|
self.assertEqual(P('a/.hgrc').stem, '.hgrc')
|
|
self.assertEqual(P('a/.hg.rc').stem, '.hg')
|
|
self.assertEqual(P('a/b.tar.gz').stem, 'b.tar')
|
|
self.assertEqual(P('a/trailing.dot.').stem, 'trailing.dot')
|
|
self.assertEqual(P('a/..d.o.t..').stem, '..d.o.t.')
|
|
self.assertEqual(P('a/inn.er..dots').stem, 'inn.er.')
|
|
self.assertEqual(P('photo').stem, 'photo')
|
|
self.assertEqual(P('photo.jpg').stem, 'photo')
|
|
|
|
def test_with_name(self):
|
|
P = self.cls
|
|
self.assertEqual(P('a/b').with_name('d.xml'), P('a/d.xml'))
|
|
self.assertEqual(P('/a/b').with_name('d.xml'), P('/a/d.xml'))
|
|
self.assertEqual(P('a/b.py').with_name('d.xml'), P('a/d.xml'))
|
|
self.assertEqual(P('/a/b.py').with_name('d.xml'), P('/a/d.xml'))
|
|
self.assertEqual(P('a/Dot ending.').with_name('d.xml'), P('a/d.xml'))
|
|
self.assertEqual(P('/a/Dot ending.').with_name('d.xml'), P('/a/d.xml'))
|
|
self.assertRaises(ValueError, P('a/b').with_name, '/c')
|
|
self.assertRaises(ValueError, P('a/b').with_name, 'c/')
|
|
self.assertRaises(ValueError, P('a/b').with_name, 'c/d')
|
|
|
|
def test_with_stem(self):
|
|
P = self.cls
|
|
self.assertEqual(P('a/b').with_stem('d'), P('a/d'))
|
|
self.assertEqual(P('/a/b').with_stem('d'), P('/a/d'))
|
|
self.assertEqual(P('a/b.py').with_stem('d'), P('a/d.py'))
|
|
self.assertEqual(P('/a/b.py').with_stem('d'), P('/a/d.py'))
|
|
self.assertEqual(P('/a/b.tar.gz').with_stem('d'), P('/a/d.gz'))
|
|
self.assertEqual(P('a/Dot ending.').with_stem('d'), P('a/d.'))
|
|
self.assertEqual(P('/a/Dot ending.').with_stem('d'), P('/a/d.'))
|
|
self.assertRaises(ValueError, P('foo.gz').with_stem, '')
|
|
self.assertRaises(ValueError, P('/a/b/foo.gz').with_stem, '')
|
|
self.assertRaises(ValueError, P('a/b').with_stem, '/c')
|
|
self.assertRaises(ValueError, P('a/b').with_stem, 'c/')
|
|
self.assertRaises(ValueError, P('a/b').with_stem, 'c/d')
|
|
|
|
def test_with_suffix(self):
|
|
P = self.cls
|
|
self.assertEqual(P('a/b').with_suffix('.gz'), P('a/b.gz'))
|
|
self.assertEqual(P('/a/b').with_suffix('.gz'), P('/a/b.gz'))
|
|
self.assertEqual(P('a/b.py').with_suffix('.gz'), P('a/b.gz'))
|
|
self.assertEqual(P('/a/b.py').with_suffix('.gz'), P('/a/b.gz'))
|
|
# Stripping suffix.
|
|
self.assertEqual(P('a/b.py').with_suffix(''), P('a/b'))
|
|
self.assertEqual(P('/a/b').with_suffix(''), P('/a/b'))
|
|
# Single dot
|
|
self.assertEqual(P('a/b').with_suffix('.'), P('a/b.'))
|
|
self.assertEqual(P('/a/b').with_suffix('.'), P('/a/b.'))
|
|
self.assertEqual(P('a/b.py').with_suffix('.'), P('a/b.'))
|
|
self.assertEqual(P('/a/b.py').with_suffix('.'), P('/a/b.'))
|
|
# Path doesn't have a "filename" component.
|
|
self.assertRaises(ValueError, P('').with_suffix, '.gz')
|
|
self.assertRaises(ValueError, P('/').with_suffix, '.gz')
|
|
# Invalid suffix.
|
|
self.assertRaises(ValueError, P('a/b').with_suffix, 'gz')
|
|
self.assertRaises(ValueError, P('a/b').with_suffix, '/')
|
|
self.assertRaises(ValueError, P('a/b').with_suffix, '/.gz')
|
|
self.assertRaises(ValueError, P('a/b').with_suffix, 'c/d')
|
|
self.assertRaises(ValueError, P('a/b').with_suffix, '.c/.d')
|
|
self.assertRaises(ValueError, P('a/b').with_suffix, './.d')
|
|
self.assertRaises(ValueError, P('a/b').with_suffix, '.d/.')
|
|
self.assertRaises(TypeError, P('a/b').with_suffix, None)
|
|
|
|
|
|
class LexicalPathJoinTest(JoinTestBase, unittest.TestCase):
|
|
cls = LexicalPath
|
|
|
|
|
|
if not is_pypi:
|
|
from pathlib import PurePath, Path
|
|
|
|
class PurePathJoinTest(JoinTestBase, unittest.TestCase):
|
|
cls = PurePath
|
|
|
|
class PathJoinTest(JoinTestBase, unittest.TestCase):
|
|
cls = Path
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|