Skip to content

Commit 73bc126

Browse files
authored
Add deprecation messages for namespace_packages (#3262)
2 parents 42d940f + 269f3ac commit 73bc126

9 files changed

Lines changed: 67 additions & 8 deletions

File tree

changelog.d/3262.deprecation.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Formally added deprecation messages for ``namespace_packages``.
2+
The methodology that uses ``pkg_resources`` and ``namespace_packages`` for
3+
creating namespaces was already discouraged by the :doc:`setuptools docs
4+
</userguide/package_discovery>` and the
5+
:doc:`Python Packaging User Guide <PyPUG:guides/packaging-namespace-packages>`,
6+
therefore this change just make the deprecation more official.
7+
Users can consider migrating to native/implicit namespaces (as introduced in
8+
:pep:`420`).

docs/references/keywords.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,11 @@ extensions).
353353
.. _keyword/namespace_packages:
354354

355355
``namespace_packages``
356+
.. warning::
357+
``namespace_packages`` is deprecated in favor of native/implicit
358+
namespaces (:pep:`420`). Check :doc:`the Python Packaging User Guide
359+
<PyPUG:guides/packaging-namespace-packages>` for more information.
360+
356361
A list of strings naming the project's "namespace packages". A namespace
357362
package is a package that may be split across multiple project
358363
distributions. For example, Zope 3's ``zope`` package is a namespace

