Entrypoints¶
Some code from progfigsite packages must be able to run even when progfiguration core is not installed.
Retrieving the version…¶
The version is calculated dynamically per pyproject.toml
,
so it must be available even when the module isn’t installed.
The site must implement the function progfigsite.get_version
,
by e.g. defining get_version()
in progfigsite/__init__.py
.
When setuptools
looks in this module for the version,
it does not do a normal python import,
where first it loads progfigsite
, then the version
submodule.
Instead, it reads the file in isolation.
The version file can only use code that is available in this unusual context.
This is why progfiguration core can’t provide a default or helper function for sites –
the helper function would require progfiguration core to be installed,
but we can’t guarantee that in all the of the scenarios where we use it go get the version.
… when building a package¶
Building progfigsite packages must be done via progfiguration build
,
in order to inject build data like the version and build date,
and statically include progfiguration core.
(progfiguration build
does use the Python build
module under the hood,
but just running python3 -m build ...
by itself
will not result in a proper progfigsite package.)
- Example
progfiguration build ...
- Working?
Yes
- Progfigsite installed to Python path?
No
- Progfiguration core installed to Python path?
Yes
… when installing a package¶
For pip packages, the version is baked in to the package metadata and get_version()
is not used.
For zipapp packages, there is no inherenent concept of a “version” or “install time” –
it’s just zip file with some data at the front to tell the operating system to use the Python interpreter to run it,
similar to a plain text Python script.
(Either type of package might call get_version()
once it’s loaded,
for instance if the user runs progfigsite version
or similar;
this case is discussed below.)
- Example
pip install progfigsite
- Working?
Yes
- Progfigsite installed to Python path?
No
- Progfiguration core installed to Python path?
No
… when installing from source with core¶
A progfigsite’s pyproject.toml
does not list progfiguration core as a dependency,
because when the package is built, we will statically include it.
This means that when running pip install -e .
,
progfiguration core must have already been installed previously.
We don’t expect that most users will use this method.
A site’s users will install built packages or run zipapps directly,
and site developers will install the development
extras (see below).
- Example
pip install progfiguration && pip install -e .
- Working?
Yes
- Progfigsite installed to Python path?
No
- Progfiguration core installed to Python path?
Yes
… when installing from source without core¶
The development
extras for a progfigsite typically do list progfiguration core as a dependency,
along with build and development packages like setuptools
, black
, etc.
Site developers typically opt for this installation method on development machines.
- Example
pip install -e '.[development]'
- Working?
Yes
- Progfigsite installed to Python path?
No
- Progfiguration core installed to Python path?
No
… at runtime¶
The version code is also called sometimes at runtime,
for instance when running progfigsite version
.
However, this just uses normal Python imports,
so we don’t need to do anything special to make sure it works.
- Example
progfigsite version
- Working?
Yes
- Progfigsite installed to Python path?
Yes
- Progfiguration core installed to Python path?
Yes, perhaps via static includes
Running the progfigsite command line program…¶
The progfigsite command is installed as The progfigsite shim
as an entrypoint in pyproject.toml
.
In this scenario, the code is already present on the system,
however, the core module may be statically included in the package
and not available in the default Python path.
From a zipapp (e.g.
/path/to/progfigsite.pyz
)From an installed built package (e.g. a .tar.gz or .whl package installed with
pip install progfigsite
)From the source code installed as editable with
pip install -e .
… from a zipapp¶
When Python runs a zipapp package,
it places the path to the zipapp in the Python path,
making any zipped subdirectories available for direct importing via import progfigsite
or similar.
Then it looks for a file called __main__.py
in the root of the zip file and runs it.
See ours in progfiguration.progfigbuild.build_progfigsite_zipapp()
.
We import the progfigsite package by name and call
progfiguration.cli.progfiguration_site_cmd:main()
,
just like the shim does.
Unlike the shim, progfiguration core is already in the Python path
because it’s also copied to the root of the zipfile,
so __main__.py
ends up simpler than progfigsite_shim.py
.
- Example
/path/to/progfigsite.pyz
- Working?
Yes
- Progfigsite installed to Python path?
Yes
- Progfiguration core installed to Python path?
Yes
… from an installed package¶
When a progfigsite package is built,
the progfiguration core package is copied inside builddata.static_include
.
The pyproject.toml
specifies an entrypoint in progfigsite.cli.progfigsite_shim:main
,
which adds the static_include
directory to the Python path
and then runs progfiguration.cli.progfiguration_site_cmd:main()
.
That file looks something like this:
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from progfigsite.cli.progfigsite_shim import main
if __name__ == "__main__":
sys.argv[0] = re.sub(r"(-script\.pyw|\.exe)?$", "", sys.argv[0])
sys.exit(main())
However, this is a a normal Python import,
which means that the line
from progfigsite.cli.progfigsite_shim import main
first loads the progfigsite
module, then the cli
module,
and then the progfigsite_shim
module,
before running main()
.
This is different from setuptools calling get_version()
.
Setuptools does not do a normal Python import;
it just finds the file directly and tries to load it.
This means that for get_version()
,
it doesn’t matter if the root progfigsite
module tries to import progfiguration core
or does anything else that might fail.
But when tring to run an installed pacakge,
the root progfigsite
module (and also cli
and progfigsite_shim
)
must be importable without error even if progfiguration core is not already installed.
The shim places progfiguration core in the Python path,
so we can’t import anything from progfiguration core until the shim runs.
- Example
pip install progfigsite && progfigsite ...
- Working?
Yes
- Progfigsite installed to Python path?
Yes
- Progfiguration core installed to Python path?
Yes
… from the source code installed as editable¶
When installing this way, progfiguration core will already be in the Python path, so this just behaves like a normal Python import.
Recall that running pip install -e .
is unusual,
and in that case progfiguration core must already be in the Python path,
and that running pip install -e '.[development]'
will install progfiguration core before installing the site.
Either way, the core package is available before the progfigsite program is run.
- Example
pip install -e '.[development]'
- Working?
Yes
- Progfigsite installed to Python path?
Yes
- Progfiguration core installed to Python path?
Yes
Importing as a library…¶
From an installed built package (e.g. a .tar.gz or .whl package installed with
pip install progfigsite
)From the source code installed as editable with
pip install -e .
From progfiguration core by its filesystem path with
importlib.import_module
even if not installed to the Python pathFrom progfiguration core by its module name if it is installed to the Python path
… from an installed package¶
This is unusual, and we may decide not to support it by default for progfigsite packages.
- Example
pip install ./my-progfigsite-package.tar.gz
, thenimport progfigsite
.- Working?
Unknown
- Progfigsite installed to Python path?
Yes
- Progfiguration core installed to Python path?
No
The core package may not be in the Python path, but it will be available under
progfigsite.builddata.static_include
; importers may import that first.
… from the source code installed as editable¶
- Example
pip install -e '.[development]'
, thenimport progfigsite
- Working?
Yes
- Progfigsite installed to Python path?
Yes
- Progfiguration core installed to Python path?
Yes
… from progfiguration core by its filesystem path¶
This will work as long as progfiguration.sitewrapper.set_progfigsite_by_module_name()
has been called.
Progfiguration core uses progfiguration.sitewrapper.get_progfigsite()
to reference it.
- Example
sitewrapper.get_progfigsite()
from progfiguration core- Working?
Yes
- Progfigsite installed to Python path?
Yes
- Progfiguration core installed to Python path?
Yes
Alternative entrypoints…¶
Sites may add alternative entrypoints as scripts in their pyproject.toml
.
These are not accessible from the zipapp,
but are available when installed via pip.
… from an installed package¶
This is a rare case, since progfigsite packages are expected to be used via zipapp at least some of the time. However, it will work as long as the process used in the cli shim is followed:
# -*- mode: python -*-
"""The progfigsite command.
This is required.
"""
def ensure_staticinclude():
"""Ensure that the static include directory is in the Python path.
If progfiguration is installed as a statically included package,
then it will find it there first.
This means it will work from inside a progfiguration+progfigsite pip package.
If it's installed as a system package, then it will find it there as well.
This means it will work if you `pip install -e '.[development]'`.
"""
from pathlib import Path
import sys
staticinclude_dir = Path(__file__).parent.parent / "builddata" / "static_include"
if staticinclude_dir.as_posix() not in sys.path:
sys.path.insert(0, staticinclude_dir.as_posix())
def main():
ensure_staticinclude()
from progfiguration import sitewrapper
from progfiguration.cli import progfiguration_site_cmd
sitewrapper.set_progfigsite_by_module_name("{$}name")
progfiguration_site_cmd.main()
(Substitute {$}name
with the name of your progfigsite package.)
- Working?
Yes
- Progfigsite installed to Python path?
Yes
- Progfiguration core installed to Python path?
No
The core package may not be in the Python path, but it will be available under
progfigsite.builddata.static_include
; importers may import that first.
… from source code installed as editable¶
This might be useful for build scripts.
- Working?
Yes
- Progfigsite installed to Python path?
Yes
- Progfiguration core installed to Python path?
No
The core package may not be in the Python path, but it will be available under
progfigsite.builddata.static_include
; importers may import that first.