MCPcopy Index your code
hub / github.com/python/mypy / process_module_assignment

Method process_module_assignment

mypy/semanal.py:5261–5331  ·  view source on GitHub ↗

Propagate module references across assignments. Recursively handles the simple form of iterable unpacking; doesn't handle advanced unpacking with *rest, dictionary unpacking, etc. In an expression like x = y = z, z is the rval and lvals will be [x, y].

(
        self, lvals: list[Lvalue], rval: Expression, ctx: AssignmentStmt
    )

Source from the content-addressed store, hash-verified

5259 self.fail(message_registry.CLASS_VAR_OUTSIDE_OF_CLASS, context)
5260
5261 def process_module_assignment(
5262 self, lvals: list[Lvalue], rval: Expression, ctx: AssignmentStmt
5263 ) -> None:
5264 """Propagate module references across assignments.
5265
5266 Recursively handles the simple form of iterable unpacking; doesn't
5267 handle advanced unpacking with *rest, dictionary unpacking, etc.
5268
5269 In an expression like x = y = z, z is the rval and lvals will be [x,
5270 y].
5271
5272 """
5273 if isinstance(rval, (TupleExpr, ListExpr)) and all(
5274 isinstance(v, TupleExpr) for v in lvals
5275 ):
5276 # rval and all lvals are either list or tuple, so we are dealing
5277 # with unpacking assignment like `x, y = a, b`. Mypy didn't
5278 # understand our all(isinstance(...)), so cast them as TupleExpr
5279 # so mypy knows it is safe to access their .items attribute.
5280 seq_lvals = cast(list[TupleExpr], lvals)
5281 # given an assignment like:
5282 # (x, y) = (m, n) = (a, b)
5283 # we now have:
5284 # seq_lvals = [(x, y), (m, n)]
5285 # seq_rval = (a, b)
5286 # We now zip this into:
5287 # elementwise_assignments = [(a, x, m), (b, y, n)]
5288 # where each elementwise assignment includes one element of rval and the
5289 # corresponding element of each lval. Basically we unpack
5290 # (x, y) = (m, n) = (a, b)
5291 # into elementwise assignments
5292 # x = m = a
5293 # y = n = b
5294 # and then we recursively call this method for each of those assignments.
5295 # If the rval and all lvals are not all of the same length, zip will just ignore
5296 # extra elements, so no error will be raised here; mypy will later complain
5297 # about the length mismatch in type-checking.
5298 elementwise_assignments = zip(rval.items, *[v.items for v in seq_lvals])
5299 for rv, *lvs in elementwise_assignments:
5300 self.process_module_assignment(lvs, rv, ctx)
5301 elif isinstance(rval, RefExpr):
5302 rnode = self.lookup_type_node(rval)
5303 if rnode and isinstance(rnode.node, MypyFile):
5304 for lval in lvals:
5305 if not isinstance(lval, RefExpr):
5306 continue
5307 # respect explicitly annotated type
5308 if isinstance(lval.node, Var) and lval.node.type is not None:
5309 continue
5310
5311 # We can handle these assignments to locals and to self
5312 if isinstance(lval, NameExpr):
5313 lnode = self.current_symbol_table().get(lval.name)
5314 elif isinstance(lval, MemberExpr) and self.is_self_member_ref(lval):
5315 assert self.type is not None
5316 lnode = self.type.names.get(lval.name)
5317 else:
5318 continue

Callers 1

visit_assignment_stmtMethod · 0.95

Calls 9

lookup_type_nodeMethod · 0.95
current_symbol_tableMethod · 0.95
is_self_member_refMethod · 0.95
failMethod · 0.95
isinstanceFunction · 0.85
allFunction · 0.85
zipFunction · 0.85
getMethod · 0.45
formatMethod · 0.45

Tested by

no test coverage detected