Skip to content

Commit

Permalink
typecheck doesn't care about origin specs
Browse files Browse the repository at this point in the history
# Rust tests and lints will be skipped. Delete if not intended.
[ci skip-rust]

# Building wheels and fs_util will be skipped. Delete if not intended.
[ci skip-build-wheels]
  • Loading branch information
Eric-Arellano committed Aug 19, 2020
1 parent 19dc559 commit 76bfcfb
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 48 deletions.
4 changes: 2 additions & 2 deletions src/python/pants/backend/python/typecheck/mypy/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@
)
from pants.engine.process import FallibleProcessResult
from pants.engine.rules import Get, MultiGet, collect_rules, rule
from pants.engine.target import FieldSetWithOrigin, TransitiveTargets
from pants.engine.target import FieldSet, TransitiveTargets
from pants.engine.unions import UnionRule
from pants.util.logging import LogLevel
from pants.util.strutil import pluralize


@dataclass(frozen=True)
class MyPyFieldSet(FieldSetWithOrigin):
class MyPyFieldSet(FieldSet):
required_fields = (PythonSources,)

sources: PythonSources
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@
from pants.backend.python.target_types import PythonLibrary
from pants.backend.python.typecheck.mypy.rules import MyPyFieldSet, MyPyRequest
from pants.backend.python.typecheck.mypy.rules import rules as mypy_rules
from pants.base.specs import AddressLiteralSpec
from pants.core.goals.typecheck import TypecheckResult, TypecheckResults
from pants.engine.addresses import Address
from pants.engine.fs import FileContent
from pants.engine.rules import RootRule
from pants.engine.target import TargetWithOrigin, WrappedTarget
from pants.engine.target import Target, WrappedTarget
from pants.testutil.engine.util import Params
from pants.testutil.external_tool_test_base import ExternalToolTestBase
from pants.testutil.option.util import create_options_bootstrapper
Expand Down Expand Up @@ -77,13 +76,13 @@ def rules(cls):
def target_types(cls):
return [PythonLibrary]

