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

mypy interprets arguments which contains a pipe to Literal as type strings instead of literals #16367

Closed
InSyncWithFoo opened this issue Oct 29, 2023 · 1 comment · Fixed by #17148
Labels
bug mypy got something wrong topic-literal-types topic-pep-604 PEP 604 (union | operator)

Comments

@InSyncWithFoo
Copy link
Contributor

InSyncWithFoo commented Oct 29, 2023

Playground:

from typing import Literal


def f(v: Literal['foo', 'bar', 'foo|bar']) -> None:
    ...

Expected behavior:

f('foo')        # Pass
f('bar')        # Pass
f('foo|bar')    # Pass
f('baz')        # Fail
f('foo|')       # Fail
f('|qux')       # Fail
f('foo|qux')    # Fail

Actual behaviour:

def f(v: Literal['foo', 'bar', 'foo|bar']) -> None:  # error: Name "foo" is not defined  [name-defined]
  ...

Environment:

  • Mypy version used: 1.4/1.5/1.6/master branch.
  • Mypy command-line flags: None.
  • Mypy configuration options from mypy.ini (and other config files): None.
  • Python version used: 3.8/3.9/3.10/3.11/3.12.

This bug is found by StackOverflow user Håkon T. at this question.

It seems that mypy would try to interpret any string containing a pipe (|) as a type, and in this case it failed.

@henryiii
Copy link
Contributor

Same issue with Literal["uv", "pip", "uv|pip"] producing a name error on uv not being defined.

JelleZijlstra added a commit that referenced this issue Apr 22, 2024
Fixes #16367

During semantic analysis, we try to parse all strings as types,
including those inside Literal[]. Previously, we preserved the original
string in the `UnboundType.original_str_expr` attribute, but if a type
is parsed as a Union, we didn't have a place to put the value.

This PR instead always wraps string types in a RawExpressionType node,
which now optionally includes a `.node` attribute containing the parsed
type. This way, we don't need to worry about preserving the original
string as a custom attribute on different kinds of types that can appear
in this context.

The downside is that more code needs to be aware of RawExpressionType.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong topic-literal-types topic-pep-604 PEP 604 (union | operator)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants