Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 900727 Details for
Bug 938210
dev-python/path-17.0.0 fails tests: "AttributeError: 'builtin_function_or_method' object has no attribute '__code__'. Did you mean: '__call__'?"
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
dev-python:path-17.0.0:20240819-133450.log
dev-python:path-17.0.0:20240819-133450.log (text/plain; charset=utf-8), 484.32 KB, created by
Jonathan Lovelace
on 2024-08-20 00:31:04 UTC
(
hide
)
Description:
dev-python:path-17.0.0:20240819-133450.log
Filename:
MIME Type:
Creator:
Jonathan Lovelace
Created:
2024-08-20 00:31:04 UTC
Size:
484.32 KB
patch
obsolete
>[32m * [39;49;00mPackage: dev-python/path-17.0.0:0 >[32m * [39;49;00mRepository: gentoo >[32m * [39;49;00mMaintainer: python@gentoo.org >[32m * [39;49;00mUSE: abi_x86_64 amd64 elibc_glibc kernel_linux python_targets_python3_12 test >[32m * [39;49;00mFEATURES: distcc fakeroot network-sandbox preserve-libs sandbox test userpriv usersandbox > [32m*[0m Build system packages: > [32m*[0m dev-python/gpep517 : 16 > [32m*[0m dev-python/installer : 0.7.0 > [32m*[0m dev-python/setuptools : 72.1.0 > [32m*[0m dev-python/setuptools-rust : 1.9.0-r1 > [32m*[0m dev-python/setuptools-scm : 8.1.0 > [32m*[0m dev-python/wheel : 0.43.0 > [32m*[0m python3_12: running distutils-r1_run_phase distutils-r1_python_compile > [32m*[0m Building the wheel for path-17.0.0 via setuptools.build_meta >python3.12 -m gpep517 build-wheel --prefix=/usr --backend setuptools.build_meta --output-fd 3 --wheel-dir /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/wheel >2024-08-19 09:34:54,662 gpep517 INFO Building wheel via backend setuptools.build_meta >2024-08-19 09:34:56,605 root INFO running bdist_wheel >2024-08-19 09:34:56,936 root INFO running build >2024-08-19 09:34:57,017 root INFO running build_py >2024-08-19 09:34:57,097 root INFO creating /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build >2024-08-19 09:34:57,098 root INFO creating /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/lib >2024-08-19 09:34:57,098 root INFO creating /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/lib/path >2024-08-19 09:34:57,099 root INFO copying path/__init__.py -> /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/lib/path >2024-08-19 09:34:57,099 root INFO copying path/matchers.py -> /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/lib/path >2024-08-19 09:34:57,100 root INFO copying path/classes.py -> /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/lib/path >2024-08-19 09:34:57,100 root INFO copying path/masks.py -> /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/lib/path >2024-08-19 09:34:57,101 root INFO creating /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/lib/path/compat >2024-08-19 09:34:57,101 root INFO copying path/compat/py38.py -> /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/lib/path/compat >2024-08-19 09:34:57,102 root INFO running egg_info >2024-08-19 09:34:57,183 root INFO writing path.egg-info/PKG-INFO >2024-08-19 09:34:57,188 root INFO writing dependency_links to path.egg-info/dependency_links.txt >2024-08-19 09:34:57,190 root INFO writing requirements to path.egg-info/requires.txt >2024-08-19 09:34:57,191 root INFO writing top-level names to path.egg-info/top_level.txt >[08/19/24 09:34:57] ERROR listing git files failed - pretending there aren't any git.py:26 >2024-08-19 09:34:57,684 root INFO reading manifest file 'path.egg-info/SOURCES.txt' >2024-08-19 09:34:57,685 root INFO adding license file 'LICENSE' >2024-08-19 09:34:57,687 root INFO writing manifest file 'path.egg-info/SOURCES.txt' >2024-08-19 09:34:57,688 root INFO copying path/__init__.pyi -> /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/lib/path >2024-08-19 09:34:57,688 root INFO copying path/classes.pyi -> /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/lib/path >2024-08-19 09:34:57,689 root INFO copying path/matchers.pyi -> /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/lib/path >2024-08-19 09:34:57,690 root INFO copying path/py.typed -> /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/lib/path >2024-08-19 09:34:57,691 root WARNING warning: build_py: byte-compiling is disabled, skipping. > >2024-08-19 09:34:57,849 root INFO installing to /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/bdist.linux-x86_64/wheel >2024-08-19 09:34:57,849 root INFO running install >2024-08-19 09:34:57,864 root INFO running install_lib >2024-08-19 09:34:57,945 root INFO creating /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/bdist.linux-x86_64 >2024-08-19 09:34:57,945 root INFO creating /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/bdist.linux-x86_64/wheel >2024-08-19 09:34:57,946 root INFO creating /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/bdist.linux-x86_64/wheel/path >2024-08-19 09:34:57,946 root INFO copying /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/lib/path/classes.pyi -> /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/bdist.linux-x86_64/wheel/path >2024-08-19 09:34:57,947 root INFO copying /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/lib/path/__init__.py -> /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/bdist.linux-x86_64/wheel/path >2024-08-19 09:34:57,947 root INFO copying /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/lib/path/py.typed -> /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/bdist.linux-x86_64/wheel/path >2024-08-19 09:34:57,948 root INFO creating /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/bdist.linux-x86_64/wheel/path/compat >2024-08-19 09:34:57,948 root INFO copying /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/lib/path/compat/py38.py -> /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/bdist.linux-x86_64/wheel/path/compat >2024-08-19 09:34:57,949 root INFO copying /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/lib/path/matchers.py -> /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/bdist.linux-x86_64/wheel/path >2024-08-19 09:34:57,949 root INFO copying /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/lib/path/classes.py -> /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/bdist.linux-x86_64/wheel/path >2024-08-19 09:34:57,950 root INFO copying /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/lib/path/__init__.pyi -> /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/bdist.linux-x86_64/wheel/path >2024-08-19 09:34:57,951 root INFO copying /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/lib/path/masks.py -> /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/bdist.linux-x86_64/wheel/path >2024-08-19 09:34:57,951 root INFO copying /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/lib/path/matchers.pyi -> /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/bdist.linux-x86_64/wheel/path >2024-08-19 09:34:57,952 root WARNING warning: install_lib: byte-compiling is disabled, skipping. > >2024-08-19 09:34:57,952 root INFO running install_egg_info >2024-08-19 09:34:58,032 root INFO Copying path.egg-info to /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/bdist.linux-x86_64/wheel/path-17.0.0-py3.12.egg-info >2024-08-19 09:34:58,034 root INFO running install_scripts >2024-08-19 09:34:58,040 root INFO creating /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/bdist.linux-x86_64/wheel/path-17.0.0.dist-info/WHEEL >2024-08-19 09:34:58,040 wheel INFO creating '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/wheel/.tmp-1b2u67d7/path-17.0.0-py3-none-any.whl' and adding '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/bdist.linux-x86_64/wheel' to it >2024-08-19 09:34:58,041 wheel INFO adding 'path/__init__.py' >2024-08-19 09:34:58,042 wheel INFO adding 'path/__init__.pyi' >2024-08-19 09:34:58,042 wheel INFO adding 'path/classes.py' >2024-08-19 09:34:58,043 wheel INFO adding 'path/classes.pyi' >2024-08-19 09:34:58,043 wheel INFO adding 'path/masks.py' >2024-08-19 09:34:58,044 wheel INFO adding 'path/matchers.py' >2024-08-19 09:34:58,044 wheel INFO adding 'path/matchers.pyi' >2024-08-19 09:34:58,045 wheel INFO adding 'path/py.typed' >2024-08-19 09:34:58,045 wheel INFO adding 'path/compat/py38.py' >2024-08-19 09:34:58,046 wheel INFO adding 'path-17.0.0.dist-info/LICENSE' >2024-08-19 09:34:58,046 wheel INFO adding 'path-17.0.0.dist-info/METADATA' >2024-08-19 09:34:58,047 wheel INFO adding 'path-17.0.0.dist-info/WHEEL' >2024-08-19 09:34:58,047 wheel INFO adding 'path-17.0.0.dist-info/top_level.txt' >2024-08-19 09:34:58,048 wheel INFO adding 'path-17.0.0.dist-info/RECORD' >2024-08-19 09:34:58,048 root INFO removing /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/build/bdist.linux-x86_64/wheel >2024-08-19 09:34:58,050 gpep517 INFO The backend produced /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/wheel/path-17.0.0-py3-none-any.whl > [32m*[0m Installing path-17.0.0-py3-none-any.whl to /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/install >python3.12 -m gpep517 install-wheel --destdir=/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/install --interpreter=/usr/bin/python3.12 --prefix=/usr --optimize=all /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/wheel/path-17.0.0-py3-none-any.whl >2024-08-19 09:34:58,246 gpep517 INFO Installing /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/wheel/path-17.0.0-py3-none-any.whl into /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/install >2024-08-19 09:34:58,309 gpep517 INFO Installation complete > [32m*[0m python3_12: running distutils-r1_run_phase python_test >python3.12 -m pytest -vv -ra -l -Wdefault -Werror::pytest.PytestUnhandledCoroutineWarning --color=yes -o console_output_style=count -o tmp_path_retention_count=0 -o tmp_path_retention_policy=failed -p no:cov -p no:flake8 -p no:flakes -p no:pylint -p no:markdown -p no:sugar -p no:xvfb -p no:pytest-describe -p no:plus -p no:tavern -p no:salt-factories --deselect test_path.py::TestPerformance >[1m============================================================================= test session starts ==============================================================================[0m >platform linux -- Python 3.12.3, pytest-8.3.2, pluggy-1.5.0 -- /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0-python3_12/install/usr/bin/python3.12 >cachedir: .pytest_cache >hypothesis profile 'default' -> database=DirectoryBasedExampleDatabase(PosixPath('/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/.hypothesis/examples')) >rootdir: /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0 >configfile: pytest.ini >plugins: timeout-2.3.1, pytest_codeblocks-0.17.0, rerunfailures-14.0, forked-1.6.0, console-scripts-1.4.1, expect-1.1.0, subtests-0.13.1, typeguard-4.3.0, mock-3.14.0, requests-mock-1.12.1, tornado-0.8.1, pytest_freezer-0.4.8, xprocess-1.0.2, betamax-0.9.0, Faker-26.0.0, import-check-0.0.4, pkgcore-0.12.27, regressions-2.5.0, pytest_httpserver-1.0.12, trio-0.8.0, aiohttp-1.0.5, asyncio-0.23.8, time-machine-2.14.2, datadir-1.5.0, home-0.5.1, httpbin-2.0.0, xdist-3.6.1, services-2.2.1, hypothesis-6.107.0, flaky-3.8.1, subprocess-1.5.2, jaraco.test-5.4.0, anyio-4.4.0, pyfakefs-5.6.0 >asyncio: mode=Mode.STRICT >[1mcollecting ... [0mcollected 118 items / 1 error > >==================================================================================== ERRORS ==================================================================================== >[31m[1m______________________________________________________________________ ERROR collecting path/__init__.py _______________________________________________________________________[0m >[1m[31m/usr/lib/python3.12/doctest.py[0m:948: in find > [0m[96mself[39;49;00m._find(tests, obj, name, module, source_lines, globs, {})[90m[39;49;00m > extraglobs = None > file = '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py' > globs = {'B_NEWLINE': re.compile(b'\r\n|\r|\n'), > 'B_NL_END': re.compile(b'\r\n|\r|\n$'), > 'Callable': typing.Callable, > 'DirectoryNotEmpty': <class 'path.DirectoryNotEmpty'>, > 'ExtantFile': <class 'path.ExtantFile'>, > 'ExtantPath': <class 'path.ExtantPath'>, > 'Handlers': <class 'path.Handlers'>, > 'Iterator': typing.Iterator, > 'LINESEPS': ['\r\n', '\r', '\n'], > 'Multi': <class 'path.Multi'>, > 'Number': <class 'numbers.Number'>, > 'Path': <class 'path.Path'>, > 'SpecialResolver': <class 'path.SpecialResolver'>, > 'TYPE_CHECKING': False, > 'TempDir': <class 'path.TempDir'>, > 'Traversal': <class 'path.Traversal'>, > 'TreeWalkWarning': <class 'path.TreeWalkWarning'>, > 'U_LINESEPS': ['\r\n', '\r', '\n', '\x85', '\u2028', '\u2029'], > 'U_NEWLINE': re.compile('\r\n|\r|\n|\x85|\u2028|\u2029'), > 'U_NL_END': re.compile('\r\n|\r|\n|\x85|\u2028|\u2029$'), > '__all__': ['Path', 'TempDir'], > '__builtins__': {'ArithmeticError': <class 'ArithmeticError'>, > 'AssertionError': <class 'AssertionError'>, > 'AttributeError': <class 'AttributeError'>, > 'BaseException': <class 'BaseException'>, > 'BaseExceptionGroup': <class 'BaseExceptionGroup'>, > 'BlockingIOError': <class 'BlockingIOError'>, > 'BrokenPipeError': <class 'BrokenPipeError'>, > 'BufferError': <class 'BufferError'>, > 'BytesWarning': <class 'BytesWarning'>, > 'ChildProcessError': <class 'ChildProcessError'>, > 'ConnectionAbortedError': <class 'ConnectionAbortedError'>, > 'ConnectionError': <class 'ConnectionError'>, > 'ConnectionRefusedError': <class 'ConnectionRefusedError'>, > 'ConnectionResetError': <class 'ConnectionResetError'>, > 'DeprecationWarning': <class 'DeprecationWarning'>, > 'EOFError': <class 'EOFError'>, > 'Ellipsis': Ellipsis, > 'EncodingWarning': <class 'EncodingWarning'>, > 'EnvironmentError': <class 'OSError'>, > 'Exception': <class 'Exception'>, > 'ExceptionGroup': <class 'ExceptionGroup'>, > 'False': False, > 'FileExistsError': <class 'FileExistsError'>, > 'FileNotFoundError': <class 'FileNotFoundError'>, > 'FloatingPointError': <class 'FloatingPointError'>, > 'FutureWarning': <class 'FutureWarning'>, > 'GeneratorExit': <class 'GeneratorExit'>, > 'IOError': <class 'OSError'>, > 'ImportError': <class 'ImportError'>, > 'ImportWarning': <class 'ImportWarning'>, > 'IndentationError': <class 'IndentationError'>, > 'IndexError': <class 'IndexError'>, > 'InterruptedError': <class 'InterruptedError'>, > 'IsADirectoryError': <class 'IsADirectoryError'>, > 'KeyError': <class 'KeyError'>, > 'KeyboardInterrupt': <class 'KeyboardInterrupt'>, > 'LookupError': <class 'LookupError'>, > 'MemoryError': <class 'MemoryError'>, > 'ModuleNotFoundError': <class 'ModuleNotFoundError'>, > 'NameError': <class 'NameError'>, > 'None': None, > 'NotADirectoryError': <class 'NotADirectoryError'>, > 'NotImplemented': NotImplemented, > 'NotImplementedError': <class 'NotImplementedError'>, > 'OSError': <class 'OSError'>, > 'OverflowError': <class 'OverflowError'>, > 'PendingDeprecationWarning': <class 'PendingDeprecationWarning'>, > 'PermissionError': <class 'PermissionError'>, > 'ProcessLookupError': <class 'ProcessLookupError'>, > 'RecursionError': <class 'RecursionError'>, > 'ReferenceError': <class 'ReferenceError'>, > 'ResourceWarning': <class 'ResourceWarning'>, > 'RuntimeError': <class 'RuntimeError'>, > 'RuntimeWarning': <class 'RuntimeWarning'>, > 'StopAsyncIteration': <class 'StopAsyncIteration'>, > 'StopIteration': <class 'StopIteration'>, > 'SyntaxError': <class 'SyntaxError'>, > 'SyntaxWarning': <class 'SyntaxWarning'>, > 'SystemError': <class 'SystemError'>, > 'SystemExit': <class 'SystemExit'>, > 'TabError': <class 'TabError'>, > 'TimeoutError': <class 'TimeoutError'>, > 'True': True, > 'TypeError': <class 'TypeError'>, > 'UnboundLocalError': <class 'UnboundLocalError'>, > 'UnicodeDecodeError': <class 'UnicodeDecodeError'>, > 'UnicodeEncodeError': <class 'UnicodeEncodeError'>, > 'UnicodeError': <class 'UnicodeError'>, > 'UnicodeTranslateError': <class 'UnicodeTranslateError'>, > 'UnicodeWarning': <class 'UnicodeWarning'>, > 'UserWarning': <class 'UserWarning'>, > 'ValueError': <class 'ValueError'>, > 'Warning': <class 'Warning'>, > 'ZeroDivisionError': <class 'ZeroDivisionError'>, > '__build_class__': <built-in function __build_class__>, > '__debug__': True, > '__doc__': 'Built-in functions, types, exceptions, and other ' > 'objects.\n' > '\n' > 'This module provides direct access to all ' > "'built-in'\n" > 'identifiers of Python; for example, builtins.len ' > 'is\n' > 'the full name for the built-in function len().\n' > '\n' > 'This module is not normally accessed explicitly ' > 'by most\n' > 'applications, but can be useful in modules that ' > 'provide\n' > 'objects with the same name as a built-in value, ' > 'but in\n' > 'which the built-in of that name is also needed.', > '__import__': <built-in function __import__>, > '__loader__': <class '_frozen_importlib.BuiltinImporter'>, > '__name__': 'builtins', > '__package__': '', > '__spec__': ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>, origin='built-in'), > 'abs': <built-in function abs>, > 'aiter': <built-in function aiter>, > 'all': <built-in function all>, > 'anext': <built-in function anext>, > 'any': <built-in function any>, > 'ascii': <built-in function ascii>, > 'bin': <built-in function bin>, > 'bool': <class 'bool'>, > 'breakpoint': <built-in function breakpoint>, > 'bytearray': <class 'bytearray'>, > 'bytes': <class 'bytes'>, > 'callable': <built-in function callable>, > 'chr': <built-in function chr>, > 'classmethod': <class 'classmethod'>, > 'compile': <built-in function compile>, > 'complex': <class 'complex'>, > 'copyright': Copyright (c) 2001-2023 Python Software Foundation. >All Rights Reserved. > >Copyright (c) 2000 BeOpen.com. >All Rights Reserved. > >Copyright (c) 1995-2001 Corporation for National Research Initiatives. >All Rights Reserved. > >Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam. >All Rights Reserved., > 'credits': Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands > for supporting Python development. See www.python.org for more information., > 'delattr': <built-in function delattr>, > 'dict': <class 'dict'>, > 'dir': <built-in function dir>, > 'divmod': <built-in function divmod>, > 'enumerate': <class 'enumerate'>, > 'eval': <built-in function eval>, > 'exec': <built-in function exec>, > 'exit': Use exit() or Ctrl-D (i.e. EOF) to exit, > 'filter': <class 'filter'>, > 'float': <class 'float'>, > 'format': <built-in function format>, > 'frozenset': <class 'frozenset'>, > 'getattr': <built-in function getattr>, > 'globals': <built-in function globals>, > 'hasattr': <built-in function hasattr>, > 'hash': <built-in function hash>, > 'help': Type help() for interactive help, or help(object) for help about object., > 'hex': <built-in function hex>, > 'id': <built-in function id>, > 'input': <built-in function input>, > 'int': <class 'int'>, > 'isinstance': <built-in function isinstance>, > 'issubclass': <built-in function issubclass>, > 'iter': <built-in function iter>, > 'len': <built-in function len>, > 'license': Type license() to see the full license text, > 'list': <class 'list'>, > 'locals': <built-in function locals>, > 'map': <class 'map'>, > 'max': <built-in function max>, > 'memoryview': <class 'memoryview'>, > 'min': <built-in function min>, > 'next': <built-in function next>, > 'object': <class 'object'>, > 'oct': <built-in function oct>, > 'open': <built-in function open>, > 'ord': <built-in function ord>, > 'pow': <built-in function pow>, > 'print': <built-in function print>, > 'property': <class 'property'>, > 'quit': Use quit() or Ctrl-D (i.e. EOF) to exit, > 'range': <class 'range'>, > 'repr': <built-in function repr>, > 'reversed': <class 'reversed'>, > 'round': <built-in function round>, > 'set': <class 'set'>, > 'setattr': <built-in function setattr>, > 'slice': <class 'slice'>, > 'sorted': <built-in function sorted>, > 'staticmethod': <class 'staticmethod'>, > 'str': <class 'str'>, > 'sum': <built-in function sum>, > 'super': <class 'super'>, > 'tuple': <class 'tuple'>, > 'type': <class 'type'>, > 'vars': <built-in function vars>, > 'zip': <class 'zip'>}, > '__cached__': '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__pycache__/__init__.cpython-312.pyc', > '__doc__': '\n' > 'Path Pie\n' > '\n' > 'Implements ``path.Path`` - An object representing a\n' > 'path to a file or directory.\n' > '\n' > 'Example::\n' > '\n' > ' from path import Path\n' > " d = Path('/home/guido/bin')\n" > '\n' > ' # Globbing\n' > " for f in d.files('*.py'):\n" > ' f.chmod(0o755)\n' > '\n' > ' # Changing the working directory:\n' > ' with Path("somewhere"):\n' > ' # cwd in now `somewhere`\n' > ' ...\n' > '\n' > ' # Concatenate paths with /\n' > ' foo_txt = Path("bar") / "foo.txt"\n', > '__file__': '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py', > '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f01aa694230>, > '__name__': 'path', > '__package__': 'path', > '__path__': ['/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path'], > '__pytest_asyncio_package_scoped_event_loop': <function pytest_collectstart.<locals>.scoped_event_loop at 0x7f01aa84dc60>, > '__pytest_asyncio_scoped_event_loop': <function pytest_collectstart.<locals>.scoped_event_loop at 0x7f01aa84e200>, > '__spec__': ModuleSpec(name='path', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7f01aa694230>, origin='/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py', submodule_search_locations=['/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path']), > '_default_linesep': <object object at 0x7f01aad185e0>, > '_make_timestamp_ns': <function _make_timestamp_ns at 0x7f01aa845ee0>, > '_strip_newlines': <function _strip_newlines at 0x7f01b0b88220>, > 'annotations': _Feature((3, 7, 0, 'beta', 1), None, 16777216), > 'builtins': <module 'builtins' (built-in)>, > 'classes': <module 'path.classes' from '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/classes.py'>, > 'compat': <module 'path.compat' (namespace) from ['/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/compat']>, > 'contextlib': <module 'contextlib' from '/usr/lib/python3.12/contextlib.py'>, > 'datetime': <module 'datetime' from '/usr/lib/python3.12/datetime.py'>, > 'errno': <module 'errno' (built-in)>, > 'fnmatch': <module 'fnmatch' from '/usr/lib/python3.12/fnmatch.py'>, > 'functools': <module 'functools' from '/usr/lib/python3.12/functools.py'>, > 'glob': <module 'glob' from '/usr/lib/python3.12/glob.py'>, > 'grp': <module 'grp' from '/usr/lib/python3.12/lib-dynload/grp.cpython-312-x86_64-linux-gnu.so'>, > 'hashlib': <module 'hashlib' from '/usr/lib/python3.12/hashlib.py'>, > 'importlib': <module 'importlib' from '/usr/lib/python3.12/importlib/__init__.py'>, > 'itertools': <module 'itertools' (built-in)>, > 'masks': <module 'path.masks' from '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/masks.py'>, > 'matchers': <module 'path.matchers' from '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/matchers.py'>, > 'only_newer': <function only_newer at 0x7f01aa84f9c0>, > 'os': <module 'os' (frozen)>, > 'overload': <function overload at 0x7f01b06491c0>, > 'pathlib': <module 'pathlib' from '/usr/lib/python3.12/pathlib.py'>, > 'pwd': <module 'pwd' (built-in)>, > 're': <module 're' from '/usr/lib/python3.12/re/__init__.py'>, > 'removeprefix': <function removeprefix at 0x7f01aa84f880>, > 'removesuffix': <function removesuffix at 0x7f01aa84f420>, > 'shutil': <module 'shutil' from '/usr/lib/python3.12/shutil.py'>, > 'sys': <module 'sys' (built-in)>, > 'tempfile': <module 'tempfile' from '/usr/lib/python3.12/tempfile.py'>, > 'warnings': <module 'warnings' from '/usr/lib/python3.12/warnings.py'>} > module = <module 'path' from '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py'> > name = 'path' > obj = <module 'path' from '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py'> > self = <_pytest.doctest.DoctestModule.collect.<locals>.MockAwareDocTestFinder object at 0x7f01aa91be60> > source_lines = ['"""\n', > 'Path Pie\n', > '\n', > 'Implements ``path.Path`` - An object representing a\n', > 'path to a file or directory.\n', > '\n', > 'Example::\n', > '\n', > ' from path import Path\n', > " d = Path('/home/guido/bin')\n", > '\n', > ' # Globbing\n', > " for f in d.files('*.py'):\n", > ' f.chmod(0o755)\n', > '\n', > ' # Changing the working directory:\n', > ' with Path("somewhere"):\n', > ' # cwd in now `somewhere`\n', > ' ...\n', > '\n', > ' # Concatenate paths with /\n', > ' foo_txt = Path("bar") / "foo.txt"\n', > '"""\n', > '\n', > 'from __future__ import annotations\n', > '\n', > 'import builtins\n', > 'import contextlib\n', > 'import datetime\n', > 'import errno\n', > 'import fnmatch\n', > 'import functools\n', > 'import glob\n', > 'import hashlib\n', > 'import importlib\n', > 'import itertools\n', > 'import os\n', > 'import pathlib\n', > 'import re\n', > 'import shutil\n', > 'import sys\n', > 'import tempfile\n', > 'import warnings\n', > 'from numbers import Number\n', > '\n', > 'with contextlib.suppress(ImportError):\n', > ' import win32security\n', > '\n', > 'with contextlib.suppress(ImportError):\n', > ' import pwd\n', > '\n', > 'with contextlib.suppress(ImportError):\n', > ' import grp\n', > '\n', > 'from typing import (\n', > ' TYPE_CHECKING,\n', > ' Callable,\n', > ' Iterator,\n', > ' overload,\n', > ')\n', > '\n', > 'if TYPE_CHECKING:\n', > ' from _typeshed import (\n', > ' OpenBinaryMode,\n', > ' OpenTextMode,\n', > ' )\n', > '\n', > 'from . import classes, masks, matchers\n', > 'from .compat.py38 import removeprefix, removesuffix\n', > '\n', > "__all__ = ['Path', 'TempDir']\n", > '\n', > '\n', > "LINESEPS = ['\\r\\n', '\\r', '\\n']\n", > "U_LINESEPS = LINESEPS + ['\\u0085', '\\u2028', '\\u2029']\n", > "B_NEWLINE = re.compile('|'.join(LINESEPS).encode())\n", > "U_NEWLINE = re.compile('|'.join(U_LINESEPS))\n", > "B_NL_END = re.compile(B_NEWLINE.pattern + b'$')\n", > "U_NL_END = re.compile(U_NEWLINE.pattern + '$')\n", > '\n', > '_default_linesep = object()\n', > '\n', > '\n', > 'def _make_timestamp_ns(value: Number | datetime.datetime) -> Number:\n', > ' timestamp_s = value if isinstance(value, Number) else ' > 'value.timestamp()\n', > ' return int(timestamp_s * 10**9)\n', > '\n', > '\n', > 'class TreeWalkWarning(Warning):\n', > ' pass\n', > '\n', > '\n', > 'class Traversal:\n', > ' """\n', > ' Wrap a walk result to customize the traversal.\n', > '\n', > ' `follow` is a function that takes an item and returns\n', > ' True if that item should be followed and False otherwise.\n', > '\n', > ' For example, to avoid traversing into directories that\n', > ' begin with `.`:\n', > '\n', > " >>> traverse = Traversal(lambda dir: not dir.startswith('.'))\n", > " >>> items = list(traverse(Path('.').walk()))\n", > '\n', > ' Directories beginning with `.` will appear in the results, but\n', > ' their children will not.\n', > '\n', > ' >>> dot_dir = next(item for item in items if item.is_dir() and ' > "item.startswith('.'))\n", > ' >>> any(item.parent == dot_dir for item in items)\n', > ' False\n', > ' """\n', > '\n', > ' def __init__(self, follow):\n', > ' self.follow = follow\n', > '\n', > ' def __call__(self, walker):\n', > ' traverse = None\n', > ' while True:\n', > ' try:\n', > ' item = walker.send(traverse)\n', > ' except StopIteration:\n', > ' return\n', > ' yield item\n', > '\n', > ' traverse = functools.partial(self.follow, item)\n', > '\n', > '\n', > 'def _strip_newlines(lines):\n', > ' r"""\n', > " >>> list(_strip_newlines(['Hello World\\r\\n', 'foo']))\n", > " ['Hello World', 'foo']\n", > ' """\n', > " return (U_NL_END.sub('', line) for line in lines)\n", > '\n', > '\n', > 'class Path(str):\n', > ' """\n', > ' Represents a filesystem path.\n', > '\n', > ' For documentation on individual methods, consult their\n', > ' counterparts in :mod:`os.path`.\n', > '\n', > ' Some methods are additionally included from :mod:`shutil`.\n', > ' The functions are linked directly into the class namespace\n', > ' such that they will be bound to the Path instance. For example,\n', > ' ``Path(src).copy(target)`` is equivalent to\n', > ' ``shutil.copy(src, target)``. Therefore, when referencing\n', > ' the docs for these methods, assume `src` references `self`,\n', > ' the Path instance.\n', > ' """\n', > '\n', > ' module = os.path\n', > ' """ The path module to use for path operations.\n', > '\n', > ' .. seealso:: :mod:`os.path`\n', > ' """\n', > '\n', > " def __new__(cls, other='.'):\n", > ' return super().__new__(cls, other)\n', > '\n', > " def __init__(self, other='.'):\n", > ' if other is None:\n', > ' raise TypeError("Invalid initial value for path: None")\n', > ' with contextlib.suppress(AttributeError):\n', > ' self._validate()\n', > '\n', > ' @classmethod\n', > ' @functools.lru_cache\n', > ' def using_module(cls, module):\n', > " subclass_name = cls.__name__ + '_' + module.__name__\n", > ' bases = (cls,)\n', > " ns = {'module': module}\n", > ' return type(subclass_name, bases, ns)\n', > '\n', > ' @classes.ClassProperty\n', > ' @classmethod\n', > ' def _next_class(cls):\n', > ' """\n', > ' What class should be used to construct new instances from this ' > 'class\n', > ' """\n', > ' return cls\n', > '\n', > ' # --- Special Python methods.\n', > '\n', > ' def __repr__(self):\n', > " return f'{type(self).__name__}({super().__repr__()})'\n", > '\n', > ' # Adding a Path and a string yields a Path.\n', > ' def __add__(self, more):\n', > ' return self._next_class(super().__add__(more))\n', > '\n', > ' def __radd__(self, other):\n', > ' return self._next_class(other.__add__(self))\n', > '\n', > ' # The / operator joins Paths.\n', > ' def __truediv__(self, rel):\n', > ' """fp.__truediv__(rel) == fp / rel == fp.joinpath(rel)\n', > '\n', > ' Join two path components, adding a separator character if\n', > ' needed.\n', > '\n', > ' .. seealso:: :func:`os.path.join`\n', > ' """\n', > ' return self._next_class(self.module.join(self, rel))\n', > '\n', > ' # The / operator joins Paths the other way around\n', > ' def __rtruediv__(self, rel):\n', > ' """fp.__rtruediv__(rel) == rel / fp\n', > '\n', > ' Join two path components, adding a separator character if\n', > ' needed.\n', > '\n', > ' .. seealso:: :func:`os.path.join`\n', > ' """\n', > ' return self._next_class(self.module.join(rel, self))\n', > '\n', > ' def __enter__(self):\n', > ' self._old_dir = self.cwd()\n', > ' os.chdir(self)\n', > ' return self\n', > '\n', > ' def __exit__(self, *_):\n', > ' os.chdir(self._old_dir)\n', > '\n', > ' @classmethod\n', > ' def cwd(cls):\n', > ' """Return the current working directory as a path object.\n', > '\n', > ' .. seealso:: :func:`os.getcwd`\n', > ' """\n', > ' return cls(os.getcwd())\n', > '\n', > ' @classmethod\n', > ' def home(cls) -> Path:\n', > " return cls(os.path.expanduser('~'))\n", > '\n', > ' #\n', > ' # --- Operations on Path strings.\n', > '\n', > ' def absolute(self):\n', > ' """.. seealso:: :func:`os.path.abspath`"""\n', > ' return self._next_class(self.module.abspath(self))\n', > '\n', > ' def normcase(self):\n', > ' """.. seealso:: :func:`os.path.normcase`"""\n', > ' return self._next_class(self.module.normcase(self))\n', > '\n', > ' def normpath(self):\n', > ' """.. seealso:: :func:`os.path.normpath`"""\n', > ' return self._next_class(self.module.normpath(self))\n', > '\n', > ' def realpath(self):\n', > ' """.. seealso:: :func:`os.path.realpath`"""\n', > ' return self._next_class(self.module.realpath(self))\n', > '\n', > ' def expanduser(self):\n', > ' """.. seealso:: :func:`os.path.expanduser`"""\n', > ' return self._next_class(self.module.expanduser(self))\n', > '\n', > ' def expandvars(self):\n', > ' """.. seealso:: :func:`os.path.expandvars`"""\n', > ' return self._next_class(self.module.expandvars(self))\n', > '\n', > ' def dirname(self):\n', > ' """.. seealso:: :attr:`parent`, :func:`os.path.dirname`"""\n', > ' return self._next_class(self.module.dirname(self))\n', > '\n', > ' def basename(self):\n', > ' """.. seealso:: :attr:`name`, :func:`os.path.basename`"""\n', > ' return self._next_class(self.module.basename(self))\n', > '\n', > ' def expand(self):\n', > ' """Clean up a filename by calling :meth:`expandvars()`,\n', > ' :meth:`expanduser()`, and :meth:`normpath()` on it.\n', > '\n', > ' This is commonly everything needed to clean up a filename\n', > ' read from a configuration file, for example.\n', > ' """\n', > ' return self.expandvars().expanduser().normpath()\n', > '\n', > ' @property\n', > ' def stem(self):\n', > ' """The same as :meth:`name`, but with one file extension stripped ' > 'off.\n', > '\n', > " >>> Path('/home/guido/python.tar.gz').stem\n", > " 'python.tar'\n", > ' """\n', > ' base, ext = self.module.splitext(self.name)\n', > ' return base\n', > '\n', > ' def with_stem(self, stem):\n', > ' """Return a new path with the stem changed.\n', > '\n', > ' >>> Path(\'/home/guido/python.tar.gz\').with_stem("foo")\n', > " Path('/home/guido/foo.gz')\n", > ' """\n', > ' return self.with_name(stem + self.suffix)\n', > '\n', > ' @property\n', > ' def suffix(self):\n', > ' """The file extension, for example ``\'.py\'``."""\n', > ' f, suffix = self.module.splitext(self)\n', > ' return suffix\n', > '\n', > ' def with_suffix(self, suffix):\n', > ' """Return a new path with the file suffix changed (or added, if ' > 'none)\n', > '\n', > ' >>> Path(\'/home/guido/python.tar.gz\').with_suffix(".foo")\n', > " Path('/home/guido/python.tar.foo')\n", > '\n', > " >>> Path('python').with_suffix('.zip')\n", > " Path('python.zip')\n", > '\n', > " >>> Path('filename.ext').with_suffix('zip')\n", > ' Traceback (most recent call last):\n', > ' ...\n', > " ValueError: Invalid suffix 'zip'\n", > ' """\n', > " if not suffix.startswith('.'):\n", > ' raise ValueError(f"Invalid suffix {suffix!r}")\n', > '\n', > ' return self.stripext() + suffix\n', > '\n', > ' @property\n', > ' def drive(self):\n', > ' """The drive specifier, for example ``\'C:\'``.\n', > '\n', > " This is always empty on systems that don't use drive specifiers.\n", > ' """\n', > ' drive, r = self.module.splitdrive(self)\n', > ' return self._next_class(drive)\n', > '\n', > ' parent = property(\n', > ' dirname,\n', > ' None,\n', > ' None,\n', > ' """ This path\'s parent directory, as a new Path object.\n', > '\n', > ' For example,\n', > " ``Path('/usr/local/lib/libpython.so').parent ==\n", > " Path('/usr/local/lib')``\n", > '\n', > ' .. seealso:: :meth:`dirname`, :func:`os.path.dirname`\n', > ' """,\n', > ' )\n', > '\n', > ' name = property(\n', > ' basename,\n', > ' None,\n', > ' None,\n', > ' """ The name of this file or directory without the full path.\n', > '\n', > ' For example,\n', > " ``Path('/usr/local/lib/libpython.so').name == 'libpython.so'``\n", > '\n', > ' .. seealso:: :meth:`basename`, :func:`os.path.basename`\n', > ' """,\n', > ' )\n', > '\n', > ' def with_name(self, name):\n', > ' """Return a new path with the name changed.\n', > '\n', > ' >>> Path(\'/home/guido/python.tar.gz\').with_name("foo.zip")\n', > " Path('/home/guido/foo.zip')\n", > ' """\n', > ' return self._next_class(removesuffix(self, self.name) + name)\n', > '\n', > ' def splitpath(self):\n', > ' """Return two-tuple of ``.parent``, ``.name``.\n', > '\n', > ' .. seealso:: :attr:`parent`, :attr:`name`, :func:`os.path.split`\n', > ' """\n', > ' parent, child = self.module.split(self)\n', > ' return self._next_class(parent), child\n', > '\n', > ' def splitdrive(self):\n', > ' """Return two-tuple of ``.drive`` and rest without drive.\n', > '\n', > ' Split the drive specifier from this path. If there is\n', > ' no drive specifier, :samp:`{p.drive}` is empty, so the return ' > 'value\n', > " is simply ``(Path(''), p)``. This is always the case on Unix.\n", > '\n', > ' .. seealso:: :func:`os.path.splitdrive`\n', > ' """\n', > ' drive, rel = self.module.splitdrive(self)\n', > ' return self._next_class(drive), self._next_class(rel)\n', > '\n', > ' def splitext(self):\n', > ' """Return two-tuple of ``.stripext()`` and ``.ext``.\n', > '\n', > ' Split the filename extension from this path and return\n', > ' the two parts. Either part may be empty.\n', > '\n', > " The extension is everything from ``'.'`` to the end of the\n", > ' last path segment. This has the property that if\n', > ' ``(a, b) == p.splitext()``, then ``a + b == p``.\n', > '\n', > ' .. seealso:: :func:`os.path.splitext`\n', > ' """\n', > ' filename, ext = self.module.splitext(self)\n', > ' return self._next_class(filename), ext\n', > '\n', > ' def stripext(self):\n', > ' """Remove one file extension from the path.\n', > '\n', > " For example, ``Path('/home/guido/python.tar.gz').stripext()``\n", > " returns ``Path('/home/guido/python.tar')``.\n", > ' """\n', > ' return self.splitext()[0]\n', > '\n', > ' @classes.multimethod\n', > ' def joinpath(cls, first, *others):\n', > ' """\n', > ' Join first to zero or more :class:`Path` components,\n', > ' adding a separator character (:samp:`{first}.module.sep`)\n', > ' if needed. Returns a new instance of\n', > ' :samp:`{first}._next_class`.\n', > '\n', > ' .. seealso:: :func:`os.path.join`\n', > ' """\n', > ' return cls._next_class(cls.module.join(first, *others))\n', > '\n', > ' def splitall(self):\n', > ' r"""Return a list of the path components in this path.\n', > '\n', > ' The first item in the list will be a Path. Its value will be\n', > ' either :data:`os.curdir`, :data:`os.pardir`, empty, or the root\n', > " directory of this path (for example, ``'/'`` or ``'C:\\\\'``). " > 'The\n', > ' other items in the list will be strings.\n', > '\n', > ' ``Path.joinpath(*result)`` will yield the original path.\n', > '\n', > " >>> Path('/foo/bar/baz').splitall()\n", > " [Path('/'), 'foo', 'bar', 'baz']\n", > ' """\n', > ' return list(self._parts())\n', > '\n', > ' def parts(self):\n', > ' """\n', > " >>> Path('/foo/bar/baz').parts()\n", > " (Path('/'), 'foo', 'bar', 'baz')\n", > ' """\n', > ' return tuple(self._parts())\n', > '\n', > ' def _parts(self):\n', > ' return reversed(tuple(self._parts_iter()))\n', > '\n', > ' def _parts_iter(self):\n', > ' loc = self\n', > ' while loc != os.curdir and loc != os.pardir:\n', > ' prev = loc\n', > ' loc, child = prev.splitpath()\n', > ' if loc == prev:\n', > ' break\n', > ' yield child\n', > ' yield loc\n', > '\n', > " def relpath(self, start='.'):\n", > ' """Return this path as a relative path,\n', > ' based from `start`, which defaults to the current working ' > 'directory.\n', > ' """\n', > ' cwd = self._next_class(start)\n', > ' return cwd.relpathto(self)\n', > '\n', > ' def relpathto(self, dest):\n', > ' """Return a relative path from `self` to `dest`.\n', > '\n', > ' If there is no relative path from `self` to `dest`, for example if\n', > ' they reside on different drives in Windows, then this returns\n', > ' ``dest.absolute()``.\n', > ' """\n', > ' origin = self.absolute()\n', > ' dest = self._next_class(dest).absolute()\n', > '\n', > ' orig_list = origin.normcase().splitall()\n', > " # Don't normcase dest! We want to preserve the case.\n", > ' dest_list = dest.splitall()\n', > '\n', > ' if orig_list[0] != self.module.normcase(dest_list[0]):\n', > " # Can't get here from there.\n", > ' return dest\n', > '\n', > ' # Find the location where the two paths start to differ.\n', > ' i = 0\n', > ' for start_seg, dest_seg in zip(orig_list, dest_list):\n', > ' if start_seg != self.module.normcase(dest_seg):\n', > ' break\n', > ' i += 1\n', > '\n', > ' # Now i is the point where the two paths diverge.\n', > ' # Need a certain number of "os.pardir"s to work up\n', > ' # from the origin to the point of divergence.\n', > ' segments = [os.pardir] * (len(orig_list) - i)\n', > ' # Need to add the diverging part of dest_list.\n', > ' segments += dest_list[i:]\n', > ' if len(segments) == 0:\n', > ' # If they happen to be identical, use os.curdir.\n', > ' relpath = os.curdir\n', > ' else:\n', > ' relpath = self.module.join(*segments)\n', > ' return self._next_class(relpath)\n', > '\n', > ' # --- Listing, searching, walking, and matching\n', > '\n', > ' def iterdir(self, match=None):\n', > ' """Yields items in this directory.\n', > '\n', > ' Use :meth:`files` or :meth:`dirs` instead if you want a listing\n', > ' of just files or just subdirectories.\n', > '\n', > ' The elements of the list are Path objects.\n', > '\n', > ' With the optional `match` argument, a callable,\n', > ' only return items whose names match the given pattern.\n', > '\n', > ' .. seealso:: :meth:`files`, :meth:`dirs`\n', > ' """\n', > ' match = matchers.load(match)\n', > ' return filter(match, (self / child for child in os.listdir(self)))\n', > '\n', > ' def dirs(self, *args, **kwargs):\n', > ' """List of this directory\'s subdirectories.\n', > '\n', > ' The elements of the list are Path objects.\n', > ' This does not walk recursively into subdirectories\n', > ' (but see :meth:`walkdirs`).\n', > '\n', > ' Accepts parameters to :meth:`iterdir`.\n', > ' """\n', > ' return [p for p in self.iterdir(*args, **kwargs) if p.is_dir()]\n', > '\n', > ' def files(self, *args, **kwargs):\n', > ' """List of the files in self.\n', > '\n', > ' The elements of the list are Path objects.\n', > ' This does not walk into subdirectories (see :meth:`walkfiles`).\n', > '\n', > ' Accepts parameters to :meth:`iterdir`.\n', > ' """\n', > '\n', > ' return [p for p in self.iterdir(*args, **kwargs) if p.is_file()]\n', > '\n', > " def walk(self, match=None, errors='strict'):\n", > ' """Iterator over files and subdirs, recursively.\n', > '\n', > ' The iterator yields Path objects naming each child item of\n', > ' this directory and its descendants. This requires that\n', > ' ``D.is_dir()``.\n', > '\n', > ' This performs a depth-first traversal of the directory tree.\n', > ' Each directory is returned just before all its children.\n', > '\n', > ' The `errors=` keyword argument controls behavior when an\n', > " error occurs. The default is ``'strict'``, which causes an\n", > " exception. Other allowed values are ``'warn'`` (which\n", > " reports the error via :func:`warnings.warn()`), and ``'ignore'``.\n", > ' `errors` may also be an arbitrary callable taking a msg parameter.\n', > ' """\n', > '\n', > ' errors = Handlers._resolve(errors)\n', > ' match = matchers.load(match)\n', > '\n', > ' try:\n', > ' childList = self.iterdir()\n', > ' except Exception as exc:\n', > ' errors(f"Unable to list directory \'{self}\': {exc}")\n', > ' return\n', > '\n', > ' for child in childList:\n', > ' traverse = None\n', > ' if match(child):\n', > ' traverse = yield child\n', > ' traverse = traverse or child.is_dir\n', > ' try:\n', > ' do_traverse = traverse()\n', > ' except Exception as exc:\n', > ' errors(f"Unable to access \'{child}\': {exc}")\n', > ' continue\n', > '\n', > ' if do_traverse:\n', > ' yield from child.walk(errors=errors, match=match)\n', > '\n', > ' def walkdirs(self, *args, **kwargs):\n', > ' """Iterator over subdirs, recursively."""\n', > ' return (item for item in self.walk(*args, **kwargs) if ' > 'item.is_dir())\n', > '\n', > ' def walkfiles(self, *args, **kwargs):\n', > ' """Iterator over files, recursively."""\n', > ' return (item for item in self.walk(*args, **kwargs) if ' > 'item.is_file())\n', > '\n', > ' def fnmatch(self, pattern, normcase=None):\n', > ' """Return ``True`` if `self.name` matches the given `pattern`.\n', > '\n', > ' `pattern` - A filename pattern with wildcards,\n', > " for example ``'*.py'``. If the pattern contains a `normcase`\n", > ' attribute, it is applied to the name and path prior to ' > 'comparison.\n', > '\n', > ' `normcase` - (optional) A function used to normalize the pattern ' > 'and\n', > ' filename before matching. Defaults to normcase from\n', > ' ``self.module``, :func:`os.path.normcase`.\n', > '\n', > ' .. seealso:: :func:`fnmatch.fnmatch`\n', > ' """\n', > " default_normcase = getattr(pattern, 'normcase', " > 'self.module.normcase)\n', > ' normcase = normcase or default_normcase\n', > ' name = normcase(self.name)\n', > ' pattern = normcase(pattern)\n', > ' return fnmatch.fnmatchcase(name, pattern)\n', > '\n', > ' def glob(self, pattern):\n', > ' """Return a list of Path objects that match the pattern.\n', > '\n', > ' `pattern` - a path relative to this directory, with wildcards.\n', > '\n', > " For example, ``Path('/users').glob('*/bin/*')`` returns a list\n", > ' of all the files users have in their :file:`bin` directories.\n', > '\n', > ' .. seealso:: :func:`glob.glob`\n', > '\n', > ' .. note:: Glob is **not** recursive, even when using ``**``.\n', > ' To do recursive globbing see :func:`walk`,\n', > ' :func:`walkdirs` or :func:`walkfiles`.\n', > ' """\n', > ' cls = self._next_class\n', > ' return [cls(s) for s in glob.glob(self / pattern)]\n', > '\n', > ' def iglob(self, pattern):\n', > ' """Return an iterator of Path objects that match the pattern.\n', > '\n', > ' `pattern` - a path relative to this directory, with wildcards.\n', > '\n', > " For example, ``Path('/users').iglob('*/bin/*')`` returns an\n", > ' iterator of all the files users have in their :file:`bin`\n', > ' directories.\n', > '\n', > ' .. seealso:: :func:`glob.iglob`\n', > '\n', > ' .. note:: Glob is **not** recursive, even when using ``**``.\n', > ' To do recursive globbing see :func:`walk`,\n', > ' :func:`walkdirs` or :func:`walkfiles`.\n', > ' """\n', > ' cls = self._next_class\n', > ' return (cls(s) for s in glob.iglob(self / pattern))\n', > '\n', > ' #\n', > ' # --- Reading or writing an entire file at once.\n', > '\n', > ' @functools.wraps(open, assigned=())\n', > ' def open(self, *args, **kwargs):\n', > ' """Open this file and return a corresponding file object.\n', > '\n', > ' Keyword arguments work as in :func:`io.open`. If the file cannot ' > 'be\n', > ' opened, an :class:`OSError` is raised.\n', > ' """\n', > ' return open(self, *args, **kwargs)\n', > '\n', > ' def bytes(self):\n', > ' """Open this file, read all bytes, return them as a string."""\n', > " with self.open('rb') as f:\n", > ' return f.read()\n', > '\n', > ' @overload\n', > ' def chunks(\n', > ' self,\n', > ' size: int,\n', > ' mode: OpenTextMode = ...,\n', > ' buffering: int = ...,\n', > ' encoding: str | None = ...,\n', > ' errors: str | None = ...,\n', > ' newline: str | None = ...,\n', > ' closefd: bool = ...,\n', > ' opener: Callable[[str, int], int] | None = ...,\n', > ' ) -> Iterator[str]: ...\n', > '\n', > ' @overload\n', > ' def chunks(\n', > ' self,\n', > ' size: int,\n', > ' mode: OpenBinaryMode,\n', > ' buffering: int = ...,\n', > ' encoding: str | None = ...,\n', > ' errors: str | None = ...,\n', > ' newline: str | None = ...,\n', > ' closefd: bool = ...,\n', > ' opener: Callable[[str, int], int] | None = ...,\n', > ' ) -> Iterator[builtins.bytes]: ...\n', > '\n', > ' @overload\n', > ' def chunks(\n', > ' self,\n', > ' size: int,\n', > ' mode: str,\n', > ' buffering: int = ...,\n', > ' encoding: str | None = ...,\n', > ' errors: str | None = ...,\n', > ' newline: str | None = ...,\n', > ' closefd: bool = ...,\n', > ' opener: Callable[[str, int], int] | None = ...,\n', > ' ) -> Iterator[str | builtins.bytes]: ...\n', > '\n', > ' def chunks(self, size, *args, **kwargs):\n', > ' """Returns a generator yielding chunks of the file, so it can\n', > ' be read piece by piece with a simple for loop.\n', > '\n', > ' Any argument you pass after `size` will be passed to :meth:`open`.\n', > '\n', > ' :example:\n', > '\n', > ' >>> hash = hashlib.md5()\n', > ' >>> for chunk in Path("NEWS.rst").chunks(8192, mode=\'rb\'):\n', > ' ... hash.update(chunk)\n', > '\n', > ' This will read the file by chunks of 8192 bytes.\n', > ' """\n', > ' with self.open(*args, **kwargs) as f:\n', > ' yield from iter(lambda: f.read(size) or None, None)\n', > '\n', > ' def write_bytes(self, bytes, append=False):\n', > ' """Open this file and write the given bytes to it.\n', > '\n', > ' Default behavior is to overwrite any existing file.\n', > ' Call ``p.write_bytes(bytes, append=True)`` to append instead.\n', > ' """\n', > " with self.open('ab' if append else 'wb') as f:\n", > ' f.write(bytes)\n', > '\n', > ' def read_text(self, encoding=None, errors=None):\n', > ' r"""Open this file, read it in, return the content as a string.\n', > '\n', > ' Optional parameters are passed to :meth:`open`.\n', > '\n', > ' .. seealso:: :meth:`lines`\n', > ' """\n', > ' with self.open(encoding=encoding, errors=errors) as f:\n', > ' return f.read()\n', > '\n', > ' def read_bytes(self):\n', > ' r"""Return the contents of this file as bytes."""\n', > " with self.open(mode='rb') as f:\n", > ' return f.read()\n', > '\n', > ' def write_text(\n', > ' self,\n', > ' text: str,\n', > ' encoding: str | None = None,\n', > " errors: str = 'strict',\n", > ' linesep: str | None = os.linesep,\n', > ' append: bool = False,\n', > ' ) -> None:\n', > ' r"""Write the given text to this file.\n', > '\n', > ' The default behavior is to overwrite any existing file;\n', > ' to append instead, use the `append=True` keyword argument.\n', > '\n', > ' There are two differences between :meth:`write_text` and\n', > ' :meth:`write_bytes`: newline handling and Unicode handling.\n', > ' See below.\n', > '\n', > ' Parameters:\n', > '\n', > ' `text` - str - The text to be written.\n', > '\n', > ' `encoding` - str - The text encoding used.\n', > '\n', > ' `errors` - str - How to handle Unicode encoding errors.\n', > " Default is ``'strict'``. See ``help(unicode.encode)`` for " > 'the\n', > " options. Ignored if `text` isn't a Unicode string.\n", > '\n', > ' `linesep` - keyword argument - str/unicode - The sequence of\n', > ' characters to be used to mark end-of-line. The default is\n', > ' :data:`os.linesep`. Specify ``None`` to\n', > ' use newlines unmodified.\n', > '\n', > ' `append` - keyword argument - bool - Specifies what to do if\n', > ' the file already exists (``True``: append to the end of it;\n', > ' ``False``: overwrite it). The default is ``False``.\n', > '\n', > '\n', > ' --- Newline handling.\n', > '\n', > ' ``write_text()`` converts all standard end-of-line sequences\n', > " (``'\\n'``, ``'\\r'``, and ``'\\r\\n'``) to your platform's " > 'default\n', > ' end-of-line sequence (see :data:`os.linesep`; on Windows, for ' > 'example,\n', > " the end-of-line marker is ``'\\r\\n'``).\n", > '\n', > " To override the platform's default, pass the `linesep=`\n", > ' keyword argument. To preserve the newlines as-is, pass\n', > ' ``linesep=None``.\n', > '\n', > ' This handling applies to Unicode text and bytes, except\n', > ' with Unicode, additional non-ASCII newlines are recognized:\n', > ' ``\\x85``, ``\\r\\x85``, and ``\\u2028``.\n', > '\n', > ' --- Unicode\n', > '\n', > ' `text` is written using the\n', > ' specified `encoding` (or the default encoding if `encoding`\n', > " isn't specified). The `errors` argument applies only to this\n", > ' conversion.\n', > ' """\n', > ' if linesep is not None:\n', > ' text = U_NEWLINE.sub(linesep, text)\n', > ' bytes = text.encode(encoding or sys.getdefaultencoding(), errors)\n', > ' self.write_bytes(bytes, append=append)\n', > '\n', > ' def lines(self, encoding=None, errors=None, retain=True):\n', > ' r"""Open this file, read all lines, return them in a list.\n', > '\n', > ' Optional arguments:\n', > ' `encoding` - The Unicode encoding (or character set) of\n', > ' the file. The default is ``None``, meaning use\n', > ' ``locale.getpreferredencoding()``.\n', > ' `errors` - How to handle Unicode errors; see\n', > ' `open ' > '<https://docs.python.org/3/library/functions.html#open>`_\n', > ' for the options. Default is ``None`` meaning "strict".\n', > ' `retain` - If ``True`` (default), retain newline characters,\n', > ' but translate all newline\n', > ' characters to ``\\n``. If ``False``, newline characters ' > 'are\n', > ' omitted.\n', > ' """\n', > " text = U_NEWLINE.sub('\\n', self.read_text(encoding, errors))\n", > ' return text.splitlines(retain)\n', > '\n', > ' def write_lines(\n', > ' self,\n', > ' lines,\n', > ' encoding=None,\n', > " errors='strict',\n", > ' *,\n', > ' append=False,\n', > ' ):\n', > ' r"""Write the given lines of text to this file.\n', > '\n', > ' By default this overwrites any existing file at this path.\n', > '\n', > ' Puts a platform-specific newline sequence on every line.\n', > '\n', > ' `lines` - A list of strings.\n', > '\n', > ' `encoding` - A Unicode encoding to use. This applies only if\n', > ' `lines` contains any Unicode strings.\n', > '\n', > ' `errors` - How to handle errors in Unicode encoding. This\n', > ' also applies only to Unicode strings.\n', > '\n', > ' Use the keyword argument ``append=True`` to append lines to the\n', > ' file. The default is to overwrite the file.\n', > ' """\n', > " mode = 'a' if append else 'w'\n", > " with self.open(mode, encoding=encoding, errors=errors, newline='') " > 'as f:\n', > ' f.writelines(self._replace_linesep(lines))\n', > '\n', > ' @staticmethod\n', > ' def _replace_linesep(lines):\n', > ' return (line + os.linesep for line in _strip_newlines(lines))\n', > '\n', > ' def read_md5(self):\n', > ' """Calculate the md5 hash for this file.\n', > '\n', > ' This reads through the entire file.\n', > '\n', > ' .. seealso:: :meth:`read_hash`\n', > ' """\n', > " return self.read_hash('md5')\n", > '\n', > ' def _hash(self, hash_name):\n', > ' """Returns a hash object for the file at the current path.\n', > '\n', > " `hash_name` should be a hash algo name (such as ``'md5'``\n", > " or ``'sha1'``) that's available in the :mod:`hashlib` module.\n", > ' """\n', > ' m = hashlib.new(hash_name)\n', > ' for chunk in self.chunks(8192, mode="rb"):\n', > ' m.update(chunk)\n', > ' return m\n', > '\n', > ' def read_hash(self, hash_name):\n', > ' """Calculate given hash for this file.\n', > '\n', > ' List of supported hashes can be obtained from :mod:`hashlib` ' > 'package.\n', > ' This reads the entire file.\n', > '\n', > ' .. seealso:: :meth:`hashlib.hash.digest`\n', > ' """\n', > ' return self._hash(hash_name).digest()\n', > '\n', > ' def read_hexhash(self, hash_name):\n', > ' """Calculate given hash for this file, returning hexdigest.\n', > '\n', > ' List of supported hashes can be obtained from :mod:`hashlib` ' > 'package.\n', > ' This reads the entire file.\n', > '\n', > ' .. seealso:: :meth:`hashlib.hash.hexdigest`\n', > ' """\n', > ' return self._hash(hash_name).hexdigest()\n', > '\n', > ' # --- Methods for querying the filesystem.\n', > ' # N.B. On some platforms, the os.path functions may be implemented in ' > 'C\n', > " # (e.g. isdir on Windows, Python 3.2.2), and compiled functions don't " > 'get\n', > ' # bound. Playing it safe and wrapping them all in method calls.\n', > '\n', > ' def isabs(self):\n', > ' """\n', > " >>> Path('.').isabs()\n", > ' False\n', > '\n', > ' .. seealso:: :func:`os.path.isabs`\n', > ' """\n', > ' return self.module.isabs(self)\n', > '\n', > ' def exists(self):\n', > ' """.. seealso:: :func:`os.path.exists`"""\n', > ' return self.module.exists(self)\n', > '\n', > ' def is_dir(self):\n', > ' """.. seealso:: :func:`os.path.isdir`"""\n', > ' return self.module.isdir(self)\n', > '\n', > ' def is_file(self):\n', > ' """.. seealso:: :func:`os.path.isfile`"""\n', > ' return self.module.isfile(self)\n', > '\n', > ' def islink(self):\n', > ' """.. seealso:: :func:`os.path.islink`"""\n', > ' return self.module.islink(self)\n', > '\n', > ' def ismount(self):\n', > ' """\n', > " >>> Path('.').ismount()\n", > ' False\n', > '\n', > ' .. seealso:: :func:`os.path.ismount`\n', > ' """\n', > ' return self.module.ismount(self)\n', > '\n', > ' def samefile(self, other):\n', > ' """.. seealso:: :func:`os.path.samefile`"""\n', > ' return self.module.samefile(self, other)\n', > '\n', > ' def getatime(self):\n', > ' """.. seealso:: :attr:`atime`, :func:`os.path.getatime`"""\n', > ' return self.module.getatime(self)\n', > '\n', > ' def set_atime(self, value):\n', > ' mtime_ns = self.stat().st_atime_ns\n', > ' self.utime(ns=(_make_timestamp_ns(value), mtime_ns))\n', > '\n', > ' atime = property(\n', > ' getatime,\n', > ' set_atime,\n', > ' None,\n', > ' """\n', > ' Last access time of the file.\n', > '\n', > " >>> Path('.').atime > 0\n", > ' True\n', > '\n', > ' Allows setting:\n', > '\n', > ' >>> some_file = ' > "Path(getfixture('tmp_path')).joinpath('file.txt').touch()\n", > ' >>> MST = datetime.timezone(datetime.timedelta(hours=-7))\n', > ' >>> some_file.atime = datetime.datetime(1976, 5, 7, 10, ' > 'tzinfo=MST)\n', > ' >>> some_file.atime\n', > ' 200336400.0\n', > '\n', > ' .. seealso:: :meth:`getatime`, :func:`os.path.getatime`\n', > ' """,\n', > ' )\n', > '\n', > ' def getmtime(self):\n', > ' """.. seealso:: :attr:`mtime`, :func:`os.path.getmtime`"""\n', > ' return self.module.getmtime(self)\n', > '\n', > ' def set_mtime(self, value):\n', > ' atime_ns = self.stat().st_atime_ns\n', > ' self.utime(ns=(atime_ns, _make_timestamp_ns(value)))\n', > '\n', > ' mtime = property(\n', > ' getmtime,\n', > ' set_mtime,\n', > ' None,\n', > ' """\n', > ' Last modified time of the file.\n', > '\n', > ' Allows setting:\n', > '\n', > ' >>> some_file = ' > "Path(getfixture('tmp_path')).joinpath('file.txt').touch()\n", > ' >>> MST = datetime.timezone(datetime.timedelta(hours=-7))\n', > ' >>> some_file.mtime = datetime.datetime(1976, 5, 7, 10, ' > 'tzinfo=MST)\n', > ' >>> some_file.mtime\n', > ' 200336400.0\n', > '\n', > ' .. seealso:: :meth:`getmtime`, :func:`os.path.getmtime`\n', > ' """,\n', > ' )\n', > '\n', > ' def getctime(self):\n', > ' """.. seealso:: :attr:`ctime`, :func:`os.path.getctime`"""\n', > ' return self.module.getctime(self)\n', > '\n', > ' ctime = property(\n', > ' getctime,\n', > ' None,\n', > ' None,\n', > ' """ Creation time of the file.\n', > '\n', > ' .. seealso:: :meth:`getctime`, :func:`os.path.getctime`\n', > ' """,\n', > ' )\n', > '\n', > ' def getsize(self):\n', > ' """.. seealso:: :attr:`size`, :func:`os.path.getsize`"""\n', > ' return self.module.getsize(self)\n', > '\n', > ' size = property(\n', > ' getsize,\n', > ' None,\n', > ' None,\n', > ' """ Size of the file, in bytes.\n', > '\n', > ' .. seealso:: :meth:`getsize`, :func:`os.path.getsize`\n', > ' """,\n', > ' )\n', > '\n', > ' @property\n', > ' def permissions(self) -> masks.Permissions:\n', > ' """\n', > ' Permissions.\n', > '\n', > " >>> perms = Path('.').permissions\n", > ' >>> isinstance(perms, int)\n', > ' True\n', > " >>> set(perms.symbolic) <= set('rwx-')\n", > ' True\n', > ' >>> perms.symbolic\n', > " 'r...'\n", > ' """\n', > ' return masks.Permissions(self.stat().st_mode)\n', > '\n', > ' def access(self, *args, **kwargs):\n', > ' """\n', > ' Return does the real user have access to this path.\n', > '\n', > " >>> Path('.').access(os.F_OK)\n", > ' True\n', > '\n', > ' .. seealso:: :func:`os.access`\n', > ' """\n', > ' return os.access(self, *args, **kwargs)\n', > '\n', > ' def stat(self, *, follow_symlinks=True):\n', > ' """\n', > ' Perform a ``stat()`` system call on this path.\n', > '\n', > " >>> Path('.').stat()\n", > ' os.stat_result(...)\n', > '\n', > ' .. seealso:: :meth:`lstat`, :func:`os.stat`\n', > ' """\n', > ' return os.stat(self, follow_symlinks=follow_symlinks)\n', > '\n', > ' def lstat(self):\n', > ' """\n', > ' Like :meth:`stat`, but do not follow symbolic links.\n', > '\n', > " >>> Path('.').lstat() == Path('.').stat()\n", > ' True\n', > '\n', > ' .. seealso:: :meth:`stat`, :func:`os.lstat`\n', > ' """\n', > ' return os.lstat(self)\n', > '\n', > ' def __get_owner_windows(self): # pragma: nocover\n', > ' r"""\n', > ' Return the name of the owner of this file or directory. Follow\n', > ' symbolic links.\n', > '\n', > ' Return a name of the form ``DOMAIN\\User Name``; may be a group.\n', > '\n', > ' .. seealso:: :attr:`owner`\n', > ' """\n', > ' desc = win32security.GetFileSecurity(\n', > ' self, win32security.OWNER_SECURITY_INFORMATION\n', > ' )\n', > ' sid = desc.GetSecurityDescriptorOwner()\n', > ' account, domain, typecode = win32security.LookupAccountSid(None, ' > 'sid)\n', > " return domain + '\\\\' + account\n", > '\n', > ' def __get_owner_unix(self): # pragma: nocover\n', > ' """\n', > ' Return the name of the owner of this file or directory. Follow\n', > ' symbolic links.\n', > '\n', > ' .. seealso:: :attr:`owner`\n', > ' """\n', > ' st = self.stat()\n', > ' return pwd.getpwuid(st.st_uid).pw_name\n', > '\n', > ' def __get_owner_not_implemented(self): # pragma: nocover\n', > ' raise NotImplementedError("Ownership not available on this ' > 'platform.")\n', > '\n', > ' get_owner = (\n', > ' __get_owner_windows\n', > " if 'win32security' in globals()\n", > ' else __get_owner_unix\n', > " if 'pwd' in globals()\n", > ' else __get_owner_not_implemented\n', > ' )\n', > '\n', > ' owner = property(\n', > ' get_owner,\n', > ' None,\n', > ' None,\n', > ' """ Name of the owner of this file or directory.\n', > '\n', > ' .. seealso:: :meth:`get_owner`""",\n', > ' )\n', > '\n', > " if 'grp' in globals(): # pragma: no cover\n", > '\n', > ' def group(self, *, follow_symlinks=True):\n', > ' """\n', > ' Return the group name of the file gid.\n', > ' """\n', > ' gid = self.stat(follow_symlinks=follow_symlinks).st_gid\n', > ' return grp.getgrgid(gid).gr_name\n', > '\n', > " if hasattr(os, 'statvfs'):\n", > '\n', > ' def statvfs(self):\n', > ' """Perform a ``statvfs()`` system call on this path.\n', > '\n', > ' .. seealso:: :func:`os.statvfs`\n', > ' """\n', > ' return os.statvfs(self)\n', > '\n', > " if hasattr(os, 'pathconf'):\n", > '\n', > ' def pathconf(self, name):\n', > ' """.. seealso:: :func:`os.pathconf`"""\n', > ' return os.pathconf(self, name)\n', > '\n', > ' #\n', > ' # --- Modifying operations on files and directories\n', > '\n', > ' def utime(self, *args, **kwargs):\n', > ' """Set the access and modified times of this file.\n', > '\n', > ' .. seealso:: :func:`os.utime`\n', > ' """\n', > ' os.utime(self, *args, **kwargs)\n', > ' return self\n', > '\n', > ' def chmod(self, mode):\n', > ' """\n', > ' Set the mode. May be the new mode (os.chmod behavior) or a ' > '`symbolic\n', > ' mode <http://en.wikipedia.org/wiki/Chmod#Symbolic_modes>`_.\n', > '\n', > ' >>> a_file = ' > "Path(getfixture('tmp_path')).joinpath('afile.txt').touch()\n", > ' >>> a_file.chmod(0o700)\n', > ' Path(...\n', > " >>> a_file.chmod('u+x')\n", > ' Path(...\n', > '\n', > ' .. seealso:: :func:`os.chmod`\n', > ' """\n', > ' if isinstance(mode, str):\n', > ' mask = masks.compound(mode)\n', > ' mode = mask(self.stat().st_mode)\n', > ' os.chmod(self, mode)\n', > ' return self\n', > '\n', > " if hasattr(os, 'chown'):\n", > '\n', > ' def chown(self, uid=-1, gid=-1):\n', > ' """\n', > ' Change the owner and group by names or numbers.\n', > '\n', > ' .. seealso:: :func:`os.chown`\n', > ' """\n', > '\n', > ' def resolve_uid(uid):\n', > ' return uid if isinstance(uid, int) else ' > 'pwd.getpwnam(uid).pw_uid\n', > '\n', > ' def resolve_gid(gid):\n', > ' return gid if isinstance(gid, int) else ' > 'grp.getgrnam(gid).gr_gid\n', > '\n', > ' os.chown(self, resolve_uid(uid), resolve_gid(gid))\n', > ' return self\n', > '\n', > ' def rename(self, new):\n', > ' """.. seealso:: :func:`os.rename`"""\n', > ' os.rename(self, new)\n', > ' return self._next_class(new)\n', > '\n', > ' def renames(self, new):\n', > ' """.. seealso:: :func:`os.renames`"""\n', > ' os.renames(self, new)\n', > ' return self._next_class(new)\n', > '\n', > ' def replace(self, target_or_old: Path | str, *args) -> Path:\n', > ' """\n', > ' Replace a path or substitute substrings.\n', > '\n', > ' Implements both pathlib.Path.replace and str.replace.\n', > '\n', > ' If only a target is supplied, rename this path to the target path,\n', > ' overwriting if that path exists.\n', > '\n', > " >>> dest = Path(getfixture('tmp_path'))\n", > " >>> orig = dest.joinpath('foo').touch()\n", > " >>> new = orig.replace(dest.joinpath('fee'))\n", > ' >>> orig.exists()\n', > ' False\n', > ' >>> new.exists()\n', > ' True\n', > '\n', > ' ..seealso:: :meth:`pathlib.Path.replace`\n', > '\n', > ' If a second parameter is supplied, perform a textual replacement.\n', > '\n', > " >>> Path('foo').replace('o', 'e')\n", > " Path('fee')\n", > " >>> Path('foo').replace('o', 'l', 1)\n", > " Path('flo')\n", > '\n', > ' ..seealso:: :meth:`str.replace`\n', > ' """\n', > ' return self._next_class(\n', > ' super().replace(target_or_old, *args)\n', > ' if args\n', > ' else pathlib.Path(self).replace(target_or_old)\n', > ' )\n', > '\n', > ' #\n', > ' # --- Create/delete operations on directories\n', > '\n', > ' def mkdir(self, mode=0o777):\n', > ' """.. seealso:: :func:`os.mkdir`"""\n', > ' os.mkdir(self, mode)\n', > ' return self\n', > '\n', > ' def mkdir_p(self, mode=0o777):\n', > ' """Like :meth:`mkdir`, but does not raise an exception if the\n', > ' directory already exists."""\n', > ' with contextlib.suppress(FileExistsError):\n', > ' self.mkdir(mode)\n', > ' return self\n', > '\n', > ' def makedirs(self, mode=0o777):\n', > ' """.. seealso:: :func:`os.makedirs`"""\n', > ' os.makedirs(self, mode)\n', > ' return self\n', > '\n', > ' def makedirs_p(self, mode=0o777):\n', > ' """Like :meth:`makedirs`, but does not raise an exception if the\n', > ' directory already exists."""\n', > ' with contextlib.suppress(FileExistsError):\n', > ' self.makedirs(mode)\n', > ' return self\n', > '\n', > ' def rmdir(self):\n', > ' """.. seealso:: :func:`os.rmdir`"""\n', > ' os.rmdir(self)\n', > ' return self\n', > '\n', > ' def rmdir_p(self):\n', > ' """Like :meth:`rmdir`, but does not raise an exception if the\n', > ' directory is not empty or does not exist."""\n', > ' suppressed = FileNotFoundError, FileExistsError, DirectoryNotEmpty\n', > ' with contextlib.suppress(suppressed):\n', > ' with DirectoryNotEmpty.translate():\n', > ' self.rmdir()\n', > ' return self\n', > '\n', > ' def removedirs(self):\n', > ' """.. seealso:: :func:`os.removedirs`"""\n', > ' os.removedirs(self)\n', > ' return self\n', > '\n', > ' def removedirs_p(self):\n', > ' """Like :meth:`removedirs`, but does not raise an exception if the\n', > ' directory is not empty or does not exist."""\n', > ' with contextlib.suppress(FileExistsError, DirectoryNotEmpty):\n', > ' with DirectoryNotEmpty.translate():\n', > ' self.removedirs()\n', > ' return self\n', > '\n', > ' # --- Modifying operations on files\n', > '\n', > ' def touch(self):\n', > ' """Set the access/modified times of this file to the current time.\n', > ' Create the file if it does not exist.\n', > ' """\n', > ' os.close(os.open(self, os.O_WRONLY | os.O_CREAT, 0o666))\n', > ' os.utime(self, None)\n', > ' return self\n', > '\n', > ' def remove(self):\n', > ' """.. seealso:: :func:`os.remove`"""\n', > ' os.remove(self)\n', > ' return self\n', > '\n', > ' def remove_p(self):\n', > ' """Like :meth:`remove`, but does not raise an exception if the\n', > ' file does not exist."""\n', > ' with contextlib.suppress(FileNotFoundError):\n', > ' self.unlink()\n', > ' return self\n', > '\n', > ' unlink = remove\n', > ' unlink_p = remove_p\n', > '\n', > ' # --- Links\n', > '\n', > ' def hardlink_to(self, target: str) -> None:\n', > ' """\n', > ' Create a hard link at self, pointing to target.\n', > '\n', > ' .. seealso:: :func:`os.link`\n', > ' """\n', > ' os.link(target, self)\n', > '\n', > ' def link(self, newpath):\n', > ' """Create a hard link at `newpath`, pointing to this file.\n', > '\n', > ' .. seealso:: :func:`os.link`\n', > ' """\n', > ' os.link(self, newpath)\n', > ' return self._next_class(newpath)\n', > '\n', > ' def symlink_to(self, target: str, target_is_directory: bool = False) -> ' > 'None:\n', > ' """\n', > ' Create a symbolic link at self, pointing to target.\n', > '\n', > ' .. seealso:: :func:`os.symlink`\n', > ' """\n', > ' os.symlink(target, self, target_is_directory)\n', > '\n', > ' def symlink(self, newlink=None):\n', > ' """Create a symbolic link at `newlink`, pointing here.\n', > '\n', > ' If newlink is not supplied, the symbolic link will assume\n', > ' the name self.basename(), creating the link in the cwd.\n', > '\n', > ' .. seealso:: :func:`os.symlink`\n', > ' """\n', > ' if newlink is None:\n', > ' newlink = self.basename()\n', > ' os.symlink(self, newlink)\n', > ' return self._next_class(newlink)\n', > '\n', > ' def readlink(self):\n', > ' """Return the path to which this symbolic link points.\n', > '\n', > ' The result may be an absolute or a relative path.\n', > '\n', > ' .. seealso:: :meth:`readlinkabs`, :func:`os.readlink`\n', > ' """\n', > ' return self._next_class(removeprefix(os.readlink(self), ' > "'\\\\\\\\?\\\\'))\n", > '\n', > ' def readlinkabs(self):\n', > ' """Return the path to which this symbolic link points.\n', > '\n', > ' The result is always an absolute path.\n', > '\n', > ' .. seealso:: :meth:`readlink`, :func:`os.readlink`\n', > ' """\n', > ' p = self.readlink()\n', > ' return p if p.isabs() else (self.parent / p).absolute()\n', > '\n', > ' # High-level functions from shutil\n', > ' # These functions will be bound to the instance such that\n', > ' # Path(name).copy(target) will invoke shutil.copy(name, target)\n', > '\n', > ' copyfile = shutil.copyfile\n', > ' copymode = shutil.copymode\n', > ' copystat = shutil.copystat\n', > ' copy = shutil.copy\n', > ' copy2 = shutil.copy2\n', > ' copytree = shutil.copytree\n', > " if hasattr(shutil, 'move'):\n", > ' move = shutil.move\n', > ' rmtree = shutil.rmtree\n', > '\n', > ' def rmtree_p(self):\n', > ' """Like :meth:`rmtree`, but does not raise an exception if the\n', > ' directory does not exist."""\n', > ' with contextlib.suppress(FileNotFoundError):\n', > ' self.rmtree()\n', > ' return self\n', > '\n', > ' def chdir(self):\n', > ' """.. seealso:: :func:`os.chdir`"""\n', > ' os.chdir(self)\n', > '\n', > ' cd = chdir\n', > '\n', > ' def merge_tree(\n', > ' self,\n', > ' dst,\n', > ' symlinks=False,\n', > ' *,\n', > ' copy_function=shutil.copy2,\n', > ' ignore=lambda dir, contents: [],\n', > ' ):\n', > ' """\n', > ' Copy entire contents of self to dst, overwriting existing\n', > ' contents in dst with those in self.\n', > '\n', > ' Pass ``symlinks=True`` to copy symbolic links as links.\n', > '\n', > ' Accepts a ``copy_function``, similar to copytree.\n', > '\n', > ' To avoid overwriting newer files, supply a copy function\n', > ' wrapped in ``only_newer``. For example::\n', > '\n', > ' src.merge_tree(dst, copy_function=only_newer(shutil.copy2))\n', > ' """\n', > ' dst = self._next_class(dst)\n', > ' dst.makedirs_p()\n', > '\n', > ' sources = list(self.iterdir())\n', > ' _ignored = ignore(self, [item.name for item in sources])\n', > '\n', > ' def ignored(item):\n', > ' return item.name in _ignored\n', > '\n', > ' for source in itertools.filterfalse(ignored, sources):\n', > ' dest = dst / source.name\n', > ' if symlinks and source.islink():\n', > ' target = source.readlink()\n', > ' target.symlink(dest)\n', > ' elif source.is_dir():\n', > ' source.merge_tree(\n', > ' dest,\n', > ' symlinks=symlinks,\n', > ' copy_function=copy_function,\n', > ' ignore=ignore,\n', > ' )\n', > ' else:\n', > ' copy_function(source, dest)\n', > '\n', > ' self.copystat(dst)\n', > '\n', > ' #\n', > ' # --- Special stuff from os\n', > '\n', > " if hasattr(os, 'chroot'):\n", > '\n', > ' def chroot(self): # pragma: nocover\n', > ' """.. seealso:: :func:`os.chroot`"""\n', > ' os.chroot(self)\n', > '\n', > " if hasattr(os, 'startfile'):\n", > '\n', > ' def startfile(self, *args, **kwargs): # pragma: nocover\n', > ' """.. seealso:: :func:`os.startfile`"""\n', > ' os.startfile(self, *args, **kwargs)\n', > ' return self\n', > '\n', > ' # in-place re-writing, courtesy of Martijn Pieters\n', > ' # http://www.zopatista.com/python/2013/11/26/inplace-file-rewriting/\n', > ' @contextlib.contextmanager\n', > ' def in_place(\n', > ' self,\n', > " mode='r',\n", > ' buffering=-1,\n', > ' encoding=None,\n', > ' errors=None,\n', > ' newline=None,\n', > ' backup_extension=None,\n', > ' ):\n', > ' """\n', > ' A context in which a file may be re-written in-place with\n', > ' new content.\n', > '\n', > ' Yields a tuple of :samp:`({readable}, {writable})` file\n', > ' objects, where `writable` replaces `readable`.\n', > '\n', > ' If an exception occurs, the old file is restored, removing the\n', > ' written data.\n', > '\n', > " Mode *must not* use ``'w'``, ``'a'``, or ``'+'``; only\n", > ' read-only-modes are allowed. A :exc:`ValueError` is raised\n', > ' on invalid modes.\n', > '\n', > ' For example, to add line numbers to a file::\n', > '\n', > ' p = Path(filename)\n', > ' assert p.is_file()\n', > ' with p.in_place() as (reader, writer):\n', > ' for number, line in enumerate(reader, 1):\n', > " writer.write('{0:3}: '.format(number)))\n", > ' writer.write(line)\n', > '\n', > ' Thereafter, the file at `filename` will have line numbers in it.\n', > ' """\n', > " if set(mode).intersection('wa+'):\n", > " raise ValueError('Only read-only file modes can be used')\n", > '\n', > ' # move existing file to backup, create new file with same ' > 'permissions\n', > ' # borrowed extensively from the fileinput module\n', > " backup_fn = self + (backup_extension or os.extsep + 'bak')\n", > ' backup_fn.remove_p()\n', > ' self.rename(backup_fn)\n', > ' readable = open(\n', > ' backup_fn,\n', > ' mode,\n', > ' buffering=buffering,\n', > ' encoding=encoding,\n', > ' errors=errors,\n', > ' newline=newline,\n', > ' )\n', > '\n', > ' perm = os.stat(readable.fileno()).st_mode\n', > ' os_mode = os.O_CREAT | os.O_WRONLY | os.O_TRUNC\n', > " os_mode |= getattr(os, 'O_BINARY', 0)\n", > ' fd = os.open(self, os_mode, perm)\n', > ' writable = open(\n', > ' fd,\n', > ' "w" + mode.replace(\'r\', \'\'),\n', > ' buffering=buffering,\n', > ' encoding=encoding,\n', > ' errors=errors,\n', > ' newline=newline,\n', > ' )\n', > ' with contextlib.suppress(OSError, AttributeError):\n', > ' self.chmod(perm)\n', > '\n', > ' try:\n', > ' yield readable, writable\n', > ' except Exception:\n', > ' # move backup back\n', > ' readable.close()\n', > ' writable.close()\n', > ' self.remove_p()\n', > ' backup_fn.rename(self)\n', > ' raise\n', > ' else:\n', > ' readable.close()\n', > ' writable.close()\n', > ' finally:\n', > ' backup_fn.remove_p()\n', > '\n', > ' @classes.ClassProperty\n', > ' @classmethod\n', > ' def special(cls):\n', > ' """\n', > ' Return a SpecialResolver object suitable referencing a suitable\n', > ' directory for the relevant platform for the given\n', > ' type of content.\n', > '\n', > ' For example, to get a user config directory, invoke:\n', > '\n', > ' dir = Path.special().user.config\n', > '\n', > ' Uses the `appdirs\n', > ' <https://pypi.python.org/pypi/appdirs/1.4.0>`_ to resolve\n', > ' the paths in a platform-friendly way.\n', > '\n', > " To create a config directory for 'My App', consider:\n", > '\n', > ' dir = Path.special("My App").user.config.makedirs_p()\n', > '\n', > ' If the ``appdirs`` module is not installed, invocation\n', > ' of special will raise an ImportError.\n', > ' """\n', > ' return functools.partial(SpecialResolver, cls)\n', > '\n', > '\n', > 'class DirectoryNotEmpty(OSError):\n', > ' @staticmethod\n', > ' @contextlib.contextmanager\n', > ' def translate():\n', > ' try:\n', > ' yield\n', > ' except OSError as exc:\n', > ' if exc.errno == errno.ENOTEMPTY:\n', > ' raise DirectoryNotEmpty(*exc.args) from exc\n', > ' raise\n', > '\n', > '\n', > 'def only_newer(copy_func):\n', > ' """\n', > ' Wrap a copy function (like shutil.copy2) to return\n', > " the dst if it's newer than the source.\n", > ' """\n', > '\n', > ' @functools.wraps(copy_func)\n', > ' def wrapper(src, dst, *args, **kwargs):\n', > ' is_newer_dst = dst.exists() and dst.getmtime() >= src.getmtime()\n', > ' if is_newer_dst:\n', > ' return dst\n', > ' return copy_func(src, dst, *args, **kwargs)\n', > '\n', > ' return wrapper\n', > '\n', > '\n', > 'class ExtantPath(Path):\n', > ' """\n', > " >>> ExtantPath('.')\n", > " ExtantPath('.')\n", > " >>> ExtantPath('does-not-exist')\n", > ' Traceback (most recent call last):\n', > ' OSError: does-not-exist does not exist.\n', > ' """\n', > '\n', > ' def _validate(self):\n', > ' if not self.exists():\n', > ' raise OSError(f"{self} does not exist.")\n', > '\n', > '\n', > 'class ExtantFile(Path):\n', > ' """\n', > " >>> ExtantFile('.')\n", > ' Traceback (most recent call last):\n', > ' FileNotFoundError: . does not exist as a file.\n', > " >>> ExtantFile('does-not-exist')\n", > ' Traceback (most recent call last):\n', > ' FileNotFoundError: does-not-exist does not exist as a file.\n', > ' """\n', > '\n', > ' def _validate(self):\n', > ' if not self.is_file():\n', > ' raise FileNotFoundError(f"{self} does not exist as a file.")\n', > '\n', > '\n', > 'class SpecialResolver:\n', > ' class ResolverScope:\n', > ' def __init__(self, paths, scope):\n', > ' self.paths = paths\n', > ' self.scope = scope\n', > '\n', > ' def __getattr__(self, class_):\n', > ' return self.paths.get_dir(self.scope, class_)\n', > '\n', > ' def __init__(self, path_class, *args, **kwargs):\n', > " appdirs = importlib.import_module('appdirs')\n", > '\n', > ' vars(self).update(\n', > ' path_class=path_class, wrapper=appdirs.AppDirs(*args, ' > '**kwargs)\n', > ' )\n', > '\n', > ' def __getattr__(self, scope):\n', > ' return self.ResolverScope(self, scope)\n', > '\n', > ' def get_dir(self, scope, class_):\n', > ' """\n', > ' Return the callable function from appdirs, but with the\n', > ' result wrapped in self.path_class\n', > ' """\n', > " prop_name = f'{scope}_{class_}_dir'\n", > ' value = getattr(self.wrapper, prop_name)\n', > ' MultiPath = Multi.for_class(self.path_class)\n', > ' return MultiPath.detect(value)\n', > '\n', > '\n', > 'class Multi:\n', > ' """\n', > ' A mix-in for a Path which may contain multiple Path separated by ' > 'pathsep.\n', > ' """\n', > '\n', > ' @classmethod\n', > ' def for_class(cls, path_cls):\n', > " name = 'Multi' + path_cls.__name__\n", > ' return type(name, (cls, path_cls), {})\n', > '\n', > ' @classmethod\n', > ' def detect(cls, input):\n', > ' if os.pathsep not in input:\n', > ' cls = cls._next_class\n', > ' return cls(input)\n', > '\n', > ' def __iter__(self):\n', > ' return iter(map(self._next_class, self.split(os.pathsep)))\n', > '\n', > ' @classes.ClassProperty\n', > ' @classmethod\n', > ' def _next_class(cls):\n', > ' """\n', > ' Multi-subclasses should use the parent class\n', > ' """\n', > ' return next(class_ for class_ in cls.__mro__ if not ' > 'issubclass(class_, Multi))\n', > '\n', > '\n', > 'class TempDir(Path):\n', > ' """\n', > ' A temporary directory via :func:`tempfile.mkdtemp`, and\n', > ' constructed with the same parameters that you can use\n', > ' as a context manager.\n', > '\n', > ' For example:\n', > '\n', > ' >>> with TempDir() as d:\n', > ' ... d.is_dir() and isinstance(d, Path)\n', > ' True\n', > '\n', > ' The directory is deleted automatically.\n', > '\n', > ' >>> d.is_dir()\n', > ' False\n', > '\n', > ' .. seealso:: :func:`tempfile.mkdtemp`\n', > ' """\n', > '\n', > ' @classes.ClassProperty\n', > ' @classmethod\n', > ' def _next_class(cls):\n', > ' return Path\n', > '\n', > ' def __new__(cls, *args, **kwargs):\n', > ' dirname = tempfile.mkdtemp(*args, **kwargs)\n', > ' return super().__new__(cls, dirname)\n', > '\n', > ' def __init__(self, *args, **kwargs):\n', > ' pass\n', > '\n', > ' def __enter__(self):\n', > ' # TempDir should return a Path version of itself and not itself\n', > ' # so that a second context manager does not create a second\n', > ' # temporary directory, but rather changes CWD to the location\n', > ' # of the temporary directory.\n', > ' return self._next_class(self)\n', > '\n', > ' def __exit__(self, exc_type, exc_value, traceback):\n', > ' self.rmtree()\n', > '\n', > '\n', > 'class Handlers:\n', > ' def strict(msg):\n', > ' raise\n', > '\n', > ' def warn(msg):\n', > ' warnings.warn(msg, TreeWalkWarning, stacklevel=2)\n', > '\n', > ' def ignore(msg):\n', > ' pass\n', > '\n', > ' @classmethod\n', > ' def _resolve(cls, param):\n', > ' if not callable(param) and param not in vars(Handlers):\n', > ' raise ValueError("invalid errors parameter")\n', > ' return vars(cls).get(param, param)\n'] > tests = [<DocTest path from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:0 (no examples)>, > <DocTest path.Traversal from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:93 (4 examples)>, > <DocTest path._strip_newlines from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:129 (1 example)>, > <DocTest path.Path from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:137 (no examples)>, > <DocTest path.Path.__truediv__ from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:197 (no examples)>, > <DocTest path.Path.__rtruediv__ from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:208 (no examples)>, > <DocTest path.Path.cwd from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:227 (no examples)>, > <DocTest path.Path.absolute from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:241 (no examples)>, > <DocTest path.Path.normcase from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:245 (no examples)>, > <DocTest path.Path.normpath from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:249 (no examples)>, > <DocTest path.Path.realpath from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:253 (no examples)>, > <DocTest path.Path.expanduser from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:257 (no examples)>, > <DocTest path.Path.expandvars from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:261 (no examples)>, > <DocTest path.Path.dirname from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:265 (no examples)>, > <DocTest path.Path.basename from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:269 (no examples)>, > <DocTest path.Path.expand from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:273 (no examples)>, > <DocTest path.Path.stem from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:283 (1 example)>, > <DocTest path.Path.with_stem from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:292 (1 example)>, > <DocTest path.Path.suffix from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:301 (no examples)>, > <DocTest path.Path.with_suffix from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:306 (3 examples)>, > <DocTest path.Path.drive from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:326 (no examples)>, > <DocTest path.Path.parent from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:265 (no examples)>, > <DocTest path.Path.name from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:269 (no examples)>, > <DocTest path.Path.with_name from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:361 (1 example)>, > <DocTest path.Path.splitpath from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:369 (no examples)>, > <DocTest path.Path.splitdrive from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:377 (no examples)>, > <DocTest path.Path.splitext from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:389 (no examples)>, > <DocTest path.Path.stripext from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:404 (no examples)>, > <DocTest path.Path.splitall from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:424 (1 example)>, > <DocTest path.Path.parts from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:439 (1 example)>, > <DocTest path.Path.relpath from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:459 (no examples)>, > <DocTest path.Path.relpathto from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:466 (no examples)>, > <DocTest path.Path.iterdir from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:506 (no examples)>, > <DocTest path.Path.dirs from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:522 (no examples)>, > <DocTest path.Path.files from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:533 (no examples)>, > <DocTest path.Path.walk from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:544 (no examples)>, > <DocTest path.Path.walkdirs from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:584 (no examples)>, > <DocTest path.Path.walkfiles from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:588 (no examples)>, > <DocTest path.Path.fnmatch from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:592 (no examples)>, > <DocTest path.Path.glob from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:611 (no examples)>, > <DocTest path.Path.iglob from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:628 (no examples)>] >[1m[31m/usr/lib/python3.12/doctest.py[0m:1022: in _find > [0m[96mself[39;49;00m._find(tests, val, valname, module, source_lines,[90m[39;49;00m > globs = {'B_NEWLINE': re.compile(b'\r\n|\r|\n'), > 'B_NL_END': re.compile(b'\r\n|\r|\n$'), > 'Callable': typing.Callable, > 'DirectoryNotEmpty': <class 'path.DirectoryNotEmpty'>, > 'ExtantFile': <class 'path.ExtantFile'>, > 'ExtantPath': <class 'path.ExtantPath'>, > 'Handlers': <class 'path.Handlers'>, > 'Iterator': typing.Iterator, > 'LINESEPS': ['\r\n', '\r', '\n'], > 'Multi': <class 'path.Multi'>, > 'Number': <class 'numbers.Number'>, > 'Path': <class 'path.Path'>, > 'SpecialResolver': <class 'path.SpecialResolver'>, > 'TYPE_CHECKING': False, > 'TempDir': <class 'path.TempDir'>, > 'Traversal': <class 'path.Traversal'>, > 'TreeWalkWarning': <class 'path.TreeWalkWarning'>, > 'U_LINESEPS': ['\r\n', '\r', '\n', '\x85', '\u2028', '\u2029'], > 'U_NEWLINE': re.compile('\r\n|\r|\n|\x85|\u2028|\u2029'), > 'U_NL_END': re.compile('\r\n|\r|\n|\x85|\u2028|\u2029$'), > '__all__': ['Path', 'TempDir'], > '__builtins__': {'ArithmeticError': <class 'ArithmeticError'>, > 'AssertionError': <class 'AssertionError'>, > 'AttributeError': <class 'AttributeError'>, > 'BaseException': <class 'BaseException'>, > 'BaseExceptionGroup': <class 'BaseExceptionGroup'>, > 'BlockingIOError': <class 'BlockingIOError'>, > 'BrokenPipeError': <class 'BrokenPipeError'>, > 'BufferError': <class 'BufferError'>, > 'BytesWarning': <class 'BytesWarning'>, > 'ChildProcessError': <class 'ChildProcessError'>, > 'ConnectionAbortedError': <class 'ConnectionAbortedError'>, > 'ConnectionError': <class 'ConnectionError'>, > 'ConnectionRefusedError': <class 'ConnectionRefusedError'>, > 'ConnectionResetError': <class 'ConnectionResetError'>, > 'DeprecationWarning': <class 'DeprecationWarning'>, > 'EOFError': <class 'EOFError'>, > 'Ellipsis': Ellipsis, > 'EncodingWarning': <class 'EncodingWarning'>, > 'EnvironmentError': <class 'OSError'>, > 'Exception': <class 'Exception'>, > 'ExceptionGroup': <class 'ExceptionGroup'>, > 'False': False, > 'FileExistsError': <class 'FileExistsError'>, > 'FileNotFoundError': <class 'FileNotFoundError'>, > 'FloatingPointError': <class 'FloatingPointError'>, > 'FutureWarning': <class 'FutureWarning'>, > 'GeneratorExit': <class 'GeneratorExit'>, > 'IOError': <class 'OSError'>, > 'ImportError': <class 'ImportError'>, > 'ImportWarning': <class 'ImportWarning'>, > 'IndentationError': <class 'IndentationError'>, > 'IndexError': <class 'IndexError'>, > 'InterruptedError': <class 'InterruptedError'>, > 'IsADirectoryError': <class 'IsADirectoryError'>, > 'KeyError': <class 'KeyError'>, > 'KeyboardInterrupt': <class 'KeyboardInterrupt'>, > 'LookupError': <class 'LookupError'>, > 'MemoryError': <class 'MemoryError'>, > 'ModuleNotFoundError': <class 'ModuleNotFoundError'>, > 'NameError': <class 'NameError'>, > 'None': None, > 'NotADirectoryError': <class 'NotADirectoryError'>, > 'NotImplemented': NotImplemented, > 'NotImplementedError': <class 'NotImplementedError'>, > 'OSError': <class 'OSError'>, > 'OverflowError': <class 'OverflowError'>, > 'PendingDeprecationWarning': <class 'PendingDeprecationWarning'>, > 'PermissionError': <class 'PermissionError'>, > 'ProcessLookupError': <class 'ProcessLookupError'>, > 'RecursionError': <class 'RecursionError'>, > 'ReferenceError': <class 'ReferenceError'>, > 'ResourceWarning': <class 'ResourceWarning'>, > 'RuntimeError': <class 'RuntimeError'>, > 'RuntimeWarning': <class 'RuntimeWarning'>, > 'StopAsyncIteration': <class 'StopAsyncIteration'>, > 'StopIteration': <class 'StopIteration'>, > 'SyntaxError': <class 'SyntaxError'>, > 'SyntaxWarning': <class 'SyntaxWarning'>, > 'SystemError': <class 'SystemError'>, > 'SystemExit': <class 'SystemExit'>, > 'TabError': <class 'TabError'>, > 'TimeoutError': <class 'TimeoutError'>, > 'True': True, > 'TypeError': <class 'TypeError'>, > 'UnboundLocalError': <class 'UnboundLocalError'>, > 'UnicodeDecodeError': <class 'UnicodeDecodeError'>, > 'UnicodeEncodeError': <class 'UnicodeEncodeError'>, > 'UnicodeError': <class 'UnicodeError'>, > 'UnicodeTranslateError': <class 'UnicodeTranslateError'>, > 'UnicodeWarning': <class 'UnicodeWarning'>, > 'UserWarning': <class 'UserWarning'>, > 'ValueError': <class 'ValueError'>, > 'Warning': <class 'Warning'>, > 'ZeroDivisionError': <class 'ZeroDivisionError'>, > '__build_class__': <built-in function __build_class__>, > '__debug__': True, > '__doc__': 'Built-in functions, types, exceptions, and other ' > 'objects.\n' > '\n' > 'This module provides direct access to all ' > "'built-in'\n" > 'identifiers of Python; for example, builtins.len ' > 'is\n' > 'the full name for the built-in function len().\n' > '\n' > 'This module is not normally accessed explicitly ' > 'by most\n' > 'applications, but can be useful in modules that ' > 'provide\n' > 'objects with the same name as a built-in value, ' > 'but in\n' > 'which the built-in of that name is also needed.', > '__import__': <built-in function __import__>, > '__loader__': <class '_frozen_importlib.BuiltinImporter'>, > '__name__': 'builtins', > '__package__': '', > '__spec__': ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>, origin='built-in'), > 'abs': <built-in function abs>, > 'aiter': <built-in function aiter>, > 'all': <built-in function all>, > 'anext': <built-in function anext>, > 'any': <built-in function any>, > 'ascii': <built-in function ascii>, > 'bin': <built-in function bin>, > 'bool': <class 'bool'>, > 'breakpoint': <built-in function breakpoint>, > 'bytearray': <class 'bytearray'>, > 'bytes': <class 'bytes'>, > 'callable': <built-in function callable>, > 'chr': <built-in function chr>, > 'classmethod': <class 'classmethod'>, > 'compile': <built-in function compile>, > 'complex': <class 'complex'>, > 'copyright': Copyright (c) 2001-2023 Python Software Foundation. >All Rights Reserved. > >Copyright (c) 2000 BeOpen.com. >All Rights Reserved. > >Copyright (c) 1995-2001 Corporation for National Research Initiatives. >All Rights Reserved. > >Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam. >All Rights Reserved., > 'credits': Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands > for supporting Python development. See www.python.org for more information., > 'delattr': <built-in function delattr>, > 'dict': <class 'dict'>, > 'dir': <built-in function dir>, > 'divmod': <built-in function divmod>, > 'enumerate': <class 'enumerate'>, > 'eval': <built-in function eval>, > 'exec': <built-in function exec>, > 'exit': Use exit() or Ctrl-D (i.e. EOF) to exit, > 'filter': <class 'filter'>, > 'float': <class 'float'>, > 'format': <built-in function format>, > 'frozenset': <class 'frozenset'>, > 'getattr': <built-in function getattr>, > 'globals': <built-in function globals>, > 'hasattr': <built-in function hasattr>, > 'hash': <built-in function hash>, > 'help': Type help() for interactive help, or help(object) for help about object., > 'hex': <built-in function hex>, > 'id': <built-in function id>, > 'input': <built-in function input>, > 'int': <class 'int'>, > 'isinstance': <built-in function isinstance>, > 'issubclass': <built-in function issubclass>, > 'iter': <built-in function iter>, > 'len': <built-in function len>, > 'license': Type license() to see the full license text, > 'list': <class 'list'>, > 'locals': <built-in function locals>, > 'map': <class 'map'>, > 'max': <built-in function max>, > 'memoryview': <class 'memoryview'>, > 'min': <built-in function min>, > 'next': <built-in function next>, > 'object': <class 'object'>, > 'oct': <built-in function oct>, > 'open': <built-in function open>, > 'ord': <built-in function ord>, > 'pow': <built-in function pow>, > 'print': <built-in function print>, > 'property': <class 'property'>, > 'quit': Use quit() or Ctrl-D (i.e. EOF) to exit, > 'range': <class 'range'>, > 'repr': <built-in function repr>, > 'reversed': <class 'reversed'>, > 'round': <built-in function round>, > 'set': <class 'set'>, > 'setattr': <built-in function setattr>, > 'slice': <class 'slice'>, > 'sorted': <built-in function sorted>, > 'staticmethod': <class 'staticmethod'>, > 'str': <class 'str'>, > 'sum': <built-in function sum>, > 'super': <class 'super'>, > 'tuple': <class 'tuple'>, > 'type': <class 'type'>, > 'vars': <built-in function vars>, > 'zip': <class 'zip'>}, > '__cached__': '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__pycache__/__init__.cpython-312.pyc', > '__doc__': '\n' > 'Path Pie\n' > '\n' > 'Implements ``path.Path`` - An object representing a\n' > 'path to a file or directory.\n' > '\n' > 'Example::\n' > '\n' > ' from path import Path\n' > " d = Path('/home/guido/bin')\n" > '\n' > ' # Globbing\n' > " for f in d.files('*.py'):\n" > ' f.chmod(0o755)\n' > '\n' > ' # Changing the working directory:\n' > ' with Path("somewhere"):\n' > ' # cwd in now `somewhere`\n' > ' ...\n' > '\n' > ' # Concatenate paths with /\n' > ' foo_txt = Path("bar") / "foo.txt"\n', > '__file__': '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py', > '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f01aa694230>, > '__name__': 'path', > '__package__': 'path', > '__path__': ['/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path'], > '__pytest_asyncio_package_scoped_event_loop': <function pytest_collectstart.<locals>.scoped_event_loop at 0x7f01aa84dc60>, > '__pytest_asyncio_scoped_event_loop': <function pytest_collectstart.<locals>.scoped_event_loop at 0x7f01aa84e200>, > '__spec__': ModuleSpec(name='path', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7f01aa694230>, origin='/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py', submodule_search_locations=['/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path']), > '_default_linesep': <object object at 0x7f01aad185e0>, > '_make_timestamp_ns': <function _make_timestamp_ns at 0x7f01aa845ee0>, > '_strip_newlines': <function _strip_newlines at 0x7f01b0b88220>, > 'annotations': _Feature((3, 7, 0, 'beta', 1), None, 16777216), > 'builtins': <module 'builtins' (built-in)>, > 'classes': <module 'path.classes' from '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/classes.py'>, > 'compat': <module 'path.compat' (namespace) from ['/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/compat']>, > 'contextlib': <module 'contextlib' from '/usr/lib/python3.12/contextlib.py'>, > 'datetime': <module 'datetime' from '/usr/lib/python3.12/datetime.py'>, > 'errno': <module 'errno' (built-in)>, > 'fnmatch': <module 'fnmatch' from '/usr/lib/python3.12/fnmatch.py'>, > 'functools': <module 'functools' from '/usr/lib/python3.12/functools.py'>, > 'glob': <module 'glob' from '/usr/lib/python3.12/glob.py'>, > 'grp': <module 'grp' from '/usr/lib/python3.12/lib-dynload/grp.cpython-312-x86_64-linux-gnu.so'>, > 'hashlib': <module 'hashlib' from '/usr/lib/python3.12/hashlib.py'>, > 'importlib': <module 'importlib' from '/usr/lib/python3.12/importlib/__init__.py'>, > 'itertools': <module 'itertools' (built-in)>, > 'masks': <module 'path.masks' from '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/masks.py'>, > 'matchers': <module 'path.matchers' from '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/matchers.py'>, > 'only_newer': <function only_newer at 0x7f01aa84f9c0>, > 'os': <module 'os' (frozen)>, > 'overload': <function overload at 0x7f01b06491c0>, > 'pathlib': <module 'pathlib' from '/usr/lib/python3.12/pathlib.py'>, > 'pwd': <module 'pwd' (built-in)>, > 're': <module 're' from '/usr/lib/python3.12/re/__init__.py'>, > 'removeprefix': <function removeprefix at 0x7f01aa84f880>, > 'removesuffix': <function removesuffix at 0x7f01aa84f420>, > 'shutil': <module 'shutil' from '/usr/lib/python3.12/shutil.py'>, > 'sys': <module 'sys' (built-in)>, > 'tempfile': <module 'tempfile' from '/usr/lib/python3.12/tempfile.py'>, > 'warnings': <module 'warnings' from '/usr/lib/python3.12/warnings.py'>} > module = <module 'path' from '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py'> > name = 'path' > obj = <module 'path' from '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py'> > seen = {93856939061456: 1, > 93856939078192: 1, > 93856939150480: 1, > 139645130706752: 1, > 139645130712032: 1, > 139645130713552: 1, > 139645130714352: 1, > 139645130715952: 1, > 139645130717232: 1, > 139645130801216: 1, > 139645130801376: 1, > 139645130801536: 1, > 139645130801696: 1, > 139645130801856: 1, > 139645130802016: 1, > 139645130802176: 1, > 139645130802336: 1, > 139645130802496: 1, > 139645130802656: 1, > 139645130802816: 1, > 139645130802976: 1, > 139645130803136: 1, > 139645130803296: 1, > 139645130803616: 1, > 139645130803936: 1, > 139645130804256: 1, > 139645130804416: 1, > 139645130804576: 1, > 139645130804736: 1, > 139645130804896: 1, > 139645130805216: 1, > 139645130805376: 1, > 139645130805536: 1, > 139645130805696: 1, > 139645130805856: 1, > 139645130806016: 1, > 139645130806176: 1, > 139645130806336: 1, > 139645130806496: 1, > 139645130806656: 1, > 139645130806816: 1, > 139645130806976: 1, > 139645130807136: 1, > 139645130807296: 1, > 139645130807456: 1, > 139645130807616: 1, > 139645131613008: 1, > 139645132496608: 1, > 139645132531456: 1, > 139645132536096: 1, > 139645132536416: 1, > 139645132536576: 1, > 139645132537216: 1, > 139645132537376: 1, > 139645132537536: 1, > 139645132537696: 1, > 139645236576800: 1} > self = <_pytest.doctest.DoctestModule.collect.<locals>.MockAwareDocTestFinder object at 0x7f01aa91be60> > source_lines = ['"""\n', > 'Path Pie\n', > '\n', > 'Implements ``path.Path`` - An object representing a\n', > 'path to a file or directory.\n', > '\n', > 'Example::\n', > '\n', > ' from path import Path\n', > " d = Path('/home/guido/bin')\n", > '\n', > ' # Globbing\n', > " for f in d.files('*.py'):\n", > ' f.chmod(0o755)\n', > '\n', > ' # Changing the working directory:\n', > ' with Path("somewhere"):\n', > ' # cwd in now `somewhere`\n', > ' ...\n', > '\n', > ' # Concatenate paths with /\n', > ' foo_txt = Path("bar") / "foo.txt"\n', > '"""\n', > '\n', > 'from __future__ import annotations\n', > '\n', > 'import builtins\n', > 'import contextlib\n', > 'import datetime\n', > 'import errno\n', > 'import fnmatch\n', > 'import functools\n', > 'import glob\n', > 'import hashlib\n', > 'import importlib\n', > 'import itertools\n', > 'import os\n', > 'import pathlib\n', > 'import re\n', > 'import shutil\n', > 'import sys\n', > 'import tempfile\n', > 'import warnings\n', > 'from numbers import Number\n', > '\n', > 'with contextlib.suppress(ImportError):\n', > ' import win32security\n', > '\n', > 'with contextlib.suppress(ImportError):\n', > ' import pwd\n', > '\n', > 'with contextlib.suppress(ImportError):\n', > ' import grp\n', > '\n', > 'from typing import (\n', > ' TYPE_CHECKING,\n', > ' Callable,\n', > ' Iterator,\n', > ' overload,\n', > ')\n', > '\n', > 'if TYPE_CHECKING:\n', > ' from _typeshed import (\n', > ' OpenBinaryMode,\n', > ' OpenTextMode,\n', > ' )\n', > '\n', > 'from . import classes, masks, matchers\n', > 'from .compat.py38 import removeprefix, removesuffix\n', > '\n', > "__all__ = ['Path', 'TempDir']\n", > '\n', > '\n', > "LINESEPS = ['\\r\\n', '\\r', '\\n']\n", > "U_LINESEPS = LINESEPS + ['\\u0085', '\\u2028', '\\u2029']\n", > "B_NEWLINE = re.compile('|'.join(LINESEPS).encode())\n", > "U_NEWLINE = re.compile('|'.join(U_LINESEPS))\n", > "B_NL_END = re.compile(B_NEWLINE.pattern + b'$')\n", > "U_NL_END = re.compile(U_NEWLINE.pattern + '$')\n", > '\n', > '_default_linesep = object()\n', > '\n', > '\n', > 'def _make_timestamp_ns(value: Number | datetime.datetime) -> Number:\n', > ' timestamp_s = value if isinstance(value, Number) else ' > 'value.timestamp()\n', > ' return int(timestamp_s * 10**9)\n', > '\n', > '\n', > 'class TreeWalkWarning(Warning):\n', > ' pass\n', > '\n', > '\n', > 'class Traversal:\n', > ' """\n', > ' Wrap a walk result to customize the traversal.\n', > '\n', > ' `follow` is a function that takes an item and returns\n', > ' True if that item should be followed and False otherwise.\n', > '\n', > ' For example, to avoid traversing into directories that\n', > ' begin with `.`:\n', > '\n', > " >>> traverse = Traversal(lambda dir: not dir.startswith('.'))\n", > " >>> items = list(traverse(Path('.').walk()))\n", > '\n', > ' Directories beginning with `.` will appear in the results, but\n', > ' their children will not.\n', > '\n', > ' >>> dot_dir = next(item for item in items if item.is_dir() and ' > "item.startswith('.'))\n", > ' >>> any(item.parent == dot_dir for item in items)\n', > ' False\n', > ' """\n', > '\n', > ' def __init__(self, follow):\n', > ' self.follow = follow\n', > '\n', > ' def __call__(self, walker):\n', > ' traverse = None\n', > ' while True:\n', > ' try:\n', > ' item = walker.send(traverse)\n', > ' except StopIteration:\n', > ' return\n', > ' yield item\n', > '\n', > ' traverse = functools.partial(self.follow, item)\n', > '\n', > '\n', > 'def _strip_newlines(lines):\n', > ' r"""\n', > " >>> list(_strip_newlines(['Hello World\\r\\n', 'foo']))\n", > " ['Hello World', 'foo']\n", > ' """\n', > " return (U_NL_END.sub('', line) for line in lines)\n", > '\n', > '\n', > 'class Path(str):\n', > ' """\n', > ' Represents a filesystem path.\n', > '\n', > ' For documentation on individual methods, consult their\n', > ' counterparts in :mod:`os.path`.\n', > '\n', > ' Some methods are additionally included from :mod:`shutil`.\n', > ' The functions are linked directly into the class namespace\n', > ' such that they will be bound to the Path instance. For example,\n', > ' ``Path(src).copy(target)`` is equivalent to\n', > ' ``shutil.copy(src, target)``. Therefore, when referencing\n', > ' the docs for these methods, assume `src` references `self`,\n', > ' the Path instance.\n', > ' """\n', > '\n', > ' module = os.path\n', > ' """ The path module to use for path operations.\n', > '\n', > ' .. seealso:: :mod:`os.path`\n', > ' """\n', > '\n', > " def __new__(cls, other='.'):\n", > ' return super().__new__(cls, other)\n', > '\n', > " def __init__(self, other='.'):\n", > ' if other is None:\n', > ' raise TypeError("Invalid initial value for path: None")\n', > ' with contextlib.suppress(AttributeError):\n', > ' self._validate()\n', > '\n', > ' @classmethod\n', > ' @functools.lru_cache\n', > ' def using_module(cls, module):\n', > " subclass_name = cls.__name__ + '_' + module.__name__\n", > ' bases = (cls,)\n', > " ns = {'module': module}\n", > ' return type(subclass_name, bases, ns)\n', > '\n', > ' @classes.ClassProperty\n', > ' @classmethod\n', > ' def _next_class(cls):\n', > ' """\n', > ' What class should be used to construct new instances from this ' > 'class\n', > ' """\n', > ' return cls\n', > '\n', > ' # --- Special Python methods.\n', > '\n', > ' def __repr__(self):\n', > " return f'{type(self).__name__}({super().__repr__()})'\n", > '\n', > ' # Adding a Path and a string yields a Path.\n', > ' def __add__(self, more):\n', > ' return self._next_class(super().__add__(more))\n', > '\n', > ' def __radd__(self, other):\n', > ' return self._next_class(other.__add__(self))\n', > '\n', > ' # The / operator joins Paths.\n', > ' def __truediv__(self, rel):\n', > ' """fp.__truediv__(rel) == fp / rel == fp.joinpath(rel)\n', > '\n', > ' Join two path components, adding a separator character if\n', > ' needed.\n', > '\n', > ' .. seealso:: :func:`os.path.join`\n', > ' """\n', > ' return self._next_class(self.module.join(self, rel))\n', > '\n', > ' # The / operator joins Paths the other way around\n', > ' def __rtruediv__(self, rel):\n', > ' """fp.__rtruediv__(rel) == rel / fp\n', > '\n', > ' Join two path components, adding a separator character if\n', > ' needed.\n', > '\n', > ' .. seealso:: :func:`os.path.join`\n', > ' """\n', > ' return self._next_class(self.module.join(rel, self))\n', > '\n', > ' def __enter__(self):\n', > ' self._old_dir = self.cwd()\n', > ' os.chdir(self)\n', > ' return self\n', > '\n', > ' def __exit__(self, *_):\n', > ' os.chdir(self._old_dir)\n', > '\n', > ' @classmethod\n', > ' def cwd(cls):\n', > ' """Return the current working directory as a path object.\n', > '\n', > ' .. seealso:: :func:`os.getcwd`\n', > ' """\n', > ' return cls(os.getcwd())\n', > '\n', > ' @classmethod\n', > ' def home(cls) -> Path:\n', > " return cls(os.path.expanduser('~'))\n", > '\n', > ' #\n', > ' # --- Operations on Path strings.\n', > '\n', > ' def absolute(self):\n', > ' """.. seealso:: :func:`os.path.abspath`"""\n', > ' return self._next_class(self.module.abspath(self))\n', > '\n', > ' def normcase(self):\n', > ' """.. seealso:: :func:`os.path.normcase`"""\n', > ' return self._next_class(self.module.normcase(self))\n', > '\n', > ' def normpath(self):\n', > ' """.. seealso:: :func:`os.path.normpath`"""\n', > ' return self._next_class(self.module.normpath(self))\n', > '\n', > ' def realpath(self):\n', > ' """.. seealso:: :func:`os.path.realpath`"""\n', > ' return self._next_class(self.module.realpath(self))\n', > '\n', > ' def expanduser(self):\n', > ' """.. seealso:: :func:`os.path.expanduser`"""\n', > ' return self._next_class(self.module.expanduser(self))\n', > '\n', > ' def expandvars(self):\n', > ' """.. seealso:: :func:`os.path.expandvars`"""\n', > ' return self._next_class(self.module.expandvars(self))\n', > '\n', > ' def dirname(self):\n', > ' """.. seealso:: :attr:`parent`, :func:`os.path.dirname`"""\n', > ' return self._next_class(self.module.dirname(self))\n', > '\n', > ' def basename(self):\n', > ' """.. seealso:: :attr:`name`, :func:`os.path.basename`"""\n', > ' return self._next_class(self.module.basename(self))\n', > '\n', > ' def expand(self):\n', > ' """Clean up a filename by calling :meth:`expandvars()`,\n', > ' :meth:`expanduser()`, and :meth:`normpath()` on it.\n', > '\n', > ' This is commonly everything needed to clean up a filename\n', > ' read from a configuration file, for example.\n', > ' """\n', > ' return self.expandvars().expanduser().normpath()\n', > '\n', > ' @property\n', > ' def stem(self):\n', > ' """The same as :meth:`name`, but with one file extension stripped ' > 'off.\n', > '\n', > " >>> Path('/home/guido/python.tar.gz').stem\n", > " 'python.tar'\n", > ' """\n', > ' base, ext = self.module.splitext(self.name)\n', > ' return base\n', > '\n', > ' def with_stem(self, stem):\n', > ' """Return a new path with the stem changed.\n', > '\n', > ' >>> Path(\'/home/guido/python.tar.gz\').with_stem("foo")\n', > " Path('/home/guido/foo.gz')\n", > ' """\n', > ' return self.with_name(stem + self.suffix)\n', > '\n', > ' @property\n', > ' def suffix(self):\n', > ' """The file extension, for example ``\'.py\'``."""\n', > ' f, suffix = self.module.splitext(self)\n', > ' return suffix\n', > '\n', > ' def with_suffix(self, suffix):\n', > ' """Return a new path with the file suffix changed (or added, if ' > 'none)\n', > '\n', > ' >>> Path(\'/home/guido/python.tar.gz\').with_suffix(".foo")\n', > " Path('/home/guido/python.tar.foo')\n", > '\n', > " >>> Path('python').with_suffix('.zip')\n", > " Path('python.zip')\n", > '\n', > " >>> Path('filename.ext').with_suffix('zip')\n", > ' Traceback (most recent call last):\n', > ' ...\n', > " ValueError: Invalid suffix 'zip'\n", > ' """\n', > " if not suffix.startswith('.'):\n", > ' raise ValueError(f"Invalid suffix {suffix!r}")\n', > '\n', > ' return self.stripext() + suffix\n', > '\n', > ' @property\n', > ' def drive(self):\n', > ' """The drive specifier, for example ``\'C:\'``.\n', > '\n', > " This is always empty on systems that don't use drive specifiers.\n", > ' """\n', > ' drive, r = self.module.splitdrive(self)\n', > ' return self._next_class(drive)\n', > '\n', > ' parent = property(\n', > ' dirname,\n', > ' None,\n', > ' None,\n', > ' """ This path\'s parent directory, as a new Path object.\n', > '\n', > ' For example,\n', > " ``Path('/usr/local/lib/libpython.so').parent ==\n", > " Path('/usr/local/lib')``\n", > '\n', > ' .. seealso:: :meth:`dirname`, :func:`os.path.dirname`\n', > ' """,\n', > ' )\n', > '\n', > ' name = property(\n', > ' basename,\n', > ' None,\n', > ' None,\n', > ' """ The name of this file or directory without the full path.\n', > '\n', > ' For example,\n', > " ``Path('/usr/local/lib/libpython.so').name == 'libpython.so'``\n", > '\n', > ' .. seealso:: :meth:`basename`, :func:`os.path.basename`\n', > ' """,\n', > ' )\n', > '\n', > ' def with_name(self, name):\n', > ' """Return a new path with the name changed.\n', > '\n', > ' >>> Path(\'/home/guido/python.tar.gz\').with_name("foo.zip")\n', > " Path('/home/guido/foo.zip')\n", > ' """\n', > ' return self._next_class(removesuffix(self, self.name) + name)\n', > '\n', > ' def splitpath(self):\n', > ' """Return two-tuple of ``.parent``, ``.name``.\n', > '\n', > ' .. seealso:: :attr:`parent`, :attr:`name`, :func:`os.path.split`\n', > ' """\n', > ' parent, child = self.module.split(self)\n', > ' return self._next_class(parent), child\n', > '\n', > ' def splitdrive(self):\n', > ' """Return two-tuple of ``.drive`` and rest without drive.\n', > '\n', > ' Split the drive specifier from this path. If there is\n', > ' no drive specifier, :samp:`{p.drive}` is empty, so the return ' > 'value\n', > " is simply ``(Path(''), p)``. This is always the case on Unix.\n", > '\n', > ' .. seealso:: :func:`os.path.splitdrive`\n', > ' """\n', > ' drive, rel = self.module.splitdrive(self)\n', > ' return self._next_class(drive), self._next_class(rel)\n', > '\n', > ' def splitext(self):\n', > ' """Return two-tuple of ``.stripext()`` and ``.ext``.\n', > '\n', > ' Split the filename extension from this path and return\n', > ' the two parts. Either part may be empty.\n', > '\n', > " The extension is everything from ``'.'`` to the end of the\n", > ' last path segment. This has the property that if\n', > ' ``(a, b) == p.splitext()``, then ``a + b == p``.\n', > '\n', > ' .. seealso:: :func:`os.path.splitext`\n', > ' """\n', > ' filename, ext = self.module.splitext(self)\n', > ' return self._next_class(filename), ext\n', > '\n', > ' def stripext(self):\n', > ' """Remove one file extension from the path.\n', > '\n', > " For example, ``Path('/home/guido/python.tar.gz').stripext()``\n", > " returns ``Path('/home/guido/python.tar')``.\n", > ' """\n', > ' return self.splitext()[0]\n', > '\n', > ' @classes.multimethod\n', > ' def joinpath(cls, first, *others):\n', > ' """\n', > ' Join first to zero or more :class:`Path` components,\n', > ' adding a separator character (:samp:`{first}.module.sep`)\n', > ' if needed. Returns a new instance of\n', > ' :samp:`{first}._next_class`.\n', > '\n', > ' .. seealso:: :func:`os.path.join`\n', > ' """\n', > ' return cls._next_class(cls.module.join(first, *others))\n', > '\n', > ' def splitall(self):\n', > ' r"""Return a list of the path components in this path.\n', > '\n', > ' The first item in the list will be a Path. Its value will be\n', > ' either :data:`os.curdir`, :data:`os.pardir`, empty, or the root\n', > " directory of this path (for example, ``'/'`` or ``'C:\\\\'``). " > 'The\n', > ' other items in the list will be strings.\n', > '\n', > ' ``Path.joinpath(*result)`` will yield the original path.\n', > '\n', > " >>> Path('/foo/bar/baz').splitall()\n", > " [Path('/'), 'foo', 'bar', 'baz']\n", > ' """\n', > ' return list(self._parts())\n', > '\n', > ' def parts(self):\n', > ' """\n', > " >>> Path('/foo/bar/baz').parts()\n", > " (Path('/'), 'foo', 'bar', 'baz')\n", > ' """\n', > ' return tuple(self._parts())\n', > '\n', > ' def _parts(self):\n', > ' return reversed(tuple(self._parts_iter()))\n', > '\n', > ' def _parts_iter(self):\n', > ' loc = self\n', > ' while loc != os.curdir and loc != os.pardir:\n', > ' prev = loc\n', > ' loc, child = prev.splitpath()\n', > ' if loc == prev:\n', > ' break\n', > ' yield child\n', > ' yield loc\n', > '\n', > " def relpath(self, start='.'):\n", > ' """Return this path as a relative path,\n', > ' based from `start`, which defaults to the current working ' > 'directory.\n', > ' """\n', > ' cwd = self._next_class(start)\n', > ' return cwd.relpathto(self)\n', > '\n', > ' def relpathto(self, dest):\n', > ' """Return a relative path from `self` to `dest`.\n', > '\n', > ' If there is no relative path from `self` to `dest`, for example if\n', > ' they reside on different drives in Windows, then this returns\n', > ' ``dest.absolute()``.\n', > ' """\n', > ' origin = self.absolute()\n', > ' dest = self._next_class(dest).absolute()\n', > '\n', > ' orig_list = origin.normcase().splitall()\n', > " # Don't normcase dest! We want to preserve the case.\n", > ' dest_list = dest.splitall()\n', > '\n', > ' if orig_list[0] != self.module.normcase(dest_list[0]):\n', > " # Can't get here from there.\n", > ' return dest\n', > '\n', > ' # Find the location where the two paths start to differ.\n', > ' i = 0\n', > ' for start_seg, dest_seg in zip(orig_list, dest_list):\n', > ' if start_seg != self.module.normcase(dest_seg):\n', > ' break\n', > ' i += 1\n', > '\n', > ' # Now i is the point where the two paths diverge.\n', > ' # Need a certain number of "os.pardir"s to work up\n', > ' # from the origin to the point of divergence.\n', > ' segments = [os.pardir] * (len(orig_list) - i)\n', > ' # Need to add the diverging part of dest_list.\n', > ' segments += dest_list[i:]\n', > ' if len(segments) == 0:\n', > ' # If they happen to be identical, use os.curdir.\n', > ' relpath = os.curdir\n', > ' else:\n', > ' relpath = self.module.join(*segments)\n', > ' return self._next_class(relpath)\n', > '\n', > ' # --- Listing, searching, walking, and matching\n', > '\n', > ' def iterdir(self, match=None):\n', > ' """Yields items in this directory.\n', > '\n', > ' Use :meth:`files` or :meth:`dirs` instead if you want a listing\n', > ' of just files or just subdirectories.\n', > '\n', > ' The elements of the list are Path objects.\n', > '\n', > ' With the optional `match` argument, a callable,\n', > ' only return items whose names match the given pattern.\n', > '\n', > ' .. seealso:: :meth:`files`, :meth:`dirs`\n', > ' """\n', > ' match = matchers.load(match)\n', > ' return filter(match, (self / child for child in os.listdir(self)))\n', > '\n', > ' def dirs(self, *args, **kwargs):\n', > ' """List of this directory\'s subdirectories.\n', > '\n', > ' The elements of the list are Path objects.\n', > ' This does not walk recursively into subdirectories\n', > ' (but see :meth:`walkdirs`).\n', > '\n', > ' Accepts parameters to :meth:`iterdir`.\n', > ' """\n', > ' return [p for p in self.iterdir(*args, **kwargs) if p.is_dir()]\n', > '\n', > ' def files(self, *args, **kwargs):\n', > ' """List of the files in self.\n', > '\n', > ' The elements of the list are Path objects.\n', > ' This does not walk into subdirectories (see :meth:`walkfiles`).\n', > '\n', > ' Accepts parameters to :meth:`iterdir`.\n', > ' """\n', > '\n', > ' return [p for p in self.iterdir(*args, **kwargs) if p.is_file()]\n', > '\n', > " def walk(self, match=None, errors='strict'):\n", > ' """Iterator over files and subdirs, recursively.\n', > '\n', > ' The iterator yields Path objects naming each child item of\n', > ' this directory and its descendants. This requires that\n', > ' ``D.is_dir()``.\n', > '\n', > ' This performs a depth-first traversal of the directory tree.\n', > ' Each directory is returned just before all its children.\n', > '\n', > ' The `errors=` keyword argument controls behavior when an\n', > " error occurs. The default is ``'strict'``, which causes an\n", > " exception. Other allowed values are ``'warn'`` (which\n", > " reports the error via :func:`warnings.warn()`), and ``'ignore'``.\n", > ' `errors` may also be an arbitrary callable taking a msg parameter.\n', > ' """\n', > '\n', > ' errors = Handlers._resolve(errors)\n', > ' match = matchers.load(match)\n', > '\n', > ' try:\n', > ' childList = self.iterdir()\n', > ' except Exception as exc:\n', > ' errors(f"Unable to list directory \'{self}\': {exc}")\n', > ' return\n', > '\n', > ' for child in childList:\n', > ' traverse = None\n', > ' if match(child):\n', > ' traverse = yield child\n', > ' traverse = traverse or child.is_dir\n', > ' try:\n', > ' do_traverse = traverse()\n', > ' except Exception as exc:\n', > ' errors(f"Unable to access \'{child}\': {exc}")\n', > ' continue\n', > '\n', > ' if do_traverse:\n', > ' yield from child.walk(errors=errors, match=match)\n', > '\n', > ' def walkdirs(self, *args, **kwargs):\n', > ' """Iterator over subdirs, recursively."""\n', > ' return (item for item in self.walk(*args, **kwargs) if ' > 'item.is_dir())\n', > '\n', > ' def walkfiles(self, *args, **kwargs):\n', > ' """Iterator over files, recursively."""\n', > ' return (item for item in self.walk(*args, **kwargs) if ' > 'item.is_file())\n', > '\n', > ' def fnmatch(self, pattern, normcase=None):\n', > ' """Return ``True`` if `self.name` matches the given `pattern`.\n', > '\n', > ' `pattern` - A filename pattern with wildcards,\n', > " for example ``'*.py'``. If the pattern contains a `normcase`\n", > ' attribute, it is applied to the name and path prior to ' > 'comparison.\n', > '\n', > ' `normcase` - (optional) A function used to normalize the pattern ' > 'and\n', > ' filename before matching. Defaults to normcase from\n', > ' ``self.module``, :func:`os.path.normcase`.\n', > '\n', > ' .. seealso:: :func:`fnmatch.fnmatch`\n', > ' """\n', > " default_normcase = getattr(pattern, 'normcase', " > 'self.module.normcase)\n', > ' normcase = normcase or default_normcase\n', > ' name = normcase(self.name)\n', > ' pattern = normcase(pattern)\n', > ' return fnmatch.fnmatchcase(name, pattern)\n', > '\n', > ' def glob(self, pattern):\n', > ' """Return a list of Path objects that match the pattern.\n', > '\n', > ' `pattern` - a path relative to this directory, with wildcards.\n', > '\n', > " For example, ``Path('/users').glob('*/bin/*')`` returns a list\n", > ' of all the files users have in their :file:`bin` directories.\n', > '\n', > ' .. seealso:: :func:`glob.glob`\n', > '\n', > ' .. note:: Glob is **not** recursive, even when using ``**``.\n', > ' To do recursive globbing see :func:`walk`,\n', > ' :func:`walkdirs` or :func:`walkfiles`.\n', > ' """\n', > ' cls = self._next_class\n', > ' return [cls(s) for s in glob.glob(self / pattern)]\n', > '\n', > ' def iglob(self, pattern):\n', > ' """Return an iterator of Path objects that match the pattern.\n', > '\n', > ' `pattern` - a path relative to this directory, with wildcards.\n', > '\n', > " For example, ``Path('/users').iglob('*/bin/*')`` returns an\n", > ' iterator of all the files users have in their :file:`bin`\n', > ' directories.\n', > '\n', > ' .. seealso:: :func:`glob.iglob`\n', > '\n', > ' .. note:: Glob is **not** recursive, even when using ``**``.\n', > ' To do recursive globbing see :func:`walk`,\n', > ' :func:`walkdirs` or :func:`walkfiles`.\n', > ' """\n', > ' cls = self._next_class\n', > ' return (cls(s) for s in glob.iglob(self / pattern))\n', > '\n', > ' #\n', > ' # --- Reading or writing an entire file at once.\n', > '\n', > ' @functools.wraps(open, assigned=())\n', > ' def open(self, *args, **kwargs):\n', > ' """Open this file and return a corresponding file object.\n', > '\n', > ' Keyword arguments work as in :func:`io.open`. If the file cannot ' > 'be\n', > ' opened, an :class:`OSError` is raised.\n', > ' """\n', > ' return open(self, *args, **kwargs)\n', > '\n', > ' def bytes(self):\n', > ' """Open this file, read all bytes, return them as a string."""\n', > " with self.open('rb') as f:\n", > ' return f.read()\n', > '\n', > ' @overload\n', > ' def chunks(\n', > ' self,\n', > ' size: int,\n', > ' mode: OpenTextMode = ...,\n', > ' buffering: int = ...,\n', > ' encoding: str | None = ...,\n', > ' errors: str | None = ...,\n', > ' newline: str | None = ...,\n', > ' closefd: bool = ...,\n', > ' opener: Callable[[str, int], int] | None = ...,\n', > ' ) -> Iterator[str]: ...\n', > '\n', > ' @overload\n', > ' def chunks(\n', > ' self,\n', > ' size: int,\n', > ' mode: OpenBinaryMode,\n', > ' buffering: int = ...,\n', > ' encoding: str | None = ...,\n', > ' errors: str | None = ...,\n', > ' newline: str | None = ...,\n', > ' closefd: bool = ...,\n', > ' opener: Callable[[str, int], int] | None = ...,\n', > ' ) -> Iterator[builtins.bytes]: ...\n', > '\n', > ' @overload\n', > ' def chunks(\n', > ' self,\n', > ' size: int,\n', > ' mode: str,\n', > ' buffering: int = ...,\n', > ' encoding: str | None = ...,\n', > ' errors: str | None = ...,\n', > ' newline: str | None = ...,\n', > ' closefd: bool = ...,\n', > ' opener: Callable[[str, int], int] | None = ...,\n', > ' ) -> Iterator[str | builtins.bytes]: ...\n', > '\n', > ' def chunks(self, size, *args, **kwargs):\n', > ' """Returns a generator yielding chunks of the file, so it can\n', > ' be read piece by piece with a simple for loop.\n', > '\n', > ' Any argument you pass after `size` will be passed to :meth:`open`.\n', > '\n', > ' :example:\n', > '\n', > ' >>> hash = hashlib.md5()\n', > ' >>> for chunk in Path("NEWS.rst").chunks(8192, mode=\'rb\'):\n', > ' ... hash.update(chunk)\n', > '\n', > ' This will read the file by chunks of 8192 bytes.\n', > ' """\n', > ' with self.open(*args, **kwargs) as f:\n', > ' yield from iter(lambda: f.read(size) or None, None)\n', > '\n', > ' def write_bytes(self, bytes, append=False):\n', > ' """Open this file and write the given bytes to it.\n', > '\n', > ' Default behavior is to overwrite any existing file.\n', > ' Call ``p.write_bytes(bytes, append=True)`` to append instead.\n', > ' """\n', > " with self.open('ab' if append else 'wb') as f:\n", > ' f.write(bytes)\n', > '\n', > ' def read_text(self, encoding=None, errors=None):\n', > ' r"""Open this file, read it in, return the content as a string.\n', > '\n', > ' Optional parameters are passed to :meth:`open`.\n', > '\n', > ' .. seealso:: :meth:`lines`\n', > ' """\n', > ' with self.open(encoding=encoding, errors=errors) as f:\n', > ' return f.read()\n', > '\n', > ' def read_bytes(self):\n', > ' r"""Return the contents of this file as bytes."""\n', > " with self.open(mode='rb') as f:\n", > ' return f.read()\n', > '\n', > ' def write_text(\n', > ' self,\n', > ' text: str,\n', > ' encoding: str | None = None,\n', > " errors: str = 'strict',\n", > ' linesep: str | None = os.linesep,\n', > ' append: bool = False,\n', > ' ) -> None:\n', > ' r"""Write the given text to this file.\n', > '\n', > ' The default behavior is to overwrite any existing file;\n', > ' to append instead, use the `append=True` keyword argument.\n', > '\n', > ' There are two differences between :meth:`write_text` and\n', > ' :meth:`write_bytes`: newline handling and Unicode handling.\n', > ' See below.\n', > '\n', > ' Parameters:\n', > '\n', > ' `text` - str - The text to be written.\n', > '\n', > ' `encoding` - str - The text encoding used.\n', > '\n', > ' `errors` - str - How to handle Unicode encoding errors.\n', > " Default is ``'strict'``. See ``help(unicode.encode)`` for " > 'the\n', > " options. Ignored if `text` isn't a Unicode string.\n", > '\n', > ' `linesep` - keyword argument - str/unicode - The sequence of\n', > ' characters to be used to mark end-of-line. The default is\n', > ' :data:`os.linesep`. Specify ``None`` to\n', > ' use newlines unmodified.\n', > '\n', > ' `append` - keyword argument - bool - Specifies what to do if\n', > ' the file already exists (``True``: append to the end of it;\n', > ' ``False``: overwrite it). The default is ``False``.\n', > '\n', > '\n', > ' --- Newline handling.\n', > '\n', > ' ``write_text()`` converts all standard end-of-line sequences\n', > " (``'\\n'``, ``'\\r'``, and ``'\\r\\n'``) to your platform's " > 'default\n', > ' end-of-line sequence (see :data:`os.linesep`; on Windows, for ' > 'example,\n', > " the end-of-line marker is ``'\\r\\n'``).\n", > '\n', > " To override the platform's default, pass the `linesep=`\n", > ' keyword argument. To preserve the newlines as-is, pass\n', > ' ``linesep=None``.\n', > '\n', > ' This handling applies to Unicode text and bytes, except\n', > ' with Unicode, additional non-ASCII newlines are recognized:\n', > ' ``\\x85``, ``\\r\\x85``, and ``\\u2028``.\n', > '\n', > ' --- Unicode\n', > '\n', > ' `text` is written using the\n', > ' specified `encoding` (or the default encoding if `encoding`\n', > " isn't specified). The `errors` argument applies only to this\n", > ' conversion.\n', > ' """\n', > ' if linesep is not None:\n', > ' text = U_NEWLINE.sub(linesep, text)\n', > ' bytes = text.encode(encoding or sys.getdefaultencoding(), errors)\n', > ' self.write_bytes(bytes, append=append)\n', > '\n', > ' def lines(self, encoding=None, errors=None, retain=True):\n', > ' r"""Open this file, read all lines, return them in a list.\n', > '\n', > ' Optional arguments:\n', > ' `encoding` - The Unicode encoding (or character set) of\n', > ' the file. The default is ``None``, meaning use\n', > ' ``locale.getpreferredencoding()``.\n', > ' `errors` - How to handle Unicode errors; see\n', > ' `open ' > '<https://docs.python.org/3/library/functions.html#open>`_\n', > ' for the options. Default is ``None`` meaning "strict".\n', > ' `retain` - If ``True`` (default), retain newline characters,\n', > ' but translate all newline\n', > ' characters to ``\\n``. If ``False``, newline characters ' > 'are\n', > ' omitted.\n', > ' """\n', > " text = U_NEWLINE.sub('\\n', self.read_text(encoding, errors))\n", > ' return text.splitlines(retain)\n', > '\n', > ' def write_lines(\n', > ' self,\n', > ' lines,\n', > ' encoding=None,\n', > " errors='strict',\n", > ' *,\n', > ' append=False,\n', > ' ):\n', > ' r"""Write the given lines of text to this file.\n', > '\n', > ' By default this overwrites any existing file at this path.\n', > '\n', > ' Puts a platform-specific newline sequence on every line.\n', > '\n', > ' `lines` - A list of strings.\n', > '\n', > ' `encoding` - A Unicode encoding to use. This applies only if\n', > ' `lines` contains any Unicode strings.\n', > '\n', > ' `errors` - How to handle errors in Unicode encoding. This\n', > ' also applies only to Unicode strings.\n', > '\n', > ' Use the keyword argument ``append=True`` to append lines to the\n', > ' file. The default is to overwrite the file.\n', > ' """\n', > " mode = 'a' if append else 'w'\n", > " with self.open(mode, encoding=encoding, errors=errors, newline='') " > 'as f:\n', > ' f.writelines(self._replace_linesep(lines))\n', > '\n', > ' @staticmethod\n', > ' def _replace_linesep(lines):\n', > ' return (line + os.linesep for line in _strip_newlines(lines))\n', > '\n', > ' def read_md5(self):\n', > ' """Calculate the md5 hash for this file.\n', > '\n', > ' This reads through the entire file.\n', > '\n', > ' .. seealso:: :meth:`read_hash`\n', > ' """\n', > " return self.read_hash('md5')\n", > '\n', > ' def _hash(self, hash_name):\n', > ' """Returns a hash object for the file at the current path.\n', > '\n', > " `hash_name` should be a hash algo name (such as ``'md5'``\n", > " or ``'sha1'``) that's available in the :mod:`hashlib` module.\n", > ' """\n', > ' m = hashlib.new(hash_name)\n', > ' for chunk in self.chunks(8192, mode="rb"):\n', > ' m.update(chunk)\n', > ' return m\n', > '\n', > ' def read_hash(self, hash_name):\n', > ' """Calculate given hash for this file.\n', > '\n', > ' List of supported hashes can be obtained from :mod:`hashlib` ' > 'package.\n', > ' This reads the entire file.\n', > '\n', > ' .. seealso:: :meth:`hashlib.hash.digest`\n', > ' """\n', > ' return self._hash(hash_name).digest()\n', > '\n', > ' def read_hexhash(self, hash_name):\n', > ' """Calculate given hash for this file, returning hexdigest.\n', > '\n', > ' List of supported hashes can be obtained from :mod:`hashlib` ' > 'package.\n', > ' This reads the entire file.\n', > '\n', > ' .. seealso:: :meth:`hashlib.hash.hexdigest`\n', > ' """\n', > ' return self._hash(hash_name).hexdigest()\n', > '\n', > ' # --- Methods for querying the filesystem.\n', > ' # N.B. On some platforms, the os.path functions may be implemented in ' > 'C\n', > " # (e.g. isdir on Windows, Python 3.2.2), and compiled functions don't " > 'get\n', > ' # bound. Playing it safe and wrapping them all in method calls.\n', > '\n', > ' def isabs(self):\n', > ' """\n', > " >>> Path('.').isabs()\n", > ' False\n', > '\n', > ' .. seealso:: :func:`os.path.isabs`\n', > ' """\n', > ' return self.module.isabs(self)\n', > '\n', > ' def exists(self):\n', > ' """.. seealso:: :func:`os.path.exists`"""\n', > ' return self.module.exists(self)\n', > '\n', > ' def is_dir(self):\n', > ' """.. seealso:: :func:`os.path.isdir`"""\n', > ' return self.module.isdir(self)\n', > '\n', > ' def is_file(self):\n', > ' """.. seealso:: :func:`os.path.isfile`"""\n', > ' return self.module.isfile(self)\n', > '\n', > ' def islink(self):\n', > ' """.. seealso:: :func:`os.path.islink`"""\n', > ' return self.module.islink(self)\n', > '\n', > ' def ismount(self):\n', > ' """\n', > " >>> Path('.').ismount()\n", > ' False\n', > '\n', > ' .. seealso:: :func:`os.path.ismount`\n', > ' """\n', > ' return self.module.ismount(self)\n', > '\n', > ' def samefile(self, other):\n', > ' """.. seealso:: :func:`os.path.samefile`"""\n', > ' return self.module.samefile(self, other)\n', > '\n', > ' def getatime(self):\n', > ' """.. seealso:: :attr:`atime`, :func:`os.path.getatime`"""\n', > ' return self.module.getatime(self)\n', > '\n', > ' def set_atime(self, value):\n', > ' mtime_ns = self.stat().st_atime_ns\n', > ' self.utime(ns=(_make_timestamp_ns(value), mtime_ns))\n', > '\n', > ' atime = property(\n', > ' getatime,\n', > ' set_atime,\n', > ' None,\n', > ' """\n', > ' Last access time of the file.\n', > '\n', > " >>> Path('.').atime > 0\n", > ' True\n', > '\n', > ' Allows setting:\n', > '\n', > ' >>> some_file = ' > "Path(getfixture('tmp_path')).joinpath('file.txt').touch()\n", > ' >>> MST = datetime.timezone(datetime.timedelta(hours=-7))\n', > ' >>> some_file.atime = datetime.datetime(1976, 5, 7, 10, ' > 'tzinfo=MST)\n', > ' >>> some_file.atime\n', > ' 200336400.0\n', > '\n', > ' .. seealso:: :meth:`getatime`, :func:`os.path.getatime`\n', > ' """,\n', > ' )\n', > '\n', > ' def getmtime(self):\n', > ' """.. seealso:: :attr:`mtime`, :func:`os.path.getmtime`"""\n', > ' return self.module.getmtime(self)\n', > '\n', > ' def set_mtime(self, value):\n', > ' atime_ns = self.stat().st_atime_ns\n', > ' self.utime(ns=(atime_ns, _make_timestamp_ns(value)))\n', > '\n', > ' mtime = property(\n', > ' getmtime,\n', > ' set_mtime,\n', > ' None,\n', > ' """\n', > ' Last modified time of the file.\n', > '\n', > ' Allows setting:\n', > '\n', > ' >>> some_file = ' > "Path(getfixture('tmp_path')).joinpath('file.txt').touch()\n", > ' >>> MST = datetime.timezone(datetime.timedelta(hours=-7))\n', > ' >>> some_file.mtime = datetime.datetime(1976, 5, 7, 10, ' > 'tzinfo=MST)\n', > ' >>> some_file.mtime\n', > ' 200336400.0\n', > '\n', > ' .. seealso:: :meth:`getmtime`, :func:`os.path.getmtime`\n', > ' """,\n', > ' )\n', > '\n', > ' def getctime(self):\n', > ' """.. seealso:: :attr:`ctime`, :func:`os.path.getctime`"""\n', > ' return self.module.getctime(self)\n', > '\n', > ' ctime = property(\n', > ' getctime,\n', > ' None,\n', > ' None,\n', > ' """ Creation time of the file.\n', > '\n', > ' .. seealso:: :meth:`getctime`, :func:`os.path.getctime`\n', > ' """,\n', > ' )\n', > '\n', > ' def getsize(self):\n', > ' """.. seealso:: :attr:`size`, :func:`os.path.getsize`"""\n', > ' return self.module.getsize(self)\n', > '\n', > ' size = property(\n', > ' getsize,\n', > ' None,\n', > ' None,\n', > ' """ Size of the file, in bytes.\n', > '\n', > ' .. seealso:: :meth:`getsize`, :func:`os.path.getsize`\n', > ' """,\n', > ' )\n', > '\n', > ' @property\n', > ' def permissions(self) -> masks.Permissions:\n', > ' """\n', > ' Permissions.\n', > '\n', > " >>> perms = Path('.').permissions\n", > ' >>> isinstance(perms, int)\n', > ' True\n', > " >>> set(perms.symbolic) <= set('rwx-')\n", > ' True\n', > ' >>> perms.symbolic\n', > " 'r...'\n", > ' """\n', > ' return masks.Permissions(self.stat().st_mode)\n', > '\n', > ' def access(self, *args, **kwargs):\n', > ' """\n', > ' Return does the real user have access to this path.\n', > '\n', > " >>> Path('.').access(os.F_OK)\n", > ' True\n', > '\n', > ' .. seealso:: :func:`os.access`\n', > ' """\n', > ' return os.access(self, *args, **kwargs)\n', > '\n', > ' def stat(self, *, follow_symlinks=True):\n', > ' """\n', > ' Perform a ``stat()`` system call on this path.\n', > '\n', > " >>> Path('.').stat()\n", > ' os.stat_result(...)\n', > '\n', > ' .. seealso:: :meth:`lstat`, :func:`os.stat`\n', > ' """\n', > ' return os.stat(self, follow_symlinks=follow_symlinks)\n', > '\n', > ' def lstat(self):\n', > ' """\n', > ' Like :meth:`stat`, but do not follow symbolic links.\n', > '\n', > " >>> Path('.').lstat() == Path('.').stat()\n", > ' True\n', > '\n', > ' .. seealso:: :meth:`stat`, :func:`os.lstat`\n', > ' """\n', > ' return os.lstat(self)\n', > '\n', > ' def __get_owner_windows(self): # pragma: nocover\n', > ' r"""\n', > ' Return the name of the owner of this file or directory. Follow\n', > ' symbolic links.\n', > '\n', > ' Return a name of the form ``DOMAIN\\User Name``; may be a group.\n', > '\n', > ' .. seealso:: :attr:`owner`\n', > ' """\n', > ' desc = win32security.GetFileSecurity(\n', > ' self, win32security.OWNER_SECURITY_INFORMATION\n', > ' )\n', > ' sid = desc.GetSecurityDescriptorOwner()\n', > ' account, domain, typecode = win32security.LookupAccountSid(None, ' > 'sid)\n', > " return domain + '\\\\' + account\n", > '\n', > ' def __get_owner_unix(self): # pragma: nocover\n', > ' """\n', > ' Return the name of the owner of this file or directory. Follow\n', > ' symbolic links.\n', > '\n', > ' .. seealso:: :attr:`owner`\n', > ' """\n', > ' st = self.stat()\n', > ' return pwd.getpwuid(st.st_uid).pw_name\n', > '\n', > ' def __get_owner_not_implemented(self): # pragma: nocover\n', > ' raise NotImplementedError("Ownership not available on this ' > 'platform.")\n', > '\n', > ' get_owner = (\n', > ' __get_owner_windows\n', > " if 'win32security' in globals()\n", > ' else __get_owner_unix\n', > " if 'pwd' in globals()\n", > ' else __get_owner_not_implemented\n', > ' )\n', > '\n', > ' owner = property(\n', > ' get_owner,\n', > ' None,\n', > ' None,\n', > ' """ Name of the owner of this file or directory.\n', > '\n', > ' .. seealso:: :meth:`get_owner`""",\n', > ' )\n', > '\n', > " if 'grp' in globals(): # pragma: no cover\n", > '\n', > ' def group(self, *, follow_symlinks=True):\n', > ' """\n', > ' Return the group name of the file gid.\n', > ' """\n', > ' gid = self.stat(follow_symlinks=follow_symlinks).st_gid\n', > ' return grp.getgrgid(gid).gr_name\n', > '\n', > " if hasattr(os, 'statvfs'):\n", > '\n', > ' def statvfs(self):\n', > ' """Perform a ``statvfs()`` system call on this path.\n', > '\n', > ' .. seealso:: :func:`os.statvfs`\n', > ' """\n', > ' return os.statvfs(self)\n', > '\n', > " if hasattr(os, 'pathconf'):\n", > '\n', > ' def pathconf(self, name):\n', > ' """.. seealso:: :func:`os.pathconf`"""\n', > ' return os.pathconf(self, name)\n', > '\n', > ' #\n', > ' # --- Modifying operations on files and directories\n', > '\n', > ' def utime(self, *args, **kwargs):\n', > ' """Set the access and modified times of this file.\n', > '\n', > ' .. seealso:: :func:`os.utime`\n', > ' """\n', > ' os.utime(self, *args, **kwargs)\n', > ' return self\n', > '\n', > ' def chmod(self, mode):\n', > ' """\n', > ' Set the mode. May be the new mode (os.chmod behavior) or a ' > '`symbolic\n', > ' mode <http://en.wikipedia.org/wiki/Chmod#Symbolic_modes>`_.\n', > '\n', > ' >>> a_file = ' > "Path(getfixture('tmp_path')).joinpath('afile.txt').touch()\n", > ' >>> a_file.chmod(0o700)\n', > ' Path(...\n', > " >>> a_file.chmod('u+x')\n", > ' Path(...\n', > '\n', > ' .. seealso:: :func:`os.chmod`\n', > ' """\n', > ' if isinstance(mode, str):\n', > ' mask = masks.compound(mode)\n', > ' mode = mask(self.stat().st_mode)\n', > ' os.chmod(self, mode)\n', > ' return self\n', > '\n', > " if hasattr(os, 'chown'):\n", > '\n', > ' def chown(self, uid=-1, gid=-1):\n', > ' """\n', > ' Change the owner and group by names or numbers.\n', > '\n', > ' .. seealso:: :func:`os.chown`\n', > ' """\n', > '\n', > ' def resolve_uid(uid):\n', > ' return uid if isinstance(uid, int) else ' > 'pwd.getpwnam(uid).pw_uid\n', > '\n', > ' def resolve_gid(gid):\n', > ' return gid if isinstance(gid, int) else ' > 'grp.getgrnam(gid).gr_gid\n', > '\n', > ' os.chown(self, resolve_uid(uid), resolve_gid(gid))\n', > ' return self\n', > '\n', > ' def rename(self, new):\n', > ' """.. seealso:: :func:`os.rename`"""\n', > ' os.rename(self, new)\n', > ' return self._next_class(new)\n', > '\n', > ' def renames(self, new):\n', > ' """.. seealso:: :func:`os.renames`"""\n', > ' os.renames(self, new)\n', > ' return self._next_class(new)\n', > '\n', > ' def replace(self, target_or_old: Path | str, *args) -> Path:\n', > ' """\n', > ' Replace a path or substitute substrings.\n', > '\n', > ' Implements both pathlib.Path.replace and str.replace.\n', > '\n', > ' If only a target is supplied, rename this path to the target path,\n', > ' overwriting if that path exists.\n', > '\n', > " >>> dest = Path(getfixture('tmp_path'))\n", > " >>> orig = dest.joinpath('foo').touch()\n", > " >>> new = orig.replace(dest.joinpath('fee'))\n", > ' >>> orig.exists()\n', > ' False\n', > ' >>> new.exists()\n', > ' True\n', > '\n', > ' ..seealso:: :meth:`pathlib.Path.replace`\n', > '\n', > ' If a second parameter is supplied, perform a textual replacement.\n', > '\n', > " >>> Path('foo').replace('o', 'e')\n", > " Path('fee')\n", > " >>> Path('foo').replace('o', 'l', 1)\n", > " Path('flo')\n", > '\n', > ' ..seealso:: :meth:`str.replace`\n', > ' """\n', > ' return self._next_class(\n', > ' super().replace(target_or_old, *args)\n', > ' if args\n', > ' else pathlib.Path(self).replace(target_or_old)\n', > ' )\n', > '\n', > ' #\n', > ' # --- Create/delete operations on directories\n', > '\n', > ' def mkdir(self, mode=0o777):\n', > ' """.. seealso:: :func:`os.mkdir`"""\n', > ' os.mkdir(self, mode)\n', > ' return self\n', > '\n', > ' def mkdir_p(self, mode=0o777):\n', > ' """Like :meth:`mkdir`, but does not raise an exception if the\n', > ' directory already exists."""\n', > ' with contextlib.suppress(FileExistsError):\n', > ' self.mkdir(mode)\n', > ' return self\n', > '\n', > ' def makedirs(self, mode=0o777):\n', > ' """.. seealso:: :func:`os.makedirs`"""\n', > ' os.makedirs(self, mode)\n', > ' return self\n', > '\n', > ' def makedirs_p(self, mode=0o777):\n', > ' """Like :meth:`makedirs`, but does not raise an exception if the\n', > ' directory already exists."""\n', > ' with contextlib.suppress(FileExistsError):\n', > ' self.makedirs(mode)\n', > ' return self\n', > '\n', > ' def rmdir(self):\n', > ' """.. seealso:: :func:`os.rmdir`"""\n', > ' os.rmdir(self)\n', > ' return self\n', > '\n', > ' def rmdir_p(self):\n', > ' """Like :meth:`rmdir`, but does not raise an exception if the\n', > ' directory is not empty or does not exist."""\n', > ' suppressed = FileNotFoundError, FileExistsError, DirectoryNotEmpty\n', > ' with contextlib.suppress(suppressed):\n', > ' with DirectoryNotEmpty.translate():\n', > ' self.rmdir()\n', > ' return self\n', > '\n', > ' def removedirs(self):\n', > ' """.. seealso:: :func:`os.removedirs`"""\n', > ' os.removedirs(self)\n', > ' return self\n', > '\n', > ' def removedirs_p(self):\n', > ' """Like :meth:`removedirs`, but does not raise an exception if the\n', > ' directory is not empty or does not exist."""\n', > ' with contextlib.suppress(FileExistsError, DirectoryNotEmpty):\n', > ' with DirectoryNotEmpty.translate():\n', > ' self.removedirs()\n', > ' return self\n', > '\n', > ' # --- Modifying operations on files\n', > '\n', > ' def touch(self):\n', > ' """Set the access/modified times of this file to the current time.\n', > ' Create the file if it does not exist.\n', > ' """\n', > ' os.close(os.open(self, os.O_WRONLY | os.O_CREAT, 0o666))\n', > ' os.utime(self, None)\n', > ' return self\n', > '\n', > ' def remove(self):\n', > ' """.. seealso:: :func:`os.remove`"""\n', > ' os.remove(self)\n', > ' return self\n', > '\n', > ' def remove_p(self):\n', > ' """Like :meth:`remove`, but does not raise an exception if the\n', > ' file does not exist."""\n', > ' with contextlib.suppress(FileNotFoundError):\n', > ' self.unlink()\n', > ' return self\n', > '\n', > ' unlink = remove\n', > ' unlink_p = remove_p\n', > '\n', > ' # --- Links\n', > '\n', > ' def hardlink_to(self, target: str) -> None:\n', > ' """\n', > ' Create a hard link at self, pointing to target.\n', > '\n', > ' .. seealso:: :func:`os.link`\n', > ' """\n', > ' os.link(target, self)\n', > '\n', > ' def link(self, newpath):\n', > ' """Create a hard link at `newpath`, pointing to this file.\n', > '\n', > ' .. seealso:: :func:`os.link`\n', > ' """\n', > ' os.link(self, newpath)\n', > ' return self._next_class(newpath)\n', > '\n', > ' def symlink_to(self, target: str, target_is_directory: bool = False) -> ' > 'None:\n', > ' """\n', > ' Create a symbolic link at self, pointing to target.\n', > '\n', > ' .. seealso:: :func:`os.symlink`\n', > ' """\n', > ' os.symlink(target, self, target_is_directory)\n', > '\n', > ' def symlink(self, newlink=None):\n', > ' """Create a symbolic link at `newlink`, pointing here.\n', > '\n', > ' If newlink is not supplied, the symbolic link will assume\n', > ' the name self.basename(), creating the link in the cwd.\n', > '\n', > ' .. seealso:: :func:`os.symlink`\n', > ' """\n', > ' if newlink is None:\n', > ' newlink = self.basename()\n', > ' os.symlink(self, newlink)\n', > ' return self._next_class(newlink)\n', > '\n', > ' def readlink(self):\n', > ' """Return the path to which this symbolic link points.\n', > '\n', > ' The result may be an absolute or a relative path.\n', > '\n', > ' .. seealso:: :meth:`readlinkabs`, :func:`os.readlink`\n', > ' """\n', > ' return self._next_class(removeprefix(os.readlink(self), ' > "'\\\\\\\\?\\\\'))\n", > '\n', > ' def readlinkabs(self):\n', > ' """Return the path to which this symbolic link points.\n', > '\n', > ' The result is always an absolute path.\n', > '\n', > ' .. seealso:: :meth:`readlink`, :func:`os.readlink`\n', > ' """\n', > ' p = self.readlink()\n', > ' return p if p.isabs() else (self.parent / p).absolute()\n', > '\n', > ' # High-level functions from shutil\n', > ' # These functions will be bound to the instance such that\n', > ' # Path(name).copy(target) will invoke shutil.copy(name, target)\n', > '\n', > ' copyfile = shutil.copyfile\n', > ' copymode = shutil.copymode\n', > ' copystat = shutil.copystat\n', > ' copy = shutil.copy\n', > ' copy2 = shutil.copy2\n', > ' copytree = shutil.copytree\n', > " if hasattr(shutil, 'move'):\n", > ' move = shutil.move\n', > ' rmtree = shutil.rmtree\n', > '\n', > ' def rmtree_p(self):\n', > ' """Like :meth:`rmtree`, but does not raise an exception if the\n', > ' directory does not exist."""\n', > ' with contextlib.suppress(FileNotFoundError):\n', > ' self.rmtree()\n', > ' return self\n', > '\n', > ' def chdir(self):\n', > ' """.. seealso:: :func:`os.chdir`"""\n', > ' os.chdir(self)\n', > '\n', > ' cd = chdir\n', > '\n', > ' def merge_tree(\n', > ' self,\n', > ' dst,\n', > ' symlinks=False,\n', > ' *,\n', > ' copy_function=shutil.copy2,\n', > ' ignore=lambda dir, contents: [],\n', > ' ):\n', > ' """\n', > ' Copy entire contents of self to dst, overwriting existing\n', > ' contents in dst with those in self.\n', > '\n', > ' Pass ``symlinks=True`` to copy symbolic links as links.\n', > '\n', > ' Accepts a ``copy_function``, similar to copytree.\n', > '\n', > ' To avoid overwriting newer files, supply a copy function\n', > ' wrapped in ``only_newer``. For example::\n', > '\n', > ' src.merge_tree(dst, copy_function=only_newer(shutil.copy2))\n', > ' """\n', > ' dst = self._next_class(dst)\n', > ' dst.makedirs_p()\n', > '\n', > ' sources = list(self.iterdir())\n', > ' _ignored = ignore(self, [item.name for item in sources])\n', > '\n', > ' def ignored(item):\n', > ' return item.name in _ignored\n', > '\n', > ' for source in itertools.filterfalse(ignored, sources):\n', > ' dest = dst / source.name\n', > ' if symlinks and source.islink():\n', > ' target = source.readlink()\n', > ' target.symlink(dest)\n', > ' elif source.is_dir():\n', > ' source.merge_tree(\n', > ' dest,\n', > ' symlinks=symlinks,\n', > ' copy_function=copy_function,\n', > ' ignore=ignore,\n', > ' )\n', > ' else:\n', > ' copy_function(source, dest)\n', > '\n', > ' self.copystat(dst)\n', > '\n', > ' #\n', > ' # --- Special stuff from os\n', > '\n', > " if hasattr(os, 'chroot'):\n", > '\n', > ' def chroot(self): # pragma: nocover\n', > ' """.. seealso:: :func:`os.chroot`"""\n', > ' os.chroot(self)\n', > '\n', > " if hasattr(os, 'startfile'):\n", > '\n', > ' def startfile(self, *args, **kwargs): # pragma: nocover\n', > ' """.. seealso:: :func:`os.startfile`"""\n', > ' os.startfile(self, *args, **kwargs)\n', > ' return self\n', > '\n', > ' # in-place re-writing, courtesy of Martijn Pieters\n', > ' # http://www.zopatista.com/python/2013/11/26/inplace-file-rewriting/\n', > ' @contextlib.contextmanager\n', > ' def in_place(\n', > ' self,\n', > " mode='r',\n", > ' buffering=-1,\n', > ' encoding=None,\n', > ' errors=None,\n', > ' newline=None,\n', > ' backup_extension=None,\n', > ' ):\n', > ' """\n', > ' A context in which a file may be re-written in-place with\n', > ' new content.\n', > '\n', > ' Yields a tuple of :samp:`({readable}, {writable})` file\n', > ' objects, where `writable` replaces `readable`.\n', > '\n', > ' If an exception occurs, the old file is restored, removing the\n', > ' written data.\n', > '\n', > " Mode *must not* use ``'w'``, ``'a'``, or ``'+'``; only\n", > ' read-only-modes are allowed. A :exc:`ValueError` is raised\n', > ' on invalid modes.\n', > '\n', > ' For example, to add line numbers to a file::\n', > '\n', > ' p = Path(filename)\n', > ' assert p.is_file()\n', > ' with p.in_place() as (reader, writer):\n', > ' for number, line in enumerate(reader, 1):\n', > " writer.write('{0:3}: '.format(number)))\n", > ' writer.write(line)\n', > '\n', > ' Thereafter, the file at `filename` will have line numbers in it.\n', > ' """\n', > " if set(mode).intersection('wa+'):\n", > " raise ValueError('Only read-only file modes can be used')\n", > '\n', > ' # move existing file to backup, create new file with same ' > 'permissions\n', > ' # borrowed extensively from the fileinput module\n', > " backup_fn = self + (backup_extension or os.extsep + 'bak')\n", > ' backup_fn.remove_p()\n', > ' self.rename(backup_fn)\n', > ' readable = open(\n', > ' backup_fn,\n', > ' mode,\n', > ' buffering=buffering,\n', > ' encoding=encoding,\n', > ' errors=errors,\n', > ' newline=newline,\n', > ' )\n', > '\n', > ' perm = os.stat(readable.fileno()).st_mode\n', > ' os_mode = os.O_CREAT | os.O_WRONLY | os.O_TRUNC\n', > " os_mode |= getattr(os, 'O_BINARY', 0)\n", > ' fd = os.open(self, os_mode, perm)\n', > ' writable = open(\n', > ' fd,\n', > ' "w" + mode.replace(\'r\', \'\'),\n', > ' buffering=buffering,\n', > ' encoding=encoding,\n', > ' errors=errors,\n', > ' newline=newline,\n', > ' )\n', > ' with contextlib.suppress(OSError, AttributeError):\n', > ' self.chmod(perm)\n', > '\n', > ' try:\n', > ' yield readable, writable\n', > ' except Exception:\n', > ' # move backup back\n', > ' readable.close()\n', > ' writable.close()\n', > ' self.remove_p()\n', > ' backup_fn.rename(self)\n', > ' raise\n', > ' else:\n', > ' readable.close()\n', > ' writable.close()\n', > ' finally:\n', > ' backup_fn.remove_p()\n', > '\n', > ' @classes.ClassProperty\n', > ' @classmethod\n', > ' def special(cls):\n', > ' """\n', > ' Return a SpecialResolver object suitable referencing a suitable\n', > ' directory for the relevant platform for the given\n', > ' type of content.\n', > '\n', > ' For example, to get a user config directory, invoke:\n', > '\n', > ' dir = Path.special().user.config\n', > '\n', > ' Uses the `appdirs\n', > ' <https://pypi.python.org/pypi/appdirs/1.4.0>`_ to resolve\n', > ' the paths in a platform-friendly way.\n', > '\n', > " To create a config directory for 'My App', consider:\n", > '\n', > ' dir = Path.special("My App").user.config.makedirs_p()\n', > '\n', > ' If the ``appdirs`` module is not installed, invocation\n', > ' of special will raise an ImportError.\n', > ' """\n', > ' return functools.partial(SpecialResolver, cls)\n', > '\n', > '\n', > 'class DirectoryNotEmpty(OSError):\n', > ' @staticmethod\n', > ' @contextlib.contextmanager\n', > ' def translate():\n', > ' try:\n', > ' yield\n', > ' except OSError as exc:\n', > ' if exc.errno == errno.ENOTEMPTY:\n', > ' raise DirectoryNotEmpty(*exc.args) from exc\n', > ' raise\n', > '\n', > '\n', > 'def only_newer(copy_func):\n', > ' """\n', > ' Wrap a copy function (like shutil.copy2) to return\n', > " the dst if it's newer than the source.\n", > ' """\n', > '\n', > ' @functools.wraps(copy_func)\n', > ' def wrapper(src, dst, *args, **kwargs):\n', > ' is_newer_dst = dst.exists() and dst.getmtime() >= src.getmtime()\n', > ' if is_newer_dst:\n', > ' return dst\n', > ' return copy_func(src, dst, *args, **kwargs)\n', > '\n', > ' return wrapper\n', > '\n', > '\n', > 'class ExtantPath(Path):\n', > ' """\n', > " >>> ExtantPath('.')\n", > " ExtantPath('.')\n", > " >>> ExtantPath('does-not-exist')\n", > ' Traceback (most recent call last):\n', > ' OSError: does-not-exist does not exist.\n', > ' """\n', > '\n', > ' def _validate(self):\n', > ' if not self.exists():\n', > ' raise OSError(f"{self} does not exist.")\n', > '\n', > '\n', > 'class ExtantFile(Path):\n', > ' """\n', > " >>> ExtantFile('.')\n", > ' Traceback (most recent call last):\n', > ' FileNotFoundError: . does not exist as a file.\n', > " >>> ExtantFile('does-not-exist')\n", > ' Traceback (most recent call last):\n', > ' FileNotFoundError: does-not-exist does not exist as a file.\n', > ' """\n', > '\n', > ' def _validate(self):\n', > ' if not self.is_file():\n', > ' raise FileNotFoundError(f"{self} does not exist as a file.")\n', > '\n', > '\n', > 'class SpecialResolver:\n', > ' class ResolverScope:\n', > ' def __init__(self, paths, scope):\n', > ' self.paths = paths\n', > ' self.scope = scope\n', > '\n', > ' def __getattr__(self, class_):\n', > ' return self.paths.get_dir(self.scope, class_)\n', > '\n', > ' def __init__(self, path_class, *args, **kwargs):\n', > " appdirs = importlib.import_module('appdirs')\n", > '\n', > ' vars(self).update(\n', > ' path_class=path_class, wrapper=appdirs.AppDirs(*args, ' > '**kwargs)\n', > ' )\n', > '\n', > ' def __getattr__(self, scope):\n', > ' return self.ResolverScope(self, scope)\n', > '\n', > ' def get_dir(self, scope, class_):\n', > ' """\n', > ' Return the callable function from appdirs, but with the\n', > ' result wrapped in self.path_class\n', > ' """\n', > " prop_name = f'{scope}_{class_}_dir'\n", > ' value = getattr(self.wrapper, prop_name)\n', > ' MultiPath = Multi.for_class(self.path_class)\n', > ' return MultiPath.detect(value)\n', > '\n', > '\n', > 'class Multi:\n', > ' """\n', > ' A mix-in for a Path which may contain multiple Path separated by ' > 'pathsep.\n', > ' """\n', > '\n', > ' @classmethod\n', > ' def for_class(cls, path_cls):\n', > " name = 'Multi' + path_cls.__name__\n", > ' return type(name, (cls, path_cls), {})\n', > '\n', > ' @classmethod\n', > ' def detect(cls, input):\n', > ' if os.pathsep not in input:\n', > ' cls = cls._next_class\n', > ' return cls(input)\n', > '\n', > ' def __iter__(self):\n', > ' return iter(map(self._next_class, self.split(os.pathsep)))\n', > '\n', > ' @classes.ClassProperty\n', > ' @classmethod\n', > ' def _next_class(cls):\n', > ' """\n', > ' Multi-subclasses should use the parent class\n', > ' """\n', > ' return next(class_ for class_ in cls.__mro__ if not ' > 'issubclass(class_, Multi))\n', > '\n', > '\n', > 'class TempDir(Path):\n', > ' """\n', > ' A temporary directory via :func:`tempfile.mkdtemp`, and\n', > ' constructed with the same parameters that you can use\n', > ' as a context manager.\n', > '\n', > ' For example:\n', > '\n', > ' >>> with TempDir() as d:\n', > ' ... d.is_dir() and isinstance(d, Path)\n', > ' True\n', > '\n', > ' The directory is deleted automatically.\n', > '\n', > ' >>> d.is_dir()\n', > ' False\n', > '\n', > ' .. seealso:: :func:`tempfile.mkdtemp`\n', > ' """\n', > '\n', > ' @classes.ClassProperty\n', > ' @classmethod\n', > ' def _next_class(cls):\n', > ' return Path\n', > '\n', > ' def __new__(cls, *args, **kwargs):\n', > ' dirname = tempfile.mkdtemp(*args, **kwargs)\n', > ' return super().__new__(cls, dirname)\n', > '\n', > ' def __init__(self, *args, **kwargs):\n', > ' pass\n', > '\n', > ' def __enter__(self):\n', > ' # TempDir should return a Path version of itself and not itself\n', > ' # so that a second context manager does not create a second\n', > ' # temporary directory, but rather changes CWD to the location\n', > ' # of the temporary directory.\n', > ' return self._next_class(self)\n', > '\n', > ' def __exit__(self, exc_type, exc_value, traceback):\n', > ' self.rmtree()\n', > '\n', > '\n', > 'class Handlers:\n', > ' def strict(msg):\n', > ' raise\n', > '\n', > ' def warn(msg):\n', > ' warnings.warn(msg, TreeWalkWarning, stacklevel=2)\n', > '\n', > ' def ignore(msg):\n', > ' pass\n', > '\n', > ' @classmethod\n', > ' def _resolve(cls, param):\n', > ' if not callable(param) and param not in vars(Handlers):\n', > ' raise ValueError("invalid errors parameter")\n', > ' return vars(cls).get(param, param)\n'] > test = <DocTest path from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:0 (no examples)> > tests = [<DocTest path from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:0 (no examples)>, > <DocTest path.Traversal from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:93 (4 examples)>, > <DocTest path._strip_newlines from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:129 (1 example)>, > <DocTest path.Path from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:137 (no examples)>, > <DocTest path.Path.__truediv__ from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:197 (no examples)>, > <DocTest path.Path.__rtruediv__ from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:208 (no examples)>, > <DocTest path.Path.cwd from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:227 (no examples)>, > <DocTest path.Path.absolute from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:241 (no examples)>, > <DocTest path.Path.normcase from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:245 (no examples)>, > <DocTest path.Path.normpath from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:249 (no examples)>, > <DocTest path.Path.realpath from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:253 (no examples)>, > <DocTest path.Path.expanduser from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:257 (no examples)>, > <DocTest path.Path.expandvars from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:261 (no examples)>, > <DocTest path.Path.dirname from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:265 (no examples)>, > <DocTest path.Path.basename from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:269 (no examples)>, > <DocTest path.Path.expand from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:273 (no examples)>, > <DocTest path.Path.stem from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:283 (1 example)>, > <DocTest path.Path.with_stem from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:292 (1 example)>, > <DocTest path.Path.suffix from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:301 (no examples)>, > <DocTest path.Path.with_suffix from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:306 (3 examples)>, > <DocTest path.Path.drive from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:326 (no examples)>, > <DocTest path.Path.parent from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:265 (no examples)>, > <DocTest path.Path.name from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:269 (no examples)>, > <DocTest path.Path.with_name from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:361 (1 example)>, > <DocTest path.Path.splitpath from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:369 (no examples)>, > <DocTest path.Path.splitdrive from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:377 (no examples)>, > <DocTest path.Path.splitext from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:389 (no examples)>, > <DocTest path.Path.stripext from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:404 (no examples)>, > <DocTest path.Path.splitall from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:424 (1 example)>, > <DocTest path.Path.parts from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:439 (1 example)>, > <DocTest path.Path.relpath from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:459 (no examples)>, > <DocTest path.Path.relpathto from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:466 (no examples)>, > <DocTest path.Path.iterdir from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:506 (no examples)>, > <DocTest path.Path.dirs from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:522 (no examples)>, > <DocTest path.Path.files from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:533 (no examples)>, > <DocTest path.Path.walk from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:544 (no examples)>, > <DocTest path.Path.walkdirs from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:584 (no examples)>, > <DocTest path.Path.walkfiles from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:588 (no examples)>, > <DocTest path.Path.fnmatch from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:592 (no examples)>, > <DocTest path.Path.glob from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:611 (no examples)>, > <DocTest path.Path.iglob from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:628 (no examples)>] > val = <class 'path.Path'> > valname = 'path.Path' >[1m[31m/usr/lib/python3.12/doctest.py[0m:1054: in _find > [0m[96mself[39;49;00m._find(tests, val, valname, module, source_lines,[90m[39;49;00m > globs = {'B_NEWLINE': re.compile(b'\r\n|\r|\n'), > 'B_NL_END': re.compile(b'\r\n|\r|\n$'), > 'Callable': typing.Callable, > 'DirectoryNotEmpty': <class 'path.DirectoryNotEmpty'>, > 'ExtantFile': <class 'path.ExtantFile'>, > 'ExtantPath': <class 'path.ExtantPath'>, > 'Handlers': <class 'path.Handlers'>, > 'Iterator': typing.Iterator, > 'LINESEPS': ['\r\n', '\r', '\n'], > 'Multi': <class 'path.Multi'>, > 'Number': <class 'numbers.Number'>, > 'Path': <class 'path.Path'>, > 'SpecialResolver': <class 'path.SpecialResolver'>, > 'TYPE_CHECKING': False, > 'TempDir': <class 'path.TempDir'>, > 'Traversal': <class 'path.Traversal'>, > 'TreeWalkWarning': <class 'path.TreeWalkWarning'>, > 'U_LINESEPS': ['\r\n', '\r', '\n', '\x85', '\u2028', '\u2029'], > 'U_NEWLINE': re.compile('\r\n|\r|\n|\x85|\u2028|\u2029'), > 'U_NL_END': re.compile('\r\n|\r|\n|\x85|\u2028|\u2029$'), > '__all__': ['Path', 'TempDir'], > '__builtins__': {'ArithmeticError': <class 'ArithmeticError'>, > 'AssertionError': <class 'AssertionError'>, > 'AttributeError': <class 'AttributeError'>, > 'BaseException': <class 'BaseException'>, > 'BaseExceptionGroup': <class 'BaseExceptionGroup'>, > 'BlockingIOError': <class 'BlockingIOError'>, > 'BrokenPipeError': <class 'BrokenPipeError'>, > 'BufferError': <class 'BufferError'>, > 'BytesWarning': <class 'BytesWarning'>, > 'ChildProcessError': <class 'ChildProcessError'>, > 'ConnectionAbortedError': <class 'ConnectionAbortedError'>, > 'ConnectionError': <class 'ConnectionError'>, > 'ConnectionRefusedError': <class 'ConnectionRefusedError'>, > 'ConnectionResetError': <class 'ConnectionResetError'>, > 'DeprecationWarning': <class 'DeprecationWarning'>, > 'EOFError': <class 'EOFError'>, > 'Ellipsis': Ellipsis, > 'EncodingWarning': <class 'EncodingWarning'>, > 'EnvironmentError': <class 'OSError'>, > 'Exception': <class 'Exception'>, > 'ExceptionGroup': <class 'ExceptionGroup'>, > 'False': False, > 'FileExistsError': <class 'FileExistsError'>, > 'FileNotFoundError': <class 'FileNotFoundError'>, > 'FloatingPointError': <class 'FloatingPointError'>, > 'FutureWarning': <class 'FutureWarning'>, > 'GeneratorExit': <class 'GeneratorExit'>, > 'IOError': <class 'OSError'>, > 'ImportError': <class 'ImportError'>, > 'ImportWarning': <class 'ImportWarning'>, > 'IndentationError': <class 'IndentationError'>, > 'IndexError': <class 'IndexError'>, > 'InterruptedError': <class 'InterruptedError'>, > 'IsADirectoryError': <class 'IsADirectoryError'>, > 'KeyError': <class 'KeyError'>, > 'KeyboardInterrupt': <class 'KeyboardInterrupt'>, > 'LookupError': <class 'LookupError'>, > 'MemoryError': <class 'MemoryError'>, > 'ModuleNotFoundError': <class 'ModuleNotFoundError'>, > 'NameError': <class 'NameError'>, > 'None': None, > 'NotADirectoryError': <class 'NotADirectoryError'>, > 'NotImplemented': NotImplemented, > 'NotImplementedError': <class 'NotImplementedError'>, > 'OSError': <class 'OSError'>, > 'OverflowError': <class 'OverflowError'>, > 'PendingDeprecationWarning': <class 'PendingDeprecationWarning'>, > 'PermissionError': <class 'PermissionError'>, > 'ProcessLookupError': <class 'ProcessLookupError'>, > 'RecursionError': <class 'RecursionError'>, > 'ReferenceError': <class 'ReferenceError'>, > 'ResourceWarning': <class 'ResourceWarning'>, > 'RuntimeError': <class 'RuntimeError'>, > 'RuntimeWarning': <class 'RuntimeWarning'>, > 'StopAsyncIteration': <class 'StopAsyncIteration'>, > 'StopIteration': <class 'StopIteration'>, > 'SyntaxError': <class 'SyntaxError'>, > 'SyntaxWarning': <class 'SyntaxWarning'>, > 'SystemError': <class 'SystemError'>, > 'SystemExit': <class 'SystemExit'>, > 'TabError': <class 'TabError'>, > 'TimeoutError': <class 'TimeoutError'>, > 'True': True, > 'TypeError': <class 'TypeError'>, > 'UnboundLocalError': <class 'UnboundLocalError'>, > 'UnicodeDecodeError': <class 'UnicodeDecodeError'>, > 'UnicodeEncodeError': <class 'UnicodeEncodeError'>, > 'UnicodeError': <class 'UnicodeError'>, > 'UnicodeTranslateError': <class 'UnicodeTranslateError'>, > 'UnicodeWarning': <class 'UnicodeWarning'>, > 'UserWarning': <class 'UserWarning'>, > 'ValueError': <class 'ValueError'>, > 'Warning': <class 'Warning'>, > 'ZeroDivisionError': <class 'ZeroDivisionError'>, > '__build_class__': <built-in function __build_class__>, > '__debug__': True, > '__doc__': 'Built-in functions, types, exceptions, and other ' > 'objects.\n' > '\n' > 'This module provides direct access to all ' > "'built-in'\n" > 'identifiers of Python; for example, builtins.len ' > 'is\n' > 'the full name for the built-in function len().\n' > '\n' > 'This module is not normally accessed explicitly ' > 'by most\n' > 'applications, but can be useful in modules that ' > 'provide\n' > 'objects with the same name as a built-in value, ' > 'but in\n' > 'which the built-in of that name is also needed.', > '__import__': <built-in function __import__>, > '__loader__': <class '_frozen_importlib.BuiltinImporter'>, > '__name__': 'builtins', > '__package__': '', > '__spec__': ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>, origin='built-in'), > 'abs': <built-in function abs>, > 'aiter': <built-in function aiter>, > 'all': <built-in function all>, > 'anext': <built-in function anext>, > 'any': <built-in function any>, > 'ascii': <built-in function ascii>, > 'bin': <built-in function bin>, > 'bool': <class 'bool'>, > 'breakpoint': <built-in function breakpoint>, > 'bytearray': <class 'bytearray'>, > 'bytes': <class 'bytes'>, > 'callable': <built-in function callable>, > 'chr': <built-in function chr>, > 'classmethod': <class 'classmethod'>, > 'compile': <built-in function compile>, > 'complex': <class 'complex'>, > 'copyright': Copyright (c) 2001-2023 Python Software Foundation. >All Rights Reserved. > >Copyright (c) 2000 BeOpen.com. >All Rights Reserved. > >Copyright (c) 1995-2001 Corporation for National Research Initiatives. >All Rights Reserved. > >Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam. >All Rights Reserved., > 'credits': Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands > for supporting Python development. See www.python.org for more information., > 'delattr': <built-in function delattr>, > 'dict': <class 'dict'>, > 'dir': <built-in function dir>, > 'divmod': <built-in function divmod>, > 'enumerate': <class 'enumerate'>, > 'eval': <built-in function eval>, > 'exec': <built-in function exec>, > 'exit': Use exit() or Ctrl-D (i.e. EOF) to exit, > 'filter': <class 'filter'>, > 'float': <class 'float'>, > 'format': <built-in function format>, > 'frozenset': <class 'frozenset'>, > 'getattr': <built-in function getattr>, > 'globals': <built-in function globals>, > 'hasattr': <built-in function hasattr>, > 'hash': <built-in function hash>, > 'help': Type help() for interactive help, or help(object) for help about object., > 'hex': <built-in function hex>, > 'id': <built-in function id>, > 'input': <built-in function input>, > 'int': <class 'int'>, > 'isinstance': <built-in function isinstance>, > 'issubclass': <built-in function issubclass>, > 'iter': <built-in function iter>, > 'len': <built-in function len>, > 'license': Type license() to see the full license text, > 'list': <class 'list'>, > 'locals': <built-in function locals>, > 'map': <class 'map'>, > 'max': <built-in function max>, > 'memoryview': <class 'memoryview'>, > 'min': <built-in function min>, > 'next': <built-in function next>, > 'object': <class 'object'>, > 'oct': <built-in function oct>, > 'open': <built-in function open>, > 'ord': <built-in function ord>, > 'pow': <built-in function pow>, > 'print': <built-in function print>, > 'property': <class 'property'>, > 'quit': Use quit() or Ctrl-D (i.e. EOF) to exit, > 'range': <class 'range'>, > 'repr': <built-in function repr>, > 'reversed': <class 'reversed'>, > 'round': <built-in function round>, > 'set': <class 'set'>, > 'setattr': <built-in function setattr>, > 'slice': <class 'slice'>, > 'sorted': <built-in function sorted>, > 'staticmethod': <class 'staticmethod'>, > 'str': <class 'str'>, > 'sum': <built-in function sum>, > 'super': <class 'super'>, > 'tuple': <class 'tuple'>, > 'type': <class 'type'>, > 'vars': <built-in function vars>, > 'zip': <class 'zip'>}, > '__cached__': '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__pycache__/__init__.cpython-312.pyc', > '__doc__': '\n' > 'Path Pie\n' > '\n' > 'Implements ``path.Path`` - An object representing a\n' > 'path to a file or directory.\n' > '\n' > 'Example::\n' > '\n' > ' from path import Path\n' > " d = Path('/home/guido/bin')\n" > '\n' > ' # Globbing\n' > " for f in d.files('*.py'):\n" > ' f.chmod(0o755)\n' > '\n' > ' # Changing the working directory:\n' > ' with Path("somewhere"):\n' > ' # cwd in now `somewhere`\n' > ' ...\n' > '\n' > ' # Concatenate paths with /\n' > ' foo_txt = Path("bar") / "foo.txt"\n', > '__file__': '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py', > '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f01aa694230>, > '__name__': 'path', > '__package__': 'path', > '__path__': ['/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path'], > '__pytest_asyncio_package_scoped_event_loop': <function pytest_collectstart.<locals>.scoped_event_loop at 0x7f01aa84dc60>, > '__pytest_asyncio_scoped_event_loop': <function pytest_collectstart.<locals>.scoped_event_loop at 0x7f01aa84e200>, > '__spec__': ModuleSpec(name='path', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7f01aa694230>, origin='/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py', submodule_search_locations=['/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path']), > '_default_linesep': <object object at 0x7f01aad185e0>, > '_make_timestamp_ns': <function _make_timestamp_ns at 0x7f01aa845ee0>, > '_strip_newlines': <function _strip_newlines at 0x7f01b0b88220>, > 'annotations': _Feature((3, 7, 0, 'beta', 1), None, 16777216), > 'builtins': <module 'builtins' (built-in)>, > 'classes': <module 'path.classes' from '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/classes.py'>, > 'compat': <module 'path.compat' (namespace) from ['/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/compat']>, > 'contextlib': <module 'contextlib' from '/usr/lib/python3.12/contextlib.py'>, > 'datetime': <module 'datetime' from '/usr/lib/python3.12/datetime.py'>, > 'errno': <module 'errno' (built-in)>, > 'fnmatch': <module 'fnmatch' from '/usr/lib/python3.12/fnmatch.py'>, > 'functools': <module 'functools' from '/usr/lib/python3.12/functools.py'>, > 'glob': <module 'glob' from '/usr/lib/python3.12/glob.py'>, > 'grp': <module 'grp' from '/usr/lib/python3.12/lib-dynload/grp.cpython-312-x86_64-linux-gnu.so'>, > 'hashlib': <module 'hashlib' from '/usr/lib/python3.12/hashlib.py'>, > 'importlib': <module 'importlib' from '/usr/lib/python3.12/importlib/__init__.py'>, > 'itertools': <module 'itertools' (built-in)>, > 'masks': <module 'path.masks' from '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/masks.py'>, > 'matchers': <module 'path.matchers' from '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/matchers.py'>, > 'only_newer': <function only_newer at 0x7f01aa84f9c0>, > 'os': <module 'os' (frozen)>, > 'overload': <function overload at 0x7f01b06491c0>, > 'pathlib': <module 'pathlib' from '/usr/lib/python3.12/pathlib.py'>, > 'pwd': <module 'pwd' (built-in)>, > 're': <module 're' from '/usr/lib/python3.12/re/__init__.py'>, > 'removeprefix': <function removeprefix at 0x7f01aa84f880>, > 'removesuffix': <function removesuffix at 0x7f01aa84f420>, > 'shutil': <module 'shutil' from '/usr/lib/python3.12/shutil.py'>, > 'sys': <module 'sys' (built-in)>, > 'tempfile': <module 'tempfile' from '/usr/lib/python3.12/tempfile.py'>, > 'warnings': <module 'warnings' from '/usr/lib/python3.12/warnings.py'>} > module = <module 'path' from '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py'> > name = 'path.Path' > obj = <class 'path.Path'> > seen = {93856939061456: 1, > 93856939078192: 1, > 93856939150480: 1, > 139645130706752: 1, > 139645130712032: 1, > 139645130713552: 1, > 139645130714352: 1, > 139645130715952: 1, > 139645130717232: 1, > 139645130801216: 1, > 139645130801376: 1, > 139645130801536: 1, > 139645130801696: 1, > 139645130801856: 1, > 139645130802016: 1, > 139645130802176: 1, > 139645130802336: 1, > 139645130802496: 1, > 139645130802656: 1, > 139645130802816: 1, > 139645130802976: 1, > 139645130803136: 1, > 139645130803296: 1, > 139645130803616: 1, > 139645130803936: 1, > 139645130804256: 1, > 139645130804416: 1, > 139645130804576: 1, > 139645130804736: 1, > 139645130804896: 1, > 139645130805216: 1, > 139645130805376: 1, > 139645130805536: 1, > 139645130805696: 1, > 139645130805856: 1, > 139645130806016: 1, > 139645130806176: 1, > 139645130806336: 1, > 139645130806496: 1, > 139645130806656: 1, > 139645130806816: 1, > 139645130806976: 1, > 139645130807136: 1, > 139645130807296: 1, > 139645130807456: 1, > 139645130807616: 1, > 139645131613008: 1, > 139645132496608: 1, > 139645132531456: 1, > 139645132536096: 1, > 139645132536416: 1, > 139645132536576: 1, > 139645132537216: 1, > 139645132537376: 1, > 139645132537536: 1, > 139645132537696: 1, > 139645236576800: 1} > self = <_pytest.doctest.DoctestModule.collect.<locals>.MockAwareDocTestFinder object at 0x7f01aa91be60> > source_lines = ['"""\n', > 'Path Pie\n', > '\n', > 'Implements ``path.Path`` - An object representing a\n', > 'path to a file or directory.\n', > '\n', > 'Example::\n', > '\n', > ' from path import Path\n', > " d = Path('/home/guido/bin')\n", > '\n', > ' # Globbing\n', > " for f in d.files('*.py'):\n", > ' f.chmod(0o755)\n', > '\n', > ' # Changing the working directory:\n', > ' with Path("somewhere"):\n', > ' # cwd in now `somewhere`\n', > ' ...\n', > '\n', > ' # Concatenate paths with /\n', > ' foo_txt = Path("bar") / "foo.txt"\n', > '"""\n', > '\n', > 'from __future__ import annotations\n', > '\n', > 'import builtins\n', > 'import contextlib\n', > 'import datetime\n', > 'import errno\n', > 'import fnmatch\n', > 'import functools\n', > 'import glob\n', > 'import hashlib\n', > 'import importlib\n', > 'import itertools\n', > 'import os\n', > 'import pathlib\n', > 'import re\n', > 'import shutil\n', > 'import sys\n', > 'import tempfile\n', > 'import warnings\n', > 'from numbers import Number\n', > '\n', > 'with contextlib.suppress(ImportError):\n', > ' import win32security\n', > '\n', > 'with contextlib.suppress(ImportError):\n', > ' import pwd\n', > '\n', > 'with contextlib.suppress(ImportError):\n', > ' import grp\n', > '\n', > 'from typing import (\n', > ' TYPE_CHECKING,\n', > ' Callable,\n', > ' Iterator,\n', > ' overload,\n', > ')\n', > '\n', > 'if TYPE_CHECKING:\n', > ' from _typeshed import (\n', > ' OpenBinaryMode,\n', > ' OpenTextMode,\n', > ' )\n', > '\n', > 'from . import classes, masks, matchers\n', > 'from .compat.py38 import removeprefix, removesuffix\n', > '\n', > "__all__ = ['Path', 'TempDir']\n", > '\n', > '\n', > "LINESEPS = ['\\r\\n', '\\r', '\\n']\n", > "U_LINESEPS = LINESEPS + ['\\u0085', '\\u2028', '\\u2029']\n", > "B_NEWLINE = re.compile('|'.join(LINESEPS).encode())\n", > "U_NEWLINE = re.compile('|'.join(U_LINESEPS))\n", > "B_NL_END = re.compile(B_NEWLINE.pattern + b'$')\n", > "U_NL_END = re.compile(U_NEWLINE.pattern + '$')\n", > '\n', > '_default_linesep = object()\n', > '\n', > '\n', > 'def _make_timestamp_ns(value: Number | datetime.datetime) -> Number:\n', > ' timestamp_s = value if isinstance(value, Number) else ' > 'value.timestamp()\n', > ' return int(timestamp_s * 10**9)\n', > '\n', > '\n', > 'class TreeWalkWarning(Warning):\n', > ' pass\n', > '\n', > '\n', > 'class Traversal:\n', > ' """\n', > ' Wrap a walk result to customize the traversal.\n', > '\n', > ' `follow` is a function that takes an item and returns\n', > ' True if that item should be followed and False otherwise.\n', > '\n', > ' For example, to avoid traversing into directories that\n', > ' begin with `.`:\n', > '\n', > " >>> traverse = Traversal(lambda dir: not dir.startswith('.'))\n", > " >>> items = list(traverse(Path('.').walk()))\n", > '\n', > ' Directories beginning with `.` will appear in the results, but\n', > ' their children will not.\n', > '\n', > ' >>> dot_dir = next(item for item in items if item.is_dir() and ' > "item.startswith('.'))\n", > ' >>> any(item.parent == dot_dir for item in items)\n', > ' False\n', > ' """\n', > '\n', > ' def __init__(self, follow):\n', > ' self.follow = follow\n', > '\n', > ' def __call__(self, walker):\n', > ' traverse = None\n', > ' while True:\n', > ' try:\n', > ' item = walker.send(traverse)\n', > ' except StopIteration:\n', > ' return\n', > ' yield item\n', > '\n', > ' traverse = functools.partial(self.follow, item)\n', > '\n', > '\n', > 'def _strip_newlines(lines):\n', > ' r"""\n', > " >>> list(_strip_newlines(['Hello World\\r\\n', 'foo']))\n", > " ['Hello World', 'foo']\n", > ' """\n', > " return (U_NL_END.sub('', line) for line in lines)\n", > '\n', > '\n', > 'class Path(str):\n', > ' """\n', > ' Represents a filesystem path.\n', > '\n', > ' For documentation on individual methods, consult their\n', > ' counterparts in :mod:`os.path`.\n', > '\n', > ' Some methods are additionally included from :mod:`shutil`.\n', > ' The functions are linked directly into the class namespace\n', > ' such that they will be bound to the Path instance. For example,\n', > ' ``Path(src).copy(target)`` is equivalent to\n', > ' ``shutil.copy(src, target)``. Therefore, when referencing\n', > ' the docs for these methods, assume `src` references `self`,\n', > ' the Path instance.\n', > ' """\n', > '\n', > ' module = os.path\n', > ' """ The path module to use for path operations.\n', > '\n', > ' .. seealso:: :mod:`os.path`\n', > ' """\n', > '\n', > " def __new__(cls, other='.'):\n", > ' return super().__new__(cls, other)\n', > '\n', > " def __init__(self, other='.'):\n", > ' if other is None:\n', > ' raise TypeError("Invalid initial value for path: None")\n', > ' with contextlib.suppress(AttributeError):\n', > ' self._validate()\n', > '\n', > ' @classmethod\n', > ' @functools.lru_cache\n', > ' def using_module(cls, module):\n', > " subclass_name = cls.__name__ + '_' + module.__name__\n", > ' bases = (cls,)\n', > " ns = {'module': module}\n", > ' return type(subclass_name, bases, ns)\n', > '\n', > ' @classes.ClassProperty\n', > ' @classmethod\n', > ' def _next_class(cls):\n', > ' """\n', > ' What class should be used to construct new instances from this ' > 'class\n', > ' """\n', > ' return cls\n', > '\n', > ' # --- Special Python methods.\n', > '\n', > ' def __repr__(self):\n', > " return f'{type(self).__name__}({super().__repr__()})'\n", > '\n', > ' # Adding a Path and a string yields a Path.\n', > ' def __add__(self, more):\n', > ' return self._next_class(super().__add__(more))\n', > '\n', > ' def __radd__(self, other):\n', > ' return self._next_class(other.__add__(self))\n', > '\n', > ' # The / operator joins Paths.\n', > ' def __truediv__(self, rel):\n', > ' """fp.__truediv__(rel) == fp / rel == fp.joinpath(rel)\n', > '\n', > ' Join two path components, adding a separator character if\n', > ' needed.\n', > '\n', > ' .. seealso:: :func:`os.path.join`\n', > ' """\n', > ' return self._next_class(self.module.join(self, rel))\n', > '\n', > ' # The / operator joins Paths the other way around\n', > ' def __rtruediv__(self, rel):\n', > ' """fp.__rtruediv__(rel) == rel / fp\n', > '\n', > ' Join two path components, adding a separator character if\n', > ' needed.\n', > '\n', > ' .. seealso:: :func:`os.path.join`\n', > ' """\n', > ' return self._next_class(self.module.join(rel, self))\n', > '\n', > ' def __enter__(self):\n', > ' self._old_dir = self.cwd()\n', > ' os.chdir(self)\n', > ' return self\n', > '\n', > ' def __exit__(self, *_):\n', > ' os.chdir(self._old_dir)\n', > '\n', > ' @classmethod\n', > ' def cwd(cls):\n', > ' """Return the current working directory as a path object.\n', > '\n', > ' .. seealso:: :func:`os.getcwd`\n', > ' """\n', > ' return cls(os.getcwd())\n', > '\n', > ' @classmethod\n', > ' def home(cls) -> Path:\n', > " return cls(os.path.expanduser('~'))\n", > '\n', > ' #\n', > ' # --- Operations on Path strings.\n', > '\n', > ' def absolute(self):\n', > ' """.. seealso:: :func:`os.path.abspath`"""\n', > ' return self._next_class(self.module.abspath(self))\n', > '\n', > ' def normcase(self):\n', > ' """.. seealso:: :func:`os.path.normcase`"""\n', > ' return self._next_class(self.module.normcase(self))\n', > '\n', > ' def normpath(self):\n', > ' """.. seealso:: :func:`os.path.normpath`"""\n', > ' return self._next_class(self.module.normpath(self))\n', > '\n', > ' def realpath(self):\n', > ' """.. seealso:: :func:`os.path.realpath`"""\n', > ' return self._next_class(self.module.realpath(self))\n', > '\n', > ' def expanduser(self):\n', > ' """.. seealso:: :func:`os.path.expanduser`"""\n', > ' return self._next_class(self.module.expanduser(self))\n', > '\n', > ' def expandvars(self):\n', > ' """.. seealso:: :func:`os.path.expandvars`"""\n', > ' return self._next_class(self.module.expandvars(self))\n', > '\n', > ' def dirname(self):\n', > ' """.. seealso:: :attr:`parent`, :func:`os.path.dirname`"""\n', > ' return self._next_class(self.module.dirname(self))\n', > '\n', > ' def basename(self):\n', > ' """.. seealso:: :attr:`name`, :func:`os.path.basename`"""\n', > ' return self._next_class(self.module.basename(self))\n', > '\n', > ' def expand(self):\n', > ' """Clean up a filename by calling :meth:`expandvars()`,\n', > ' :meth:`expanduser()`, and :meth:`normpath()` on it.\n', > '\n', > ' This is commonly everything needed to clean up a filename\n', > ' read from a configuration file, for example.\n', > ' """\n', > ' return self.expandvars().expanduser().normpath()\n', > '\n', > ' @property\n', > ' def stem(self):\n', > ' """The same as :meth:`name`, but with one file extension stripped ' > 'off.\n', > '\n', > " >>> Path('/home/guido/python.tar.gz').stem\n", > " 'python.tar'\n", > ' """\n', > ' base, ext = self.module.splitext(self.name)\n', > ' return base\n', > '\n', > ' def with_stem(self, stem):\n', > ' """Return a new path with the stem changed.\n', > '\n', > ' >>> Path(\'/home/guido/python.tar.gz\').with_stem("foo")\n', > " Path('/home/guido/foo.gz')\n", > ' """\n', > ' return self.with_name(stem + self.suffix)\n', > '\n', > ' @property\n', > ' def suffix(self):\n', > ' """The file extension, for example ``\'.py\'``."""\n', > ' f, suffix = self.module.splitext(self)\n', > ' return suffix\n', > '\n', > ' def with_suffix(self, suffix):\n', > ' """Return a new path with the file suffix changed (or added, if ' > 'none)\n', > '\n', > ' >>> Path(\'/home/guido/python.tar.gz\').with_suffix(".foo")\n', > " Path('/home/guido/python.tar.foo')\n", > '\n', > " >>> Path('python').with_suffix('.zip')\n", > " Path('python.zip')\n", > '\n', > " >>> Path('filename.ext').with_suffix('zip')\n", > ' Traceback (most recent call last):\n', > ' ...\n', > " ValueError: Invalid suffix 'zip'\n", > ' """\n', > " if not suffix.startswith('.'):\n", > ' raise ValueError(f"Invalid suffix {suffix!r}")\n', > '\n', > ' return self.stripext() + suffix\n', > '\n', > ' @property\n', > ' def drive(self):\n', > ' """The drive specifier, for example ``\'C:\'``.\n', > '\n', > " This is always empty on systems that don't use drive specifiers.\n", > ' """\n', > ' drive, r = self.module.splitdrive(self)\n', > ' return self._next_class(drive)\n', > '\n', > ' parent = property(\n', > ' dirname,\n', > ' None,\n', > ' None,\n', > ' """ This path\'s parent directory, as a new Path object.\n', > '\n', > ' For example,\n', > " ``Path('/usr/local/lib/libpython.so').parent ==\n", > " Path('/usr/local/lib')``\n", > '\n', > ' .. seealso:: :meth:`dirname`, :func:`os.path.dirname`\n', > ' """,\n', > ' )\n', > '\n', > ' name = property(\n', > ' basename,\n', > ' None,\n', > ' None,\n', > ' """ The name of this file or directory without the full path.\n', > '\n', > ' For example,\n', > " ``Path('/usr/local/lib/libpython.so').name == 'libpython.so'``\n", > '\n', > ' .. seealso:: :meth:`basename`, :func:`os.path.basename`\n', > ' """,\n', > ' )\n', > '\n', > ' def with_name(self, name):\n', > ' """Return a new path with the name changed.\n', > '\n', > ' >>> Path(\'/home/guido/python.tar.gz\').with_name("foo.zip")\n', > " Path('/home/guido/foo.zip')\n", > ' """\n', > ' return self._next_class(removesuffix(self, self.name) + name)\n', > '\n', > ' def splitpath(self):\n', > ' """Return two-tuple of ``.parent``, ``.name``.\n', > '\n', > ' .. seealso:: :attr:`parent`, :attr:`name`, :func:`os.path.split`\n', > ' """\n', > ' parent, child = self.module.split(self)\n', > ' return self._next_class(parent), child\n', > '\n', > ' def splitdrive(self):\n', > ' """Return two-tuple of ``.drive`` and rest without drive.\n', > '\n', > ' Split the drive specifier from this path. If there is\n', > ' no drive specifier, :samp:`{p.drive}` is empty, so the return ' > 'value\n', > " is simply ``(Path(''), p)``. This is always the case on Unix.\n", > '\n', > ' .. seealso:: :func:`os.path.splitdrive`\n', > ' """\n', > ' drive, rel = self.module.splitdrive(self)\n', > ' return self._next_class(drive), self._next_class(rel)\n', > '\n', > ' def splitext(self):\n', > ' """Return two-tuple of ``.stripext()`` and ``.ext``.\n', > '\n', > ' Split the filename extension from this path and return\n', > ' the two parts. Either part may be empty.\n', > '\n', > " The extension is everything from ``'.'`` to the end of the\n", > ' last path segment. This has the property that if\n', > ' ``(a, b) == p.splitext()``, then ``a + b == p``.\n', > '\n', > ' .. seealso:: :func:`os.path.splitext`\n', > ' """\n', > ' filename, ext = self.module.splitext(self)\n', > ' return self._next_class(filename), ext\n', > '\n', > ' def stripext(self):\n', > ' """Remove one file extension from the path.\n', > '\n', > " For example, ``Path('/home/guido/python.tar.gz').stripext()``\n", > " returns ``Path('/home/guido/python.tar')``.\n", > ' """\n', > ' return self.splitext()[0]\n', > '\n', > ' @classes.multimethod\n', > ' def joinpath(cls, first, *others):\n', > ' """\n', > ' Join first to zero or more :class:`Path` components,\n', > ' adding a separator character (:samp:`{first}.module.sep`)\n', > ' if needed. Returns a new instance of\n', > ' :samp:`{first}._next_class`.\n', > '\n', > ' .. seealso:: :func:`os.path.join`\n', > ' """\n', > ' return cls._next_class(cls.module.join(first, *others))\n', > '\n', > ' def splitall(self):\n', > ' r"""Return a list of the path components in this path.\n', > '\n', > ' The first item in the list will be a Path. Its value will be\n', > ' either :data:`os.curdir`, :data:`os.pardir`, empty, or the root\n', > " directory of this path (for example, ``'/'`` or ``'C:\\\\'``). " > 'The\n', > ' other items in the list will be strings.\n', > '\n', > ' ``Path.joinpath(*result)`` will yield the original path.\n', > '\n', > " >>> Path('/foo/bar/baz').splitall()\n", > " [Path('/'), 'foo', 'bar', 'baz']\n", > ' """\n', > ' return list(self._parts())\n', > '\n', > ' def parts(self):\n', > ' """\n', > " >>> Path('/foo/bar/baz').parts()\n", > " (Path('/'), 'foo', 'bar', 'baz')\n", > ' """\n', > ' return tuple(self._parts())\n', > '\n', > ' def _parts(self):\n', > ' return reversed(tuple(self._parts_iter()))\n', > '\n', > ' def _parts_iter(self):\n', > ' loc = self\n', > ' while loc != os.curdir and loc != os.pardir:\n', > ' prev = loc\n', > ' loc, child = prev.splitpath()\n', > ' if loc == prev:\n', > ' break\n', > ' yield child\n', > ' yield loc\n', > '\n', > " def relpath(self, start='.'):\n", > ' """Return this path as a relative path,\n', > ' based from `start`, which defaults to the current working ' > 'directory.\n', > ' """\n', > ' cwd = self._next_class(start)\n', > ' return cwd.relpathto(self)\n', > '\n', > ' def relpathto(self, dest):\n', > ' """Return a relative path from `self` to `dest`.\n', > '\n', > ' If there is no relative path from `self` to `dest`, for example if\n', > ' they reside on different drives in Windows, then this returns\n', > ' ``dest.absolute()``.\n', > ' """\n', > ' origin = self.absolute()\n', > ' dest = self._next_class(dest).absolute()\n', > '\n', > ' orig_list = origin.normcase().splitall()\n', > " # Don't normcase dest! We want to preserve the case.\n", > ' dest_list = dest.splitall()\n', > '\n', > ' if orig_list[0] != self.module.normcase(dest_list[0]):\n', > " # Can't get here from there.\n", > ' return dest\n', > '\n', > ' # Find the location where the two paths start to differ.\n', > ' i = 0\n', > ' for start_seg, dest_seg in zip(orig_list, dest_list):\n', > ' if start_seg != self.module.normcase(dest_seg):\n', > ' break\n', > ' i += 1\n', > '\n', > ' # Now i is the point where the two paths diverge.\n', > ' # Need a certain number of "os.pardir"s to work up\n', > ' # from the origin to the point of divergence.\n', > ' segments = [os.pardir] * (len(orig_list) - i)\n', > ' # Need to add the diverging part of dest_list.\n', > ' segments += dest_list[i:]\n', > ' if len(segments) == 0:\n', > ' # If they happen to be identical, use os.curdir.\n', > ' relpath = os.curdir\n', > ' else:\n', > ' relpath = self.module.join(*segments)\n', > ' return self._next_class(relpath)\n', > '\n', > ' # --- Listing, searching, walking, and matching\n', > '\n', > ' def iterdir(self, match=None):\n', > ' """Yields items in this directory.\n', > '\n', > ' Use :meth:`files` or :meth:`dirs` instead if you want a listing\n', > ' of just files or just subdirectories.\n', > '\n', > ' The elements of the list are Path objects.\n', > '\n', > ' With the optional `match` argument, a callable,\n', > ' only return items whose names match the given pattern.\n', > '\n', > ' .. seealso:: :meth:`files`, :meth:`dirs`\n', > ' """\n', > ' match = matchers.load(match)\n', > ' return filter(match, (self / child for child in os.listdir(self)))\n', > '\n', > ' def dirs(self, *args, **kwargs):\n', > ' """List of this directory\'s subdirectories.\n', > '\n', > ' The elements of the list are Path objects.\n', > ' This does not walk recursively into subdirectories\n', > ' (but see :meth:`walkdirs`).\n', > '\n', > ' Accepts parameters to :meth:`iterdir`.\n', > ' """\n', > ' return [p for p in self.iterdir(*args, **kwargs) if p.is_dir()]\n', > '\n', > ' def files(self, *args, **kwargs):\n', > ' """List of the files in self.\n', > '\n', > ' The elements of the list are Path objects.\n', > ' This does not walk into subdirectories (see :meth:`walkfiles`).\n', > '\n', > ' Accepts parameters to :meth:`iterdir`.\n', > ' """\n', > '\n', > ' return [p for p in self.iterdir(*args, **kwargs) if p.is_file()]\n', > '\n', > " def walk(self, match=None, errors='strict'):\n", > ' """Iterator over files and subdirs, recursively.\n', > '\n', > ' The iterator yields Path objects naming each child item of\n', > ' this directory and its descendants. This requires that\n', > ' ``D.is_dir()``.\n', > '\n', > ' This performs a depth-first traversal of the directory tree.\n', > ' Each directory is returned just before all its children.\n', > '\n', > ' The `errors=` keyword argument controls behavior when an\n', > " error occurs. The default is ``'strict'``, which causes an\n", > " exception. Other allowed values are ``'warn'`` (which\n", > " reports the error via :func:`warnings.warn()`), and ``'ignore'``.\n", > ' `errors` may also be an arbitrary callable taking a msg parameter.\n', > ' """\n', > '\n', > ' errors = Handlers._resolve(errors)\n', > ' match = matchers.load(match)\n', > '\n', > ' try:\n', > ' childList = self.iterdir()\n', > ' except Exception as exc:\n', > ' errors(f"Unable to list directory \'{self}\': {exc}")\n', > ' return\n', > '\n', > ' for child in childList:\n', > ' traverse = None\n', > ' if match(child):\n', > ' traverse = yield child\n', > ' traverse = traverse or child.is_dir\n', > ' try:\n', > ' do_traverse = traverse()\n', > ' except Exception as exc:\n', > ' errors(f"Unable to access \'{child}\': {exc}")\n', > ' continue\n', > '\n', > ' if do_traverse:\n', > ' yield from child.walk(errors=errors, match=match)\n', > '\n', > ' def walkdirs(self, *args, **kwargs):\n', > ' """Iterator over subdirs, recursively."""\n', > ' return (item for item in self.walk(*args, **kwargs) if ' > 'item.is_dir())\n', > '\n', > ' def walkfiles(self, *args, **kwargs):\n', > ' """Iterator over files, recursively."""\n', > ' return (item for item in self.walk(*args, **kwargs) if ' > 'item.is_file())\n', > '\n', > ' def fnmatch(self, pattern, normcase=None):\n', > ' """Return ``True`` if `self.name` matches the given `pattern`.\n', > '\n', > ' `pattern` - A filename pattern with wildcards,\n', > " for example ``'*.py'``. If the pattern contains a `normcase`\n", > ' attribute, it is applied to the name and path prior to ' > 'comparison.\n', > '\n', > ' `normcase` - (optional) A function used to normalize the pattern ' > 'and\n', > ' filename before matching. Defaults to normcase from\n', > ' ``self.module``, :func:`os.path.normcase`.\n', > '\n', > ' .. seealso:: :func:`fnmatch.fnmatch`\n', > ' """\n', > " default_normcase = getattr(pattern, 'normcase', " > 'self.module.normcase)\n', > ' normcase = normcase or default_normcase\n', > ' name = normcase(self.name)\n', > ' pattern = normcase(pattern)\n', > ' return fnmatch.fnmatchcase(name, pattern)\n', > '\n', > ' def glob(self, pattern):\n', > ' """Return a list of Path objects that match the pattern.\n', > '\n', > ' `pattern` - a path relative to this directory, with wildcards.\n', > '\n', > " For example, ``Path('/users').glob('*/bin/*')`` returns a list\n", > ' of all the files users have in their :file:`bin` directories.\n', > '\n', > ' .. seealso:: :func:`glob.glob`\n', > '\n', > ' .. note:: Glob is **not** recursive, even when using ``**``.\n', > ' To do recursive globbing see :func:`walk`,\n', > ' :func:`walkdirs` or :func:`walkfiles`.\n', > ' """\n', > ' cls = self._next_class\n', > ' return [cls(s) for s in glob.glob(self / pattern)]\n', > '\n', > ' def iglob(self, pattern):\n', > ' """Return an iterator of Path objects that match the pattern.\n', > '\n', > ' `pattern` - a path relative to this directory, with wildcards.\n', > '\n', > " For example, ``Path('/users').iglob('*/bin/*')`` returns an\n", > ' iterator of all the files users have in their :file:`bin`\n', > ' directories.\n', > '\n', > ' .. seealso:: :func:`glob.iglob`\n', > '\n', > ' .. note:: Glob is **not** recursive, even when using ``**``.\n', > ' To do recursive globbing see :func:`walk`,\n', > ' :func:`walkdirs` or :func:`walkfiles`.\n', > ' """\n', > ' cls = self._next_class\n', > ' return (cls(s) for s in glob.iglob(self / pattern))\n', > '\n', > ' #\n', > ' # --- Reading or writing an entire file at once.\n', > '\n', > ' @functools.wraps(open, assigned=())\n', > ' def open(self, *args, **kwargs):\n', > ' """Open this file and return a corresponding file object.\n', > '\n', > ' Keyword arguments work as in :func:`io.open`. If the file cannot ' > 'be\n', > ' opened, an :class:`OSError` is raised.\n', > ' """\n', > ' return open(self, *args, **kwargs)\n', > '\n', > ' def bytes(self):\n', > ' """Open this file, read all bytes, return them as a string."""\n', > " with self.open('rb') as f:\n", > ' return f.read()\n', > '\n', > ' @overload\n', > ' def chunks(\n', > ' self,\n', > ' size: int,\n', > ' mode: OpenTextMode = ...,\n', > ' buffering: int = ...,\n', > ' encoding: str | None = ...,\n', > ' errors: str | None = ...,\n', > ' newline: str | None = ...,\n', > ' closefd: bool = ...,\n', > ' opener: Callable[[str, int], int] | None = ...,\n', > ' ) -> Iterator[str]: ...\n', > '\n', > ' @overload\n', > ' def chunks(\n', > ' self,\n', > ' size: int,\n', > ' mode: OpenBinaryMode,\n', > ' buffering: int = ...,\n', > ' encoding: str | None = ...,\n', > ' errors: str | None = ...,\n', > ' newline: str | None = ...,\n', > ' closefd: bool = ...,\n', > ' opener: Callable[[str, int], int] | None = ...,\n', > ' ) -> Iterator[builtins.bytes]: ...\n', > '\n', > ' @overload\n', > ' def chunks(\n', > ' self,\n', > ' size: int,\n', > ' mode: str,\n', > ' buffering: int = ...,\n', > ' encoding: str | None = ...,\n', > ' errors: str | None = ...,\n', > ' newline: str | None = ...,\n', > ' closefd: bool = ...,\n', > ' opener: Callable[[str, int], int] | None = ...,\n', > ' ) -> Iterator[str | builtins.bytes]: ...\n', > '\n', > ' def chunks(self, size, *args, **kwargs):\n', > ' """Returns a generator yielding chunks of the file, so it can\n', > ' be read piece by piece with a simple for loop.\n', > '\n', > ' Any argument you pass after `size` will be passed to :meth:`open`.\n', > '\n', > ' :example:\n', > '\n', > ' >>> hash = hashlib.md5()\n', > ' >>> for chunk in Path("NEWS.rst").chunks(8192, mode=\'rb\'):\n', > ' ... hash.update(chunk)\n', > '\n', > ' This will read the file by chunks of 8192 bytes.\n', > ' """\n', > ' with self.open(*args, **kwargs) as f:\n', > ' yield from iter(lambda: f.read(size) or None, None)\n', > '\n', > ' def write_bytes(self, bytes, append=False):\n', > ' """Open this file and write the given bytes to it.\n', > '\n', > ' Default behavior is to overwrite any existing file.\n', > ' Call ``p.write_bytes(bytes, append=True)`` to append instead.\n', > ' """\n', > " with self.open('ab' if append else 'wb') as f:\n", > ' f.write(bytes)\n', > '\n', > ' def read_text(self, encoding=None, errors=None):\n', > ' r"""Open this file, read it in, return the content as a string.\n', > '\n', > ' Optional parameters are passed to :meth:`open`.\n', > '\n', > ' .. seealso:: :meth:`lines`\n', > ' """\n', > ' with self.open(encoding=encoding, errors=errors) as f:\n', > ' return f.read()\n', > '\n', > ' def read_bytes(self):\n', > ' r"""Return the contents of this file as bytes."""\n', > " with self.open(mode='rb') as f:\n", > ' return f.read()\n', > '\n', > ' def write_text(\n', > ' self,\n', > ' text: str,\n', > ' encoding: str | None = None,\n', > " errors: str = 'strict',\n", > ' linesep: str | None = os.linesep,\n', > ' append: bool = False,\n', > ' ) -> None:\n', > ' r"""Write the given text to this file.\n', > '\n', > ' The default behavior is to overwrite any existing file;\n', > ' to append instead, use the `append=True` keyword argument.\n', > '\n', > ' There are two differences between :meth:`write_text` and\n', > ' :meth:`write_bytes`: newline handling and Unicode handling.\n', > ' See below.\n', > '\n', > ' Parameters:\n', > '\n', > ' `text` - str - The text to be written.\n', > '\n', > ' `encoding` - str - The text encoding used.\n', > '\n', > ' `errors` - str - How to handle Unicode encoding errors.\n', > " Default is ``'strict'``. See ``help(unicode.encode)`` for " > 'the\n', > " options. Ignored if `text` isn't a Unicode string.\n", > '\n', > ' `linesep` - keyword argument - str/unicode - The sequence of\n', > ' characters to be used to mark end-of-line. The default is\n', > ' :data:`os.linesep`. Specify ``None`` to\n', > ' use newlines unmodified.\n', > '\n', > ' `append` - keyword argument - bool - Specifies what to do if\n', > ' the file already exists (``True``: append to the end of it;\n', > ' ``False``: overwrite it). The default is ``False``.\n', > '\n', > '\n', > ' --- Newline handling.\n', > '\n', > ' ``write_text()`` converts all standard end-of-line sequences\n', > " (``'\\n'``, ``'\\r'``, and ``'\\r\\n'``) to your platform's " > 'default\n', > ' end-of-line sequence (see :data:`os.linesep`; on Windows, for ' > 'example,\n', > " the end-of-line marker is ``'\\r\\n'``).\n", > '\n', > " To override the platform's default, pass the `linesep=`\n", > ' keyword argument. To preserve the newlines as-is, pass\n', > ' ``linesep=None``.\n', > '\n', > ' This handling applies to Unicode text and bytes, except\n', > ' with Unicode, additional non-ASCII newlines are recognized:\n', > ' ``\\x85``, ``\\r\\x85``, and ``\\u2028``.\n', > '\n', > ' --- Unicode\n', > '\n', > ' `text` is written using the\n', > ' specified `encoding` (or the default encoding if `encoding`\n', > " isn't specified). The `errors` argument applies only to this\n", > ' conversion.\n', > ' """\n', > ' if linesep is not None:\n', > ' text = U_NEWLINE.sub(linesep, text)\n', > ' bytes = text.encode(encoding or sys.getdefaultencoding(), errors)\n', > ' self.write_bytes(bytes, append=append)\n', > '\n', > ' def lines(self, encoding=None, errors=None, retain=True):\n', > ' r"""Open this file, read all lines, return them in a list.\n', > '\n', > ' Optional arguments:\n', > ' `encoding` - The Unicode encoding (or character set) of\n', > ' the file. The default is ``None``, meaning use\n', > ' ``locale.getpreferredencoding()``.\n', > ' `errors` - How to handle Unicode errors; see\n', > ' `open ' > '<https://docs.python.org/3/library/functions.html#open>`_\n', > ' for the options. Default is ``None`` meaning "strict".\n', > ' `retain` - If ``True`` (default), retain newline characters,\n', > ' but translate all newline\n', > ' characters to ``\\n``. If ``False``, newline characters ' > 'are\n', > ' omitted.\n', > ' """\n', > " text = U_NEWLINE.sub('\\n', self.read_text(encoding, errors))\n", > ' return text.splitlines(retain)\n', > '\n', > ' def write_lines(\n', > ' self,\n', > ' lines,\n', > ' encoding=None,\n', > " errors='strict',\n", > ' *,\n', > ' append=False,\n', > ' ):\n', > ' r"""Write the given lines of text to this file.\n', > '\n', > ' By default this overwrites any existing file at this path.\n', > '\n', > ' Puts a platform-specific newline sequence on every line.\n', > '\n', > ' `lines` - A list of strings.\n', > '\n', > ' `encoding` - A Unicode encoding to use. This applies only if\n', > ' `lines` contains any Unicode strings.\n', > '\n', > ' `errors` - How to handle errors in Unicode encoding. This\n', > ' also applies only to Unicode strings.\n', > '\n', > ' Use the keyword argument ``append=True`` to append lines to the\n', > ' file. The default is to overwrite the file.\n', > ' """\n', > " mode = 'a' if append else 'w'\n", > " with self.open(mode, encoding=encoding, errors=errors, newline='') " > 'as f:\n', > ' f.writelines(self._replace_linesep(lines))\n', > '\n', > ' @staticmethod\n', > ' def _replace_linesep(lines):\n', > ' return (line + os.linesep for line in _strip_newlines(lines))\n', > '\n', > ' def read_md5(self):\n', > ' """Calculate the md5 hash for this file.\n', > '\n', > ' This reads through the entire file.\n', > '\n', > ' .. seealso:: :meth:`read_hash`\n', > ' """\n', > " return self.read_hash('md5')\n", > '\n', > ' def _hash(self, hash_name):\n', > ' """Returns a hash object for the file at the current path.\n', > '\n', > " `hash_name` should be a hash algo name (such as ``'md5'``\n", > " or ``'sha1'``) that's available in the :mod:`hashlib` module.\n", > ' """\n', > ' m = hashlib.new(hash_name)\n', > ' for chunk in self.chunks(8192, mode="rb"):\n', > ' m.update(chunk)\n', > ' return m\n', > '\n', > ' def read_hash(self, hash_name):\n', > ' """Calculate given hash for this file.\n', > '\n', > ' List of supported hashes can be obtained from :mod:`hashlib` ' > 'package.\n', > ' This reads the entire file.\n', > '\n', > ' .. seealso:: :meth:`hashlib.hash.digest`\n', > ' """\n', > ' return self._hash(hash_name).digest()\n', > '\n', > ' def read_hexhash(self, hash_name):\n', > ' """Calculate given hash for this file, returning hexdigest.\n', > '\n', > ' List of supported hashes can be obtained from :mod:`hashlib` ' > 'package.\n', > ' This reads the entire file.\n', > '\n', > ' .. seealso:: :meth:`hashlib.hash.hexdigest`\n', > ' """\n', > ' return self._hash(hash_name).hexdigest()\n', > '\n', > ' # --- Methods for querying the filesystem.\n', > ' # N.B. On some platforms, the os.path functions may be implemented in ' > 'C\n', > " # (e.g. isdir on Windows, Python 3.2.2), and compiled functions don't " > 'get\n', > ' # bound. Playing it safe and wrapping them all in method calls.\n', > '\n', > ' def isabs(self):\n', > ' """\n', > " >>> Path('.').isabs()\n", > ' False\n', > '\n', > ' .. seealso:: :func:`os.path.isabs`\n', > ' """\n', > ' return self.module.isabs(self)\n', > '\n', > ' def exists(self):\n', > ' """.. seealso:: :func:`os.path.exists`"""\n', > ' return self.module.exists(self)\n', > '\n', > ' def is_dir(self):\n', > ' """.. seealso:: :func:`os.path.isdir`"""\n', > ' return self.module.isdir(self)\n', > '\n', > ' def is_file(self):\n', > ' """.. seealso:: :func:`os.path.isfile`"""\n', > ' return self.module.isfile(self)\n', > '\n', > ' def islink(self):\n', > ' """.. seealso:: :func:`os.path.islink`"""\n', > ' return self.module.islink(self)\n', > '\n', > ' def ismount(self):\n', > ' """\n', > " >>> Path('.').ismount()\n", > ' False\n', > '\n', > ' .. seealso:: :func:`os.path.ismount`\n', > ' """\n', > ' return self.module.ismount(self)\n', > '\n', > ' def samefile(self, other):\n', > ' """.. seealso:: :func:`os.path.samefile`"""\n', > ' return self.module.samefile(self, other)\n', > '\n', > ' def getatime(self):\n', > ' """.. seealso:: :attr:`atime`, :func:`os.path.getatime`"""\n', > ' return self.module.getatime(self)\n', > '\n', > ' def set_atime(self, value):\n', > ' mtime_ns = self.stat().st_atime_ns\n', > ' self.utime(ns=(_make_timestamp_ns(value), mtime_ns))\n', > '\n', > ' atime = property(\n', > ' getatime,\n', > ' set_atime,\n', > ' None,\n', > ' """\n', > ' Last access time of the file.\n', > '\n', > " >>> Path('.').atime > 0\n", > ' True\n', > '\n', > ' Allows setting:\n', > '\n', > ' >>> some_file = ' > "Path(getfixture('tmp_path')).joinpath('file.txt').touch()\n", > ' >>> MST = datetime.timezone(datetime.timedelta(hours=-7))\n', > ' >>> some_file.atime = datetime.datetime(1976, 5, 7, 10, ' > 'tzinfo=MST)\n', > ' >>> some_file.atime\n', > ' 200336400.0\n', > '\n', > ' .. seealso:: :meth:`getatime`, :func:`os.path.getatime`\n', > ' """,\n', > ' )\n', > '\n', > ' def getmtime(self):\n', > ' """.. seealso:: :attr:`mtime`, :func:`os.path.getmtime`"""\n', > ' return self.module.getmtime(self)\n', > '\n', > ' def set_mtime(self, value):\n', > ' atime_ns = self.stat().st_atime_ns\n', > ' self.utime(ns=(atime_ns, _make_timestamp_ns(value)))\n', > '\n', > ' mtime = property(\n', > ' getmtime,\n', > ' set_mtime,\n', > ' None,\n', > ' """\n', > ' Last modified time of the file.\n', > '\n', > ' Allows setting:\n', > '\n', > ' >>> some_file = ' > "Path(getfixture('tmp_path')).joinpath('file.txt').touch()\n", > ' >>> MST = datetime.timezone(datetime.timedelta(hours=-7))\n', > ' >>> some_file.mtime = datetime.datetime(1976, 5, 7, 10, ' > 'tzinfo=MST)\n', > ' >>> some_file.mtime\n', > ' 200336400.0\n', > '\n', > ' .. seealso:: :meth:`getmtime`, :func:`os.path.getmtime`\n', > ' """,\n', > ' )\n', > '\n', > ' def getctime(self):\n', > ' """.. seealso:: :attr:`ctime`, :func:`os.path.getctime`"""\n', > ' return self.module.getctime(self)\n', > '\n', > ' ctime = property(\n', > ' getctime,\n', > ' None,\n', > ' None,\n', > ' """ Creation time of the file.\n', > '\n', > ' .. seealso:: :meth:`getctime`, :func:`os.path.getctime`\n', > ' """,\n', > ' )\n', > '\n', > ' def getsize(self):\n', > ' """.. seealso:: :attr:`size`, :func:`os.path.getsize`"""\n', > ' return self.module.getsize(self)\n', > '\n', > ' size = property(\n', > ' getsize,\n', > ' None,\n', > ' None,\n', > ' """ Size of the file, in bytes.\n', > '\n', > ' .. seealso:: :meth:`getsize`, :func:`os.path.getsize`\n', > ' """,\n', > ' )\n', > '\n', > ' @property\n', > ' def permissions(self) -> masks.Permissions:\n', > ' """\n', > ' Permissions.\n', > '\n', > " >>> perms = Path('.').permissions\n", > ' >>> isinstance(perms, int)\n', > ' True\n', > " >>> set(perms.symbolic) <= set('rwx-')\n", > ' True\n', > ' >>> perms.symbolic\n', > " 'r...'\n", > ' """\n', > ' return masks.Permissions(self.stat().st_mode)\n', > '\n', > ' def access(self, *args, **kwargs):\n', > ' """\n', > ' Return does the real user have access to this path.\n', > '\n', > " >>> Path('.').access(os.F_OK)\n", > ' True\n', > '\n', > ' .. seealso:: :func:`os.access`\n', > ' """\n', > ' return os.access(self, *args, **kwargs)\n', > '\n', > ' def stat(self, *, follow_symlinks=True):\n', > ' """\n', > ' Perform a ``stat()`` system call on this path.\n', > '\n', > " >>> Path('.').stat()\n", > ' os.stat_result(...)\n', > '\n', > ' .. seealso:: :meth:`lstat`, :func:`os.stat`\n', > ' """\n', > ' return os.stat(self, follow_symlinks=follow_symlinks)\n', > '\n', > ' def lstat(self):\n', > ' """\n', > ' Like :meth:`stat`, but do not follow symbolic links.\n', > '\n', > " >>> Path('.').lstat() == Path('.').stat()\n", > ' True\n', > '\n', > ' .. seealso:: :meth:`stat`, :func:`os.lstat`\n', > ' """\n', > ' return os.lstat(self)\n', > '\n', > ' def __get_owner_windows(self): # pragma: nocover\n', > ' r"""\n', > ' Return the name of the owner of this file or directory. Follow\n', > ' symbolic links.\n', > '\n', > ' Return a name of the form ``DOMAIN\\User Name``; may be a group.\n', > '\n', > ' .. seealso:: :attr:`owner`\n', > ' """\n', > ' desc = win32security.GetFileSecurity(\n', > ' self, win32security.OWNER_SECURITY_INFORMATION\n', > ' )\n', > ' sid = desc.GetSecurityDescriptorOwner()\n', > ' account, domain, typecode = win32security.LookupAccountSid(None, ' > 'sid)\n', > " return domain + '\\\\' + account\n", > '\n', > ' def __get_owner_unix(self): # pragma: nocover\n', > ' """\n', > ' Return the name of the owner of this file or directory. Follow\n', > ' symbolic links.\n', > '\n', > ' .. seealso:: :attr:`owner`\n', > ' """\n', > ' st = self.stat()\n', > ' return pwd.getpwuid(st.st_uid).pw_name\n', > '\n', > ' def __get_owner_not_implemented(self): # pragma: nocover\n', > ' raise NotImplementedError("Ownership not available on this ' > 'platform.")\n', > '\n', > ' get_owner = (\n', > ' __get_owner_windows\n', > " if 'win32security' in globals()\n", > ' else __get_owner_unix\n', > " if 'pwd' in globals()\n", > ' else __get_owner_not_implemented\n', > ' )\n', > '\n', > ' owner = property(\n', > ' get_owner,\n', > ' None,\n', > ' None,\n', > ' """ Name of the owner of this file or directory.\n', > '\n', > ' .. seealso:: :meth:`get_owner`""",\n', > ' )\n', > '\n', > " if 'grp' in globals(): # pragma: no cover\n", > '\n', > ' def group(self, *, follow_symlinks=True):\n', > ' """\n', > ' Return the group name of the file gid.\n', > ' """\n', > ' gid = self.stat(follow_symlinks=follow_symlinks).st_gid\n', > ' return grp.getgrgid(gid).gr_name\n', > '\n', > " if hasattr(os, 'statvfs'):\n", > '\n', > ' def statvfs(self):\n', > ' """Perform a ``statvfs()`` system call on this path.\n', > '\n', > ' .. seealso:: :func:`os.statvfs`\n', > ' """\n', > ' return os.statvfs(self)\n', > '\n', > " if hasattr(os, 'pathconf'):\n", > '\n', > ' def pathconf(self, name):\n', > ' """.. seealso:: :func:`os.pathconf`"""\n', > ' return os.pathconf(self, name)\n', > '\n', > ' #\n', > ' # --- Modifying operations on files and directories\n', > '\n', > ' def utime(self, *args, **kwargs):\n', > ' """Set the access and modified times of this file.\n', > '\n', > ' .. seealso:: :func:`os.utime`\n', > ' """\n', > ' os.utime(self, *args, **kwargs)\n', > ' return self\n', > '\n', > ' def chmod(self, mode):\n', > ' """\n', > ' Set the mode. May be the new mode (os.chmod behavior) or a ' > '`symbolic\n', > ' mode <http://en.wikipedia.org/wiki/Chmod#Symbolic_modes>`_.\n', > '\n', > ' >>> a_file = ' > "Path(getfixture('tmp_path')).joinpath('afile.txt').touch()\n", > ' >>> a_file.chmod(0o700)\n', > ' Path(...\n', > " >>> a_file.chmod('u+x')\n", > ' Path(...\n', > '\n', > ' .. seealso:: :func:`os.chmod`\n', > ' """\n', > ' if isinstance(mode, str):\n', > ' mask = masks.compound(mode)\n', > ' mode = mask(self.stat().st_mode)\n', > ' os.chmod(self, mode)\n', > ' return self\n', > '\n', > " if hasattr(os, 'chown'):\n", > '\n', > ' def chown(self, uid=-1, gid=-1):\n', > ' """\n', > ' Change the owner and group by names or numbers.\n', > '\n', > ' .. seealso:: :func:`os.chown`\n', > ' """\n', > '\n', > ' def resolve_uid(uid):\n', > ' return uid if isinstance(uid, int) else ' > 'pwd.getpwnam(uid).pw_uid\n', > '\n', > ' def resolve_gid(gid):\n', > ' return gid if isinstance(gid, int) else ' > 'grp.getgrnam(gid).gr_gid\n', > '\n', > ' os.chown(self, resolve_uid(uid), resolve_gid(gid))\n', > ' return self\n', > '\n', > ' def rename(self, new):\n', > ' """.. seealso:: :func:`os.rename`"""\n', > ' os.rename(self, new)\n', > ' return self._next_class(new)\n', > '\n', > ' def renames(self, new):\n', > ' """.. seealso:: :func:`os.renames`"""\n', > ' os.renames(self, new)\n', > ' return self._next_class(new)\n', > '\n', > ' def replace(self, target_or_old: Path | str, *args) -> Path:\n', > ' """\n', > ' Replace a path or substitute substrings.\n', > '\n', > ' Implements both pathlib.Path.replace and str.replace.\n', > '\n', > ' If only a target is supplied, rename this path to the target path,\n', > ' overwriting if that path exists.\n', > '\n', > " >>> dest = Path(getfixture('tmp_path'))\n", > " >>> orig = dest.joinpath('foo').touch()\n", > " >>> new = orig.replace(dest.joinpath('fee'))\n", > ' >>> orig.exists()\n', > ' False\n', > ' >>> new.exists()\n', > ' True\n', > '\n', > ' ..seealso:: :meth:`pathlib.Path.replace`\n', > '\n', > ' If a second parameter is supplied, perform a textual replacement.\n', > '\n', > " >>> Path('foo').replace('o', 'e')\n", > " Path('fee')\n", > " >>> Path('foo').replace('o', 'l', 1)\n", > " Path('flo')\n", > '\n', > ' ..seealso:: :meth:`str.replace`\n', > ' """\n', > ' return self._next_class(\n', > ' super().replace(target_or_old, *args)\n', > ' if args\n', > ' else pathlib.Path(self).replace(target_or_old)\n', > ' )\n', > '\n', > ' #\n', > ' # --- Create/delete operations on directories\n', > '\n', > ' def mkdir(self, mode=0o777):\n', > ' """.. seealso:: :func:`os.mkdir`"""\n', > ' os.mkdir(self, mode)\n', > ' return self\n', > '\n', > ' def mkdir_p(self, mode=0o777):\n', > ' """Like :meth:`mkdir`, but does not raise an exception if the\n', > ' directory already exists."""\n', > ' with contextlib.suppress(FileExistsError):\n', > ' self.mkdir(mode)\n', > ' return self\n', > '\n', > ' def makedirs(self, mode=0o777):\n', > ' """.. seealso:: :func:`os.makedirs`"""\n', > ' os.makedirs(self, mode)\n', > ' return self\n', > '\n', > ' def makedirs_p(self, mode=0o777):\n', > ' """Like :meth:`makedirs`, but does not raise an exception if the\n', > ' directory already exists."""\n', > ' with contextlib.suppress(FileExistsError):\n', > ' self.makedirs(mode)\n', > ' return self\n', > '\n', > ' def rmdir(self):\n', > ' """.. seealso:: :func:`os.rmdir`"""\n', > ' os.rmdir(self)\n', > ' return self\n', > '\n', > ' def rmdir_p(self):\n', > ' """Like :meth:`rmdir`, but does not raise an exception if the\n', > ' directory is not empty or does not exist."""\n', > ' suppressed = FileNotFoundError, FileExistsError, DirectoryNotEmpty\n', > ' with contextlib.suppress(suppressed):\n', > ' with DirectoryNotEmpty.translate():\n', > ' self.rmdir()\n', > ' return self\n', > '\n', > ' def removedirs(self):\n', > ' """.. seealso:: :func:`os.removedirs`"""\n', > ' os.removedirs(self)\n', > ' return self\n', > '\n', > ' def removedirs_p(self):\n', > ' """Like :meth:`removedirs`, but does not raise an exception if the\n', > ' directory is not empty or does not exist."""\n', > ' with contextlib.suppress(FileExistsError, DirectoryNotEmpty):\n', > ' with DirectoryNotEmpty.translate():\n', > ' self.removedirs()\n', > ' return self\n', > '\n', > ' # --- Modifying operations on files\n', > '\n', > ' def touch(self):\n', > ' """Set the access/modified times of this file to the current time.\n', > ' Create the file if it does not exist.\n', > ' """\n', > ' os.close(os.open(self, os.O_WRONLY | os.O_CREAT, 0o666))\n', > ' os.utime(self, None)\n', > ' return self\n', > '\n', > ' def remove(self):\n', > ' """.. seealso:: :func:`os.remove`"""\n', > ' os.remove(self)\n', > ' return self\n', > '\n', > ' def remove_p(self):\n', > ' """Like :meth:`remove`, but does not raise an exception if the\n', > ' file does not exist."""\n', > ' with contextlib.suppress(FileNotFoundError):\n', > ' self.unlink()\n', > ' return self\n', > '\n', > ' unlink = remove\n', > ' unlink_p = remove_p\n', > '\n', > ' # --- Links\n', > '\n', > ' def hardlink_to(self, target: str) -> None:\n', > ' """\n', > ' Create a hard link at self, pointing to target.\n', > '\n', > ' .. seealso:: :func:`os.link`\n', > ' """\n', > ' os.link(target, self)\n', > '\n', > ' def link(self, newpath):\n', > ' """Create a hard link at `newpath`, pointing to this file.\n', > '\n', > ' .. seealso:: :func:`os.link`\n', > ' """\n', > ' os.link(self, newpath)\n', > ' return self._next_class(newpath)\n', > '\n', > ' def symlink_to(self, target: str, target_is_directory: bool = False) -> ' > 'None:\n', > ' """\n', > ' Create a symbolic link at self, pointing to target.\n', > '\n', > ' .. seealso:: :func:`os.symlink`\n', > ' """\n', > ' os.symlink(target, self, target_is_directory)\n', > '\n', > ' def symlink(self, newlink=None):\n', > ' """Create a symbolic link at `newlink`, pointing here.\n', > '\n', > ' If newlink is not supplied, the symbolic link will assume\n', > ' the name self.basename(), creating the link in the cwd.\n', > '\n', > ' .. seealso:: :func:`os.symlink`\n', > ' """\n', > ' if newlink is None:\n', > ' newlink = self.basename()\n', > ' os.symlink(self, newlink)\n', > ' return self._next_class(newlink)\n', > '\n', > ' def readlink(self):\n', > ' """Return the path to which this symbolic link points.\n', > '\n', > ' The result may be an absolute or a relative path.\n', > '\n', > ' .. seealso:: :meth:`readlinkabs`, :func:`os.readlink`\n', > ' """\n', > ' return self._next_class(removeprefix(os.readlink(self), ' > "'\\\\\\\\?\\\\'))\n", > '\n', > ' def readlinkabs(self):\n', > ' """Return the path to which this symbolic link points.\n', > '\n', > ' The result is always an absolute path.\n', > '\n', > ' .. seealso:: :meth:`readlink`, :func:`os.readlink`\n', > ' """\n', > ' p = self.readlink()\n', > ' return p if p.isabs() else (self.parent / p).absolute()\n', > '\n', > ' # High-level functions from shutil\n', > ' # These functions will be bound to the instance such that\n', > ' # Path(name).copy(target) will invoke shutil.copy(name, target)\n', > '\n', > ' copyfile = shutil.copyfile\n', > ' copymode = shutil.copymode\n', > ' copystat = shutil.copystat\n', > ' copy = shutil.copy\n', > ' copy2 = shutil.copy2\n', > ' copytree = shutil.copytree\n', > " if hasattr(shutil, 'move'):\n", > ' move = shutil.move\n', > ' rmtree = shutil.rmtree\n', > '\n', > ' def rmtree_p(self):\n', > ' """Like :meth:`rmtree`, but does not raise an exception if the\n', > ' directory does not exist."""\n', > ' with contextlib.suppress(FileNotFoundError):\n', > ' self.rmtree()\n', > ' return self\n', > '\n', > ' def chdir(self):\n', > ' """.. seealso:: :func:`os.chdir`"""\n', > ' os.chdir(self)\n', > '\n', > ' cd = chdir\n', > '\n', > ' def merge_tree(\n', > ' self,\n', > ' dst,\n', > ' symlinks=False,\n', > ' *,\n', > ' copy_function=shutil.copy2,\n', > ' ignore=lambda dir, contents: [],\n', > ' ):\n', > ' """\n', > ' Copy entire contents of self to dst, overwriting existing\n', > ' contents in dst with those in self.\n', > '\n', > ' Pass ``symlinks=True`` to copy symbolic links as links.\n', > '\n', > ' Accepts a ``copy_function``, similar to copytree.\n', > '\n', > ' To avoid overwriting newer files, supply a copy function\n', > ' wrapped in ``only_newer``. For example::\n', > '\n', > ' src.merge_tree(dst, copy_function=only_newer(shutil.copy2))\n', > ' """\n', > ' dst = self._next_class(dst)\n', > ' dst.makedirs_p()\n', > '\n', > ' sources = list(self.iterdir())\n', > ' _ignored = ignore(self, [item.name for item in sources])\n', > '\n', > ' def ignored(item):\n', > ' return item.name in _ignored\n', > '\n', > ' for source in itertools.filterfalse(ignored, sources):\n', > ' dest = dst / source.name\n', > ' if symlinks and source.islink():\n', > ' target = source.readlink()\n', > ' target.symlink(dest)\n', > ' elif source.is_dir():\n', > ' source.merge_tree(\n', > ' dest,\n', > ' symlinks=symlinks,\n', > ' copy_function=copy_function,\n', > ' ignore=ignore,\n', > ' )\n', > ' else:\n', > ' copy_function(source, dest)\n', > '\n', > ' self.copystat(dst)\n', > '\n', > ' #\n', > ' # --- Special stuff from os\n', > '\n', > " if hasattr(os, 'chroot'):\n", > '\n', > ' def chroot(self): # pragma: nocover\n', > ' """.. seealso:: :func:`os.chroot`"""\n', > ' os.chroot(self)\n', > '\n', > " if hasattr(os, 'startfile'):\n", > '\n', > ' def startfile(self, *args, **kwargs): # pragma: nocover\n', > ' """.. seealso:: :func:`os.startfile`"""\n', > ' os.startfile(self, *args, **kwargs)\n', > ' return self\n', > '\n', > ' # in-place re-writing, courtesy of Martijn Pieters\n', > ' # http://www.zopatista.com/python/2013/11/26/inplace-file-rewriting/\n', > ' @contextlib.contextmanager\n', > ' def in_place(\n', > ' self,\n', > " mode='r',\n", > ' buffering=-1,\n', > ' encoding=None,\n', > ' errors=None,\n', > ' newline=None,\n', > ' backup_extension=None,\n', > ' ):\n', > ' """\n', > ' A context in which a file may be re-written in-place with\n', > ' new content.\n', > '\n', > ' Yields a tuple of :samp:`({readable}, {writable})` file\n', > ' objects, where `writable` replaces `readable`.\n', > '\n', > ' If an exception occurs, the old file is restored, removing the\n', > ' written data.\n', > '\n', > " Mode *must not* use ``'w'``, ``'a'``, or ``'+'``; only\n", > ' read-only-modes are allowed. A :exc:`ValueError` is raised\n', > ' on invalid modes.\n', > '\n', > ' For example, to add line numbers to a file::\n', > '\n', > ' p = Path(filename)\n', > ' assert p.is_file()\n', > ' with p.in_place() as (reader, writer):\n', > ' for number, line in enumerate(reader, 1):\n', > " writer.write('{0:3}: '.format(number)))\n", > ' writer.write(line)\n', > '\n', > ' Thereafter, the file at `filename` will have line numbers in it.\n', > ' """\n', > " if set(mode).intersection('wa+'):\n", > " raise ValueError('Only read-only file modes can be used')\n", > '\n', > ' # move existing file to backup, create new file with same ' > 'permissions\n', > ' # borrowed extensively from the fileinput module\n', > " backup_fn = self + (backup_extension or os.extsep + 'bak')\n", > ' backup_fn.remove_p()\n', > ' self.rename(backup_fn)\n', > ' readable = open(\n', > ' backup_fn,\n', > ' mode,\n', > ' buffering=buffering,\n', > ' encoding=encoding,\n', > ' errors=errors,\n', > ' newline=newline,\n', > ' )\n', > '\n', > ' perm = os.stat(readable.fileno()).st_mode\n', > ' os_mode = os.O_CREAT | os.O_WRONLY | os.O_TRUNC\n', > " os_mode |= getattr(os, 'O_BINARY', 0)\n", > ' fd = os.open(self, os_mode, perm)\n', > ' writable = open(\n', > ' fd,\n', > ' "w" + mode.replace(\'r\', \'\'),\n', > ' buffering=buffering,\n', > ' encoding=encoding,\n', > ' errors=errors,\n', > ' newline=newline,\n', > ' )\n', > ' with contextlib.suppress(OSError, AttributeError):\n', > ' self.chmod(perm)\n', > '\n', > ' try:\n', > ' yield readable, writable\n', > ' except Exception:\n', > ' # move backup back\n', > ' readable.close()\n', > ' writable.close()\n', > ' self.remove_p()\n', > ' backup_fn.rename(self)\n', > ' raise\n', > ' else:\n', > ' readable.close()\n', > ' writable.close()\n', > ' finally:\n', > ' backup_fn.remove_p()\n', > '\n', > ' @classes.ClassProperty\n', > ' @classmethod\n', > ' def special(cls):\n', > ' """\n', > ' Return a SpecialResolver object suitable referencing a suitable\n', > ' directory for the relevant platform for the given\n', > ' type of content.\n', > '\n', > ' For example, to get a user config directory, invoke:\n', > '\n', > ' dir = Path.special().user.config\n', > '\n', > ' Uses the `appdirs\n', > ' <https://pypi.python.org/pypi/appdirs/1.4.0>`_ to resolve\n', > ' the paths in a platform-friendly way.\n', > '\n', > " To create a config directory for 'My App', consider:\n", > '\n', > ' dir = Path.special("My App").user.config.makedirs_p()\n', > '\n', > ' If the ``appdirs`` module is not installed, invocation\n', > ' of special will raise an ImportError.\n', > ' """\n', > ' return functools.partial(SpecialResolver, cls)\n', > '\n', > '\n', > 'class DirectoryNotEmpty(OSError):\n', > ' @staticmethod\n', > ' @contextlib.contextmanager\n', > ' def translate():\n', > ' try:\n', > ' yield\n', > ' except OSError as exc:\n', > ' if exc.errno == errno.ENOTEMPTY:\n', > ' raise DirectoryNotEmpty(*exc.args) from exc\n', > ' raise\n', > '\n', > '\n', > 'def only_newer(copy_func):\n', > ' """\n', > ' Wrap a copy function (like shutil.copy2) to return\n', > " the dst if it's newer than the source.\n", > ' """\n', > '\n', > ' @functools.wraps(copy_func)\n', > ' def wrapper(src, dst, *args, **kwargs):\n', > ' is_newer_dst = dst.exists() and dst.getmtime() >= src.getmtime()\n', > ' if is_newer_dst:\n', > ' return dst\n', > ' return copy_func(src, dst, *args, **kwargs)\n', > '\n', > ' return wrapper\n', > '\n', > '\n', > 'class ExtantPath(Path):\n', > ' """\n', > " >>> ExtantPath('.')\n", > " ExtantPath('.')\n", > " >>> ExtantPath('does-not-exist')\n", > ' Traceback (most recent call last):\n', > ' OSError: does-not-exist does not exist.\n', > ' """\n', > '\n', > ' def _validate(self):\n', > ' if not self.exists():\n', > ' raise OSError(f"{self} does not exist.")\n', > '\n', > '\n', > 'class ExtantFile(Path):\n', > ' """\n', > " >>> ExtantFile('.')\n", > ' Traceback (most recent call last):\n', > ' FileNotFoundError: . does not exist as a file.\n', > " >>> ExtantFile('does-not-exist')\n", > ' Traceback (most recent call last):\n', > ' FileNotFoundError: does-not-exist does not exist as a file.\n', > ' """\n', > '\n', > ' def _validate(self):\n', > ' if not self.is_file():\n', > ' raise FileNotFoundError(f"{self} does not exist as a file.")\n', > '\n', > '\n', > 'class SpecialResolver:\n', > ' class ResolverScope:\n', > ' def __init__(self, paths, scope):\n', > ' self.paths = paths\n', > ' self.scope = scope\n', > '\n', > ' def __getattr__(self, class_):\n', > ' return self.paths.get_dir(self.scope, class_)\n', > '\n', > ' def __init__(self, path_class, *args, **kwargs):\n', > " appdirs = importlib.import_module('appdirs')\n", > '\n', > ' vars(self).update(\n', > ' path_class=path_class, wrapper=appdirs.AppDirs(*args, ' > '**kwargs)\n', > ' )\n', > '\n', > ' def __getattr__(self, scope):\n', > ' return self.ResolverScope(self, scope)\n', > '\n', > ' def get_dir(self, scope, class_):\n', > ' """\n', > ' Return the callable function from appdirs, but with the\n', > ' result wrapped in self.path_class\n', > ' """\n', > " prop_name = f'{scope}_{class_}_dir'\n", > ' value = getattr(self.wrapper, prop_name)\n', > ' MultiPath = Multi.for_class(self.path_class)\n', > ' return MultiPath.detect(value)\n', > '\n', > '\n', > 'class Multi:\n', > ' """\n', > ' A mix-in for a Path which may contain multiple Path separated by ' > 'pathsep.\n', > ' """\n', > '\n', > ' @classmethod\n', > ' def for_class(cls, path_cls):\n', > " name = 'Multi' + path_cls.__name__\n", > ' return type(name, (cls, path_cls), {})\n', > '\n', > ' @classmethod\n', > ' def detect(cls, input):\n', > ' if os.pathsep not in input:\n', > ' cls = cls._next_class\n', > ' return cls(input)\n', > '\n', > ' def __iter__(self):\n', > ' return iter(map(self._next_class, self.split(os.pathsep)))\n', > '\n', > ' @classes.ClassProperty\n', > ' @classmethod\n', > ' def _next_class(cls):\n', > ' """\n', > ' Multi-subclasses should use the parent class\n', > ' """\n', > ' return next(class_ for class_ in cls.__mro__ if not ' > 'issubclass(class_, Multi))\n', > '\n', > '\n', > 'class TempDir(Path):\n', > ' """\n', > ' A temporary directory via :func:`tempfile.mkdtemp`, and\n', > ' constructed with the same parameters that you can use\n', > ' as a context manager.\n', > '\n', > ' For example:\n', > '\n', > ' >>> with TempDir() as d:\n', > ' ... d.is_dir() and isinstance(d, Path)\n', > ' True\n', > '\n', > ' The directory is deleted automatically.\n', > '\n', > ' >>> d.is_dir()\n', > ' False\n', > '\n', > ' .. seealso:: :func:`tempfile.mkdtemp`\n', > ' """\n', > '\n', > ' @classes.ClassProperty\n', > ' @classmethod\n', > ' def _next_class(cls):\n', > ' return Path\n', > '\n', > ' def __new__(cls, *args, **kwargs):\n', > ' dirname = tempfile.mkdtemp(*args, **kwargs)\n', > ' return super().__new__(cls, dirname)\n', > '\n', > ' def __init__(self, *args, **kwargs):\n', > ' pass\n', > '\n', > ' def __enter__(self):\n', > ' # TempDir should return a Path version of itself and not itself\n', > ' # so that a second context manager does not create a second\n', > ' # temporary directory, but rather changes CWD to the location\n', > ' # of the temporary directory.\n', > ' return self._next_class(self)\n', > '\n', > ' def __exit__(self, exc_type, exc_value, traceback):\n', > ' self.rmtree()\n', > '\n', > '\n', > 'class Handlers:\n', > ' def strict(msg):\n', > ' raise\n', > '\n', > ' def warn(msg):\n', > ' warnings.warn(msg, TreeWalkWarning, stacklevel=2)\n', > '\n', > ' def ignore(msg):\n', > ' pass\n', > '\n', > ' @classmethod\n', > ' def _resolve(cls, param):\n', > ' if not callable(param) and param not in vars(Handlers):\n', > ' raise ValueError("invalid errors parameter")\n', > ' return vars(cls).get(param, param)\n'] > test = <DocTest path.Path from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:137 (no examples)> > tests = [<DocTest path from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:0 (no examples)>, > <DocTest path.Traversal from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:93 (4 examples)>, > <DocTest path._strip_newlines from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:129 (1 example)>, > <DocTest path.Path from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:137 (no examples)>, > <DocTest path.Path.__truediv__ from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:197 (no examples)>, > <DocTest path.Path.__rtruediv__ from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:208 (no examples)>, > <DocTest path.Path.cwd from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:227 (no examples)>, > <DocTest path.Path.absolute from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:241 (no examples)>, > <DocTest path.Path.normcase from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:245 (no examples)>, > <DocTest path.Path.normpath from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:249 (no examples)>, > <DocTest path.Path.realpath from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:253 (no examples)>, > <DocTest path.Path.expanduser from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:257 (no examples)>, > <DocTest path.Path.expandvars from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:261 (no examples)>, > <DocTest path.Path.dirname from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:265 (no examples)>, > <DocTest path.Path.basename from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:269 (no examples)>, > <DocTest path.Path.expand from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:273 (no examples)>, > <DocTest path.Path.stem from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:283 (1 example)>, > <DocTest path.Path.with_stem from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:292 (1 example)>, > <DocTest path.Path.suffix from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:301 (no examples)>, > <DocTest path.Path.with_suffix from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:306 (3 examples)>, > <DocTest path.Path.drive from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:326 (no examples)>, > <DocTest path.Path.parent from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:265 (no examples)>, > <DocTest path.Path.name from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:269 (no examples)>, > <DocTest path.Path.with_name from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:361 (1 example)>, > <DocTest path.Path.splitpath from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:369 (no examples)>, > <DocTest path.Path.splitdrive from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:377 (no examples)>, > <DocTest path.Path.splitext from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:389 (no examples)>, > <DocTest path.Path.stripext from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:404 (no examples)>, > <DocTest path.Path.splitall from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:424 (1 example)>, > <DocTest path.Path.parts from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:439 (1 example)>, > <DocTest path.Path.relpath from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:459 (no examples)>, > <DocTest path.Path.relpathto from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:466 (no examples)>, > <DocTest path.Path.iterdir from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:506 (no examples)>, > <DocTest path.Path.dirs from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:522 (no examples)>, > <DocTest path.Path.files from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:533 (no examples)>, > <DocTest path.Path.walk from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:544 (no examples)>, > <DocTest path.Path.walkdirs from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:584 (no examples)>, > <DocTest path.Path.walkfiles from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:588 (no examples)>, > <DocTest path.Path.fnmatch from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:592 (no examples)>, > <DocTest path.Path.glob from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:611 (no examples)>, > <DocTest path.Path.iglob from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:628 (no examples)>] > val = <function Path.open at 0x7f01aa6a9940> > valname = 'path.Path.open' >[1m[31m/usr/lib/python3.12/doctest.py[0m:1010: in _find > [0mtest = [96mself[39;49;00m._get_test(obj, name, module, globs, source_lines)[90m[39;49;00m > globs = {'B_NEWLINE': re.compile(b'\r\n|\r|\n'), > 'B_NL_END': re.compile(b'\r\n|\r|\n$'), > 'Callable': typing.Callable, > 'DirectoryNotEmpty': <class 'path.DirectoryNotEmpty'>, > 'ExtantFile': <class 'path.ExtantFile'>, > 'ExtantPath': <class 'path.ExtantPath'>, > 'Handlers': <class 'path.Handlers'>, > 'Iterator': typing.Iterator, > 'LINESEPS': ['\r\n', '\r', '\n'], > 'Multi': <class 'path.Multi'>, > 'Number': <class 'numbers.Number'>, > 'Path': <class 'path.Path'>, > 'SpecialResolver': <class 'path.SpecialResolver'>, > 'TYPE_CHECKING': False, > 'TempDir': <class 'path.TempDir'>, > 'Traversal': <class 'path.Traversal'>, > 'TreeWalkWarning': <class 'path.TreeWalkWarning'>, > 'U_LINESEPS': ['\r\n', '\r', '\n', '\x85', '\u2028', '\u2029'], > 'U_NEWLINE': re.compile('\r\n|\r|\n|\x85|\u2028|\u2029'), > 'U_NL_END': re.compile('\r\n|\r|\n|\x85|\u2028|\u2029$'), > '__all__': ['Path', 'TempDir'], > '__builtins__': {'ArithmeticError': <class 'ArithmeticError'>, > 'AssertionError': <class 'AssertionError'>, > 'AttributeError': <class 'AttributeError'>, > 'BaseException': <class 'BaseException'>, > 'BaseExceptionGroup': <class 'BaseExceptionGroup'>, > 'BlockingIOError': <class 'BlockingIOError'>, > 'BrokenPipeError': <class 'BrokenPipeError'>, > 'BufferError': <class 'BufferError'>, > 'BytesWarning': <class 'BytesWarning'>, > 'ChildProcessError': <class 'ChildProcessError'>, > 'ConnectionAbortedError': <class 'ConnectionAbortedError'>, > 'ConnectionError': <class 'ConnectionError'>, > 'ConnectionRefusedError': <class 'ConnectionRefusedError'>, > 'ConnectionResetError': <class 'ConnectionResetError'>, > 'DeprecationWarning': <class 'DeprecationWarning'>, > 'EOFError': <class 'EOFError'>, > 'Ellipsis': Ellipsis, > 'EncodingWarning': <class 'EncodingWarning'>, > 'EnvironmentError': <class 'OSError'>, > 'Exception': <class 'Exception'>, > 'ExceptionGroup': <class 'ExceptionGroup'>, > 'False': False, > 'FileExistsError': <class 'FileExistsError'>, > 'FileNotFoundError': <class 'FileNotFoundError'>, > 'FloatingPointError': <class 'FloatingPointError'>, > 'FutureWarning': <class 'FutureWarning'>, > 'GeneratorExit': <class 'GeneratorExit'>, > 'IOError': <class 'OSError'>, > 'ImportError': <class 'ImportError'>, > 'ImportWarning': <class 'ImportWarning'>, > 'IndentationError': <class 'IndentationError'>, > 'IndexError': <class 'IndexError'>, > 'InterruptedError': <class 'InterruptedError'>, > 'IsADirectoryError': <class 'IsADirectoryError'>, > 'KeyError': <class 'KeyError'>, > 'KeyboardInterrupt': <class 'KeyboardInterrupt'>, > 'LookupError': <class 'LookupError'>, > 'MemoryError': <class 'MemoryError'>, > 'ModuleNotFoundError': <class 'ModuleNotFoundError'>, > 'NameError': <class 'NameError'>, > 'None': None, > 'NotADirectoryError': <class 'NotADirectoryError'>, > 'NotImplemented': NotImplemented, > 'NotImplementedError': <class 'NotImplementedError'>, > 'OSError': <class 'OSError'>, > 'OverflowError': <class 'OverflowError'>, > 'PendingDeprecationWarning': <class 'PendingDeprecationWarning'>, > 'PermissionError': <class 'PermissionError'>, > 'ProcessLookupError': <class 'ProcessLookupError'>, > 'RecursionError': <class 'RecursionError'>, > 'ReferenceError': <class 'ReferenceError'>, > 'ResourceWarning': <class 'ResourceWarning'>, > 'RuntimeError': <class 'RuntimeError'>, > 'RuntimeWarning': <class 'RuntimeWarning'>, > 'StopAsyncIteration': <class 'StopAsyncIteration'>, > 'StopIteration': <class 'StopIteration'>, > 'SyntaxError': <class 'SyntaxError'>, > 'SyntaxWarning': <class 'SyntaxWarning'>, > 'SystemError': <class 'SystemError'>, > 'SystemExit': <class 'SystemExit'>, > 'TabError': <class 'TabError'>, > 'TimeoutError': <class 'TimeoutError'>, > 'True': True, > 'TypeError': <class 'TypeError'>, > 'UnboundLocalError': <class 'UnboundLocalError'>, > 'UnicodeDecodeError': <class 'UnicodeDecodeError'>, > 'UnicodeEncodeError': <class 'UnicodeEncodeError'>, > 'UnicodeError': <class 'UnicodeError'>, > 'UnicodeTranslateError': <class 'UnicodeTranslateError'>, > 'UnicodeWarning': <class 'UnicodeWarning'>, > 'UserWarning': <class 'UserWarning'>, > 'ValueError': <class 'ValueError'>, > 'Warning': <class 'Warning'>, > 'ZeroDivisionError': <class 'ZeroDivisionError'>, > '__build_class__': <built-in function __build_class__>, > '__debug__': True, > '__doc__': 'Built-in functions, types, exceptions, and other ' > 'objects.\n' > '\n' > 'This module provides direct access to all ' > "'built-in'\n" > 'identifiers of Python; for example, builtins.len ' > 'is\n' > 'the full name for the built-in function len().\n' > '\n' > 'This module is not normally accessed explicitly ' > 'by most\n' > 'applications, but can be useful in modules that ' > 'provide\n' > 'objects with the same name as a built-in value, ' > 'but in\n' > 'which the built-in of that name is also needed.', > '__import__': <built-in function __import__>, > '__loader__': <class '_frozen_importlib.BuiltinImporter'>, > '__name__': 'builtins', > '__package__': '', > '__spec__': ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>, origin='built-in'), > 'abs': <built-in function abs>, > 'aiter': <built-in function aiter>, > 'all': <built-in function all>, > 'anext': <built-in function anext>, > 'any': <built-in function any>, > 'ascii': <built-in function ascii>, > 'bin': <built-in function bin>, > 'bool': <class 'bool'>, > 'breakpoint': <built-in function breakpoint>, > 'bytearray': <class 'bytearray'>, > 'bytes': <class 'bytes'>, > 'callable': <built-in function callable>, > 'chr': <built-in function chr>, > 'classmethod': <class 'classmethod'>, > 'compile': <built-in function compile>, > 'complex': <class 'complex'>, > 'copyright': Copyright (c) 2001-2023 Python Software Foundation. >All Rights Reserved. > >Copyright (c) 2000 BeOpen.com. >All Rights Reserved. > >Copyright (c) 1995-2001 Corporation for National Research Initiatives. >All Rights Reserved. > >Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam. >All Rights Reserved., > 'credits': Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands > for supporting Python development. See www.python.org for more information., > 'delattr': <built-in function delattr>, > 'dict': <class 'dict'>, > 'dir': <built-in function dir>, > 'divmod': <built-in function divmod>, > 'enumerate': <class 'enumerate'>, > 'eval': <built-in function eval>, > 'exec': <built-in function exec>, > 'exit': Use exit() or Ctrl-D (i.e. EOF) to exit, > 'filter': <class 'filter'>, > 'float': <class 'float'>, > 'format': <built-in function format>, > 'frozenset': <class 'frozenset'>, > 'getattr': <built-in function getattr>, > 'globals': <built-in function globals>, > 'hasattr': <built-in function hasattr>, > 'hash': <built-in function hash>, > 'help': Type help() for interactive help, or help(object) for help about object., > 'hex': <built-in function hex>, > 'id': <built-in function id>, > 'input': <built-in function input>, > 'int': <class 'int'>, > 'isinstance': <built-in function isinstance>, > 'issubclass': <built-in function issubclass>, > 'iter': <built-in function iter>, > 'len': <built-in function len>, > 'license': Type license() to see the full license text, > 'list': <class 'list'>, > 'locals': <built-in function locals>, > 'map': <class 'map'>, > 'max': <built-in function max>, > 'memoryview': <class 'memoryview'>, > 'min': <built-in function min>, > 'next': <built-in function next>, > 'object': <class 'object'>, > 'oct': <built-in function oct>, > 'open': <built-in function open>, > 'ord': <built-in function ord>, > 'pow': <built-in function pow>, > 'print': <built-in function print>, > 'property': <class 'property'>, > 'quit': Use quit() or Ctrl-D (i.e. EOF) to exit, > 'range': <class 'range'>, > 'repr': <built-in function repr>, > 'reversed': <class 'reversed'>, > 'round': <built-in function round>, > 'set': <class 'set'>, > 'setattr': <built-in function setattr>, > 'slice': <class 'slice'>, > 'sorted': <built-in function sorted>, > 'staticmethod': <class 'staticmethod'>, > 'str': <class 'str'>, > 'sum': <built-in function sum>, > 'super': <class 'super'>, > 'tuple': <class 'tuple'>, > 'type': <class 'type'>, > 'vars': <built-in function vars>, > 'zip': <class 'zip'>}, > '__cached__': '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__pycache__/__init__.cpython-312.pyc', > '__doc__': '\n' > 'Path Pie\n' > '\n' > 'Implements ``path.Path`` - An object representing a\n' > 'path to a file or directory.\n' > '\n' > 'Example::\n' > '\n' > ' from path import Path\n' > " d = Path('/home/guido/bin')\n" > '\n' > ' # Globbing\n' > " for f in d.files('*.py'):\n" > ' f.chmod(0o755)\n' > '\n' > ' # Changing the working directory:\n' > ' with Path("somewhere"):\n' > ' # cwd in now `somewhere`\n' > ' ...\n' > '\n' > ' # Concatenate paths with /\n' > ' foo_txt = Path("bar") / "foo.txt"\n', > '__file__': '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py', > '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f01aa694230>, > '__name__': 'path', > '__package__': 'path', > '__path__': ['/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path'], > '__pytest_asyncio_package_scoped_event_loop': <function pytest_collectstart.<locals>.scoped_event_loop at 0x7f01aa84dc60>, > '__pytest_asyncio_scoped_event_loop': <function pytest_collectstart.<locals>.scoped_event_loop at 0x7f01aa84e200>, > '__spec__': ModuleSpec(name='path', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7f01aa694230>, origin='/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py', submodule_search_locations=['/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path']), > '_default_linesep': <object object at 0x7f01aad185e0>, > '_make_timestamp_ns': <function _make_timestamp_ns at 0x7f01aa845ee0>, > '_strip_newlines': <function _strip_newlines at 0x7f01b0b88220>, > 'annotations': _Feature((3, 7, 0, 'beta', 1), None, 16777216), > 'builtins': <module 'builtins' (built-in)>, > 'classes': <module 'path.classes' from '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/classes.py'>, > 'compat': <module 'path.compat' (namespace) from ['/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/compat']>, > 'contextlib': <module 'contextlib' from '/usr/lib/python3.12/contextlib.py'>, > 'datetime': <module 'datetime' from '/usr/lib/python3.12/datetime.py'>, > 'errno': <module 'errno' (built-in)>, > 'fnmatch': <module 'fnmatch' from '/usr/lib/python3.12/fnmatch.py'>, > 'functools': <module 'functools' from '/usr/lib/python3.12/functools.py'>, > 'glob': <module 'glob' from '/usr/lib/python3.12/glob.py'>, > 'grp': <module 'grp' from '/usr/lib/python3.12/lib-dynload/grp.cpython-312-x86_64-linux-gnu.so'>, > 'hashlib': <module 'hashlib' from '/usr/lib/python3.12/hashlib.py'>, > 'importlib': <module 'importlib' from '/usr/lib/python3.12/importlib/__init__.py'>, > 'itertools': <module 'itertools' (built-in)>, > 'masks': <module 'path.masks' from '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/masks.py'>, > 'matchers': <module 'path.matchers' from '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/matchers.py'>, > 'only_newer': <function only_newer at 0x7f01aa84f9c0>, > 'os': <module 'os' (frozen)>, > 'overload': <function overload at 0x7f01b06491c0>, > 'pathlib': <module 'pathlib' from '/usr/lib/python3.12/pathlib.py'>, > 'pwd': <module 'pwd' (built-in)>, > 're': <module 're' from '/usr/lib/python3.12/re/__init__.py'>, > 'removeprefix': <function removeprefix at 0x7f01aa84f880>, > 'removesuffix': <function removesuffix at 0x7f01aa84f420>, > 'shutil': <module 'shutil' from '/usr/lib/python3.12/shutil.py'>, > 'sys': <module 'sys' (built-in)>, > 'tempfile': <module 'tempfile' from '/usr/lib/python3.12/tempfile.py'>, > 'warnings': <module 'warnings' from '/usr/lib/python3.12/warnings.py'>} > module = <module 'path' from '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py'> > name = 'path.Path.open' > obj = <function Path.open at 0x7f01aa6a9940> > seen = {93856939061456: 1, > 93856939078192: 1, > 93856939150480: 1, > 139645130706752: 1, > 139645130712032: 1, > 139645130713552: 1, > 139645130714352: 1, > 139645130715952: 1, > 139645130717232: 1, > 139645130801216: 1, > 139645130801376: 1, > 139645130801536: 1, > 139645130801696: 1, > 139645130801856: 1, > 139645130802016: 1, > 139645130802176: 1, > 139645130802336: 1, > 139645130802496: 1, > 139645130802656: 1, > 139645130802816: 1, > 139645130802976: 1, > 139645130803136: 1, > 139645130803296: 1, > 139645130803616: 1, > 139645130803936: 1, > 139645130804256: 1, > 139645130804416: 1, > 139645130804576: 1, > 139645130804736: 1, > 139645130804896: 1, > 139645130805216: 1, > 139645130805376: 1, > 139645130805536: 1, > 139645130805696: 1, > 139645130805856: 1, > 139645130806016: 1, > 139645130806176: 1, > 139645130806336: 1, > 139645130806496: 1, > 139645130806656: 1, > 139645130806816: 1, > 139645130806976: 1, > 139645130807136: 1, > 139645130807296: 1, > 139645130807456: 1, > 139645130807616: 1, > 139645131613008: 1, > 139645132496608: 1, > 139645132531456: 1, > 139645132536096: 1, > 139645132536416: 1, > 139645132536576: 1, > 139645132537216: 1, > 139645132537376: 1, > 139645132537536: 1, > 139645132537696: 1, > 139645236576800: 1} > self = <_pytest.doctest.DoctestModule.collect.<locals>.MockAwareDocTestFinder object at 0x7f01aa91be60> > source_lines = ['"""\n', > 'Path Pie\n', > '\n', > 'Implements ``path.Path`` - An object representing a\n', > 'path to a file or directory.\n', > '\n', > 'Example::\n', > '\n', > ' from path import Path\n', > " d = Path('/home/guido/bin')\n", > '\n', > ' # Globbing\n', > " for f in d.files('*.py'):\n", > ' f.chmod(0o755)\n', > '\n', > ' # Changing the working directory:\n', > ' with Path("somewhere"):\n', > ' # cwd in now `somewhere`\n', > ' ...\n', > '\n', > ' # Concatenate paths with /\n', > ' foo_txt = Path("bar") / "foo.txt"\n', > '"""\n', > '\n', > 'from __future__ import annotations\n', > '\n', > 'import builtins\n', > 'import contextlib\n', > 'import datetime\n', > 'import errno\n', > 'import fnmatch\n', > 'import functools\n', > 'import glob\n', > 'import hashlib\n', > 'import importlib\n', > 'import itertools\n', > 'import os\n', > 'import pathlib\n', > 'import re\n', > 'import shutil\n', > 'import sys\n', > 'import tempfile\n', > 'import warnings\n', > 'from numbers import Number\n', > '\n', > 'with contextlib.suppress(ImportError):\n', > ' import win32security\n', > '\n', > 'with contextlib.suppress(ImportError):\n', > ' import pwd\n', > '\n', > 'with contextlib.suppress(ImportError):\n', > ' import grp\n', > '\n', > 'from typing import (\n', > ' TYPE_CHECKING,\n', > ' Callable,\n', > ' Iterator,\n', > ' overload,\n', > ')\n', > '\n', > 'if TYPE_CHECKING:\n', > ' from _typeshed import (\n', > ' OpenBinaryMode,\n', > ' OpenTextMode,\n', > ' )\n', > '\n', > 'from . import classes, masks, matchers\n', > 'from .compat.py38 import removeprefix, removesuffix\n', > '\n', > "__all__ = ['Path', 'TempDir']\n", > '\n', > '\n', > "LINESEPS = ['\\r\\n', '\\r', '\\n']\n", > "U_LINESEPS = LINESEPS + ['\\u0085', '\\u2028', '\\u2029']\n", > "B_NEWLINE = re.compile('|'.join(LINESEPS).encode())\n", > "U_NEWLINE = re.compile('|'.join(U_LINESEPS))\n", > "B_NL_END = re.compile(B_NEWLINE.pattern + b'$')\n", > "U_NL_END = re.compile(U_NEWLINE.pattern + '$')\n", > '\n', > '_default_linesep = object()\n', > '\n', > '\n', > 'def _make_timestamp_ns(value: Number | datetime.datetime) -> Number:\n', > ' timestamp_s = value if isinstance(value, Number) else ' > 'value.timestamp()\n', > ' return int(timestamp_s * 10**9)\n', > '\n', > '\n', > 'class TreeWalkWarning(Warning):\n', > ' pass\n', > '\n', > '\n', > 'class Traversal:\n', > ' """\n', > ' Wrap a walk result to customize the traversal.\n', > '\n', > ' `follow` is a function that takes an item and returns\n', > ' True if that item should be followed and False otherwise.\n', > '\n', > ' For example, to avoid traversing into directories that\n', > ' begin with `.`:\n', > '\n', > " >>> traverse = Traversal(lambda dir: not dir.startswith('.'))\n", > " >>> items = list(traverse(Path('.').walk()))\n", > '\n', > ' Directories beginning with `.` will appear in the results, but\n', > ' their children will not.\n', > '\n', > ' >>> dot_dir = next(item for item in items if item.is_dir() and ' > "item.startswith('.'))\n", > ' >>> any(item.parent == dot_dir for item in items)\n', > ' False\n', > ' """\n', > '\n', > ' def __init__(self, follow):\n', > ' self.follow = follow\n', > '\n', > ' def __call__(self, walker):\n', > ' traverse = None\n', > ' while True:\n', > ' try:\n', > ' item = walker.send(traverse)\n', > ' except StopIteration:\n', > ' return\n', > ' yield item\n', > '\n', > ' traverse = functools.partial(self.follow, item)\n', > '\n', > '\n', > 'def _strip_newlines(lines):\n', > ' r"""\n', > " >>> list(_strip_newlines(['Hello World\\r\\n', 'foo']))\n", > " ['Hello World', 'foo']\n", > ' """\n', > " return (U_NL_END.sub('', line) for line in lines)\n", > '\n', > '\n', > 'class Path(str):\n', > ' """\n', > ' Represents a filesystem path.\n', > '\n', > ' For documentation on individual methods, consult their\n', > ' counterparts in :mod:`os.path`.\n', > '\n', > ' Some methods are additionally included from :mod:`shutil`.\n', > ' The functions are linked directly into the class namespace\n', > ' such that they will be bound to the Path instance. For example,\n', > ' ``Path(src).copy(target)`` is equivalent to\n', > ' ``shutil.copy(src, target)``. Therefore, when referencing\n', > ' the docs for these methods, assume `src` references `self`,\n', > ' the Path instance.\n', > ' """\n', > '\n', > ' module = os.path\n', > ' """ The path module to use for path operations.\n', > '\n', > ' .. seealso:: :mod:`os.path`\n', > ' """\n', > '\n', > " def __new__(cls, other='.'):\n", > ' return super().__new__(cls, other)\n', > '\n', > " def __init__(self, other='.'):\n", > ' if other is None:\n', > ' raise TypeError("Invalid initial value for path: None")\n', > ' with contextlib.suppress(AttributeError):\n', > ' self._validate()\n', > '\n', > ' @classmethod\n', > ' @functools.lru_cache\n', > ' def using_module(cls, module):\n', > " subclass_name = cls.__name__ + '_' + module.__name__\n", > ' bases = (cls,)\n', > " ns = {'module': module}\n", > ' return type(subclass_name, bases, ns)\n', > '\n', > ' @classes.ClassProperty\n', > ' @classmethod\n', > ' def _next_class(cls):\n', > ' """\n', > ' What class should be used to construct new instances from this ' > 'class\n', > ' """\n', > ' return cls\n', > '\n', > ' # --- Special Python methods.\n', > '\n', > ' def __repr__(self):\n', > " return f'{type(self).__name__}({super().__repr__()})'\n", > '\n', > ' # Adding a Path and a string yields a Path.\n', > ' def __add__(self, more):\n', > ' return self._next_class(super().__add__(more))\n', > '\n', > ' def __radd__(self, other):\n', > ' return self._next_class(other.__add__(self))\n', > '\n', > ' # The / operator joins Paths.\n', > ' def __truediv__(self, rel):\n', > ' """fp.__truediv__(rel) == fp / rel == fp.joinpath(rel)\n', > '\n', > ' Join two path components, adding a separator character if\n', > ' needed.\n', > '\n', > ' .. seealso:: :func:`os.path.join`\n', > ' """\n', > ' return self._next_class(self.module.join(self, rel))\n', > '\n', > ' # The / operator joins Paths the other way around\n', > ' def __rtruediv__(self, rel):\n', > ' """fp.__rtruediv__(rel) == rel / fp\n', > '\n', > ' Join two path components, adding a separator character if\n', > ' needed.\n', > '\n', > ' .. seealso:: :func:`os.path.join`\n', > ' """\n', > ' return self._next_class(self.module.join(rel, self))\n', > '\n', > ' def __enter__(self):\n', > ' self._old_dir = self.cwd()\n', > ' os.chdir(self)\n', > ' return self\n', > '\n', > ' def __exit__(self, *_):\n', > ' os.chdir(self._old_dir)\n', > '\n', > ' @classmethod\n', > ' def cwd(cls):\n', > ' """Return the current working directory as a path object.\n', > '\n', > ' .. seealso:: :func:`os.getcwd`\n', > ' """\n', > ' return cls(os.getcwd())\n', > '\n', > ' @classmethod\n', > ' def home(cls) -> Path:\n', > " return cls(os.path.expanduser('~'))\n", > '\n', > ' #\n', > ' # --- Operations on Path strings.\n', > '\n', > ' def absolute(self):\n', > ' """.. seealso:: :func:`os.path.abspath`"""\n', > ' return self._next_class(self.module.abspath(self))\n', > '\n', > ' def normcase(self):\n', > ' """.. seealso:: :func:`os.path.normcase`"""\n', > ' return self._next_class(self.module.normcase(self))\n', > '\n', > ' def normpath(self):\n', > ' """.. seealso:: :func:`os.path.normpath`"""\n', > ' return self._next_class(self.module.normpath(self))\n', > '\n', > ' def realpath(self):\n', > ' """.. seealso:: :func:`os.path.realpath`"""\n', > ' return self._next_class(self.module.realpath(self))\n', > '\n', > ' def expanduser(self):\n', > ' """.. seealso:: :func:`os.path.expanduser`"""\n', > ' return self._next_class(self.module.expanduser(self))\n', > '\n', > ' def expandvars(self):\n', > ' """.. seealso:: :func:`os.path.expandvars`"""\n', > ' return self._next_class(self.module.expandvars(self))\n', > '\n', > ' def dirname(self):\n', > ' """.. seealso:: :attr:`parent`, :func:`os.path.dirname`"""\n', > ' return self._next_class(self.module.dirname(self))\n', > '\n', > ' def basename(self):\n', > ' """.. seealso:: :attr:`name`, :func:`os.path.basename`"""\n', > ' return self._next_class(self.module.basename(self))\n', > '\n', > ' def expand(self):\n', > ' """Clean up a filename by calling :meth:`expandvars()`,\n', > ' :meth:`expanduser()`, and :meth:`normpath()` on it.\n', > '\n', > ' This is commonly everything needed to clean up a filename\n', > ' read from a configuration file, for example.\n', > ' """\n', > ' return self.expandvars().expanduser().normpath()\n', > '\n', > ' @property\n', > ' def stem(self):\n', > ' """The same as :meth:`name`, but with one file extension stripped ' > 'off.\n', > '\n', > " >>> Path('/home/guido/python.tar.gz').stem\n", > " 'python.tar'\n", > ' """\n', > ' base, ext = self.module.splitext(self.name)\n', > ' return base\n', > '\n', > ' def with_stem(self, stem):\n', > ' """Return a new path with the stem changed.\n', > '\n', > ' >>> Path(\'/home/guido/python.tar.gz\').with_stem("foo")\n', > " Path('/home/guido/foo.gz')\n", > ' """\n', > ' return self.with_name(stem + self.suffix)\n', > '\n', > ' @property\n', > ' def suffix(self):\n', > ' """The file extension, for example ``\'.py\'``."""\n', > ' f, suffix = self.module.splitext(self)\n', > ' return suffix\n', > '\n', > ' def with_suffix(self, suffix):\n', > ' """Return a new path with the file suffix changed (or added, if ' > 'none)\n', > '\n', > ' >>> Path(\'/home/guido/python.tar.gz\').with_suffix(".foo")\n', > " Path('/home/guido/python.tar.foo')\n", > '\n', > " >>> Path('python').with_suffix('.zip')\n", > " Path('python.zip')\n", > '\n', > " >>> Path('filename.ext').with_suffix('zip')\n", > ' Traceback (most recent call last):\n', > ' ...\n', > " ValueError: Invalid suffix 'zip'\n", > ' """\n', > " if not suffix.startswith('.'):\n", > ' raise ValueError(f"Invalid suffix {suffix!r}")\n', > '\n', > ' return self.stripext() + suffix\n', > '\n', > ' @property\n', > ' def drive(self):\n', > ' """The drive specifier, for example ``\'C:\'``.\n', > '\n', > " This is always empty on systems that don't use drive specifiers.\n", > ' """\n', > ' drive, r = self.module.splitdrive(self)\n', > ' return self._next_class(drive)\n', > '\n', > ' parent = property(\n', > ' dirname,\n', > ' None,\n', > ' None,\n', > ' """ This path\'s parent directory, as a new Path object.\n', > '\n', > ' For example,\n', > " ``Path('/usr/local/lib/libpython.so').parent ==\n", > " Path('/usr/local/lib')``\n", > '\n', > ' .. seealso:: :meth:`dirname`, :func:`os.path.dirname`\n', > ' """,\n', > ' )\n', > '\n', > ' name = property(\n', > ' basename,\n', > ' None,\n', > ' None,\n', > ' """ The name of this file or directory without the full path.\n', > '\n', > ' For example,\n', > " ``Path('/usr/local/lib/libpython.so').name == 'libpython.so'``\n", > '\n', > ' .. seealso:: :meth:`basename`, :func:`os.path.basename`\n', > ' """,\n', > ' )\n', > '\n', > ' def with_name(self, name):\n', > ' """Return a new path with the name changed.\n', > '\n', > ' >>> Path(\'/home/guido/python.tar.gz\').with_name("foo.zip")\n', > " Path('/home/guido/foo.zip')\n", > ' """\n', > ' return self._next_class(removesuffix(self, self.name) + name)\n', > '\n', > ' def splitpath(self):\n', > ' """Return two-tuple of ``.parent``, ``.name``.\n', > '\n', > ' .. seealso:: :attr:`parent`, :attr:`name`, :func:`os.path.split`\n', > ' """\n', > ' parent, child = self.module.split(self)\n', > ' return self._next_class(parent), child\n', > '\n', > ' def splitdrive(self):\n', > ' """Return two-tuple of ``.drive`` and rest without drive.\n', > '\n', > ' Split the drive specifier from this path. If there is\n', > ' no drive specifier, :samp:`{p.drive}` is empty, so the return ' > 'value\n', > " is simply ``(Path(''), p)``. This is always the case on Unix.\n", > '\n', > ' .. seealso:: :func:`os.path.splitdrive`\n', > ' """\n', > ' drive, rel = self.module.splitdrive(self)\n', > ' return self._next_class(drive), self._next_class(rel)\n', > '\n', > ' def splitext(self):\n', > ' """Return two-tuple of ``.stripext()`` and ``.ext``.\n', > '\n', > ' Split the filename extension from this path and return\n', > ' the two parts. Either part may be empty.\n', > '\n', > " The extension is everything from ``'.'`` to the end of the\n", > ' last path segment. This has the property that if\n', > ' ``(a, b) == p.splitext()``, then ``a + b == p``.\n', > '\n', > ' .. seealso:: :func:`os.path.splitext`\n', > ' """\n', > ' filename, ext = self.module.splitext(self)\n', > ' return self._next_class(filename), ext\n', > '\n', > ' def stripext(self):\n', > ' """Remove one file extension from the path.\n', > '\n', > " For example, ``Path('/home/guido/python.tar.gz').stripext()``\n", > " returns ``Path('/home/guido/python.tar')``.\n", > ' """\n', > ' return self.splitext()[0]\n', > '\n', > ' @classes.multimethod\n', > ' def joinpath(cls, first, *others):\n', > ' """\n', > ' Join first to zero or more :class:`Path` components,\n', > ' adding a separator character (:samp:`{first}.module.sep`)\n', > ' if needed. Returns a new instance of\n', > ' :samp:`{first}._next_class`.\n', > '\n', > ' .. seealso:: :func:`os.path.join`\n', > ' """\n', > ' return cls._next_class(cls.module.join(first, *others))\n', > '\n', > ' def splitall(self):\n', > ' r"""Return a list of the path components in this path.\n', > '\n', > ' The first item in the list will be a Path. Its value will be\n', > ' either :data:`os.curdir`, :data:`os.pardir`, empty, or the root\n', > " directory of this path (for example, ``'/'`` or ``'C:\\\\'``). " > 'The\n', > ' other items in the list will be strings.\n', > '\n', > ' ``Path.joinpath(*result)`` will yield the original path.\n', > '\n', > " >>> Path('/foo/bar/baz').splitall()\n", > " [Path('/'), 'foo', 'bar', 'baz']\n", > ' """\n', > ' return list(self._parts())\n', > '\n', > ' def parts(self):\n', > ' """\n', > " >>> Path('/foo/bar/baz').parts()\n", > " (Path('/'), 'foo', 'bar', 'baz')\n", > ' """\n', > ' return tuple(self._parts())\n', > '\n', > ' def _parts(self):\n', > ' return reversed(tuple(self._parts_iter()))\n', > '\n', > ' def _parts_iter(self):\n', > ' loc = self\n', > ' while loc != os.curdir and loc != os.pardir:\n', > ' prev = loc\n', > ' loc, child = prev.splitpath()\n', > ' if loc == prev:\n', > ' break\n', > ' yield child\n', > ' yield loc\n', > '\n', > " def relpath(self, start='.'):\n", > ' """Return this path as a relative path,\n', > ' based from `start`, which defaults to the current working ' > 'directory.\n', > ' """\n', > ' cwd = self._next_class(start)\n', > ' return cwd.relpathto(self)\n', > '\n', > ' def relpathto(self, dest):\n', > ' """Return a relative path from `self` to `dest`.\n', > '\n', > ' If there is no relative path from `self` to `dest`, for example if\n', > ' they reside on different drives in Windows, then this returns\n', > ' ``dest.absolute()``.\n', > ' """\n', > ' origin = self.absolute()\n', > ' dest = self._next_class(dest).absolute()\n', > '\n', > ' orig_list = origin.normcase().splitall()\n', > " # Don't normcase dest! We want to preserve the case.\n", > ' dest_list = dest.splitall()\n', > '\n', > ' if orig_list[0] != self.module.normcase(dest_list[0]):\n', > " # Can't get here from there.\n", > ' return dest\n', > '\n', > ' # Find the location where the two paths start to differ.\n', > ' i = 0\n', > ' for start_seg, dest_seg in zip(orig_list, dest_list):\n', > ' if start_seg != self.module.normcase(dest_seg):\n', > ' break\n', > ' i += 1\n', > '\n', > ' # Now i is the point where the two paths diverge.\n', > ' # Need a certain number of "os.pardir"s to work up\n', > ' # from the origin to the point of divergence.\n', > ' segments = [os.pardir] * (len(orig_list) - i)\n', > ' # Need to add the diverging part of dest_list.\n', > ' segments += dest_list[i:]\n', > ' if len(segments) == 0:\n', > ' # If they happen to be identical, use os.curdir.\n', > ' relpath = os.curdir\n', > ' else:\n', > ' relpath = self.module.join(*segments)\n', > ' return self._next_class(relpath)\n', > '\n', > ' # --- Listing, searching, walking, and matching\n', > '\n', > ' def iterdir(self, match=None):\n', > ' """Yields items in this directory.\n', > '\n', > ' Use :meth:`files` or :meth:`dirs` instead if you want a listing\n', > ' of just files or just subdirectories.\n', > '\n', > ' The elements of the list are Path objects.\n', > '\n', > ' With the optional `match` argument, a callable,\n', > ' only return items whose names match the given pattern.\n', > '\n', > ' .. seealso:: :meth:`files`, :meth:`dirs`\n', > ' """\n', > ' match = matchers.load(match)\n', > ' return filter(match, (self / child for child in os.listdir(self)))\n', > '\n', > ' def dirs(self, *args, **kwargs):\n', > ' """List of this directory\'s subdirectories.\n', > '\n', > ' The elements of the list are Path objects.\n', > ' This does not walk recursively into subdirectories\n', > ' (but see :meth:`walkdirs`).\n', > '\n', > ' Accepts parameters to :meth:`iterdir`.\n', > ' """\n', > ' return [p for p in self.iterdir(*args, **kwargs) if p.is_dir()]\n', > '\n', > ' def files(self, *args, **kwargs):\n', > ' """List of the files in self.\n', > '\n', > ' The elements of the list are Path objects.\n', > ' This does not walk into subdirectories (see :meth:`walkfiles`).\n', > '\n', > ' Accepts parameters to :meth:`iterdir`.\n', > ' """\n', > '\n', > ' return [p for p in self.iterdir(*args, **kwargs) if p.is_file()]\n', > '\n', > " def walk(self, match=None, errors='strict'):\n", > ' """Iterator over files and subdirs, recursively.\n', > '\n', > ' The iterator yields Path objects naming each child item of\n', > ' this directory and its descendants. This requires that\n', > ' ``D.is_dir()``.\n', > '\n', > ' This performs a depth-first traversal of the directory tree.\n', > ' Each directory is returned just before all its children.\n', > '\n', > ' The `errors=` keyword argument controls behavior when an\n', > " error occurs. The default is ``'strict'``, which causes an\n", > " exception. Other allowed values are ``'warn'`` (which\n", > " reports the error via :func:`warnings.warn()`), and ``'ignore'``.\n", > ' `errors` may also be an arbitrary callable taking a msg parameter.\n', > ' """\n', > '\n', > ' errors = Handlers._resolve(errors)\n', > ' match = matchers.load(match)\n', > '\n', > ' try:\n', > ' childList = self.iterdir()\n', > ' except Exception as exc:\n', > ' errors(f"Unable to list directory \'{self}\': {exc}")\n', > ' return\n', > '\n', > ' for child in childList:\n', > ' traverse = None\n', > ' if match(child):\n', > ' traverse = yield child\n', > ' traverse = traverse or child.is_dir\n', > ' try:\n', > ' do_traverse = traverse()\n', > ' except Exception as exc:\n', > ' errors(f"Unable to access \'{child}\': {exc}")\n', > ' continue\n', > '\n', > ' if do_traverse:\n', > ' yield from child.walk(errors=errors, match=match)\n', > '\n', > ' def walkdirs(self, *args, **kwargs):\n', > ' """Iterator over subdirs, recursively."""\n', > ' return (item for item in self.walk(*args, **kwargs) if ' > 'item.is_dir())\n', > '\n', > ' def walkfiles(self, *args, **kwargs):\n', > ' """Iterator over files, recursively."""\n', > ' return (item for item in self.walk(*args, **kwargs) if ' > 'item.is_file())\n', > '\n', > ' def fnmatch(self, pattern, normcase=None):\n', > ' """Return ``True`` if `self.name` matches the given `pattern`.\n', > '\n', > ' `pattern` - A filename pattern with wildcards,\n', > " for example ``'*.py'``. If the pattern contains a `normcase`\n", > ' attribute, it is applied to the name and path prior to ' > 'comparison.\n', > '\n', > ' `normcase` - (optional) A function used to normalize the pattern ' > 'and\n', > ' filename before matching. Defaults to normcase from\n', > ' ``self.module``, :func:`os.path.normcase`.\n', > '\n', > ' .. seealso:: :func:`fnmatch.fnmatch`\n', > ' """\n', > " default_normcase = getattr(pattern, 'normcase', " > 'self.module.normcase)\n', > ' normcase = normcase or default_normcase\n', > ' name = normcase(self.name)\n', > ' pattern = normcase(pattern)\n', > ' return fnmatch.fnmatchcase(name, pattern)\n', > '\n', > ' def glob(self, pattern):\n', > ' """Return a list of Path objects that match the pattern.\n', > '\n', > ' `pattern` - a path relative to this directory, with wildcards.\n', > '\n', > " For example, ``Path('/users').glob('*/bin/*')`` returns a list\n", > ' of all the files users have in their :file:`bin` directories.\n', > '\n', > ' .. seealso:: :func:`glob.glob`\n', > '\n', > ' .. note:: Glob is **not** recursive, even when using ``**``.\n', > ' To do recursive globbing see :func:`walk`,\n', > ' :func:`walkdirs` or :func:`walkfiles`.\n', > ' """\n', > ' cls = self._next_class\n', > ' return [cls(s) for s in glob.glob(self / pattern)]\n', > '\n', > ' def iglob(self, pattern):\n', > ' """Return an iterator of Path objects that match the pattern.\n', > '\n', > ' `pattern` - a path relative to this directory, with wildcards.\n', > '\n', > " For example, ``Path('/users').iglob('*/bin/*')`` returns an\n", > ' iterator of all the files users have in their :file:`bin`\n', > ' directories.\n', > '\n', > ' .. seealso:: :func:`glob.iglob`\n', > '\n', > ' .. note:: Glob is **not** recursive, even when using ``**``.\n', > ' To do recursive globbing see :func:`walk`,\n', > ' :func:`walkdirs` or :func:`walkfiles`.\n', > ' """\n', > ' cls = self._next_class\n', > ' return (cls(s) for s in glob.iglob(self / pattern))\n', > '\n', > ' #\n', > ' # --- Reading or writing an entire file at once.\n', > '\n', > ' @functools.wraps(open, assigned=())\n', > ' def open(self, *args, **kwargs):\n', > ' """Open this file and return a corresponding file object.\n', > '\n', > ' Keyword arguments work as in :func:`io.open`. If the file cannot ' > 'be\n', > ' opened, an :class:`OSError` is raised.\n', > ' """\n', > ' return open(self, *args, **kwargs)\n', > '\n', > ' def bytes(self):\n', > ' """Open this file, read all bytes, return them as a string."""\n', > " with self.open('rb') as f:\n", > ' return f.read()\n', > '\n', > ' @overload\n', > ' def chunks(\n', > ' self,\n', > ' size: int,\n', > ' mode: OpenTextMode = ...,\n', > ' buffering: int = ...,\n', > ' encoding: str | None = ...,\n', > ' errors: str | None = ...,\n', > ' newline: str | None = ...,\n', > ' closefd: bool = ...,\n', > ' opener: Callable[[str, int], int] | None = ...,\n', > ' ) -> Iterator[str]: ...\n', > '\n', > ' @overload\n', > ' def chunks(\n', > ' self,\n', > ' size: int,\n', > ' mode: OpenBinaryMode,\n', > ' buffering: int = ...,\n', > ' encoding: str | None = ...,\n', > ' errors: str | None = ...,\n', > ' newline: str | None = ...,\n', > ' closefd: bool = ...,\n', > ' opener: Callable[[str, int], int] | None = ...,\n', > ' ) -> Iterator[builtins.bytes]: ...\n', > '\n', > ' @overload\n', > ' def chunks(\n', > ' self,\n', > ' size: int,\n', > ' mode: str,\n', > ' buffering: int = ...,\n', > ' encoding: str | None = ...,\n', > ' errors: str | None = ...,\n', > ' newline: str | None = ...,\n', > ' closefd: bool = ...,\n', > ' opener: Callable[[str, int], int] | None = ...,\n', > ' ) -> Iterator[str | builtins.bytes]: ...\n', > '\n', > ' def chunks(self, size, *args, **kwargs):\n', > ' """Returns a generator yielding chunks of the file, so it can\n', > ' be read piece by piece with a simple for loop.\n', > '\n', > ' Any argument you pass after `size` will be passed to :meth:`open`.\n', > '\n', > ' :example:\n', > '\n', > ' >>> hash = hashlib.md5()\n', > ' >>> for chunk in Path("NEWS.rst").chunks(8192, mode=\'rb\'):\n', > ' ... hash.update(chunk)\n', > '\n', > ' This will read the file by chunks of 8192 bytes.\n', > ' """\n', > ' with self.open(*args, **kwargs) as f:\n', > ' yield from iter(lambda: f.read(size) or None, None)\n', > '\n', > ' def write_bytes(self, bytes, append=False):\n', > ' """Open this file and write the given bytes to it.\n', > '\n', > ' Default behavior is to overwrite any existing file.\n', > ' Call ``p.write_bytes(bytes, append=True)`` to append instead.\n', > ' """\n', > " with self.open('ab' if append else 'wb') as f:\n", > ' f.write(bytes)\n', > '\n', > ' def read_text(self, encoding=None, errors=None):\n', > ' r"""Open this file, read it in, return the content as a string.\n', > '\n', > ' Optional parameters are passed to :meth:`open`.\n', > '\n', > ' .. seealso:: :meth:`lines`\n', > ' """\n', > ' with self.open(encoding=encoding, errors=errors) as f:\n', > ' return f.read()\n', > '\n', > ' def read_bytes(self):\n', > ' r"""Return the contents of this file as bytes."""\n', > " with self.open(mode='rb') as f:\n", > ' return f.read()\n', > '\n', > ' def write_text(\n', > ' self,\n', > ' text: str,\n', > ' encoding: str | None = None,\n', > " errors: str = 'strict',\n", > ' linesep: str | None = os.linesep,\n', > ' append: bool = False,\n', > ' ) -> None:\n', > ' r"""Write the given text to this file.\n', > '\n', > ' The default behavior is to overwrite any existing file;\n', > ' to append instead, use the `append=True` keyword argument.\n', > '\n', > ' There are two differences between :meth:`write_text` and\n', > ' :meth:`write_bytes`: newline handling and Unicode handling.\n', > ' See below.\n', > '\n', > ' Parameters:\n', > '\n', > ' `text` - str - The text to be written.\n', > '\n', > ' `encoding` - str - The text encoding used.\n', > '\n', > ' `errors` - str - How to handle Unicode encoding errors.\n', > " Default is ``'strict'``. See ``help(unicode.encode)`` for " > 'the\n', > " options. Ignored if `text` isn't a Unicode string.\n", > '\n', > ' `linesep` - keyword argument - str/unicode - The sequence of\n', > ' characters to be used to mark end-of-line. The default is\n', > ' :data:`os.linesep`. Specify ``None`` to\n', > ' use newlines unmodified.\n', > '\n', > ' `append` - keyword argument - bool - Specifies what to do if\n', > ' the file already exists (``True``: append to the end of it;\n', > ' ``False``: overwrite it). The default is ``False``.\n', > '\n', > '\n', > ' --- Newline handling.\n', > '\n', > ' ``write_text()`` converts all standard end-of-line sequences\n', > " (``'\\n'``, ``'\\r'``, and ``'\\r\\n'``) to your platform's " > 'default\n', > ' end-of-line sequence (see :data:`os.linesep`; on Windows, for ' > 'example,\n', > " the end-of-line marker is ``'\\r\\n'``).\n", > '\n', > " To override the platform's default, pass the `linesep=`\n", > ' keyword argument. To preserve the newlines as-is, pass\n', > ' ``linesep=None``.\n', > '\n', > ' This handling applies to Unicode text and bytes, except\n', > ' with Unicode, additional non-ASCII newlines are recognized:\n', > ' ``\\x85``, ``\\r\\x85``, and ``\\u2028``.\n', > '\n', > ' --- Unicode\n', > '\n', > ' `text` is written using the\n', > ' specified `encoding` (or the default encoding if `encoding`\n', > " isn't specified). The `errors` argument applies only to this\n", > ' conversion.\n', > ' """\n', > ' if linesep is not None:\n', > ' text = U_NEWLINE.sub(linesep, text)\n', > ' bytes = text.encode(encoding or sys.getdefaultencoding(), errors)\n', > ' self.write_bytes(bytes, append=append)\n', > '\n', > ' def lines(self, encoding=None, errors=None, retain=True):\n', > ' r"""Open this file, read all lines, return them in a list.\n', > '\n', > ' Optional arguments:\n', > ' `encoding` - The Unicode encoding (or character set) of\n', > ' the file. The default is ``None``, meaning use\n', > ' ``locale.getpreferredencoding()``.\n', > ' `errors` - How to handle Unicode errors; see\n', > ' `open ' > '<https://docs.python.org/3/library/functions.html#open>`_\n', > ' for the options. Default is ``None`` meaning "strict".\n', > ' `retain` - If ``True`` (default), retain newline characters,\n', > ' but translate all newline\n', > ' characters to ``\\n``. If ``False``, newline characters ' > 'are\n', > ' omitted.\n', > ' """\n', > " text = U_NEWLINE.sub('\\n', self.read_text(encoding, errors))\n", > ' return text.splitlines(retain)\n', > '\n', > ' def write_lines(\n', > ' self,\n', > ' lines,\n', > ' encoding=None,\n', > " errors='strict',\n", > ' *,\n', > ' append=False,\n', > ' ):\n', > ' r"""Write the given lines of text to this file.\n', > '\n', > ' By default this overwrites any existing file at this path.\n', > '\n', > ' Puts a platform-specific newline sequence on every line.\n', > '\n', > ' `lines` - A list of strings.\n', > '\n', > ' `encoding` - A Unicode encoding to use. This applies only if\n', > ' `lines` contains any Unicode strings.\n', > '\n', > ' `errors` - How to handle errors in Unicode encoding. This\n', > ' also applies only to Unicode strings.\n', > '\n', > ' Use the keyword argument ``append=True`` to append lines to the\n', > ' file. The default is to overwrite the file.\n', > ' """\n', > " mode = 'a' if append else 'w'\n", > " with self.open(mode, encoding=encoding, errors=errors, newline='') " > 'as f:\n', > ' f.writelines(self._replace_linesep(lines))\n', > '\n', > ' @staticmethod\n', > ' def _replace_linesep(lines):\n', > ' return (line + os.linesep for line in _strip_newlines(lines))\n', > '\n', > ' def read_md5(self):\n', > ' """Calculate the md5 hash for this file.\n', > '\n', > ' This reads through the entire file.\n', > '\n', > ' .. seealso:: :meth:`read_hash`\n', > ' """\n', > " return self.read_hash('md5')\n", > '\n', > ' def _hash(self, hash_name):\n', > ' """Returns a hash object for the file at the current path.\n', > '\n', > " `hash_name` should be a hash algo name (such as ``'md5'``\n", > " or ``'sha1'``) that's available in the :mod:`hashlib` module.\n", > ' """\n', > ' m = hashlib.new(hash_name)\n', > ' for chunk in self.chunks(8192, mode="rb"):\n', > ' m.update(chunk)\n', > ' return m\n', > '\n', > ' def read_hash(self, hash_name):\n', > ' """Calculate given hash for this file.\n', > '\n', > ' List of supported hashes can be obtained from :mod:`hashlib` ' > 'package.\n', > ' This reads the entire file.\n', > '\n', > ' .. seealso:: :meth:`hashlib.hash.digest`\n', > ' """\n', > ' return self._hash(hash_name).digest()\n', > '\n', > ' def read_hexhash(self, hash_name):\n', > ' """Calculate given hash for this file, returning hexdigest.\n', > '\n', > ' List of supported hashes can be obtained from :mod:`hashlib` ' > 'package.\n', > ' This reads the entire file.\n', > '\n', > ' .. seealso:: :meth:`hashlib.hash.hexdigest`\n', > ' """\n', > ' return self._hash(hash_name).hexdigest()\n', > '\n', > ' # --- Methods for querying the filesystem.\n', > ' # N.B. On some platforms, the os.path functions may be implemented in ' > 'C\n', > " # (e.g. isdir on Windows, Python 3.2.2), and compiled functions don't " > 'get\n', > ' # bound. Playing it safe and wrapping them all in method calls.\n', > '\n', > ' def isabs(self):\n', > ' """\n', > " >>> Path('.').isabs()\n", > ' False\n', > '\n', > ' .. seealso:: :func:`os.path.isabs`\n', > ' """\n', > ' return self.module.isabs(self)\n', > '\n', > ' def exists(self):\n', > ' """.. seealso:: :func:`os.path.exists`"""\n', > ' return self.module.exists(self)\n', > '\n', > ' def is_dir(self):\n', > ' """.. seealso:: :func:`os.path.isdir`"""\n', > ' return self.module.isdir(self)\n', > '\n', > ' def is_file(self):\n', > ' """.. seealso:: :func:`os.path.isfile`"""\n', > ' return self.module.isfile(self)\n', > '\n', > ' def islink(self):\n', > ' """.. seealso:: :func:`os.path.islink`"""\n', > ' return self.module.islink(self)\n', > '\n', > ' def ismount(self):\n', > ' """\n', > " >>> Path('.').ismount()\n", > ' False\n', > '\n', > ' .. seealso:: :func:`os.path.ismount`\n', > ' """\n', > ' return self.module.ismount(self)\n', > '\n', > ' def samefile(self, other):\n', > ' """.. seealso:: :func:`os.path.samefile`"""\n', > ' return self.module.samefile(self, other)\n', > '\n', > ' def getatime(self):\n', > ' """.. seealso:: :attr:`atime`, :func:`os.path.getatime`"""\n', > ' return self.module.getatime(self)\n', > '\n', > ' def set_atime(self, value):\n', > ' mtime_ns = self.stat().st_atime_ns\n', > ' self.utime(ns=(_make_timestamp_ns(value), mtime_ns))\n', > '\n', > ' atime = property(\n', > ' getatime,\n', > ' set_atime,\n', > ' None,\n', > ' """\n', > ' Last access time of the file.\n', > '\n', > " >>> Path('.').atime > 0\n", > ' True\n', > '\n', > ' Allows setting:\n', > '\n', > ' >>> some_file = ' > "Path(getfixture('tmp_path')).joinpath('file.txt').touch()\n", > ' >>> MST = datetime.timezone(datetime.timedelta(hours=-7))\n', > ' >>> some_file.atime = datetime.datetime(1976, 5, 7, 10, ' > 'tzinfo=MST)\n', > ' >>> some_file.atime\n', > ' 200336400.0\n', > '\n', > ' .. seealso:: :meth:`getatime`, :func:`os.path.getatime`\n', > ' """,\n', > ' )\n', > '\n', > ' def getmtime(self):\n', > ' """.. seealso:: :attr:`mtime`, :func:`os.path.getmtime`"""\n', > ' return self.module.getmtime(self)\n', > '\n', > ' def set_mtime(self, value):\n', > ' atime_ns = self.stat().st_atime_ns\n', > ' self.utime(ns=(atime_ns, _make_timestamp_ns(value)))\n', > '\n', > ' mtime = property(\n', > ' getmtime,\n', > ' set_mtime,\n', > ' None,\n', > ' """\n', > ' Last modified time of the file.\n', > '\n', > ' Allows setting:\n', > '\n', > ' >>> some_file = ' > "Path(getfixture('tmp_path')).joinpath('file.txt').touch()\n", > ' >>> MST = datetime.timezone(datetime.timedelta(hours=-7))\n', > ' >>> some_file.mtime = datetime.datetime(1976, 5, 7, 10, ' > 'tzinfo=MST)\n', > ' >>> some_file.mtime\n', > ' 200336400.0\n', > '\n', > ' .. seealso:: :meth:`getmtime`, :func:`os.path.getmtime`\n', > ' """,\n', > ' )\n', > '\n', > ' def getctime(self):\n', > ' """.. seealso:: :attr:`ctime`, :func:`os.path.getctime`"""\n', > ' return self.module.getctime(self)\n', > '\n', > ' ctime = property(\n', > ' getctime,\n', > ' None,\n', > ' None,\n', > ' """ Creation time of the file.\n', > '\n', > ' .. seealso:: :meth:`getctime`, :func:`os.path.getctime`\n', > ' """,\n', > ' )\n', > '\n', > ' def getsize(self):\n', > ' """.. seealso:: :attr:`size`, :func:`os.path.getsize`"""\n', > ' return self.module.getsize(self)\n', > '\n', > ' size = property(\n', > ' getsize,\n', > ' None,\n', > ' None,\n', > ' """ Size of the file, in bytes.\n', > '\n', > ' .. seealso:: :meth:`getsize`, :func:`os.path.getsize`\n', > ' """,\n', > ' )\n', > '\n', > ' @property\n', > ' def permissions(self) -> masks.Permissions:\n', > ' """\n', > ' Permissions.\n', > '\n', > " >>> perms = Path('.').permissions\n", > ' >>> isinstance(perms, int)\n', > ' True\n', > " >>> set(perms.symbolic) <= set('rwx-')\n", > ' True\n', > ' >>> perms.symbolic\n', > " 'r...'\n", > ' """\n', > ' return masks.Permissions(self.stat().st_mode)\n', > '\n', > ' def access(self, *args, **kwargs):\n', > ' """\n', > ' Return does the real user have access to this path.\n', > '\n', > " >>> Path('.').access(os.F_OK)\n", > ' True\n', > '\n', > ' .. seealso:: :func:`os.access`\n', > ' """\n', > ' return os.access(self, *args, **kwargs)\n', > '\n', > ' def stat(self, *, follow_symlinks=True):\n', > ' """\n', > ' Perform a ``stat()`` system call on this path.\n', > '\n', > " >>> Path('.').stat()\n", > ' os.stat_result(...)\n', > '\n', > ' .. seealso:: :meth:`lstat`, :func:`os.stat`\n', > ' """\n', > ' return os.stat(self, follow_symlinks=follow_symlinks)\n', > '\n', > ' def lstat(self):\n', > ' """\n', > ' Like :meth:`stat`, but do not follow symbolic links.\n', > '\n', > " >>> Path('.').lstat() == Path('.').stat()\n", > ' True\n', > '\n', > ' .. seealso:: :meth:`stat`, :func:`os.lstat`\n', > ' """\n', > ' return os.lstat(self)\n', > '\n', > ' def __get_owner_windows(self): # pragma: nocover\n', > ' r"""\n', > ' Return the name of the owner of this file or directory. Follow\n', > ' symbolic links.\n', > '\n', > ' Return a name of the form ``DOMAIN\\User Name``; may be a group.\n', > '\n', > ' .. seealso:: :attr:`owner`\n', > ' """\n', > ' desc = win32security.GetFileSecurity(\n', > ' self, win32security.OWNER_SECURITY_INFORMATION\n', > ' )\n', > ' sid = desc.GetSecurityDescriptorOwner()\n', > ' account, domain, typecode = win32security.LookupAccountSid(None, ' > 'sid)\n', > " return domain + '\\\\' + account\n", > '\n', > ' def __get_owner_unix(self): # pragma: nocover\n', > ' """\n', > ' Return the name of the owner of this file or directory. Follow\n', > ' symbolic links.\n', > '\n', > ' .. seealso:: :attr:`owner`\n', > ' """\n', > ' st = self.stat()\n', > ' return pwd.getpwuid(st.st_uid).pw_name\n', > '\n', > ' def __get_owner_not_implemented(self): # pragma: nocover\n', > ' raise NotImplementedError("Ownership not available on this ' > 'platform.")\n', > '\n', > ' get_owner = (\n', > ' __get_owner_windows\n', > " if 'win32security' in globals()\n", > ' else __get_owner_unix\n', > " if 'pwd' in globals()\n", > ' else __get_owner_not_implemented\n', > ' )\n', > '\n', > ' owner = property(\n', > ' get_owner,\n', > ' None,\n', > ' None,\n', > ' """ Name of the owner of this file or directory.\n', > '\n', > ' .. seealso:: :meth:`get_owner`""",\n', > ' )\n', > '\n', > " if 'grp' in globals(): # pragma: no cover\n", > '\n', > ' def group(self, *, follow_symlinks=True):\n', > ' """\n', > ' Return the group name of the file gid.\n', > ' """\n', > ' gid = self.stat(follow_symlinks=follow_symlinks).st_gid\n', > ' return grp.getgrgid(gid).gr_name\n', > '\n', > " if hasattr(os, 'statvfs'):\n", > '\n', > ' def statvfs(self):\n', > ' """Perform a ``statvfs()`` system call on this path.\n', > '\n', > ' .. seealso:: :func:`os.statvfs`\n', > ' """\n', > ' return os.statvfs(self)\n', > '\n', > " if hasattr(os, 'pathconf'):\n", > '\n', > ' def pathconf(self, name):\n', > ' """.. seealso:: :func:`os.pathconf`"""\n', > ' return os.pathconf(self, name)\n', > '\n', > ' #\n', > ' # --- Modifying operations on files and directories\n', > '\n', > ' def utime(self, *args, **kwargs):\n', > ' """Set the access and modified times of this file.\n', > '\n', > ' .. seealso:: :func:`os.utime`\n', > ' """\n', > ' os.utime(self, *args, **kwargs)\n', > ' return self\n', > '\n', > ' def chmod(self, mode):\n', > ' """\n', > ' Set the mode. May be the new mode (os.chmod behavior) or a ' > '`symbolic\n', > ' mode <http://en.wikipedia.org/wiki/Chmod#Symbolic_modes>`_.\n', > '\n', > ' >>> a_file = ' > "Path(getfixture('tmp_path')).joinpath('afile.txt').touch()\n", > ' >>> a_file.chmod(0o700)\n', > ' Path(...\n', > " >>> a_file.chmod('u+x')\n", > ' Path(...\n', > '\n', > ' .. seealso:: :func:`os.chmod`\n', > ' """\n', > ' if isinstance(mode, str):\n', > ' mask = masks.compound(mode)\n', > ' mode = mask(self.stat().st_mode)\n', > ' os.chmod(self, mode)\n', > ' return self\n', > '\n', > " if hasattr(os, 'chown'):\n", > '\n', > ' def chown(self, uid=-1, gid=-1):\n', > ' """\n', > ' Change the owner and group by names or numbers.\n', > '\n', > ' .. seealso:: :func:`os.chown`\n', > ' """\n', > '\n', > ' def resolve_uid(uid):\n', > ' return uid if isinstance(uid, int) else ' > 'pwd.getpwnam(uid).pw_uid\n', > '\n', > ' def resolve_gid(gid):\n', > ' return gid if isinstance(gid, int) else ' > 'grp.getgrnam(gid).gr_gid\n', > '\n', > ' os.chown(self, resolve_uid(uid), resolve_gid(gid))\n', > ' return self\n', > '\n', > ' def rename(self, new):\n', > ' """.. seealso:: :func:`os.rename`"""\n', > ' os.rename(self, new)\n', > ' return self._next_class(new)\n', > '\n', > ' def renames(self, new):\n', > ' """.. seealso:: :func:`os.renames`"""\n', > ' os.renames(self, new)\n', > ' return self._next_class(new)\n', > '\n', > ' def replace(self, target_or_old: Path | str, *args) -> Path:\n', > ' """\n', > ' Replace a path or substitute substrings.\n', > '\n', > ' Implements both pathlib.Path.replace and str.replace.\n', > '\n', > ' If only a target is supplied, rename this path to the target path,\n', > ' overwriting if that path exists.\n', > '\n', > " >>> dest = Path(getfixture('tmp_path'))\n", > " >>> orig = dest.joinpath('foo').touch()\n", > " >>> new = orig.replace(dest.joinpath('fee'))\n", > ' >>> orig.exists()\n', > ' False\n', > ' >>> new.exists()\n', > ' True\n', > '\n', > ' ..seealso:: :meth:`pathlib.Path.replace`\n', > '\n', > ' If a second parameter is supplied, perform a textual replacement.\n', > '\n', > " >>> Path('foo').replace('o', 'e')\n", > " Path('fee')\n", > " >>> Path('foo').replace('o', 'l', 1)\n", > " Path('flo')\n", > '\n', > ' ..seealso:: :meth:`str.replace`\n', > ' """\n', > ' return self._next_class(\n', > ' super().replace(target_or_old, *args)\n', > ' if args\n', > ' else pathlib.Path(self).replace(target_or_old)\n', > ' )\n', > '\n', > ' #\n', > ' # --- Create/delete operations on directories\n', > '\n', > ' def mkdir(self, mode=0o777):\n', > ' """.. seealso:: :func:`os.mkdir`"""\n', > ' os.mkdir(self, mode)\n', > ' return self\n', > '\n', > ' def mkdir_p(self, mode=0o777):\n', > ' """Like :meth:`mkdir`, but does not raise an exception if the\n', > ' directory already exists."""\n', > ' with contextlib.suppress(FileExistsError):\n', > ' self.mkdir(mode)\n', > ' return self\n', > '\n', > ' def makedirs(self, mode=0o777):\n', > ' """.. seealso:: :func:`os.makedirs`"""\n', > ' os.makedirs(self, mode)\n', > ' return self\n', > '\n', > ' def makedirs_p(self, mode=0o777):\n', > ' """Like :meth:`makedirs`, but does not raise an exception if the\n', > ' directory already exists."""\n', > ' with contextlib.suppress(FileExistsError):\n', > ' self.makedirs(mode)\n', > ' return self\n', > '\n', > ' def rmdir(self):\n', > ' """.. seealso:: :func:`os.rmdir`"""\n', > ' os.rmdir(self)\n', > ' return self\n', > '\n', > ' def rmdir_p(self):\n', > ' """Like :meth:`rmdir`, but does not raise an exception if the\n', > ' directory is not empty or does not exist."""\n', > ' suppressed = FileNotFoundError, FileExistsError, DirectoryNotEmpty\n', > ' with contextlib.suppress(suppressed):\n', > ' with DirectoryNotEmpty.translate():\n', > ' self.rmdir()\n', > ' return self\n', > '\n', > ' def removedirs(self):\n', > ' """.. seealso:: :func:`os.removedirs`"""\n', > ' os.removedirs(self)\n', > ' return self\n', > '\n', > ' def removedirs_p(self):\n', > ' """Like :meth:`removedirs`, but does not raise an exception if the\n', > ' directory is not empty or does not exist."""\n', > ' with contextlib.suppress(FileExistsError, DirectoryNotEmpty):\n', > ' with DirectoryNotEmpty.translate():\n', > ' self.removedirs()\n', > ' return self\n', > '\n', > ' # --- Modifying operations on files\n', > '\n', > ' def touch(self):\n', > ' """Set the access/modified times of this file to the current time.\n', > ' Create the file if it does not exist.\n', > ' """\n', > ' os.close(os.open(self, os.O_WRONLY | os.O_CREAT, 0o666))\n', > ' os.utime(self, None)\n', > ' return self\n', > '\n', > ' def remove(self):\n', > ' """.. seealso:: :func:`os.remove`"""\n', > ' os.remove(self)\n', > ' return self\n', > '\n', > ' def remove_p(self):\n', > ' """Like :meth:`remove`, but does not raise an exception if the\n', > ' file does not exist."""\n', > ' with contextlib.suppress(FileNotFoundError):\n', > ' self.unlink()\n', > ' return self\n', > '\n', > ' unlink = remove\n', > ' unlink_p = remove_p\n', > '\n', > ' # --- Links\n', > '\n', > ' def hardlink_to(self, target: str) -> None:\n', > ' """\n', > ' Create a hard link at self, pointing to target.\n', > '\n', > ' .. seealso:: :func:`os.link`\n', > ' """\n', > ' os.link(target, self)\n', > '\n', > ' def link(self, newpath):\n', > ' """Create a hard link at `newpath`, pointing to this file.\n', > '\n', > ' .. seealso:: :func:`os.link`\n', > ' """\n', > ' os.link(self, newpath)\n', > ' return self._next_class(newpath)\n', > '\n', > ' def symlink_to(self, target: str, target_is_directory: bool = False) -> ' > 'None:\n', > ' """\n', > ' Create a symbolic link at self, pointing to target.\n', > '\n', > ' .. seealso:: :func:`os.symlink`\n', > ' """\n', > ' os.symlink(target, self, target_is_directory)\n', > '\n', > ' def symlink(self, newlink=None):\n', > ' """Create a symbolic link at `newlink`, pointing here.\n', > '\n', > ' If newlink is not supplied, the symbolic link will assume\n', > ' the name self.basename(), creating the link in the cwd.\n', > '\n', > ' .. seealso:: :func:`os.symlink`\n', > ' """\n', > ' if newlink is None:\n', > ' newlink = self.basename()\n', > ' os.symlink(self, newlink)\n', > ' return self._next_class(newlink)\n', > '\n', > ' def readlink(self):\n', > ' """Return the path to which this symbolic link points.\n', > '\n', > ' The result may be an absolute or a relative path.\n', > '\n', > ' .. seealso:: :meth:`readlinkabs`, :func:`os.readlink`\n', > ' """\n', > ' return self._next_class(removeprefix(os.readlink(self), ' > "'\\\\\\\\?\\\\'))\n", > '\n', > ' def readlinkabs(self):\n', > ' """Return the path to which this symbolic link points.\n', > '\n', > ' The result is always an absolute path.\n', > '\n', > ' .. seealso:: :meth:`readlink`, :func:`os.readlink`\n', > ' """\n', > ' p = self.readlink()\n', > ' return p if p.isabs() else (self.parent / p).absolute()\n', > '\n', > ' # High-level functions from shutil\n', > ' # These functions will be bound to the instance such that\n', > ' # Path(name).copy(target) will invoke shutil.copy(name, target)\n', > '\n', > ' copyfile = shutil.copyfile\n', > ' copymode = shutil.copymode\n', > ' copystat = shutil.copystat\n', > ' copy = shutil.copy\n', > ' copy2 = shutil.copy2\n', > ' copytree = shutil.copytree\n', > " if hasattr(shutil, 'move'):\n", > ' move = shutil.move\n', > ' rmtree = shutil.rmtree\n', > '\n', > ' def rmtree_p(self):\n', > ' """Like :meth:`rmtree`, but does not raise an exception if the\n', > ' directory does not exist."""\n', > ' with contextlib.suppress(FileNotFoundError):\n', > ' self.rmtree()\n', > ' return self\n', > '\n', > ' def chdir(self):\n', > ' """.. seealso:: :func:`os.chdir`"""\n', > ' os.chdir(self)\n', > '\n', > ' cd = chdir\n', > '\n', > ' def merge_tree(\n', > ' self,\n', > ' dst,\n', > ' symlinks=False,\n', > ' *,\n', > ' copy_function=shutil.copy2,\n', > ' ignore=lambda dir, contents: [],\n', > ' ):\n', > ' """\n', > ' Copy entire contents of self to dst, overwriting existing\n', > ' contents in dst with those in self.\n', > '\n', > ' Pass ``symlinks=True`` to copy symbolic links as links.\n', > '\n', > ' Accepts a ``copy_function``, similar to copytree.\n', > '\n', > ' To avoid overwriting newer files, supply a copy function\n', > ' wrapped in ``only_newer``. For example::\n', > '\n', > ' src.merge_tree(dst, copy_function=only_newer(shutil.copy2))\n', > ' """\n', > ' dst = self._next_class(dst)\n', > ' dst.makedirs_p()\n', > '\n', > ' sources = list(self.iterdir())\n', > ' _ignored = ignore(self, [item.name for item in sources])\n', > '\n', > ' def ignored(item):\n', > ' return item.name in _ignored\n', > '\n', > ' for source in itertools.filterfalse(ignored, sources):\n', > ' dest = dst / source.name\n', > ' if symlinks and source.islink():\n', > ' target = source.readlink()\n', > ' target.symlink(dest)\n', > ' elif source.is_dir():\n', > ' source.merge_tree(\n', > ' dest,\n', > ' symlinks=symlinks,\n', > ' copy_function=copy_function,\n', > ' ignore=ignore,\n', > ' )\n', > ' else:\n', > ' copy_function(source, dest)\n', > '\n', > ' self.copystat(dst)\n', > '\n', > ' #\n', > ' # --- Special stuff from os\n', > '\n', > " if hasattr(os, 'chroot'):\n", > '\n', > ' def chroot(self): # pragma: nocover\n', > ' """.. seealso:: :func:`os.chroot`"""\n', > ' os.chroot(self)\n', > '\n', > " if hasattr(os, 'startfile'):\n", > '\n', > ' def startfile(self, *args, **kwargs): # pragma: nocover\n', > ' """.. seealso:: :func:`os.startfile`"""\n', > ' os.startfile(self, *args, **kwargs)\n', > ' return self\n', > '\n', > ' # in-place re-writing, courtesy of Martijn Pieters\n', > ' # http://www.zopatista.com/python/2013/11/26/inplace-file-rewriting/\n', > ' @contextlib.contextmanager\n', > ' def in_place(\n', > ' self,\n', > " mode='r',\n", > ' buffering=-1,\n', > ' encoding=None,\n', > ' errors=None,\n', > ' newline=None,\n', > ' backup_extension=None,\n', > ' ):\n', > ' """\n', > ' A context in which a file may be re-written in-place with\n', > ' new content.\n', > '\n', > ' Yields a tuple of :samp:`({readable}, {writable})` file\n', > ' objects, where `writable` replaces `readable`.\n', > '\n', > ' If an exception occurs, the old file is restored, removing the\n', > ' written data.\n', > '\n', > " Mode *must not* use ``'w'``, ``'a'``, or ``'+'``; only\n", > ' read-only-modes are allowed. A :exc:`ValueError` is raised\n', > ' on invalid modes.\n', > '\n', > ' For example, to add line numbers to a file::\n', > '\n', > ' p = Path(filename)\n', > ' assert p.is_file()\n', > ' with p.in_place() as (reader, writer):\n', > ' for number, line in enumerate(reader, 1):\n', > " writer.write('{0:3}: '.format(number)))\n", > ' writer.write(line)\n', > '\n', > ' Thereafter, the file at `filename` will have line numbers in it.\n', > ' """\n', > " if set(mode).intersection('wa+'):\n", > " raise ValueError('Only read-only file modes can be used')\n", > '\n', > ' # move existing file to backup, create new file with same ' > 'permissions\n', > ' # borrowed extensively from the fileinput module\n', > " backup_fn = self + (backup_extension or os.extsep + 'bak')\n", > ' backup_fn.remove_p()\n', > ' self.rename(backup_fn)\n', > ' readable = open(\n', > ' backup_fn,\n', > ' mode,\n', > ' buffering=buffering,\n', > ' encoding=encoding,\n', > ' errors=errors,\n', > ' newline=newline,\n', > ' )\n', > '\n', > ' perm = os.stat(readable.fileno()).st_mode\n', > ' os_mode = os.O_CREAT | os.O_WRONLY | os.O_TRUNC\n', > " os_mode |= getattr(os, 'O_BINARY', 0)\n", > ' fd = os.open(self, os_mode, perm)\n', > ' writable = open(\n', > ' fd,\n', > ' "w" + mode.replace(\'r\', \'\'),\n', > ' buffering=buffering,\n', > ' encoding=encoding,\n', > ' errors=errors,\n', > ' newline=newline,\n', > ' )\n', > ' with contextlib.suppress(OSError, AttributeError):\n', > ' self.chmod(perm)\n', > '\n', > ' try:\n', > ' yield readable, writable\n', > ' except Exception:\n', > ' # move backup back\n', > ' readable.close()\n', > ' writable.close()\n', > ' self.remove_p()\n', > ' backup_fn.rename(self)\n', > ' raise\n', > ' else:\n', > ' readable.close()\n', > ' writable.close()\n', > ' finally:\n', > ' backup_fn.remove_p()\n', > '\n', > ' @classes.ClassProperty\n', > ' @classmethod\n', > ' def special(cls):\n', > ' """\n', > ' Return a SpecialResolver object suitable referencing a suitable\n', > ' directory for the relevant platform for the given\n', > ' type of content.\n', > '\n', > ' For example, to get a user config directory, invoke:\n', > '\n', > ' dir = Path.special().user.config\n', > '\n', > ' Uses the `appdirs\n', > ' <https://pypi.python.org/pypi/appdirs/1.4.0>`_ to resolve\n', > ' the paths in a platform-friendly way.\n', > '\n', > " To create a config directory for 'My App', consider:\n", > '\n', > ' dir = Path.special("My App").user.config.makedirs_p()\n', > '\n', > ' If the ``appdirs`` module is not installed, invocation\n', > ' of special will raise an ImportError.\n', > ' """\n', > ' return functools.partial(SpecialResolver, cls)\n', > '\n', > '\n', > 'class DirectoryNotEmpty(OSError):\n', > ' @staticmethod\n', > ' @contextlib.contextmanager\n', > ' def translate():\n', > ' try:\n', > ' yield\n', > ' except OSError as exc:\n', > ' if exc.errno == errno.ENOTEMPTY:\n', > ' raise DirectoryNotEmpty(*exc.args) from exc\n', > ' raise\n', > '\n', > '\n', > 'def only_newer(copy_func):\n', > ' """\n', > ' Wrap a copy function (like shutil.copy2) to return\n', > " the dst if it's newer than the source.\n", > ' """\n', > '\n', > ' @functools.wraps(copy_func)\n', > ' def wrapper(src, dst, *args, **kwargs):\n', > ' is_newer_dst = dst.exists() and dst.getmtime() >= src.getmtime()\n', > ' if is_newer_dst:\n', > ' return dst\n', > ' return copy_func(src, dst, *args, **kwargs)\n', > '\n', > ' return wrapper\n', > '\n', > '\n', > 'class ExtantPath(Path):\n', > ' """\n', > " >>> ExtantPath('.')\n", > " ExtantPath('.')\n", > " >>> ExtantPath('does-not-exist')\n", > ' Traceback (most recent call last):\n', > ' OSError: does-not-exist does not exist.\n', > ' """\n', > '\n', > ' def _validate(self):\n', > ' if not self.exists():\n', > ' raise OSError(f"{self} does not exist.")\n', > '\n', > '\n', > 'class ExtantFile(Path):\n', > ' """\n', > " >>> ExtantFile('.')\n", > ' Traceback (most recent call last):\n', > ' FileNotFoundError: . does not exist as a file.\n', > " >>> ExtantFile('does-not-exist')\n", > ' Traceback (most recent call last):\n', > ' FileNotFoundError: does-not-exist does not exist as a file.\n', > ' """\n', > '\n', > ' def _validate(self):\n', > ' if not self.is_file():\n', > ' raise FileNotFoundError(f"{self} does not exist as a file.")\n', > '\n', > '\n', > 'class SpecialResolver:\n', > ' class ResolverScope:\n', > ' def __init__(self, paths, scope):\n', > ' self.paths = paths\n', > ' self.scope = scope\n', > '\n', > ' def __getattr__(self, class_):\n', > ' return self.paths.get_dir(self.scope, class_)\n', > '\n', > ' def __init__(self, path_class, *args, **kwargs):\n', > " appdirs = importlib.import_module('appdirs')\n", > '\n', > ' vars(self).update(\n', > ' path_class=path_class, wrapper=appdirs.AppDirs(*args, ' > '**kwargs)\n', > ' )\n', > '\n', > ' def __getattr__(self, scope):\n', > ' return self.ResolverScope(self, scope)\n', > '\n', > ' def get_dir(self, scope, class_):\n', > ' """\n', > ' Return the callable function from appdirs, but with the\n', > ' result wrapped in self.path_class\n', > ' """\n', > " prop_name = f'{scope}_{class_}_dir'\n", > ' value = getattr(self.wrapper, prop_name)\n', > ' MultiPath = Multi.for_class(self.path_class)\n', > ' return MultiPath.detect(value)\n', > '\n', > '\n', > 'class Multi:\n', > ' """\n', > ' A mix-in for a Path which may contain multiple Path separated by ' > 'pathsep.\n', > ' """\n', > '\n', > ' @classmethod\n', > ' def for_class(cls, path_cls):\n', > " name = 'Multi' + path_cls.__name__\n", > ' return type(name, (cls, path_cls), {})\n', > '\n', > ' @classmethod\n', > ' def detect(cls, input):\n', > ' if os.pathsep not in input:\n', > ' cls = cls._next_class\n', > ' return cls(input)\n', > '\n', > ' def __iter__(self):\n', > ' return iter(map(self._next_class, self.split(os.pathsep)))\n', > '\n', > ' @classes.ClassProperty\n', > ' @classmethod\n', > ' def _next_class(cls):\n', > ' """\n', > ' Multi-subclasses should use the parent class\n', > ' """\n', > ' return next(class_ for class_ in cls.__mro__ if not ' > 'issubclass(class_, Multi))\n', > '\n', > '\n', > 'class TempDir(Path):\n', > ' """\n', > ' A temporary directory via :func:`tempfile.mkdtemp`, and\n', > ' constructed with the same parameters that you can use\n', > ' as a context manager.\n', > '\n', > ' For example:\n', > '\n', > ' >>> with TempDir() as d:\n', > ' ... d.is_dir() and isinstance(d, Path)\n', > ' True\n', > '\n', > ' The directory is deleted automatically.\n', > '\n', > ' >>> d.is_dir()\n', > ' False\n', > '\n', > ' .. seealso:: :func:`tempfile.mkdtemp`\n', > ' """\n', > '\n', > ' @classes.ClassProperty\n', > ' @classmethod\n', > ' def _next_class(cls):\n', > ' return Path\n', > '\n', > ' def __new__(cls, *args, **kwargs):\n', > ' dirname = tempfile.mkdtemp(*args, **kwargs)\n', > ' return super().__new__(cls, dirname)\n', > '\n', > ' def __init__(self, *args, **kwargs):\n', > ' pass\n', > '\n', > ' def __enter__(self):\n', > ' # TempDir should return a Path version of itself and not itself\n', > ' # so that a second context manager does not create a second\n', > ' # temporary directory, but rather changes CWD to the location\n', > ' # of the temporary directory.\n', > ' return self._next_class(self)\n', > '\n', > ' def __exit__(self, exc_type, exc_value, traceback):\n', > ' self.rmtree()\n', > '\n', > '\n', > 'class Handlers:\n', > ' def strict(msg):\n', > ' raise\n', > '\n', > ' def warn(msg):\n', > ' warnings.warn(msg, TreeWalkWarning, stacklevel=2)\n', > '\n', > ' def ignore(msg):\n', > ' pass\n', > '\n', > ' @classmethod\n', > ' def _resolve(cls, param):\n', > ' if not callable(param) and param not in vars(Handlers):\n', > ' raise ValueError("invalid errors parameter")\n', > ' return vars(cls).get(param, param)\n'] > tests = [<DocTest path from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:0 (no examples)>, > <DocTest path.Traversal from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:93 (4 examples)>, > <DocTest path._strip_newlines from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:129 (1 example)>, > <DocTest path.Path from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:137 (no examples)>, > <DocTest path.Path.__truediv__ from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:197 (no examples)>, > <DocTest path.Path.__rtruediv__ from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:208 (no examples)>, > <DocTest path.Path.cwd from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:227 (no examples)>, > <DocTest path.Path.absolute from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:241 (no examples)>, > <DocTest path.Path.normcase from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:245 (no examples)>, > <DocTest path.Path.normpath from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:249 (no examples)>, > <DocTest path.Path.realpath from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:253 (no examples)>, > <DocTest path.Path.expanduser from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:257 (no examples)>, > <DocTest path.Path.expandvars from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:261 (no examples)>, > <DocTest path.Path.dirname from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:265 (no examples)>, > <DocTest path.Path.basename from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:269 (no examples)>, > <DocTest path.Path.expand from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:273 (no examples)>, > <DocTest path.Path.stem from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:283 (1 example)>, > <DocTest path.Path.with_stem from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:292 (1 example)>, > <DocTest path.Path.suffix from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:301 (no examples)>, > <DocTest path.Path.with_suffix from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:306 (3 examples)>, > <DocTest path.Path.drive from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:326 (no examples)>, > <DocTest path.Path.parent from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:265 (no examples)>, > <DocTest path.Path.name from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:269 (no examples)>, > <DocTest path.Path.with_name from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:361 (1 example)>, > <DocTest path.Path.splitpath from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:369 (no examples)>, > <DocTest path.Path.splitdrive from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:377 (no examples)>, > <DocTest path.Path.splitext from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:389 (no examples)>, > <DocTest path.Path.stripext from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:404 (no examples)>, > <DocTest path.Path.splitall from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:424 (1 example)>, > <DocTest path.Path.parts from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:439 (1 example)>, > <DocTest path.Path.relpath from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:459 (no examples)>, > <DocTest path.Path.relpathto from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:466 (no examples)>, > <DocTest path.Path.iterdir from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:506 (no examples)>, > <DocTest path.Path.dirs from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:522 (no examples)>, > <DocTest path.Path.files from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:533 (no examples)>, > <DocTest path.Path.walk from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:544 (no examples)>, > <DocTest path.Path.walkdirs from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:584 (no examples)>, > <DocTest path.Path.walkfiles from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:588 (no examples)>, > <DocTest path.Path.fnmatch from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:592 (no examples)>, > <DocTest path.Path.glob from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:611 (no examples)>, > <DocTest path.Path.iglob from /var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py:628 (no examples)>] >[1m[31m/usr/lib/python3.12/doctest.py[0m:1078: in _get_test > [0mlineno = [96mself[39;49;00m._find_lineno(obj, source_lines)[90m[39;49;00m > docstring = ('Open this file and return a corresponding file object.\n' > '\n' > ' Keyword arguments work as in :func:`io.open`. If the file cannot ' > 'be\n' > ' opened, an :class:`OSError` is raised.\n' > ' ') > globs = {'B_NEWLINE': re.compile(b'\r\n|\r|\n'), > 'B_NL_END': re.compile(b'\r\n|\r|\n$'), > 'Callable': typing.Callable, > 'DirectoryNotEmpty': <class 'path.DirectoryNotEmpty'>, > 'ExtantFile': <class 'path.ExtantFile'>, > 'ExtantPath': <class 'path.ExtantPath'>, > 'Handlers': <class 'path.Handlers'>, > 'Iterator': typing.Iterator, > 'LINESEPS': ['\r\n', '\r', '\n'], > 'Multi': <class 'path.Multi'>, > 'Number': <class 'numbers.Number'>, > 'Path': <class 'path.Path'>, > 'SpecialResolver': <class 'path.SpecialResolver'>, > 'TYPE_CHECKING': False, > 'TempDir': <class 'path.TempDir'>, > 'Traversal': <class 'path.Traversal'>, > 'TreeWalkWarning': <class 'path.TreeWalkWarning'>, > 'U_LINESEPS': ['\r\n', '\r', '\n', '\x85', '\u2028', '\u2029'], > 'U_NEWLINE': re.compile('\r\n|\r|\n|\x85|\u2028|\u2029'), > 'U_NL_END': re.compile('\r\n|\r|\n|\x85|\u2028|\u2029$'), > '__all__': ['Path', 'TempDir'], > '__builtins__': {'ArithmeticError': <class 'ArithmeticError'>, > 'AssertionError': <class 'AssertionError'>, > 'AttributeError': <class 'AttributeError'>, > 'BaseException': <class 'BaseException'>, > 'BaseExceptionGroup': <class 'BaseExceptionGroup'>, > 'BlockingIOError': <class 'BlockingIOError'>, > 'BrokenPipeError': <class 'BrokenPipeError'>, > 'BufferError': <class 'BufferError'>, > 'BytesWarning': <class 'BytesWarning'>, > 'ChildProcessError': <class 'ChildProcessError'>, > 'ConnectionAbortedError': <class 'ConnectionAbortedError'>, > 'ConnectionError': <class 'ConnectionError'>, > 'ConnectionRefusedError': <class 'ConnectionRefusedError'>, > 'ConnectionResetError': <class 'ConnectionResetError'>, > 'DeprecationWarning': <class 'DeprecationWarning'>, > 'EOFError': <class 'EOFError'>, > 'Ellipsis': Ellipsis, > 'EncodingWarning': <class 'EncodingWarning'>, > 'EnvironmentError': <class 'OSError'>, > 'Exception': <class 'Exception'>, > 'ExceptionGroup': <class 'ExceptionGroup'>, > 'False': False, > 'FileExistsError': <class 'FileExistsError'>, > 'FileNotFoundError': <class 'FileNotFoundError'>, > 'FloatingPointError': <class 'FloatingPointError'>, > 'FutureWarning': <class 'FutureWarning'>, > 'GeneratorExit': <class 'GeneratorExit'>, > 'IOError': <class 'OSError'>, > 'ImportError': <class 'ImportError'>, > 'ImportWarning': <class 'ImportWarning'>, > 'IndentationError': <class 'IndentationError'>, > 'IndexError': <class 'IndexError'>, > 'InterruptedError': <class 'InterruptedError'>, > 'IsADirectoryError': <class 'IsADirectoryError'>, > 'KeyError': <class 'KeyError'>, > 'KeyboardInterrupt': <class 'KeyboardInterrupt'>, > 'LookupError': <class 'LookupError'>, > 'MemoryError': <class 'MemoryError'>, > 'ModuleNotFoundError': <class 'ModuleNotFoundError'>, > 'NameError': <class 'NameError'>, > 'None': None, > 'NotADirectoryError': <class 'NotADirectoryError'>, > 'NotImplemented': NotImplemented, > 'NotImplementedError': <class 'NotImplementedError'>, > 'OSError': <class 'OSError'>, > 'OverflowError': <class 'OverflowError'>, > 'PendingDeprecationWarning': <class 'PendingDeprecationWarning'>, > 'PermissionError': <class 'PermissionError'>, > 'ProcessLookupError': <class 'ProcessLookupError'>, > 'RecursionError': <class 'RecursionError'>, > 'ReferenceError': <class 'ReferenceError'>, > 'ResourceWarning': <class 'ResourceWarning'>, > 'RuntimeError': <class 'RuntimeError'>, > 'RuntimeWarning': <class 'RuntimeWarning'>, > 'StopAsyncIteration': <class 'StopAsyncIteration'>, > 'StopIteration': <class 'StopIteration'>, > 'SyntaxError': <class 'SyntaxError'>, > 'SyntaxWarning': <class 'SyntaxWarning'>, > 'SystemError': <class 'SystemError'>, > 'SystemExit': <class 'SystemExit'>, > 'TabError': <class 'TabError'>, > 'TimeoutError': <class 'TimeoutError'>, > 'True': True, > 'TypeError': <class 'TypeError'>, > 'UnboundLocalError': <class 'UnboundLocalError'>, > 'UnicodeDecodeError': <class 'UnicodeDecodeError'>, > 'UnicodeEncodeError': <class 'UnicodeEncodeError'>, > 'UnicodeError': <class 'UnicodeError'>, > 'UnicodeTranslateError': <class 'UnicodeTranslateError'>, > 'UnicodeWarning': <class 'UnicodeWarning'>, > 'UserWarning': <class 'UserWarning'>, > 'ValueError': <class 'ValueError'>, > 'Warning': <class 'Warning'>, > 'ZeroDivisionError': <class 'ZeroDivisionError'>, > '__build_class__': <built-in function __build_class__>, > '__debug__': True, > '__doc__': 'Built-in functions, types, exceptions, and other ' > 'objects.\n' > '\n' > 'This module provides direct access to all ' > "'built-in'\n" > 'identifiers of Python; for example, builtins.len ' > 'is\n' > 'the full name for the built-in function len().\n' > '\n' > 'This module is not normally accessed explicitly ' > 'by most\n' > 'applications, but can be useful in modules that ' > 'provide\n' > 'objects with the same name as a built-in value, ' > 'but in\n' > 'which the built-in of that name is also needed.', > '__import__': <built-in function __import__>, > '__loader__': <class '_frozen_importlib.BuiltinImporter'>, > '__name__': 'builtins', > '__package__': '', > '__spec__': ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>, origin='built-in'), > 'abs': <built-in function abs>, > 'aiter': <built-in function aiter>, > 'all': <built-in function all>, > 'anext': <built-in function anext>, > 'any': <built-in function any>, > 'ascii': <built-in function ascii>, > 'bin': <built-in function bin>, > 'bool': <class 'bool'>, > 'breakpoint': <built-in function breakpoint>, > 'bytearray': <class 'bytearray'>, > 'bytes': <class 'bytes'>, > 'callable': <built-in function callable>, > 'chr': <built-in function chr>, > 'classmethod': <class 'classmethod'>, > 'compile': <built-in function compile>, > 'complex': <class 'complex'>, > 'copyright': Copyright (c) 2001-2023 Python Software Foundation. >All Rights Reserved. > >Copyright (c) 2000 BeOpen.com. >All Rights Reserved. > >Copyright (c) 1995-2001 Corporation for National Research Initiatives. >All Rights Reserved. > >Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam. >All Rights Reserved., > 'credits': Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands > for supporting Python development. See www.python.org for more information., > 'delattr': <built-in function delattr>, > 'dict': <class 'dict'>, > 'dir': <built-in function dir>, > 'divmod': <built-in function divmod>, > 'enumerate': <class 'enumerate'>, > 'eval': <built-in function eval>, > 'exec': <built-in function exec>, > 'exit': Use exit() or Ctrl-D (i.e. EOF) to exit, > 'filter': <class 'filter'>, > 'float': <class 'float'>, > 'format': <built-in function format>, > 'frozenset': <class 'frozenset'>, > 'getattr': <built-in function getattr>, > 'globals': <built-in function globals>, > 'hasattr': <built-in function hasattr>, > 'hash': <built-in function hash>, > 'help': Type help() for interactive help, or help(object) for help about object., > 'hex': <built-in function hex>, > 'id': <built-in function id>, > 'input': <built-in function input>, > 'int': <class 'int'>, > 'isinstance': <built-in function isinstance>, > 'issubclass': <built-in function issubclass>, > 'iter': <built-in function iter>, > 'len': <built-in function len>, > 'license': Type license() to see the full license text, > 'list': <class 'list'>, > 'locals': <built-in function locals>, > 'map': <class 'map'>, > 'max': <built-in function max>, > 'memoryview': <class 'memoryview'>, > 'min': <built-in function min>, > 'next': <built-in function next>, > 'object': <class 'object'>, > 'oct': <built-in function oct>, > 'open': <built-in function open>, > 'ord': <built-in function ord>, > 'pow': <built-in function pow>, > 'print': <built-in function print>, > 'property': <class 'property'>, > 'quit': Use quit() or Ctrl-D (i.e. EOF) to exit, > 'range': <class 'range'>, > 'repr': <built-in function repr>, > 'reversed': <class 'reversed'>, > 'round': <built-in function round>, > 'set': <class 'set'>, > 'setattr': <built-in function setattr>, > 'slice': <class 'slice'>, > 'sorted': <built-in function sorted>, > 'staticmethod': <class 'staticmethod'>, > 'str': <class 'str'>, > 'sum': <built-in function sum>, > 'super': <class 'super'>, > 'tuple': <class 'tuple'>, > 'type': <class 'type'>, > 'vars': <built-in function vars>, > 'zip': <class 'zip'>}, > '__cached__': '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__pycache__/__init__.cpython-312.pyc', > '__doc__': '\n' > 'Path Pie\n' > '\n' > 'Implements ``path.Path`` - An object representing a\n' > 'path to a file or directory.\n' > '\n' > 'Example::\n' > '\n' > ' from path import Path\n' > " d = Path('/home/guido/bin')\n" > '\n' > ' # Globbing\n' > " for f in d.files('*.py'):\n" > ' f.chmod(0o755)\n' > '\n' > ' # Changing the working directory:\n' > ' with Path("somewhere"):\n' > ' # cwd in now `somewhere`\n' > ' ...\n' > '\n' > ' # Concatenate paths with /\n' > ' foo_txt = Path("bar") / "foo.txt"\n', > '__file__': '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py', > '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f01aa694230>, > '__name__': 'path', > '__package__': 'path', > '__path__': ['/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path'], > '__pytest_asyncio_package_scoped_event_loop': <function pytest_collectstart.<locals>.scoped_event_loop at 0x7f01aa84dc60>, > '__pytest_asyncio_scoped_event_loop': <function pytest_collectstart.<locals>.scoped_event_loop at 0x7f01aa84e200>, > '__spec__': ModuleSpec(name='path', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7f01aa694230>, origin='/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py', submodule_search_locations=['/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path']), > '_default_linesep': <object object at 0x7f01aad185e0>, > '_make_timestamp_ns': <function _make_timestamp_ns at 0x7f01aa845ee0>, > '_strip_newlines': <function _strip_newlines at 0x7f01b0b88220>, > 'annotations': _Feature((3, 7, 0, 'beta', 1), None, 16777216), > 'builtins': <module 'builtins' (built-in)>, > 'classes': <module 'path.classes' from '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/classes.py'>, > 'compat': <module 'path.compat' (namespace) from ['/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/compat']>, > 'contextlib': <module 'contextlib' from '/usr/lib/python3.12/contextlib.py'>, > 'datetime': <module 'datetime' from '/usr/lib/python3.12/datetime.py'>, > 'errno': <module 'errno' (built-in)>, > 'fnmatch': <module 'fnmatch' from '/usr/lib/python3.12/fnmatch.py'>, > 'functools': <module 'functools' from '/usr/lib/python3.12/functools.py'>, > 'glob': <module 'glob' from '/usr/lib/python3.12/glob.py'>, > 'grp': <module 'grp' from '/usr/lib/python3.12/lib-dynload/grp.cpython-312-x86_64-linux-gnu.so'>, > 'hashlib': <module 'hashlib' from '/usr/lib/python3.12/hashlib.py'>, > 'importlib': <module 'importlib' from '/usr/lib/python3.12/importlib/__init__.py'>, > 'itertools': <module 'itertools' (built-in)>, > 'masks': <module 'path.masks' from '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/masks.py'>, > 'matchers': <module 'path.matchers' from '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/matchers.py'>, > 'only_newer': <function only_newer at 0x7f01aa84f9c0>, > 'os': <module 'os' (frozen)>, > 'overload': <function overload at 0x7f01b06491c0>, > 'pathlib': <module 'pathlib' from '/usr/lib/python3.12/pathlib.py'>, > 'pwd': <module 'pwd' (built-in)>, > 're': <module 're' from '/usr/lib/python3.12/re/__init__.py'>, > 'removeprefix': <function removeprefix at 0x7f01aa84f880>, > 'removesuffix': <function removesuffix at 0x7f01aa84f420>, > 'shutil': <module 'shutil' from '/usr/lib/python3.12/shutil.py'>, > 'sys': <module 'sys' (built-in)>, > 'tempfile': <module 'tempfile' from '/usr/lib/python3.12/tempfile.py'>, > 'warnings': <module 'warnings' from '/usr/lib/python3.12/warnings.py'>} > module = <module 'path' from '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0/path/__init__.py'> > name = 'path.Path.open' > obj = <function Path.open at 0x7f01aa6a9940> > self = <_pytest.doctest.DoctestModule.collect.<locals>.MockAwareDocTestFinder object at 0x7f01aa91be60> > source_lines = ['"""\n', > 'Path Pie\n', > '\n', > 'Implements ``path.Path`` - An object representing a\n', > 'path to a file or directory.\n', > '\n', > 'Example::\n', > '\n', > ' from path import Path\n', > " d = Path('/home/guido/bin')\n", > '\n', > ' # Globbing\n', > " for f in d.files('*.py'):\n", > ' f.chmod(0o755)\n', > '\n', > ' # Changing the working directory:\n', > ' with Path("somewhere"):\n', > ' # cwd in now `somewhere`\n', > ' ...\n', > '\n', > ' # Concatenate paths with /\n', > ' foo_txt = Path("bar") / "foo.txt"\n', > '"""\n', > '\n', > 'from __future__ import annotations\n', > '\n', > 'import builtins\n', > 'import contextlib\n', > 'import datetime\n', > 'import errno\n', > 'import fnmatch\n', > 'import functools\n', > 'import glob\n', > 'import hashlib\n', > 'import importlib\n', > 'import itertools\n', > 'import os\n', > 'import pathlib\n', > 'import re\n', > 'import shutil\n', > 'import sys\n', > 'import tempfile\n', > 'import warnings\n', > 'from numbers import Number\n', > '\n', > 'with contextlib.suppress(ImportError):\n', > ' import win32security\n', > '\n', > 'with contextlib.suppress(ImportError):\n', > ' import pwd\n', > '\n', > 'with contextlib.suppress(ImportError):\n', > ' import grp\n', > '\n', > 'from typing import (\n', > ' TYPE_CHECKING,\n', > ' Callable,\n', > ' Iterator,\n', > ' overload,\n', > ')\n', > '\n', > 'if TYPE_CHECKING:\n', > ' from _typeshed import (\n', > ' OpenBinaryMode,\n', > ' OpenTextMode,\n', > ' )\n', > '\n', > 'from . import classes, masks, matchers\n', > 'from .compat.py38 import removeprefix, removesuffix\n', > '\n', > "__all__ = ['Path', 'TempDir']\n", > '\n', > '\n', > "LINESEPS = ['\\r\\n', '\\r', '\\n']\n", > "U_LINESEPS = LINESEPS + ['\\u0085', '\\u2028', '\\u2029']\n", > "B_NEWLINE = re.compile('|'.join(LINESEPS).encode())\n", > "U_NEWLINE = re.compile('|'.join(U_LINESEPS))\n", > "B_NL_END = re.compile(B_NEWLINE.pattern + b'$')\n", > "U_NL_END = re.compile(U_NEWLINE.pattern + '$')\n", > '\n', > '_default_linesep = object()\n', > '\n', > '\n', > 'def _make_timestamp_ns(value: Number | datetime.datetime) -> Number:\n', > ' timestamp_s = value if isinstance(value, Number) else ' > 'value.timestamp()\n', > ' return int(timestamp_s * 10**9)\n', > '\n', > '\n', > 'class TreeWalkWarning(Warning):\n', > ' pass\n', > '\n', > '\n', > 'class Traversal:\n', > ' """\n', > ' Wrap a walk result to customize the traversal.\n', > '\n', > ' `follow` is a function that takes an item and returns\n', > ' True if that item should be followed and False otherwise.\n', > '\n', > ' For example, to avoid traversing into directories that\n', > ' begin with `.`:\n', > '\n', > " >>> traverse = Traversal(lambda dir: not dir.startswith('.'))\n", > " >>> items = list(traverse(Path('.').walk()))\n", > '\n', > ' Directories beginning with `.` will appear in the results, but\n', > ' their children will not.\n', > '\n', > ' >>> dot_dir = next(item for item in items if item.is_dir() and ' > "item.startswith('.'))\n", > ' >>> any(item.parent == dot_dir for item in items)\n', > ' False\n', > ' """\n', > '\n', > ' def __init__(self, follow):\n', > ' self.follow = follow\n', > '\n', > ' def __call__(self, walker):\n', > ' traverse = None\n', > ' while True:\n', > ' try:\n', > ' item = walker.send(traverse)\n', > ' except StopIteration:\n', > ' return\n', > ' yield item\n', > '\n', > ' traverse = functools.partial(self.follow, item)\n', > '\n', > '\n', > 'def _strip_newlines(lines):\n', > ' r"""\n', > " >>> list(_strip_newlines(['Hello World\\r\\n', 'foo']))\n", > " ['Hello World', 'foo']\n", > ' """\n', > " return (U_NL_END.sub('', line) for line in lines)\n", > '\n', > '\n', > 'class Path(str):\n', > ' """\n', > ' Represents a filesystem path.\n', > '\n', > ' For documentation on individual methods, consult their\n', > ' counterparts in :mod:`os.path`.\n', > '\n', > ' Some methods are additionally included from :mod:`shutil`.\n', > ' The functions are linked directly into the class namespace\n', > ' such that they will be bound to the Path instance. For example,\n', > ' ``Path(src).copy(target)`` is equivalent to\n', > ' ``shutil.copy(src, target)``. Therefore, when referencing\n', > ' the docs for these methods, assume `src` references `self`,\n', > ' the Path instance.\n', > ' """\n', > '\n', > ' module = os.path\n', > ' """ The path module to use for path operations.\n', > '\n', > ' .. seealso:: :mod:`os.path`\n', > ' """\n', > '\n', > " def __new__(cls, other='.'):\n", > ' return super().__new__(cls, other)\n', > '\n', > " def __init__(self, other='.'):\n", > ' if other is None:\n', > ' raise TypeError("Invalid initial value for path: None")\n', > ' with contextlib.suppress(AttributeError):\n', > ' self._validate()\n', > '\n', > ' @classmethod\n', > ' @functools.lru_cache\n', > ' def using_module(cls, module):\n', > " subclass_name = cls.__name__ + '_' + module.__name__\n", > ' bases = (cls,)\n', > " ns = {'module': module}\n", > ' return type(subclass_name, bases, ns)\n', > '\n', > ' @classes.ClassProperty\n', > ' @classmethod\n', > ' def _next_class(cls):\n', > ' """\n', > ' What class should be used to construct new instances from this ' > 'class\n', > ' """\n', > ' return cls\n', > '\n', > ' # --- Special Python methods.\n', > '\n', > ' def __repr__(self):\n', > " return f'{type(self).__name__}({super().__repr__()})'\n", > '\n', > ' # Adding a Path and a string yields a Path.\n', > ' def __add__(self, more):\n', > ' return self._next_class(super().__add__(more))\n', > '\n', > ' def __radd__(self, other):\n', > ' return self._next_class(other.__add__(self))\n', > '\n', > ' # The / operator joins Paths.\n', > ' def __truediv__(self, rel):\n', > ' """fp.__truediv__(rel) == fp / rel == fp.joinpath(rel)\n', > '\n', > ' Join two path components, adding a separator character if\n', > ' needed.\n', > '\n', > ' .. seealso:: :func:`os.path.join`\n', > ' """\n', > ' return self._next_class(self.module.join(self, rel))\n', > '\n', > ' # The / operator joins Paths the other way around\n', > ' def __rtruediv__(self, rel):\n', > ' """fp.__rtruediv__(rel) == rel / fp\n', > '\n', > ' Join two path components, adding a separator character if\n', > ' needed.\n', > '\n', > ' .. seealso:: :func:`os.path.join`\n', > ' """\n', > ' return self._next_class(self.module.join(rel, self))\n', > '\n', > ' def __enter__(self):\n', > ' self._old_dir = self.cwd()\n', > ' os.chdir(self)\n', > ' return self\n', > '\n', > ' def __exit__(self, *_):\n', > ' os.chdir(self._old_dir)\n', > '\n', > ' @classmethod\n', > ' def cwd(cls):\n', > ' """Return the current working directory as a path object.\n', > '\n', > ' .. seealso:: :func:`os.getcwd`\n', > ' """\n', > ' return cls(os.getcwd())\n', > '\n', > ' @classmethod\n', > ' def home(cls) -> Path:\n', > " return cls(os.path.expanduser('~'))\n", > '\n', > ' #\n', > ' # --- Operations on Path strings.\n', > '\n', > ' def absolute(self):\n', > ' """.. seealso:: :func:`os.path.abspath`"""\n', > ' return self._next_class(self.module.abspath(self))\n', > '\n', > ' def normcase(self):\n', > ' """.. seealso:: :func:`os.path.normcase`"""\n', > ' return self._next_class(self.module.normcase(self))\n', > '\n', > ' def normpath(self):\n', > ' """.. seealso:: :func:`os.path.normpath`"""\n', > ' return self._next_class(self.module.normpath(self))\n', > '\n', > ' def realpath(self):\n', > ' """.. seealso:: :func:`os.path.realpath`"""\n', > ' return self._next_class(self.module.realpath(self))\n', > '\n', > ' def expanduser(self):\n', > ' """.. seealso:: :func:`os.path.expanduser`"""\n', > ' return self._next_class(self.module.expanduser(self))\n', > '\n', > ' def expandvars(self):\n', > ' """.. seealso:: :func:`os.path.expandvars`"""\n', > ' return self._next_class(self.module.expandvars(self))\n', > '\n', > ' def dirname(self):\n', > ' """.. seealso:: :attr:`parent`, :func:`os.path.dirname`"""\n', > ' return self._next_class(self.module.dirname(self))\n', > '\n', > ' def basename(self):\n', > ' """.. seealso:: :attr:`name`, :func:`os.path.basename`"""\n', > ' return self._next_class(self.module.basename(self))\n', > '\n', > ' def expand(self):\n', > ' """Clean up a filename by calling :meth:`expandvars()`,\n', > ' :meth:`expanduser()`, and :meth:`normpath()` on it.\n', > '\n', > ' This is commonly everything needed to clean up a filename\n', > ' read from a configuration file, for example.\n', > ' """\n', > ' return self.expandvars().expanduser().normpath()\n', > '\n', > ' @property\n', > ' def stem(self):\n', > ' """The same as :meth:`name`, but with one file extension stripped ' > 'off.\n', > '\n', > " >>> Path('/home/guido/python.tar.gz').stem\n", > " 'python.tar'\n", > ' """\n', > ' base, ext = self.module.splitext(self.name)\n', > ' return base\n', > '\n', > ' def with_stem(self, stem):\n', > ' """Return a new path with the stem changed.\n', > '\n', > ' >>> Path(\'/home/guido/python.tar.gz\').with_stem("foo")\n', > " Path('/home/guido/foo.gz')\n", > ' """\n', > ' return self.with_name(stem + self.suffix)\n', > '\n', > ' @property\n', > ' def suffix(self):\n', > ' """The file extension, for example ``\'.py\'``."""\n', > ' f, suffix = self.module.splitext(self)\n', > ' return suffix\n', > '\n', > ' def with_suffix(self, suffix):\n', > ' """Return a new path with the file suffix changed (or added, if ' > 'none)\n', > '\n', > ' >>> Path(\'/home/guido/python.tar.gz\').with_suffix(".foo")\n', > " Path('/home/guido/python.tar.foo')\n", > '\n', > " >>> Path('python').with_suffix('.zip')\n", > " Path('python.zip')\n", > '\n', > " >>> Path('filename.ext').with_suffix('zip')\n", > ' Traceback (most recent call last):\n', > ' ...\n', > " ValueError: Invalid suffix 'zip'\n", > ' """\n', > " if not suffix.startswith('.'):\n", > ' raise ValueError(f"Invalid suffix {suffix!r}")\n', > '\n', > ' return self.stripext() + suffix\n', > '\n', > ' @property\n', > ' def drive(self):\n', > ' """The drive specifier, for example ``\'C:\'``.\n', > '\n', > " This is always empty on systems that don't use drive specifiers.\n", > ' """\n', > ' drive, r = self.module.splitdrive(self)\n', > ' return self._next_class(drive)\n', > '\n', > ' parent = property(\n', > ' dirname,\n', > ' None,\n', > ' None,\n', > ' """ This path\'s parent directory, as a new Path object.\n', > '\n', > ' For example,\n', > " ``Path('/usr/local/lib/libpython.so').parent ==\n", > " Path('/usr/local/lib')``\n", > '\n', > ' .. seealso:: :meth:`dirname`, :func:`os.path.dirname`\n', > ' """,\n', > ' )\n', > '\n', > ' name = property(\n', > ' basename,\n', > ' None,\n', > ' None,\n', > ' """ The name of this file or directory without the full path.\n', > '\n', > ' For example,\n', > " ``Path('/usr/local/lib/libpython.so').name == 'libpython.so'``\n", > '\n', > ' .. seealso:: :meth:`basename`, :func:`os.path.basename`\n', > ' """,\n', > ' )\n', > '\n', > ' def with_name(self, name):\n', > ' """Return a new path with the name changed.\n', > '\n', > ' >>> Path(\'/home/guido/python.tar.gz\').with_name("foo.zip")\n', > " Path('/home/guido/foo.zip')\n", > ' """\n', > ' return self._next_class(removesuffix(self, self.name) + name)\n', > '\n', > ' def splitpath(self):\n', > ' """Return two-tuple of ``.parent``, ``.name``.\n', > '\n', > ' .. seealso:: :attr:`parent`, :attr:`name`, :func:`os.path.split`\n', > ' """\n', > ' parent, child = self.module.split(self)\n', > ' return self._next_class(parent), child\n', > '\n', > ' def splitdrive(self):\n', > ' """Return two-tuple of ``.drive`` and rest without drive.\n', > '\n', > ' Split the drive specifier from this path. If there is\n', > ' no drive specifier, :samp:`{p.drive}` is empty, so the return ' > 'value\n', > " is simply ``(Path(''), p)``. This is always the case on Unix.\n", > '\n', > ' .. seealso:: :func:`os.path.splitdrive`\n', > ' """\n', > ' drive, rel = self.module.splitdrive(self)\n', > ' return self._next_class(drive), self._next_class(rel)\n', > '\n', > ' def splitext(self):\n', > ' """Return two-tuple of ``.stripext()`` and ``.ext``.\n', > '\n', > ' Split the filename extension from this path and return\n', > ' the two parts. Either part may be empty.\n', > '\n', > " The extension is everything from ``'.'`` to the end of the\n", > ' last path segment. This has the property that if\n', > ' ``(a, b) == p.splitext()``, then ``a + b == p``.\n', > '\n', > ' .. seealso:: :func:`os.path.splitext`\n', > ' """\n', > ' filename, ext = self.module.splitext(self)\n', > ' return self._next_class(filename), ext\n', > '\n', > ' def stripext(self):\n', > ' """Remove one file extension from the path.\n', > '\n', > " For example, ``Path('/home/guido/python.tar.gz').stripext()``\n", > " returns ``Path('/home/guido/python.tar')``.\n", > ' """\n', > ' return self.splitext()[0]\n', > '\n', > ' @classes.multimethod\n', > ' def joinpath(cls, first, *others):\n', > ' """\n', > ' Join first to zero or more :class:`Path` components,\n', > ' adding a separator character (:samp:`{first}.module.sep`)\n', > ' if needed. Returns a new instance of\n', > ' :samp:`{first}._next_class`.\n', > '\n', > ' .. seealso:: :func:`os.path.join`\n', > ' """\n', > ' return cls._next_class(cls.module.join(first, *others))\n', > '\n', > ' def splitall(self):\n', > ' r"""Return a list of the path components in this path.\n', > '\n', > ' The first item in the list will be a Path. Its value will be\n', > ' either :data:`os.curdir`, :data:`os.pardir`, empty, or the root\n', > " directory of this path (for example, ``'/'`` or ``'C:\\\\'``). " > 'The\n', > ' other items in the list will be strings.\n', > '\n', > ' ``Path.joinpath(*result)`` will yield the original path.\n', > '\n', > " >>> Path('/foo/bar/baz').splitall()\n", > " [Path('/'), 'foo', 'bar', 'baz']\n", > ' """\n', > ' return list(self._parts())\n', > '\n', > ' def parts(self):\n', > ' """\n', > " >>> Path('/foo/bar/baz').parts()\n", > " (Path('/'), 'foo', 'bar', 'baz')\n", > ' """\n', > ' return tuple(self._parts())\n', > '\n', > ' def _parts(self):\n', > ' return reversed(tuple(self._parts_iter()))\n', > '\n', > ' def _parts_iter(self):\n', > ' loc = self\n', > ' while loc != os.curdir and loc != os.pardir:\n', > ' prev = loc\n', > ' loc, child = prev.splitpath()\n', > ' if loc == prev:\n', > ' break\n', > ' yield child\n', > ' yield loc\n', > '\n', > " def relpath(self, start='.'):\n", > ' """Return this path as a relative path,\n', > ' based from `start`, which defaults to the current working ' > 'directory.\n', > ' """\n', > ' cwd = self._next_class(start)\n', > ' return cwd.relpathto(self)\n', > '\n', > ' def relpathto(self, dest):\n', > ' """Return a relative path from `self` to `dest`.\n', > '\n', > ' If there is no relative path from `self` to `dest`, for example if\n', > ' they reside on different drives in Windows, then this returns\n', > ' ``dest.absolute()``.\n', > ' """\n', > ' origin = self.absolute()\n', > ' dest = self._next_class(dest).absolute()\n', > '\n', > ' orig_list = origin.normcase().splitall()\n', > " # Don't normcase dest! We want to preserve the case.\n", > ' dest_list = dest.splitall()\n', > '\n', > ' if orig_list[0] != self.module.normcase(dest_list[0]):\n', > " # Can't get here from there.\n", > ' return dest\n', > '\n', > ' # Find the location where the two paths start to differ.\n', > ' i = 0\n', > ' for start_seg, dest_seg in zip(orig_list, dest_list):\n', > ' if start_seg != self.module.normcase(dest_seg):\n', > ' break\n', > ' i += 1\n', > '\n', > ' # Now i is the point where the two paths diverge.\n', > ' # Need a certain number of "os.pardir"s to work up\n', > ' # from the origin to the point of divergence.\n', > ' segments = [os.pardir] * (len(orig_list) - i)\n', > ' # Need to add the diverging part of dest_list.\n', > ' segments += dest_list[i:]\n', > ' if len(segments) == 0:\n', > ' # If they happen to be identical, use os.curdir.\n', > ' relpath = os.curdir\n', > ' else:\n', > ' relpath = self.module.join(*segments)\n', > ' return self._next_class(relpath)\n', > '\n', > ' # --- Listing, searching, walking, and matching\n', > '\n', > ' def iterdir(self, match=None):\n', > ' """Yields items in this directory.\n', > '\n', > ' Use :meth:`files` or :meth:`dirs` instead if you want a listing\n', > ' of just files or just subdirectories.\n', > '\n', > ' The elements of the list are Path objects.\n', > '\n', > ' With the optional `match` argument, a callable,\n', > ' only return items whose names match the given pattern.\n', > '\n', > ' .. seealso:: :meth:`files`, :meth:`dirs`\n', > ' """\n', > ' match = matchers.load(match)\n', > ' return filter(match, (self / child for child in os.listdir(self)))\n', > '\n', > ' def dirs(self, *args, **kwargs):\n', > ' """List of this directory\'s subdirectories.\n', > '\n', > ' The elements of the list are Path objects.\n', > ' This does not walk recursively into subdirectories\n', > ' (but see :meth:`walkdirs`).\n', > '\n', > ' Accepts parameters to :meth:`iterdir`.\n', > ' """\n', > ' return [p for p in self.iterdir(*args, **kwargs) if p.is_dir()]\n', > '\n', > ' def files(self, *args, **kwargs):\n', > ' """List of the files in self.\n', > '\n', > ' The elements of the list are Path objects.\n', > ' This does not walk into subdirectories (see :meth:`walkfiles`).\n', > '\n', > ' Accepts parameters to :meth:`iterdir`.\n', > ' """\n', > '\n', > ' return [p for p in self.iterdir(*args, **kwargs) if p.is_file()]\n', > '\n', > " def walk(self, match=None, errors='strict'):\n", > ' """Iterator over files and subdirs, recursively.\n', > '\n', > ' The iterator yields Path objects naming each child item of\n', > ' this directory and its descendants. This requires that\n', > ' ``D.is_dir()``.\n', > '\n', > ' This performs a depth-first traversal of the directory tree.\n', > ' Each directory is returned just before all its children.\n', > '\n', > ' The `errors=` keyword argument controls behavior when an\n', > " error occurs. The default is ``'strict'``, which causes an\n", > " exception. Other allowed values are ``'warn'`` (which\n", > " reports the error via :func:`warnings.warn()`), and ``'ignore'``.\n", > ' `errors` may also be an arbitrary callable taking a msg parameter.\n', > ' """\n', > '\n', > ' errors = Handlers._resolve(errors)\n', > ' match = matchers.load(match)\n', > '\n', > ' try:\n', > ' childList = self.iterdir()\n', > ' except Exception as exc:\n', > ' errors(f"Unable to list directory \'{self}\': {exc}")\n', > ' return\n', > '\n', > ' for child in childList:\n', > ' traverse = None\n', > ' if match(child):\n', > ' traverse = yield child\n', > ' traverse = traverse or child.is_dir\n', > ' try:\n', > ' do_traverse = traverse()\n', > ' except Exception as exc:\n', > ' errors(f"Unable to access \'{child}\': {exc}")\n', > ' continue\n', > '\n', > ' if do_traverse:\n', > ' yield from child.walk(errors=errors, match=match)\n', > '\n', > ' def walkdirs(self, *args, **kwargs):\n', > ' """Iterator over subdirs, recursively."""\n', > ' return (item for item in self.walk(*args, **kwargs) if ' > 'item.is_dir())\n', > '\n', > ' def walkfiles(self, *args, **kwargs):\n', > ' """Iterator over files, recursively."""\n', > ' return (item for item in self.walk(*args, **kwargs) if ' > 'item.is_file())\n', > '\n', > ' def fnmatch(self, pattern, normcase=None):\n', > ' """Return ``True`` if `self.name` matches the given `pattern`.\n', > '\n', > ' `pattern` - A filename pattern with wildcards,\n', > " for example ``'*.py'``. If the pattern contains a `normcase`\n", > ' attribute, it is applied to the name and path prior to ' > 'comparison.\n', > '\n', > ' `normcase` - (optional) A function used to normalize the pattern ' > 'and\n', > ' filename before matching. Defaults to normcase from\n', > ' ``self.module``, :func:`os.path.normcase`.\n', > '\n', > ' .. seealso:: :func:`fnmatch.fnmatch`\n', > ' """\n', > " default_normcase = getattr(pattern, 'normcase', " > 'self.module.normcase)\n', > ' normcase = normcase or default_normcase\n', > ' name = normcase(self.name)\n', > ' pattern = normcase(pattern)\n', > ' return fnmatch.fnmatchcase(name, pattern)\n', > '\n', > ' def glob(self, pattern):\n', > ' """Return a list of Path objects that match the pattern.\n', > '\n', > ' `pattern` - a path relative to this directory, with wildcards.\n', > '\n', > " For example, ``Path('/users').glob('*/bin/*')`` returns a list\n", > ' of all the files users have in their :file:`bin` directories.\n', > '\n', > ' .. seealso:: :func:`glob.glob`\n', > '\n', > ' .. note:: Glob is **not** recursive, even when using ``**``.\n', > ' To do recursive globbing see :func:`walk`,\n', > ' :func:`walkdirs` or :func:`walkfiles`.\n', > ' """\n', > ' cls = self._next_class\n', > ' return [cls(s) for s in glob.glob(self / pattern)]\n', > '\n', > ' def iglob(self, pattern):\n', > ' """Return an iterator of Path objects that match the pattern.\n', > '\n', > ' `pattern` - a path relative to this directory, with wildcards.\n', > '\n', > " For example, ``Path('/users').iglob('*/bin/*')`` returns an\n", > ' iterator of all the files users have in their :file:`bin`\n', > ' directories.\n', > '\n', > ' .. seealso:: :func:`glob.iglob`\n', > '\n', > ' .. note:: Glob is **not** recursive, even when using ``**``.\n', > ' To do recursive globbing see :func:`walk`,\n', > ' :func:`walkdirs` or :func:`walkfiles`.\n', > ' """\n', > ' cls = self._next_class\n', > ' return (cls(s) for s in glob.iglob(self / pattern))\n', > '\n', > ' #\n', > ' # --- Reading or writing an entire file at once.\n', > '\n', > ' @functools.wraps(open, assigned=())\n', > ' def open(self, *args, **kwargs):\n', > ' """Open this file and return a corresponding file object.\n', > '\n', > ' Keyword arguments work as in :func:`io.open`. If the file cannot ' > 'be\n', > ' opened, an :class:`OSError` is raised.\n', > ' """\n', > ' return open(self, *args, **kwargs)\n', > '\n', > ' def bytes(self):\n', > ' """Open this file, read all bytes, return them as a string."""\n', > " with self.open('rb') as f:\n", > ' return f.read()\n', > '\n', > ' @overload\n', > ' def chunks(\n', > ' self,\n', > ' size: int,\n', > ' mode: OpenTextMode = ...,\n', > ' buffering: int = ...,\n', > ' encoding: str | None = ...,\n', > ' errors: str | None = ...,\n', > ' newline: str | None = ...,\n', > ' closefd: bool = ...,\n', > ' opener: Callable[[str, int], int] | None = ...,\n', > ' ) -> Iterator[str]: ...\n', > '\n', > ' @overload\n', > ' def chunks(\n', > ' self,\n', > ' size: int,\n', > ' mode: OpenBinaryMode,\n', > ' buffering: int = ...,\n', > ' encoding: str | None = ...,\n', > ' errors: str | None = ...,\n', > ' newline: str | None = ...,\n', > ' closefd: bool = ...,\n', > ' opener: Callable[[str, int], int] | None = ...,\n', > ' ) -> Iterator[builtins.bytes]: ...\n', > '\n', > ' @overload\n', > ' def chunks(\n', > ' self,\n', > ' size: int,\n', > ' mode: str,\n', > ' buffering: int = ...,\n', > ' encoding: str | None = ...,\n', > ' errors: str | None = ...,\n', > ' newline: str | None = ...,\n', > ' closefd: bool = ...,\n', > ' opener: Callable[[str, int], int] | None = ...,\n', > ' ) -> Iterator[str | builtins.bytes]: ...\n', > '\n', > ' def chunks(self, size, *args, **kwargs):\n', > ' """Returns a generator yielding chunks of the file, so it can\n', > ' be read piece by piece with a simple for loop.\n', > '\n', > ' Any argument you pass after `size` will be passed to :meth:`open`.\n', > '\n', > ' :example:\n', > '\n', > ' >>> hash = hashlib.md5()\n', > ' >>> for chunk in Path("NEWS.rst").chunks(8192, mode=\'rb\'):\n', > ' ... hash.update(chunk)\n', > '\n', > ' This will read the file by chunks of 8192 bytes.\n', > ' """\n', > ' with self.open(*args, **kwargs) as f:\n', > ' yield from iter(lambda: f.read(size) or None, None)\n', > '\n', > ' def write_bytes(self, bytes, append=False):\n', > ' """Open this file and write the given bytes to it.\n', > '\n', > ' Default behavior is to overwrite any existing file.\n', > ' Call ``p.write_bytes(bytes, append=True)`` to append instead.\n', > ' """\n', > " with self.open('ab' if append else 'wb') as f:\n", > ' f.write(bytes)\n', > '\n', > ' def read_text(self, encoding=None, errors=None):\n', > ' r"""Open this file, read it in, return the content as a string.\n', > '\n', > ' Optional parameters are passed to :meth:`open`.\n', > '\n', > ' .. seealso:: :meth:`lines`\n', > ' """\n', > ' with self.open(encoding=encoding, errors=errors) as f:\n', > ' return f.read()\n', > '\n', > ' def read_bytes(self):\n', > ' r"""Return the contents of this file as bytes."""\n', > " with self.open(mode='rb') as f:\n", > ' return f.read()\n', > '\n', > ' def write_text(\n', > ' self,\n', > ' text: str,\n', > ' encoding: str | None = None,\n', > " errors: str = 'strict',\n", > ' linesep: str | None = os.linesep,\n', > ' append: bool = False,\n', > ' ) -> None:\n', > ' r"""Write the given text to this file.\n', > '\n', > ' The default behavior is to overwrite any existing file;\n', > ' to append instead, use the `append=True` keyword argument.\n', > '\n', > ' There are two differences between :meth:`write_text` and\n', > ' :meth:`write_bytes`: newline handling and Unicode handling.\n', > ' See below.\n', > '\n', > ' Parameters:\n', > '\n', > ' `text` - str - The text to be written.\n', > '\n', > ' `encoding` - str - The text encoding used.\n', > '\n', > ' `errors` - str - How to handle Unicode encoding errors.\n', > " Default is ``'strict'``. See ``help(unicode.encode)`` for " > 'the\n', > " options. Ignored if `text` isn't a Unicode string.\n", > '\n', > ' `linesep` - keyword argument - str/unicode - The sequence of\n', > ' characters to be used to mark end-of-line. The default is\n', > ' :data:`os.linesep`. Specify ``None`` to\n', > ' use newlines unmodified.\n', > '\n', > ' `append` - keyword argument - bool - Specifies what to do if\n', > ' the file already exists (``True``: append to the end of it;\n', > ' ``False``: overwrite it). The default is ``False``.\n', > '\n', > '\n', > ' --- Newline handling.\n', > '\n', > ' ``write_text()`` converts all standard end-of-line sequences\n', > " (``'\\n'``, ``'\\r'``, and ``'\\r\\n'``) to your platform's " > 'default\n', > ' end-of-line sequence (see :data:`os.linesep`; on Windows, for ' > 'example,\n', > " the end-of-line marker is ``'\\r\\n'``).\n", > '\n', > " To override the platform's default, pass the `linesep=`\n", > ' keyword argument. To preserve the newlines as-is, pass\n', > ' ``linesep=None``.\n', > '\n', > ' This handling applies to Unicode text and bytes, except\n', > ' with Unicode, additional non-ASCII newlines are recognized:\n', > ' ``\\x85``, ``\\r\\x85``, and ``\\u2028``.\n', > '\n', > ' --- Unicode\n', > '\n', > ' `text` is written using the\n', > ' specified `encoding` (or the default encoding if `encoding`\n', > " isn't specified). The `errors` argument applies only to this\n", > ' conversion.\n', > ' """\n', > ' if linesep is not None:\n', > ' text = U_NEWLINE.sub(linesep, text)\n', > ' bytes = text.encode(encoding or sys.getdefaultencoding(), errors)\n', > ' self.write_bytes(bytes, append=append)\n', > '\n', > ' def lines(self, encoding=None, errors=None, retain=True):\n', > ' r"""Open this file, read all lines, return them in a list.\n', > '\n', > ' Optional arguments:\n', > ' `encoding` - The Unicode encoding (or character set) of\n', > ' the file. The default is ``None``, meaning use\n', > ' ``locale.getpreferredencoding()``.\n', > ' `errors` - How to handle Unicode errors; see\n', > ' `open ' > '<https://docs.python.org/3/library/functions.html#open>`_\n', > ' for the options. Default is ``None`` meaning "strict".\n', > ' `retain` - If ``True`` (default), retain newline characters,\n', > ' but translate all newline\n', > ' characters to ``\\n``. If ``False``, newline characters ' > 'are\n', > ' omitted.\n', > ' """\n', > " text = U_NEWLINE.sub('\\n', self.read_text(encoding, errors))\n", > ' return text.splitlines(retain)\n', > '\n', > ' def write_lines(\n', > ' self,\n', > ' lines,\n', > ' encoding=None,\n', > " errors='strict',\n", > ' *,\n', > ' append=False,\n', > ' ):\n', > ' r"""Write the given lines of text to this file.\n', > '\n', > ' By default this overwrites any existing file at this path.\n', > '\n', > ' Puts a platform-specific newline sequence on every line.\n', > '\n', > ' `lines` - A list of strings.\n', > '\n', > ' `encoding` - A Unicode encoding to use. This applies only if\n', > ' `lines` contains any Unicode strings.\n', > '\n', > ' `errors` - How to handle errors in Unicode encoding. This\n', > ' also applies only to Unicode strings.\n', > '\n', > ' Use the keyword argument ``append=True`` to append lines to the\n', > ' file. The default is to overwrite the file.\n', > ' """\n', > " mode = 'a' if append else 'w'\n", > " with self.open(mode, encoding=encoding, errors=errors, newline='') " > 'as f:\n', > ' f.writelines(self._replace_linesep(lines))\n', > '\n', > ' @staticmethod\n', > ' def _replace_linesep(lines):\n', > ' return (line + os.linesep for line in _strip_newlines(lines))\n', > '\n', > ' def read_md5(self):\n', > ' """Calculate the md5 hash for this file.\n', > '\n', > ' This reads through the entire file.\n', > '\n', > ' .. seealso:: :meth:`read_hash`\n', > ' """\n', > " return self.read_hash('md5')\n", > '\n', > ' def _hash(self, hash_name):\n', > ' """Returns a hash object for the file at the current path.\n', > '\n', > " `hash_name` should be a hash algo name (such as ``'md5'``\n", > " or ``'sha1'``) that's available in the :mod:`hashlib` module.\n", > ' """\n', > ' m = hashlib.new(hash_name)\n', > ' for chunk in self.chunks(8192, mode="rb"):\n', > ' m.update(chunk)\n', > ' return m\n', > '\n', > ' def read_hash(self, hash_name):\n', > ' """Calculate given hash for this file.\n', > '\n', > ' List of supported hashes can be obtained from :mod:`hashlib` ' > 'package.\n', > ' This reads the entire file.\n', > '\n', > ' .. seealso:: :meth:`hashlib.hash.digest`\n', > ' """\n', > ' return self._hash(hash_name).digest()\n', > '\n', > ' def read_hexhash(self, hash_name):\n', > ' """Calculate given hash for this file, returning hexdigest.\n', > '\n', > ' List of supported hashes can be obtained from :mod:`hashlib` ' > 'package.\n', > ' This reads the entire file.\n', > '\n', > ' .. seealso:: :meth:`hashlib.hash.hexdigest`\n', > ' """\n', > ' return self._hash(hash_name).hexdigest()\n', > '\n', > ' # --- Methods for querying the filesystem.\n', > ' # N.B. On some platforms, the os.path functions may be implemented in ' > 'C\n', > " # (e.g. isdir on Windows, Python 3.2.2), and compiled functions don't " > 'get\n', > ' # bound. Playing it safe and wrapping them all in method calls.\n', > '\n', > ' def isabs(self):\n', > ' """\n', > " >>> Path('.').isabs()\n", > ' False\n', > '\n', > ' .. seealso:: :func:`os.path.isabs`\n', > ' """\n', > ' return self.module.isabs(self)\n', > '\n', > ' def exists(self):\n', > ' """.. seealso:: :func:`os.path.exists`"""\n', > ' return self.module.exists(self)\n', > '\n', > ' def is_dir(self):\n', > ' """.. seealso:: :func:`os.path.isdir`"""\n', > ' return self.module.isdir(self)\n', > '\n', > ' def is_file(self):\n', > ' """.. seealso:: :func:`os.path.isfile`"""\n', > ' return self.module.isfile(self)\n', > '\n', > ' def islink(self):\n', > ' """.. seealso:: :func:`os.path.islink`"""\n', > ' return self.module.islink(self)\n', > '\n', > ' def ismount(self):\n', > ' """\n', > " >>> Path('.').ismount()\n", > ' False\n', > '\n', > ' .. seealso:: :func:`os.path.ismount`\n', > ' """\n', > ' return self.module.ismount(self)\n', > '\n', > ' def samefile(self, other):\n', > ' """.. seealso:: :func:`os.path.samefile`"""\n', > ' return self.module.samefile(self, other)\n', > '\n', > ' def getatime(self):\n', > ' """.. seealso:: :attr:`atime`, :func:`os.path.getatime`"""\n', > ' return self.module.getatime(self)\n', > '\n', > ' def set_atime(self, value):\n', > ' mtime_ns = self.stat().st_atime_ns\n', > ' self.utime(ns=(_make_timestamp_ns(value), mtime_ns))\n', > '\n', > ' atime = property(\n', > ' getatime,\n', > ' set_atime,\n', > ' None,\n', > ' """\n', > ' Last access time of the file.\n', > '\n', > " >>> Path('.').atime > 0\n", > ' True\n', > '\n', > ' Allows setting:\n', > '\n', > ' >>> some_file = ' > "Path(getfixture('tmp_path')).joinpath('file.txt').touch()\n", > ' >>> MST = datetime.timezone(datetime.timedelta(hours=-7))\n', > ' >>> some_file.atime = datetime.datetime(1976, 5, 7, 10, ' > 'tzinfo=MST)\n', > ' >>> some_file.atime\n', > ' 200336400.0\n', > '\n', > ' .. seealso:: :meth:`getatime`, :func:`os.path.getatime`\n', > ' """,\n', > ' )\n', > '\n', > ' def getmtime(self):\n', > ' """.. seealso:: :attr:`mtime`, :func:`os.path.getmtime`"""\n', > ' return self.module.getmtime(self)\n', > '\n', > ' def set_mtime(self, value):\n', > ' atime_ns = self.stat().st_atime_ns\n', > ' self.utime(ns=(atime_ns, _make_timestamp_ns(value)))\n', > '\n', > ' mtime = property(\n', > ' getmtime,\n', > ' set_mtime,\n', > ' None,\n', > ' """\n', > ' Last modified time of the file.\n', > '\n', > ' Allows setting:\n', > '\n', > ' >>> some_file = ' > "Path(getfixture('tmp_path')).joinpath('file.txt').touch()\n", > ' >>> MST = datetime.timezone(datetime.timedelta(hours=-7))\n', > ' >>> some_file.mtime = datetime.datetime(1976, 5, 7, 10, ' > 'tzinfo=MST)\n', > ' >>> some_file.mtime\n', > ' 200336400.0\n', > '\n', > ' .. seealso:: :meth:`getmtime`, :func:`os.path.getmtime`\n', > ' """,\n', > ' )\n', > '\n', > ' def getctime(self):\n', > ' """.. seealso:: :attr:`ctime`, :func:`os.path.getctime`"""\n', > ' return self.module.getctime(self)\n', > '\n', > ' ctime = property(\n', > ' getctime,\n', > ' None,\n', > ' None,\n', > ' """ Creation time of the file.\n', > '\n', > ' .. seealso:: :meth:`getctime`, :func:`os.path.getctime`\n', > ' """,\n', > ' )\n', > '\n', > ' def getsize(self):\n', > ' """.. seealso:: :attr:`size`, :func:`os.path.getsize`"""\n', > ' return self.module.getsize(self)\n', > '\n', > ' size = property(\n', > ' getsize,\n', > ' None,\n', > ' None,\n', > ' """ Size of the file, in bytes.\n', > '\n', > ' .. seealso:: :meth:`getsize`, :func:`os.path.getsize`\n', > ' """,\n', > ' )\n', > '\n', > ' @property\n', > ' def permissions(self) -> masks.Permissions:\n', > ' """\n', > ' Permissions.\n', > '\n', > " >>> perms = Path('.').permissions\n", > ' >>> isinstance(perms, int)\n', > ' True\n', > " >>> set(perms.symbolic) <= set('rwx-')\n", > ' True\n', > ' >>> perms.symbolic\n', > " 'r...'\n", > ' """\n', > ' return masks.Permissions(self.stat().st_mode)\n', > '\n', > ' def access(self, *args, **kwargs):\n', > ' """\n', > ' Return does the real user have access to this path.\n', > '\n', > " >>> Path('.').access(os.F_OK)\n", > ' True\n', > '\n', > ' .. seealso:: :func:`os.access`\n', > ' """\n', > ' return os.access(self, *args, **kwargs)\n', > '\n', > ' def stat(self, *, follow_symlinks=True):\n', > ' """\n', > ' Perform a ``stat()`` system call on this path.\n', > '\n', > " >>> Path('.').stat()\n", > ' os.stat_result(...)\n', > '\n', > ' .. seealso:: :meth:`lstat`, :func:`os.stat`\n', > ' """\n', > ' return os.stat(self, follow_symlinks=follow_symlinks)\n', > '\n', > ' def lstat(self):\n', > ' """\n', > ' Like :meth:`stat`, but do not follow symbolic links.\n', > '\n', > " >>> Path('.').lstat() == Path('.').stat()\n", > ' True\n', > '\n', > ' .. seealso:: :meth:`stat`, :func:`os.lstat`\n', > ' """\n', > ' return os.lstat(self)\n', > '\n', > ' def __get_owner_windows(self): # pragma: nocover\n', > ' r"""\n', > ' Return the name of the owner of this file or directory. Follow\n', > ' symbolic links.\n', > '\n', > ' Return a name of the form ``DOMAIN\\User Name``; may be a group.\n', > '\n', > ' .. seealso:: :attr:`owner`\n', > ' """\n', > ' desc = win32security.GetFileSecurity(\n', > ' self, win32security.OWNER_SECURITY_INFORMATION\n', > ' )\n', > ' sid = desc.GetSecurityDescriptorOwner()\n', > ' account, domain, typecode = win32security.LookupAccountSid(None, ' > 'sid)\n', > " return domain + '\\\\' + account\n", > '\n', > ' def __get_owner_unix(self): # pragma: nocover\n', > ' """\n', > ' Return the name of the owner of this file or directory. Follow\n', > ' symbolic links.\n', > '\n', > ' .. seealso:: :attr:`owner`\n', > ' """\n', > ' st = self.stat()\n', > ' return pwd.getpwuid(st.st_uid).pw_name\n', > '\n', > ' def __get_owner_not_implemented(self): # pragma: nocover\n', > ' raise NotImplementedError("Ownership not available on this ' > 'platform.")\n', > '\n', > ' get_owner = (\n', > ' __get_owner_windows\n', > " if 'win32security' in globals()\n", > ' else __get_owner_unix\n', > " if 'pwd' in globals()\n", > ' else __get_owner_not_implemented\n', > ' )\n', > '\n', > ' owner = property(\n', > ' get_owner,\n', > ' None,\n', > ' None,\n', > ' """ Name of the owner of this file or directory.\n', > '\n', > ' .. seealso:: :meth:`get_owner`""",\n', > ' )\n', > '\n', > " if 'grp' in globals(): # pragma: no cover\n", > '\n', > ' def group(self, *, follow_symlinks=True):\n', > ' """\n', > ' Return the group name of the file gid.\n', > ' """\n', > ' gid = self.stat(follow_symlinks=follow_symlinks).st_gid\n', > ' return grp.getgrgid(gid).gr_name\n', > '\n', > " if hasattr(os, 'statvfs'):\n", > '\n', > ' def statvfs(self):\n', > ' """Perform a ``statvfs()`` system call on this path.\n', > '\n', > ' .. seealso:: :func:`os.statvfs`\n', > ' """\n', > ' return os.statvfs(self)\n', > '\n', > " if hasattr(os, 'pathconf'):\n", > '\n', > ' def pathconf(self, name):\n', > ' """.. seealso:: :func:`os.pathconf`"""\n', > ' return os.pathconf(self, name)\n', > '\n', > ' #\n', > ' # --- Modifying operations on files and directories\n', > '\n', > ' def utime(self, *args, **kwargs):\n', > ' """Set the access and modified times of this file.\n', > '\n', > ' .. seealso:: :func:`os.utime`\n', > ' """\n', > ' os.utime(self, *args, **kwargs)\n', > ' return self\n', > '\n', > ' def chmod(self, mode):\n', > ' """\n', > ' Set the mode. May be the new mode (os.chmod behavior) or a ' > '`symbolic\n', > ' mode <http://en.wikipedia.org/wiki/Chmod#Symbolic_modes>`_.\n', > '\n', > ' >>> a_file = ' > "Path(getfixture('tmp_path')).joinpath('afile.txt').touch()\n", > ' >>> a_file.chmod(0o700)\n', > ' Path(...\n', > " >>> a_file.chmod('u+x')\n", > ' Path(...\n', > '\n', > ' .. seealso:: :func:`os.chmod`\n', > ' """\n', > ' if isinstance(mode, str):\n', > ' mask = masks.compound(mode)\n', > ' mode = mask(self.stat().st_mode)\n', > ' os.chmod(self, mode)\n', > ' return self\n', > '\n', > " if hasattr(os, 'chown'):\n", > '\n', > ' def chown(self, uid=-1, gid=-1):\n', > ' """\n', > ' Change the owner and group by names or numbers.\n', > '\n', > ' .. seealso:: :func:`os.chown`\n', > ' """\n', > '\n', > ' def resolve_uid(uid):\n', > ' return uid if isinstance(uid, int) else ' > 'pwd.getpwnam(uid).pw_uid\n', > '\n', > ' def resolve_gid(gid):\n', > ' return gid if isinstance(gid, int) else ' > 'grp.getgrnam(gid).gr_gid\n', > '\n', > ' os.chown(self, resolve_uid(uid), resolve_gid(gid))\n', > ' return self\n', > '\n', > ' def rename(self, new):\n', > ' """.. seealso:: :func:`os.rename`"""\n', > ' os.rename(self, new)\n', > ' return self._next_class(new)\n', > '\n', > ' def renames(self, new):\n', > ' """.. seealso:: :func:`os.renames`"""\n', > ' os.renames(self, new)\n', > ' return self._next_class(new)\n', > '\n', > ' def replace(self, target_or_old: Path | str, *args) -> Path:\n', > ' """\n', > ' Replace a path or substitute substrings.\n', > '\n', > ' Implements both pathlib.Path.replace and str.replace.\n', > '\n', > ' If only a target is supplied, rename this path to the target path,\n', > ' overwriting if that path exists.\n', > '\n', > " >>> dest = Path(getfixture('tmp_path'))\n", > " >>> orig = dest.joinpath('foo').touch()\n", > " >>> new = orig.replace(dest.joinpath('fee'))\n", > ' >>> orig.exists()\n', > ' False\n', > ' >>> new.exists()\n', > ' True\n', > '\n', > ' ..seealso:: :meth:`pathlib.Path.replace`\n', > '\n', > ' If a second parameter is supplied, perform a textual replacement.\n', > '\n', > " >>> Path('foo').replace('o', 'e')\n", > " Path('fee')\n", > " >>> Path('foo').replace('o', 'l', 1)\n", > " Path('flo')\n", > '\n', > ' ..seealso:: :meth:`str.replace`\n', > ' """\n', > ' return self._next_class(\n', > ' super().replace(target_or_old, *args)\n', > ' if args\n', > ' else pathlib.Path(self).replace(target_or_old)\n', > ' )\n', > '\n', > ' #\n', > ' # --- Create/delete operations on directories\n', > '\n', > ' def mkdir(self, mode=0o777):\n', > ' """.. seealso:: :func:`os.mkdir`"""\n', > ' os.mkdir(self, mode)\n', > ' return self\n', > '\n', > ' def mkdir_p(self, mode=0o777):\n', > ' """Like :meth:`mkdir`, but does not raise an exception if the\n', > ' directory already exists."""\n', > ' with contextlib.suppress(FileExistsError):\n', > ' self.mkdir(mode)\n', > ' return self\n', > '\n', > ' def makedirs(self, mode=0o777):\n', > ' """.. seealso:: :func:`os.makedirs`"""\n', > ' os.makedirs(self, mode)\n', > ' return self\n', > '\n', > ' def makedirs_p(self, mode=0o777):\n', > ' """Like :meth:`makedirs`, but does not raise an exception if the\n', > ' directory already exists."""\n', > ' with contextlib.suppress(FileExistsError):\n', > ' self.makedirs(mode)\n', > ' return self\n', > '\n', > ' def rmdir(self):\n', > ' """.. seealso:: :func:`os.rmdir`"""\n', > ' os.rmdir(self)\n', > ' return self\n', > '\n', > ' def rmdir_p(self):\n', > ' """Like :meth:`rmdir`, but does not raise an exception if the\n', > ' directory is not empty or does not exist."""\n', > ' suppressed = FileNotFoundError, FileExistsError, DirectoryNotEmpty\n', > ' with contextlib.suppress(suppressed):\n', > ' with DirectoryNotEmpty.translate():\n', > ' self.rmdir()\n', > ' return self\n', > '\n', > ' def removedirs(self):\n', > ' """.. seealso:: :func:`os.removedirs`"""\n', > ' os.removedirs(self)\n', > ' return self\n', > '\n', > ' def removedirs_p(self):\n', > ' """Like :meth:`removedirs`, but does not raise an exception if the\n', > ' directory is not empty or does not exist."""\n', > ' with contextlib.suppress(FileExistsError, DirectoryNotEmpty):\n', > ' with DirectoryNotEmpty.translate():\n', > ' self.removedirs()\n', > ' return self\n', > '\n', > ' # --- Modifying operations on files\n', > '\n', > ' def touch(self):\n', > ' """Set the access/modified times of this file to the current time.\n', > ' Create the file if it does not exist.\n', > ' """\n', > ' os.close(os.open(self, os.O_WRONLY | os.O_CREAT, 0o666))\n', > ' os.utime(self, None)\n', > ' return self\n', > '\n', > ' def remove(self):\n', > ' """.. seealso:: :func:`os.remove`"""\n', > ' os.remove(self)\n', > ' return self\n', > '\n', > ' def remove_p(self):\n', > ' """Like :meth:`remove`, but does not raise an exception if the\n', > ' file does not exist."""\n', > ' with contextlib.suppress(FileNotFoundError):\n', > ' self.unlink()\n', > ' return self\n', > '\n', > ' unlink = remove\n', > ' unlink_p = remove_p\n', > '\n', > ' # --- Links\n', > '\n', > ' def hardlink_to(self, target: str) -> None:\n', > ' """\n', > ' Create a hard link at self, pointing to target.\n', > '\n', > ' .. seealso:: :func:`os.link`\n', > ' """\n', > ' os.link(target, self)\n', > '\n', > ' def link(self, newpath):\n', > ' """Create a hard link at `newpath`, pointing to this file.\n', > '\n', > ' .. seealso:: :func:`os.link`\n', > ' """\n', > ' os.link(self, newpath)\n', > ' return self._next_class(newpath)\n', > '\n', > ' def symlink_to(self, target: str, target_is_directory: bool = False) -> ' > 'None:\n', > ' """\n', > ' Create a symbolic link at self, pointing to target.\n', > '\n', > ' .. seealso:: :func:`os.symlink`\n', > ' """\n', > ' os.symlink(target, self, target_is_directory)\n', > '\n', > ' def symlink(self, newlink=None):\n', > ' """Create a symbolic link at `newlink`, pointing here.\n', > '\n', > ' If newlink is not supplied, the symbolic link will assume\n', > ' the name self.basename(), creating the link in the cwd.\n', > '\n', > ' .. seealso:: :func:`os.symlink`\n', > ' """\n', > ' if newlink is None:\n', > ' newlink = self.basename()\n', > ' os.symlink(self, newlink)\n', > ' return self._next_class(newlink)\n', > '\n', > ' def readlink(self):\n', > ' """Return the path to which this symbolic link points.\n', > '\n', > ' The result may be an absolute or a relative path.\n', > '\n', > ' .. seealso:: :meth:`readlinkabs`, :func:`os.readlink`\n', > ' """\n', > ' return self._next_class(removeprefix(os.readlink(self), ' > "'\\\\\\\\?\\\\'))\n", > '\n', > ' def readlinkabs(self):\n', > ' """Return the path to which this symbolic link points.\n', > '\n', > ' The result is always an absolute path.\n', > '\n', > ' .. seealso:: :meth:`readlink`, :func:`os.readlink`\n', > ' """\n', > ' p = self.readlink()\n', > ' return p if p.isabs() else (self.parent / p).absolute()\n', > '\n', > ' # High-level functions from shutil\n', > ' # These functions will be bound to the instance such that\n', > ' # Path(name).copy(target) will invoke shutil.copy(name, target)\n', > '\n', > ' copyfile = shutil.copyfile\n', > ' copymode = shutil.copymode\n', > ' copystat = shutil.copystat\n', > ' copy = shutil.copy\n', > ' copy2 = shutil.copy2\n', > ' copytree = shutil.copytree\n', > " if hasattr(shutil, 'move'):\n", > ' move = shutil.move\n', > ' rmtree = shutil.rmtree\n', > '\n', > ' def rmtree_p(self):\n', > ' """Like :meth:`rmtree`, but does not raise an exception if the\n', > ' directory does not exist."""\n', > ' with contextlib.suppress(FileNotFoundError):\n', > ' self.rmtree()\n', > ' return self\n', > '\n', > ' def chdir(self):\n', > ' """.. seealso:: :func:`os.chdir`"""\n', > ' os.chdir(self)\n', > '\n', > ' cd = chdir\n', > '\n', > ' def merge_tree(\n', > ' self,\n', > ' dst,\n', > ' symlinks=False,\n', > ' *,\n', > ' copy_function=shutil.copy2,\n', > ' ignore=lambda dir, contents: [],\n', > ' ):\n', > ' """\n', > ' Copy entire contents of self to dst, overwriting existing\n', > ' contents in dst with those in self.\n', > '\n', > ' Pass ``symlinks=True`` to copy symbolic links as links.\n', > '\n', > ' Accepts a ``copy_function``, similar to copytree.\n', > '\n', > ' To avoid overwriting newer files, supply a copy function\n', > ' wrapped in ``only_newer``. For example::\n', > '\n', > ' src.merge_tree(dst, copy_function=only_newer(shutil.copy2))\n', > ' """\n', > ' dst = self._next_class(dst)\n', > ' dst.makedirs_p()\n', > '\n', > ' sources = list(self.iterdir())\n', > ' _ignored = ignore(self, [item.name for item in sources])\n', > '\n', > ' def ignored(item):\n', > ' return item.name in _ignored\n', > '\n', > ' for source in itertools.filterfalse(ignored, sources):\n', > ' dest = dst / source.name\n', > ' if symlinks and source.islink():\n', > ' target = source.readlink()\n', > ' target.symlink(dest)\n', > ' elif source.is_dir():\n', > ' source.merge_tree(\n', > ' dest,\n', > ' symlinks=symlinks,\n', > ' copy_function=copy_function,\n', > ' ignore=ignore,\n', > ' )\n', > ' else:\n', > ' copy_function(source, dest)\n', > '\n', > ' self.copystat(dst)\n', > '\n', > ' #\n', > ' # --- Special stuff from os\n', > '\n', > " if hasattr(os, 'chroot'):\n", > '\n', > ' def chroot(self): # pragma: nocover\n', > ' """.. seealso:: :func:`os.chroot`"""\n', > ' os.chroot(self)\n', > '\n', > " if hasattr(os, 'startfile'):\n", > '\n', > ' def startfile(self, *args, **kwargs): # pragma: nocover\n', > ' """.. seealso:: :func:`os.startfile`"""\n', > ' os.startfile(self, *args, **kwargs)\n', > ' return self\n', > '\n', > ' # in-place re-writing, courtesy of Martijn Pieters\n', > ' # http://www.zopatista.com/python/2013/11/26/inplace-file-rewriting/\n', > ' @contextlib.contextmanager\n', > ' def in_place(\n', > ' self,\n', > " mode='r',\n", > ' buffering=-1,\n', > ' encoding=None,\n', > ' errors=None,\n', > ' newline=None,\n', > ' backup_extension=None,\n', > ' ):\n', > ' """\n', > ' A context in which a file may be re-written in-place with\n', > ' new content.\n', > '\n', > ' Yields a tuple of :samp:`({readable}, {writable})` file\n', > ' objects, where `writable` replaces `readable`.\n', > '\n', > ' If an exception occurs, the old file is restored, removing the\n', > ' written data.\n', > '\n', > " Mode *must not* use ``'w'``, ``'a'``, or ``'+'``; only\n", > ' read-only-modes are allowed. A :exc:`ValueError` is raised\n', > ' on invalid modes.\n', > '\n', > ' For example, to add line numbers to a file::\n', > '\n', > ' p = Path(filename)\n', > ' assert p.is_file()\n', > ' with p.in_place() as (reader, writer):\n', > ' for number, line in enumerate(reader, 1):\n', > " writer.write('{0:3}: '.format(number)))\n", > ' writer.write(line)\n', > '\n', > ' Thereafter, the file at `filename` will have line numbers in it.\n', > ' """\n', > " if set(mode).intersection('wa+'):\n", > " raise ValueError('Only read-only file modes can be used')\n", > '\n', > ' # move existing file to backup, create new file with same ' > 'permissions\n', > ' # borrowed extensively from the fileinput module\n', > " backup_fn = self + (backup_extension or os.extsep + 'bak')\n", > ' backup_fn.remove_p()\n', > ' self.rename(backup_fn)\n', > ' readable = open(\n', > ' backup_fn,\n', > ' mode,\n', > ' buffering=buffering,\n', > ' encoding=encoding,\n', > ' errors=errors,\n', > ' newline=newline,\n', > ' )\n', > '\n', > ' perm = os.stat(readable.fileno()).st_mode\n', > ' os_mode = os.O_CREAT | os.O_WRONLY | os.O_TRUNC\n', > " os_mode |= getattr(os, 'O_BINARY', 0)\n", > ' fd = os.open(self, os_mode, perm)\n', > ' writable = open(\n', > ' fd,\n', > ' "w" + mode.replace(\'r\', \'\'),\n', > ' buffering=buffering,\n', > ' encoding=encoding,\n', > ' errors=errors,\n', > ' newline=newline,\n', > ' )\n', > ' with contextlib.suppress(OSError, AttributeError):\n', > ' self.chmod(perm)\n', > '\n', > ' try:\n', > ' yield readable, writable\n', > ' except Exception:\n', > ' # move backup back\n', > ' readable.close()\n', > ' writable.close()\n', > ' self.remove_p()\n', > ' backup_fn.rename(self)\n', > ' raise\n', > ' else:\n', > ' readable.close()\n', > ' writable.close()\n', > ' finally:\n', > ' backup_fn.remove_p()\n', > '\n', > ' @classes.ClassProperty\n', > ' @classmethod\n', > ' def special(cls):\n', > ' """\n', > ' Return a SpecialResolver object suitable referencing a suitable\n', > ' directory for the relevant platform for the given\n', > ' type of content.\n', > '\n', > ' For example, to get a user config directory, invoke:\n', > '\n', > ' dir = Path.special().user.config\n', > '\n', > ' Uses the `appdirs\n', > ' <https://pypi.python.org/pypi/appdirs/1.4.0>`_ to resolve\n', > ' the paths in a platform-friendly way.\n', > '\n', > " To create a config directory for 'My App', consider:\n", > '\n', > ' dir = Path.special("My App").user.config.makedirs_p()\n', > '\n', > ' If the ``appdirs`` module is not installed, invocation\n', > ' of special will raise an ImportError.\n', > ' """\n', > ' return functools.partial(SpecialResolver, cls)\n', > '\n', > '\n', > 'class DirectoryNotEmpty(OSError):\n', > ' @staticmethod\n', > ' @contextlib.contextmanager\n', > ' def translate():\n', > ' try:\n', > ' yield\n', > ' except OSError as exc:\n', > ' if exc.errno == errno.ENOTEMPTY:\n', > ' raise DirectoryNotEmpty(*exc.args) from exc\n', > ' raise\n', > '\n', > '\n', > 'def only_newer(copy_func):\n', > ' """\n', > ' Wrap a copy function (like shutil.copy2) to return\n', > " the dst if it's newer than the source.\n", > ' """\n', > '\n', > ' @functools.wraps(copy_func)\n', > ' def wrapper(src, dst, *args, **kwargs):\n', > ' is_newer_dst = dst.exists() and dst.getmtime() >= src.getmtime()\n', > ' if is_newer_dst:\n', > ' return dst\n', > ' return copy_func(src, dst, *args, **kwargs)\n', > '\n', > ' return wrapper\n', > '\n', > '\n', > 'class ExtantPath(Path):\n', > ' """\n', > " >>> ExtantPath('.')\n", > " ExtantPath('.')\n", > " >>> ExtantPath('does-not-exist')\n", > ' Traceback (most recent call last):\n', > ' OSError: does-not-exist does not exist.\n', > ' """\n', > '\n', > ' def _validate(self):\n', > ' if not self.exists():\n', > ' raise OSError(f"{self} does not exist.")\n', > '\n', > '\n', > 'class ExtantFile(Path):\n', > ' """\n', > " >>> ExtantFile('.')\n", > ' Traceback (most recent call last):\n', > ' FileNotFoundError: . does not exist as a file.\n', > " >>> ExtantFile('does-not-exist')\n", > ' Traceback (most recent call last):\n', > ' FileNotFoundError: does-not-exist does not exist as a file.\n', > ' """\n', > '\n', > ' def _validate(self):\n', > ' if not self.is_file():\n', > ' raise FileNotFoundError(f"{self} does not exist as a file.")\n', > '\n', > '\n', > 'class SpecialResolver:\n', > ' class ResolverScope:\n', > ' def __init__(self, paths, scope):\n', > ' self.paths = paths\n', > ' self.scope = scope\n', > '\n', > ' def __getattr__(self, class_):\n', > ' return self.paths.get_dir(self.scope, class_)\n', > '\n', > ' def __init__(self, path_class, *args, **kwargs):\n', > " appdirs = importlib.import_module('appdirs')\n", > '\n', > ' vars(self).update(\n', > ' path_class=path_class, wrapper=appdirs.AppDirs(*args, ' > '**kwargs)\n', > ' )\n', > '\n', > ' def __getattr__(self, scope):\n', > ' return self.ResolverScope(self, scope)\n', > '\n', > ' def get_dir(self, scope, class_):\n', > ' """\n', > ' Return the callable function from appdirs, but with the\n', > ' result wrapped in self.path_class\n', > ' """\n', > " prop_name = f'{scope}_{class_}_dir'\n", > ' value = getattr(self.wrapper, prop_name)\n', > ' MultiPath = Multi.for_class(self.path_class)\n', > ' return MultiPath.detect(value)\n', > '\n', > '\n', > 'class Multi:\n', > ' """\n', > ' A mix-in for a Path which may contain multiple Path separated by ' > 'pathsep.\n', > ' """\n', > '\n', > ' @classmethod\n', > ' def for_class(cls, path_cls):\n', > " name = 'Multi' + path_cls.__name__\n", > ' return type(name, (cls, path_cls), {})\n', > '\n', > ' @classmethod\n', > ' def detect(cls, input):\n', > ' if os.pathsep not in input:\n', > ' cls = cls._next_class\n', > ' return cls(input)\n', > '\n', > ' def __iter__(self):\n', > ' return iter(map(self._next_class, self.split(os.pathsep)))\n', > '\n', > ' @classes.ClassProperty\n', > ' @classmethod\n', > ' def _next_class(cls):\n', > ' """\n', > ' Multi-subclasses should use the parent class\n', > ' """\n', > ' return next(class_ for class_ in cls.__mro__ if not ' > 'issubclass(class_, Multi))\n', > '\n', > '\n', > 'class TempDir(Path):\n', > ' """\n', > ' A temporary directory via :func:`tempfile.mkdtemp`, and\n', > ' constructed with the same parameters that you can use\n', > ' as a context manager.\n', > '\n', > ' For example:\n', > '\n', > ' >>> with TempDir() as d:\n', > ' ... d.is_dir() and isinstance(d, Path)\n', > ' True\n', > '\n', > ' The directory is deleted automatically.\n', > '\n', > ' >>> d.is_dir()\n', > ' False\n', > '\n', > ' .. seealso:: :func:`tempfile.mkdtemp`\n', > ' """\n', > '\n', > ' @classes.ClassProperty\n', > ' @classmethod\n', > ' def _next_class(cls):\n', > ' return Path\n', > '\n', > ' def __new__(cls, *args, **kwargs):\n', > ' dirname = tempfile.mkdtemp(*args, **kwargs)\n', > ' return super().__new__(cls, dirname)\n', > '\n', > ' def __init__(self, *args, **kwargs):\n', > ' pass\n', > '\n', > ' def __enter__(self):\n', > ' # TempDir should return a Path version of itself and not itself\n', > ' # so that a second context manager does not create a second\n', > ' # temporary directory, but rather changes CWD to the location\n', > ' # of the temporary directory.\n', > ' return self._next_class(self)\n', > '\n', > ' def __exit__(self, exc_type, exc_value, traceback):\n', > ' self.rmtree()\n', > '\n', > '\n', > 'class Handlers:\n', > ' def strict(msg):\n', > ' raise\n', > '\n', > ' def warn(msg):\n', > ' warnings.warn(msg, TreeWalkWarning, stacklevel=2)\n', > '\n', > ' def ignore(msg):\n', > ' pass\n', > '\n', > ' @classmethod\n', > ' def _resolve(cls, param):\n', > ' if not callable(param) and param not in vars(Handlers):\n', > ' raise ValueError("invalid errors parameter")\n', > ' return vars(cls).get(param, param)\n'] >[1m[31m/usr/lib/python3.12/doctest.py[0m:1127: in _find_lineno > [0mobj = inspect.unwrap(obj).[91m__code__[39;49;00m[90m[39;49;00m >[1m[31mE AttributeError: 'builtin_function_or_method' object has no attribute '__code__'. Did you mean: '__call__'?[0m > docstring = ('Open this file and return a corresponding file object.\n' > '\n' > ' Keyword arguments work as in :func:`io.open`. If the file cannot ' > 'be\n' > ' opened, an :class:`OSError` is raised.\n' > ' ') > lineno = None > obj = <function Path.open at 0x7f01aa6a9940> > self = <_pytest.doctest.DoctestModule.collect.<locals>.MockAwareDocTestFinder object at 0x7f01aa91be60> > source_lines = ['"""\n', > 'Path Pie\n', > '\n', > 'Implements ``path.Path`` - An object representing a\n', > 'path to a file or directory.\n', > '\n', > 'Example::\n', > '\n', > ' from path import Path\n', > " d = Path('/home/guido/bin')\n", > '\n', > ' # Globbing\n', > " for f in d.files('*.py'):\n", > ' f.chmod(0o755)\n', > '\n', > ' # Changing the working directory:\n', > ' with Path("somewhere"):\n', > ' # cwd in now `somewhere`\n', > ' ...\n', > '\n', > ' # Concatenate paths with /\n', > ' foo_txt = Path("bar") / "foo.txt"\n', > '"""\n', > '\n', > 'from __future__ import annotations\n', > '\n', > 'import builtins\n', > 'import contextlib\n', > 'import datetime\n', > 'import errno\n', > 'import fnmatch\n', > 'import functools\n', > 'import glob\n', > 'import hashlib\n', > 'import importlib\n', > 'import itertools\n', > 'import os\n', > 'import pathlib\n', > 'import re\n', > 'import shutil\n', > 'import sys\n', > 'import tempfile\n', > 'import warnings\n', > 'from numbers import Number\n', > '\n', > 'with contextlib.suppress(ImportError):\n', > ' import win32security\n', > '\n', > 'with contextlib.suppress(ImportError):\n', > ' import pwd\n', > '\n', > 'with contextlib.suppress(ImportError):\n', > ' import grp\n', > '\n', > 'from typing import (\n', > ' TYPE_CHECKING,\n', > ' Callable,\n', > ' Iterator,\n', > ' overload,\n', > ')\n', > '\n', > 'if TYPE_CHECKING:\n', > ' from _typeshed import (\n', > ' OpenBinaryMode,\n', > ' OpenTextMode,\n', > ' )\n', > '\n', > 'from . import classes, masks, matchers\n', > 'from .compat.py38 import removeprefix, removesuffix\n', > '\n', > "__all__ = ['Path', 'TempDir']\n", > '\n', > '\n', > "LINESEPS = ['\\r\\n', '\\r', '\\n']\n", > "U_LINESEPS = LINESEPS + ['\\u0085', '\\u2028', '\\u2029']\n", > "B_NEWLINE = re.compile('|'.join(LINESEPS).encode())\n", > "U_NEWLINE = re.compile('|'.join(U_LINESEPS))\n", > "B_NL_END = re.compile(B_NEWLINE.pattern + b'$')\n", > "U_NL_END = re.compile(U_NEWLINE.pattern + '$')\n", > '\n', > '_default_linesep = object()\n', > '\n', > '\n', > 'def _make_timestamp_ns(value: Number | datetime.datetime) -> Number:\n', > ' timestamp_s = value if isinstance(value, Number) else ' > 'value.timestamp()\n', > ' return int(timestamp_s * 10**9)\n', > '\n', > '\n', > 'class TreeWalkWarning(Warning):\n', > ' pass\n', > '\n', > '\n', > 'class Traversal:\n', > ' """\n', > ' Wrap a walk result to customize the traversal.\n', > '\n', > ' `follow` is a function that takes an item and returns\n', > ' True if that item should be followed and False otherwise.\n', > '\n', > ' For example, to avoid traversing into directories that\n', > ' begin with `.`:\n', > '\n', > " >>> traverse = Traversal(lambda dir: not dir.startswith('.'))\n", > " >>> items = list(traverse(Path('.').walk()))\n", > '\n', > ' Directories beginning with `.` will appear in the results, but\n', > ' their children will not.\n', > '\n', > ' >>> dot_dir = next(item for item in items if item.is_dir() and ' > "item.startswith('.'))\n", > ' >>> any(item.parent == dot_dir for item in items)\n', > ' False\n', > ' """\n', > '\n', > ' def __init__(self, follow):\n', > ' self.follow = follow\n', > '\n', > ' def __call__(self, walker):\n', > ' traverse = None\n', > ' while True:\n', > ' try:\n', > ' item = walker.send(traverse)\n', > ' except StopIteration:\n', > ' return\n', > ' yield item\n', > '\n', > ' traverse = functools.partial(self.follow, item)\n', > '\n', > '\n', > 'def _strip_newlines(lines):\n', > ' r"""\n', > " >>> list(_strip_newlines(['Hello World\\r\\n', 'foo']))\n", > " ['Hello World', 'foo']\n", > ' """\n', > " return (U_NL_END.sub('', line) for line in lines)\n", > '\n', > '\n', > 'class Path(str):\n', > ' """\n', > ' Represents a filesystem path.\n', > '\n', > ' For documentation on individual methods, consult their\n', > ' counterparts in :mod:`os.path`.\n', > '\n', > ' Some methods are additionally included from :mod:`shutil`.\n', > ' The functions are linked directly into the class namespace\n', > ' such that they will be bound to the Path instance. For example,\n', > ' ``Path(src).copy(target)`` is equivalent to\n', > ' ``shutil.copy(src, target)``. Therefore, when referencing\n', > ' the docs for these methods, assume `src` references `self`,\n', > ' the Path instance.\n', > ' """\n', > '\n', > ' module = os.path\n', > ' """ The path module to use for path operations.\n', > '\n', > ' .. seealso:: :mod:`os.path`\n', > ' """\n', > '\n', > " def __new__(cls, other='.'):\n", > ' return super().__new__(cls, other)\n', > '\n', > " def __init__(self, other='.'):\n", > ' if other is None:\n', > ' raise TypeError("Invalid initial value for path: None")\n', > ' with contextlib.suppress(AttributeError):\n', > ' self._validate()\n', > '\n', > ' @classmethod\n', > ' @functools.lru_cache\n', > ' def using_module(cls, module):\n', > " subclass_name = cls.__name__ + '_' + module.__name__\n", > ' bases = (cls,)\n', > " ns = {'module': module}\n", > ' return type(subclass_name, bases, ns)\n', > '\n', > ' @classes.ClassProperty\n', > ' @classmethod\n', > ' def _next_class(cls):\n', > ' """\n', > ' What class should be used to construct new instances from this ' > 'class\n', > ' """\n', > ' return cls\n', > '\n', > ' # --- Special Python methods.\n', > '\n', > ' def __repr__(self):\n', > " return f'{type(self).__name__}({super().__repr__()})'\n", > '\n', > ' # Adding a Path and a string yields a Path.\n', > ' def __add__(self, more):\n', > ' return self._next_class(super().__add__(more))\n', > '\n', > ' def __radd__(self, other):\n', > ' return self._next_class(other.__add__(self))\n', > '\n', > ' # The / operator joins Paths.\n', > ' def __truediv__(self, rel):\n', > ' """fp.__truediv__(rel) == fp / rel == fp.joinpath(rel)\n', > '\n', > ' Join two path components, adding a separator character if\n', > ' needed.\n', > '\n', > ' .. seealso:: :func:`os.path.join`\n', > ' """\n', > ' return self._next_class(self.module.join(self, rel))\n', > '\n', > ' # The / operator joins Paths the other way around\n', > ' def __rtruediv__(self, rel):\n', > ' """fp.__rtruediv__(rel) == rel / fp\n', > '\n', > ' Join two path components, adding a separator character if\n', > ' needed.\n', > '\n', > ' .. seealso:: :func:`os.path.join`\n', > ' """\n', > ' return self._next_class(self.module.join(rel, self))\n', > '\n', > ' def __enter__(self):\n', > ' self._old_dir = self.cwd()\n', > ' os.chdir(self)\n', > ' return self\n', > '\n', > ' def __exit__(self, *_):\n', > ' os.chdir(self._old_dir)\n', > '\n', > ' @classmethod\n', > ' def cwd(cls):\n', > ' """Return the current working directory as a path object.\n', > '\n', > ' .. seealso:: :func:`os.getcwd`\n', > ' """\n', > ' return cls(os.getcwd())\n', > '\n', > ' @classmethod\n', > ' def home(cls) -> Path:\n', > " return cls(os.path.expanduser('~'))\n", > '\n', > ' #\n', > ' # --- Operations on Path strings.\n', > '\n', > ' def absolute(self):\n', > ' """.. seealso:: :func:`os.path.abspath`"""\n', > ' return self._next_class(self.module.abspath(self))\n', > '\n', > ' def normcase(self):\n', > ' """.. seealso:: :func:`os.path.normcase`"""\n', > ' return self._next_class(self.module.normcase(self))\n', > '\n', > ' def normpath(self):\n', > ' """.. seealso:: :func:`os.path.normpath`"""\n', > ' return self._next_class(self.module.normpath(self))\n', > '\n', > ' def realpath(self):\n', > ' """.. seealso:: :func:`os.path.realpath`"""\n', > ' return self._next_class(self.module.realpath(self))\n', > '\n', > ' def expanduser(self):\n', > ' """.. seealso:: :func:`os.path.expanduser`"""\n', > ' return self._next_class(self.module.expanduser(self))\n', > '\n', > ' def expandvars(self):\n', > ' """.. seealso:: :func:`os.path.expandvars`"""\n', > ' return self._next_class(self.module.expandvars(self))\n', > '\n', > ' def dirname(self):\n', > ' """.. seealso:: :attr:`parent`, :func:`os.path.dirname`"""\n', > ' return self._next_class(self.module.dirname(self))\n', > '\n', > ' def basename(self):\n', > ' """.. seealso:: :attr:`name`, :func:`os.path.basename`"""\n', > ' return self._next_class(self.module.basename(self))\n', > '\n', > ' def expand(self):\n', > ' """Clean up a filename by calling :meth:`expandvars()`,\n', > ' :meth:`expanduser()`, and :meth:`normpath()` on it.\n', > '\n', > ' This is commonly everything needed to clean up a filename\n', > ' read from a configuration file, for example.\n', > ' """\n', > ' return self.expandvars().expanduser().normpath()\n', > '\n', > ' @property\n', > ' def stem(self):\n', > ' """The same as :meth:`name`, but with one file extension stripped ' > 'off.\n', > '\n', > " >>> Path('/home/guido/python.tar.gz').stem\n", > " 'python.tar'\n", > ' """\n', > ' base, ext = self.module.splitext(self.name)\n', > ' return base\n', > '\n', > ' def with_stem(self, stem):\n', > ' """Return a new path with the stem changed.\n', > '\n', > ' >>> Path(\'/home/guido/python.tar.gz\').with_stem("foo")\n', > " Path('/home/guido/foo.gz')\n", > ' """\n', > ' return self.with_name(stem + self.suffix)\n', > '\n', > ' @property\n', > ' def suffix(self):\n', > ' """The file extension, for example ``\'.py\'``."""\n', > ' f, suffix = self.module.splitext(self)\n', > ' return suffix\n', > '\n', > ' def with_suffix(self, suffix):\n', > ' """Return a new path with the file suffix changed (or added, if ' > 'none)\n', > '\n', > ' >>> Path(\'/home/guido/python.tar.gz\').with_suffix(".foo")\n', > " Path('/home/guido/python.tar.foo')\n", > '\n', > " >>> Path('python').with_suffix('.zip')\n", > " Path('python.zip')\n", > '\n', > " >>> Path('filename.ext').with_suffix('zip')\n", > ' Traceback (most recent call last):\n', > ' ...\n', > " ValueError: Invalid suffix 'zip'\n", > ' """\n', > " if not suffix.startswith('.'):\n", > ' raise ValueError(f"Invalid suffix {suffix!r}")\n', > '\n', > ' return self.stripext() + suffix\n', > '\n', > ' @property\n', > ' def drive(self):\n', > ' """The drive specifier, for example ``\'C:\'``.\n', > '\n', > " This is always empty on systems that don't use drive specifiers.\n", > ' """\n', > ' drive, r = self.module.splitdrive(self)\n', > ' return self._next_class(drive)\n', > '\n', > ' parent = property(\n', > ' dirname,\n', > ' None,\n', > ' None,\n', > ' """ This path\'s parent directory, as a new Path object.\n', > '\n', > ' For example,\n', > " ``Path('/usr/local/lib/libpython.so').parent ==\n", > " Path('/usr/local/lib')``\n", > '\n', > ' .. seealso:: :meth:`dirname`, :func:`os.path.dirname`\n', > ' """,\n', > ' )\n', > '\n', > ' name = property(\n', > ' basename,\n', > ' None,\n', > ' None,\n', > ' """ The name of this file or directory without the full path.\n', > '\n', > ' For example,\n', > " ``Path('/usr/local/lib/libpython.so').name == 'libpython.so'``\n", > '\n', > ' .. seealso:: :meth:`basename`, :func:`os.path.basename`\n', > ' """,\n', > ' )\n', > '\n', > ' def with_name(self, name):\n', > ' """Return a new path with the name changed.\n', > '\n', > ' >>> Path(\'/home/guido/python.tar.gz\').with_name("foo.zip")\n', > " Path('/home/guido/foo.zip')\n", > ' """\n', > ' return self._next_class(removesuffix(self, self.name) + name)\n', > '\n', > ' def splitpath(self):\n', > ' """Return two-tuple of ``.parent``, ``.name``.\n', > '\n', > ' .. seealso:: :attr:`parent`, :attr:`name`, :func:`os.path.split`\n', > ' """\n', > ' parent, child = self.module.split(self)\n', > ' return self._next_class(parent), child\n', > '\n', > ' def splitdrive(self):\n', > ' """Return two-tuple of ``.drive`` and rest without drive.\n', > '\n', > ' Split the drive specifier from this path. If there is\n', > ' no drive specifier, :samp:`{p.drive}` is empty, so the return ' > 'value\n', > " is simply ``(Path(''), p)``. This is always the case on Unix.\n", > '\n', > ' .. seealso:: :func:`os.path.splitdrive`\n', > ' """\n', > ' drive, rel = self.module.splitdrive(self)\n', > ' return self._next_class(drive), self._next_class(rel)\n', > '\n', > ' def splitext(self):\n', > ' """Return two-tuple of ``.stripext()`` and ``.ext``.\n', > '\n', > ' Split the filename extension from this path and return\n', > ' the two parts. Either part may be empty.\n', > '\n', > " The extension is everything from ``'.'`` to the end of the\n", > ' last path segment. This has the property that if\n', > ' ``(a, b) == p.splitext()``, then ``a + b == p``.\n', > '\n', > ' .. seealso:: :func:`os.path.splitext`\n', > ' """\n', > ' filename, ext = self.module.splitext(self)\n', > ' return self._next_class(filename), ext\n', > '\n', > ' def stripext(self):\n', > ' """Remove one file extension from the path.\n', > '\n', > " For example, ``Path('/home/guido/python.tar.gz').stripext()``\n", > " returns ``Path('/home/guido/python.tar')``.\n", > ' """\n', > ' return self.splitext()[0]\n', > '\n', > ' @classes.multimethod\n', > ' def joinpath(cls, first, *others):\n', > ' """\n', > ' Join first to zero or more :class:`Path` components,\n', > ' adding a separator character (:samp:`{first}.module.sep`)\n', > ' if needed. Returns a new instance of\n', > ' :samp:`{first}._next_class`.\n', > '\n', > ' .. seealso:: :func:`os.path.join`\n', > ' """\n', > ' return cls._next_class(cls.module.join(first, *others))\n', > '\n', > ' def splitall(self):\n', > ' r"""Return a list of the path components in this path.\n', > '\n', > ' The first item in the list will be a Path. Its value will be\n', > ' either :data:`os.curdir`, :data:`os.pardir`, empty, or the root\n', > " directory of this path (for example, ``'/'`` or ``'C:\\\\'``). " > 'The\n', > ' other items in the list will be strings.\n', > '\n', > ' ``Path.joinpath(*result)`` will yield the original path.\n', > '\n', > " >>> Path('/foo/bar/baz').splitall()\n", > " [Path('/'), 'foo', 'bar', 'baz']\n", > ' """\n', > ' return list(self._parts())\n', > '\n', > ' def parts(self):\n', > ' """\n', > " >>> Path('/foo/bar/baz').parts()\n", > " (Path('/'), 'foo', 'bar', 'baz')\n", > ' """\n', > ' return tuple(self._parts())\n', > '\n', > ' def _parts(self):\n', > ' return reversed(tuple(self._parts_iter()))\n', > '\n', > ' def _parts_iter(self):\n', > ' loc = self\n', > ' while loc != os.curdir and loc != os.pardir:\n', > ' prev = loc\n', > ' loc, child = prev.splitpath()\n', > ' if loc == prev:\n', > ' break\n', > ' yield child\n', > ' yield loc\n', > '\n', > " def relpath(self, start='.'):\n", > ' """Return this path as a relative path,\n', > ' based from `start`, which defaults to the current working ' > 'directory.\n', > ' """\n', > ' cwd = self._next_class(start)\n', > ' return cwd.relpathto(self)\n', > '\n', > ' def relpathto(self, dest):\n', > ' """Return a relative path from `self` to `dest`.\n', > '\n', > ' If there is no relative path from `self` to `dest`, for example if\n', > ' they reside on different drives in Windows, then this returns\n', > ' ``dest.absolute()``.\n', > ' """\n', > ' origin = self.absolute()\n', > ' dest = self._next_class(dest).absolute()\n', > '\n', > ' orig_list = origin.normcase().splitall()\n', > " # Don't normcase dest! We want to preserve the case.\n", > ' dest_list = dest.splitall()\n', > '\n', > ' if orig_list[0] != self.module.normcase(dest_list[0]):\n', > " # Can't get here from there.\n", > ' return dest\n', > '\n', > ' # Find the location where the two paths start to differ.\n', > ' i = 0\n', > ' for start_seg, dest_seg in zip(orig_list, dest_list):\n', > ' if start_seg != self.module.normcase(dest_seg):\n', > ' break\n', > ' i += 1\n', > '\n', > ' # Now i is the point where the two paths diverge.\n', > ' # Need a certain number of "os.pardir"s to work up\n', > ' # from the origin to the point of divergence.\n', > ' segments = [os.pardir] * (len(orig_list) - i)\n', > ' # Need to add the diverging part of dest_list.\n', > ' segments += dest_list[i:]\n', > ' if len(segments) == 0:\n', > ' # If they happen to be identical, use os.curdir.\n', > ' relpath = os.curdir\n', > ' else:\n', > ' relpath = self.module.join(*segments)\n', > ' return self._next_class(relpath)\n', > '\n', > ' # --- Listing, searching, walking, and matching\n', > '\n', > ' def iterdir(self, match=None):\n', > ' """Yields items in this directory.\n', > '\n', > ' Use :meth:`files` or :meth:`dirs` instead if you want a listing\n', > ' of just files or just subdirectories.\n', > '\n', > ' The elements of the list are Path objects.\n', > '\n', > ' With the optional `match` argument, a callable,\n', > ' only return items whose names match the given pattern.\n', > '\n', > ' .. seealso:: :meth:`files`, :meth:`dirs`\n', > ' """\n', > ' match = matchers.load(match)\n', > ' return filter(match, (self / child for child in os.listdir(self)))\n', > '\n', > ' def dirs(self, *args, **kwargs):\n', > ' """List of this directory\'s subdirectories.\n', > '\n', > ' The elements of the list are Path objects.\n', > ' This does not walk recursively into subdirectories\n', > ' (but see :meth:`walkdirs`).\n', > '\n', > ' Accepts parameters to :meth:`iterdir`.\n', > ' """\n', > ' return [p for p in self.iterdir(*args, **kwargs) if p.is_dir()]\n', > '\n', > ' def files(self, *args, **kwargs):\n', > ' """List of the files in self.\n', > '\n', > ' The elements of the list are Path objects.\n', > ' This does not walk into subdirectories (see :meth:`walkfiles`).\n', > '\n', > ' Accepts parameters to :meth:`iterdir`.\n', > ' """\n', > '\n', > ' return [p for p in self.iterdir(*args, **kwargs) if p.is_file()]\n', > '\n', > " def walk(self, match=None, errors='strict'):\n", > ' """Iterator over files and subdirs, recursively.\n', > '\n', > ' The iterator yields Path objects naming each child item of\n', > ' this directory and its descendants. This requires that\n', > ' ``D.is_dir()``.\n', > '\n', > ' This performs a depth-first traversal of the directory tree.\n', > ' Each directory is returned just before all its children.\n', > '\n', > ' The `errors=` keyword argument controls behavior when an\n', > " error occurs. The default is ``'strict'``, which causes an\n", > " exception. Other allowed values are ``'warn'`` (which\n", > " reports the error via :func:`warnings.warn()`), and ``'ignore'``.\n", > ' `errors` may also be an arbitrary callable taking a msg parameter.\n', > ' """\n', > '\n', > ' errors = Handlers._resolve(errors)\n', > ' match = matchers.load(match)\n', > '\n', > ' try:\n', > ' childList = self.iterdir()\n', > ' except Exception as exc:\n', > ' errors(f"Unable to list directory \'{self}\': {exc}")\n', > ' return\n', > '\n', > ' for child in childList:\n', > ' traverse = None\n', > ' if match(child):\n', > ' traverse = yield child\n', > ' traverse = traverse or child.is_dir\n', > ' try:\n', > ' do_traverse = traverse()\n', > ' except Exception as exc:\n', > ' errors(f"Unable to access \'{child}\': {exc}")\n', > ' continue\n', > '\n', > ' if do_traverse:\n', > ' yield from child.walk(errors=errors, match=match)\n', > '\n', > ' def walkdirs(self, *args, **kwargs):\n', > ' """Iterator over subdirs, recursively."""\n', > ' return (item for item in self.walk(*args, **kwargs) if ' > 'item.is_dir())\n', > '\n', > ' def walkfiles(self, *args, **kwargs):\n', > ' """Iterator over files, recursively."""\n', > ' return (item for item in self.walk(*args, **kwargs) if ' > 'item.is_file())\n', > '\n', > ' def fnmatch(self, pattern, normcase=None):\n', > ' """Return ``True`` if `self.name` matches the given `pattern`.\n', > '\n', > ' `pattern` - A filename pattern with wildcards,\n', > " for example ``'*.py'``. If the pattern contains a `normcase`\n", > ' attribute, it is applied to the name and path prior to ' > 'comparison.\n', > '\n', > ' `normcase` - (optional) A function used to normalize the pattern ' > 'and\n', > ' filename before matching. Defaults to normcase from\n', > ' ``self.module``, :func:`os.path.normcase`.\n', > '\n', > ' .. seealso:: :func:`fnmatch.fnmatch`\n', > ' """\n', > " default_normcase = getattr(pattern, 'normcase', " > 'self.module.normcase)\n', > ' normcase = normcase or default_normcase\n', > ' name = normcase(self.name)\n', > ' pattern = normcase(pattern)\n', > ' return fnmatch.fnmatchcase(name, pattern)\n', > '\n', > ' def glob(self, pattern):\n', > ' """Return a list of Path objects that match the pattern.\n', > '\n', > ' `pattern` - a path relative to this directory, with wildcards.\n', > '\n', > " For example, ``Path('/users').glob('*/bin/*')`` returns a list\n", > ' of all the files users have in their :file:`bin` directories.\n', > '\n', > ' .. seealso:: :func:`glob.glob`\n', > '\n', > ' .. note:: Glob is **not** recursive, even when using ``**``.\n', > ' To do recursive globbing see :func:`walk`,\n', > ' :func:`walkdirs` or :func:`walkfiles`.\n', > ' """\n', > ' cls = self._next_class\n', > ' return [cls(s) for s in glob.glob(self / pattern)]\n', > '\n', > ' def iglob(self, pattern):\n', > ' """Return an iterator of Path objects that match the pattern.\n', > '\n', > ' `pattern` - a path relative to this directory, with wildcards.\n', > '\n', > " For example, ``Path('/users').iglob('*/bin/*')`` returns an\n", > ' iterator of all the files users have in their :file:`bin`\n', > ' directories.\n', > '\n', > ' .. seealso:: :func:`glob.iglob`\n', > '\n', > ' .. note:: Glob is **not** recursive, even when using ``**``.\n', > ' To do recursive globbing see :func:`walk`,\n', > ' :func:`walkdirs` or :func:`walkfiles`.\n', > ' """\n', > ' cls = self._next_class\n', > ' return (cls(s) for s in glob.iglob(self / pattern))\n', > '\n', > ' #\n', > ' # --- Reading or writing an entire file at once.\n', > '\n', > ' @functools.wraps(open, assigned=())\n', > ' def open(self, *args, **kwargs):\n', > ' """Open this file and return a corresponding file object.\n', > '\n', > ' Keyword arguments work as in :func:`io.open`. If the file cannot ' > 'be\n', > ' opened, an :class:`OSError` is raised.\n', > ' """\n', > ' return open(self, *args, **kwargs)\n', > '\n', > ' def bytes(self):\n', > ' """Open this file, read all bytes, return them as a string."""\n', > " with self.open('rb') as f:\n", > ' return f.read()\n', > '\n', > ' @overload\n', > ' def chunks(\n', > ' self,\n', > ' size: int,\n', > ' mode: OpenTextMode = ...,\n', > ' buffering: int = ...,\n', > ' encoding: str | None = ...,\n', > ' errors: str | None = ...,\n', > ' newline: str | None = ...,\n', > ' closefd: bool = ...,\n', > ' opener: Callable[[str, int], int] | None = ...,\n', > ' ) -> Iterator[str]: ...\n', > '\n', > ' @overload\n', > ' def chunks(\n', > ' self,\n', > ' size: int,\n', > ' mode: OpenBinaryMode,\n', > ' buffering: int = ...,\n', > ' encoding: str | None = ...,\n', > ' errors: str | None = ...,\n', > ' newline: str | None = ...,\n', > ' closefd: bool = ...,\n', > ' opener: Callable[[str, int], int] | None = ...,\n', > ' ) -> Iterator[builtins.bytes]: ...\n', > '\n', > ' @overload\n', > ' def chunks(\n', > ' self,\n', > ' size: int,\n', > ' mode: str,\n', > ' buffering: int = ...,\n', > ' encoding: str | None = ...,\n', > ' errors: str | None = ...,\n', > ' newline: str | None = ...,\n', > ' closefd: bool = ...,\n', > ' opener: Callable[[str, int], int] | None = ...,\n', > ' ) -> Iterator[str | builtins.bytes]: ...\n', > '\n', > ' def chunks(self, size, *args, **kwargs):\n', > ' """Returns a generator yielding chunks of the file, so it can\n', > ' be read piece by piece with a simple for loop.\n', > '\n', > ' Any argument you pass after `size` will be passed to :meth:`open`.\n', > '\n', > ' :example:\n', > '\n', > ' >>> hash = hashlib.md5()\n', > ' >>> for chunk in Path("NEWS.rst").chunks(8192, mode=\'rb\'):\n', > ' ... hash.update(chunk)\n', > '\n', > ' This will read the file by chunks of 8192 bytes.\n', > ' """\n', > ' with self.open(*args, **kwargs) as f:\n', > ' yield from iter(lambda: f.read(size) or None, None)\n', > '\n', > ' def write_bytes(self, bytes, append=False):\n', > ' """Open this file and write the given bytes to it.\n', > '\n', > ' Default behavior is to overwrite any existing file.\n', > ' Call ``p.write_bytes(bytes, append=True)`` to append instead.\n', > ' """\n', > " with self.open('ab' if append else 'wb') as f:\n", > ' f.write(bytes)\n', > '\n', > ' def read_text(self, encoding=None, errors=None):\n', > ' r"""Open this file, read it in, return the content as a string.\n', > '\n', > ' Optional parameters are passed to :meth:`open`.\n', > '\n', > ' .. seealso:: :meth:`lines`\n', > ' """\n', > ' with self.open(encoding=encoding, errors=errors) as f:\n', > ' return f.read()\n', > '\n', > ' def read_bytes(self):\n', > ' r"""Return the contents of this file as bytes."""\n', > " with self.open(mode='rb') as f:\n", > ' return f.read()\n', > '\n', > ' def write_text(\n', > ' self,\n', > ' text: str,\n', > ' encoding: str | None = None,\n', > " errors: str = 'strict',\n", > ' linesep: str | None = os.linesep,\n', > ' append: bool = False,\n', > ' ) -> None:\n', > ' r"""Write the given text to this file.\n', > '\n', > ' The default behavior is to overwrite any existing file;\n', > ' to append instead, use the `append=True` keyword argument.\n', > '\n', > ' There are two differences between :meth:`write_text` and\n', > ' :meth:`write_bytes`: newline handling and Unicode handling.\n', > ' See below.\n', > '\n', > ' Parameters:\n', > '\n', > ' `text` - str - The text to be written.\n', > '\n', > ' `encoding` - str - The text encoding used.\n', > '\n', > ' `errors` - str - How to handle Unicode encoding errors.\n', > " Default is ``'strict'``. See ``help(unicode.encode)`` for " > 'the\n', > " options. Ignored if `text` isn't a Unicode string.\n", > '\n', > ' `linesep` - keyword argument - str/unicode - The sequence of\n', > ' characters to be used to mark end-of-line. The default is\n', > ' :data:`os.linesep`. Specify ``None`` to\n', > ' use newlines unmodified.\n', > '\n', > ' `append` - keyword argument - bool - Specifies what to do if\n', > ' the file already exists (``True``: append to the end of it;\n', > ' ``False``: overwrite it). The default is ``False``.\n', > '\n', > '\n', > ' --- Newline handling.\n', > '\n', > ' ``write_text()`` converts all standard end-of-line sequences\n', > " (``'\\n'``, ``'\\r'``, and ``'\\r\\n'``) to your platform's " > 'default\n', > ' end-of-line sequence (see :data:`os.linesep`; on Windows, for ' > 'example,\n', > " the end-of-line marker is ``'\\r\\n'``).\n", > '\n', > " To override the platform's default, pass the `linesep=`\n", > ' keyword argument. To preserve the newlines as-is, pass\n', > ' ``linesep=None``.\n', > '\n', > ' This handling applies to Unicode text and bytes, except\n', > ' with Unicode, additional non-ASCII newlines are recognized:\n', > ' ``\\x85``, ``\\r\\x85``, and ``\\u2028``.\n', > '\n', > ' --- Unicode\n', > '\n', > ' `text` is written using the\n', > ' specified `encoding` (or the default encoding if `encoding`\n', > " isn't specified). The `errors` argument applies only to this\n", > ' conversion.\n', > ' """\n', > ' if linesep is not None:\n', > ' text = U_NEWLINE.sub(linesep, text)\n', > ' bytes = text.encode(encoding or sys.getdefaultencoding(), errors)\n', > ' self.write_bytes(bytes, append=append)\n', > '\n', > ' def lines(self, encoding=None, errors=None, retain=True):\n', > ' r"""Open this file, read all lines, return them in a list.\n', > '\n', > ' Optional arguments:\n', > ' `encoding` - The Unicode encoding (or character set) of\n', > ' the file. The default is ``None``, meaning use\n', > ' ``locale.getpreferredencoding()``.\n', > ' `errors` - How to handle Unicode errors; see\n', > ' `open ' > '<https://docs.python.org/3/library/functions.html#open>`_\n', > ' for the options. Default is ``None`` meaning "strict".\n', > ' `retain` - If ``True`` (default), retain newline characters,\n', > ' but translate all newline\n', > ' characters to ``\\n``. If ``False``, newline characters ' > 'are\n', > ' omitted.\n', > ' """\n', > " text = U_NEWLINE.sub('\\n', self.read_text(encoding, errors))\n", > ' return text.splitlines(retain)\n', > '\n', > ' def write_lines(\n', > ' self,\n', > ' lines,\n', > ' encoding=None,\n', > " errors='strict',\n", > ' *,\n', > ' append=False,\n', > ' ):\n', > ' r"""Write the given lines of text to this file.\n', > '\n', > ' By default this overwrites any existing file at this path.\n', > '\n', > ' Puts a platform-specific newline sequence on every line.\n', > '\n', > ' `lines` - A list of strings.\n', > '\n', > ' `encoding` - A Unicode encoding to use. This applies only if\n', > ' `lines` contains any Unicode strings.\n', > '\n', > ' `errors` - How to handle errors in Unicode encoding. This\n', > ' also applies only to Unicode strings.\n', > '\n', > ' Use the keyword argument ``append=True`` to append lines to the\n', > ' file. The default is to overwrite the file.\n', > ' """\n', > " mode = 'a' if append else 'w'\n", > " with self.open(mode, encoding=encoding, errors=errors, newline='') " > 'as f:\n', > ' f.writelines(self._replace_linesep(lines))\n', > '\n', > ' @staticmethod\n', > ' def _replace_linesep(lines):\n', > ' return (line + os.linesep for line in _strip_newlines(lines))\n', > '\n', > ' def read_md5(self):\n', > ' """Calculate the md5 hash for this file.\n', > '\n', > ' This reads through the entire file.\n', > '\n', > ' .. seealso:: :meth:`read_hash`\n', > ' """\n', > " return self.read_hash('md5')\n", > '\n', > ' def _hash(self, hash_name):\n', > ' """Returns a hash object for the file at the current path.\n', > '\n', > " `hash_name` should be a hash algo name (such as ``'md5'``\n", > " or ``'sha1'``) that's available in the :mod:`hashlib` module.\n", > ' """\n', > ' m = hashlib.new(hash_name)\n', > ' for chunk in self.chunks(8192, mode="rb"):\n', > ' m.update(chunk)\n', > ' return m\n', > '\n', > ' def read_hash(self, hash_name):\n', > ' """Calculate given hash for this file.\n', > '\n', > ' List of supported hashes can be obtained from :mod:`hashlib` ' > 'package.\n', > ' This reads the entire file.\n', > '\n', > ' .. seealso:: :meth:`hashlib.hash.digest`\n', > ' """\n', > ' return self._hash(hash_name).digest()\n', > '\n', > ' def read_hexhash(self, hash_name):\n', > ' """Calculate given hash for this file, returning hexdigest.\n', > '\n', > ' List of supported hashes can be obtained from :mod:`hashlib` ' > 'package.\n', > ' This reads the entire file.\n', > '\n', > ' .. seealso:: :meth:`hashlib.hash.hexdigest`\n', > ' """\n', > ' return self._hash(hash_name).hexdigest()\n', > '\n', > ' # --- Methods for querying the filesystem.\n', > ' # N.B. On some platforms, the os.path functions may be implemented in ' > 'C\n', > " # (e.g. isdir on Windows, Python 3.2.2), and compiled functions don't " > 'get\n', > ' # bound. Playing it safe and wrapping them all in method calls.\n', > '\n', > ' def isabs(self):\n', > ' """\n', > " >>> Path('.').isabs()\n", > ' False\n', > '\n', > ' .. seealso:: :func:`os.path.isabs`\n', > ' """\n', > ' return self.module.isabs(self)\n', > '\n', > ' def exists(self):\n', > ' """.. seealso:: :func:`os.path.exists`"""\n', > ' return self.module.exists(self)\n', > '\n', > ' def is_dir(self):\n', > ' """.. seealso:: :func:`os.path.isdir`"""\n', > ' return self.module.isdir(self)\n', > '\n', > ' def is_file(self):\n', > ' """.. seealso:: :func:`os.path.isfile`"""\n', > ' return self.module.isfile(self)\n', > '\n', > ' def islink(self):\n', > ' """.. seealso:: :func:`os.path.islink`"""\n', > ' return self.module.islink(self)\n', > '\n', > ' def ismount(self):\n', > ' """\n', > " >>> Path('.').ismount()\n", > ' False\n', > '\n', > ' .. seealso:: :func:`os.path.ismount`\n', > ' """\n', > ' return self.module.ismount(self)\n', > '\n', > ' def samefile(self, other):\n', > ' """.. seealso:: :func:`os.path.samefile`"""\n', > ' return self.module.samefile(self, other)\n', > '\n', > ' def getatime(self):\n', > ' """.. seealso:: :attr:`atime`, :func:`os.path.getatime`"""\n', > ' return self.module.getatime(self)\n', > '\n', > ' def set_atime(self, value):\n', > ' mtime_ns = self.stat().st_atime_ns\n', > ' self.utime(ns=(_make_timestamp_ns(value), mtime_ns))\n', > '\n', > ' atime = property(\n', > ' getatime,\n', > ' set_atime,\n', > ' None,\n', > ' """\n', > ' Last access time of the file.\n', > '\n', > " >>> Path('.').atime > 0\n", > ' True\n', > '\n', > ' Allows setting:\n', > '\n', > ' >>> some_file = ' > "Path(getfixture('tmp_path')).joinpath('file.txt').touch()\n", > ' >>> MST = datetime.timezone(datetime.timedelta(hours=-7))\n', > ' >>> some_file.atime = datetime.datetime(1976, 5, 7, 10, ' > 'tzinfo=MST)\n', > ' >>> some_file.atime\n', > ' 200336400.0\n', > '\n', > ' .. seealso:: :meth:`getatime`, :func:`os.path.getatime`\n', > ' """,\n', > ' )\n', > '\n', > ' def getmtime(self):\n', > ' """.. seealso:: :attr:`mtime`, :func:`os.path.getmtime`"""\n', > ' return self.module.getmtime(self)\n', > '\n', > ' def set_mtime(self, value):\n', > ' atime_ns = self.stat().st_atime_ns\n', > ' self.utime(ns=(atime_ns, _make_timestamp_ns(value)))\n', > '\n', > ' mtime = property(\n', > ' getmtime,\n', > ' set_mtime,\n', > ' None,\n', > ' """\n', > ' Last modified time of the file.\n', > '\n', > ' Allows setting:\n', > '\n', > ' >>> some_file = ' > "Path(getfixture('tmp_path')).joinpath('file.txt').touch()\n", > ' >>> MST = datetime.timezone(datetime.timedelta(hours=-7))\n', > ' >>> some_file.mtime = datetime.datetime(1976, 5, 7, 10, ' > 'tzinfo=MST)\n', > ' >>> some_file.mtime\n', > ' 200336400.0\n', > '\n', > ' .. seealso:: :meth:`getmtime`, :func:`os.path.getmtime`\n', > ' """,\n', > ' )\n', > '\n', > ' def getctime(self):\n', > ' """.. seealso:: :attr:`ctime`, :func:`os.path.getctime`"""\n', > ' return self.module.getctime(self)\n', > '\n', > ' ctime = property(\n', > ' getctime,\n', > ' None,\n', > ' None,\n', > ' """ Creation time of the file.\n', > '\n', > ' .. seealso:: :meth:`getctime`, :func:`os.path.getctime`\n', > ' """,\n', > ' )\n', > '\n', > ' def getsize(self):\n', > ' """.. seealso:: :attr:`size`, :func:`os.path.getsize`"""\n', > ' return self.module.getsize(self)\n', > '\n', > ' size = property(\n', > ' getsize,\n', > ' None,\n', > ' None,\n', > ' """ Size of the file, in bytes.\n', > '\n', > ' .. seealso:: :meth:`getsize`, :func:`os.path.getsize`\n', > ' """,\n', > ' )\n', > '\n', > ' @property\n', > ' def permissions(self) -> masks.Permissions:\n', > ' """\n', > ' Permissions.\n', > '\n', > " >>> perms = Path('.').permissions\n", > ' >>> isinstance(perms, int)\n', > ' True\n', > " >>> set(perms.symbolic) <= set('rwx-')\n", > ' True\n', > ' >>> perms.symbolic\n', > " 'r...'\n", > ' """\n', > ' return masks.Permissions(self.stat().st_mode)\n', > '\n', > ' def access(self, *args, **kwargs):\n', > ' """\n', > ' Return does the real user have access to this path.\n', > '\n', > " >>> Path('.').access(os.F_OK)\n", > ' True\n', > '\n', > ' .. seealso:: :func:`os.access`\n', > ' """\n', > ' return os.access(self, *args, **kwargs)\n', > '\n', > ' def stat(self, *, follow_symlinks=True):\n', > ' """\n', > ' Perform a ``stat()`` system call on this path.\n', > '\n', > " >>> Path('.').stat()\n", > ' os.stat_result(...)\n', > '\n', > ' .. seealso:: :meth:`lstat`, :func:`os.stat`\n', > ' """\n', > ' return os.stat(self, follow_symlinks=follow_symlinks)\n', > '\n', > ' def lstat(self):\n', > ' """\n', > ' Like :meth:`stat`, but do not follow symbolic links.\n', > '\n', > " >>> Path('.').lstat() == Path('.').stat()\n", > ' True\n', > '\n', > ' .. seealso:: :meth:`stat`, :func:`os.lstat`\n', > ' """\n', > ' return os.lstat(self)\n', > '\n', > ' def __get_owner_windows(self): # pragma: nocover\n', > ' r"""\n', > ' Return the name of the owner of this file or directory. Follow\n', > ' symbolic links.\n', > '\n', > ' Return a name of the form ``DOMAIN\\User Name``; may be a group.\n', > '\n', > ' .. seealso:: :attr:`owner`\n', > ' """\n', > ' desc = win32security.GetFileSecurity(\n', > ' self, win32security.OWNER_SECURITY_INFORMATION\n', > ' )\n', > ' sid = desc.GetSecurityDescriptorOwner()\n', > ' account, domain, typecode = win32security.LookupAccountSid(None, ' > 'sid)\n', > " return domain + '\\\\' + account\n", > '\n', > ' def __get_owner_unix(self): # pragma: nocover\n', > ' """\n', > ' Return the name of the owner of this file or directory. Follow\n', > ' symbolic links.\n', > '\n', > ' .. seealso:: :attr:`owner`\n', > ' """\n', > ' st = self.stat()\n', > ' return pwd.getpwuid(st.st_uid).pw_name\n', > '\n', > ' def __get_owner_not_implemented(self): # pragma: nocover\n', > ' raise NotImplementedError("Ownership not available on this ' > 'platform.")\n', > '\n', > ' get_owner = (\n', > ' __get_owner_windows\n', > " if 'win32security' in globals()\n", > ' else __get_owner_unix\n', > " if 'pwd' in globals()\n", > ' else __get_owner_not_implemented\n', > ' )\n', > '\n', > ' owner = property(\n', > ' get_owner,\n', > ' None,\n', > ' None,\n', > ' """ Name of the owner of this file or directory.\n', > '\n', > ' .. seealso:: :meth:`get_owner`""",\n', > ' )\n', > '\n', > " if 'grp' in globals(): # pragma: no cover\n", > '\n', > ' def group(self, *, follow_symlinks=True):\n', > ' """\n', > ' Return the group name of the file gid.\n', > ' """\n', > ' gid = self.stat(follow_symlinks=follow_symlinks).st_gid\n', > ' return grp.getgrgid(gid).gr_name\n', > '\n', > " if hasattr(os, 'statvfs'):\n", > '\n', > ' def statvfs(self):\n', > ' """Perform a ``statvfs()`` system call on this path.\n', > '\n', > ' .. seealso:: :func:`os.statvfs`\n', > ' """\n', > ' return os.statvfs(self)\n', > '\n', > " if hasattr(os, 'pathconf'):\n", > '\n', > ' def pathconf(self, name):\n', > ' """.. seealso:: :func:`os.pathconf`"""\n', > ' return os.pathconf(self, name)\n', > '\n', > ' #\n', > ' # --- Modifying operations on files and directories\n', > '\n', > ' def utime(self, *args, **kwargs):\n', > ' """Set the access and modified times of this file.\n', > '\n', > ' .. seealso:: :func:`os.utime`\n', > ' """\n', > ' os.utime(self, *args, **kwargs)\n', > ' return self\n', > '\n', > ' def chmod(self, mode):\n', > ' """\n', > ' Set the mode. May be the new mode (os.chmod behavior) or a ' > '`symbolic\n', > ' mode <http://en.wikipedia.org/wiki/Chmod#Symbolic_modes>`_.\n', > '\n', > ' >>> a_file = ' > "Path(getfixture('tmp_path')).joinpath('afile.txt').touch()\n", > ' >>> a_file.chmod(0o700)\n', > ' Path(...\n', > " >>> a_file.chmod('u+x')\n", > ' Path(...\n', > '\n', > ' .. seealso:: :func:`os.chmod`\n', > ' """\n', > ' if isinstance(mode, str):\n', > ' mask = masks.compound(mode)\n', > ' mode = mask(self.stat().st_mode)\n', > ' os.chmod(self, mode)\n', > ' return self\n', > '\n', > " if hasattr(os, 'chown'):\n", > '\n', > ' def chown(self, uid=-1, gid=-1):\n', > ' """\n', > ' Change the owner and group by names or numbers.\n', > '\n', > ' .. seealso:: :func:`os.chown`\n', > ' """\n', > '\n', > ' def resolve_uid(uid):\n', > ' return uid if isinstance(uid, int) else ' > 'pwd.getpwnam(uid).pw_uid\n', > '\n', > ' def resolve_gid(gid):\n', > ' return gid if isinstance(gid, int) else ' > 'grp.getgrnam(gid).gr_gid\n', > '\n', > ' os.chown(self, resolve_uid(uid), resolve_gid(gid))\n', > ' return self\n', > '\n', > ' def rename(self, new):\n', > ' """.. seealso:: :func:`os.rename`"""\n', > ' os.rename(self, new)\n', > ' return self._next_class(new)\n', > '\n', > ' def renames(self, new):\n', > ' """.. seealso:: :func:`os.renames`"""\n', > ' os.renames(self, new)\n', > ' return self._next_class(new)\n', > '\n', > ' def replace(self, target_or_old: Path | str, *args) -> Path:\n', > ' """\n', > ' Replace a path or substitute substrings.\n', > '\n', > ' Implements both pathlib.Path.replace and str.replace.\n', > '\n', > ' If only a target is supplied, rename this path to the target path,\n', > ' overwriting if that path exists.\n', > '\n', > " >>> dest = Path(getfixture('tmp_path'))\n", > " >>> orig = dest.joinpath('foo').touch()\n", > " >>> new = orig.replace(dest.joinpath('fee'))\n", > ' >>> orig.exists()\n', > ' False\n', > ' >>> new.exists()\n', > ' True\n', > '\n', > ' ..seealso:: :meth:`pathlib.Path.replace`\n', > '\n', > ' If a second parameter is supplied, perform a textual replacement.\n', > '\n', > " >>> Path('foo').replace('o', 'e')\n", > " Path('fee')\n", > " >>> Path('foo').replace('o', 'l', 1)\n", > " Path('flo')\n", > '\n', > ' ..seealso:: :meth:`str.replace`\n', > ' """\n', > ' return self._next_class(\n', > ' super().replace(target_or_old, *args)\n', > ' if args\n', > ' else pathlib.Path(self).replace(target_or_old)\n', > ' )\n', > '\n', > ' #\n', > ' # --- Create/delete operations on directories\n', > '\n', > ' def mkdir(self, mode=0o777):\n', > ' """.. seealso:: :func:`os.mkdir`"""\n', > ' os.mkdir(self, mode)\n', > ' return self\n', > '\n', > ' def mkdir_p(self, mode=0o777):\n', > ' """Like :meth:`mkdir`, but does not raise an exception if the\n', > ' directory already exists."""\n', > ' with contextlib.suppress(FileExistsError):\n', > ' self.mkdir(mode)\n', > ' return self\n', > '\n', > ' def makedirs(self, mode=0o777):\n', > ' """.. seealso:: :func:`os.makedirs`"""\n', > ' os.makedirs(self, mode)\n', > ' return self\n', > '\n', > ' def makedirs_p(self, mode=0o777):\n', > ' """Like :meth:`makedirs`, but does not raise an exception if the\n', > ' directory already exists."""\n', > ' with contextlib.suppress(FileExistsError):\n', > ' self.makedirs(mode)\n', > ' return self\n', > '\n', > ' def rmdir(self):\n', > ' """.. seealso:: :func:`os.rmdir`"""\n', > ' os.rmdir(self)\n', > ' return self\n', > '\n', > ' def rmdir_p(self):\n', > ' """Like :meth:`rmdir`, but does not raise an exception if the\n', > ' directory is not empty or does not exist."""\n', > ' suppressed = FileNotFoundError, FileExistsError, DirectoryNotEmpty\n', > ' with contextlib.suppress(suppressed):\n', > ' with DirectoryNotEmpty.translate():\n', > ' self.rmdir()\n', > ' return self\n', > '\n', > ' def removedirs(self):\n', > ' """.. seealso:: :func:`os.removedirs`"""\n', > ' os.removedirs(self)\n', > ' return self\n', > '\n', > ' def removedirs_p(self):\n', > ' """Like :meth:`removedirs`, but does not raise an exception if the\n', > ' directory is not empty or does not exist."""\n', > ' with contextlib.suppress(FileExistsError, DirectoryNotEmpty):\n', > ' with DirectoryNotEmpty.translate():\n', > ' self.removedirs()\n', > ' return self\n', > '\n', > ' # --- Modifying operations on files\n', > '\n', > ' def touch(self):\n', > ' """Set the access/modified times of this file to the current time.\n', > ' Create the file if it does not exist.\n', > ' """\n', > ' os.close(os.open(self, os.O_WRONLY | os.O_CREAT, 0o666))\n', > ' os.utime(self, None)\n', > ' return self\n', > '\n', > ' def remove(self):\n', > ' """.. seealso:: :func:`os.remove`"""\n', > ' os.remove(self)\n', > ' return self\n', > '\n', > ' def remove_p(self):\n', > ' """Like :meth:`remove`, but does not raise an exception if the\n', > ' file does not exist."""\n', > ' with contextlib.suppress(FileNotFoundError):\n', > ' self.unlink()\n', > ' return self\n', > '\n', > ' unlink = remove\n', > ' unlink_p = remove_p\n', > '\n', > ' # --- Links\n', > '\n', > ' def hardlink_to(self, target: str) -> None:\n', > ' """\n', > ' Create a hard link at self, pointing to target.\n', > '\n', > ' .. seealso:: :func:`os.link`\n', > ' """\n', > ' os.link(target, self)\n', > '\n', > ' def link(self, newpath):\n', > ' """Create a hard link at `newpath`, pointing to this file.\n', > '\n', > ' .. seealso:: :func:`os.link`\n', > ' """\n', > ' os.link(self, newpath)\n', > ' return self._next_class(newpath)\n', > '\n', > ' def symlink_to(self, target: str, target_is_directory: bool = False) -> ' > 'None:\n', > ' """\n', > ' Create a symbolic link at self, pointing to target.\n', > '\n', > ' .. seealso:: :func:`os.symlink`\n', > ' """\n', > ' os.symlink(target, self, target_is_directory)\n', > '\n', > ' def symlink(self, newlink=None):\n', > ' """Create a symbolic link at `newlink`, pointing here.\n', > '\n', > ' If newlink is not supplied, the symbolic link will assume\n', > ' the name self.basename(), creating the link in the cwd.\n', > '\n', > ' .. seealso:: :func:`os.symlink`\n', > ' """\n', > ' if newlink is None:\n', > ' newlink = self.basename()\n', > ' os.symlink(self, newlink)\n', > ' return self._next_class(newlink)\n', > '\n', > ' def readlink(self):\n', > ' """Return the path to which this symbolic link points.\n', > '\n', > ' The result may be an absolute or a relative path.\n', > '\n', > ' .. seealso:: :meth:`readlinkabs`, :func:`os.readlink`\n', > ' """\n', > ' return self._next_class(removeprefix(os.readlink(self), ' > "'\\\\\\\\?\\\\'))\n", > '\n', > ' def readlinkabs(self):\n', > ' """Return the path to which this symbolic link points.\n', > '\n', > ' The result is always an absolute path.\n', > '\n', > ' .. seealso:: :meth:`readlink`, :func:`os.readlink`\n', > ' """\n', > ' p = self.readlink()\n', > ' return p if p.isabs() else (self.parent / p).absolute()\n', > '\n', > ' # High-level functions from shutil\n', > ' # These functions will be bound to the instance such that\n', > ' # Path(name).copy(target) will invoke shutil.copy(name, target)\n', > '\n', > ' copyfile = shutil.copyfile\n', > ' copymode = shutil.copymode\n', > ' copystat = shutil.copystat\n', > ' copy = shutil.copy\n', > ' copy2 = shutil.copy2\n', > ' copytree = shutil.copytree\n', > " if hasattr(shutil, 'move'):\n", > ' move = shutil.move\n', > ' rmtree = shutil.rmtree\n', > '\n', > ' def rmtree_p(self):\n', > ' """Like :meth:`rmtree`, but does not raise an exception if the\n', > ' directory does not exist."""\n', > ' with contextlib.suppress(FileNotFoundError):\n', > ' self.rmtree()\n', > ' return self\n', > '\n', > ' def chdir(self):\n', > ' """.. seealso:: :func:`os.chdir`"""\n', > ' os.chdir(self)\n', > '\n', > ' cd = chdir\n', > '\n', > ' def merge_tree(\n', > ' self,\n', > ' dst,\n', > ' symlinks=False,\n', > ' *,\n', > ' copy_function=shutil.copy2,\n', > ' ignore=lambda dir, contents: [],\n', > ' ):\n', > ' """\n', > ' Copy entire contents of self to dst, overwriting existing\n', > ' contents in dst with those in self.\n', > '\n', > ' Pass ``symlinks=True`` to copy symbolic links as links.\n', > '\n', > ' Accepts a ``copy_function``, similar to copytree.\n', > '\n', > ' To avoid overwriting newer files, supply a copy function\n', > ' wrapped in ``only_newer``. For example::\n', > '\n', > ' src.merge_tree(dst, copy_function=only_newer(shutil.copy2))\n', > ' """\n', > ' dst = self._next_class(dst)\n', > ' dst.makedirs_p()\n', > '\n', > ' sources = list(self.iterdir())\n', > ' _ignored = ignore(self, [item.name for item in sources])\n', > '\n', > ' def ignored(item):\n', > ' return item.name in _ignored\n', > '\n', > ' for source in itertools.filterfalse(ignored, sources):\n', > ' dest = dst / source.name\n', > ' if symlinks and source.islink():\n', > ' target = source.readlink()\n', > ' target.symlink(dest)\n', > ' elif source.is_dir():\n', > ' source.merge_tree(\n', > ' dest,\n', > ' symlinks=symlinks,\n', > ' copy_function=copy_function,\n', > ' ignore=ignore,\n', > ' )\n', > ' else:\n', > ' copy_function(source, dest)\n', > '\n', > ' self.copystat(dst)\n', > '\n', > ' #\n', > ' # --- Special stuff from os\n', > '\n', > " if hasattr(os, 'chroot'):\n", > '\n', > ' def chroot(self): # pragma: nocover\n', > ' """.. seealso:: :func:`os.chroot`"""\n', > ' os.chroot(self)\n', > '\n', > " if hasattr(os, 'startfile'):\n", > '\n', > ' def startfile(self, *args, **kwargs): # pragma: nocover\n', > ' """.. seealso:: :func:`os.startfile`"""\n', > ' os.startfile(self, *args, **kwargs)\n', > ' return self\n', > '\n', > ' # in-place re-writing, courtesy of Martijn Pieters\n', > ' # http://www.zopatista.com/python/2013/11/26/inplace-file-rewriting/\n', > ' @contextlib.contextmanager\n', > ' def in_place(\n', > ' self,\n', > " mode='r',\n", > ' buffering=-1,\n', > ' encoding=None,\n', > ' errors=None,\n', > ' newline=None,\n', > ' backup_extension=None,\n', > ' ):\n', > ' """\n', > ' A context in which a file may be re-written in-place with\n', > ' new content.\n', > '\n', > ' Yields a tuple of :samp:`({readable}, {writable})` file\n', > ' objects, where `writable` replaces `readable`.\n', > '\n', > ' If an exception occurs, the old file is restored, removing the\n', > ' written data.\n', > '\n', > " Mode *must not* use ``'w'``, ``'a'``, or ``'+'``; only\n", > ' read-only-modes are allowed. A :exc:`ValueError` is raised\n', > ' on invalid modes.\n', > '\n', > ' For example, to add line numbers to a file::\n', > '\n', > ' p = Path(filename)\n', > ' assert p.is_file()\n', > ' with p.in_place() as (reader, writer):\n', > ' for number, line in enumerate(reader, 1):\n', > " writer.write('{0:3}: '.format(number)))\n", > ' writer.write(line)\n', > '\n', > ' Thereafter, the file at `filename` will have line numbers in it.\n', > ' """\n', > " if set(mode).intersection('wa+'):\n", > " raise ValueError('Only read-only file modes can be used')\n", > '\n', > ' # move existing file to backup, create new file with same ' > 'permissions\n', > ' # borrowed extensively from the fileinput module\n', > " backup_fn = self + (backup_extension or os.extsep + 'bak')\n", > ' backup_fn.remove_p()\n', > ' self.rename(backup_fn)\n', > ' readable = open(\n', > ' backup_fn,\n', > ' mode,\n', > ' buffering=buffering,\n', > ' encoding=encoding,\n', > ' errors=errors,\n', > ' newline=newline,\n', > ' )\n', > '\n', > ' perm = os.stat(readable.fileno()).st_mode\n', > ' os_mode = os.O_CREAT | os.O_WRONLY | os.O_TRUNC\n', > " os_mode |= getattr(os, 'O_BINARY', 0)\n", > ' fd = os.open(self, os_mode, perm)\n', > ' writable = open(\n', > ' fd,\n', > ' "w" + mode.replace(\'r\', \'\'),\n', > ' buffering=buffering,\n', > ' encoding=encoding,\n', > ' errors=errors,\n', > ' newline=newline,\n', > ' )\n', > ' with contextlib.suppress(OSError, AttributeError):\n', > ' self.chmod(perm)\n', > '\n', > ' try:\n', > ' yield readable, writable\n', > ' except Exception:\n', > ' # move backup back\n', > ' readable.close()\n', > ' writable.close()\n', > ' self.remove_p()\n', > ' backup_fn.rename(self)\n', > ' raise\n', > ' else:\n', > ' readable.close()\n', > ' writable.close()\n', > ' finally:\n', > ' backup_fn.remove_p()\n', > '\n', > ' @classes.ClassProperty\n', > ' @classmethod\n', > ' def special(cls):\n', > ' """\n', > ' Return a SpecialResolver object suitable referencing a suitable\n', > ' directory for the relevant platform for the given\n', > ' type of content.\n', > '\n', > ' For example, to get a user config directory, invoke:\n', > '\n', > ' dir = Path.special().user.config\n', > '\n', > ' Uses the `appdirs\n', > ' <https://pypi.python.org/pypi/appdirs/1.4.0>`_ to resolve\n', > ' the paths in a platform-friendly way.\n', > '\n', > " To create a config directory for 'My App', consider:\n", > '\n', > ' dir = Path.special("My App").user.config.makedirs_p()\n', > '\n', > ' If the ``appdirs`` module is not installed, invocation\n', > ' of special will raise an ImportError.\n', > ' """\n', > ' return functools.partial(SpecialResolver, cls)\n', > '\n', > '\n', > 'class DirectoryNotEmpty(OSError):\n', > ' @staticmethod\n', > ' @contextlib.contextmanager\n', > ' def translate():\n', > ' try:\n', > ' yield\n', > ' except OSError as exc:\n', > ' if exc.errno == errno.ENOTEMPTY:\n', > ' raise DirectoryNotEmpty(*exc.args) from exc\n', > ' raise\n', > '\n', > '\n', > 'def only_newer(copy_func):\n', > ' """\n', > ' Wrap a copy function (like shutil.copy2) to return\n', > " the dst if it's newer than the source.\n", > ' """\n', > '\n', > ' @functools.wraps(copy_func)\n', > ' def wrapper(src, dst, *args, **kwargs):\n', > ' is_newer_dst = dst.exists() and dst.getmtime() >= src.getmtime()\n', > ' if is_newer_dst:\n', > ' return dst\n', > ' return copy_func(src, dst, *args, **kwargs)\n', > '\n', > ' return wrapper\n', > '\n', > '\n', > 'class ExtantPath(Path):\n', > ' """\n', > " >>> ExtantPath('.')\n", > " ExtantPath('.')\n", > " >>> ExtantPath('does-not-exist')\n", > ' Traceback (most recent call last):\n', > ' OSError: does-not-exist does not exist.\n', > ' """\n', > '\n', > ' def _validate(self):\n', > ' if not self.exists():\n', > ' raise OSError(f"{self} does not exist.")\n', > '\n', > '\n', > 'class ExtantFile(Path):\n', > ' """\n', > " >>> ExtantFile('.')\n", > ' Traceback (most recent call last):\n', > ' FileNotFoundError: . does not exist as a file.\n', > " >>> ExtantFile('does-not-exist')\n", > ' Traceback (most recent call last):\n', > ' FileNotFoundError: does-not-exist does not exist as a file.\n', > ' """\n', > '\n', > ' def _validate(self):\n', > ' if not self.is_file():\n', > ' raise FileNotFoundError(f"{self} does not exist as a file.")\n', > '\n', > '\n', > 'class SpecialResolver:\n', > ' class ResolverScope:\n', > ' def __init__(self, paths, scope):\n', > ' self.paths = paths\n', > ' self.scope = scope\n', > '\n', > ' def __getattr__(self, class_):\n', > ' return self.paths.get_dir(self.scope, class_)\n', > '\n', > ' def __init__(self, path_class, *args, **kwargs):\n', > " appdirs = importlib.import_module('appdirs')\n", > '\n', > ' vars(self).update(\n', > ' path_class=path_class, wrapper=appdirs.AppDirs(*args, ' > '**kwargs)\n', > ' )\n', > '\n', > ' def __getattr__(self, scope):\n', > ' return self.ResolverScope(self, scope)\n', > '\n', > ' def get_dir(self, scope, class_):\n', > ' """\n', > ' Return the callable function from appdirs, but with the\n', > ' result wrapped in self.path_class\n', > ' """\n', > " prop_name = f'{scope}_{class_}_dir'\n", > ' value = getattr(self.wrapper, prop_name)\n', > ' MultiPath = Multi.for_class(self.path_class)\n', > ' return MultiPath.detect(value)\n', > '\n', > '\n', > 'class Multi:\n', > ' """\n', > ' A mix-in for a Path which may contain multiple Path separated by ' > 'pathsep.\n', > ' """\n', > '\n', > ' @classmethod\n', > ' def for_class(cls, path_cls):\n', > " name = 'Multi' + path_cls.__name__\n", > ' return type(name, (cls, path_cls), {})\n', > '\n', > ' @classmethod\n', > ' def detect(cls, input):\n', > ' if os.pathsep not in input:\n', > ' cls = cls._next_class\n', > ' return cls(input)\n', > '\n', > ' def __iter__(self):\n', > ' return iter(map(self._next_class, self.split(os.pathsep)))\n', > '\n', > ' @classes.ClassProperty\n', > ' @classmethod\n', > ' def _next_class(cls):\n', > ' """\n', > ' Multi-subclasses should use the parent class\n', > ' """\n', > ' return next(class_ for class_ in cls.__mro__ if not ' > 'issubclass(class_, Multi))\n', > '\n', > '\n', > 'class TempDir(Path):\n', > ' """\n', > ' A temporary directory via :func:`tempfile.mkdtemp`, and\n', > ' constructed with the same parameters that you can use\n', > ' as a context manager.\n', > '\n', > ' For example:\n', > '\n', > ' >>> with TempDir() as d:\n', > ' ... d.is_dir() and isinstance(d, Path)\n', > ' True\n', > '\n', > ' The directory is deleted automatically.\n', > '\n', > ' >>> d.is_dir()\n', > ' False\n', > '\n', > ' .. seealso:: :func:`tempfile.mkdtemp`\n', > ' """\n', > '\n', > ' @classes.ClassProperty\n', > ' @classmethod\n', > ' def _next_class(cls):\n', > ' return Path\n', > '\n', > ' def __new__(cls, *args, **kwargs):\n', > ' dirname = tempfile.mkdtemp(*args, **kwargs)\n', > ' return super().__new__(cls, dirname)\n', > '\n', > ' def __init__(self, *args, **kwargs):\n', > ' pass\n', > '\n', > ' def __enter__(self):\n', > ' # TempDir should return a Path version of itself and not itself\n', > ' # so that a second context manager does not create a second\n', > ' # temporary directory, but rather changes CWD to the location\n', > ' # of the temporary directory.\n', > ' return self._next_class(self)\n', > '\n', > ' def __exit__(self, exc_type, exc_value, traceback):\n', > ' self.rmtree()\n', > '\n', > '\n', > 'class Handlers:\n', > ' def strict(msg):\n', > ' raise\n', > '\n', > ' def warn(msg):\n', > ' warnings.warn(msg, TreeWalkWarning, stacklevel=2)\n', > '\n', > ' def ignore(msg):\n', > ' pass\n', > '\n', > ' @classmethod\n', > ' def _resolve(cls, param):\n', > ' if not callable(param) and param not in vars(Handlers):\n', > ' raise ValueError("invalid errors parameter")\n', > ' return vars(cls).get(param, param)\n'] >[36m[1m=========================================================================== short test summary info ============================================================================[0m >[31mERROR[0m path/__init__.py - AttributeError: 'builtin_function_or_method' object has no attribute '__code__'. Did you mean: '__call__'? >!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! >[31m=============================================================================== [31m[1m1 error[0m[31m in 1.13s[0m[31m ===============================================================================[0m >pytest-xprocess reminder::Be sure to terminate the started process by running 'pytest --xkill' if you have not explicitly done so in your fixture with 'xprocess.getinfo(<process_name>).terminate()'. > [31;01m*[0m ERROR: dev-python/path-17.0.0::gentoo failed (test phase): > [31;01m*[0m pytest failed with python3.12 > [31;01m*[0m > [31;01m*[0m Call stack: > [31;01m*[0m ebuild.sh, line 136: Called src_test > [31;01m*[0m environment, line 4142: Called distutils-r1_src_test > [31;01m*[0m environment, line 2060: Called _distutils-r1_run_foreach_impl 'python_test' > [31;01m*[0m environment, line 791: Called python_foreach_impl 'distutils-r1_run_phase' 'python_test' > [31;01m*[0m environment, line 3703: Called multibuild_foreach_variant '_python_multibuild_wrapper' 'distutils-r1_run_phase' 'python_test' > [31;01m*[0m environment, line 3179: Called _multibuild_run '_python_multibuild_wrapper' 'distutils-r1_run_phase' 'python_test' > [31;01m*[0m environment, line 3177: Called _python_multibuild_wrapper 'distutils-r1_run_phase' 'python_test' > [31;01m*[0m environment, line 1283: Called distutils-r1_run_phase 'python_test' > [31;01m*[0m environment, line 1983: Called python_test > [31;01m*[0m environment, line 3992: Called distutils-r1_python_test > [31;01m*[0m environment, line 1929: Called epytest > [31;01m*[0m environment, line 2605: Called die > [31;01m*[0m The specific snippet of code: > [31;01m*[0m [[ ${ret} -ne 0 ]] && die -n "pytest failed with ${EPYTHON}"; > [31;01m*[0m > [31;01m*[0m If you need support, post the output of `emerge --info '=dev-python/path-17.0.0::gentoo'`, > [31;01m*[0m the complete build log and the output of `emerge -pqv '=dev-python/path-17.0.0::gentoo'`. > [31;01m*[0m The complete build log is located at '/var/log/portage/dev-python:path-17.0.0:20240819-133450.log'. > [31;01m*[0m For convenience, a symlink to the build log is located at '/var/tmp/portage/dev-python/path-17.0.0/temp/build.log'. > [31;01m*[0m The ebuild environment file is located at '/var/tmp/portage/dev-python/path-17.0.0/temp/environment'. > [31;01m*[0m Working directory: '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0' > [31;01m*[0m S: '/var/tmp/portage/dev-python/path-17.0.0/work/path-17.0.0'
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 938210
: 900727 |
900728