Skip to main content

inherits from pathlib.Path with methods for hashing, copying, deleting and more

Project description

pathlibutil

PyPI - Python Version PyPI - Version PyPI - Downloads PyPI - License GitHub - Pytest GitHub - Page GitHub - Release codecov pre-commit


pathlibutil.Path inherits from pathlib.Path with some useful built-in python functions from shutil and hashlib

  • Path.hexdigest() to calculate and Path.verify() for verification of hexdigest from a file
  • Path.default_hash to configurate default hash algorithm for Path class (default: 'md5')
  • Path.size() to get size in bytes of a file or directory
    • byteint function decorator converts the return value of int to a ByteInt object
  • Path.read_lines() to yield over all lines from a file until EOF
  • contextmanager to change current working directory with with statement
  • Path.copy() copy a file or directory to a new path destination
  • Path.delete() delete a file or directory-tree
  • Path.move() move a file or directory to a new path destination
  • Path.make_archive() creates and Path.unpack_archive() uncompresses an archive from a file or directory
  • Path.archive_formats to get all available archive formats
  • Path.stat() returns a StatResult object to get file or directory information containing
    • TimeInt objects for atime, ctime, mtime and birthtime
    • ByteInt object for size
  • Path.relative_to() to get relative path from a file or directory, walk_up to walk up the directory tree.
  • Path.with_suffix() to change the multiple suffixes of a file
  • Path.cwd() to get the current working directory or executable path when script is bundled, e.g. with pyinstaller
  • Path.resolve() to resolve a unc path to a mapped windows drive.
  • Path.walk() to walk over a directory tree like os.walk()
  • Path.iterdir() with recursive all files from the directory tree will be yielded and exclude_dirs via callable.
  • Path.is_expired() to check if a file is expired by a given datetime.timedelta
  • Path.expand() yields file paths for multiple file patterns if they exsits.

JSON serialization of Path objects is supported in pathlibutil.json.

  • pathlibutil.json.dumps() and pathlibutil.json.dump() to serialize Path objects as posix paths.

Parse and modify URLs with pathlibutil.urlpath.

  • pathlibutil.urlpath.UrlPath() modify URL and easy access the path of the url like a pathlib.PurePosixPath object.
  • pathlibutil.urlpath.UrlNetloc() to parse and modify the netloc part of a URL.
  • pathlibutil.urlpath.normalize() to normalize a URL string.
  • pathlibutil.urlpath.url_from() to create a URL from an UNC path object.

Installation

pip install pathlibutil

7zip support

to handle 7zip archives, an extra package py7zr>=0.20.2 is required!

PyPI - Version

# install as extra dependency
pip install pathlibutil[7z]

Usage

from pathlibutil import Path

readme = Path('README.md')

print(f'File size: {readme.size()} Bytes')

Example 1

Read a file and print its content and some file information to stdout.

Path.read_lines()

from pathlibutil import Path

readme = Path("README.md")

print(f"File size: {readme.size()} Bytes")
print(f'File sha1: {readme.hexdigest("sha1")}')

print("File content".center(80, "="))

for line in readme.read_lines(encoding="utf-8"):
  print(line, end="")

print("EOF".center(80, "="))

Example 2

Write a file with md5 checksums of all python files in the pathlibutil-directory.

Path.hexdigest()

from pathlibutil import Path

file = Path("pathlibutil.md5")

with file.open("w") as f:
  f.write(
      "# MD5 checksums generated with pathlibutil "
      "(https://pypi.org/project/pathlibutil/)\n\n"
  )

  i = 0
  for i, filename in enumerate(Path("./pathlibutil").glob("*.py"), start=1):
    f.write(f"{filename.hexdigest()} *{filename}\n")

print(f"\nwritten: {i:>5} {file.default_hash}-hashes to: {file}")

Example 3

Read a file with md5 checksums and verify them.

Path.verify(), Path.default_hash and contextmanager

from pathlibutil import Path

file = Path("pathlibutil.md5")


def no_comment(line: str) -> bool:
  return not line.startswith("#")