docs/userguide/declarative_config.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ packages find:, find_namespace:, list-comma [#
210210
package_dir dict
211211
package_data section [#opt-1]_
212212
exclude_package_data section
213-
namespace_packages list-comma
213+
namespace_packages list-comma [#opt-5]_
214214
py_modules list-comma 34.4.0
215215
data_files section 40.6.0 [#opt-4]_
216216
======================= =================================== =============== =========
@@ -243,6 +243,10 @@ data_files section 40.6.0 [#
243243
.. [#opt-4] ``data_files`` is deprecated and should be avoided.
244244
Please check :doc:`/userguide/datafiles` for more information.
245245
246+
.. [#opt-5] ``namespace_packages`` is deprecated in favour of native/implicit
247+
namespaces (:pep:`420`). Check :doc:`the Python Packaging User Guide
248+
<PyPUG:guides/packaging-namespace-packages>` for more information.
249+
246250
247251
Compatibility with other tools
248252
==============================

docs/userguide/pyproject_config.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ Key Value Type (TOML) Notes
9494
``py-modules`` array See tip below
9595
``packages`` array or ``find`` directive See tip below
9696
``package-dir`` table/inline-table Used when explicitly listing ``packages``
97-
``namespace-packages`` array Not necessary if you use :pep:`420`
97+
``namespace-packages`` array **Deprecated** - Use implicit namespaces instead (:pep:`420`)
9898
``package-data`` table/inline-table See :doc:`/userguide/datafiles`
9999
``include-package-data`` boolean ``True`` by default
100100
``exclude-package-data`` table/inline-table

setuptools/config/_apply_pyprojecttoml.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
from typing import (TYPE_CHECKING, Any, Callable, Dict, List, Optional, Set, Tuple,
1717
Type, Union)
1818

19+
from setuptools._deprecation_warning import SetuptoolsDeprecationWarning
20+
1921
if TYPE_CHECKING:
2022
from setuptools._importlib import metadata # noqa
2123
from setuptools.dist import Distribution # noqa
@@ -75,6 +77,12 @@ def _apply_tool_table(dist: "Distribution", config: dict, filename: _Path):
7577

7678
for field, value in tool_table.items():
7779
norm_key = json_compatible_key(field)
80+
81+
if norm_key in TOOL_TABLE_DEPRECATIONS:
82+
suggestion = TOOL_TABLE_DEPRECATIONS[norm_key]
83+
msg = f"The parameter `{norm_key}` is deprecated, {suggestion}"
84+
warnings.warn(msg, SetuptoolsDeprecationWarning)
85+
7886
norm_key = TOOL_TABLE_RENAMES.get(norm_key, norm_key)
7987
_set_config(dist, norm_key, value)
8088

@@ -307,6 +315,9 @@ def _acessor(obj):
307315
}
308316

309317
TOOL_TABLE_RENAMES = {"script_files": "scripts"}
318+
TOOL_TABLE_DEPRECATIONS = {
319+
"namespace_packages": "consider using implicit namespaces instead (PEP 420)."
320+
}
310321

311322
SETUPTOOLS_PATCHES = {"long_description_content_type", "project_urls",
312323
"provides_extras", "license_file", "license_files"}

setuptools/config/setupcfg.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from distutils.errors import DistutilsOptionError, DistutilsFileError
1313
from setuptools.extern.packaging.version import Version, InvalidVersion
1414
from setuptools.extern.packaging.specifiers import SpecifierSet
15+
from setuptools._deprecation_warning import SetuptoolsDeprecationWarning
1516

1617
from . import expand
1718

@@ -507,7 +508,7 @@ def parsers(self):
507508
parse_list,
508509
"The requires parameter is deprecated, please use "
509510
"install_requires for runtime dependencies.",
510-
DeprecationWarning,
511+
SetuptoolsDeprecationWarning,
511512
),
512513
'obsoletes': parse_list,
513514
'classifiers': self._get_parser_compound(parse_file, parse_list),
@@ -516,7 +517,7 @@ def parsers(self):
516517
exclude_files_parser('license_file'),
517518
"The license_file parameter is deprecated, "
518519
"use license_files instead.",
519-
DeprecationWarning,
520+
SetuptoolsDeprecationWarning,
520521
),
521522
'license_files': parse_list,
522523
'description': parse_file,
@@ -584,7 +585,12 @@ def parsers(self):
584585
'scripts': parse_list,
585586
'eager_resources': parse_list,
586587
'dependency_links': parse_list,
587-
'namespace_packages': parse_list,
588+
'namespace_packages': self._deprecated_config_handler(
589+
parse_list,
590+
"The namespace_packages parameter is deprecated, "
591+
"consider using implicit namespaces instead (PEP 420).",
592+
SetuptoolsDeprecationWarning,
593+
),
588594
'install_requires': parse_list_semicolon,
589595
'setup_requires': parse_list_semicolon,
590596
'tests_require': parse_list_semicolon,

setuptools/dist.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,11 @@ def check_nsp(dist, attr, value):
280280
nsp,
281281
parent,
282282
)
283+
msg = (
284+
"The namespace_packages parameter is deprecated, "
285+
"consider using implicit namespaces instead (PEP 420).",
286+
)
287+
warnings.warn(msg, SetuptoolsDeprecationWarning)
283288

284289

285290
def check_extras(dist, attr, value):

setuptools/tests/config/test_apply_pyprojecttoml.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import io
77
import re
88
import tarfile
9+
from inspect import cleandoc
910
from pathlib import Path
1011
from unittest.mock import Mock
1112
from zipfile import ZipFile
@@ -14,6 +15,7 @@
1415
from ini2toml.api import Translator
1516

1617
import setuptools # noqa ensure monkey patch to metadata
18+
from setuptools._deprecation_warning import SetuptoolsDeprecationWarning
1719
from setuptools.dist import Distribution
1820
from setuptools.config import setupcfg, pyprojecttoml
1921
from setuptools.config import expand
@@ -211,6 +213,21 @@ def test_license_and_license_files(tmp_path):
211213
assert dist.metadata.license == "LicenseRef-Proprietary\n"
212214

213215

216+
class TestDeprecatedFields:
217+
def test_namespace_packages(self, tmp_path):
218+
pyproject = tmp_path / "pyproject.toml"
219+
config = """
220+
[project]
221+
name = "myproj"
222+
version = "42"
223+
[tool.setuptools]
224+
namespace-packages = ["myproj.pkg"]
225+
"""
226+
pyproject.write_text(cleandoc(config), encoding="utf-8")
227+
with pytest.warns(SetuptoolsDeprecationWarning, match="namespace_packages"):
228+
pyprojecttoml.apply_configuration(makedist(tmp_path), pyproject)
229+
230+
214231
class TestPresetField:
215232
def pyproject(self, tmp_path, dynamic, extra_content=""):
216233
content = f"[project]\nname = 'proj'\ndynamic = {dynamic!r}\n"

setuptools/tests/config/test_setupcfg.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import pytest
88

99
from distutils.errors import DistutilsOptionError, DistutilsFileError
10+
from setuptools._deprecation_warning import SetuptoolsDeprecationWarning
1011
from setuptools.dist import Distribution, _Distribution
1112
from setuptools.config.setupcfg import ConfigHandler, read_configuration
1213
from ..textwrap import DALS
@@ -409,7 +410,7 @@ def test_deprecated_config_handlers(self, tmpdir):
409410
'requires = some, requirement\n',
410411
)
411412

412-
with pytest.deprecated_call():
413+
with pytest.warns(SetuptoolsDeprecationWarning, match="requires"):
413414
with get_dist(tmpdir) as dist:
414415
metadata = dist.metadata
415416

@@ -518,7 +519,8 @@ def test_basic(self, tmpdir):
518519
'python_requires = >=1.0, !=2.8\n'
519520
'py_modules = module1, module2\n',
520521
)
521-
with get_dist(tmpdir) as dist:
522+
deprec = pytest.warns(SetuptoolsDeprecationWarning, match="namespace_packages")
523+
with deprec, get_dist(tmpdir) as dist:
522524
assert dist.zip_safe
523525
assert dist.include_package_data
524526
assert dist.package_dir == {'': 'src', 'b': 'c'}
@@ -572,7 +574,8 @@ def test_multiline(self, tmpdir):
572574
' http://some.com/here/1\n'
573575
' http://some.com/there/2\n',
574576
)
575-
with get_dist(tmpdir) as dist:
577+
deprec = pytest.warns(SetuptoolsDeprecationWarning, match="namespace_packages")
578+
with deprec, get_dist(tmpdir) as dist:
576579
assert dist.package_dir == {'': 'src', 'b': 'c'}
577580
assert dist.packages == ['pack_a', 'pack_b.subpack']
578581
assert dist.namespace_packages == ['pack1', 'pack2']

0 commit comments

Comments
 (0)