@kernlang/python 3.5.6 → 3.5.7
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/dist/adapters/django.d.ts +49 -0
- package/dist/adapters/django.js +151 -0
- package/dist/adapters/django.js.map +1 -0
- package/dist/adapters/fastapi.d.ts +43 -0
- package/dist/adapters/fastapi.js +139 -0
- package/dist/adapters/fastapi.js.map +1 -0
- package/dist/codegen-body-python.d.ts +17 -5
- package/dist/codegen-body-python.js +83 -67
- package/dist/codegen-body-python.js.map +1 -1
- package/dist/core/expr/helpers.d.ts +5 -0
- package/dist/core/expr/helpers.js +62 -0
- package/dist/core/expr/helpers.js.map +1 -0
- package/dist/core/expr/index.d.ts +9 -0
- package/dist/core/expr/index.js +2046 -0
- package/dist/core/expr/index.js.map +1 -0
- package/dist/core/handlers/index.d.ts +74 -0
- package/dist/core/handlers/index.js +462 -0
- package/dist/core/handlers/index.js.map +1 -0
- package/dist/fastapi-portable.js +3 -2
- package/dist/fastapi-portable.js.map +1 -1
- package/dist/fastapi-response.d.ts +0 -6
- package/dist/fastapi-response.js +2 -2217
- package/dist/fastapi-response.js.map +1 -1
- package/dist/fastapi-route.js +24 -3
- package/dist/fastapi-route.js.map +1 -1
- package/dist/fastapi-utils.d.ts +2 -1
- package/dist/fastapi-utils.js +2 -58
- package/dist/fastapi-utils.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/ir-semantics/python-leg.js +5 -0
- package/dist/ir-semantics/python-leg.js.map +1 -1
- package/dist/targets/python.d.ts +27 -0
- package/dist/targets/python.js +130 -4
- package/dist/targets/python.js.map +1 -1
- package/package.json +2 -2
package/dist/targets/python.js
CHANGED
|
@@ -2,6 +2,102 @@ import { countTokens, serializeIR } from '@kernlang/core';
|
|
|
2
2
|
import { emitImports } from '../core/emit-imports.js';
|
|
3
3
|
import { emitModels } from '../core/emit-models.js';
|
|
4
4
|
import { collectFenceDiagnostics } from '../core/fence-diagnostics.js';
|
|
5
|
+
import { emitPureHandlers } from '../core/handlers/index.js';
|
|
6
|
+
import { findServerNode } from '../fastapi-utils.js';
|
|
7
|
+
/**
|
|
8
|
+
* The PyDotDict / _DotList shim, emitted at the top of every `--emit=backend`
|
|
9
|
+
* Python module that contains pure handlers. Re-exported so the conformance
|
|
10
|
+
* harness can import the SAME bytes instead of maintaining a near-duplicate
|
|
11
|
+
* string (Wave 3 round-3 agon-review finding D — kimi 0.90 / claude 0.50 /
|
|
12
|
+
* zai 0.65 convergence on the drift hazard).
|
|
13
|
+
*
|
|
14
|
+
* Design notes (cumulative across Wave 3 review rounds):
|
|
15
|
+
* • Python name-mangling: an identifier with two leading underscores
|
|
16
|
+
* INSIDE a class body becomes `_ClassName__name`. So `__DotDict(val)`
|
|
17
|
+
* inside `__DotDict`'s own methods would resolve to `_DotDict__DotDict`
|
|
18
|
+
* (NameError). Route dict recursion through `cls = type(self); cls(val)`,
|
|
19
|
+
* and use `_DotList` (single underscore — NOT mangled) as the list
|
|
20
|
+
* idempotency marker.
|
|
21
|
+
* • Cached write-back (`self[key] = val`) makes both branches O(1) on
|
|
22
|
+
* re-access and persists in-handler writes — `body.profile.name = "x"`
|
|
23
|
+
* now sticks. SIDE EFFECT: a dotted read mutates the parent dict; raw
|
|
24
|
+
* `body.items()` iteration sees wrapped values. Intentional.
|
|
25
|
+
* • `_DotList.__getitem__` auto-wraps elements so post-access append/insert
|
|
26
|
+
* of plain dicts still reads back as `__DotDict` — `body.rows.append({a:1});
|
|
27
|
+
* body.rows[0].a` works (round-3 codex 0.86 + agy 0.95 regression close).
|
|
28
|
+
* Bound at module level so the `__DotDict` reference inside it isn't
|
|
29
|
+
* subject to class-body name-mangling.
|
|
30
|
+
* • `__delattr__` mirrors `__getattr__`'s camelCase fallback; the
|
|
31
|
+
* `from None` suppresses chained KeyError tracebacks (round-3 claude 0.70).
|
|
32
|
+
*/
|
|
33
|
+
export const DOT_DICT_SHIM_PY = `class _DotList(list):
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class __DotDict(dict):
|
|
38
|
+
def __getattr__(self, name):
|
|
39
|
+
try:
|
|
40
|
+
val = self[name]
|
|
41
|
+
key = name
|
|
42
|
+
except KeyError:
|
|
43
|
+
camel = ''.join(x.capitalize() or '_' for x in name.split('_'))
|
|
44
|
+
camel = camel[0].lower() + camel[1:] if camel else ''
|
|
45
|
+
if camel in self:
|
|
46
|
+
val = self[camel]
|
|
47
|
+
key = camel
|
|
48
|
+
else:
|
|
49
|
+
raise AttributeError(name) from None
|
|
50
|
+
cls = type(self)
|
|
51
|
+
def _wrap(x):
|
|
52
|
+
if isinstance(x, cls):
|
|
53
|
+
return x
|
|
54
|
+
if isinstance(x, _DotList):
|
|
55
|
+
return x
|
|
56
|
+
if isinstance(x, dict):
|
|
57
|
+
return cls(x)
|
|
58
|
+
if isinstance(x, list):
|
|
59
|
+
return _DotList([_wrap(y) for y in x])
|
|
60
|
+
return x
|
|
61
|
+
if isinstance(val, dict) and not isinstance(val, cls):
|
|
62
|
+
val = cls(val)
|
|
63
|
+
self[key] = val
|
|
64
|
+
elif isinstance(val, list) and not isinstance(val, _DotList):
|
|
65
|
+
val = _DotList([_wrap(x) for x in val])
|
|
66
|
+
self[key] = val
|
|
67
|
+
return val
|
|
68
|
+
|
|
69
|
+
def __setattr__(self, name, value):
|
|
70
|
+
self[name] = value
|
|
71
|
+
|
|
72
|
+
def __delattr__(self, name):
|
|
73
|
+
try:
|
|
74
|
+
del self[name]
|
|
75
|
+
except KeyError:
|
|
76
|
+
camel = ''.join(x.capitalize() or '_' for x in name.split('_'))
|
|
77
|
+
camel = camel[0].lower() + camel[1:] if camel else ''
|
|
78
|
+
if camel in self:
|
|
79
|
+
del self[camel]
|
|
80
|
+
else:
|
|
81
|
+
raise AttributeError(name) from None
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _dotlist_getitem(self, index):
|
|
85
|
+
val = list.__getitem__(self, index)
|
|
86
|
+
if isinstance(val, (__DotDict, _DotList)):
|
|
87
|
+
return val
|
|
88
|
+
if isinstance(val, dict):
|
|
89
|
+
wrapped = __DotDict(val)
|
|
90
|
+
list.__setitem__(self, index, wrapped)
|
|
91
|
+
return wrapped
|
|
92
|
+
if isinstance(val, list):
|
|
93
|
+
wrapped = _DotList(val)
|
|
94
|
+
list.__setitem__(self, index, wrapped)
|
|
95
|
+
return wrapped
|
|
96
|
+
return val
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
_DotList.__getitem__ = _dotlist_getitem
|
|
100
|
+
`;
|
|
5
101
|
/**
|
|
6
102
|
* First-class `python` transpiler target. Lowering KERN types and models to pure Python.
|
|
7
103
|
*/
|
|
@@ -10,15 +106,40 @@ export function transpilePython(root, config) {
|
|
|
10
106
|
const emit = config?.emit || 'models'; // In Phase 1, target python implies models-only
|
|
11
107
|
// 1. Demand-driven imports
|
|
12
108
|
const { lines: preambleLines, imports } = emitImports(root, { pythonModelBackend });
|
|
13
|
-
// 2.
|
|
14
|
-
|
|
109
|
+
// 2. Pure route handlers — emit only when caller requested `emit: 'backend'`.
|
|
110
|
+
// The existing models-only path (the default) must stay byte-identical whether
|
|
111
|
+
// a server node is present or not; `python-target.test.ts:60` (`route
|
|
112
|
+
// invariance (decl-driven emit-models)`) is the canonical contract.
|
|
113
|
+
const serverNode = emit === 'backend' ? findServerNode(root) : undefined;
|
|
114
|
+
let handlersCode = '';
|
|
115
|
+
if (serverNode) {
|
|
116
|
+
const handlers = emitPureHandlers(serverNode, imports, root);
|
|
117
|
+
if (handlers.length > 0) {
|
|
118
|
+
const handlerBlocks = handlers.map((h) => `${h.signature}\n${h.bodyLines.join('\n')}`).join('\n\n');
|
|
119
|
+
handlersCode = `\n${DOT_DICT_SHIM_PY}\n\n${handlerBlocks}\n`;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// 3. Core node render
|
|
123
|
+
const { code: modelsCode } = emitModels(root, {
|
|
15
124
|
pythonModelBackend,
|
|
16
125
|
emit,
|
|
17
126
|
target: 'python',
|
|
18
127
|
});
|
|
19
128
|
const lines = [];
|
|
20
129
|
// Sort and print imports
|
|
21
|
-
|
|
130
|
+
let filteredImports = [...imports];
|
|
131
|
+
if (emit === 'backend') {
|
|
132
|
+
filteredImports = filteredImports.filter((imp) => {
|
|
133
|
+
const lower = imp.toLowerCase();
|
|
134
|
+
return (!lower.includes('pydantic') &&
|
|
135
|
+
!lower.includes('fastapi') &&
|
|
136
|
+
!lower.includes('django') &&
|
|
137
|
+
!lower.includes('httpexception') &&
|
|
138
|
+
!lower.includes('jsonresponse') &&
|
|
139
|
+
!lower.includes('depends('));
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
for (const imp of filteredImports.sort()) {
|
|
22
143
|
lines.push(imp);
|
|
23
144
|
}
|
|
24
145
|
lines.push('');
|
|
@@ -28,10 +149,15 @@ export function transpilePython(root, config) {
|
|
|
28
149
|
lines.push(...preambleLines);
|
|
29
150
|
}
|
|
30
151
|
// Model and type definitions
|
|
31
|
-
if (modelsCode.trim().length > 0) {
|
|
152
|
+
if (emit !== 'backend' && modelsCode.trim().length > 0) {
|
|
32
153
|
lines.push('');
|
|
33
154
|
lines.push(modelsCode);
|
|
34
155
|
}
|
|
156
|
+
// Pure handlers (additive)
|
|
157
|
+
if (handlersCode) {
|
|
158
|
+
lines.push('');
|
|
159
|
+
lines.push(handlersCode);
|
|
160
|
+
}
|
|
35
161
|
const output = lines.join('\n');
|
|
36
162
|
const irText = serializeIR(root);
|
|
37
163
|
const irTokenCount = countTokens(irText);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"python.js","sourceRoot":"","sources":["../../src/targets/python.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"python.js","sourceRoot":"","sources":["../../src/targets/python.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kernlang/python",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.7",
|
|
4
4
|
"description": "KERN Python backend codegen (FastAPI router target included)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"python": ">=3.8"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@kernlang/core": "3.5.
|
|
31
|
+
"@kernlang/core": "3.5.7"
|
|
32
32
|
},
|
|
33
33
|
"scripts": {
|
|
34
34
|
"build": "tsc -b",
|