sitecustomize-entrypoints
is a library that installs a python-module called sitecustomize
,
and allows you to define and register any callable as a sitecustomize
-entrypoint in your project's setup.py
or pyproject.toml
.
These callables will be then executed automatically whenever sitecustomize
is imported during python-startup.
This provides a simple & modular way to patch or extend the functionality of any python-code installed in your environment without modifying its source code.
sitecustomize
is a special python-module that can be used to customize the python environment at startup.
When the python-interpreter starts, it looks for a sitecustomize.py
-file in the site-packages directory or any other directory specified in the PYTHONPATH
.
The sitecustomize.py
-file is executed before any other Python code, allowing you to make customizations that will be applied to the entire python environment.
For more information, check the official site.py-documentation.
You can install sitecustomize-entrypoints
using pip:
> bin/pip install sitecustomize-entrypoints
Or add it to your poetry-based project:
> poetry add sitecustomize-entrypoints
To use sitecustomize-entrypoints
, you need to define and register one or more entrypoints
in your project's setup.py
or pyproject.toml
file. Here's an example:
[tool.poetry.plugins."sitecustomize"]
"my-action" = "my_project.action:my_action"
In this example, we're registering an entrypoint called my-action
in the sitecustomize
-group.
This entrypoint points to the my_action
-function in the my_project.actions
-module.
Once you've registered your entrypoints, they will be executed automatically
when the sitecustomize
-module is imported.
import sitecustomize
Entrypoints are sorted by name.
The ordering in which the entrypoints are defined in your setup.py
or pyproject.toml
are unfortunately not the order in which they are registered internally.
The entrypoints are first ordered alphanumerically by name.
So defined entrypoints are re-ordered from
[tool.poetry.plugins."sitecustomize"]
foo = "my_project.action:action_foo"
bar = "my_project.action:action_bar"
into
[tool.poetry.plugins."sitecustomize"]
bar = "my_project.action:action_bar"
foo = "my_project.action:action_foo"
This can cause issues when there are dependencies between your entrypoints.
TIP: You can use integer-prefixes to the name to enforce the ordering in which you define your entrypoints.:
[tool.poetry.plugins."sitecustomize"]
10-foo = "my_project.action:action_foo"
20-bar = "my_project.action:action_bar"
Imagine a third-party package has registered an entrypoint as follows:
[tool.poetry.plugins."sitecustomize"]
their-action = "external_module:their_action"
But it does not match the ordering you'd like.
You can cancel the execution of this plugin, by registering an entrypoint with the same name in your own setup.py
or pyproject.toml
file,
and pointing to the no-action sitecustomize.cancel
-function.
[tool.poetry.plugins."sitecustomize"]
their-action = "sitecustomize:cancel"
By registering an entrypoint with the same name it overrides the previous registered action. Subsequently you can re-register this entrypoint by a different name to change the order of execution.
You can override and re-order registered entrypoints by defining your own entrypoints with the same name in your setup.py or pyproject.toml file.
When sitecustomize
executes registered entrypoints, it uses a FIFO-approach (first in, first out):
Only the last registered entrypoint with a given name is executed. Any prior entrypoints with the same name are filtered out (overriden by the last).
To re-order entrypoints, you can use the cancel
-function provided by sitecustomize-entrypoints
.
The cancel
-function allows you to cancel out a previously registered entrypoint, so you can re-register it in a different order.
Here's an example to enforce a specific order of execution:
[tool.poetry.plugins."sitecustomize"]
"their-action = external_module:their_action"
[tool.poetry.plugins."sitecustomize"]
"their-action = sitecustomize:cancel"
"10-my-action = my_project.action:my_action"
"20-their-action = external_module:their_action"
In this example, we're re-ordering an entrypoint registered by a third-party module to be executed after our own. First we re-register it with the same name to override and cancel its action, and subsequently we re-register it under a different name to ensure it get executed after our own entrypoints, even if all entrypoints are sorted alphabetically
The sitecustomize.print_entrypoints
-function provided by sitecustomize-entrypoints
allows you to display a list of all registered entrypoints.
By default, it will display all registered entrypoints in the sitecustomize
-group in order of execution.
You can optionally pass a different entrypoint group name as an argument.
If you pass filtered=True
as an argument, the function will also filter out any duplicate entrypoints and display only the last instance of each entrypoint. Here's an example usage:
import sitecustomize
# Display all registered entrypoints in the sitecustomize group
sitecustomize.print_entrypoints()
# More explicit equivalent
sitecustomize.print_entrypoints(group_name="sitecustomize")
# Display only the first instance of each registered entrypoint in the sitecustomize group
sitecustomize.print_entrypoints(filtered=True)