@suss/adapter-python 0.11.0 → 0.13.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/README.md +15 -1
- package/dist/index.cjs +5 -1
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +5 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ The Python language adapter for suss. It parses source with tree-sitter (WASM),
|
|
|
6
6
|
|
|
7
7
|
`@suss/adapter-python` is the Python language adapter. It meets the Layer 1 contract in [`docs/internal/facts-and-rules.md`](../../../docs/internal/facts-and-rules.md): discover units, emit summaries in the shared IR, emit facts. It parses a file with `web-tree-sitter` and a vendored Python grammar (`grammar/tree-sitter-python.wasm`, so there is no native build step), builds module, class and function scopes over the tree (imports, assignments, `global`/`nonlocal`), works out which file in the repo an import points at, and finds routes on decorated functions and class methods whose decorator resolves to a module the pack was configured with. When a pack says the library mounts routers (FastAPI's `APIRouter` plus `include_router`), the adapter builds a route's path out of the two literal prefixes, one mount hop deep. When it cannot build the path, the route keeps its name, gets no path, and gets a gap explaining why. Each unit it finds becomes a `RawCodeStructure` object, which it hands to `assembleSummary` in `@suss/extractor`, the same assembly code the TypeScript adapter uses.
|
|
8
8
|
|
|
9
|
-
v0 (this slice) does nothing with the path engine. A route either has no transitions at all, or one transition that describes the response the code declares (a FastAPI `response_model` / `status_code`, or a return annotation). It never breaks a route into branches. See [`
|
|
9
|
+
v0 (this slice) does nothing with the path engine. A route either has no transitions at all, or one transition that describes the response the code declares (a FastAPI `response_model` / `status_code`, or a return annotation). It never breaks a route into branches. See [`design/proposals/language-adapters.md`](../../../design/proposals/language-adapters.md) for what a later slice adds.
|
|
10
10
|
|
|
11
11
|
## Where it fits in suss
|
|
12
12
|
|
|
@@ -81,6 +81,20 @@ FastAPI has no column here: its app has no prefix of its own, and the pack decla
|
|
|
81
81
|
| `""`, `None`, `False`, `0` | the blueprint's prefix + the rest | unstated |
|
|
82
82
|
| a name or a call | whatever it evaluates to | unreadable |
|
|
83
83
|
|
|
84
|
+
### A call that spreads a dictionary
|
|
85
|
+
|
|
86
|
+
`Api(**build_authorizations())` and `include_router(router, **options)`
|
|
87
|
+
spread a value the call does not write out. The reader skips the spread
|
|
88
|
+
and reads the keywords that are written, so the routes underneath keep
|
|
89
|
+
their paths.
|
|
90
|
+
|
|
91
|
+
That leaves one thing it cannot see. If the dictionary sets the prefix
|
|
92
|
+
keyword itself, the composed path is wrong, and nothing in the output
|
|
93
|
+
says so. Reading the prefix as unknown instead would be correct and would
|
|
94
|
+
cost every route under every call that spreads a config dictionary, which
|
|
95
|
+
is most of them. Propagating the uncertainty rather than choosing between
|
|
96
|
+
the two is the work that would settle this.
|
|
97
|
+
|
|
84
98
|
**At the registration** (`app.register_blueprint(bp, ...)`), which the reader consults only to abstain:
|
|
85
99
|
|
|
86
100
|
| Written | flask-restx serves | The reader says |
|
package/dist/index.cjs
CHANGED
|
@@ -622,6 +622,9 @@ function readCallArguments(argumentList) {
|
|
|
622
622
|
}
|
|
623
623
|
continue;
|
|
624
624
|
}
|
|
625
|
+
if (child.type === "dictionary_splat" || child.type === "list_splat") {
|
|
626
|
+
continue;
|
|
627
|
+
}
|
|
625
628
|
args.push(readArg(child));
|
|
626
629
|
}
|
|
627
630
|
return { args, keywordArgs };
|
|
@@ -19248,7 +19251,8 @@ function recordMountStatement(stmt, position, scan) {
|
|
|
19248
19251
|
scan.composition,
|
|
19249
19252
|
position.site
|
|
19250
19253
|
);
|
|
19251
|
-
|
|
19254
|
+
const mounted = args[0] ?? (scan.composition.routerKeyword === void 0 ? void 0 : keywordArgs[scan.composition.routerKeyword]);
|
|
19255
|
+
for (const target of mountedConstructions(mounted, position, scan)) {
|
|
19252
19256
|
recordMount(scan.index, target, state);
|
|
19253
19257
|
}
|
|
19254
19258
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -304,6 +304,12 @@ interface RouterComposition {
|
|
|
304
304
|
routerConstructorName: string;
|
|
305
305
|
/** Method that mounts a router onto the app, FastAPI's `include_router`. */
|
|
306
306
|
includeMethodName: string;
|
|
307
|
+
/**
|
|
308
|
+
* What the mount method calls its router parameter, FastAPI's `router`.
|
|
309
|
+
* A call that passes the router by keyword rather than by position is
|
|
310
|
+
* read through this. Unset reads the first argument only.
|
|
311
|
+
*/
|
|
312
|
+
routerKeyword?: string;
|
|
307
313
|
/** One keyword serves the constructor and the mount alike. A library that spells them apart needs two fields here. */
|
|
308
314
|
prefixKeyword: string;
|
|
309
315
|
/** Default "prefixes". */
|
package/dist/index.d.ts
CHANGED
|
@@ -304,6 +304,12 @@ interface RouterComposition {
|
|
|
304
304
|
routerConstructorName: string;
|
|
305
305
|
/** Method that mounts a router onto the app, FastAPI's `include_router`. */
|
|
306
306
|
includeMethodName: string;
|
|
307
|
+
/**
|
|
308
|
+
* What the mount method calls its router parameter, FastAPI's `router`.
|
|
309
|
+
* A call that passes the router by keyword rather than by position is
|
|
310
|
+
* read through this. Unset reads the first argument only.
|
|
311
|
+
*/
|
|
312
|
+
routerKeyword?: string;
|
|
307
313
|
/** One keyword serves the constructor and the mount alike. A library that spells them apart needs two fields here. */
|
|
308
314
|
prefixKeyword: string;
|
|
309
315
|
/** Default "prefixes". */
|
package/dist/index.js
CHANGED
|
@@ -568,6 +568,9 @@ function readCallArguments(argumentList) {
|
|
|
568
568
|
}
|
|
569
569
|
continue;
|
|
570
570
|
}
|
|
571
|
+
if (child.type === "dictionary_splat" || child.type === "list_splat") {
|
|
572
|
+
continue;
|
|
573
|
+
}
|
|
571
574
|
args.push(readArg(child));
|
|
572
575
|
}
|
|
573
576
|
return { args, keywordArgs };
|
|
@@ -19204,7 +19207,8 @@ function recordMountStatement(stmt, position, scan) {
|
|
|
19204
19207
|
scan.composition,
|
|
19205
19208
|
position.site
|
|
19206
19209
|
);
|
|
19207
|
-
|
|
19210
|
+
const mounted = args[0] ?? (scan.composition.routerKeyword === void 0 ? void 0 : keywordArgs[scan.composition.routerKeyword]);
|
|
19211
|
+
for (const target of mountedConstructions(mounted, position, scan)) {
|
|
19208
19212
|
recordMount(scan.index, target, state);
|
|
19209
19213
|
}
|
|
19210
19214
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suss/adapter-python",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Python language adapter for suss — parses source with tree-sitter (WASM), resolves names with a lexical binder, and emits raw extractions for the suss pipeline.",
|
|
6
6
|
"keywords": [
|
|
@@ -47,10 +47,10 @@
|
|
|
47
47
|
"typecheck": "tsc --noEmit"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@suss/behavioral-ir": "0.
|
|
51
|
-
"@suss/datalog": "0.
|
|
52
|
-
"@suss/extractor": "0.
|
|
53
|
-
"@suss/sql": "0.
|
|
50
|
+
"@suss/behavioral-ir": "0.13.0",
|
|
51
|
+
"@suss/datalog": "0.13.0",
|
|
52
|
+
"@suss/extractor": "0.13.0",
|
|
53
|
+
"@suss/sql": "0.13.0",
|
|
54
54
|
"web-tree-sitter": "^0.26.11"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|