Package: pathlib3x
pathlib3xVersion v2.0.3 as of 2023-07-20 seeChangelogBackport 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 packagethis 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.8Of course You can do :import pathlib

try:
    pathlib.Path('some_file').unlink()
except FileNotFoundError:
    passbut that clutters the code unnecessarily. So just use :import pathlib3x as pathliband 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 withPizzaCutter(cookiecutter on steroids)Python version required: 3.8.0 or newertested on recent linux with python 3.8, 3.9, 3.10, 3.11, 3.12-dev, pypy-3.9, pypy-3.10 - architectures: amd64100% (for my added functions) code coverage, flake8 style checking ,mypy static type checking ,tested underLinux, macOS, Windows, automatic daily builds and monitoringUsageUsage from CommandlineInstallation and UpgradeRequirementsAcknowledgementsContributeReport IssuesPull RequestCode of ConductLicenseChangelogUsagejust check out the latest python documentation :https://docs.python.org/3/library/pathlib.htmland select 3.10 BranchAdditional Features are documented here :PurePath.append_suffix(suffix)Return a new path with thesuffixappended. 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.
Ifsuffixis 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__objis 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>>>importpathlib3x>>>importpathlib>>>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)TruePurePath.replace_parts(old, new, count=-1)Return a new Path with parts replaced. If the Original Path oroldhas 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, newcan be pathlib.Path or Path-like objectsif the Original Path is resolved, You should probably also resolveoldandnew- 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')>>>forsourceinsource_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 wrappersPath.copy(target, follow_symlinks)wraps shutil.copy, see:https://docs.python.org/3/library/shutil.html>>>importpathlib3xaspathlib>>>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>>>importpathlib3xaspathlib>>>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>>>importpathlib3xaspathlib>>>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>>>importpathlib3xaspathlib>>>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>>>importpathlib3xaspathlib>>>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.htmldirs_exists_ok=True will raise a TypeError on Python Versions < 3.8>>>importpathlib3xaspathlib>>>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>>>importpathlib3xaspathlib>>>p=pathlib.Path('c:/Downloads/old')>>>p.rmtree()Caveats of pathlib3x>>>importpathlib3x>>>importpathlib>>>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)TrueSo 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 CommandlineUsage: 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 informationsInstallation and UpgradeBefore You start, its highly recommended to update pip and setup tools:python -m pip --upgrade pip
python -m pip --upgrade setuptoolsto install the latest release from PyPi via pip (recommended):python -m pip install --upgrade pathlib3xto 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.gitinclude 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.txtto 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:$gitclonehttps://github.com/bitranox/pathlib3x.git$cdpathlib3x# to run the tests:$maketest# to install the package$makeinstall# to clean the package$makeclean# uninstall the package$makeuninstallRequirementsfollowing modules will be automatically installed :## Project Requirementsclickcli_exit_toolsAcknowledgementsspecial thanks to “uncle bob” Robert C. Martin, especially for his books on “clean code” and “clean architecture”ContributeI would love for you to fork and send me pull request for this project.
-please ContributeLicenseThis software is licensed under theMIT license—Changelognew MAJOR version for incompatible API changes,new MINOR version for added functionality in a backwards compatible mannernew PATCH version for backwards compatible bug fixesv2.0.32023-07-13:require minimum python 3.8remove python 3.7 testsintroduce PEP517 packaging standardintroduce pyproject.toml build-systemremove mypy.iniremove pytest.iniremove setup.cfgremove setup.pyremove .bettercodehub.ymlremove .travis.ymlupdate black configclean ./tests/test_cli.pyadd codeql badgemove 3rd_party_stubs outside the src directory to./.3rd_party_stubsadd pypy 3.10 testsadd python 3.12-dev testsv2.0.2.12022-06-03: use io.encoding only on 3.10 upwardsv2.0.22022-06-03: define __fspath__ only on python >= 3.10v2.0.12022-06-03: use io.encoding only on 3.10 upwardsv2.0.02022-06-03:upgrade to pathlib python 3.11a0 versionupgrade to github actions @v3v1.3.92020-10-09: service releaseupdate travis build matrix for linux 3.9-devupdate travis build matrix (paths) for windows 3.9 / 3.10v1.3.82020-08-08: service releasefix documentationfix travisdeprecate pycodestyleimplement flake8v1.3.72020-08-01: fix pypi deployv1.3.62020-07-31: fix travis buildv0.3.52020-07-29: feature releaseuse the new pizzacutter templateuse cli_exit_toolsv0.3.42020-07-15patch releasefix cli testenable traceback option on cli errorsv0.3.32020-07-15patch releasefix minor typosv0.3.22020-07-05patch releasefix typo in setup.py setup parameter zip_safev0.3.12020-07-05patch releasefix version issues in the stub filesv0.3.02020-07-05added functions, include stub files for typing, setup python_requiresadded python_requires in setup.pyinclude type stub files, its fully type hinted package now (PEP 561)pep8 fix the standard library codeadded PurePath.replace_partsadded PurePath.is_path_instanceadded Path.copyadded Path.copy2added Path.copyfileadded Path.copymodeadded Path.copystatadded Path.copytreeadded Path.rmtreev0.2.02020-07-02added function: PurePath.append_suffix(suffix)added function: PurePath.append_suffix(suffix)v0.1.12020-07-01: patch releaseguarded the sys.audit calls with try-except clauses, because sys.event is only avail in python 3.8v0.1.02020-06-29: initial releaseinitial release