Skip to content

Commit be80bb2

Browse files
authored
Merge pull request #176 from diazona/fix-failing-release-tests/2/dev
Handle "optional" dependencies with no extra
2 parents eb18597 + fe7c4d8 commit be80bb2

4 files changed

Lines changed: 49 additions & 15 deletions

File tree

.github/workflows/main.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,11 @@ jobs:
4848
- python: "3.13"
4949
platform: ubuntu-latest
5050
force-minimum-dependencies: false
51-
# For testing forced minimum deps, use the latest stable version of Python
52-
# on which those dependencies can be installed
51+
# For testing forced minimum deps, use the newest and oldest stable
52+
# versions of Python on which those dependencies can be installed.
53+
- python: "3.8"
54+
platform: ubuntu-latest
55+
force-minimum-dependencies: true
5356
- python: "3.12"
5457
platform: ubuntu-latest
5558
force-minimum-dependencies: true

src/setuptools_pyproject_migration/__init__.py

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import configparser
22
import itertools
3+
import logging
34
import re
45
import setuptools
56
import sys
@@ -13,6 +14,9 @@
1314
from typing import Dict, List, Optional, Set, Tuple, TypeVar, Union
1415

1516

17+
_logger = logging.getLogger("setuptools_pyproject_migration")
18+
19+
1620
def _parse_entry_point(entry_point: str) -> Tuple[str, str]:
1721
"""
1822
Extract the entry point and name from the string.
@@ -343,24 +347,39 @@ def _generate(self) -> Pyproject:
343347
# version constraint string, which is exactly what we want here
344348
pyproject["project"]["requires-python"] = str(python_specifiers)
345349

346-
# NB: ensure a consistent alphabetical ordering of dependencies
347-
dependencies = sorted(set(dist.install_requires))
348-
if dependencies:
349-
pyproject["project"]["dependencies"] = dependencies
350+
_logger.debug("dist.install_requires: %r", dist.install_requires)
351+
dependencies = set(dist.install_requires)
350352

353+
_logger.debug("dist.extras_require: %r", dist.extras_require)
351354
optional_dependencies: Dict[str, Set[str]] = {}
352355
for extra_dep_key, deps in dist.extras_require.items():
353356
extra, _, constraint = extra_dep_key.partition(":")
354-
optional_dependencies.setdefault(extra, set())
357+
_logger.debug("Handling extra=%r, constraint=%r", extra, constraint)
358+
target: Set[str]
359+
if extra:
360+
_logger.debug("Adding to optional_dependencies[%r]", extra)
361+
target = optional_dependencies.setdefault(extra, set())
362+
else:
363+
_logger.debug("Adding to dependencies")
364+
target = dependencies
355365
for dep in deps:
356366
if constraint:
357-
optional_dependencies[extra].add(f"{dep}; {constraint}")
367+
_logger.debug("Adding dependency %s with constraint %r", dep, constraint)
368+
target.add(f"{dep}; {constraint}")
358369
else:
359-
optional_dependencies[extra].add(dep)
370+
_logger.debug("Adding dependency %s with no constraint", dep)
371+
target.add(dep)
372+
373+
if dependencies:
374+
# NB: ensure a consistent alphabetical ordering of dependencies
375+
sorted_dependencies = sorted(dependencies)
376+
_logger.debug("Setting project.dependencies to: %r", sorted_dependencies)
377+
pyproject["project"]["dependencies"] = sorted_dependencies
378+
360379
if optional_dependencies:
361-
pyproject["project"]["optional-dependencies"] = {
362-
extra: sorted(deps) for extra, deps in optional_dependencies.items()
363-
}
380+
sorted_optional_dependencies = {extra: sorted(deps) for extra, deps in optional_dependencies.items()}
381+
_logger.debug("Setting project.optional_dependencies to: %r", sorted_optional_dependencies)
382+
pyproject["project"]["optional-dependencies"] = sorted_optional_dependencies
364383

365384
entry_points = _generate_entry_points(dist.entry_points)
366385

tests/distribution/test_distribution_packages.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import packaging.markers
2525
import packaging.requirements
2626
import pytest
27-
import sys
2827

2928
from typing import Iterator, List
3029

@@ -51,8 +50,6 @@ def _setuptools_scm_version_conflict() -> bool:
5150
See `issue 145 <https://github.com/diazona/setuptools-pyproject-migration/issues/145>`_.
5251
"""
5352

54-
if sys.version_info < (3, 12):
55-
return False
5653
from test_support import importlib_metadata
5754
from packaging.version import Version
5855

tests/test_optional_dependencies.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,18 @@ def test_empty_extras(make_write_pyproject) -> None:
205205
cmd = make_write_pyproject(extras_require={})
206206
result = cmd._generate()
207207
assert "optional-dependencies" not in result["project"]
208+
209+
210+
def test_required_dependencies_with_constraints(make_write_pyproject) -> None:
211+
"""
212+
Test that required dependencies with constraints are not added to the list
213+
of optional dependencies.
214+
215+
This exercises a bug in setuptools<68.2 where required deps with constraints
216+
get added to the list of optional dependencies with an empty extra.
217+
"""
218+
dependencies: List[str] = ["holy-pin", 'holy-hand-grenade; python_version == "3.*"']
219+
cmd = make_write_pyproject(install_requires=dependencies)
220+
result = cmd._generate()
221+
assert set(result["project"]["dependencies"]) == set(dependencies)
222+
assert "optional-dependencies" not in result["project"]

0 commit comments

Comments
 (0)