364364# string literal as a type expression.
365365_MULTIPLE_WORDS_NONTYPE_RE = re .compile (r'\s*[^\s.\'"|\[]+\s+[^\s.\'"|\[]' )
366366
367- # Matches any valid Python identifier, including identifiers with Unicode characters.
368- #
369- # [^\d\W] = word character that is not a digit
370- # \w = word character
371- # \Z = match end of string; does not allow a trailing \n, unlike $
372- _IDENTIFIER_RE = re .compile (r"^[^\d\W]\w*\Z" , re .UNICODE )
373-
374367
375368class SemanticAnalyzer (
376369 NodeVisitor [None ], SemanticAnalyzerInterface , SemanticAnalyzerPluginInterface , SplittingVisitor
@@ -8043,16 +8036,9 @@ def try_parse_as_type_expression(self, maybe_type_expr: Expression) -> None:
80438036 return
80448037 elif isinstance (maybe_type_expr , StrExpr ):
80458038 str_value = maybe_type_expr .value # cache
8046- # Filter out string literals with common patterns that could not
8047- # possibly be in a type expression
8048- if _MULTIPLE_WORDS_NONTYPE_RE .match (str_value ):
8049- # A common pattern in string literals containing a sentence.
8050- # But cannot be a type expression.
8051- maybe_type_expr .as_type = None
8052- return
80538039 # Filter out string literals which look like an identifier but
80548040 # cannot be a type expression, for a few common reasons
8055- if _IDENTIFIER_RE . fullmatch ( str_value ):
8041+ if str_value . isidentifier ( ):
80568042 sym = self .lookup (str_value , UnboundType (str_value ), suppress_errors = True )
80578043 if sym is None :
80588044 # Does not refer to anything in the local symbol table
@@ -8078,13 +8064,21 @@ def try_parse_as_type_expression(self, maybe_type_expr: Expression) -> None:
80788064 return
80798065 else : # does not look like an identifier
80808066 if '"' in str_value or "'" in str_value :
8081- # Only valid inside a Literal[...] type
8067+ # Only valid inside a Literal[...] or Annotated[..., ...] type
80828068 if "[" not in str_value :
8083- # Cannot be a Literal[...] type
8069+ # Cannot be a Literal[...] or Annotated[..., ...] type
80848070 maybe_type_expr .as_type = None
80858071 return
8086- elif str_value == "" :
8087- # Empty string is not a valid type
8072+ elif len (str_value ) < 2 or str_value .isspace ():
8073+ # Whitespace-only strings cannot be valid types. Very short strings can
8074+ # only be valid if they are identifiers, but we already checked for those.
8075+ maybe_type_expr .as_type = None
8076+ return
8077+ # Filter out string literals with common patterns that could not
8078+ # possibly be in a type expression
8079+ if _MULTIPLE_WORDS_NONTYPE_RE .match (str_value ):
8080+ # A common pattern in string literals containing a sentence.
8081+ # But cannot be a type expression.
80888082 maybe_type_expr .as_type = None
80898083 return
80908084 elif isinstance (maybe_type_expr , IndexExpr ):
0 commit comments