Skip to content
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

Improve errors for invalid Get objects #10593

Merged
merged 1 commit into from Aug 12, 2020

Conversation

Eric-Arellano
Copy link
Contributor

There are two times an invalid Get can trigger errors: a) when parsing the AST in rules.py, or b) when Python creates the actual Get object, i.e. calling Get.__init__(). Typically, the former happens first, which was resulting in very confusing error messages, like this for the invalid line await Get(str, AddressInput.parse("")):

▶ ./pants
'Attribute' object has no attribute 'id'

After

Invalid # of args:

Invalid Get. Expected either two or three arguments, but got 4 arguments. Failed for Get(Address, AddressInput, AddressInput.parse(), <class '_ast.Num'>) in /Users/eric/DocsLocal/code/projects/pants/src/python/pants/engine/internals/graph.py.

Invalid product:

Invalid Get. The first argument should be the type of the product, like Digest or ProcessResult. Failed for Get(Address(), AddressInput, AddressInput.parse()) in /Users/eric/DocsLocal/code/projects/pants/src/python/pants/engine/internals/graph.py.

Invalid subject:

Invalid Get. Because you are using the longhand form Get(ProductType, SubjectType, subject_instance), the second argument should be a type, like MergeDigests or Process. Failed for Get(Address, AddressInput(), AddressInput.parse()) in /Users/eric/DocsLocal/code/projects/pants/src/python/pants/engine/internals/graph.py.

Invalid Get. Because you are using the shorthand form Get(ProductType, SubjectType(constructor args), the second argument should be a constructor call, like MergeDigest(...) or Process(...). Failed for Get(Address, AddressInput) in /Users/eric/DocsLocal/code/projects/pants/src/python/pants/engine/internals/graph.py.

Invalid Get. Because you are using the shorthand form Get(ProductType, SubjectType(constructor args), the second argument should be a top-level constructor function call, like MergeDigest(...) or Process(...), rather than a method call. Failed for Get(Address, AddressInput.parse()) in /Users/eric/DocsLocal/code/projects/pants/src/python/pants/engine/internals/graph.py.

[ci skip-rust]
[ci skip-build-wheels]

# 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]
return f"{expr.func.value.id}.{expr.func.attr}()" # type: ignore[attr-defined]

# Fall back to the name of the ast node's class.
return str(type(expr))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original code used type(expr).__name__, but I think this made the error confusing because we would output Str rather than <class '_ast.Str'>.

def test_parse_get_types_wrong_number_args() -> None:
assert_parse_get_types_fails(
"Get()",
expected_explanation="Expected either two or three arguments, but got 0 arguments.",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is brittle to be doing exact string matches. But because we're trying to improve the quality of our error messages, I think this fragility is justified so that we are confident the error message is rendering exactly how we'd like.

@@ -153,19 +155,19 @@ def test_valid_get_unresolvable_subject_declared_type(self) -> None:
self._parse_rule_gets("Get(int, DNE, 'bob')")

def test_invalid_get_no_subject_args(self) -> None:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests duplicate selectors_test.py now. I didn't delete them though because these are small and I'm thinking they act like ~integration tests, i.e. that everything is wired up correctly.

@Eric-Arellano
Copy link
Contributor Author

Ran the tests with Py36, 37, and 38 to ensure that these new tests pass. (The AST changes between versions)

@coveralls
Copy link

Coverage Status

Coverage remained the same at 0.0% when pulling 3611d5e on Eric-Arellano:invalid-get into b10cca1 on pantsbuild:master.

Copy link
Sponsor Contributor

@benjyw benjyw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neat!

@Eric-Arellano Eric-Arellano merged commit 26e5007 into pantsbuild:master Aug 12, 2020
@Eric-Arellano Eric-Arellano deleted the invalid-get branch August 12, 2020 16:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants