File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -5432,17 +5432,6 @@ def visit_dict_expr(self, e: DictExpr) -> Type:
54325432 expected_types : list [Type ] = []
54335433 for key , value in e .items :
54345434 if key is None :
5435- # This is a **expr unpacking.
5436- # If this DictExpr came from a dict() call, we need to check that
5437- # the expression has string keys (since dict() uses keyword args).
5438- # For plain dict literals like {**mapping}, non-string keys are valid.
5439- if e .from_dict_call :
5440- value_type = get_proper_type (self .accept (value ))
5441- if not self .is_valid_keyword_var_arg (value_type ):
5442- is_mapping = is_subtype (
5443- value_type , self .chk .named_type ("_typeshed.SupportsKeysAndGetItem" )
5444- )
5445- self .msg .invalid_keyword_var_arg (value_type , is_mapping , value )
54465435 args .append (value )
54475436 expected_types .append (
54485437 self .chk .named_generic_type ("_typeshed.SupportsKeysAndGetItem" , [kt , vt ])
Original file line number Diff line number Diff line change @@ -2672,22 +2672,15 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
26722672class DictExpr (Expression ):
26732673 """Dictionary literal expression {key: value, ...}."""
26742674
2675- __slots__ = ("items" , "from_dict_call" )
2675+ __slots__ = ("items" ,)
26762676
26772677 __match_args__ = ("items" ,)
26782678
26792679 items : list [tuple [Expression | None , Expression ]]
2680- # True if this DictExpr was created from a dict() call (e.g., dict(a=1, **x))
2681- from_dict_call : bool
26822680
2683- def __init__ (
2684- self ,
2685- items : list [tuple [Expression | None , Expression ]],
2686- from_dict_call : bool = False ,
2687- ) -> None :
2681+ def __init__ (self , items : list [tuple [Expression | None , Expression ]]) -> None :
26882682 super ().__init__ ()
26892683 self .items = items
2690- self .from_dict_call = from_dict_call
26912684
26922685 def accept (self , visitor : ExpressionVisitor [T ]) -> T :
26932686 return visitor .visit_dict_expr (self )
Original file line number Diff line number Diff line change @@ -6051,12 +6051,23 @@ def translate_dict_call(self, call: CallExpr) -> DictExpr | None:
60516051 for a in call .args :
60526052 a .accept (self )
60536053 return None
6054+ # Check if any **kwargs argument is a dict literal with non-string keys.
6055+ # In that case, don't translate so that normal function call type checking
6056+ # will catch the "keywords must be strings" error.
6057+ for kind , arg in zip (call .arg_kinds , call .args ):
6058+ if kind == ARG_STAR2 and isinstance (arg , DictExpr ):
6059+ # Check if all keys in the dict literal are strings
6060+ for key , _ in arg .items :
6061+ if key is not None and not isinstance (key , (StrExpr , BytesExpr )):
6062+ # Non-string key found, don't translate
6063+ for a in call .args :
6064+ a .accept (self )
6065+ return None
60546066 expr = DictExpr (
60556067 [
60566068 (StrExpr (key ) if key is not None else None , value )
60576069 for key , value in zip (call .arg_names , call .args )
6058- ],
6059- from_dict_call = True ,
6070+ ]
60606071 )
60616072 expr .set_line (call )
60626073 expr .accept (self )
You can’t perform that action at this time.
0 commit comments