with file.parent as cwd:
  miss = 0
  ok = 0
  fail = 0

  for line in filter(no_comment, file.read_lines()):
    try:
      digest, filename = line.strip().split(" *")
      verification = Path(filename).verify(digest, "md5")
    except ValueError as split_failed:
      continue
    except FileNotFoundError as verify_failed:
      tag = "missing"
      miss += 1
    else:
      if verification:
        tag = "ok"
        ok += 1
      else:
        tag = "fail"
        fail += 1

    print(f'{tag.ljust(len(digest), ".")} *{filename}')

  print(f"\nok: {ok:<5} fail: {fail:<5} missing: {miss}")

Example 4

Search all pycache directories and free the memory and display the number of deleted directories and the amount of memory freed in MB.

Path.delete(), Path.size() and ByteInt

from pathlibutil import ByteInt, Path

mem = ByteInt(0)
i = 0

for i, cache in enumerate(Path(".").rglob("*/__pycache__/"), start=1):
  cache_size = cache.size()
  try:
    cache.delete(recursive=True)
  except OSError:
    print(f"Failed to delete {cache}")
  else:
    mem += cache_size

print(f"{i} cache directories deleted, {mem:.1mb} MB freed.")

Example 5

Inherit from pathlibutil.Path to register new a archive format. Specify a archive as keyword argument in the new subclass, which has to be the suffix without . of the archives. Implement a classmethod _register_archive_format() to register new archive formats.

Path.make_archive(), Path.archive_formats and Path.move()

import shutil

import pathlibutil


class RegisterFooBarFormat(pathlibutil.Path, archive="foobar"):
  @classmethod
  def _register_archive_format(cls):
    """
    implement new register functions for given `archive`
    """
    try:
      import required_package_name
    except ModuleNotFoundError:
      raise ModuleNotFoundError("pip install <required_package_name>")

    def pack_foobar(
        base_name, base_dir, owner=None, group=None, dry_run=None, logger=None
    ) -> str:
      """callable that will be used to unpack archives.

      Args:
          base_name (`str`): name of the file to create
          base_dir (`str`): directory to start archiving from, defaults to `os.curdir`
          owner (`Any`, optional): as passed in `make_archive(*args, owner=None, **kwargs)`. Defaults to None.
          group (`Any`, optional): as passed in `make_archive(*args, group=None, **kwargs)`. Defaults to None.
          dry_run (`Any`, optional): as passed in `make_archive(*args, dry_run=None, **kwargs)`. Defaults to None.
          logger (`logging.Logger`, optional): as passed in `make_archive(*args, logger=None, **kwargs)`. Defaults to None.

      Returns:
          str: path of the new created archive
      """
      raise NotImplementedError("implement your own pack function")

    def unpack_foobar(archive, path, filter=None, extra_args=None) -> None:
      """callable that will be used to unpack archives.

      Args:
          archive (`str`): path of the archive
          path (`str`): directory the archive must be extracted to
          filter (`Any`, optional): as passed in `unpack_archive(*args, filter=None, **kwargs)`. Defaults to None.
          extra_args (`Sequence[Tuple[name, value]]`, optional): additional keyword arguments, specified by `register_unpack_format(*args, extra_args=None, **kwargs)`. Defaults to None.
      """
      raise NotImplementedError("implement your own unpack function")

    shutil.register_archive_format(
        "foobar", pack_foobar, description="foobar archives"
    )
    shutil.register_unpack_format("foobar", [".foo.bar"], unpack_foobar)


file = pathlibutil.Path("README.md")

print(f"available archive formats: {file.archive_formats}")

archive = file.make_archive("README.foo.bar")

backup = archive.move("./backup/")

print(f"archive created: {archive.name} and moved to: {backup.parent}")

Example 6

Access the current working directory with optional parameter frozen to determine different directories when script is bundled to an executable, e.g. with pyinstaller.

Path.cwd()

>>> poetry run examples/example6.py -b
Building frozen: K:/pathlibutil/examples/example6.exe
Build succeeded: 0

>>> poetry run examples/example6.py
we are                          not frozen

bundle dir is                   K:/pathlibutil/examples
sys.argv[0] is                  K:/pathlibutil/examples/example6.py
sys.executable is               K:/pathlibutil/.venv/Scripts/python.exe
os.getcwd is                    K:/pathlibutil