def make_target_with_origin(
def make_target(
self,
source_files: List[FileContent],
*,
package: Optional[str] = None,
name: str = "target",
) -> TargetWithOrigin:
) -> Target:
if not package:
package = self.package
for source_file in source_files:
Expand All @@ -100,19 +99,17 @@ def make_target_with_origin(
"""
),
)
target = self.request_single_product(
return self.request_single_product(
WrappedTarget,
Params(
Address(package, target_name=name),
create_options_bootstrapper(args=self.global_args),
),
).target
origin = AddressLiteralSpec(package, name)
return TargetWithOrigin(target, origin)

def run_mypy(
self,
targets: List[TargetWithOrigin],
targets: List[Target],
*,
config: Optional[str] = None,
passthrough_args: Optional[str] = None,
Expand All @@ -139,21 +136,21 @@ def run_mypy(
return result.results

def test_passing_source(self) -> None:
target = self.make_target_with_origin([self.good_source])
target = self.make_target([self.good_source])
result = self.run_mypy([target])
assert len(result) == 1
assert result[0].exit_code == 0
assert "Success: no issues found" in result[0].stdout.strip()

def test_failing_source(self) -> None:
target = self.make_target_with_origin([self.bad_source])
target = self.make_target([self.bad_source])
result = self.run_mypy([target])
assert len(result) == 1
assert result[0].exit_code == 1
assert f"{self.package}/bad.py:4" in result[0].stdout

def test_mixed_sources(self) -> None:
target = self.make_target_with_origin([self.good_source, self.bad_source])
target = self.make_target([self.good_source, self.bad_source])
result = self.run_mypy([target])
assert len(result) == 1
assert result[0].exit_code == 1
Expand All @@ -163,8 +160,8 @@ def test_mixed_sources(self) -> None:

def test_multiple_targets(self) -> None:
targets = [
self.make_target_with_origin([self.good_source], name="t1"),
self.make_target_with_origin([self.bad_source], name="t2"),
self.make_target([self.good_source], name="t1"),
self.make_target([self.bad_source], name="t2"),
]
result = self.run_mypy(targets)
assert len(result) == 1
Expand All @@ -174,21 +171,21 @@ def test_multiple_targets(self) -> None:
assert "checked 2 source files" in result[0].stdout

def test_respects_config_file(self) -> None:
target = self.make_target_with_origin([self.needs_config_source])
target = self.make_target([self.needs_config_source])
result = self.run_mypy([target], config="[mypy]\ndisallow_any_expr = True\n")
assert len(result) == 1
assert result[0].exit_code == 1
assert f"{self.package}/needs_config.py:4" in result[0].stdout

def test_respects_passthrough_args(self) -> None:
target = self.make_target_with_origin([self.needs_config_source])
target = self.make_target([self.needs_config_source])
result = self.run_mypy([target], passthrough_args="--disallow-any-expr")
assert len(result) == 1
assert result[0].exit_code == 1
assert f"{self.package}/needs_config.py:4" in result[0].stdout

def test_skip(self) -> None:
target = self.make_target_with_origin([self.bad_source])
target = self.make_target([self.bad_source])
result = self.run_mypy([target], skip=True)
assert not result

Expand Down Expand Up @@ -235,7 +232,7 @@ def add(x: int, y: int) -> str:
),
FileContent(f"{self.package}/__init__.py", b""),
]
target = self.make_target_with_origin(sources_content)
target = self.make_target(sources_content)
result = self.run_mypy([target])
assert len(result) == 1
assert result[0].exit_code == 1
Expand Down
10 changes: 5 additions & 5 deletions src/python/pants/core/goals/typecheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from pants.engine.goal import Goal, GoalSubsystem
from pants.engine.process import FallibleProcessResult
from pants.engine.rules import Get, MultiGet, collect_rules, goal_rule
from pants.engine.target import TargetsWithOrigins
from pants.engine.target import Targets
from pants.engine.unions import UnionMembership, union
from pants.util.logging import LogLevel
from pants.util.memo import memoized_property
Expand Down Expand Up @@ -129,14 +129,14 @@ class Typecheck(Goal):

@goal_rule
async def typecheck(
console: Console, targets_with_origins: TargetsWithOrigins, union_membership: UnionMembership
console: Console, targets: Targets, union_membership: UnionMembership
) -> Typecheck:
typecheck_request_types = union_membership[TypecheckRequest]
requests: Iterable[StyleRequest] = tuple(
lint_request_type(
lint_request_type.field_set_type.create(target_with_origin)
for target_with_origin in targets_with_origins
if lint_request_type.field_set_type.is_valid(target_with_origin.target)
lint_request_type.field_set_type.create(target)
for target in targets
if lint_request_type.field_set_type.is_valid(target)
)
for lint_request_type in typecheck_request_types
)
Expand Down
33 changes: 9 additions & 24 deletions src/python/pants/core/goals/typecheck_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from textwrap import dedent
from typing import ClassVar, Iterable, List, Optional, Tuple, Type

from pants.base.specs import AddressLiteralSpec
from pants.core.goals.typecheck import (
Typecheck,
TypecheckRequest,
Expand All @@ -18,13 +17,7 @@
FieldSetsWithSourcesRequest,
)
from pants.engine.addresses import Address
from pants.engine.target import (
FieldSetWithOrigin,
Sources,
Target,
TargetsWithOrigins,
TargetWithOrigin,
)
from pants.engine.target import FieldSet, Sources, Target, Targets
from pants.engine.unions import UnionMembership
from pants.testutil.engine.util import MockConsole, MockGet, run_rule
from pants.testutil.test_base import TestBase
Expand All @@ -36,7 +29,7 @@ class MockTarget(Target):
core_fields = (Sources,)


class MockTypecheckFieldSet(FieldSetWithOrigin):
class MockTypecheckFieldSet(FieldSet):
required_fields = (Sources,)


Expand Down Expand Up @@ -113,26 +106,23 @@ def exit_code(_: Iterable[Address]) -> int:

class TypecheckTest(TestBase):
@staticmethod
def make_target_with_origin(address: Optional[Address] = None) -> TargetWithOrigin:
def make_target(address: Optional[Address] = None) -> Target:
if address is None:
address = Address.parse(":tests")
return TargetWithOrigin(
MockTarget({}, address=address),
origin=AddressLiteralSpec(address.spec_path, address.target_name),
)
return MockTarget({}, address=address)

@staticmethod
def run_typecheck_rule(
*,
request_types: List[Type[TypecheckRequest]],
targets: List[TargetWithOrigin],
targets: List[Target],
include_sources: bool = True,
) -> Tuple[int, str]:
console = MockConsole(use_colors=False)
union_membership = UnionMembership({TypecheckRequest: request_types})
result: Typecheck = run_rule(
typecheck,
rule_args=[console, TargetsWithOrigins(targets), union_membership],
rule_args=[console, Targets(targets), union_membership],
mock_gets=[
MockGet(
product_type=TypecheckResults,
Expand All @@ -154,16 +144,14 @@ def run_typecheck_rule(

def test_empty_target_noops(self) -> None:
exit_code, stderr = self.run_typecheck_rule(
request_types=[FailingRequest],
targets=[self.make_target_with_origin()],
include_sources=False,
request_types=[FailingRequest], targets=[self.make_target()], include_sources=False,
)
assert exit_code == 0
assert stderr == ""

def test_invalid_target_noops(self) -> None:
exit_code, stderr = self.run_typecheck_rule(
request_types=[InvalidRequest], targets=[self.make_target_with_origin()]
request_types=[InvalidRequest], targets=[self.make_target()]
)
assert exit_code == 0
assert stderr == ""
Expand All @@ -178,10 +166,7 @@ def test_summary(self) -> None:
SkippedRequest,
SuccessfulRequest,
],
targets=[
self.make_target_with_origin(good_address),
self.make_target_with_origin(bad_address),
],
targets=[self.make_target(good_address), self.make_target(bad_address),],
)
assert exit_code == FailingRequest.exit_code([bad_address])
assert stderr == dedent(
Expand Down

0 comments on commit 76bfcfb

Please sign in to comment.