-
-
Notifications
You must be signed in to change notification settings - Fork 643
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Error out if the user explicitly tries to test a non-test tgt. #8402
Conversation
50ab4cf
to
f27519c
Compare
Awesome! I'll more closely review tomorrow. Question in the meantime: do we care about parity with V1 behavior? V1 will still no-op, whereas V2 will have a nice error. I think this is fine—and I'm not sure where we'd even start to change this in V1—but worth discussing. |
# TODO(#6004): when streaming to live TTY, rely on V2 UI for this information. When not a | ||
# live TTY, periodically dump heavy hitters to stderr. See | ||
# https://github.com/pantsbuild/pants/issues/6004#issuecomment-492699898. | ||
if union_membership.is_member(TestTarget, target.adaptor): | ||
if (provenance_map.is_single_address(target.address) or |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neat!
I can't find the tickets that discuss this, but: one approach that would be parallel to how we implement "glob" validation would be to require that each Spec has at least one match. So even a glob like ./pants test ${dir}::
would fail if there were no tests in the directory.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I'm not convinced that specs should be required to match at least one "relevant" target. I'm not convinced of the converse either. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool!
Yeah, I don't think parity is expected or required... |
Previously we would apply the union filter to all targets. So `./pants test path/to:non-test-target` would noop. Now we only apply the filter to targets that originated in a glob spec, such as path/to/targets::. If the user tries to run tests on a non-test target via a single address spec then we don't apply the filter, and instead fail on attempting to cast the non-test target to the TestTarget union (which yields a sensible error message). This gives us the best of both worlds: We can give a sensible error, instead of nooping, when the user specifies a single target, but treat globs in the expected way. This required introducing the concept of the "provenance" of a BuildFileAddress. That is, the Spec it originated from. The term "source" is overloaded in this context, so we use "provenance" instead.
4fdfeaa
to
a1f8f66
Compare
Ping, now that this is green :) |
key, value = entry | ||
return key | ||
key, value = entry | ||
return key | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately, this file seems to have been formatted with black
=(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Skipping review of this because the diff is unclear to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm I'm not sure what happened here, I thought I'd reverted my attempts to apply black. Will fix it up.
_specificity = { | ||
SingleAddress: 0, | ||
SiblingAddresses: 1, | ||
AscendantAddresses: 2, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible for an end-user to type an ascendant address through the CLI, or is this only used in internal code? I'm wondering if this should even belong here.
Also, what is the reasoning for an ascendant address being more specific than a descendant address? I'm not able to give a good technical reason for this, but a descendant address "feels" more specific intuitively to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really know what ascendant addresses are for. I just know that they're there, so I had to do something with them. To me they are less specific because they span multiple levels, whereas siblings are all in the same dir.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it fail if we remove them from the dictionary? I suppose we should regardless have it as a matter of defensive programming.
Agreed that ascendant is less specific than sibling. I mean that ascendant also seems less specific than descendent. I would order it:
single > sibling > descendant > ascendant
src/python/pants/base/specs.py
Outdated
} | ||
|
||
|
||
def more_specific(spec1, spec2): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Type hints appreciated if you know them. I think this would be:
def more_specific(spec1, spec2): | |
def more_specific(spec1: Spec, spec2: Spec) -> bool: |
) | ||
|
||
|
||
def test_more_specific(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for using the Pytest assert
strategy rather than subclassing unittest
key, value = entry | ||
return key | ||
key, value = entry | ||
return key | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Skipping review of this because the diff is unclear to me.
# TODO(#6004): when streaming to live TTY, rely on V2 UI for this information. When not a | ||
# live TTY, periodically dump heavy hitters to stderr. See | ||
# https://github.com/pantsbuild/pants/issues/6004#issuecomment-492699898. | ||
if union_membership.is_member(TestTarget, target.adaptor): | ||
if (provenance_map.is_single_address(target.address) or |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool!
bfaddr = BuildFileAddress(None, 'bin', 'some/dir') | ||
target_adaptor = PythonBinaryAdaptor(type_alias='python_binary') | ||
with self.captured_logging(logging.INFO): | ||
# Note that this is not the same error message the end user will see, as we're resolving |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd be interested in an integration test which actually shows that the error we should the user is a good one...
In general I worry that testing @console_rules
as unit tests is kind of hard to reason about, and would maybe be interested in an integration test for the globbed case too, but in this one particularly I don't love that we're asserting that an unhelpful error is shown, and commenting to say that the user won't see such a bad error...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I don't love this either. But I'm pretty against integration tests for very specific bits of functionality. They have incredibly high overhead and we should be using them much more sparingly than we do. In so many cases they exist because some underlying functionality is too hard to test in isolation.
I'd prefer that we figure out a way to have run_rule apply the same union casting logic as in prod, and get the right error message that way.
Previously we would apply the union filter to all targets.
So
./pants test path/to:non-test-target
would noop.Now we only apply the filter to targets that originated in a glob spec,
such as path/to/targets::. If the user tries to run tests on
a non-test target via a single address spec then we don't apply
the filter, and instead fail on attempting to cast the non-test
target to the TestTarget union (which yields a sensible error message).
This gives us the best of both worlds: We can give a sensible error,
instead of nooping, when the user specifies a single target, but
treat globs in the expected way.
This required introducing the concept of the "provenance" of a
BuildFileAddress. That is, the Spec it originated from. The term
"source" is overloaded in this context, so we use "provenance"
instead.