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

pantsbuild / pants / 25441711719

06 May 2026 02:31PM UTC coverage: 92.915%. Remained the same
25441711719

push

github

web-flow
use sha pin (with comment) format for generated actions (#23312)

Per the GitHub Action best practices we recently enabled at #23249, we
should pin each action to a SHA so that the reference is actually
immutable.

This will -- I hope -- knock out a large chunk of the 421 alerts we
currently get from zizmor. The next followup would then be upgrades and
harmonizing the generated and none-generated pins.

Notice: This idea was suggested by Claude while going over pinact output
and I was surprised to see that post processing the yaml wasn't too
gross.

92206 of 99237 relevant lines covered (92.91%)

4.04 hits per line

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

100.0
/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
5✔
5

6
import json
5✔
7

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

28

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

33

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

49

50
class GenerateFromPipenvRequirementsRequest(GenerateTargetsRequest):
5✔
51
    generate_from = PipenvRequirementsTargetGenerator
5✔
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)
5✔
57
async def generate_from_pipenv_requirements(
5✔
58
    request: GenerateFromPipenvRequirementsRequest,
59
    union_membership: UnionMembership,
60
    python_setup: PythonSetup,
61
) -> GeneratedTargets:
62
    result = await _generate_requirements(
1✔
63
        request,
64
        union_membership,
65
        python_setup,
66
        parse_requirements_callback=parse_pipenv_requirements,
67
    )
68
    return GeneratedTargets(request.generator, result)
1✔
69

70

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

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

83
        return PipRequirement.parse(raw_req)
1✔
84

85
    return tuple(
2✔
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():
5✔
92
    return (
5✔
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