Skip to content

Commit

Permalink
infer go_external_module targets
Browse files Browse the repository at this point in the history
[ci skip-rust]

[ci skip-build-wheels]
  • Loading branch information
Tom Dyas committed Jul 22, 2021
1 parent baa1b46 commit 12388c6
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 18 deletions.
68 changes: 67 additions & 1 deletion src/python/pants/backend/go/tailor.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
# Copyright 2021 Pants project contributors (see CONTRIBUTORS.md).
# Licensed under the Apache License, Version 2.0 (see LICENSE).
import itertools
import os
from dataclasses import dataclass

from pants.backend.go.target_types import GoModule, GoPackage
from pants.backend.go.module import ResolvedGoModule, ResolveGoModuleRequest
from pants.backend.go.target_types import GoExternalModule, GoModule, GoModuleSources, GoPackage
from pants.base.specs import AddressSpecs, MaybeEmptyDescendantAddresses, MaybeEmptySiblingAddresses
from pants.core.goals.tailor import (
AllOwnedSources,
PutativeTarget,
Expand All @@ -14,6 +17,7 @@
from pants.engine.fs import PathGlobs, Paths
from pants.engine.internals.selectors import Get
from pants.engine.rules import collect_rules, rule
from pants.engine.target import UnexpandedTargets
from pants.engine.unions import UnionRule
from pants.util.logging import LogLevel

Expand Down Expand Up @@ -70,9 +74,71 @@ async def find_putative_go_module_targets(
return PutativeTargets(putative_targets)


def compute_go_external_module_target_name(name: str, version: str) -> str:
return f"{name.replace('/', '_')}_{version}"


@dataclass(frozen=True)
class PutativeGoExternalModuleTargetsRequest(PutativeTargetsRequest):
pass


@rule(level=LogLevel.DEBUG, desc="Determine candidate Go `go_external_module` targets to create")
async def find_putative_go_external_module_targets(
request: PutativeGoExternalModuleTargetsRequest, _all_owned_sources: AllOwnedSources
) -> PutativeTargets:
# Unlike ordinary tailor invocations, this rule looks at existing `go_module` targets and not at actual
# source files because it infers `go_external_module` targets based on go.mod contents. (This may require
# invoking `tailor` first to create `go_module` targets and then again to create `go_external_module`
# targets.)

addresses = itertools.chain.from_iterable(
[
[MaybeEmptySiblingAddresses(search_path), MaybeEmptyDescendantAddresses(search_path)]
for search_path in request.search_paths.dirs
]
)
candidate_targets = await Get(UnexpandedTargets, AddressSpecs(addresses))
go_module_targets = [
tgt
for tgt in candidate_targets
if tgt.has_field(GoModuleSources) and not tgt.address.is_file_target
]

putative_targets = []

for go_module_target in go_module_targets:
resolved_go_module = await Get(
ResolvedGoModule, ResolveGoModuleRequest(go_module_target.address)
)
for module_descriptor in resolved_go_module.modules:
putative_targets.append(
PutativeTarget.for_target_type(
GoExternalModule,
go_module_target.address.spec_path,
compute_go_external_module_target_name(
module_descriptor.module_path, module_descriptor.module_version
),
[],
kwargs={
"path": module_descriptor.module_path,
"version": module_descriptor.module_version,
"import_path": module_descriptor.import_path,
},
build_file_name="BUILD.godeps",
comments=(
"Auto-generated by `./pants tailor`. Re-run `./pants tailor` if go.mod changes.",
),
)
)

return PutativeTargets(putative_targets)


def rules():
return [
*collect_rules(),
UnionRule(PutativeTargetsRequest, PutativeGoPackageTargetsRequest),
UnionRule(PutativeTargetsRequest, PutativeGoModuleTargetsRequest),
UnionRule(PutativeTargetsRequest, PutativeGoExternalModuleTargetsRequest),
]
96 changes: 79 additions & 17 deletions src/python/pants/backend/go/tailor_test.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,61 @@
# Copyright 2021 Pants project contributors (see CONTRIBUTORS.md).
# Licensed under the Apache License, Version 2.0 (see LICENSE).
from pants.backend.go.tailor import PutativeGoModuleTargetsRequest, PutativeGoPackageTargetsRequest
import textwrap

import pytest

from pants.backend.go import module, target_type_rules
from pants.backend.go.module import ResolvedGoModule, ResolveGoModuleRequest
from pants.backend.go.tailor import (
PutativeGoExternalModuleTargetsRequest,
PutativeGoModuleTargetsRequest,
PutativeGoPackageTargetsRequest,
)
from pants.backend.go.tailor import rules as go_tailor_rules
from pants.backend.go.target_types import GoModule, GoPackage
from pants.backend.go.target_types import GoExternalModule, GoModule, GoPackage
from pants.core.goals.tailor import (
AllOwnedSources,
PutativeTarget,
PutativeTargets,
PutativeTargetsSearchPaths,
)
from pants.core.goals.tailor import rules as core_tailor_rules
from pants.core.util_rules import external_tool, source_files
from pants.engine.addresses import Addresses
from pants.engine.rules import QueryRule
from pants.engine.target import DependenciesRequest, UnexpandedTargets
from pants.testutil.rule_runner import RuleRunner


def test_find_putative_go_package_targets() -> None:
@pytest.fixture
def rule_runner() -> RuleRunner:
rule_runner = RuleRunner(
rules=[
*core_tailor_rules(),
*go_tailor_rules(),
*external_tool.rules(),
*source_files.rules(),
*module.rules(),
*target_type_rules.rules(),
QueryRule(PutativeTargets, [PutativeGoPackageTargetsRequest, AllOwnedSources]),
QueryRule(PutativeTargets, [PutativeGoModuleTargetsRequest, AllOwnedSources]),
QueryRule(PutativeTargets, [PutativeGoExternalModuleTargetsRequest, AllOwnedSources]),
QueryRule(AllOwnedSources, ()),
QueryRule(Addresses, (DependenciesRequest,)),
QueryRule(UnexpandedTargets, (Addresses,)),
QueryRule(ResolvedGoModule, [ResolveGoModuleRequest]),
],
target_types=[
GoPackage,
GoModule,
GoExternalModule,
],
)
rule_runner.set_options(["--backend-packages=pants.backend.experimental.go"])
return rule_runner


def test_find_putative_go_package_targets(rule_runner: RuleRunner) -> None:
rule_runner.write_files(
{
"src/go/owned/BUILD": "go_package()\n",
Expand Down Expand Up @@ -60,20 +88,7 @@ def test_find_putative_go_package_targets() -> None:
)


def test_find_putative_go_module_targets() -> None:
rule_runner = RuleRunner(
rules=[
*core_tailor_rules(),
*go_tailor_rules(),
QueryRule(PutativeTargets, [PutativeGoModuleTargetsRequest, AllOwnedSources]),
QueryRule(AllOwnedSources, ()),
],
target_types=[
GoModule,
],
)
rule_runner.set_options(["--backend-packages=pants.backend.experimental.go"])

def test_find_putative_go_module_targets(rule_runner: RuleRunner) -> None:
rule_runner.write_files(
{
"src/go/owned/BUILD": "go_module()\n",
Expand Down Expand Up @@ -104,3 +119,50 @@ def test_find_putative_go_module_targets() -> None:
),
]
)


def test_find_putative_go_external_module_targets(rule_runner: RuleRunner) -> None:
rule_runner.write_files(
{
"src/go/BUILD": "go_module()\n",
"src/go/go.mod": textwrap.dedent(
"""\
module example.com/src/go
go 1.16
require (
github.com/google/uuid v1.2.0
)
"""
),
}
)
putative_targets = rule_runner.request(
PutativeTargets,
[
PutativeGoExternalModuleTargetsRequest(PutativeTargetsSearchPaths(("src/",))),
AllOwnedSources(
[
"src/go/go.mod",
]
),
],
)
assert putative_targets == PutativeTargets(
[
PutativeTarget.for_target_type(
GoExternalModule,
"src/go",
"github.com_google_uuid_v1.2.0",
[],
kwargs={
"path": "github.com/google/uuid",
"version": "v1.2.0",
"import_path": "github.com/google/uuid",
},
build_file_name="BUILD.godeps",
comments=(
"Auto-generated by `./pants tailor`. Re-run `./pants tailor` if go.mod changes.",
),
),
]
)

0 comments on commit 12388c6

Please sign in to comment.