Skip to content

Commit

Permalink
Merge pull request #51 from sbrunner/multiple-constraints
Browse files Browse the repository at this point in the history
Fix multiple constraints
  • Loading branch information
carlio authored Nov 8, 2024
2 parents ae17781 + e84d27b commit 41c39cb
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 10 deletions.
40 changes: 30 additions & 10 deletions requirements_detector/detect.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import re
import sys
from pathlib import Path
from typing import List, Union
from typing import List, Optional, Union

import toml

from .exceptions import CouldNotParseRequirements, RequirementsNotFound
from .handle_setup import from_setup_py
from .poetry_semver import parse_constraint
from .poetry_semver.version_constraint import VersionConstraint
from .requirement import DetectedRequirement

_USE_TOMLLIB = sys.version_info.major > 3 or sys.version_info.minor >= 11
Expand Down Expand Up @@ -109,6 +110,25 @@ def find_requirements(path: P) -> List[DetectedRequirement]:
raise RequirementsNotFound


def _version_from_spec(spec: Union[list, dict, str]) -> Optional[VersionConstraint]:
if isinstance(spec, list):
constraint = None
for new_constraint in [_version_from_spec(s) for s in spec]:
if constraint is None:
constraint = new_constraint
elif new_constraint is not None:
constraint = constraint.union(new_constraint)
return constraint

if isinstance(spec, dict):
if "version" in spec:
spec = spec["version"]
else:
return None

return parse_constraint(spec)


def from_pyproject_toml(toml_file: P) -> List[DetectedRequirement]:
requirements = []

Expand All @@ -127,15 +147,15 @@ def from_pyproject_toml(toml_file: P) -> List[DetectedRequirement]:
for name, spec in dependencies.items():
if name.lower() == "python":
continue
if isinstance(spec, dict):
if "version" in spec:
spec = spec["version"]
else:
req = DetectedRequirement.parse(f"{name}", toml_file)
if req is not None:
requirements.append(req)
continue
parsed_spec = str(parse_constraint(spec))

parsed_spec_obj = _version_from_spec(spec)
if parsed_spec_obj is None and isinstance(spec, dict) and "version" not in spec:
req = DetectedRequirement.parse(f"{name}", toml_file)
if req is not None:
requirements.append(req)
continue
assert parsed_spec_obj is not None
parsed_spec = str(parsed_spec_obj)
if "," not in parsed_spec and "<" not in parsed_spec and ">" not in parsed_spec and "=" not in parsed_spec:
parsed_spec = f"=={parsed_spec}"

Expand Down
14 changes: 14 additions & 0 deletions tests/test_poetry_semver/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,3 +196,17 @@ def test_versions_are_sortable(unsorted, sorted_):
sorted_ = [parse_constraint(s) for s in sorted_]

assert sorted(unsorted) == sorted_


@pytest.mark.parametrize(
"constraint, expected",
[
([
{'version': "<=1.9", 'python': ">=3.6,<3.8"},
{'version': "^2.0", 'python': ">=3.8"}
], VersionUnion(VersionRange(max=Version(1, 9), include_max=True), VersionRange(Version(2), Version(3), True)))
])
def test_versions_list(constraint, expected):
from requirements_detector.detect import _version_from_spec
assert _version_from_spec(constraint) == expected

0 comments on commit 41c39cb

Please sign in to comment.