• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pantsbuild / pants / 22285099215

22 Feb 2026 08:52PM UTC coverage: 75.854% (-17.1%) from 92.936%
22285099215

Pull #23121

github

web-flow
Merge c7299df9c into ba8359840
Pull Request #23121: fix issue with optional fields in dependency validator

28 of 29 new or added lines in 2 files covered. (96.55%)

11174 existing lines in 400 files now uncovered.

53694 of 70786 relevant lines covered (75.85%)

1.88 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

71.79
/src/python/pants/backend/python/macros/pipenv_requirements.py
1
# Copyright 2022 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3

4
from __future__ import annotations
1✔
5

6
import json
1✔
7

8
from pants.backend.python.macros.common_fields import (
1✔
9
    ModuleMappingField,
10
    RequirementsOverrideField,
11
    TypeStubsModuleMappingField,
12
)
13
from pants.backend.python.macros.common_requirements_rule import _generate_requirements
1✔
14
from pants.backend.python.subsystems.setup import PythonSetup
1✔
15
from pants.backend.python.target_types import PythonRequirementResolveField, PythonRequirementTarget
1✔
16
from pants.engine.rules import collect_rules, rule
1✔
17
from pants.engine.target import (
1✔
18
    COMMON_TARGET_FIELDS,
19
    GeneratedTargets,
20
    GenerateTargetsRequest,
21
    SingleSourceField,
22
    TargetGenerator,
23
)
24
from pants.engine.unions import UnionMembership, UnionRule
1✔
25
from pants.util.logging import LogLevel
1✔
26
from pants.util.pip_requirement import PipRequirement
1✔
27

28

29
class PipenvSourceField(SingleSourceField):
1✔
30
    default = "Pipfile.lock"
1✔
31
    required = False
1✔
32

33

34
class PipenvRequirementsTargetGenerator(TargetGenerator):
1✔
35
    alias = "pipenv_requirements"
1✔
36
    help = "Generate a `python_requirement` for each entry in `Pipenv.lock`."
1✔
37
    generated_target_cls = PythonRequirementTarget
1✔
38
    # Note that this does not have a `dependencies` field.
39
    core_fields = (
1✔
40
        *COMMON_TARGET_FIELDS,
41
        ModuleMappingField,
42
        TypeStubsModuleMappingField,
43
        PipenvSourceField,
44
        RequirementsOverrideField,
45
    )
46
    copied_fields = COMMON_TARGET_FIELDS
1✔
47
    moved_fields = (PythonRequirementResolveField,)
1✔
48

49

50
class GenerateFromPipenvRequirementsRequest(GenerateTargetsRequest):
1✔
51
    generate_from = PipenvRequirementsTargetGenerator
1✔
52

53

54
# TODO(#10655): add support for PEP 440 direct references (aka VCS style).
55
# TODO(#10655): differentiate between Pipfile vs. Pipfile.lock.
56
@rule(desc="Generate `python_requirement` targets from Pipfile.lock", level=LogLevel.DEBUG)
1✔
57
async def generate_from_pipenv_requirements(
1✔
58
    request: GenerateFromPipenvRequirementsRequest,
59
    union_membership: UnionMembership,
60
    python_setup: PythonSetup,
61
) -> GeneratedTargets:
UNCOV
62
    result = await _generate_requirements(
×
63
        request,
64
        union_membership,
65
        python_setup,
66
        parse_requirements_callback=parse_pipenv_requirements,
67
    )
UNCOV
68
    return GeneratedTargets(request.generator, result)
×
69

70

71
def parse_pipenv_requirements(
1✔
72
    file_contents: bytes, file_path: str = ""
73
) -> tuple[PipRequirement, ...]:
UNCOV
74
    lock_info = json.loads(file_contents)
×
75

UNCOV
76
    def _parse_pipenv_requirement(raw_req: str, info: dict) -> PipRequirement:
×
UNCOV
77
        if info.get("extras"):
×
UNCOV
78
            raw_req += f"[{','.join(info['extras'])}]"
×
UNCOV
79
        raw_req += info.get("version", "")
×
UNCOV
80
        if info.get("markers"):
×
UNCOV
81
            raw_req += f";{info['markers']}"
×
82

UNCOV
83
        return PipRequirement.parse(raw_req)
×
84

UNCOV
85
    return tuple(
×
86
        _parse_pipenv_requirement(req, info)
87
        for req, info in {**lock_info.get("default", {}), **lock_info.get("develop", {})}.items()
88
    )
89

90

91
def rules():
1✔
92
    return (
1✔
93
        *collect_rules(),
94
        UnionRule(GenerateTargetsRequest, GenerateFromPipenvRequirementsRequest),
95
    )
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc