gabion 0.1.0__py3-none-any.whl → 0.1.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -68,6 +68,7 @@ class UseVisitor(ast.NodeVisitor):
68
68
  callee_name: Callable[[ast.Call], str],
69
69
  call_args_factory: Callable[..., CallArgs],
70
70
  call_context: Callable[[ast.AST, dict[ast.AST, ast.AST]], tuple[ast.Call | None, bool]],
71
+ return_aliases: dict[str, tuple[list[str], list[str]]] | None = None,
71
72
  ) -> None:
72
73
  # dataflow-bundle: alias_to_param, call_args, call_args_factory, call_context, callee_name, const_repr, is_test, parents, strictness, use_map
73
74
  self.parents = parents
@@ -80,6 +81,7 @@ class UseVisitor(ast.NodeVisitor):
80
81
  self.callee_name = callee_name
81
82
  self.call_args_factory = call_args_factory
82
83
  self.call_context = call_context
84
+ self.return_aliases = return_aliases or {}
83
85
  self._suspend_non_forward: set[str] = set()
84
86
  self._attr_alias_to_param: dict[tuple[str, str], str] = {}
85
87
  self._key_alias_to_param: dict[tuple[str, str], str] = {}
@@ -196,7 +198,76 @@ class UseVisitor(ast.NodeVisitor):
196
198
  return sources
197
199
  return set()
198
200
 
201
+ def _alias_from_call(self, call: ast.Call) -> list[str] | None:
202
+ if not self.return_aliases:
203
+ return None
204
+ callee = self.callee_name(call)
205
+ info = self.return_aliases.get(callee)
206
+ if info is None:
207
+ return None
208
+ params, aliases = info
209
+ if not aliases:
210
+ return None
211
+ mapping: dict[str, str | None] = {}
212
+ for idx, arg in enumerate(call.args):
213
+ if isinstance(arg, ast.Starred):
214
+ return None
215
+ if idx >= len(params):
216
+ return None
217
+ if isinstance(arg, ast.Name) and arg.id in self.alias_to_param:
218
+ mapping[params[idx]] = self.alias_to_param[arg.id]
219
+ else:
220
+ mapping[params[idx]] = None
221
+ for kw in call.keywords:
222
+ if kw.arg is None:
223
+ return None
224
+ if kw.arg not in params:
225
+ continue
226
+ if isinstance(kw.value, ast.Name) and kw.value.id in self.alias_to_param:
227
+ mapping[kw.arg] = self.alias_to_param[kw.value.id]
228
+ else:
229
+ mapping[kw.arg] = None
230
+ resolved: list[str] = []
231
+ for param in aliases:
232
+ mapped = mapping.get(param)
233
+ if not mapped:
234
+ return None
235
+ resolved.append(mapped)
236
+ return resolved
237
+
238
+ def _bind_return_alias(
239
+ self, targets: list[ast.AST], aliases: list[str]
240
+ ) -> bool:
241
+ if len(targets) != 1:
242
+ return False
243
+ target = targets[0]
244
+ if isinstance(target, ast.Name):
245
+ if len(aliases) != 1:
246
+ return False
247
+ param = aliases[0]
248
+ self.alias_to_param[target.id] = param
249
+ if param in self.use_map:
250
+ self.use_map[param].current_aliases.add(target.id)
251
+ return True
252
+ if isinstance(target, (ast.Tuple, ast.List)):
253
+ if len(target.elts) != len(aliases):
254
+ return False
255
+ if not all(isinstance(elt, ast.Name) for elt in target.elts):
256
+ return False
257
+ for elt, param in zip(target.elts, aliases):
258
+ if isinstance(elt, ast.Name):
259
+ self.alias_to_param[elt.id] = param
260
+ if param in self.use_map:
261
+ self.use_map[param].current_aliases.add(elt.id)
262
+ return True
263
+ return False
264
+
199
265
  def visit_Assign(self, node: ast.Assign) -> None:
266
+ if isinstance(node.value, ast.Call):
267
+ aliases = self._alias_from_call(node.value)
268
+ if aliases and self._bind_return_alias(node.targets, aliases):
269
+ self.visit(node.value)
270
+ return
200
271
  rhs_param = None
201
272
  if isinstance(node.value, ast.Name) and node.value.id in self.alias_to_param:
202
273
  rhs_param = self.alias_to_param[node.value.id]
@@ -238,6 +309,15 @@ class UseVisitor(ast.NodeVisitor):
238
309
  def visit_AnnAssign(self, node: ast.AnnAssign) -> None:
239
310
  if node.value is None:
240
311
  return
312
+ if isinstance(node.value, ast.Call) and isinstance(node.target, ast.Name):
313
+ aliases = self._alias_from_call(node.value)
314
+ if aliases and len(aliases) == 1:
315
+ param = aliases[0]
316
+ self.alias_to_param[node.target.id] = param
317
+ if param in self.use_map:
318
+ self.use_map[param].current_aliases.add(node.target.id)
319
+ self.visit(node.value)
320
+ return
241
321
  rhs_param = None
242
322
  if isinstance(node.value, ast.Name) and node.value.id in self.alias_to_param:
243
323
  rhs_param = self.alias_to_param[node.value.id]