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

pantsbuild / pants / 19015773527

02 Nov 2025 05:33PM UTC coverage: 17.872% (-62.4%) from 80.3%
19015773527

Pull #22816

github

web-flow
Merge a12d75757 into 6c024e162
Pull Request #22816: Update Pants internal Python to 3.14

4 of 5 new or added lines in 3 files covered. (80.0%)

28452 existing lines in 683 files now uncovered.

9831 of 55007 relevant lines covered (17.87%)

0.18 hits per line

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

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

UNCOV
4
from __future__ import annotations
×
5

UNCOV
6
import dataclasses
×
UNCOV
7
import re
×
UNCOV
8
from collections.abc import Iterable, Iterator, Mapping
×
UNCOV
9
from dataclasses import dataclass
×
10

UNCOV
11
from pants.backend.openapi.subsystems import openapi_generator
×
UNCOV
12
from pants.backend.openapi.subsystems.openapi_generator import OpenAPIGenerator
×
UNCOV
13
from pants.engine.fs import Digest
×
UNCOV
14
from pants.engine.internals.native_engine import EMPTY_DIGEST
×
UNCOV
15
from pants.engine.process import Process, ProcessCacheScope, fallible_to_exec_result_or_raise
×
UNCOV
16
from pants.engine.rules import collect_rules, implicitly, rule
×
UNCOV
17
from pants.jvm import jdk_rules, non_jvm_dependencies
×
UNCOV
18
from pants.jvm.jdk_rules import InternalJdk, JvmProcess, jvm_process
×
UNCOV
19
from pants.jvm.resolve import coursier_fetch, coursier_setup, jvm_tool
×
UNCOV
20
from pants.jvm.resolve.coursier_fetch import ToolClasspathRequest, materialize_classpath_for_tool
×
UNCOV
21
from pants.jvm.resolve.jvm_tool import GenerateJvmLockfileFromTool
×
UNCOV
22
from pants.jvm.util_rules import rules as jvm_util_rules
×
UNCOV
23
from pants.util.frozendict import FrozenDict
×
UNCOV
24
from pants.util.logging import LogLevel
×
25

26

UNCOV
27
@dataclass(frozen=True)
×
UNCOV
28
class OpenAPIGeneratorProcess:
×
UNCOV
29
    argv: tuple[str, ...]
×
UNCOV
30
    generator_name: str
×
UNCOV
31
    input_digest: Digest
×
UNCOV
32
    description: str = dataclasses.field(compare=False)
×
UNCOV
33
    level: LogLevel
×
UNCOV
34
    extra_env: FrozenDict[str, str]
×
UNCOV
35
    extra_immutable_input_digests: FrozenDict[str, Digest]
×
UNCOV
36
    extra_classpath_entries: tuple[str, ...]
×
UNCOV
37
    extra_jvm_options: tuple[str, ...]
×
UNCOV
38
    cache_scope: ProcessCacheScope | None
×
UNCOV
39
    output_directories: tuple[str, ...]
×
UNCOV
40
    output_files: tuple[str, ...]
×
41

UNCOV
42
    def __init__(
×
43
        self,
44
        *,
45
        generator_name: str,
46
        argv: Iterable[str],
47
        input_digest: Digest,
48
        description: str,
49
        level: LogLevel = LogLevel.INFO,
50
        output_directories: Iterable[str] | None = None,
51
        output_files: Iterable[str] | None = None,
52
        extra_env: Mapping[str, str] | None = None,
53
        extra_classpath_entries: Iterable[str] | None = None,
54
        extra_immutable_input_digests: Mapping[str, Digest] | None = None,
55
        extra_jvm_options: Iterable[str] | None = None,
56
        cache_scope: ProcessCacheScope | None = None,
57
    ):
UNCOV
58
        object.__setattr__(self, "generator_name", generator_name)
×
UNCOV
59
        object.__setattr__(self, "argv", tuple(argv))
×
UNCOV
60
        object.__setattr__(self, "input_digest", input_digest)
×
UNCOV
61
        object.__setattr__(self, "description", description)
×
UNCOV
62
        object.__setattr__(self, "level", level)
×
UNCOV
63
        object.__setattr__(self, "output_directories", tuple(output_directories or ()))
×
UNCOV
64
        object.__setattr__(self, "output_files", tuple(output_files or ()))
×
UNCOV
65
        object.__setattr__(self, "extra_env", FrozenDict(extra_env or {}))
×
UNCOV
66
        object.__setattr__(self, "extra_classpath_entries", tuple(extra_classpath_entries or ()))
×
UNCOV
67
        object.__setattr__(
×
68
            self, "extra_immutable_input_digests", FrozenDict(extra_immutable_input_digests or {})
69
        )
UNCOV
70
        object.__setattr__(self, "extra_jvm_options", tuple(extra_jvm_options or ()))
