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

pantsbuild / pants / 20332790708

18 Dec 2025 09:48AM UTC coverage: 64.992% (-15.3%) from 80.295%
20332790708

Pull #22949

github

web-flow
Merge f730a56cd into 407284c67
Pull Request #22949: Add experimental uv resolver for Python lockfiles

54 of 97 new or added lines in 5 files covered. (55.67%)

8270 existing lines in 295 files now uncovered.

48990 of 75379 relevant lines covered (64.99%)

1.81 hits per line

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

67.31
/src/python/pants/backend/terraform/dependency_inference_test.py
1
# Copyright 2021 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3
import textwrap
1✔
4

5
import pytest
1✔
6

7
from pants.backend.terraform import dependency_inference
1✔
8
from pants.backend.terraform.dependency_inference import (
1✔
9
    InferTerraformDeploymentDependenciesRequest,
10
    InferTerraformModuleDependenciesRequest,
11
    ParseTerraformModuleSources,
12
    TerraformDeploymentDependenciesInferenceFieldSet,
13
    TerraformHcl2Parser,
14
    TerraformModuleDependenciesInferenceFieldSet,
15
)
16
from pants.backend.terraform.goals.lockfiles import rules as terraform_lockfile_rules
1✔
17
from pants.backend.terraform.target_types import (
1✔
18
    TerraformBackendTarget,
19
    TerraformDeploymentTarget,
20
    TerraformLockfileTarget,
21
    TerraformModuleTarget,
22
    TerraformVarFileTarget,
23
)
24
from pants.build_graph.address import Address
1✔
25
from pants.core.util_rules import external_tool, source_files
1✔
26
from pants.engine.process import ProcessResult
1✔
27
from pants.engine.rules import QueryRule
1✔
28
from pants.engine.target import (
1✔
29
    HydratedSources,
30
    HydrateSourcesRequest,
31
    InferredDependencies,
32
    SourcesField,
33
)
34
from pants.testutil.pants_integration_test import run_pants
1✔
35
from pants.testutil.python_interpreter_selection import all_major_minor_python_versions
1✔
36
from pants.testutil.rule_runner import RuleRunner
1✔
37
from pants.util.ordered_set import FrozenOrderedSet
1✔
38

39

40
@pytest.fixture
1✔
41
def rule_runner() -> RuleRunner:
1✔
42
    rule_runner = RuleRunner(
1✔
43
        target_types=[
44
            TerraformModuleTarget,
45
            TerraformDeploymentTarget,
46
            TerraformBackendTarget,
47
            TerraformVarFileTarget,
48
            TerraformLockfileTarget,
49
        ],
50
        rules=[
51
            *external_tool.rules(),
52
            *source_files.rules(),
53
            *terraform_lockfile_rules(),
54
            *dependency_inference.rules(),
55
            QueryRule(InferredDependencies, [InferTerraformModuleDependenciesRequest]),
56
            QueryRule(InferredDependencies, [InferTerraformDeploymentDependenciesRequest]),
57
            QueryRule(HydratedSources, [HydrateSourcesRequest]),
58
            QueryRule(ProcessResult, [ParseTerraformModuleSources]),
59
        ],
60
    )
61
    rule_runner.set_options(
1✔
62
        ["--backend-packages=pants.backend.experimental.terraform"],
63
        env_inherit={"PATH", "PYENV_ROOT", "HOME"},
64
    )
65
    return rule_runner
1✔
66

67

