tywrap 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.
- package/LICENSE +21 -0
- package/README.md +319 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +263 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/index.d.ts +41 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +234 -0
- package/dist/config/index.js.map +1 -0
- package/dist/core/analyzer.d.ts +63 -0
- package/dist/core/analyzer.d.ts.map +1 -0
- package/dist/core/analyzer.js +676 -0
- package/dist/core/analyzer.js.map +1 -0
- package/dist/core/discovery.d.ts +85 -0
- package/dist/core/discovery.d.ts.map +1 -0
- package/dist/core/discovery.js +344 -0
- package/dist/core/discovery.js.map +1 -0
- package/dist/core/generator.d.ts +37 -0
- package/dist/core/generator.d.ts.map +1 -0
- package/dist/core/generator.js +368 -0
- package/dist/core/generator.js.map +1 -0
- package/dist/core/mapper.d.ts +40 -0
- package/dist/core/mapper.d.ts.map +1 -0
- package/dist/core/mapper.js +401 -0
- package/dist/core/mapper.js.map +1 -0
- package/dist/core/validation.d.ts +79 -0
- package/dist/core/validation.d.ts.map +1 -0
- package/dist/core/validation.js +486 -0
- package/dist/core/validation.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime/base.d.ts +12 -0
- package/dist/runtime/base.d.ts.map +1 -0
- package/dist/runtime/base.js +6 -0
- package/dist/runtime/base.js.map +1 -0
- package/dist/runtime/errors.d.ts +17 -0
- package/dist/runtime/errors.d.ts.map +1 -0
- package/dist/runtime/errors.js +21 -0
- package/dist/runtime/errors.js.map +1 -0
- package/dist/runtime/http.d.ts +22 -0
- package/dist/runtime/http.d.ts.map +1 -0
- package/dist/runtime/http.js +79 -0
- package/dist/runtime/http.js.map +1 -0
- package/dist/runtime/index.d.ts +8 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +17 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/node.d.ts +48 -0
- package/dist/runtime/node.d.ts.map +1 -0
- package/dist/runtime/node.js +328 -0
- package/dist/runtime/node.js.map +1 -0
- package/dist/runtime/optimized-node.d.ts +131 -0
- package/dist/runtime/optimized-node.d.ts.map +1 -0
- package/dist/runtime/optimized-node.js +622 -0
- package/dist/runtime/optimized-node.js.map +1 -0
- package/dist/runtime/protocol.d.ts +3 -0
- package/dist/runtime/protocol.d.ts.map +1 -0
- package/dist/runtime/protocol.js +3 -0
- package/dist/runtime/protocol.js.map +1 -0
- package/dist/runtime/pyodide.d.ts +27 -0
- package/dist/runtime/pyodide.d.ts.map +1 -0
- package/dist/runtime/pyodide.js +191 -0
- package/dist/runtime/pyodide.js.map +1 -0
- package/dist/tools/python_suite.js +173 -0
- package/dist/tools/python_suite.js.map +1 -0
- package/dist/types/index.d.ts +299 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/dist/tywrap.d.ts +29 -0
- package/dist/tywrap.d.ts.map +1 -0
- package/dist/tywrap.js +589 -0
- package/dist/tywrap.js.map +1 -0
- package/dist/utils/bundle-optimizer.d.ts +182 -0
- package/dist/utils/bundle-optimizer.d.ts.map +1 -0
- package/dist/utils/bundle-optimizer.js +680 -0
- package/dist/utils/bundle-optimizer.js.map +1 -0
- package/dist/utils/cache.d.ts +149 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +492 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/codec.d.ts +94 -0
- package/dist/utils/codec.d.ts.map +1 -0
- package/dist/utils/codec.js +150 -0
- package/dist/utils/codec.js.map +1 -0
- package/dist/utils/logger.d.ts +42 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +140 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/memory-profiler.d.ts +123 -0
- package/dist/utils/memory-profiler.d.ts.map +1 -0
- package/dist/utils/memory-profiler.js +426 -0
- package/dist/utils/memory-profiler.js.map +1 -0
- package/dist/utils/parallel-processor.d.ts +146 -0
- package/dist/utils/parallel-processor.d.ts.map +1 -0
- package/dist/utils/parallel-processor.js +636 -0
- package/dist/utils/parallel-processor.js.map +1 -0
- package/dist/utils/python.d.ts +8 -0
- package/dist/utils/python.d.ts.map +1 -0
- package/dist/utils/python.js +56 -0
- package/dist/utils/python.js.map +1 -0
- package/dist/utils/runtime.d.ts +153 -0
- package/dist/utils/runtime.d.ts.map +1 -0
- package/dist/utils/runtime.js +519 -0
- package/dist/utils/runtime.js.map +1 -0
- package/package.json +136 -0
- package/runtime/python_bridge.py +476 -0
- package/src/cli.ts +331 -0
- package/src/config/index.ts +289 -0
- package/src/core/analyzer.ts +788 -0
- package/src/core/discovery.ts +415 -0
- package/src/core/generator.ts +447 -0
- package/src/core/mapper.ts +504 -0
- package/src/core/validation.ts +693 -0
- package/src/index.ts +83 -0
- package/src/runtime/base.ts +32 -0
- package/src/runtime/errors.ts +19 -0
- package/src/runtime/http.ts +132 -0
- package/src/runtime/index.ts +24 -0
- package/src/runtime/node.ts +431 -0
- package/src/runtime/optimized-node.ts +838 -0
- package/src/runtime/protocol.ts +2 -0
- package/src/runtime/pyodide.ts +228 -0
- package/src/types/global.d.ts +60 -0
- package/src/types/index.ts +410 -0
- package/src/tywrap.ts +669 -0
- package/src/utils/bundle-optimizer.ts +876 -0
- package/src/utils/cache.ts +634 -0
- package/src/utils/codec.ts +275 -0
- package/src/utils/logger.ts +201 -0
- package/src/utils/memory-profiler.ts +582 -0
- package/src/utils/parallel-processor.ts +879 -0
- package/src/utils/python.ts +79 -0
- package/src/utils/runtime.ts +616 -0
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeMapper - Python to TypeScript type conversion
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type {
|
|
6
|
+
PythonType,
|
|
7
|
+
PrimitiveType as PyPrimitiveType,
|
|
8
|
+
CollectionType as PyCollectionType,
|
|
9
|
+
UnionType as PyUnionType,
|
|
10
|
+
OptionalType as PyOptionalType,
|
|
11
|
+
GenericType as PyGenericType,
|
|
12
|
+
TypeVarType as PyTypeVarType,
|
|
13
|
+
FinalType as PyFinalType,
|
|
14
|
+
ClassVarType as PyClassVarType,
|
|
15
|
+
TypescriptType,
|
|
16
|
+
TSPrimitiveType,
|
|
17
|
+
TSArrayType,
|
|
18
|
+
TSTupleType,
|
|
19
|
+
TSObjectType,
|
|
20
|
+
TSUnionType,
|
|
21
|
+
TSFunctionType,
|
|
22
|
+
TSGenericType,
|
|
23
|
+
TSCustomType,
|
|
24
|
+
TSIndexSignature,
|
|
25
|
+
TSLiteralType,
|
|
26
|
+
TypePreset,
|
|
27
|
+
} from '../types/index.js';
|
|
28
|
+
|
|
29
|
+
export type MappingContext = 'value' | 'return';
|
|
30
|
+
|
|
31
|
+
export interface TypeMapperOptions {
|
|
32
|
+
presets?: readonly TypePreset[];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export class TypeMapper {
|
|
36
|
+
private readonly presets: Set<TypePreset>;
|
|
37
|
+
|
|
38
|
+
constructor(options: TypeMapperOptions = {}) {
|
|
39
|
+
this.presets = new Set(options.presets ?? []);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
mapPythonType(pythonType: PythonType, context: MappingContext = 'value'): TypescriptType {
|
|
43
|
+
switch (pythonType.kind) {
|
|
44
|
+
case 'primitive':
|
|
45
|
+
return this.mapPrimitiveType(pythonType, context);
|
|
46
|
+
case 'collection':
|
|
47
|
+
return this.mapCollectionType(pythonType);
|
|
48
|
+
case 'union':
|
|
49
|
+
return this.mapUnionType(pythonType, context);
|
|
50
|
+
case 'optional':
|
|
51
|
+
return this.mapOptionalType(pythonType, context);
|
|
52
|
+
case 'generic':
|
|
53
|
+
return this.mapGenericType(pythonType, context);
|
|
54
|
+
case 'custom':
|
|
55
|
+
return this.mapCustomType(pythonType, context);
|
|
56
|
+
case 'callable':
|
|
57
|
+
return this.mapCallableType(pythonType);
|
|
58
|
+
case 'literal':
|
|
59
|
+
return this.mapLiteralType(pythonType);
|
|
60
|
+
case 'annotated':
|
|
61
|
+
// Pass-through base for type shape; metadata used at generation when configured
|
|
62
|
+
return this.mapPythonType(pythonType.base, context);
|
|
63
|
+
case 'typevar':
|
|
64
|
+
return this.mapTypeVarType(pythonType, context);
|
|
65
|
+
case 'final':
|
|
66
|
+
return this.mapFinalType(pythonType, context);
|
|
67
|
+
case 'classvar':
|
|
68
|
+
return this.mapClassVarType(pythonType, context);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
mapPrimitiveType(type: PyPrimitiveType, context: MappingContext = 'value'): TSPrimitiveType {
|
|
73
|
+
const name =
|
|
74
|
+
type.name === 'int' || type.name === 'float'
|
|
75
|
+
? 'number'
|
|
76
|
+
: type.name === 'str'
|
|
77
|
+
? 'string'
|
|
78
|
+
: type.name === 'bool'
|
|
79
|
+
? 'boolean'
|
|
80
|
+
: type.name === 'bytes'
|
|
81
|
+
? 'string'
|
|
82
|
+
: // None
|
|
83
|
+
context === 'return'
|
|
84
|
+
? 'void'
|
|
85
|
+
: 'null';
|
|
86
|
+
|
|
87
|
+
return { kind: 'primitive', name };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
mapCollectionType(
|
|
91
|
+
type: PyCollectionType
|
|
92
|
+
): TSArrayType | TSTupleType | TSObjectType | TSGenericType {
|
|
93
|
+
// list[T] -> Array<T>
|
|
94
|
+
if (type.name === 'list') {
|
|
95
|
+
const elementType = this.mapPythonType(
|
|
96
|
+
type.itemTypes[0] ?? { kind: 'custom', name: 'Any', module: 'typing' }
|
|
97
|
+
);
|
|
98
|
+
return {
|
|
99
|
+
kind: 'array',
|
|
100
|
+
elementType,
|
|
101
|
+
} satisfies TSArrayType;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// tuple[T1, T2, ...] -> [T1, T2, ...] (exact arity)
|
|
105
|
+
if (type.name === 'tuple') {
|
|
106
|
+
const elementTypes: TypescriptType[] =
|
|
107
|
+
type.itemTypes.length > 0
|
|
108
|
+
? type.itemTypes.map(t => this.mapPythonType(t))
|
|
109
|
+
: ([{ kind: 'primitive', name: 'undefined' }] as const);
|
|
110
|
+
return { kind: 'tuple', elementTypes } satisfies TSTupleType;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// set[T] -> Set<T>
|
|
114
|
+
if (type.name === 'set' || type.name === 'frozenset') {
|
|
115
|
+
const elementType = this.mapPythonType(
|
|
116
|
+
type.itemTypes[0] ?? { kind: 'custom', name: 'Any', module: 'typing' }
|
|
117
|
+
);
|
|
118
|
+
return {
|
|
119
|
+
kind: 'generic',
|
|
120
|
+
name: 'Set',
|
|
121
|
+
typeArgs: [elementType],
|
|
122
|
+
} satisfies TSGenericType;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// dict[K, V] -> { [key: K]: V }
|
|
126
|
+
if (type.name === 'dict') {
|
|
127
|
+
const keyPy = type.itemTypes[0] ?? { kind: 'primitive', name: 'str' };
|
|
128
|
+
const valPy = type.itemTypes[1] ?? { kind: 'custom', name: 'Any', module: 'typing' };
|
|
129
|
+
const key = this.mapPythonType(keyPy);
|
|
130
|
+
const value = this.mapPythonType(valPy);
|
|
131
|
+
|
|
132
|
+
const indexSignature: TSIndexSignature = {
|
|
133
|
+
keyType: this.asIndexKeyType(key),
|
|
134
|
+
valueType: value,
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
kind: 'object',
|
|
139
|
+
properties: [],
|
|
140
|
+
indexSignature,
|
|
141
|
+
} satisfies TSObjectType;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Default to object unknown index
|
|
145
|
+
return {
|
|
146
|
+
kind: 'object',
|
|
147
|
+
properties: [],
|
|
148
|
+
indexSignature: {
|
|
149
|
+
keyType: { kind: 'primitive', name: 'string' },
|
|
150
|
+
valueType: { kind: 'primitive', name: 'unknown' },
|
|
151
|
+
},
|
|
152
|
+
} satisfies TSObjectType;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
mapUnionType(type: PyUnionType, context: MappingContext = 'value'): TSUnionType {
|
|
156
|
+
return {
|
|
157
|
+
kind: 'union',
|
|
158
|
+
types: type.types.map(t => this.mapPythonType(t, context)),
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
mapOptionalType(type: PyOptionalType, context: MappingContext = 'value'): TSUnionType {
|
|
163
|
+
const inner = this.mapPythonType(type.type, context);
|
|
164
|
+
return {
|
|
165
|
+
kind: 'union',
|
|
166
|
+
types: [inner, { kind: 'primitive', name: 'null' }],
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
mapGenericType(type: PyGenericType, context: MappingContext = 'value'): TSGenericType {
|
|
171
|
+
return {
|
|
172
|
+
kind: 'generic',
|
|
173
|
+
name: type.name,
|
|
174
|
+
typeArgs: type.typeArgs.map(t => this.mapPythonType(t, context)),
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
mapCustomType(
|
|
179
|
+
type: { kind: 'custom'; name: string; module?: string },
|
|
180
|
+
_context: MappingContext = 'value'
|
|
181
|
+
): TypescriptType {
|
|
182
|
+
// Normalize some known typing names into TS primitives/generics
|
|
183
|
+
const name = type.name;
|
|
184
|
+
const fullName = type.module ? `${type.module}.${name}` : name;
|
|
185
|
+
|
|
186
|
+
// Top and bottom types
|
|
187
|
+
if (name === 'Any' || fullName === 'typing.Any') {
|
|
188
|
+
return { kind: 'primitive', name: 'unknown' };
|
|
189
|
+
}
|
|
190
|
+
if (
|
|
191
|
+
name === 'Never' ||
|
|
192
|
+
fullName === 'typing.Never' ||
|
|
193
|
+
name === 'NoReturn' ||
|
|
194
|
+
fullName === 'typing.NoReturn'
|
|
195
|
+
) {
|
|
196
|
+
return { kind: 'primitive', name: 'never' };
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// String types
|
|
200
|
+
if (name === 'LiteralString' || fullName === 'typing.LiteralString') {
|
|
201
|
+
return { kind: 'primitive', name: 'string' };
|
|
202
|
+
}
|
|
203
|
+
if (name === 'AnyStr' || fullName === 'typing.AnyStr') {
|
|
204
|
+
return { kind: 'primitive', name: 'string' };
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Object types
|
|
208
|
+
if (name === 'object' || fullName === 'builtins.object') {
|
|
209
|
+
return { kind: 'primitive', name: 'object' };
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Callable types
|
|
213
|
+
if (name === 'Callable' || fullName === 'typing.Callable') {
|
|
214
|
+
return {
|
|
215
|
+
kind: 'function',
|
|
216
|
+
isAsync: false,
|
|
217
|
+
parameters: [
|
|
218
|
+
{
|
|
219
|
+
name: 'args',
|
|
220
|
+
type: { kind: 'array', elementType: { kind: 'primitive', name: 'unknown' } },
|
|
221
|
+
optional: false,
|
|
222
|
+
rest: true,
|
|
223
|
+
},
|
|
224
|
+
],
|
|
225
|
+
returnType: { kind: 'primitive', name: 'unknown' },
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Async types
|
|
230
|
+
if (name === 'Awaitable' || fullName === 'typing.Awaitable') {
|
|
231
|
+
return {
|
|
232
|
+
kind: 'generic',
|
|
233
|
+
name: 'Promise',
|
|
234
|
+
typeArgs: [{ kind: 'primitive', name: 'unknown' }],
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
if (name === 'Coroutine' || fullName === 'typing.Coroutine') {
|
|
238
|
+
return {
|
|
239
|
+
kind: 'generic',
|
|
240
|
+
name: 'Promise',
|
|
241
|
+
typeArgs: [{ kind: 'primitive', name: 'unknown' }],
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Collection types that should be generics
|
|
246
|
+
if (name === 'Sequence' || fullName === 'typing.Sequence') {
|
|
247
|
+
return {
|
|
248
|
+
kind: 'generic',
|
|
249
|
+
name: 'Array',
|
|
250
|
+
typeArgs: [{ kind: 'primitive', name: 'unknown' }],
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
if (name === 'Mapping' || fullName === 'typing.Mapping') {
|
|
254
|
+
return {
|
|
255
|
+
kind: 'object',
|
|
256
|
+
properties: [],
|
|
257
|
+
indexSignature: {
|
|
258
|
+
keyType: { kind: 'primitive', name: 'string' },
|
|
259
|
+
valueType: { kind: 'primitive', name: 'unknown' },
|
|
260
|
+
},
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const presetType = this.mapPresetType(type);
|
|
265
|
+
if (presetType) {
|
|
266
|
+
return presetType;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Forward references and user types
|
|
270
|
+
return { kind: 'custom', name: type.name, module: type.module };
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
mapCallableType(type: {
|
|
274
|
+
kind: 'callable';
|
|
275
|
+
parameters: PythonType[];
|
|
276
|
+
returnType: PythonType;
|
|
277
|
+
}): TSFunctionType {
|
|
278
|
+
// Support Callable[[...], R] → (...args: unknown[]) => R
|
|
279
|
+
const onlyEllipsis =
|
|
280
|
+
type.parameters.length === 1 &&
|
|
281
|
+
type.parameters[0]?.kind === 'custom' &&
|
|
282
|
+
(type.parameters[0] as { kind: 'custom'; name: string }).name === '...';
|
|
283
|
+
|
|
284
|
+
return {
|
|
285
|
+
kind: 'function',
|
|
286
|
+
isAsync: false,
|
|
287
|
+
parameters: onlyEllipsis
|
|
288
|
+
? ([
|
|
289
|
+
{
|
|
290
|
+
name: 'args',
|
|
291
|
+
type: { kind: 'array', elementType: { kind: 'primitive', name: 'unknown' } },
|
|
292
|
+
optional: false,
|
|
293
|
+
rest: true,
|
|
294
|
+
},
|
|
295
|
+
] as const satisfies TSFunctionType['parameters'])
|
|
296
|
+
: type.parameters.map((p, i) => ({
|
|
297
|
+
name: `arg${i}`,
|
|
298
|
+
type: this.mapPythonType(p, 'value'),
|
|
299
|
+
optional: false,
|
|
300
|
+
rest: false,
|
|
301
|
+
})),
|
|
302
|
+
returnType: this.mapPythonType(type.returnType, 'return'),
|
|
303
|
+
} satisfies TSFunctionType;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
mapLiteralType(type: {
|
|
307
|
+
kind: 'literal';
|
|
308
|
+
value: string | number | boolean | null;
|
|
309
|
+
}): TSLiteralType {
|
|
310
|
+
return { kind: 'literal', value: type.value };
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
mapTypeVarType(type: PyTypeVarType, _context: MappingContext = 'value'): TSCustomType {
|
|
314
|
+
// TypeVar maps to a generic type parameter in TypeScript
|
|
315
|
+
// Bounds and constraints are not directly expressible in TypeScript type system
|
|
316
|
+
return {
|
|
317
|
+
kind: 'custom',
|
|
318
|
+
name: type.name,
|
|
319
|
+
module: 'typing',
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
mapFinalType(type: PyFinalType, context: MappingContext = 'value'): TypescriptType {
|
|
324
|
+
// Final[T] maps to T in TypeScript (no direct Final equivalent)
|
|
325
|
+
// The Final qualifier is more of a static analysis hint
|
|
326
|
+
return this.mapPythonType(type.type, context);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
mapClassVarType(type: PyClassVarType, context: MappingContext = 'value'): TypescriptType {
|
|
330
|
+
// ClassVar[T] maps to T in TypeScript (class variables are just properties)
|
|
331
|
+
// The ClassVar qualifier is more of a static analysis hint
|
|
332
|
+
return this.mapPythonType(type.type, context);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
private asIndexKeyType(key: TypescriptType): TSPrimitiveType {
|
|
336
|
+
if (key.kind === 'primitive' && (key.name === 'string' || key.name === 'number')) {
|
|
337
|
+
return key;
|
|
338
|
+
}
|
|
339
|
+
return { kind: 'primitive', name: 'string' };
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
private hasPreset(name: TypePreset): boolean {
|
|
343
|
+
return this.presets.has(name);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
private normalizeCustomType(type: { name: string; module?: string }): {
|
|
347
|
+
name: string;
|
|
348
|
+
module?: string;
|
|
349
|
+
rawName: string;
|
|
350
|
+
} {
|
|
351
|
+
const rawName = type.name;
|
|
352
|
+
if (type.module) {
|
|
353
|
+
return { name: type.name, module: type.module, rawName };
|
|
354
|
+
}
|
|
355
|
+
if (rawName.includes('.')) {
|
|
356
|
+
const parts = rawName.split('.');
|
|
357
|
+
return {
|
|
358
|
+
name: parts[parts.length - 1] ?? rawName,
|
|
359
|
+
module: parts.slice(0, -1).join('.'),
|
|
360
|
+
rawName,
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
return { name: rawName, module: undefined, rawName };
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
private mapPresetType(type: { name: string; module?: string }): TypescriptType | undefined {
|
|
367
|
+
const normalized = this.normalizeCustomType(type);
|
|
368
|
+
const name = normalized.name;
|
|
369
|
+
const moduleName = normalized.module;
|
|
370
|
+
const stringType: TSPrimitiveType = { kind: 'primitive', name: 'string' };
|
|
371
|
+
const numberType: TSPrimitiveType = { kind: 'primitive', name: 'number' };
|
|
372
|
+
const unknownType: TSPrimitiveType = { kind: 'primitive', name: 'unknown' };
|
|
373
|
+
const numberArray: TSArrayType = { kind: 'array', elementType: numberType };
|
|
374
|
+
const unknownArray: TSArrayType = { kind: 'array', elementType: unknownType };
|
|
375
|
+
const recordObject: TSObjectType = {
|
|
376
|
+
kind: 'object',
|
|
377
|
+
properties: [],
|
|
378
|
+
indexSignature: {
|
|
379
|
+
keyType: stringType,
|
|
380
|
+
valueType: unknownType,
|
|
381
|
+
},
|
|
382
|
+
};
|
|
383
|
+
const prop = (
|
|
384
|
+
propName: string,
|
|
385
|
+
typeValue: TypescriptType,
|
|
386
|
+
optional = false
|
|
387
|
+
): TSObjectType['properties'][number] => ({
|
|
388
|
+
name: propName,
|
|
389
|
+
type: typeValue,
|
|
390
|
+
optional,
|
|
391
|
+
readonly: false,
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
if (this.hasPreset('stdlib')) {
|
|
395
|
+
const stdlibModule = moduleName ?? '';
|
|
396
|
+
const allowModule =
|
|
397
|
+
!moduleName ||
|
|
398
|
+
stdlibModule === 'datetime' ||
|
|
399
|
+
stdlibModule === 'decimal' ||
|
|
400
|
+
stdlibModule === 'uuid' ||
|
|
401
|
+
stdlibModule === 'pathlib';
|
|
402
|
+
if (allowModule) {
|
|
403
|
+
if (name === 'datetime' || name === 'date' || name === 'time') {
|
|
404
|
+
return { kind: 'primitive', name: 'string' };
|
|
405
|
+
}
|
|
406
|
+
if (name === 'timedelta') {
|
|
407
|
+
return { kind: 'primitive', name: 'number' };
|
|
408
|
+
}
|
|
409
|
+
if (name === 'Decimal' || name === 'UUID') {
|
|
410
|
+
return { kind: 'primitive', name: 'string' };
|
|
411
|
+
}
|
|
412
|
+
if (
|
|
413
|
+
name === 'Path' ||
|
|
414
|
+
name === 'PurePath' ||
|
|
415
|
+
name === 'PosixPath' ||
|
|
416
|
+
name === 'WindowsPath'
|
|
417
|
+
) {
|
|
418
|
+
return { kind: 'primitive', name: 'string' };
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
if (this.hasPreset('pandas')) {
|
|
424
|
+
const allowModule = !moduleName || moduleName.startsWith('pandas');
|
|
425
|
+
if (allowModule) {
|
|
426
|
+
if (name === 'DataFrame') {
|
|
427
|
+
const recordsArray: TSArrayType = { kind: 'array', elementType: recordObject };
|
|
428
|
+
return { kind: 'union', types: [recordObject, recordsArray] };
|
|
429
|
+
}
|
|
430
|
+
if (name === 'Series') {
|
|
431
|
+
const valuesArray: TSArrayType = {
|
|
432
|
+
kind: 'array',
|
|
433
|
+
elementType: { kind: 'primitive', name: 'unknown' },
|
|
434
|
+
};
|
|
435
|
+
return { kind: 'union', types: [valuesArray, recordObject] };
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
if (this.hasPreset('scipy')) {
|
|
441
|
+
const allowModule = !moduleName || moduleName.startsWith('scipy');
|
|
442
|
+
if (allowModule) {
|
|
443
|
+
const baseProps = [prop('shape', numberArray), prop('dtype', stringType, true)];
|
|
444
|
+
const buildSparse = (
|
|
445
|
+
format: 'csr' | 'csc' | 'coo'
|
|
446
|
+
): TSObjectType => ({
|
|
447
|
+
kind: 'object',
|
|
448
|
+
properties: [
|
|
449
|
+
prop('format', { kind: 'literal', value: format }),
|
|
450
|
+
...baseProps,
|
|
451
|
+
prop('data', unknownArray),
|
|
452
|
+
...(format === 'coo'
|
|
453
|
+
? [prop('row', numberArray), prop('col', numberArray)]
|
|
454
|
+
: [prop('indices', numberArray), prop('indptr', numberArray)]),
|
|
455
|
+
],
|
|
456
|
+
});
|
|
457
|
+
if (name === 'csr_matrix') {
|
|
458
|
+
return buildSparse('csr');
|
|
459
|
+
}
|
|
460
|
+
if (name === 'csc_matrix') {
|
|
461
|
+
return buildSparse('csc');
|
|
462
|
+
}
|
|
463
|
+
if (name === 'coo_matrix') {
|
|
464
|
+
return buildSparse('coo');
|
|
465
|
+
}
|
|
466
|
+
if (name === 'spmatrix') {
|
|
467
|
+
return { kind: 'union', types: [buildSparse('csr'), buildSparse('csc'), buildSparse('coo')] };
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
if (this.hasPreset('torch')) {
|
|
473
|
+
const allowModule = !moduleName || moduleName.startsWith('torch');
|
|
474
|
+
if (allowModule && name === 'Tensor') {
|
|
475
|
+
return {
|
|
476
|
+
kind: 'object',
|
|
477
|
+
properties: [
|
|
478
|
+
prop('data', unknownType),
|
|
479
|
+
prop('shape', numberArray),
|
|
480
|
+
prop('dtype', stringType, true),
|
|
481
|
+
prop('device', stringType, true),
|
|
482
|
+
],
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
if (this.hasPreset('sklearn')) {
|
|
488
|
+
const allowModule = !moduleName || moduleName.startsWith('sklearn');
|
|
489
|
+
if (allowModule && name === 'BaseEstimator') {
|
|
490
|
+
return {
|
|
491
|
+
kind: 'object',
|
|
492
|
+
properties: [
|
|
493
|
+
prop('className', stringType),
|
|
494
|
+
prop('module', stringType),
|
|
495
|
+
prop('version', stringType, true),
|
|
496
|
+
prop('params', recordObject),
|
|
497
|
+
],
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
return undefined;
|
|
503
|
+
}
|
|
504
|
+
}
|