@descryy/adapter-python 0.2.0 → 0.3.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/LICENSE +8 -0
- package/dist/adapter.d.ts +13 -20
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +91 -114
- package/dist/adapter.js.map +1 -1
- package/dist/client.d.ts +22 -41
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +35 -62
- package/dist/client.js.map +1 -1
- package/dist/extract.d.ts +16 -0
- package/dist/extract.d.ts.map +1 -1
- package/dist/extract.js +81 -5
- package/dist/extract.js.map +1 -1
- package/dist/extract.py +45 -4
- package/dist/graphql.d.ts +57 -123
- package/dist/graphql.d.ts.map +1 -1
- package/dist/graphql.js +62 -130
- package/dist/graphql.js.map +1 -1
- package/dist/module.d.ts +23 -42
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +26 -47
- package/dist/module.js.map +1 -1
- package/dist/orm.d.ts +31 -46
- package/dist/orm.d.ts.map +1 -1
- package/dist/orm.js +53 -89
- package/dist/orm.js.map +1 -1
- package/dist/pydantic.d.ts +76 -91
- package/dist/pydantic.d.ts.map +1 -1
- package/dist/pydantic.js +106 -99
- package/dist/pydantic.js.map +1 -1
- package/dist/routes.d.ts +46 -93
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +65 -129
- package/dist/routes.js.map +1 -1
- package/package.json +14 -5
- package/src/extract.py +45 -4
package/package.json
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@descryy/adapter-python",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Python adapter. Parses with Python's own ast in one subprocess (DEC-062) \u2014 no grammar to keep in sync, and annotations arrive as source text.",
|
|
6
6
|
"license": "UNLICENSED",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/descryhq-wq/descry-adapters.git",
|
|
10
|
+
"directory": "packages/adapter-python"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/descryhq-wq/descry-adapters/issues"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://github.com/descryhq-wq/descry-adapters#readme",
|
|
7
16
|
"engines": {
|
|
8
17
|
"node": ">=22.5"
|
|
9
18
|
},
|
|
@@ -26,9 +35,9 @@
|
|
|
26
35
|
"build:assets": "node -e \"require('fs').copyFileSync('src/extract.py','dist/extract.py')\""
|
|
27
36
|
},
|
|
28
37
|
"dependencies": {
|
|
29
|
-
"@descryy/adapter-common": "0.
|
|
30
|
-
"@descryy/ir": "0.
|
|
31
|
-
"@descryy/adapter-openapi": "0.
|
|
32
|
-
"@descryy/adapter-sql": "0.
|
|
38
|
+
"@descryy/adapter-common": "0.2.0",
|
|
39
|
+
"@descryy/ir": "0.5.0",
|
|
40
|
+
"@descryy/adapter-openapi": "0.3.0",
|
|
41
|
+
"@descryy/adapter-sql": "0.3.0"
|
|
33
42
|
}
|
|
34
43
|
}
|
package/src/extract.py
CHANGED
|
@@ -290,6 +290,17 @@ class Collector(ast.NodeVisitor):
|
|
|
290
290
|
# Module-level `name = ClassName()`, which is the only inference this
|
|
291
291
|
# file performs and the only one it can perform without a checker.
|
|
292
292
|
self.instantiations: list[dict] = []
|
|
293
|
+
# A local variable's *own* type annotation — `org: Organization | None
|
|
294
|
+
# = await get_org_for_user(...)` — as opposed to `instantiations`
|
|
295
|
+
# above, which only sees a bare constructor call on the right-hand
|
|
296
|
+
# side. The ground truth this exists for is exactly this shape: a
|
|
297
|
+
# local carrying its own annotation, assigned from a call whose
|
|
298
|
+
# return type nothing here resolves. Kept as the raw annotation
|
|
299
|
+
# string (not a single type name) so the Node side can run its own
|
|
300
|
+
# `typeNamesIn` + "exactly one candidate" discipline against
|
|
301
|
+
# `Optional[X]` / `X | None` / `Union[X, Y]`, the same as it already
|
|
302
|
+
# does for a parameter's own annotation.
|
|
303
|
+
self.local_annotations: list[dict] = []
|
|
293
304
|
# Module-level assignments that *might* be type aliases. Classified in
|
|
294
305
|
# `collect()` rather than here, because rule 4 asks where a constructor
|
|
295
306
|
# was imported from and the import table is only complete once the whole
|
|
@@ -682,6 +693,20 @@ class Collector(ast.NodeVisitor):
|
|
|
682
693
|
"line": node.lineno,
|
|
683
694
|
}
|
|
684
695
|
)
|
|
696
|
+
# A local variable's own annotation, inside a function (or
|
|
697
|
+
# nested closure) body — `org: Organization | None = await
|
|
698
|
+
# get_org_for_user(...)`. Module-level annotated assignments are
|
|
699
|
+
# already covered by `alias_candidates`/`_alembic_revision`; this
|
|
700
|
+
# is specifically the local-scope case those do not read.
|
|
701
|
+
if self._scope:
|
|
702
|
+
self.local_annotations.append(
|
|
703
|
+
{
|
|
704
|
+
"local": node.target.id,
|
|
705
|
+
"annotation": _annotation(node.annotation),
|
|
706
|
+
"scope": list(self._scope),
|
|
707
|
+
"line": node.lineno,
|
|
708
|
+
}
|
|
709
|
+
)
|
|
685
710
|
if not self._scope and node.value is not None:
|
|
686
711
|
self.alias_candidates.append(
|
|
687
712
|
{
|
|
@@ -1210,19 +1235,34 @@ def _alembic_revision(tree: ast.Module) -> dict | None:
|
|
|
1210
1235
|
down_revision: str | list[str] | None = None
|
|
1211
1236
|
|
|
1212
1237
|
for node in tree.body:
|
|
1213
|
-
|
|
1238
|
+
target: ast.AST | None
|
|
1239
|
+
value: ast.AST | None
|
|
1240
|
+
if isinstance(node, ast.Assign) and len(node.targets) == 1:
|
|
1241
|
+
target = node.targets[0]
|
|
1242
|
+
value = node.value
|
|
1243
|
+
elif isinstance(node, ast.AnnAssign):
|
|
1244
|
+
# `revision: str = "..."` — a type-annotated assignment. Alembic's
|
|
1245
|
+
# newer templates and mypy-strict repos write the pair this way;
|
|
1246
|
+
# it is semantically the same assignment, just with an annotation
|
|
1247
|
+
# attached. `node.value` is `None` for a bare annotation with no
|
|
1248
|
+
# value (`down_revision: str` alone) — that assigns nothing, so it
|
|
1249
|
+
# must not be treated as `down_revision = None` (a root migration
|
|
1250
|
+
# is a real, distinct fact). Skip the node entirely in that case.
|
|
1251
|
+
if node.value is None:
|
|
1252
|
+
continue
|
|
1253
|
+
target = node.target
|
|
1254
|
+
value = node.value
|
|
1255
|
+
else:
|
|
1214
1256
|
continue
|
|
1215
|
-
target = node.targets[0]
|
|
1216
1257
|
if not isinstance(target, ast.Name):
|
|
1217
1258
|
continue
|
|
1218
1259
|
|
|
1219
1260
|
if target.id == "revision":
|
|
1220
|
-
revision = string_of(
|
|
1261
|
+
revision = string_of(value)
|
|
1221
1262
|
continue
|
|
1222
1263
|
|
|
1223
1264
|
if target.id == "down_revision":
|
|
1224
1265
|
has_down_revision = True
|
|
1225
|
-
value = node.value
|
|
1226
1266
|
if isinstance(value, ast.Constant) and value.value is None:
|
|
1227
1267
|
down_revision = None
|
|
1228
1268
|
else:
|
|
@@ -1301,6 +1341,7 @@ def collect(path: str, source: str, deep_call_modules: frozenset[str] = frozense
|
|
|
1301
1341
|
"imports": collector.imports,
|
|
1302
1342
|
"references": collector.references,
|
|
1303
1343
|
"instantiations": collector.instantiations,
|
|
1344
|
+
"localAnnotations": collector.local_annotations,
|
|
1304
1345
|
"valueRefs": collector.value_refs,
|
|
1305
1346
|
"aliases": aliases,
|
|
1306
1347
|
"calls": collector.calls,
|