×
UNCOV
71
        object.__setattr__(self, "cache_scope", cache_scope)
×
72

73

UNCOV
74
_GENERATOR_CLASS_NAME = "org.openapitools.codegen.OpenAPIGenerator"
×
75

76

UNCOV
77
@dataclass(frozen=True)
×
UNCOV
78
class OpenAPIGeneratorNames:
×
UNCOV
79
    names: tuple[str, ...]
×
80

81

UNCOV
82
def _parse_names(stdout: str) -> Iterator[str]:
×
83
    regex = re.compile(r"^ *- (?P<name>[^ ]+)")
×
84
    for line in stdout.splitlines():
×
85
        if (match := regex.match(line)) is not None:
×
86
            yield match.group("name")
×
87

88

UNCOV
89
@rule
×
UNCOV
90
async def get_openapi_generator_names(
×
91
    subsystem: OpenAPIGenerator, jdk: InternalJdk
92
) -> OpenAPIGeneratorNames:
93
    tool_classpath = await materialize_classpath_for_tool(
×
94
        ToolClasspathRequest(lockfile=GenerateJvmLockfileFromTool.create(subsystem))
95
    )
96

97
    toolcp_relpath = "__toolcp"
×
98
    immutable_input_digests = {
×
99
        toolcp_relpath: tool_classpath.digest,
100
    }
101

102
    classpath_entries = [
×
103
        *tool_classpath.classpath_entries(toolcp_relpath),
104
    ]
105

106
    jvm_process = JvmProcess(
×
107
        jdk=jdk,
108
        argv=[_GENERATOR_CLASS_NAME, "list"],
109
        classpath_entries=classpath_entries,
110
        input_digest=EMPTY_DIGEST,
111
        extra_immutable_input_digests=immutable_input_digests,
112
        extra_jvm_options=subsystem.jvm_options,
113
        description="Get openapi generator names.",
114
        cache_scope=ProcessCacheScope.SUCCESSFUL,
115
    )
116
    result = await fallible_to_exec_result_or_raise(**implicitly({jvm_process: JvmProcess}))
×
117
    return OpenAPIGeneratorNames(names=tuple(_parse_names(result.stdout.decode("utf-8"))))
×
118

119

UNCOV
120
@rule
×
UNCOV
121
async def openapi_generator_process(
×
122
    request: OpenAPIGeneratorProcess,
123
    jdk: InternalJdk,
124
    subsystem: OpenAPIGenerator,
125
    generator_names: OpenAPIGeneratorNames,
126
) -> Process:
127
    if request.generator_name not in generator_names.names:
×
128
        names = ", ".join(f"`{name}`" for name in generator_names.names)
×
129
        raise ValueError(
×
130
            f"OpenAPI generator `{request.generator_name}` is not found, available generators: {names}"
131
        )
132

133
    tool_classpath = await materialize_classpath_for_tool(
×
134
        ToolClasspathRequest(lockfile=GenerateJvmLockfileFromTool.create(subsystem))
135
    )
136

137
    toolcp_relpath = "__toolcp"
×
138
    immutable_input_digests = {
×
139
        toolcp_relpath: tool_classpath.digest,
140
        **request.extra_immutable_input_digests,
141
    }
142

143
    classpath_entries = [
×
144
        *tool_classpath.classpath_entries(toolcp_relpath),
145
        *request.extra_classpath_entries,
146
    ]
147

148
    extra_jvm_options = [*subsystem.jvm_options, *request.extra_jvm_options]
×
149

150
    return await jvm_process(
×
151
        **implicitly(
152
            JvmProcess(
153
                jdk=jdk,
154
                argv=[
155
                    _GENERATOR_CLASS_NAME,
156
                    "generate",
157
                    "-g",
158
                    request.generator_name,
159
                    *request.argv,
160
                ],
161
                classpath_entries=classpath_entries,
162
                input_digest=request.input_digest,
163
                extra_env=request.extra_env,
164
                extra_immutable_input_digests=immutable_input_digests,
165
                extra_jvm_options=extra_jvm_options,
166
                description=request.description,
167
                level=request.level,
168
                output_directories=request.output_directories,
169
                output_files=request.output_files,
170
                cache_scope=request.cache_scope or ProcessCacheScope.SUCCESSFUL,
171
            )
172
        )
173
    )
174

175

UNCOV
176
def rules():
×
UNCOV
177
    return [
×
178
        *collect_rules(),
179
        *openapi_generator.rules(),
180
        *coursier_setup.rules(),
181
        *coursier_fetch.rules(),
182
        *jvm_tool.rules(),
183
        *jdk_rules.rules(),
184
        *non_jvm_dependencies.rules(),
185
        *jvm_util_rules(),
186
    ]
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

© 2025 Coveralls, Inc