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

Reject more syntactically invalid Python programs #8524

Merged
merged 3 commits into from
Nov 7, 2023
Merged

Conversation

BurntSushi
Copy link
Member

@BurntSushi BurntSushi commented Nov 6, 2023

Summary

This commit adds some additional error checking to the parser such that assignments that are invalid syntax are rejected. This covers the obvious cases like 5 = 3 and some not so obvious cases like x + y = 42.

This does add an additional recursive call to the parser for the cases handling assignments. I had initially been concerned about doing this, but set_context is already doing recursion during assignments, so I didn't feel as though this was changing any fundamental performance characteristics of the parser. (Also, in practice, I would expect any such recursion here to be quite shallow since the recursion is done on the target of an assignment. Such things are rarely nested much in practice.)

Fixes #6895

Test Plan

I've added unit tests covering every case that is detected as invalid on an Expr.

Copy link
Member

@charliermarsh charliermarsh left a comment

Choose a reason for hiding this comment

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

This is excellent! Welcome to the repo :)

crates/ruff_python_parser/src/invalid.rs Outdated Show resolved Hide resolved
crates/ruff_python_parser/src/invalid.rs Outdated Show resolved Hide resolved
crates/ruff_python_parser/src/invalid.rs Outdated Show resolved Hide resolved
crates/ruff_python_parser/src/invalid.rs Show resolved Hide resolved
@charliermarsh charliermarsh added the bug Something isn't working label Nov 6, 2023
This commit adds some additional error checking to the parser such
that assignments that are invalid syntax are rejected. This covers the
obvious cases like `5 = 3` and some not so obvious cases like `x + y =
42`.

This does add an additional recursive call to the parser for the cases
handling assignments. I had initially been concerned about doing this,
but `set_context` is already doing recursion during assignments, so I
didn't feel as though this was changing any fundamental performance
characteristics of the parser. (Also, in practice, I would expect any
such recursion here to be quite shallow since the recursion is done
on the target of an assignment. Such things are rarely nested much in
practice.)

Fixes #6895
This test previously asserted that, e.g., `a = 1, b = 2`, was valid
Python code. But it turns out that it is not:

    >>> a = 1, b = 2
      File "<input>", line 1
        a = 1, b = 2
        ^^^^^
    SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?

This commit flips the particular assert to check that no Python code is
detected within the comment.
With the parser becoming a bit more strict, it discovered some invalid
syntax in one of the formatter tests. In particular, `yield a = 1`:

    >>> (yield a, b) = (1, 2)
      File "<input>", line 1
        (yield a, b) = (1, 2)
         ^^^^^^^^^^
    SyntaxError: cannot assign to yield expression here. Maybe you meant '==' instead of '='?

We just remove that bit from the `yield` test.
Copy link
Member

@charliermarsh charliermarsh left a comment

Choose a reason for hiding this comment

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

Nice work.

@BurntSushi
Copy link
Member Author

@charliermarsh Can you check out the two commits I've just pushed? In particular, the stricter parser caused two tests to fail. I think my changes to those tests are correct, but I'd like to be cautious here!

@charliermarsh
Copy link
Member

Taking a closer look at those changes...

@charliermarsh
Copy link
Member

@BurntSushi - Those both look correct to me. I actually don't fully understand why app_label=\"core\", model=\"user\"", was previously marked as valid code, what was the "target" and the "value"?

@BurntSushi
Copy link
Member Author

was previously marked as valid code, what was the "target" and the "value"?

For x="a", y="b", it looks like it parsed as two targets, x and ("a", y) with a single value of b. It's not totally clear to me how it gets that particular parse. That first equals sign, I'd imagine, would inhibit picking up the second target.

@charliermarsh
Copy link
Member

Ahh ok, so it's like x = ("a", y) = "b". Makes sense-ish.

Copy link
Contributor

github-actions bot commented Nov 6, 2023

ruff-ecosystem results

Linter (stable)

ℹ️ ecosystem check detected linter changes. (+0 -27 violations, +0 -0 fixes in 41 projects)

