https://img.shields.io/github/actions/workflow/status/Darsstar/sitecustomize-entrypoints/testing.yaml?branch=main&longCache=true&style=flat-square&label=tests&logo=GitHub%20Actions&logoColor=fff%22Testing https://img.shields.io/github/actions/workflow/status/Darsstar/sitecustomize-entrypoints/linting.yaml?branch=main&longCache=true&style=flat-square&label=Linting&logo=GitHub%20Actions&logoColor=fff%22Linting https://readthedocs.org/projects/sitecustomize-entrypoints/badge/?version=latestRead the Docs https://img.shields.io/pypi/v/sitecustomize-entrypoints?color=%2334D058&label=pypi%20packagePyPi Package https://img.shields.io/badge/license-MIT-blue.svgMIT License

sitecustomize-entrypoints

Overview

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.

Installation

You can install sitecustomize-entrypoints using pip:

> bin/pip install sitecustomize-entrypoints

Or add it to your poetry-based project:

> poetry add sitecustomize-entrypoints

Usage

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

Ordering

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"

Cancel entrypoints registered by third-party packages

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.

Overriding and re-ordering entrypoints

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

Display all registered entrypoint in order of execution

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)