Skip to content

Commit 1a5d06b

Browse files
authored
Merge pull request #1877 from pypa/feature/distribution-options-hooks
Add new hook 'setuptools.finalize_distribution_options'
2 parents e44d9bc + 3e755ec commit 1a5d06b

File tree

4 files changed

+51
-4
lines changed

4 files changed

+51
-4
lines changed

changelog.d/1877.change.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Setuptools now exposes a new entry point hook "setuptools.finalize_distribution_options", enabling plugins like `setuptools_scm <https://pypi.org/project/setuptools_scm>`_ to configure options on the distribution at finalization time.

docs/setuptools.txt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2419,6 +2419,10 @@ script defines entry points for them!
24192419
Adding ``setup()`` Arguments
24202420
----------------------------
24212421

2422+
.. warning:: Adding arguments to setup is discouraged as such arguments
2423+
are only supported through imperative execution and not supported through
2424+
declarative config.
2425+
24222426
Sometimes, your commands may need additional arguments to the ``setup()``
24232427
call. You can enable this by defining entry points in the
24242428
``distutils.setup_keywords`` group. For example, if you wanted a ``setup()``
@@ -2470,6 +2474,25 @@ script using your extension lists your project in its ``setup_requires``
24702474
argument.
24712475

24722476

2477+
Customizing Distribution Options
2478+
--------------------------------
2479+
2480+
Plugins may wish to extend or alter the options on a Distribution object to
2481+
suit the purposes of that project. For example, a tool that infers the
2482+
``Distribution.version`` from SCM-metadata may need to hook into the
2483+
option finalization. To enable this feature, Setuptools offers an entry
2484+
point "setuptools.finalize_distribution_options". That entry point must
2485+
be a callable taking one argument (the Distribution instance).
2486+
2487+
If the callable has an ``.order`` property, that value will be used to
2488+
determine the order in which the hook is called. Lower numbers are called
2489+
first and the default is zero (0).
2490+
2491+
Plugins may read, alter, and set properties on the distribution, but each
2492+
plugin is encouraged to load the configuration/settings for their behavior
2493+
independently.
2494+
2495+
24732496
Adding new EGG-INFO Files
24742497
-------------------------
24752498

setup.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,13 @@ def pypi_link(pkg_filename):
8989
"%(cmd)s = setuptools.command.%(cmd)s:%(cmd)s" % locals()
9090
for cmd in read_commands()
9191
],
92+
"setuptools.finalize_distribution_options": [
93+
"parent_finalize = setuptools.dist:_Distribution.finalize_options",
94+
"features = setuptools.dist:Distribution._finalize_feature_opts",
95+
"keywords = setuptools.dist:Distribution._finalize_setup_keywords",
96+
"2to3_doctests = "
97+
"setuptools.dist:Distribution._finalize_2to3_doctests",
98+
],
9299
"distutils.setup_keywords": [
93100
"eager_resources = setuptools.dist:assert_string_list",
94101
"namespace_packages = setuptools.dist:check_nsp",

setuptools/dist.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -725,15 +725,28 @@ def fetch_build_eggs(self, requires):
725725
return resolved_dists
726726

727727
def finalize_options(self):
728-
_Distribution.finalize_options(self)
729-
if self.features:
730-
self._set_global_opts_from_features()
728+
"""
729+
Allow plugins to apply arbitrary operations to the
730+
distribution. Each hook may optionally define a 'order'
731+
to influence the order of execution. Smaller numbers
732+
go first and the default is 0.
733+
"""
734+
hook_key = 'setuptools.finalize_distribution_options'
735+
736+
def by_order(hook):
737+
return getattr(hook, 'order', 0)
738+
eps = pkg_resources.iter_entry_points(hook_key)
739+
for ep in sorted(eps, key=by_order):
740+
ep.load()(self)
731741

742+
def _finalize_setup_keywords(self):
732743
for ep in pkg_resources.iter_entry_points('distutils.setup_keywords'):
733744
value = getattr(self, ep.name, None)
734745
if value is not None:
735746
ep.require(installer=self.fetch_build_egg)
736747
ep.load()(self, ep.name, value)
748+
749+
def _finalize_2to3_doctests(self):
737750
if getattr(self, 'convert_2to3_doctests', None):
738751
# XXX may convert to set here when we can rely on set being builtin
739752
self.convert_2to3_doctests = [
@@ -763,9 +776,12 @@ def fetch_build_egg(self, req):
763776
from setuptools.installer import fetch_build_egg
764777
return fetch_build_egg(self, req)
765778

766-
def _set_global_opts_from_features(self):
779+
def _finalize_feature_opts(self):
767780
"""Add --with-X/--without-X options based on optional features"""
768781

782+
if not self.features:
783+
return
784+
769785
go = []
770786
no = self.negative_opt.copy()
771787

0 commit comments

Comments
 (0)