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

Respect parent-scoping rules for NamedExpr assignments #4145

Merged
merged 2 commits into from
Apr 29, 2023

Conversation

charliermarsh
Copy link
Member

Summary

Per PEP 572, a named expression assignment within a generator or comprehension actually binds to the parent scope. This is useful as it enables patterns like:

# Compute partial sums in a list comprehension
total = 0
partial_sums = [total := total + v for v in values]
print("Total:", total)

Previously, we bound the named expression within the generator or comprehension, which led to us flagging key as undefined here:

if any((key := x) for x in ["ok"]):
    print(key)

Closes #3997.

@charliermarsh charliermarsh force-pushed the charlie/named-expr-in-comprehension branch from 4c1515a to 6dbb410 Compare April 28, 2023 23:11
@github-actions
Copy link
Contributor

github-actions bot commented Apr 28, 2023

PR Check Results

Ecosystem

✅ ecosystem check detected no changes.

Benchmark

Linux

group                                      main                                    pr
-----                                      ----                                    --
linter/all-rules/large/dataset.py          1.03     14.3±0.97ms     2.8 MB/sec     1.00     14.0±0.09ms     2.9 MB/sec
linter/all-rules/numpy/ctypeslib.py        1.00      3.4±0.01ms     5.0 MB/sec     1.00      3.3±0.01ms     5.0 MB/sec
linter/all-rules/numpy/globals.py          1.00    419.4±1.06µs     7.0 MB/sec     1.00    418.6±1.14µs     7.0 MB/sec
linter/all-rules/pydantic/types.py         1.00      5.8±0.01ms     4.4 MB/sec     1.00      5.8±0.02ms     4.4 MB/sec
linter/default-rules/large/dataset.py      1.00      6.9±0.01ms     5.9 MB/sec     1.00      6.9±0.03ms     5.9 MB/sec
linter/default-rules/numpy/ctypeslib.py    1.00   1478.9±2.42µs    11.3 MB/sec     1.00   1480.5±2.86µs    11.2 MB/sec
linter/default-rules/numpy/globals.py      1.01    166.8±0.35µs    17.7 MB/sec     1.00    166.0±0.21µs    17.8 MB/sec
linter/default-rules/pydantic/types.py     1.00      3.1±0.01ms     8.3 MB/sec     1.00      3.1±0.02ms     8.3 MB/sec
parser/large/dataset.py                    1.00      5.5±0.08ms     7.4 MB/sec     1.00      5.5±0.01ms     7.5 MB/sec
parser/numpy/ctypeslib.py                  1.15  1220.1±288.13µs    13.6 MB/sec    1.00   1065.2±2.45µs    15.6 MB/sec
parser/numpy/globals.py                    1.14   123.7±49.00µs    23.9 MB/sec     1.00    108.6±0.15µs    27.2 MB/sec
parser/pydantic/types.py                   1.15      2.7±0.72ms     9.6 MB/sec     1.00      2.3±0.04ms    11.0 MB/sec

Windows

group                                      main                                   pr
-----                                      ----                                   --
linter/all-rules/large/dataset.py          1.01     16.6±0.25ms     2.4 MB/sec    1.00     16.5±0.21ms     2.5 MB/sec
linter/all-rules/numpy/ctypeslib.py        1.00      4.2±0.06ms     4.0 MB/sec    1.00      4.1±0.06ms     4.0 MB/sec
linter/all-rules/numpy/globals.py          1.00   493.1±13.65µs     6.0 MB/sec    1.00   490.9±14.77µs     6.0 MB/sec
linter/all-rules/pydantic/types.py         1.00      7.0±0.09ms     3.7 MB/sec    1.00      6.9±0.08ms     3.7 MB/sec
linter/default-rules/large/dataset.py      1.01      8.4±0.09ms     4.9 MB/sec    1.00      8.3±0.08ms     4.9 MB/sec
linter/default-rules/numpy/ctypeslib.py    1.00  1777.5±18.24µs     9.4 MB/sec    1.00  1775.8±21.25µs     9.4 MB/sec
linter/default-rules/numpy/globals.py      1.00    198.9±5.61µs    14.8 MB/sec    1.00    198.3±4.32µs    14.9 MB/sec
linter/default-rules/pydantic/types.py     1.01      3.7±0.04ms     6.8 MB/sec    1.00      3.7±0.04ms     6.9 MB/sec
parser/large/dataset.py                    1.00      6.8±0.07ms     6.0 MB/sec    1.00      6.8±0.06ms     6.0 MB/sec
parser/numpy/ctypeslib.py                  1.00  1293.6±13.72µs    12.9 MB/sec    1.01  1301.9±18.06µs    12.8 MB/sec
parser/numpy/globals.py                    1.00    132.2±2.45µs    22.3 MB/sec    1.01    133.7±2.87µs    22.1 MB/sec
parser/pydantic/types.py                   1.00      2.9±0.04ms     8.8 MB/sec    1.00      2.9±0.03ms     8.8 MB/sec

