Skip to content

Commit

Permalink
Merge pull request #176 from diazona/fix-failing-release-tests/2/dev
Browse files Browse the repository at this point in the history
Handle "optional" dependencies with no extra
  • Loading branch information
diazona authored Aug 28, 2024
2 parents eb18597 + fe7c4d8 commit be80bb2
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 15 deletions.
7 changes: 5 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,11 @@ jobs:
- python: "3.13"
platform: ubuntu-latest
force-minimum-dependencies: false
# For testing forced minimum deps, use the latest stable version of Python
# on which those dependencies can be installed
# For testing forced minimum deps, use the newest and oldest stable
# versions of Python on which those dependencies can be installed.
- python: "3.8"
platform: ubuntu-latest
force-minimum-dependencies: true
- python: "3.12"
platform: ubuntu-latest
force-minimum-dependencies: true
Expand Down
39 changes: 29 additions & 10 deletions src/setuptools_pyproject_migration/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import configparser
import itertools
import logging
import re
import setuptools
import sys
Expand All @@ -13,6 +14,9 @@
from typing import Dict, List, Optional, Set, Tuple, TypeVar, Union


_logger = logging.getLogger("setuptools_pyproject_migration")


def _parse_entry_point(entry_point: str) -> Tuple[str, str]:
"""
Extract the entry point and name from the string.
Expand Down Expand Up @@ -343,24 +347,39 @@ def _generate(self) -> Pyproject:
# version constraint string, which is exactly what we want here
pyproject["project"]["requires-python"] = str(python_specifiers)

# NB: ensure a consistent alphabetical ordering of dependencies
dependencies = sorted(set(dist.install_requires))
if dependencies:
pyproject["project"]["dependencies"] = dependencies
_logger.debug("dist.install_requires: %r", dist.install_requires)
dependencies = set(dist.install_requires)

_logger.debug("dist.extras_require: %r", dist.extras_require)
optional_dependencies: Dict[str, Set[str]] = {}
for extra_dep_key, deps in dist.extras_require.items():
extra, _, constraint = extra_dep_key.partition(":")
optional_dependencies.setdefault(extra, set())
_logger.debug("Handling extra=%r, constraint=%r", extra, constraint)
target: Set[str]
if extra:
_logger.debug("Adding to optional_dependencies[%r]", extra)
target = optional_dependencies.setdefault(extra, set())
else:
_logger.debug("Adding to dependencies")
target = dependencies
for dep in deps:
if constraint:
optional_dependencies[extra].add(f"{dep}; {constraint}")
_logger.debug("Adding dependency %s with constraint %r", dep, constraint)
target.add(f"{dep}; {constraint}")
else:
optional_dependencies[extra].add(dep)
_logger.debug("Adding dependency %s with no constraint", dep)
target.add(dep)

if dependencies:
# NB: ensure a consistent alphabetical ordering of dependencies
sorted_dependencies = sorted(dependencies)
_logger.debug("Setting project.dependencies to: %r", sorted_dependencies)
pyproject["project"]["dependencies"] = sorted_dependencies

if optional_dependencies:
pyproject["project"]["optional-dependencies"] = {
extra: sorted(deps) for extra, deps in optional_dependencies.items()
}
sorted_optional_dependencies = {extra: sorted(deps) for extra, deps in optional_dependencies.items()}
_logger.debug("Setting project.optional_dependencies to: %r", sorted_optional_dependencies)
pyproject["project"]["optional-dependencies"] = sorted_optional_dependencies

entry_points = _generate_entry_points(dist.entry_points)

Expand Down
3 changes: 0 additions & 3 deletions tests/distribution/test_distribution_packages.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import packaging.markers
import packaging.requirements
import pytest
import sys

from typing import Iterator, List

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

if sys.version_info < (3, 12):
return False
from test_support import importlib_metadata
from packaging.version import Version

Expand Down
15 changes: 15 additions & 0 deletions tests/test_optional_dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,3 +205,18 @@ def test_empty_extras(make_write_pyproject) -> None:
cmd = make_write_pyproject(extras_require={})
result = cmd._generate()
assert "optional-dependencies" not in result["project"]


def test_required_dependencies_with_constraints(make_write_pyproject) -> None:
"""
Test that required dependencies with constraints are not added to the list
of optional dependencies.
This exercises a bug in setuptools<68.2 where required deps with constraints
get added to the list of optional dependencies with an empty extra.
"""
dependencies: List[str] = ["holy-pin", 'holy-hand-grenade; python_version == "3.*"']
cmd = make_write_pyproject(install_requires=dependencies)
result = cmd._generate()
assert set(result["project"]["dependencies"]) == set(dependencies)
assert "optional-dependencies" not in result["project"]

0 comments on commit be80bb2

Please sign in to comment.