68
def test_dependency_inference_module(rule_runner: RuleRunner) -> None:
1✔
UNCOV
69
    rule_runner.write_files(
×
70
        {
71
            "src/tf/modules/foo/BUILD": "terraform_module()\n",
72
            "src/tf/modules/foo/versions.tf": "",
73
            "src/tf/modules/foo/bar/BUILD": "terraform_module()\n",
74
            "src/tf/modules/foo/bar/versions.tf": "",
75
            "src/tf/resources/grok/.terraform.lock.hcl": "",
76
            "src/tf/resources/grok/subdir/BUILD": "terraform_module()\n",
77
            "src/tf/resources/grok/subdir/versions.tf": "",
78
            "src/tf/resources/grok/BUILD": "terraform_module()\n",
79
            "src/tf/resources/grok/resources.tf": textwrap.dedent(
80
                """\
81
            module "foo" {
82
              source = "../../modules/foo"
83
            }
84
            module "bar" {
85
              source = "../../modules/foo/bar"
86
            }
87
            module "subdir" {
88
              source = "./subdir"
89
            }
90
            # Should not be inferred as a dependency since not a local path.
91
            module "external" {
92
              source = "app.terraform.io/example-corp/k8s-cluster/azurerm"
93
              version = "1.1.0"
94
            }
95
            """
96
            ),
97
        }
98
    )
99

UNCOV
100
    target = rule_runner.get_target(Address("src/tf/resources/grok"))
×
UNCOV
101
    inferred_deps = rule_runner.request(
×
102
        InferredDependencies,
103
        [
104
            InferTerraformModuleDependenciesRequest(
105
                TerraformModuleDependenciesInferenceFieldSet.create(target)
106
            )
107
        ],
108
    )
UNCOV
109
    assert inferred_deps == InferredDependencies(
×
110
        FrozenOrderedSet(
111
            [
112
                Address("src/tf/modules/foo"),
113
                Address("src/tf/modules/foo/bar"),
114
                Address("src/tf/resources/grok/subdir"),
115
                Address("src/tf/resources/grok", target_name=".terraform.lock.hcl"),
116
            ]
117
        ),
118
    )
119

120

121
def test_dependency_inference_deployment(rule_runner: RuleRunner) -> None:
1✔
UNCOV
122
    rule_runner.write_files(
×
123
        {
124
            "src/tf/BUILD": "terraform_module(name='mod')\nterraform_deployment(name='deployment',root_module=':mod')",
125
            "src/tf/main.tf": "",
126
        }
127
    )
128

UNCOV
129
    target = rule_runner.get_target(Address("src/tf", target_name="deployment"))
×
UNCOV
130
    inferred_deps = rule_runner.request(
×
131
        InferredDependencies,
132
        [
133
            InferTerraformDeploymentDependenciesRequest(
134
                TerraformDeploymentDependenciesInferenceFieldSet.create(target)
135
            )
136
        ],
137
    )
UNCOV
138
    assert inferred_deps == InferredDependencies(
×
139
        FrozenOrderedSet([Address("src/tf", target_name="mod")])
140
    )
141

142

143
def test_dependency_inference_autoinfered_files(rule_runner: RuleRunner) -> None:
1✔
144
    """Check that autoinference on tfvars and tfbackends works."""
UNCOV
145
    rule_runner.write_files(
×
146
        {
147
            "src/tf/BUILD": 'terraform_module(name="mod")\nterraform_deployment(name="deployment",root_module=":mod",)\nterraform_backend(name="tfbackend", source="main.tfbackend")\nterraform_var_files(name="tfvars")',
148
            "src/tf/main.tf": "",
149
            "src/tf/main.tfvars": "",
150
            "src/tf/main.tfbackend": "",
151
            "src/tf/.terraform.lock.hcl": "",
152
        }
153
    )
UNCOV
154
    target = rule_runner.get_target(Address("src/tf", target_name="deployment"))
×
UNCOV
155
    inferred_deps = rule_runner.request(
×
156
        InferredDependencies,
157
        [
158
            InferTerraformDeploymentDependenciesRequest(
159
                TerraformDeploymentDependenciesInferenceFieldSet.create(target)
160
            )
161
        ],
162
    )
UNCOV
163
    assert set(inferred_deps.include) == {
×
164
        Address("src/tf", target_name=tgt) for tgt in ("mod", "tfbackend", "tfvars")
165
    }
166

167

