progfiguration.progfigbuild#

Support for building pip and zipapp progfigsite packages

Package Contents#

Classes#

InjectedFile

A file to inject into the built package

ProgfigsitePythonPackagePreparer

A context manager which prepares for building a Python package.

Functions#

generate_builddata_version_py(→ str)

Generate the contents of builddata_version.py

find_pyproject_root_from_package_path(→ pathlib.Path)

Find the project root containing a pyproject.toml from a package path

build_progfigsite_zipapp(progfigsite_filesystem_path, ...)

Build a .pyz zipapp progfigsite package

build_progfigsite_pip(→ pathlib.Path)

Build a pip package

class progfiguration.progfigbuild.InjectedFile#

A file to inject into the built package

path: pathlib.Path#

The path to the file relative to the package root.

contents: str#

The contents of the file.

progfiguration.progfigbuild.generate_builddata_version_py(version: str, build_date: datetime.datetime) str#

Generate the contents of builddata_version.py

progfiguration.progfigbuild.find_pyproject_root_from_package_path(package_path: progfiguration.progfigtypes.PathOrStr, traverse_max: int = 10) pathlib.Path#

Find the project root containing a pyproject.toml from a package path

Look in the parent directories of the package path for a pyproject.toml file, and return the path to the directory containing it.

We assume that the project is using pyproject.toml rather than setup.py or setup.cfg.

Parameters:
  • package_path – The path to the package, eg “/path/to/progfigsite/src/progfigsite”

  • traverse_max – The maximum number of directories to traverse before giving up

Returns:

The path to the project root, eg “/path/to/progfigsite”

progfiguration.progfigbuild.build_progfigsite_zipapp(progfigsite_filesystem_path: pathlib.Path, progfigsite_modname: str, package_out_path: pathlib.Path, build_date: datetime.datetime | None = None, progfiguration_package_path: pathlib.Path | None = None, compression: int = zipfile.ZIP_STORED)#

Build a .pyz zipapp progfigsite package

Parameters:
  • progfigsite_filesystem_path – The path to the progfigsite package, eg “/path/to/progfigsite”.

  • package_out_path – The path where the zipfile will be written.

  • build_date – The build date to embed in the zipapp. If None, the current UTC time will be used.

  • progfiguration_package_path – The path to the progfiguration package, eg “/path/to/progfiguration”. If None, the progfiguration package will be copied from the Python path. This will only work if progfiguration is installed via pip (probably in a venv, possibly editable with ‘pip install -e’)… it won’t work if you’re running progfiguration itself from a zipapp for some reason.

  • compression – The compression level to use for the zipapp file. This can be zipfile.ZIP_STORED (no compression) or zipfile.ZIP_DEFLATED (deflate compression). ZIP_STORED (the default) is faster.

Returns:

The path to the zipapp file, eg “/path/to/my_progfigsite.pyz”.

What this function does:

  • Zip up the contents of the site package.

  • Place them inside a subdirectory called ‘progfigsite’.

  • Add a __main__.py file to the root of the zip file.

  • Add the progfiguration package to the zip file.

  • Add a shebang to the beginning of the zip file.

Inspired by the zipapp module code <https://github.com/python/cpython/blob/3.11/Lib/zipapp.py>

We don’t use the zipapp code itself because we want more control over what goes into the zipfile, like ignoring __pycache__, *.dist-info, etc.

We don’t need the ProgfigsitePythonPackagePreparer context manager here, because we don’t need to inject build data into the filesystem before building the zipapp. We can inject the build data directly into the zipapp file.

class progfiguration.progfigbuild.ProgfigsitePythonPackagePreparer(progfigsite_filesystem_path: pathlib.Path, progfigsite_modname: str, build_date: datetime.datetime | None = None, progfiguration_package_path: pathlib.Path | None = None, injections: List[InjectedFile] | None = None, keep_injected_files: bool = False)#