apache/airflow (+0 -8 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --select ALL

- airflow/config_templates/default_webserver_config.py:84:1: ERA001 Found commented-out code
- airflow/example_dags/tutorial.py:63:9: ERA001 Found commented-out code
- airflow/serialization/serialized_objects.py:1195:13: ERA001 Found commented-out code
- airflow/serialization/serialized_objects.py:1211:13: ERA001 Found commented-out code
- airflow/settings.py:633:1: ERA001 Found commented-out code
- airflow/utils/log/secrets_masker.py:174:13: ERA001 Found commented-out code
- tests/system/providers/amazon/aws/example_eks_templated.py:45:1: ERA001 Found commented-out code
- tests/system/providers/amazon/aws/example_eks_templated.py:49:1: ERA001 Found commented-out code

bokeh/bokeh (+0 -6 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --select ALL

- examples/integration/layout/plot_fixed_frame_size.py:40:1: ERA001 Found commented-out code
- tests/integration/widgets/tables/test_source_updates.py:114:9: ERA001 Found commented-out code
- tests/integration/widgets/tables/test_source_updates.py:167:9: ERA001 Found commented-out code
- tests/integration/widgets/tables/test_source_updates.py:221:9: ERA001 Found commented-out code
- tests/integration/widgets/tables/test_source_updates.py:269:9: ERA001 Found commented-out code
- tests/unit/bokeh/plotting/test__renderer.py:125:1: ERA001 Found commented-out code

zulip/zulip (+0 -13 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --select ALL

- zerver/data_import/slack.py:581:13: ERA001 Found commented-out code
- zerver/lib/digest.py:89:1: ERA001 Found commented-out code
- zerver/lib/display_recipient.py:106:5: ERA001 Found commented-out code
- zerver/lib/email_notifications.py:309:5: ERA001 Found commented-out code
- zerver/lib/email_notifications.py:317:5: ERA001 Found commented-out code
- zerver/lib/email_notifications.py:321:5: ERA001 Found commented-out code
- zerver/middleware.py:152:13: ERA001 Found commented-out code
- zerver/middleware.py:175:13: ERA001 Found commented-out code
- zerver/tests/test_events.py:548:13: ERA001 Found commented-out code
- zerver/tests/test_events.py:550:13: ERA001 Found commented-out code
- zerver/tests/test_events.py:556:17: ERA001 Found commented-out code
- zerver/tests/test_events.py:727:9: ERA001 Found commented-out code
- zproject/prod_settings_template.py:264:1: ERA001 Found commented-out code

Changes by rule (1 rules affected)

code total + violation - violation + fix - fix
ERA001 27 0 27 0 0

Linter (preview)

ℹ️ ecosystem check detected linter changes. (+0 -25 violations, +0 -0 fixes in 41 projects)

apache/airflow (+0 -6 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --select ALL --preview

- airflow/config_templates/default_webserver_config.py:84:1: ERA001 Found commented-out code
- airflow/example_dags/tutorial.py:63:9: ERA001 Found commented-out code
- airflow/settings.py:633:1: ERA001 Found commented-out code
- airflow/utils/log/secrets_masker.py:174:13: ERA001 Found commented-out code
- tests/system/providers/amazon/aws/example_eks_templated.py:45:1: ERA001 Found commented-out code
- tests/system/providers/amazon/aws/example_eks_templated.py:49:1: ERA001 Found commented-out code

bokeh/bokeh (+0 -6 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --select ALL --preview

- examples/integration/layout/plot_fixed_frame_size.py:40:1: ERA001 Found commented-out code
- tests/integration/widgets/tables/test_source_updates.py:114:9: ERA001 Found commented-out code
- tests/integration/widgets/tables/test_source_updates.py:167:9: ERA001 Found commented-out code
- tests/integration/widgets/tables/test_source_updates.py:221:9: ERA001 Found commented-out code
- tests/integration/widgets/tables/test_source_updates.py:269:9: ERA001 Found commented-out code
- tests/unit/bokeh/plotting/test__renderer.py:125:1: ERA001 Found commented-out code

zulip/zulip (+0 -13 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --select ALL --preview

- zerver/data_import/slack.py:581:13: ERA001 Found commented-out code
- zerver/lib/digest.py:89:1: ERA001 Found commented-out code
- zerver/lib/display_recipient.py:106:5: ERA001 Found commented-out code
- zerver/lib/email_notifications.py:309:5: ERA001 Found commented-out code
- zerver/lib/email_notifications.py:317:5: ERA001 Found commented-out code
- zerver/lib/email_notifications.py:321:5: ERA001 Found commented-out code
- zerver/middleware.py:152:13: ERA001 Found commented-out code
- zerver/middleware.py:175:13: ERA001 Found commented-out code
- zerver/tests/test_events.py:548:13: ERA001 Found commented-out code
- zerver/tests/test_events.py:550:13: ERA001 Found commented-out code
- zerver/tests/test_events.py:556:17: ERA001 Found commented-out code
- zerver/tests/test_events.py:727:9: ERA001 Found commented-out code
- zproject/prod_settings_template.py:264:1: ERA001 Found commented-out code

Changes by rule (1 rules affected)

code total + violation - violation + fix - fix
ERA001 25 0 25 0 0

Formatter (stable)

✅ ecosystem check detected no format changes.

Formatter (preview)

✅ ecosystem check detected no format changes.

@charliermarsh
Copy link
Member

Those ecosystem changes look like strict improvements to me.

Copy link
Member

@zanieb zanieb left a comment

Choose a reason for hiding this comment

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

Nice :)

Copy link
Member

@dhruvmanila dhruvmanila left a comment

Choose a reason for hiding this comment

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

Thanks for writing such a thorough test suite! :)

@BurntSushi BurntSushi merged commit 6a1fa47 into main Nov 7, 2023
17 checks passed
@BurntSushi BurntSushi deleted the ag/fix-6895 branch November 7, 2023 12:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Ruff does not signal E999 SyntaxError on literal assignment.
4 participants