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

pantsbuild / pants / 20632486505

01 Jan 2026 04:21AM UTC coverage: 43.231% (-37.1%) from 80.281%
20632486505

Pull #22962

github

web-flow
Merge 08d5c63b0 into f52ab6675
Pull Request #22962: Bump the gha-deps group across 1 directory with 6 updates

26122 of 60424 relevant lines covered (43.23%)

0.86 hits per line

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

70.45
/src/python/pants/jvm/resolve/lockfile_metadata.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
2✔
5

6
from collections.abc import Iterable
2✔
7
from dataclasses import dataclass
2✔
8
from enum import Enum
2✔
9
from typing import Any, cast
2✔
10

11
from pants.core.util_rules.lockfile_metadata import (
2✔
12
    LockfileMetadata,
13
    LockfileMetadataValidation,
14
    LockfileScope,
15
    _get_metadata,
16
    lockfile_metadata_registrar,
17
)
18
from pants.jvm.resolve.common import ArtifactRequirement
2✔
19
from pants.util.ordered_set import FrozenOrderedSet
2✔
20

21
_jvm_lockfile_metadata = lockfile_metadata_registrar(LockfileScope.JVM)
2✔
22

23

24
class InvalidJVMLockfileReason(Enum):
2✔
25
    REQUIREMENTS_MISMATCH = "requirements_mismatch"
2✔
26

27

28
class LockfileContext(Enum):
2✔
29
    USER = "user"
2✔
30
    TOOL = "tool"
2✔
31

32

33
@dataclass(frozen=True)
2✔
34
class JVMLockfileMetadata(LockfileMetadata):
2✔
35
    scope = LockfileScope.JVM
2✔
36

37
    @staticmethod
2✔
38
    def new(
2✔
39
        requirements: Iterable[ArtifactRequirement],
40
    ) -> JVMLockfileMetadata:
41
        """Call the most recent version of the `LockfileMetadata` class to construct a concrete
42
        instance.
43

44
        This static method should be used in place of the `LockfileMetadata` constructor. This gives
45
        calling sites a predictable method to call to construct a new `LockfileMetadata` for
46
        writing, while still allowing us to support _reading_ older, deprecated metadata versions.
47
        """
48

49
        return JVMLockfileMetadataV1.from_artifact_requirements(requirements)
×
50

51
    def is_valid_for(
2✔
52
        self,
53
        requirements: Iterable[ArtifactRequirement] | None,
54
        context: LockfileContext,
55
    ) -> LockfileMetadataValidation:
56
        """Returns Truthy if this `JVMLockfileMetadata` can be used in the current execution
57
        context."""
58

59
        raise NotImplementedError("call `is_valid_for` on subclasses only")
×
60

61

62
@_jvm_lockfile_metadata(1)
2✔
63
@dataclass(frozen=True)
2✔
64
class JVMLockfileMetadataV1(JVMLockfileMetadata):
2✔
65
    """Initial metadata version for JVM user lockfiles.
66

67
    User validity is tested by the set of user requirements strings appearing as a subset of those
68
    in the metadata requirements.
69

70
    Tool validity is tested by the set of user requirements strings being an exact match of those
71
    in the metadata requirements.
72
    """
73

74
    requirements: FrozenOrderedSet[str]
2✔
75

76
    @classmethod
2✔
77
    def from_artifact_requirements(
2✔
78
        cls, requirements: Iterable[ArtifactRequirement]
79
    ) -> JVMLockfileMetadataV1:
80
        return cls(FrozenOrderedSet(sorted(i.to_metadata_str() for i in requirements)))
×
81

82
    @classmethod
2✔
83
    def _from_json_dict(
2✔
84
        cls: type[JVMLockfileMetadataV1],
85
        json_dict: dict[Any, Any],
86
        lockfile_description: str,
87
        error_suffix: str,
88
    ) -> JVMLockfileMetadataV1:
89
        metadata = _get_metadata(json_dict, lockfile_description, error_suffix)
×
90

91
        requirements = metadata(
×
92
            "generated_with_requirements",
93
            FrozenOrderedSet[str],
94
            FrozenOrderedSet,
95
        )
96

97
        return JVMLockfileMetadataV1(requirements)
×
98

99
    @classmethod
2✔
100
    def additional_header_attrs(cls, instance: LockfileMetadata) -> dict[Any, Any]:
2✔
101
        instance = cast(JVMLockfileMetadataV1, instance)
×
102
        return {
×
103
            "generated_with_requirements": (
104
                sorted(instance.requirements) if instance.requirements is not None else None
105
            )
106
        }
107

108
    def is_valid_for(
2✔
109
        self,
110
        requirements: Iterable[ArtifactRequirement] | None,
111
        context: LockfileContext,
112
    ) -> LockfileMetadataValidation:
113
        """Returns a truthy object if the request requirements match the metadata requirements."""
114

115
        failure_reasons: set[InvalidJVMLockfileReason] = set()
×
116
        req_strings = FrozenOrderedSet(sorted(i.to_metadata_str() for i in requirements or []))
×
117

118
        if (context == LockfileContext.USER and not self.requirements.issuperset(req_strings)) or (
×
119
            context == LockfileContext.TOOL and self.requirements != req_strings
120
        ):
121
            failure_reasons.add(InvalidJVMLockfileReason.REQUIREMENTS_MISMATCH)
×
122

123
        return LockfileMetadataValidation(failure_reasons)
×
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