@descryy/adapter-python 0.1.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.
@@ -0,0 +1,231 @@
1
+ /**
2
+ * Parsed Python to Canonical IR.
3
+ *
4
+ * The Python side reports what one file says; everything that needs two files
5
+ * happens here, where the resolution level is tracked and can be claimed
6
+ * honestly.
7
+ *
8
+ * ## Name binding, which is the whole of R2 for this adapter
9
+ *
10
+ * There is no type checker (DEC-062). A name is resolved by building, per file,
11
+ * the set of module-level bindings that Python itself would build:
12
+ *
13
+ * 1. imports — `from .money import format_money` binds `format_money`;
14
+ * 2. module-level declarations — a `def` or `class` in this file;
15
+ * 3. module-level instantiations — `service = OrderService()`, the one
16
+ * inference made anywhere in this adapter.
17
+ *
18
+ * Anything else resolves to nothing and is disclosed. `self.repo.save()`,
19
+ * `getattr(obj, name)()`, a name rebound in a loop — all absent, all recorded.
20
+ * That is the recall cost of having no checker, and it is stated rather than
21
+ * covered with a guess.
22
+ *
23
+ * ## The re-export hop
24
+ *
25
+ * `from . import validate_order` reaches `src/__init__.py`, which is not where
26
+ * `validate_order` is defined. Golden pattern 03 requires the edge to terminate
27
+ * at the definition and explicitly forbids it terminating at the package — the
28
+ * single most common symbol-resolution bug, and the one the TypeScript adapter
29
+ * hit three separate times. `followReexport` walks the hop, with a visited set
30
+ * because `a/__init__.py` importing from `b/__init__.py` importing back is legal
31
+ * Python and must not hang the run.
32
+ */
33
+ import { type IREdge, type IRNode, type ResolutionLevel, type UnresolvedRef } from "@descryy/ir";
34
+ import { type ImportRecord } from "./module.ts";
35
+ import { type PyAttribute } from "./orm.ts";
36
+ import { type PytestConfig } from "./pytest-config.ts";
37
+ export declare const LANGUAGE = "python";
38
+ interface PyRange {
39
+ readonly startLine: number;
40
+ readonly endLine: number;
41
+ }
42
+ interface PyDeclaration {
43
+ readonly kind: "class" | "function";
44
+ readonly path: readonly string[];
45
+ readonly name: string;
46
+ readonly range: PyRange;
47
+ readonly returns?: string | null;
48
+ readonly params?: readonly {
49
+ name: string;
50
+ annotation: string | null;
51
+ }[];
52
+ readonly bases?: readonly (string | null)[];
53
+ readonly fields?: readonly {
54
+ name: string;
55
+ annotation: string | null;
56
+ hasDefault: boolean;
57
+ }[];
58
+ /** Every assignment in the class body. Optional so a pre-DEC-093 recording still parses. */
59
+ readonly attributes?: readonly PyAttribute[];
60
+ readonly decorators?: readonly (string | null)[];
61
+ /** Decorators that are calls, structured. Optional so a pre-DEC-099 recording still parses. */
62
+ readonly decoratorCalls?: readonly PyCall[];
63
+ }
64
+ /**
65
+ * One call as `extract.py` recorded it — receiver, attribute, arguments.
66
+ *
67
+ * `literals` and `argNames` are parallel to `args` and are the whole point: a
68
+ * path written as a string and a path computed at runtime must stay
69
+ * distinguishable here, because a route emitted for the second joins a caller
70
+ * to an endpoint that does not exist, and no layer above the graph can tell
71
+ * that from a correct edge.
72
+ */
73
+ /** `app = flask.Flask(__name__)` — the target, the callee as written, the line. */
74
+ export interface PyConstruction {
75
+ readonly local: string;
76
+ readonly callee: string | null;
77
+ readonly scope: readonly string[];
78
+ readonly line: number;
79
+ }
80
+ export interface PyCall {
81
+ readonly callee: string | null;
82
+ readonly receiver: string | null;
83
+ readonly attribute: string | null;
84
+ readonly args: readonly string[];
85
+ readonly literals: readonly (string | number | boolean | null)[];
86
+ readonly argNames: readonly (string | null)[];
87
+ /** One level of nesting: `path("api/", include("app.urls"))`. */
88
+ readonly argCalls: readonly (PyCall | null)[];
89
+ readonly hasLiterals: readonly boolean[];
90
+ readonly keywords: Readonly<Record<string, unknown>>;
91
+ readonly keywordNames: Readonly<Record<string, string>>;
92
+ /** Every keyword's value as source text, bare name or not. */
93
+ readonly keywordText: Readonly<Record<string, string>>;
94
+ /** Keyword arguments written as a list or tuple of constants: `methods=["GET"]`. */
95
+ readonly keywordLists: Readonly<Record<string, readonly unknown[]>>;
96
+ readonly opaqueKeywords: readonly string[];
97
+ /** The scope the call is evaluated in — `[]` at module level. */
98
+ readonly scope: readonly string[];
99
+ readonly line: number;
100
+ }
101
+ interface PyReference {
102
+ readonly kind: "call" | "method" | "attribute" | "attribute_write" | "annotation";
103
+ readonly name: string | null;
104
+ readonly receiver: string | null;
105
+ readonly scope: readonly string[];
106
+ readonly line: number;
107
+ }
108
+ interface PyInstantiation {
109
+ readonly local: string;
110
+ readonly typeName: string;
111
+ readonly scope: readonly string[];
112
+ readonly line: number;
113
+ }
114
+ /**
115
+ * A module-level type alias (DEC-069), already classified on the Python side —
116
+ * `rule` records *which* admission rule accepted it, so a surprising node can be
117
+ * traced to the rule that produced it rather than re-derived.
118
+ */
119
+ interface PyAlias {
120
+ readonly name: string;
121
+ readonly range: PyRange;
122
+ readonly rule: string;
123
+ readonly constituents: readonly string[];
124
+ }
125
+ /**
126
+ * A class referenced as a *value* — DEC-072.
127
+ *
128
+ * `form` is the syntactic position, kept so a form admitted on measurement can
129
+ * be withdrawn on measurement. Every one was counted on real code before it was
130
+ * included; two of them, `except` and `match`, were invisible until the AST was
131
+ * walked and would never have made an intuition-written list.
132
+ */
133
+ interface PyValueRef {
134
+ readonly name: string;
135
+ readonly form: string;
136
+ readonly scope: readonly string[];
137
+ readonly line: number;
138
+ }
139
+ interface PyFile {
140
+ readonly declarations: readonly PyDeclaration[];
141
+ readonly imports: readonly ImportRecord[];
142
+ readonly references: readonly PyReference[];
143
+ readonly instantiations: readonly PyInstantiation[];
144
+ readonly valueRefs: readonly PyValueRef[];
145
+ /** Optional so a recording made before DEC-069 still parses. */
146
+ readonly aliases?: readonly PyAlias[];
147
+ /** Module-scope calls with their arguments. Optional so a pre-DEC-099 recording still parses. */
148
+ readonly calls?: readonly PyCall[];
149
+ /** `name = Call(...)`, dotted callees included. Optional for the same reason. */
150
+ readonly constructions?: readonly PyConstruction[];
151
+ /** Module-scope `NAME = "literal"`. Optional so an older recording still parses. */
152
+ readonly constants?: readonly PyConstant[];
153
+ /** `url = f"{BASE}/x"` inside a function. Optional for the same reason. */
154
+ readonly localStrings?: readonly PyLocalString[];
155
+ /** `attrs.envReads` (DEC-120/121/124). Optional for the same reason. */
156
+ readonly envReads?: readonly PyEnvRead[];
157
+ /** Reads with a non-literal key — counted, never named (DEC-121). */
158
+ readonly envDynamicReads?: number;
159
+ /** `attrs.migrationOps` (DEC-122/124). Optional for the same reason. */
160
+ readonly migrationOps?: readonly PyMigrationOp[];
161
+ }
162
+ /** One name this module reads from the environment, and whether it must be set. */
163
+ interface PyEnvRead {
164
+ readonly name: string;
165
+ readonly required: boolean;
166
+ readonly line: number;
167
+ }
168
+ /** One destructive Alembic operation — the exact shape `readMigrationOps` expects. */
169
+ interface PyMigrationOp {
170
+ readonly kind: "DROP_TABLE" | "DROP_COLUMN" | "DROP_SCHEMA" | "TRUNCATE" | "RENAME";
171
+ readonly target: string;
172
+ readonly line: number;
173
+ readonly section: "forward" | "reverse" | "unknown";
174
+ readonly guarded: boolean;
175
+ }
176
+ interface PyConstant {
177
+ readonly name: string;
178
+ readonly value: string;
179
+ readonly line: number;
180
+ }
181
+ interface PyLocalString {
182
+ readonly name: string;
183
+ /** Source text, not a template — every path rule lives on this side. */
184
+ readonly value: string;
185
+ readonly scope: readonly string[];
186
+ readonly line: number;
187
+ }
188
+ export interface PyResult {
189
+ readonly pythonVersion: string;
190
+ readonly files: Readonly<Record<string, PyFile>>;
191
+ readonly errors: Readonly<Record<string, string>>;
192
+ }
193
+ export interface ExtractInput {
194
+ readonly repo: string;
195
+ readonly workspace: string | undefined;
196
+ readonly producedBy: string;
197
+ readonly reached: ResolutionLevel;
198
+ readonly packageName: string;
199
+ readonly parsed: PyResult;
200
+ /** The repository's own collection rules. Omitted means pytest's defaults. */
201
+ readonly pytest?: PytestConfig;
202
+ }
203
+ export interface Extraction {
204
+ readonly nodes: readonly IRNode[];
205
+ readonly edges: readonly IREdge[];
206
+ readonly unresolved: readonly UnresolvedRef[];
207
+ }
208
+ /**
209
+ * The graph to return when the parse produced nothing but the files are there.
210
+ *
211
+ * **A failed analysis must not look like an empty repository.** The two were
212
+ * indistinguishable, and home-assistant-core and posthog each came back with 0
213
+ * nodes over ~18,000 files and a successful R0 status.
214
+ *
215
+ * A `MODULE` per file is honest at R0 and needs no parse: the file exists and
216
+ * its module path is a fact about the filesystem. It also gives the disclosure
217
+ * a real node to hang from — the ledger requires a valid `fromNodeId`, and the
218
+ * first attempt at this invented one and was rightly rejected by the Normaliser
219
+ * as `MALFORMED_UNRESOLVED_REF`, which would have thrown away the very warning
220
+ * it was carrying.
221
+ *
222
+ * The result reads as what it is: every module present, every module empty, and
223
+ * one row saying loudly why.
224
+ */
225
+ export declare function degradedGraph(input: Omit<ExtractInput, "parsed"> & {
226
+ readonly files: readonly string[];
227
+ readonly cause: string;
228
+ }): Extraction;
229
+ export declare function extract(input: ExtractInput): Extraction;
230
+ export {};
231
+ //# sourceMappingURL=extract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,EAUL,KAAK,MAAM,EACX,KAAK,MAAM,EAGX,KAAK,eAAe,EACpB,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AAErB,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EAOL,KAAK,WAAW,EACjB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAiC,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAwCtF,eAAO,MAAM,QAAQ,WAAW,CAAC;AA6GjC,UAAU,OAAO;IACf,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,UAAU,aAAa;IACrB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,UAAU,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,EAAE,CAAC;IACzE,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IAC5C,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,UAAU,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;IAC9F,4FAA4F;IAC5F,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;IAC7C,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IACjD,+FAA+F;IAC/F,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7C;AAED;;;;;;;;GAQG;AACH,mFAAmF;AACnF,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC;IACjE,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IAC9C,iEAAiE;IACjE,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IAC9C,QAAQ,CAAC,WAAW,EAAE,SAAS,OAAO,EAAE,CAAC;IACzC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACrD,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACxD,8DAA8D;IAC9D,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACvD,oFAAoF;IACpF,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,CAAC,CAAC,CAAC;IACpE,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,WAAW;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,iBAAiB,GAAG,YAAY,CAAC;IAClF,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,eAAe;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;;;GAIG;AACH,UAAU,OAAO;IACf,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1C;AAED;;;;;;;GAOG;AACH,UAAU,UAAU;IAClB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,MAAM;IACd,QAAQ,CAAC,YAAY,EAAE,SAAS,aAAa,EAAE,CAAC;IAChD,QAAQ,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IAC1C,QAAQ,CAAC,UAAU,EAAE,SAAS,WAAW,EAAE,CAAC;IAC5C,QAAQ,CAAC,cAAc,EAAE,SAAS,eAAe,EAAE,CAAC;IACpD,QAAQ,CAAC,SAAS,EAAE,SAAS,UAAU,EAAE,CAAC;IAC1C,gEAAgE;IAChE,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;IACtC,iGAAiG;IACjG,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,iFAAiF;IACjF,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IACnD,oFAAoF;IACpF,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IAC3C,2EAA2E;IAC3E,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;IACjD,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IACzC,qEAAqE;IACrE,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,wEAAwE;IACxE,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;CAClD;AAED,mFAAmF;AACnF,UAAU,SAAS;IACjB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,sFAAsF;AACtF,UAAU,aAAa;IACrB,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,aAAa,GAAG,aAAa,GAAG,UAAU,GAAG,QAAQ,CAAC;IACpF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IACpD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED,UAAU,UAAU;IAClB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,aAAa;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACjD,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;CAChC;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,UAAU,EAAE,SAAS,aAAa,EAAE,CAAC;CAC/C;AAoKD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAClG,UAAU,CAuCZ;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,UAAU,CA6jEvD"}