backport of pathlib 3.10 to python 3.6, 3.7, 3.8, 3.9 with a few extensions
Project description
pathlib3x
Version v2.0.3 as of 2023-07-20 see Changelog
Backport of Python 3.11.0a0 pathlib for Python 3.6, 3.7, 3.8, 3.9, 3.10 with a few tweaks to make it compatible.
added wrappers to shutil copy, copy2, rmtree, copytree and other useful functions.
fully typed PEP561 package
this will be updated periodically to have the latest version of pathlib available on 3.6, 3.7, 3.8, 3.9, 3.10 and probably others.
WHY pathlib3x ?
There are a number of small, but very handy features added in pathlib over the last python versions, so I want to be able to use those also on older python versions.
if You are used to :
import pathlib
pathlib.Path('some_file').unlink(missing_ok=True)
You will have no luck on python 3.7 - because the “missing_ok” parameter was added in python3.8
Of course You can do :
import pathlib
try:
pathlib.Path('some_file').unlink()
except FileNotFoundError:
pass
but that clutters the code unnecessarily. So just use :
import pathlib3x as pathlib
and You can enjoy the latest pathlib features even on older python versions.
Some own extensions to that pathlib will be added probably over time. At the moment we added some wrappers to shutil like “copy”, “rmtree”, “copytree”, so You can do :
import pathlib3x as pathlib
my_file = pathlib.Path('/etc/hosts')
to_file = pathlib.Path('/tmp/foo')
my_file.copy(to_file)
If You have some nice features for pathlib, let me know - I will consider to integrate them.
automated tests, Github Actions, Documentation, Badges, etc. are managed with PizzaCutter (cookiecutter on steroids)
Python version required: 3.8.0 or newer
tested on recent linux with python 3.8, 3.9, 3.10, 3.11, 3.12-dev, pypy-3.9, pypy-3.10 - architectures: amd64
100% (for my added functions) code coverage, flake8 style checking ,mypy static type checking ,tested under Linux, macOS, Windows, automatic daily builds and monitoring
Usage
just check out the latest python documentation : https://docs.python.org/3/library/pathlib.html and select 3.10 Branch
Additional Features are documented here :
- PurePath.append_suffix(suffix)
Return a new path with the suffix appended. If the original path doesn’t have a suffix, the new suffix is appended. If the original path have a suffix, the new suffix will be appended at the end. If suffix is an empty string the original Path will be returned.
>>> p = PureWindowsPath('c:/Downloads/pathlib.tar.gz')
>>> p.append_suffix('.bz2')
PureWindowsPath('c:/Downloads/pathlib.tar.gz.bz2')
>>> p = PureWindowsPath('README')
>>> p.append_suffix('.txt')
PureWindowsPath('README.txt')
>>> p = PureWindowsPath('README.txt')
>>> p.append_suffix('')
PureWindowsPath('README.txt')
- PurePath.is_path_instance(__obj)
Return True if __obj is instance of the original pathlib.Path or pathlib3x.Path. Useful if You need to check for Path type, in an environment were You mix pathlib and pathlib3x
>>> import pathlib3x
>>> import pathlib
>>> pathlib3x_path = pathlib3x.Path('some_path') # this might happen in another module !
>>> pathlib_path = pathlib.Path('some_path')
>>> isinstance(pathlib3x_path, pathlib.Path)
False
>>> isinstance(pathlib_path, pathlib3x.Path)
False
# in such cases were You need to mix pathlib and pathlib3x in different modules, use:
>>> pathlib3x_path.Path.is_path_instance(pathlib3x_path)
True
>>> pathlib3x_path.Path.is_path_instance(pathlib_path)
True
- PurePath.replace_parts(old, new, count=-1)
Return a new Path with parts replaced. If the Original Path or old has no parts, the Original Path will be returned. On Windows, the replacement operation is not case sensitive, because of case folding on drives, directory and filenames. You can also replace absolute paths with relative paths what is quite handy - just be aware that the results might look unexpected, especially on Windows.
old, new can be pathlib.Path or Path-like objects
if the Original Path is resolved, You should probably also resolve old and new - because if symlinks are involved, the results might be unexpected.
be aware of case folding in windows, the file “c:/Test/test.txt” is the same as “c:/test/Test.TXT”
>>> p = PureWindowsPath('c:/Downloads/pathlib.tar.gz')
>>> p.replace_parts(PureWindowsPath('C:/downloads'), PureWindowsPath('D:/uploads'))
PureWindowsPath('D:/uploads/pathlib.tar.gz')
>>> p = PureWindowsPath('c:/Downloads/pathlib.tar.gz')
>>> p.replace_parts('C:/downloads','D:/uploads')
PureWindowsPath('D:/uploads/pathlib.tar.gz')
# handy to replace source directories with target directories on copy or move operations :
>>> source_dir = pathlib.Path('c:/source_dir')
>>> target_dir = pathlib.Path('c:/target_dir')
>>> source_files = source_dir.glob('**/*.txt')
>>> for source in source_files:
target = source.replace_parts(source_dir, target_dir)
... source.copy(target)
# this will always return PureWindowsPath(), because PureWindowsPath('.') has no parts to replace
>>> p = PureWindowsPath('.')
>>> p.replace_parts('.', 'test')
PureWindowsPath()
# looks unexpected but is correct, since PureWindowsPath('/uploads') is a relative path in Windows
>>> p = PureWindowsPath('c:/Downloads/pathlib.tar.gz')
>>> p.replace_parts('C:/downloads', '/uploads')
PureWindowsPath('uploads/pathlib.tar.gz')
# take care when replace, it might match on parts You are not aware of
>>> p = PureWindowsPath('c:/downloads/Downloads.tar.gz')
>>> p.replace_parts('downloads', 'uploads')
PureWindowsPath('c:/uploads/uploads.tar.gz') # that was not intended !
# better
>>> p = PureWindowsPath('c:/downloads/Downloads.tar.gz')
>>> p.replace_parts('downloads', 'uploads', 1)
PureWindowsPath('c:/uploads/Downloads.tar.gz')
# much better
>>> p = PureWindowsPath('c:/downloads/Downloads.tar.gz')
>>> p.replace_parts('c:/downloads', 'c:/uploads')
PureWindowsPath('c:/uploads/Downloads.tar.gz')
shutil wrappers
- Path.copy(target, follow_symlinks)
wraps shutil.copy, see: https://docs.python.org/3/library/shutil.html
>>> import pathlib3x as pathlib
>>> s = pathlib.Path('c:/Downloads/pathlib.tar.gz')
>>> t = pathlib.Path('c:/Downloads/pathlib.tar.gz.backup')
>>> s.copy(t)
- Path.copy2(target, follow_symlinks=True)
wraps shutil.copy2, see: https://docs.python.org/3/library/shutil.html
>>> import pathlib3x as pathlib
>>> s = pathlib.Path('c:/Downloads/pathlib.tar.gz')
>>> t = pathlib.Path('c:/Downloads/pathlib.tar.gz.backup')
>>> s.copy2(t)
- Path.copyfile(target, follow_symlinks)
wraps shutil.copyfile, see: https://docs.python.org/3/library/shutil.html
>>> import pathlib3x as pathlib
>>> s = pathlib.Path('c:/Downloads/pathlib.tar.gz')
>>> t = pathlib.Path('c:/Downloads/pathlib.tar.gz.backup')
>>> s.copyfile(t)
- Path.copymode(target, follow_symlinks=True)
wraps shutil.copymode, see: https://docs.python.org/3/library/shutil.html
>>> import pathlib3x as pathlib
>>> s = pathlib.Path('c:/Downloads/pathlib.tar.gz')
>>> t = pathlib.Path('c:/Downloads/pathlib.tar.gz.backup')
>>> s.copymode(t)
- Path.copystat(target, follow_symlinks=True)
wraps shutil.copystat, see: https://docs.python.org/3/library/shutil.html
>>> import pathlib3x as pathlib
>>> s = pathlib.Path('c:/Downloads/pathlib.tar.gz')
>>> t = pathlib.Path('c:/Downloads/pathlib.tar.gz.backup')
>>> s.copystat(t)
- Path.copytree(target, symlinks=False, ignore=None, copy_function=copy2, ignore_dangling_symlinks=True, dirs_exists_ok=False)
wraps shutil.copytree, see: https://docs.python.org/3/library/shutil.html
dirs_exists_ok=True will raise a TypeError on Python Versions < 3.8
>>> import pathlib3x as pathlib
>>> s = pathlib.Path('c:/Downloads')
>>> t = pathlib.Path('c:/temp/Backups')
>>> s.copytree(t)
- Path.rmtree(ignore_errors=False, onerror=None)
wraps shutil.rmtree, see: https://docs.python.org/3/library/shutil.html
>>> import pathlib3x as pathlib
>>> p = pathlib.Path('c:/Downloads/old')
>>> p.rmtree()
Caveats of pathlib3x
>>> import pathlib3x
>>> import pathlib
>>> pathlib3x_path = pathlib3x.Path('some_path') # this might happen in another module !
>>> pathlib_path = pathlib.Path('some_path')
>>> isinstance(pathlib3x_path, pathlib.Path)
False
>>> isinstance(pathlib_path, pathlib3x.Path)
False
# in such cases were You need to mix pathlib and pathlib3x in different modules, use:
>>> pathlib3x_path.Path.is_path_instance(pathlib3x_path)
True
>>> pathlib3x_path.Path.is_path_instance(pathlib_path)
True
So dont mix pathlib with pathlib3x and expect that objects are an instance of Pathlib and vice versa. This can happen easily if You have many Modules. Just keep it in mind !
Usage from Commandline
Usage: pathlib3x [OPTIONS] COMMAND [ARGS]...
backport of pathlib 3.10 to python 3.6, 3.7, 3.8, 3.9 with a few extensions
Options:
--version Show the version and exit.
--traceback / --no-traceback return traceback information on cli
-h, --help Show this message and exit.
Commands:
info get program informations
Installation and Upgrade
Before You start, its highly recommended to update pip and setup tools:
python -m pip --upgrade pip
python -m pip --upgrade setuptools
to install the latest release from PyPi via pip (recommended):
python -m pip install --upgrade pathlib3x
to install the latest release from PyPi via pip, including test dependencies:
python -m pip install --upgrade pathlib3x[test]
to install the latest version from github via pip:
python -m pip install --upgrade git+https://github.com/bitranox/pathlib3x.git
include it into Your requirements.txt:
# Insert following line in Your requirements.txt:
# for the latest Release on pypi:
pathlib3x
# for the latest development version :
pathlib3x @ git+https://github.com/bitranox/pathlib3x.git
# to install and upgrade all modules mentioned in requirements.txt:
python -m pip install --upgrade -r /<path>/requirements.txt
to install the latest development version, including test dependencies from source code:
# cd ~
$ git clone https://github.com/bitranox/pathlib3x.git
$ cd pathlib3x
python -m pip install -e .[test]
via makefile: makefiles are a very convenient way to install. Here we can do much more, like installing virtual environments, clean caches and so on.
# from Your shell's homedirectory:
$ git clone https://github.com/bitranox/pathlib3x.git
$ cd pathlib3x
# to run the tests:
$ make test
# to install the package
$ make install
# to clean the package
$ make clean
# uninstall the package
$ make uninstall
Requirements
following modules will be automatically installed :
## Project Requirements
click
cli_exit_tools
Acknowledgements
special thanks to “uncle bob” Robert C. Martin, especially for his books on “clean code” and “clean architecture”
Contribute
I would love for you to fork and send me pull request for this project. - please Contribute
License
This software is licensed under the MIT license
—
Changelog
new MAJOR version for incompatible API changes,
new MINOR version for added functionality in a backwards compatible manner
new PATCH version for backwards compatible bug fixes
v2.0.3
- 2023-07-13:
require minimum python 3.8
remove python 3.7 tests
introduce PEP517 packaging standard
introduce pyproject.toml build-system
remove mypy.ini
remove pytest.ini
remove setup.cfg
remove setup.py
remove .bettercodehub.yml
remove .travis.yml
update black config
clean ./tests/test_cli.py
add codeql badge
move 3rd_party_stubs outside the src directory to ./.3rd_party_stubs
add pypy 3.10 tests
add python 3.12-dev tests
v2.0.2.1
2022-06-03: use io.encoding only on 3.10 upwards
v2.0.2
2022-06-03: define __fspath__ only on python >= 3.10
v2.0.1
2022-06-03: use io.encoding only on 3.10 upwards
v2.0.0
- 2022-06-03:
upgrade to pathlib python 3.11a0 version
upgrade to github actions @v3
v1.3.9
- 2020-10-09: service release
update travis build matrix for linux 3.9-dev
update travis build matrix (paths) for windows 3.9 / 3.10
v1.3.8
- 2020-08-08: service release
fix documentation
fix travis
deprecate pycodestyle
implement flake8
v1.3.7
2020-08-01: fix pypi deploy
v1.3.6
2020-07-31: fix travis build
v0.3.5
- 2020-07-29: feature release
use the new pizzacutter template
use cli_exit_tools
v0.3.4
- 2020-07-15patch release
fix cli test
enable traceback option on cli errors
v0.3.3
- 2020-07-15patch release
fix minor typos
v0.3.2
- 2020-07-05patch release
fix typo in setup.py setup parameter zip_safe
v0.3.1
- 2020-07-05patch release
fix version issues in the stub files
v0.3.0
- 2020-07-05added functions, include stub files for typing, setup python_requires
added python_requires in setup.py
include type stub files, its fully type hinted package now (PEP 561)
pep8 fix the standard library code
added PurePath.replace_parts
added PurePath.is_path_instance
added Path.copy
added Path.copy2
added Path.copyfile
added Path.copymode
added Path.copystat
added Path.copytree
added Path.rmtree
v0.2.0
- 2020-07-02added function: PurePath.append_suffix(suffix)
added function: PurePath.append_suffix(suffix)
v0.1.1
- 2020-07-01: patch release
guarded the sys.audit calls with try-except clauses, because sys.event is only avail in python 3.8
v0.1.0
- 2020-06-29: initial release
initial release
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file pathlib3x-2.0.3.tar.gz
.
File metadata
- Download URL: pathlib3x-2.0.3.tar.gz
- Upload date:
- Size: 77.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.10.12
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 9cc220d8706a5f047d34602eadf1cf3435ecbecf54dc676259c1ef1bef10ed60 |
|
MD5 | 64dc43c3fb3d4984d29e0b1c55bb1d85 |
|
BLAKE2b-256 | ba58526842390491f3b573487c21b0acd1028169c3c7ae2933101595aabc5736 |
File details
Details for the file pathlib3x-2.0.3-py3-none-any.whl
.
File metadata
- Download URL: pathlib3x-2.0.3-py3-none-any.whl
- Upload date:
- Size: 25.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.10.12
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6948a0675b4b7b392ba8d89866aade48a935626bceb979381d4cd3c6b423878d |
|
MD5 | 0149b65a87bd6767ff2cbbdbaa067321 |
|
BLAKE2b-256 | bb2e6dbfabf2ef7de276cfed3352753f2366b926805b232f049ecf4b60a9b245 |