168
def test_dependency_inference_autoinfered_override(rule_runner: RuleRunner) -> None:
1✔
169
    """Check that autoinference on tfvars and tfbackends can be overridden."""
UNCOV
170
    rule_runner.write_files(
×
171
        {
172
            "src/tf/BUILD": textwrap.dedent(
173
                """\
174
                terraform_module(name="mod")
175
                terraform_deployment(name="deployment",root_module=":mod",dependencies=[":0.tfbackend",":0.tfvars"])
176
                terraform_backend(name="0.tfbackend", source="0.tfbackend")
177
                terraform_backend(name="1.tfbackend", source="1.tfbackend")
178
                terraform_var_files(name="0.tfvars", sources=["0.tfvars"])
179
                terraform_var_files(name="1.tfvars", sources=["1.tfvars"])
180
                """
181
            ),
182
            "src/tf/main.tf": "",
183
            "src/tf/0.tfvars": "",
184
            "src/tf/1.tfvars": "",
185
            "src/tf/0.tfbackend": "",
186
            "src/tf/1.tfbackend": "",
187
        }
188
    )
UNCOV
189
    target = rule_runner.get_target(Address("src/tf", target_name="deployment"))
×
UNCOV
190
    inferred_deps = rule_runner.request(
×
191
        InferredDependencies,
192
        [
193
            InferTerraformDeploymentDependenciesRequest(
194
                TerraformDeploymentDependenciesInferenceFieldSet.create(target)
195
            )
196
        ],
197
    )
UNCOV
198
    assert set(inferred_deps.include) == {
×
199
        Address("src/tf", target_name=tgt) for tgt in ("mod", "0.tfvars", "0.tfbackend")
200
    }
201

202

203
@pytest.mark.platform_specific_behavior
1✔
204
@pytest.mark.parametrize(
1✔
205
    "major_minor_interpreter",
206
    all_major_minor_python_versions(TerraformHcl2Parser.default_interpreter_constraints),
207
)
208
def test_hcl_parser_wrapper_runs(rule_runner: RuleRunner, major_minor_interpreter: str) -> None:
1✔
209
    rule_runner.set_options(
1✔
210
        [
211
            "--backend-packages=pants.backend.experimental.terraform",
212
            f"--terraform-hcl2-parser-interpreter-constraints=['=={major_minor_interpreter}.*']",
213
        ],
214
        env_inherit={"PATH", "PYENV_ROOT", "HOME"},
215
    )
216

217
    rule_runner.write_files(
1✔
218
        {
219
            "foo/BUILD": "terraform_module(name='t')\n",
220
            "foo/bar.tf": textwrap.dedent(
221
                """
222
                module "foo" {
223
                  source = "../grok"
224
                }
225
                module "bar" {
226
                  source = "./hello/./world"
227
                }
228
                """
229
            ),
230
        }
231
    )
232
    target = rule_runner.get_target(Address("foo", target_name="t"))
1✔
233
    sources = rule_runner.request(HydratedSources, [HydrateSourcesRequest(target[SourcesField])])
1✔
234
    result = rule_runner.request(
1✔
235
        ProcessResult,
236
        [
237
            ParseTerraformModuleSources(
238
                sources_digest=sources.snapshot.digest, paths=("foo/bar.tf",)
239
            )
240
        ],
241
    )
242

243
    lines = {line for line in result.stdout.decode("utf-8").splitlines() if line}
1✔
244
    assert lines == {"grok", "foo/hello/world"}
1✔
245

246

247
def test_generate_lockfile_without_python_backend() -> None:
1✔
248
    """Regression test for https://github.com/pantsbuild/pants/issues/14876."""
UNCOV
249
    run_pants(
×
250
        [
251
            "--backend-packages=pants.backend.experimental.terraform",
252
            "--python-resolves={'terraform-hcl2-parser':'tf.lock'}",
253
            "generate-lockfiles",
254
            "--resolve=terraform-hcl2-parser",
255
        ]
256
    ).assert_success()
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