.ancestor_scopes(self.ctx.scope_id)
.find(|scope| !scope.kind.is_generator())
.expect("Every scope must descend from the global scope.")
.id
Copy link
Member

Choose a reason for hiding this comment

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

Nit: The documentation mentions that the comprehension binds to the parent scope but the find binds to the first non generator scope. Can we either update the documentation or the code.

Could this crash if we support linting individual expressions?

let scope = self.ctx.scope();
// Per [PEP 572](https://peps.python.org/pep-0572/#scope-of-the-target), named
// expressions in generators and comprehensions bind to the parent scope.
let scope_id = if binding.kind.is_named_expr_assignment() {
Copy link
Member

Choose a reason for hiding this comment

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

Nit: Would it make sense to return the scope instead

Suggested change
let scope_id = if binding.kind.is_named_expr_assignment() {
let scope = if binding.kind.is_named_expr_assignment() {

It would avoid retrieving the id from the ancestor scope only to look it up again.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, it has to be mut though. I'll try to get it working.

@charliermarsh charliermarsh force-pushed the charlie/scopes branch 2 times, most recently from cbe31ef to 30b53b7 Compare April 29, 2023 22:12
Base automatically changed from charlie/scopes to main April 29, 2023 22:23
@charliermarsh charliermarsh force-pushed the charlie/named-expr-in-comprehension branch from 6dbb410 to d464e1e Compare April 29, 2023 22:24
@charliermarsh charliermarsh force-pushed the charlie/named-expr-in-comprehension branch from a5f1ff1 to 9935345 Compare April 29, 2023 22:39
@charliermarsh charliermarsh enabled auto-merge (squash) April 29, 2023 22:40
@charliermarsh charliermarsh merged commit 64b7280 into main Apr 29, 2023
12 checks passed
@charliermarsh charliermarsh deleted the charlie/named-expr-in-comprehension branch April 29, 2023 22:45
renovate bot added a commit to ixm-one/pytest-cmake-presets that referenced this pull request May 2, 2023
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [ruff](https://togithub.com/charliermarsh/ruff) | `^0.0.263` ->
`^0.0.264` |
[![age](https://badges.renovateapi.com/packages/pypi/ruff/0.0.264/age-slim)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://badges.renovateapi.com/packages/pypi/ruff/0.0.264/adoption-slim)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://badges.renovateapi.com/packages/pypi/ruff/0.0.264/compatibility-slim/0.0.263)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://badges.renovateapi.com/packages/pypi/ruff/0.0.264/confidence-slim/0.0.263)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>charliermarsh/ruff</summary>

###
[`v0.0.264`](https://togithub.com/charliermarsh/ruff/releases/tag/v0.0.264)

[Compare
Source](https://togithub.com/charliermarsh/ruff/compare/v0.0.263...v0.0.264)

<!-- Release notes generated using configuration in .github/release.yml
at 8cb76f85eba1c970a8c800348fd1e0c874621a57 -->

#### What's Changed

##### Rules

- Autofix `EM101`, `EM102`, `EM103` if possible by
[@&#8203;dhruvmanila](https://togithub.com/dhruvmanila) in
[astral-sh/ruff#4123
- Add bugbear immutable functions as allowed in dataclasses by
[@&#8203;mosauter](https://togithub.com/mosauter) in
[astral-sh/ruff#4122

##### Settings

- Add support for providing command-line arguments via `argfile` by
[@&#8203;charliermarsh](https://togithub.com/charliermarsh) in
[astral-sh/ruff#4087

##### Bug Fixes

- Make D410/D411 autofixes mutually exclusive by
[@&#8203;evanrittenhouse](https://togithub.com/evanrittenhouse) in
[astral-sh/ruff#4110
- Remove `pyright` comment prefix from PYI033 checks by
[@&#8203;evanrittenhouse](https://togithub.com/evanrittenhouse) in
[astral-sh/ruff#4152
- Fix F811 false positive with match by
[@&#8203;JonathanPlasse](https://togithub.com/JonathanPlasse) in
[astral-sh/ruff#4161
- Fix `E713` and `E714` false positives for multiple comparisons by
[@&#8203;JonathanPlasse](https://togithub.com/JonathanPlasse) in
[astral-sh/ruff#4083
- Fix B023 shadowed variables in nested functions by
[@&#8203;MichaReiser](https://togithub.com/MichaReiser) in
[astral-sh/ruff#4111
- Preserve star-handling special-casing for force-single-line by
[@&#8203;charliermarsh](https://togithub.com/charliermarsh) in
[astral-sh/ruff#4129
- Respect parent-scoping rules for `NamedExpr` assignments by
[@&#8203;charliermarsh](https://togithub.com/charliermarsh) in
[astral-sh/ruff#4145
- Fix UP032 auto-fix by
[@&#8203;JonathanPlasse](https://togithub.com/JonathanPlasse) in
[astral-sh/ruff#4165
- Allow boolean parameters for `pytest.param` by
[@&#8203;charliermarsh](https://togithub.com/charliermarsh) in
[astral-sh/ruff#4176

##### Internal

- Replace row/column based `Location` with byte-offsets. by
[@&#8203;MichaReiser](https://togithub.com/MichaReiser) in
[astral-sh/ruff#3931
- perf(logical-lines): Various small perf improvements by
[@&#8203;MichaReiser](https://togithub.com/MichaReiser) in
[astral-sh/ruff#4022
- Use `memchr` to speedup newline search on x86 by
[@&#8203;MichaReiser](https://togithub.com/MichaReiser) in
[astral-sh/ruff#3985
- Remove `ScopeStack` in favor of child-parent `ScopeId` pointers by
[@&#8203;charliermarsh](https://togithub.com/charliermarsh) in
[astral-sh/ruff#4138

**Full Changelog**:
astral-sh/ruff@v0.0.263...v0.0.264

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://app.renovatebot.com/dashboard#github/ixm-one/pytest-cmake-presets).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNS42Ni4zIiwidXBkYXRlZEluVmVyIjoiMzUuNjYuMyIsInRhcmdldEJyYW5jaCI6Im1haW4ifQ==-->

Signed-off-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
renovate bot added a commit to allenporter/flux-local that referenced this pull request May 3, 2023
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [ruff](https://togithub.com/charliermarsh/ruff) | `==0.0.263` ->
`==0.0.264` |
[![age](https://badges.renovateapi.com/packages/pypi/ruff/0.0.264/age-slim)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://badges.renovateapi.com/packages/pypi/ruff/0.0.264/adoption-slim)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://badges.renovateapi.com/packages/pypi/ruff/0.0.264/compatibility-slim/0.0.263)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://badges.renovateapi.com/packages/pypi/ruff/0.0.264/confidence-slim/0.0.263)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>charliermarsh/ruff</summary>

###
[`v0.0.264`](https://togithub.com/charliermarsh/ruff/releases/tag/v0.0.264)

[Compare
Source](https://togithub.com/charliermarsh/ruff/compare/v0.0.263...v0.0.264)

<!-- Release notes generated using configuration in .github/release.yml
at 8cb76f85eba1c970a8c800348fd1e0c874621a57 -->

#### What's Changed

##### Rules

- Autofix `EM101`, `EM102`, `EM103` if possible by
[@&#8203;dhruvmanila](https://togithub.com/dhruvmanila) in
[astral-sh/ruff#4123
- Add bugbear immutable functions as allowed in dataclasses by
[@&#8203;mosauter](https://togithub.com/mosauter) in
[astral-sh/ruff#4122

##### Settings

- Add support for providing command-line arguments via `argfile` by
[@&#8203;charliermarsh](https://togithub.com/charliermarsh) in
[astral-sh/ruff#4087

##### Bug Fixes

- Make D410/D411 autofixes mutually exclusive by
[@&#8203;evanrittenhouse](https://togithub.com/evanrittenhouse) in
[astral-sh/ruff#4110
- Remove `pyright` comment prefix from PYI033 checks by
[@&#8203;evanrittenhouse](https://togithub.com/evanrittenhouse) in
[astral-sh/ruff#4152
- Fix F811 false positive with match by
[@&#8203;JonathanPlasse](https://togithub.com/JonathanPlasse) in
[astral-sh/ruff#4161
- Fix `E713` and `E714` false positives for multiple comparisons by
[@&#8203;JonathanPlasse](https://togithub.com/JonathanPlasse) in
[astral-sh/ruff#4083
- Fix B023 shadowed variables in nested functions by
[@&#8203;MichaReiser](https://togithub.com/MichaReiser) in
[astral-sh/ruff#4111
- Preserve star-handling special-casing for force-single-line by
[@&#8203;charliermarsh](https://togithub.com/charliermarsh) in
[astral-sh/ruff#4129
- Respect parent-scoping rules for `NamedExpr` assignments by
[@&#8203;charliermarsh](https://togithub.com/charliermarsh) in
[astral-sh/ruff#4145
- Fix UP032 auto-fix by
[@&#8203;JonathanPlasse](https://togithub.com/JonathanPlasse) in
[astral-sh/ruff#4165
- Allow boolean parameters for `pytest.param` by
[@&#8203;charliermarsh](https://togithub.com/charliermarsh) in
[astral-sh/ruff#4176

##### Internal

- Replace row/column based `Location` with byte-offsets. by
[@&#8203;MichaReiser](https://togithub.com/MichaReiser) in
[astral-sh/ruff#3931
- perf(logical-lines): Various small perf improvements by
[@&#8203;MichaReiser](https://togithub.com/MichaReiser) in
[astral-sh/ruff#4022
- Use `memchr` to speedup newline search on x86 by
[@&#8203;MichaReiser](https://togithub.com/MichaReiser) in
[astral-sh/ruff#3985
- Remove `ScopeStack` in favor of child-parent `ScopeId` pointers by
[@&#8203;charliermarsh](https://togithub.com/charliermarsh) in
[astral-sh/ruff#4138

**Full Changelog**:
astral-sh/ruff@v0.0.263...v0.0.264

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://app.renovatebot.com/dashboard#github/allenporter/flux-local).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNS42OS4zIiwidXBkYXRlZEluVmVyIjoiMzUuNjkuMyIsInRhcmdldEJyYW5jaCI6Im1haW4ifQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
renovate bot added a commit to allenporter/pyrainbird that referenced this pull request May 3, 2023
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [ruff](https://togithub.com/charliermarsh/ruff) | `==0.0.263` ->
`==0.0.264` |
[![age](https://badges.renovateapi.com/packages/pypi/ruff/0.0.264/age-slim)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://badges.renovateapi.com/packages/pypi/ruff/0.0.264/adoption-slim)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://badges.renovateapi.com/packages/pypi/ruff/0.0.264/compatibility-slim/0.0.263)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://badges.renovateapi.com/packages/pypi/ruff/0.0.264/confidence-slim/0.0.263)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>charliermarsh/ruff</summary>

###
[`v0.0.264`](https://togithub.com/charliermarsh/ruff/releases/tag/v0.0.264)

[Compare
Source](https://togithub.com/charliermarsh/ruff/compare/v0.0.263...v0.0.264)

<!-- Release notes generated using configuration in .github/release.yml
at 8cb76f85eba1c970a8c800348fd1e0c874621a57 -->

#### What's Changed

##### Rules

- Autofix `EM101`, `EM102`, `EM103` if possible by
[@&#8203;dhruvmanila](https://togithub.com/dhruvmanila) in
[astral-sh/ruff#4123
- Add bugbear immutable functions as allowed in dataclasses by
[@&#8203;mosauter](https://togithub.com/mosauter) in
[astral-sh/ruff#4122

##### Settings

- Add support for providing command-line arguments via `argfile` by
[@&#8203;charliermarsh](https://togithub.com/charliermarsh) in
[astral-sh/ruff#4087

##### Bug Fixes

- Make D410/D411 autofixes mutually exclusive by
[@&#8203;evanrittenhouse](https://togithub.com/evanrittenhouse) in
[astral-sh/ruff#4110
- Remove `pyright` comment prefix from PYI033 checks by
[@&#8203;evanrittenhouse](https://togithub.com/evanrittenhouse) in
[astral-sh/ruff#4152
- Fix F811 false positive with match by
[@&#8203;JonathanPlasse](https://togithub.com/JonathanPlasse) in
[astral-sh/ruff#4161
- Fix `E713` and `E714` false positives for multiple comparisons by
[@&#8203;JonathanPlasse](https://togithub.com/JonathanPlasse) in
[astral-sh/ruff#4083
- Fix B023 shadowed variables in nested functions by
[@&#8203;MichaReiser](https://togithub.com/MichaReiser) in
[astral-sh/ruff#4111
- Preserve star-handling special-casing for force-single-line by
[@&#8203;charliermarsh](https://togithub.com/charliermarsh) in
[astral-sh/ruff#4129
- Respect parent-scoping rules for `NamedExpr` assignments by
[@&#8203;charliermarsh](https://togithub.com/charliermarsh) in
[astral-sh/ruff#4145
- Fix UP032 auto-fix by
[@&#8203;JonathanPlasse](https://togithub.com/JonathanPlasse) in
[astral-sh/ruff#4165
- Allow boolean parameters for `pytest.param` by
[@&#8203;charliermarsh](https://togithub.com/charliermarsh) in
[astral-sh/ruff#4176

##### Internal

- Replace row/column based `Location` with byte-offsets. by
[@&#8203;MichaReiser](https://togithub.com/MichaReiser) in
[astral-sh/ruff#3931
- perf(logical-lines): Various small perf improvements by
[@&#8203;MichaReiser](https://togithub.com/MichaReiser) in
[astral-sh/ruff#4022
- Use `memchr` to speedup newline search on x86 by
[@&#8203;MichaReiser](https://togithub.com/MichaReiser) in
[astral-sh/ruff#3985
- Remove `ScopeStack` in favor of child-parent `ScopeId` pointers by
[@&#8203;charliermarsh](https://togithub.com/charliermarsh) in
[astral-sh/ruff#4138

**Full Changelog**:
astral-sh/ruff@v0.0.263...v0.0.264

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://app.renovatebot.com/dashboard#github/allenporter/pyrainbird).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNS42OS4zIiwidXBkYXRlZEluVmVyIjoiMzUuNjkuMyIsInRhcmdldEJyYW5jaCI6Im1haW4ifQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
MichaReiser pushed a commit that referenced this pull request Jul 27, 2023
Since the upstream grammar for this is not LR(1), we abuse LALRPOP
macros and the Into/TryInto traits to build a cover grammar that
converts to either tuples or `with` items after additional validation.
It’s annoying and ugly, but something like this is basically our only
option short of switching to a more powerful parser algorithm.

Fixes #4145.

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
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.

Fails with assignment expression used in "any()" function
2 participants