Skip to content

fix(Y062): report duplicates inside nested Literals - #556

Open
Cherith1222 wants to merge 2 commits into
PyCQA:mainfrom
Cherith1222:fix/485-y062-nested-literal
Open

Cherith1222 wants to merge 2 commits into
PyCQA:mainfrom
Cherith1222:fix/485-y062-nested-literal

Conversation

@Cherith1222

Copy link
Copy Markdown

Why

Y062 compares the direct members of one Literal slice. A nested Literal counts as a single member, so Literal[1, Literal[2, 1]] does not report the repeated 1. The check now unwraps nested Literal slices before it looks for duplicates. See #485.

What changed

  • Y062 flattens nested Literal values, including typing.Literal.
  • The outer slice reports each duplicated value once.
  • A Literal nested inside another type, such as Annotated, still checks itself.

Scope

This covers duplicate values inside nested Literal slices. It does not add a new error for a nested Literal that has no duplicate, such as Literal[1, Literal[2, 3]].

Tradeoffs

A nested Literal with no repeated value could also be rewritten as one flat slice. This change only reports duplicates, which is what Y062 already does for a flat slice.

Blast Radius

Stub files that repeat a value inside a nested Literal now get Y062. Slices that were already flat stay the same.

Verification

  • Before the change, flake8 was silent on Literal[1, Literal[2, 1]], and it reported Literal[Literal[1], Literal[1]] as a duplicate Literal[1].
  • After the change, both cases report Y062 for the value 1. Literal[1, Literal[2, 3]] stays quiet.
  • uv run --python 3.13 --group=dev pytest -q reported 37 passed.
  • mypy in strict mode reported no issues in 5 source files.
  • flake8 on flake8_pyi and tests/test_pyi_files.py produced no findings.

Drafted with Cursor.

Literal[1, Literal[2, 1]] is silent. Two identical nested Literals are reported as a duplicate subscript rather than a duplicate value.
PEP 586 flattens a nested Literal, so duplicate detection has to unwrap those slices. The outer slice reports each duplicated value once.
@github-actions

Copy link
Copy Markdown

This change has no effect on typeshed. 🤖🎉

@srittau srittau left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks, one nit below.

Comment thread ERRORCODES.md
| <a id="Y060" href="#Y060">Y060</a> | Redundant inheritance from `Generic[]`. For example, `class Foo(Iterable[_T], Generic[_T]): ...` can be written more simply as `class Foo(Iterable[_T]): ...`.<br><br>To avoid false-positive errors, and to avoid complexity in the implementation, this check is deliberately conservative: it only flags classes where all subscripted bases have identical code inside their subscript slices. | Style
| <a id="Y061" href="#Y061">Y061</a> | Do not use `None` inside a `Literal[]` slice. For example, use `Literal["foo"] \| None` instead of `Literal["foo", None]`. While both are legal according to [PEP 586](https://peps.python.org/pep-0586/), the former is preferred for stylistic consistency. Note that this warning is not emitted if Y062 is emitted for the same `Literal[]` slice. For example, `Literal[None, None, True, True]` only causes Y062 to be emitted. | Style
| <a id="Y062" href="#Y062">Y062</a> | `Literal[]` slices shouldn't contain duplicates, e.g. `Literal[True, True]` is not allowed. | Redundant code
| <a id="Y062" href="#Y062">Y062</a> | `Literal[]` slices shouldn't contain duplicates, e.g. `Literal[True, True]` is not allowed. Nested `Literal` slices are flattened first, so `Literal[1, Literal[2, 1]]` is checked as `Literal[1, 2, 1]`. | Redundant code

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Let's keep this text user-focused. Maybe just "Literal[] slices shouldn't contain duplicates, e.g. Literal[True, True] or Literal[True, Literal[True]] is not allowed."

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.

2 participants