From 3344ff4ce90e550fae587b3df2251314f498d6b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= Date: Mon, 11 Apr 2022 11:41:07 +0200 Subject: [PATCH] Trigger deprecation warning when find_packages() finds reserved name Trigger SetuptoolsDeprecationWarning whenever find_packages() finds a top-level package whose name is found in reserved package name list, e.g. "tests". Installing these packages is probably always wrong, yet it is still a frequent mistake in packages using setuptools. This warning should increase the chance of the mistake being caught before releasing. Fixes #3243 --- changelog.d/3243.deprecation.rst | 3 +++ setuptools/discovery.py | 10 ++++++++++ setuptools/tests/test_find_packages.py | 11 ++++++++--- 3 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 changelog.d/3243.deprecation.rst diff --git a/changelog.d/3243.deprecation.rst b/changelog.d/3243.deprecation.rst new file mode 100644 index 0000000000..067bf29f69 --- /dev/null +++ b/changelog.d/3243.deprecation.rst @@ -0,0 +1,3 @@ +Added a deprecation warning when `setuptools.find_packages()` includes +a package in the reserved top-level package name list (e.g. ``tests``) +-- by :user:`mgorny`. diff --git a/setuptools/discovery.py b/setuptools/discovery.py index 95c3c7f83e..45f75acafc 100644 --- a/setuptools/discovery.py +++ b/setuptools/discovery.py @@ -44,12 +44,15 @@ from pathlib import Path from typing import TYPE_CHECKING from typing import Callable, Dict, Iterator, Iterable, List, Optional, Tuple, Union +import warnings import _distutils_hack.override # noqa: F401 from distutils import log from distutils.util import convert_path +import setuptools + _Path = Union[str, os.PathLike] _Filter = Callable[[str], bool] StrIter = Iterator[str] @@ -148,6 +151,13 @@ def _find_iter(cls, where: _Path, exclude: _Filter, include: _Filter) -> StrIter # Should this package be included? if include(package) and not exclude(package): + top_package = package.split(".")[0] + if top_package in FlatLayoutPackageFinder._EXCLUDE: + warnings.warn( + f"{top_package!r} is a reserved package name. " + "Please add it to find_package(exclude=...)", + setuptools.SetuptoolsDeprecationWarning, + ) yield package # Keep searching subdirectories, as there may be more packages diff --git a/setuptools/tests/test_find_packages.py b/setuptools/tests/test_find_packages.py index efcce924e5..570d2623dd 100644 --- a/setuptools/tests/test_find_packages.py +++ b/setuptools/tests/test_find_packages.py @@ -7,6 +7,7 @@ import pytest +import setuptools from setuptools import find_packages from setuptools import find_namespace_packages from setuptools.discovery import FlatLayoutPackageFinder @@ -157,13 +158,17 @@ def test_pep420_ns_package(self): self._assert_packages(packages, ['pkg', 'pkg.nspkg', 'pkg.subpkg']) def test_pep420_ns_package_no_includes(self): - packages = find_namespace_packages( - self.dist_dir, exclude=['pkg.subpkg.assets']) + with pytest.warns(setuptools.SetuptoolsDeprecationWarning, + match="'docs' is a reserved package name"): + packages = find_namespace_packages( + self.dist_dir, exclude=['pkg.subpkg.assets']) self._assert_packages( packages, ['docs', 'pkg', 'pkg.nspkg', 'pkg.subpkg']) def test_pep420_ns_package_no_includes_or_excludes(self): - packages = find_namespace_packages(self.dist_dir) + with pytest.warns(setuptools.SetuptoolsDeprecationWarning, + match="'docs' is a reserved package name"): + packages = find_namespace_packages(self.dist_dir) expected = [ 'docs', 'pkg', 'pkg.nspkg', 'pkg.subpkg', 'pkg.subpkg.assets'] self._assert_packages(packages, expected)