diff --git a/setuptools/config/_apply_pyprojecttoml.py b/setuptools/config/_apply_pyprojecttoml.py index 5d34cdb7d8..fce5c40e34 100644 --- a/setuptools/config/_apply_pyprojecttoml.py +++ b/setuptools/config/_apply_pyprojecttoml.py @@ -303,7 +303,7 @@ def _some_attrgetter(*items): """ def _acessor(obj): values = (_attrgetter(i)(obj) for i in items) - return next((i for i in values if i), None) + return next((i for i in values if i is not None), None) return _acessor diff --git a/setuptools/config/pyprojecttoml.py b/setuptools/config/pyprojecttoml.py index 0ee1b8f9a1..e20d71d2ff 100644 --- a/setuptools/config/pyprojecttoml.py +++ b/setuptools/config/pyprojecttoml.py @@ -282,11 +282,12 @@ def _expand_all_dynamic(self, dist: "Distribution", package_dir: Mapping[str, st ) # `None` indicates there is nothing in `tool.setuptools.dynamic` but the value # might have already been set by setup.py/extensions, so avoid overwriting. - self.project_cfg.update({k: v for k, v in obtained_dynamic.items() if v}) + updates = {k: v for k, v in obtained_dynamic.items() if v is not None} + self.project_cfg.update(updates) def _ensure_previously_set(self, dist: "Distribution", field: str): previous = _PREVIOUSLY_DEFINED[field](dist) - if not previous and not self.ignore_option_errors: + if previous is None and not self.ignore_option_errors: msg = ( f"No configuration found for dynamic {field!r}.\n" "Some dynamic fields need to be specified via `tool.setuptools.dynamic`" diff --git a/setuptools/tests/config/test_apply_pyprojecttoml.py b/setuptools/tests/config/test_apply_pyprojecttoml.py index a88bc1ec19..b822096363 100644 --- a/setuptools/tests/config/test_apply_pyprojecttoml.py +++ b/setuptools/tests/config/test_apply_pyprojecttoml.py @@ -14,7 +14,7 @@ from setuptools.dist import Distribution from setuptools.config import setupcfg, pyprojecttoml from setuptools.config import expand -from setuptools.config._apply_pyprojecttoml import _WouldIgnoreField +from setuptools.config._apply_pyprojecttoml import _WouldIgnoreField, _some_attrgetter from setuptools.command.egg_info import write_requirements @@ -234,12 +234,14 @@ def test_not_listed_in_dynamic(self, tmp_path, attr, field, value): dist = pyprojecttoml.apply_configuration(dist, pyproject) # TODO: Once support for pyproject.toml config stabilizes attr should be None - dist_value = getattr(dist, attr, None) or getattr(dist.metadata, attr, object()) + dist_value = _some_attrgetter(f"metadata.{attr}", attr)(dist) assert dist_value == value @pytest.mark.parametrize( "attr, field, value", [ + ("install_requires", "dependencies", []), + ("extras_require", "optional-dependencies", {}), ("install_requires", "dependencies", ["six"]), ("classifiers", "classifiers", ["Private :: Classifier"]), ] @@ -248,7 +250,7 @@ def test_listed_in_dynamic(self, tmp_path, attr, field, value): pyproject = self.pyproject(tmp_path, [field]) dist = makedist(tmp_path, **{attr: value}) dist = pyprojecttoml.apply_configuration(dist, pyproject) - dist_value = getattr(dist, attr, None) or getattr(dist.metadata, attr, object()) + dist_value = _some_attrgetter(f"metadata.{attr}", attr)(dist) assert dist_value == value def test_optional_dependencies_dont_remove_env_markers(self, tmp_path):