Path.cwd(frozen=True) is        K:/pathlibutil
Path.cwd(frozen=False) is       K:/pathlibutil
Path.cwd(frozen=_MEIPASS) is    K:/pathlibutil

>>> examples/example6.exe
we are                          ever so frozen

bundle dir is                   C:/Users/CHRIST~1.DOE/AppData/Local/Temp/_MEI106042
sys.argv[0] is                  examples/example6.exe
sys.executable is               K:/pathlibutil/examples/example6.exe
os.getcwd is                    K:/pathlibutil

Path.cwd(frozen=True) is        K:/pathlibutil/examples
Path.cwd(frozen=False) is       K:/pathlibutil
Path.cwd(frozen=_MEIPASS) is    C:/Users/CHRIST~1.DOE/AppData/Local/Temp/_MEI106042

Example 7

Console application to convert UNC paths to intranet URLs.

By default, it checks if the filename and URL are available and copies the normalized URL to the clipboard.

pathlibutil.urlpath.url_from()

import argparse
import sys

try:
    import pyperclip

    import pathlibutil.urlpath as up
except ModuleNotFoundError as e:
    raise ModuleNotFoundError(f"pip install {e.name.split('.')[0]}") from e


def intranet_from(uncpath: str, check: bool = True) -> str:
    """
    Return the intranet URL for the given UNC path.
    """

    url = up.url_from(
        uncpath,
        hostname="http://intranet.example.de",
        strict=check,
    )

    return url.normalize()


def cli():

    parser = argparse.ArgumentParser(
        description=intranet_from.__doc__,
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
    )

    parser.add_argument(
        "filename",
        nargs="*",
        help="The UNC path to the file.",
    )
    parser.add_argument(
        "-c",
        "--no-check",
        action="store_false",
        dest="check",
        help="Don't check if filename and url is available.",
    )
    parser.add_argument(
        "-s",
        "--silent",
        action="store_true",
        help="Do not print the url to stdout.",
    )
    parser.add_argument(
        "-n",
        "--no-clip",
        action="store_false",
        dest="clip",
        help="Don't copy the url to the clipboard.",
    )

    args = parser.parse_args()
    filename = " ".join(args.filename)

    url = intranet_from(filename, check=args.check)

    if not args.silent:
        print(url)

    if args.clip:
        pyperclip.copy(url)


if __name__ == "__main__":
    try:
        cli()
    except Exception as e:
        print(e, file=sys.stderr)
        sys.exit(1)

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

pathlibutil-0.3.3.tar.gz (23.4 kB view details)

Uploaded Source

Built Distribution

pathlibutil-0.3.3-py3-none-any.whl (22.0 kB view details)

Uploaded Python 3

File details

Details for the file pathlibutil-0.3.3.tar.gz.

File metadata

  • Download URL: pathlibutil-0.3.3.tar.gz
  • Upload date:
  • Size: 23.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.4 CPython/3.10.12 Linux/6.5.0-1025-azure

File hashes

Hashes for pathlibutil-0.3.3.tar.gz
Algorithm Hash digest
SHA256 ff5cd1f21ed54cd1d796d57363cf89f3d36287163f52c5d35f46205e497f0d23
MD5 22ccad67ad24520e2d7274ac41f0e783
BLAKE2b-256 034b8d1e1f7365aef36b69727fb6c5bbcbf793522b32c4d0cea3dbf4f22f20ab

See more details on using hashes here.

File details

Details for the file pathlibutil-0.3.3-py3-none-any.whl.

File metadata

  • Download URL: pathlibutil-0.3.3-py3-none-any.whl
  • Upload date:
  • Size: 22.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.4 CPython/3.10.12 Linux/6.5.0-1025-azure

File hashes

Hashes for pathlibutil-0.3.3-py3-none-any.whl
Algorithm Hash digest
SHA256 e5aceaa695711a3d325a2c1564d0e8fae3a4c0abda80b64e954587bba1304d5a
MD5 4d64c31f7bbeb5661af0d72c6a6f648a
BLAKE2b-256 f230d0ef9ec022e0105f5cba646548f5e9e45f56829ba592465953c133276cea

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page