@descryy/adapter-python 0.3.3 → 0.4.0

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@descryy/adapter-python",
3
- "version": "0.3.3",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "description": "Python adapter. Parses with Python's own ast in one subprocess (DEC-062) — no grammar to keep in sync, and annotations arrive as source text.",
6
6
  "license": "UNLICENSED",
@@ -36,8 +36,8 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "@descryy/adapter-common": "0.2.0",
39
- "@descryy/ir": "0.6.3",
40
- "@descryy/adapter-openapi": "0.3.3",
41
- "@descryy/adapter-sql": "0.3.3"
39
+ "@descryy/ir": "0.7.0",
40
+ "@descryy/adapter-openapi": "0.4.0",
41
+ "@descryy/adapter-sql": "0.4.0"
42
42
  }
43
43
  }
package/src/extract.py CHANGED
@@ -443,6 +443,10 @@ class Collector(ast.NodeVisitor):
443
443
  "module": alias.name,
444
444
  "name": None,
445
445
  "local": alias.asname or alias.name.split(".")[0],
446
+ # `import a.b.c` binds `a`; `import a.b.c as a` binds
447
+ # `a.b.c`. Nothing in resolution can tell those apart from
448
+ # `local` and `module`, and the dependency boundary has to.
449
+ "asname": alias.asname,
446
450
  "line": node.lineno,
447
451
  }
448
452
  )
@@ -460,6 +464,7 @@ class Collector(ast.NodeVisitor):
460
464
  "module": node.module,
461
465
  "name": alias.name,
462
466
  "local": alias.asname or alias.name,
467
+ "asname": alias.asname,
463
468
  "line": node.lineno,
464
469
  }
465
470
  )
@@ -1295,6 +1300,43 @@ def _alembic_revision(tree: ast.Module) -> dict | None:
1295
1300
  return {"revision": revision, "downRevision": down_revision}
1296
1301
 
1297
1302
 
1303
+ def _assigned_names(tree: ast.AST) -> list[str]:
1304
+ """Every name this file binds itself, anywhere in it.
1305
+
1306
+ The dependency boundary needs this and nothing else does: an import can be
1307
+ shadowed (`import json` then `json = load_config()`), and an import table
1308
+ cannot see the shadow. A name in here makes the Node side decline to
1309
+ attribute a call through it -- see `external.ts`.
1310
+
1311
+ **File-level rather than scope-precise, deliberately.** A blunter set
1312
+ refuses MORE sites, and rule 2 prices a wrong attribution far above a
1313
+ missing one. Measured cost of the bluntness: 2 attributions of 4,838 on
1314
+ dispatch, 1 of 4,543 on plane.
1315
+
1316
+ Import statements are not included -- they are the table this guards, not a
1317
+ shadow of it.
1318
+ """
1319
+ names: set[str] = set()
1320
+ for node in ast.walk(tree):
1321
+ if isinstance(node, ast.Name) and isinstance(node.ctx, ast.Store):
1322
+ # Assignment, `for`, `with ... as`, a walrus, a comprehension
1323
+ # target, an augmented or annotated assignment -- all one case.
1324
+ names.add(node.id)
1325
+ elif isinstance(node, ast.arg):
1326
+ names.add(node.arg)
1327
+ elif isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef)):
1328
+ names.add(node.name)
1329
+ elif isinstance(node, ast.ExceptHandler) and node.name:
1330
+ names.add(node.name)
1331
+ elif isinstance(node, ast.MatchAs) and node.name:
1332
+ names.add(node.name)
1333
+ elif isinstance(node, ast.MatchStar) and node.name:
1334
+ names.add(node.name)
1335
+ elif isinstance(node, ast.MatchMapping) and node.rest:
1336
+ names.add(node.rest)
1337
+ return sorted(names)
1338
+
1339
+
1298
1340
  def collect(path: str, source: str, deep_call_modules: frozenset[str] = frozenset()) -> dict:
1299
1341
  tree = ast.parse(source, filename=path)
1300
1342
  collector = Collector(path)
@@ -1347,6 +1389,7 @@ def collect(path: str, source: str, deep_call_modules: frozenset[str] = frozense
1347
1389
  )
1348
1390
 
1349
1391
  env_reads, env_dynamic_reads = _env_reads(tree, collector.imports)
1392
+
1350
1393
  migration_ops = _migration_ops(tree, collector.imports)
1351
1394
  migration_revision = _alembic_revision(tree)
1352
1395
 
@@ -1366,6 +1409,7 @@ def collect(path: str, source: str, deep_call_modules: frozenset[str] = frozense
1366
1409
  "envDynamicReads": env_dynamic_reads,
1367
1410
  "migrationOps": migration_ops,
1368
1411
  "migrationRevision": migration_revision,
1412
+ "assignedNames": _assigned_names(tree),
1369
1413
  }
1370
1414
 
1371
1415