A context manager which prepares for building a Python package.

Preparation consists of finding the project path from the package path (see progfigsite_project_path and progfigsite_filesystem_path properties), and injecting build data into the filesystem like a version from progfigsite’s mint_version() and the build date. When the context manager exits, the injected files are removed.

You can use this to build a pip package with build and setuptools like this:

with ProgfigsitePythonPackagePreparer("/path/to/mysite", "mysite") as preparer:
    result = subprocess.run(
        ["python", "-m", "build", "-s", "-o", preparer.package_out_path.as_posix(), preparer.progfigsite_project_path.as_posix()],
        check=True,
        capture_output=True,
        cwd=preparer.progfigsite_project_path,
    )
built_package_path = result.stdout.read()

See the implementation of build_progfigsite_pip() for a more complete example.

If you want to modify the build in some way, or build another kind of package after we prepare the filesystem and inject build data, you can do that instead.

Can be used by progfigsite to do something with the result of python -m build, like build a package for another package manager.

progfigsite_filesystem_path#

The filesystem path to the progfigsite package, eg /path/to/progfigsite/src/progfigsite

This PACKAGE directory should be the path to the Python package itself with an __init__.py. It should usually be inside the “src” subfolder of the PROJECT directory, which is the directory containing a pyproject.toml file.

See also: progfigsite_project_path.

progfiguration_package_path#

The filesystem path to the progfiguration package, eg /path/to/progfiguration

build_date#

The build date to inject into the package version metadata

keep_injected_files#

If True, the injected files will be kept after the package is built.

progfigsite#

The progfigsite module

progfigsite_modname#

The name of the progfigsite module

inventory#

The inventory submodule

minted_version: str#

The version of the package we are building, generated by a call to the progfigsite’s mint_version()

progfigsite_project_path#

The filesystem path to the progfigsite project, eg /path/to/progfigsite

This PROJECT directory should be the directory containing a pyproject.toml file. It should usually contain a “src” subfolder which contains a folder like “progfigsite” containing the Python PACKAGE itself.

This is the directory you should run python -m build from.

See also: progfigsite_filesystem_path.

progfiguration_staticinclude_path#

The filesystem path to the progfiguration core package inside the progfigsite package

We inject a symlink to the progfiguration package into the progfigsite package so that progfiguration can find it when run from the pip package. (python -m build will dereference the symlink and include the actual progfiguration package in the pip package.)

injections#

Build data we will inject into the filesystem before building the pip package

We always inject a version.py file containing the version and build date. We have to do this on disk before building the pip package; we can’t inject version metadata into the package after it’s built, because we need to know the version before we build the package.

Users may also inject other files if they want to with the injections argument.

__enter__()#
__exit__(type, value, traceback)#
progfiguration.progfigbuild.build_progfigsite_pip(progfigsite_filesystem_path: pathlib.Path, progfigsite_modname: str, package_out_path: pathlib.Path, build_date: datetime.datetime | None = None, progfiguration_package_path: pathlib.Path | None = None, keep_injected_files: bool = False) pathlib.Path#

Build a pip package

Parameters:
  • progfigsite_filesystem_path – The path to the progfigsite package, eg “/path/to/progfigsite”.

  • package_out_path – The path where the zipfile will be written.

  • build_date – The build date to inject into the package. If None, the current date will be used.

  • progfiguration_package_path – The path to the progfiguration package, eg “/path/to/progfiguration”. If None, the progfiguration package will be copied from the Python path. This will only work if progfiguration is installed via pip (probably in a venv, possibly editable with ‘pip install -e’)… it won’t work if you’re running progfiguration itself from a zipapp for some reason.

  • keep_injected_files – If True, the injected files will be kept after the package is built. You will need to remove them manually. Intended for debugging.

Returns:

The path to the pip package, eg “/path/to/my_progfigsite/dist/my_progfigsite-0.1.0.tar.gz”