xlr-lib-types 0.1.1.dev9190__py3-none-any.whl
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.
|
File without changes
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Deserialization utilities for XLR nodes.
|
|
3
|
+
Converts JSON strings back into proper XLR node objects.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import json
|
|
7
|
+
from typing import Any, Dict, Union
|
|
8
|
+
from .nodes import (
|
|
9
|
+
|
|
10
|
+
# Simple types
|
|
11
|
+
AnyType, UnknownType, UndefinedType, NullType, VoidType, StringType,
|
|
12
|
+
NumberType, BooleanType, NeverType, TemplateLiteralType,
|
|
13
|
+
|
|
14
|
+
# Complex types
|
|
15
|
+
RefType, ObjectType, ArrayType, TupleType, AndType, OrType,
|
|
16
|
+
RecordType, FunctionType, ConditionalType,
|
|
17
|
+
|
|
18
|
+
# Helper classes
|
|
19
|
+
ObjectProperty, TupleMember, FunctionTypeParameters, ParamTypeNode,
|
|
20
|
+
NamedType, NamedTypeWithGenerics,
|
|
21
|
+
|
|
22
|
+
# Type unions
|
|
23
|
+
NodeType
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def deserialize_xlr_node(json_string: str) -> NodeType:
|
|
28
|
+
"""
|
|
29
|
+
Deserialize a JSON string into an XLR node object.
|
|
30
|
+
|
|
31
|
+
Uses Python's built-in json library with the loads function and object_hook
|
|
32
|
+
parameter to pass in custom deserialization logic.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
json_string: JSON string representation of an XLR node
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
The deserialized XLR node object
|
|
39
|
+
|
|
40
|
+
Raises:
|
|
41
|
+
ValueError: If the JSON cannot be deserialized or contains invalid node types
|
|
42
|
+
json.JSONDecodeError: If the JSON string is malformed
|
|
43
|
+
"""
|
|
44
|
+
return json.loads(json_string, object_hook=_deserialize_object_hook)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _deserialize_object_hook(obj: Dict[str, Any]) -> Any:
|
|
48
|
+
"""
|
|
49
|
+
Object hook function for JSON deserialization.
|
|
50
|
+
|
|
51
|
+
This function is called for every JSON object during deserialization
|
|
52
|
+
and converts dictionaries with type information into appropriate XLR node objects.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
obj: Dictionary from JSON parsing
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
Either the original dict or a deserialized XLR node object
|
|
59
|
+
"""
|
|
60
|
+
# Handle special helper classes first (they don't have a "type" field)
|
|
61
|
+
if _is_named_type(obj):
|
|
62
|
+
return _deserialize_named_type(obj)
|
|
63
|
+
elif _is_object_property(obj):
|
|
64
|
+
return _deserialize_object_property(obj)
|
|
65
|
+
elif _is_function_type_parameter(obj):
|
|
66
|
+
return _deserialize_function_type_parameter(obj)
|
|
67
|
+
elif _is_param_type_node(obj):
|
|
68
|
+
return _deserialize_param_type_node(obj)
|
|
69
|
+
|
|
70
|
+
# Handle main node types based on "type" field
|
|
71
|
+
node_type = obj.get("type")
|
|
72
|
+
if not node_type or not isinstance(node_type, str):
|
|
73
|
+
return obj # Not an XLR node, return as-is
|
|
74
|
+
|
|
75
|
+
try:
|
|
76
|
+
return _deserialize_by_type(node_type, obj)
|
|
77
|
+
except Exception as e:
|
|
78
|
+
raise ValueError(f"Failed to deserialize node of type '{node_type}': {e}") from e
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _deserialize_by_type(node_type: str, obj: Dict[str, Any]) -> NodeType:
|
|
82
|
+
"""Deserialize based on the node type."""
|
|
83
|
+
type_map = {
|
|
84
|
+
"any": _deserialize_any_type,
|
|
85
|
+
"unknown": _deserialize_unknown_type,
|
|
86
|
+
"undefined": _deserialize_undefined_type,
|
|
87
|
+
"null": _deserialize_null_type,
|
|
88
|
+
"void": _deserialize_void_type,
|
|
89
|
+
"string": _deserialize_string_type,
|
|
90
|
+
"number": _deserialize_number_type,
|
|
91
|
+
"boolean": _deserialize_boolean_type,
|
|
92
|
+
"never": _deserialize_never_type,
|
|
93
|
+
"ref": _deserialize_ref_type,
|
|
94
|
+
"object": _deserialize_object_type,
|
|
95
|
+
"array": _deserialize_array_type,
|
|
96
|
+
"tuple": _deserialize_tuple_type,
|
|
97
|
+
"and": _deserialize_and_type,
|
|
98
|
+
"or": _deserialize_or_type,
|
|
99
|
+
"template": _deserialize_template_literal_type,
|
|
100
|
+
"record": _deserialize_record_type,
|
|
101
|
+
"function": _deserialize_function_type,
|
|
102
|
+
"conditional": _deserialize_conditional_type,
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
deserializer = type_map.get(node_type)
|
|
106
|
+
if not deserializer:
|
|
107
|
+
raise ValueError(f"Unknown node type: {node_type}")
|
|
108
|
+
|
|
109
|
+
return deserializer(obj)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
# Simple type deserializers
|
|
113
|
+
def _deserialize_any_type(obj: Dict[str, Any]) -> AnyType:
|
|
114
|
+
return AnyType(**_extract_common_props(obj))
|
|
115
|
+
|
|
116
|
+
def _deserialize_unknown_type(obj: Dict[str, Any]) -> UnknownType:
|
|
117
|
+
return UnknownType(**_extract_common_props(obj))
|
|
118
|
+
|
|
119
|
+
def _deserialize_undefined_type(obj: Dict[str, Any]) -> UndefinedType:
|
|
120
|
+
return UndefinedType(**_extract_common_props(obj))
|
|
121
|
+
|
|
122
|
+
def _deserialize_null_type(obj: Dict[str, Any]) -> NullType:
|
|
123
|
+
return NullType(**_extract_common_props(obj))
|
|
124
|
+
|
|
125
|
+
def _deserialize_void_type(obj: Dict[str, Any]) -> VoidType:
|
|
126
|
+
return VoidType(**_extract_common_props(obj))
|
|
127
|
+
|
|
128
|
+
def _deserialize_string_type(obj: Dict[str, Any]) -> StringType:
|
|
129
|
+
return StringType(**_extract_common_props(obj))
|
|
130
|
+
|
|
131
|
+
def _deserialize_number_type(obj: Dict[str, Any]) -> NumberType:
|
|
132
|
+
return NumberType(**_extract_common_props(obj))
|
|
133
|
+
|
|
134
|
+
def _deserialize_boolean_type(obj: Dict[str, Any]) -> BooleanType:
|
|
135
|
+
return BooleanType(**_extract_common_props(obj))
|
|
136
|
+
|
|
137
|
+
def _deserialize_never_type(obj: Dict[str, Any]) -> NeverType:
|
|
138
|
+
return NeverType(**_extract_common_props(obj))
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
# Complex type deserializers
|
|
142
|
+
def _deserialize_ref_type(obj: Dict[str, Any]) -> RefType:
|
|
143
|
+
kwargs = _extract_annotation_props(obj)
|
|
144
|
+
kwargs['ref'] = obj['ref']
|
|
145
|
+
if 'genericArguments' in obj:
|
|
146
|
+
kwargs['genericArguments'] = obj['genericArguments']
|
|
147
|
+
if 'property' in obj:
|
|
148
|
+
kwargs['property'] = obj['property']
|
|
149
|
+
return RefType(**kwargs)
|
|
150
|
+
|
|
151
|
+
def _deserialize_object_type(obj: Dict[str, Any]) -> ObjectType:
|
|
152
|
+
kwargs = _extract_common_props(obj)
|
|
153
|
+
kwargs['properties'] = obj.get('properties', {})
|
|
154
|
+
if 'extends' in obj:
|
|
155
|
+
kwargs['extends'] = obj['extends']
|
|
156
|
+
if 'additionalProperties' in obj:
|
|
157
|
+
kwargs['additionalProperties'] = obj['additionalProperties']
|
|
158
|
+
return ObjectType(**kwargs)
|
|
159
|
+
|
|
160
|
+
def _deserialize_array_type(obj: Dict[str, Any]) -> ArrayType:
|
|
161
|
+
kwargs = _extract_common_props(obj)
|
|
162
|
+
kwargs['elementType'] = obj['elementType']
|
|
163
|
+
return ArrayType(**kwargs)
|
|
164
|
+
|
|
165
|
+
def _deserialize_tuple_type(obj: Dict[str, Any]) -> TupleType:
|
|
166
|
+
kwargs = _extract_common_props(obj)
|
|
167
|
+
kwargs['elementTypes'] = obj['elementTypes']
|
|
168
|
+
kwargs['minItems'] = obj['minItems']
|
|
169
|
+
if 'additionalItems' in obj:
|
|
170
|
+
kwargs['additionalItems'] = obj['additionalItems']
|
|
171
|
+
return TupleType(**kwargs)
|
|
172
|
+
|
|
173
|
+
def _deserialize_and_type(obj: Dict[str, Any]) -> AndType:
|
|
174
|
+
kwargs = _extract_annotation_props(obj)
|
|
175
|
+
kwargs['and_types'] = obj.get('and', obj.get('and_types', []))
|
|
176
|
+
return AndType(**kwargs)
|
|
177
|
+
|
|
178
|
+
def _deserialize_or_type(obj: Dict[str, Any]) -> OrType:
|
|
179
|
+
kwargs = _extract_annotation_props(obj)
|
|
180
|
+
kwargs['or_types'] = obj.get('or', obj.get('or_types', []))
|
|
181
|
+
return OrType(**kwargs)
|
|
182
|
+
|
|
183
|
+
def _deserialize_template_literal_type(obj: Dict[str, Any]) -> TemplateLiteralType:
|
|
184
|
+
kwargs = _extract_annotation_props(obj)
|
|
185
|
+
kwargs['format'] = obj['format']
|
|
186
|
+
return TemplateLiteralType(**kwargs)
|
|
187
|
+
|
|
188
|
+
def _deserialize_record_type(obj: Dict[str, Any]) -> RecordType:
|
|
189
|
+
kwargs = _extract_annotation_props(obj)
|
|
190
|
+
kwargs['keyType'] = obj['keyType']
|
|
191
|
+
kwargs['valueType'] = obj['valueType']
|
|
192
|
+
return RecordType(**kwargs)
|
|
193
|
+
|
|
194
|
+
def _deserialize_function_type(obj: Dict[str, Any]) -> FunctionType:
|
|
195
|
+
kwargs = _extract_annotation_props(obj)
|
|
196
|
+
kwargs['parameters'] = obj.get('parameters', [])
|
|
197
|
+
if 'returnType' in obj:
|
|
198
|
+
kwargs['returnType'] = obj['returnType']
|
|
199
|
+
return FunctionType(**kwargs)
|
|
200
|
+
|
|
201
|
+
def _deserialize_conditional_type(obj: Dict[str, Any]) -> ConditionalType:
|
|
202
|
+
kwargs = _extract_annotation_props(obj)
|
|
203
|
+
kwargs['check'] = obj['check']
|
|
204
|
+
kwargs['value'] = obj['value']
|
|
205
|
+
return ConditionalType(**kwargs)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
# Helper class deserializers
|
|
209
|
+
def _deserialize_object_property(obj: Dict[str, Any]) -> ObjectProperty:
|
|
210
|
+
return ObjectProperty(
|
|
211
|
+
required=obj['required'],
|
|
212
|
+
node=obj['node']
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
def _deserialize_tuple_member(obj: Dict[str, Any]) -> TupleMember:
|
|
216
|
+
kwargs = {'type': obj['type']}
|
|
217
|
+
if 'name' in obj:
|
|
218
|
+
kwargs['name'] = obj['name']
|
|
219
|
+
if 'optional' in obj:
|
|
220
|
+
kwargs['optional'] = obj['optional']
|
|
221
|
+
return TupleMember(**kwargs)
|
|
222
|
+
|
|
223
|
+
def _deserialize_function_type_parameter(obj: Dict[str, Any]) -> FunctionTypeParameters:
|
|
224
|
+
kwargs = {
|
|
225
|
+
'name': obj['name'],
|
|
226
|
+
'type': obj['type']
|
|
227
|
+
}
|
|
228
|
+
if 'optional' in obj:
|
|
229
|
+
kwargs['optional'] = obj['optional']
|
|
230
|
+
if 'default' in obj:
|
|
231
|
+
kwargs['default'] = obj['default']
|
|
232
|
+
return FunctionTypeParameters(**kwargs)
|
|
233
|
+
|
|
234
|
+
def _deserialize_param_type_node(obj: Dict[str, Any]) -> ParamTypeNode:
|
|
235
|
+
kwargs = {'symbol': obj['symbol']}
|
|
236
|
+
if 'constraints' in obj:
|
|
237
|
+
kwargs['constraints'] = obj['constraints']
|
|
238
|
+
if 'default' in obj:
|
|
239
|
+
kwargs['default'] = obj['default']
|
|
240
|
+
return ParamTypeNode(**kwargs)
|
|
241
|
+
|
|
242
|
+
def _deserialize_named_type(obj: Dict[str, Any]) -> Union[NamedType, NamedTypeWithGenerics]:
|
|
243
|
+
# Extract the base node data (everything except name, source, and genericTokens)
|
|
244
|
+
base_obj = {
|
|
245
|
+
k: v for k,
|
|
246
|
+
v in obj.items() if k not in ['name', 'typeName', 'source', 'genericTokens']
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
# Extract annotation properties for the NamedType wrapper
|
|
250
|
+
annotation_kwargs = _extract_annotation_props(obj)
|
|
251
|
+
name = obj.get('name', obj.get('typeName', annotation_kwargs.get('name', "")))
|
|
252
|
+
if 'name' in annotation_kwargs:
|
|
253
|
+
del annotation_kwargs['name']
|
|
254
|
+
|
|
255
|
+
source = obj['source']
|
|
256
|
+
|
|
257
|
+
# Deserialize the base node using the object hook recursively
|
|
258
|
+
# We need to be careful not to create infinite recursion
|
|
259
|
+
base_node = _deserialize_object_hook(base_obj)
|
|
260
|
+
|
|
261
|
+
if 'genericTokens' in obj:
|
|
262
|
+
return NamedTypeWithGenerics(
|
|
263
|
+
base_node,
|
|
264
|
+
name,
|
|
265
|
+
source,
|
|
266
|
+
obj['genericTokens'],
|
|
267
|
+
**annotation_kwargs
|
|
268
|
+
)
|
|
269
|
+
else:
|
|
270
|
+
return NamedType(base_node, name, source, **annotation_kwargs)
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
# Helper functions for identifying object types
|
|
274
|
+
def _is_object_property(obj: Dict[str, Any]) -> bool:
|
|
275
|
+
return 'required' in obj and 'node' in obj and 'type' not in obj
|
|
276
|
+
|
|
277
|
+
def _is_tuple_member(obj: Dict[str, Any]) -> bool:
|
|
278
|
+
return 'type' in obj and \
|
|
279
|
+
('name' in obj or 'optional' in obj) and \
|
|
280
|
+
not isinstance(obj.get('type'), str)
|
|
281
|
+
|
|
282
|
+
def _is_function_type_parameter(obj: Dict[str, Any]) -> bool:
|
|
283
|
+
return 'name' in obj and 'type' in obj and \
|
|
284
|
+
('optional' in obj or 'default' in obj) and \
|
|
285
|
+
not isinstance(obj.get('type'), str)
|
|
286
|
+
|
|
287
|
+
def _is_param_type_node(obj: Dict[str, Any]) -> bool:
|
|
288
|
+
return 'symbol' in obj and ('constraints' in obj or 'default' in obj)
|
|
289
|
+
|
|
290
|
+
def _is_named_type(obj: Dict[str, Any]) -> bool:
|
|
291
|
+
return 'name' in obj and 'source' in obj
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
# Property extraction helpers
|
|
295
|
+
def _extract_annotation_props(obj: Dict[str, Any]) -> Dict[str, Any]:
|
|
296
|
+
"""Extract annotation properties from object."""
|
|
297
|
+
annotation_keys = [
|
|
298
|
+
'name',
|
|
299
|
+
'title',
|
|
300
|
+
'description',
|
|
301
|
+
'examples',
|
|
302
|
+
'default',
|
|
303
|
+
'see',
|
|
304
|
+
'comment',
|
|
305
|
+
'meta'
|
|
306
|
+
]
|
|
307
|
+
return {k: v for k, v in obj.items() if k in annotation_keys}
|
|
308
|
+
|
|
309
|
+
def _extract_common_props(obj: Dict[str, Any]) -> Dict[str, Any]:
|
|
310
|
+
"""Extract common properties (annotations + const + enum) from object."""
|
|
311
|
+
props = _extract_annotation_props(obj)
|
|
312
|
+
if 'const' in obj:
|
|
313
|
+
props['const'] = obj['const']
|
|
314
|
+
if 'enum' in obj:
|
|
315
|
+
props['enum'] = obj['enum']
|
|
316
|
+
return props
|
xlr_lib_types/guards.py
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Type Guard Functions that provide type narrowing capabilities for TypeScript-like type checking
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import TypeGuard, Any, Union
|
|
6
|
+
from .nodes import (
|
|
7
|
+
AndType,
|
|
8
|
+
AnyType,
|
|
9
|
+
ArrayNode,
|
|
10
|
+
ArrayType,
|
|
11
|
+
BooleanType,
|
|
12
|
+
ConditionalNode,
|
|
13
|
+
ConditionalType,
|
|
14
|
+
FunctionType,
|
|
15
|
+
NamedType,
|
|
16
|
+
NamedTypeWithGenerics,
|
|
17
|
+
NeverType,
|
|
18
|
+
NodeType,
|
|
19
|
+
NullType,
|
|
20
|
+
NumberType,
|
|
21
|
+
ObjectNode,
|
|
22
|
+
ObjectType,
|
|
23
|
+
OrType,
|
|
24
|
+
PrimitiveTypes,
|
|
25
|
+
RecordType,
|
|
26
|
+
RefNode,
|
|
27
|
+
RefType,
|
|
28
|
+
StringType,
|
|
29
|
+
TemplateLiteralType,
|
|
30
|
+
TupleNode,
|
|
31
|
+
TupleType,
|
|
32
|
+
TypeNode,
|
|
33
|
+
UndefinedType,
|
|
34
|
+
UnknownType,
|
|
35
|
+
VoidType
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def is_any_type(obj: Any) -> TypeGuard[AnyType]:
|
|
40
|
+
"""Type guard for AnyType nodes."""
|
|
41
|
+
return isinstance(obj, AnyType)
|
|
42
|
+
|
|
43
|
+
def is_unknown_type(obj: Any) -> TypeGuard[UnknownType]:
|
|
44
|
+
"""Type guard for UnknownType nodes."""
|
|
45
|
+
return isinstance(obj, UnknownType)
|
|
46
|
+
|
|
47
|
+
def is_undefined_type(obj: Any) -> TypeGuard[UndefinedType]:
|
|
48
|
+
"""Type guard for UndefinedType nodes."""
|
|
49
|
+
return isinstance(obj, UndefinedType)
|
|
50
|
+
|
|
51
|
+
def is_null_type(obj: Any) -> TypeGuard[NullType]:
|
|
52
|
+
"""Type guard for NullType nodes."""
|
|
53
|
+
return isinstance(obj, NullType)
|
|
54
|
+
|
|
55
|
+
def is_void_type(obj: Any) -> TypeGuard[VoidType]:
|
|
56
|
+
"""Type guard for VoidType nodes."""
|
|
57
|
+
return isinstance(obj, VoidType)
|
|
58
|
+
|
|
59
|
+
def is_string_type(obj: Any) -> TypeGuard[StringType]:
|
|
60
|
+
"""Type guard for StringType nodes."""
|
|
61
|
+
return isinstance(obj, StringType)
|
|
62
|
+
|
|
63
|
+
def is_number_type(obj: Any) -> TypeGuard[NumberType]:
|
|
64
|
+
"""Type guard for NumberType nodes."""
|
|
65
|
+
return isinstance(obj, NumberType)
|
|
66
|
+
|
|
67
|
+
def is_boolean_type(obj: Any) -> TypeGuard[BooleanType]:
|
|
68
|
+
"""Type guard for BooleanType nodes."""
|
|
69
|
+
return isinstance(obj, BooleanType)
|
|
70
|
+
|
|
71
|
+
def is_never_type(obj: Any) -> TypeGuard[NeverType]:
|
|
72
|
+
"""Type guard for NeverType nodes."""
|
|
73
|
+
return isinstance(obj, NeverType)
|
|
74
|
+
|
|
75
|
+
def is_ref_node(obj: Any) -> TypeGuard[RefNode]:
|
|
76
|
+
"""Type guard for RefNode nodes."""
|
|
77
|
+
return isinstance(obj, RefNode)
|
|
78
|
+
|
|
79
|
+
def is_ref_type(obj: Any) -> TypeGuard[RefType]:
|
|
80
|
+
"""Type guard for RefType nodes."""
|
|
81
|
+
return isinstance(obj, RefType)
|
|
82
|
+
|
|
83
|
+
def is_object_node(obj: Any) -> TypeGuard[ObjectNode]:
|
|
84
|
+
"""Type guard for ObjectNode nodes."""
|
|
85
|
+
return isinstance(obj, ObjectNode)
|
|
86
|
+
|
|
87
|
+
def is_object_type(obj: Any) -> TypeGuard[ObjectType]:
|
|
88
|
+
"""Type guard for ObjectType nodes."""
|
|
89
|
+
return isinstance(obj, ObjectType) or (is_named_type(obj) and is_object_type(obj.base_node))
|
|
90
|
+
|
|
91
|
+
def is_array_node(obj: Any) -> TypeGuard[ArrayNode]:
|
|
92
|
+
"""Type guard for ArrayNode nodes."""
|
|
93
|
+
return isinstance(obj, ArrayNode)
|
|
94
|
+
|
|
95
|
+
def is_array_type(obj: Any) -> TypeGuard[ArrayType]:
|
|
96
|
+
"""Type guard for ArrayType nodes."""
|
|
97
|
+
return isinstance(obj, ArrayType) or (is_named_type(obj) and is_array_type(obj.base_node))
|
|
98
|
+
|
|
99
|
+
def is_conditional_node(obj: Any) -> TypeGuard[ConditionalNode]:
|
|
100
|
+
"""Type guard for ConditionalNode nodes."""
|
|
101
|
+
return isinstance(obj, ConditionalNode)
|
|
102
|
+
|
|
103
|
+
def is_conditional_type(obj: Any) -> TypeGuard[ConditionalType]:
|
|
104
|
+
"""Type guard for ConditionalType nodes."""
|
|
105
|
+
return isinstance(obj, ConditionalType)
|
|
106
|
+
|
|
107
|
+
def is_tuple_node(obj: Any) -> TypeGuard[TupleNode]:
|
|
108
|
+
"""Type guard for TupleNode nodes."""
|
|
109
|
+
return isinstance(obj, TupleNode)
|
|
110
|
+
|
|
111
|
+
def is_tuple_type(obj: Any) -> TypeGuard[TupleType]:
|
|
112
|
+
"""Type guard for TupleType nodes."""
|
|
113
|
+
return isinstance(obj, TupleType)
|
|
114
|
+
|
|
115
|
+
def is_and_type(obj: Any) -> TypeGuard[AndType]:
|
|
116
|
+
"""Type guard for AndType (intersection) nodes."""
|
|
117
|
+
return isinstance(obj, AndType)
|
|
118
|
+
|
|
119
|
+
def is_or_type(obj: Any) -> TypeGuard[OrType]:
|
|
120
|
+
"""Type guard for OrType (union) nodes."""
|
|
121
|
+
return isinstance(obj, OrType) or (is_named_type(obj) and is_or_type(obj.base_node))
|
|
122
|
+
|
|
123
|
+
def is_template_literal_type(obj: Any) -> TypeGuard[TemplateLiteralType]:
|
|
124
|
+
"""Type guard for TemplateLiteralType nodes."""
|
|
125
|
+
return isinstance(obj, TemplateLiteralType)
|
|
126
|
+
|
|
127
|
+
def is_record_type(obj: Any) -> TypeGuard[RecordType]:
|
|
128
|
+
"""Type guard for RecordType nodes."""
|
|
129
|
+
return isinstance(obj, RecordType)
|
|
130
|
+
|
|
131
|
+
def is_function_type(obj: Any) -> TypeGuard[FunctionType]:
|
|
132
|
+
"""Type guard for FunctionType nodes."""
|
|
133
|
+
return isinstance(obj, FunctionType)
|
|
134
|
+
|
|
135
|
+
def is_type_node(obj: Any) -> TypeGuard[TypeNode]:
|
|
136
|
+
"""Type guard for any TypeNode (base class)."""
|
|
137
|
+
return isinstance(obj, TypeNode)
|
|
138
|
+
|
|
139
|
+
def is_node_type(obj: Any) -> TypeGuard[NodeType]:
|
|
140
|
+
"""Type guard for any NodeType union member."""
|
|
141
|
+
return (is_any_type(obj) or is_unknown_type(obj) or is_undefined_type(obj) or
|
|
142
|
+
is_null_type(obj) or is_never_type(obj) or is_string_type(obj) or
|
|
143
|
+
is_template_literal_type(obj) or is_number_type(obj) or is_boolean_type(obj) or
|
|
144
|
+
is_object_type(obj) or is_array_type(obj) or is_tuple_type(obj) or
|
|
145
|
+
is_record_type(obj) or is_and_type(obj) or is_or_type(obj) or
|
|
146
|
+
is_ref_type(obj) or is_function_type(obj) or is_conditional_type(obj) or
|
|
147
|
+
is_void_type(obj))
|
|
148
|
+
|
|
149
|
+
def is_named_type(obj: Any) -> TypeGuard[NamedType]:
|
|
150
|
+
""" Type guard for NamedType nodes."""
|
|
151
|
+
return isinstance(obj, NamedType) or isinstance(obj, NamedTypeWithGenerics)
|
|
152
|
+
|
|
153
|
+
def is_named_type_with_generics(obj:Any) -> TypeGuard[NamedTypeWithGenerics]:
|
|
154
|
+
""" Type guard for NamedTypeWithGeneric nodes."""
|
|
155
|
+
return isinstance(obj, NamedTypeWithGenerics)
|
|
156
|
+
|
|
157
|
+
def is_primitive_type(obj:Any) -> TypeGuard[PrimitiveTypes]:
|
|
158
|
+
""" Type guard for Primitive nodes."""
|
|
159
|
+
return is_never_type(obj) or \
|
|
160
|
+
is_null_type(obj) or \
|
|
161
|
+
is_string_type(obj) or \
|
|
162
|
+
is_number_type(obj) or \
|
|
163
|
+
is_boolean_type(obj) or \
|
|
164
|
+
is_any_type(obj) or \
|
|
165
|
+
is_unknown_type(obj) or \
|
|
166
|
+
is_undefined_type(obj) or \
|
|
167
|
+
is_void_type(obj)
|
|
168
|
+
|
|
169
|
+
def is_primitive_const(obj:Any) -> TypeGuard[Union[StringType, NumberType, BooleanType]]:
|
|
170
|
+
""" Type guard for Primitive nodes with const values."""
|
|
171
|
+
return is_primitive_type(obj) and obj.const is not None
|
xlr_lib_types/nodes.py
ADDED
|
@@ -0,0 +1,895 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Python equivalent of TypeScript interfaces for XLR Nodes
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Any, Dict, List, Mapping, Optional, Union, Generic, TypeVar
|
|
6
|
+
|
|
7
|
+
T = TypeVar('T', bound='TypeNode')
|
|
8
|
+
|
|
9
|
+
class Annotations:
|
|
10
|
+
"""The name used to reference this type"""
|
|
11
|
+
|
|
12
|
+
def __init__(self,
|
|
13
|
+
name: Optional[str] = None,
|
|
14
|
+
title: Optional[str] = None,
|
|
15
|
+
description: Optional[str] = None,
|
|
16
|
+
examples: Optional[Union[str, List[str]]] = None,
|
|
17
|
+
default: Optional[str] = None,
|
|
18
|
+
see: Optional[Union[str, List[str]]] = None,
|
|
19
|
+
comment: Optional[str] = None,
|
|
20
|
+
meta: Optional[Dict[str, str]] = None):
|
|
21
|
+
self._name = name
|
|
22
|
+
self._title = title
|
|
23
|
+
self._description = description
|
|
24
|
+
self._examples = examples
|
|
25
|
+
self._default = default
|
|
26
|
+
self._see = see
|
|
27
|
+
self._comment = comment
|
|
28
|
+
self._meta = meta
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def name(self) -> Optional[str]:
|
|
32
|
+
"""The name used to reference this type"""
|
|
33
|
+
return self._name
|
|
34
|
+
|
|
35
|
+
@name.setter
|
|
36
|
+
def name(self, value: Optional[str]) -> None:
|
|
37
|
+
self._name = value
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def title(self) -> Optional[str]:
|
|
41
|
+
"""The path within a type to this type (may be the same as `name`)"""
|
|
42
|
+
return self._title
|
|
43
|
+
|
|
44
|
+
@title.setter
|
|
45
|
+
def title(self, value: Optional[str]) -> None:
|
|
46
|
+
self._title = value
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def description(self) -> Optional[str]:
|
|
50
|
+
"""The JSDoc string for this type"""
|
|
51
|
+
return self._description
|
|
52
|
+
|
|
53
|
+
@description.setter
|
|
54
|
+
def description(self, value: Optional[str]) -> None:
|
|
55
|
+
self._description = value
|
|
56
|
+
|
|
57
|
+
@property
|
|
58
|
+
def examples(self) -> Optional[Union[str, List[str]]]:
|
|
59
|
+
"""The JSDoc `@example` string for this type"""
|
|
60
|
+
return self._examples
|
|
61
|
+
|
|
62
|
+
@examples.setter
|
|
63
|
+
def examples(self, value: Optional[Union[str, List[str]]]) -> None:
|
|
64
|
+
self._examples = value
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def default(self) -> Optional[str]:
|
|
68
|
+
"""The JSDoc `@default` string for this type"""
|
|
69
|
+
return self._default
|
|
70
|
+
|
|
71
|
+
@default.setter
|
|
72
|
+
def default(self, value: Optional[str]) -> None:
|
|
73
|
+
self._default = value
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def see(self) -> Optional[Union[str, List[str]]]:
|
|
77
|
+
"""The JSDoc `@see` string for this type"""
|
|
78
|
+
return self._see
|
|
79
|
+
|
|
80
|
+
@see.setter
|
|
81
|
+
def see(self, value: Optional[Union[str, List[str]]]) -> None:
|
|
82
|
+
self._see = value
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def comment(self) -> Optional[str]:
|
|
86
|
+
"""The Typescript comment associated with the type"""
|
|
87
|
+
return self._comment
|
|
88
|
+
|
|
89
|
+
@comment.setter
|
|
90
|
+
def comment(self, value: Optional[str]) -> None:
|
|
91
|
+
self._comment = value
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def meta(self) -> Optional[Dict[str, str]]:
|
|
95
|
+
"""The JSDoc `@meta` string for this type"""
|
|
96
|
+
return self._meta
|
|
97
|
+
|
|
98
|
+
@meta.setter
|
|
99
|
+
def meta(self, value: Optional[Dict[str, str]]) -> None:
|
|
100
|
+
self._meta = value
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class Const:
|
|
104
|
+
"""Generic const interface"""
|
|
105
|
+
|
|
106
|
+
def __init__(self, const: Optional[Any] = None):
|
|
107
|
+
self._const = const
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def const(self) -> Optional[Any]:
|
|
111
|
+
"""The literal value for the node"""
|
|
112
|
+
return self._const
|
|
113
|
+
|
|
114
|
+
@const.setter
|
|
115
|
+
def const(self, value: Optional[Any]) -> None:
|
|
116
|
+
self._const = value
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class Enum:
|
|
120
|
+
"""Generic enum interface"""
|
|
121
|
+
|
|
122
|
+
def __init__(self, enum: Optional[List[Any]] = None):
|
|
123
|
+
self._enum = enum
|
|
124
|
+
|
|
125
|
+
@property
|
|
126
|
+
def enum(self) -> Optional[List[Any]]:
|
|
127
|
+
"""The list of enums for the node"""
|
|
128
|
+
return self._enum
|
|
129
|
+
|
|
130
|
+
@enum.setter
|
|
131
|
+
def enum(self, value: Optional[List[Any]]) -> None:
|
|
132
|
+
self._enum = value
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class CommonTypeInfo(Const, Enum):
|
|
136
|
+
"""Common type information combining Const and Enum"""
|
|
137
|
+
|
|
138
|
+
def __init__(self, const: Optional[Any] = None, enum: Optional[List[Any]] = None):
|
|
139
|
+
Const.__init__(self, const)
|
|
140
|
+
Enum.__init__(self, enum)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class TypeNode:
|
|
144
|
+
"""Base type node with type identifier"""
|
|
145
|
+
|
|
146
|
+
def __init__(self, type_name: str):
|
|
147
|
+
self._type = type_name
|
|
148
|
+
|
|
149
|
+
@property
|
|
150
|
+
def type(self) -> str:
|
|
151
|
+
"""The type of Node"""
|
|
152
|
+
return self._type
|
|
153
|
+
|
|
154
|
+
@type.setter
|
|
155
|
+
def type(self, value: str) -> None:
|
|
156
|
+
self._type = value
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class AnyType(TypeNode, CommonTypeInfo, Annotations):
|
|
160
|
+
"""Any type implementation"""
|
|
161
|
+
|
|
162
|
+
def __init__(self, **kwargs):
|
|
163
|
+
TypeNode.__init__(self, "any")
|
|
164
|
+
CommonTypeInfo.__init__(self, kwargs.get('const'), kwargs.get('enum'))
|
|
165
|
+
Annotations.__init__(self,
|
|
166
|
+
**{k: v for k, v in kwargs.items() if k not in ['const', 'enum']}
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
class UnknownType(TypeNode, CommonTypeInfo, Annotations):
|
|
171
|
+
"""Unknown type implementation"""
|
|
172
|
+
|
|
173
|
+
def __init__(self, **kwargs):
|
|
174
|
+
TypeNode.__init__(self, "unknown")
|
|
175
|
+
CommonTypeInfo.__init__(self, kwargs.get('const'), kwargs.get('enum'))
|
|
176
|
+
Annotations.__init__(self,
|
|
177
|
+
**{k: v for k, v in kwargs.items() if k not in ['const', 'enum']}
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
class UndefinedType(TypeNode, CommonTypeInfo, Annotations):
|
|
182
|
+
"""Undefined type implementation"""
|
|
183
|
+
|
|
184
|
+
def __init__(self, **kwargs):
|
|
185
|
+
TypeNode.__init__(self, "undefined")
|
|
186
|
+
CommonTypeInfo.__init__(self, kwargs.get('const'), kwargs.get('enum'))
|
|
187
|
+
Annotations.__init__(self,
|
|
188
|
+
**{k: v for k, v in kwargs.items() if k not in ['const', 'enum']}
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
class NullType(TypeNode, CommonTypeInfo, Annotations):
|
|
193
|
+
"""Null type implementation"""
|
|
194
|
+
|
|
195
|
+
def __init__(self, **kwargs):
|
|
196
|
+
TypeNode.__init__(self, "null")
|
|
197
|
+
CommonTypeInfo.__init__(self, kwargs.get('const'), kwargs.get('enum'))
|
|
198
|
+
Annotations.__init__(self,
|
|
199
|
+
**{k: v for k, v in kwargs.items() if k not in ['const', 'enum']}
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
class VoidType(TypeNode, CommonTypeInfo, Annotations):
|
|
204
|
+
"""Void type implementation"""
|
|
205
|
+
|
|
206
|
+
def __init__(self, **kwargs):
|
|
207
|
+
TypeNode.__init__(self, "void")
|
|
208
|
+
CommonTypeInfo.__init__(self, kwargs.get('const'), kwargs.get('enum'))
|
|
209
|
+
Annotations.__init__(self,
|
|
210
|
+
**{k: v for k, v in kwargs.items() if k not in ['const', 'enum']}
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
class StringType(TypeNode, CommonTypeInfo, Annotations):
|
|
215
|
+
"""String type implementation"""
|
|
216
|
+
|
|
217
|
+
def __init__(self, **kwargs):
|
|
218
|
+
TypeNode.__init__(self, "string")
|
|
219
|
+
CommonTypeInfo.__init__(self, kwargs.get('const'), kwargs.get('enum'))
|
|
220
|
+
Annotations.__init__(self,
|
|
221
|
+
**{k: v for k, v in kwargs.items() if k not in ['const', 'enum']}
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
class NumberType(TypeNode, CommonTypeInfo, Annotations):
|
|
226
|
+
"""Number type implementation"""
|
|
227
|
+
|
|
228
|
+
def __init__(self, **kwargs):
|
|
229
|
+
TypeNode.__init__(self, "number")
|
|
230
|
+
CommonTypeInfo.__init__(self, kwargs.get('const'), kwargs.get('enum'))
|
|
231
|
+
Annotations.__init__(self,
|
|
232
|
+
**{k: v for k, v in kwargs.items() if k not in ['const', 'enum']}
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
class BooleanType(TypeNode, CommonTypeInfo, Annotations):
|
|
237
|
+
"""Boolean type implementation"""
|
|
238
|
+
|
|
239
|
+
def __init__(self, **kwargs):
|
|
240
|
+
TypeNode.__init__(self, "boolean")
|
|
241
|
+
CommonTypeInfo.__init__(self, kwargs.get('const'), kwargs.get('enum'))
|
|
242
|
+
Annotations.__init__(self,
|
|
243
|
+
**{k: v for k, v in kwargs.items() if k not in ['const', 'enum']}
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
class NeverType(TypeNode, CommonTypeInfo, Annotations):
|
|
248
|
+
"""Never type implementation"""
|
|
249
|
+
|
|
250
|
+
def __init__(self, **kwargs):
|
|
251
|
+
TypeNode.__init__(self, "never")
|
|
252
|
+
CommonTypeInfo.__init__(self, kwargs.get('const'), kwargs.get('enum'))
|
|
253
|
+
Annotations.__init__(self,
|
|
254
|
+
**{k: v for k, v in kwargs.items() if k not in ['const', 'enum']}
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
class RefNode(TypeNode):
|
|
259
|
+
"""Reference node implementation"""
|
|
260
|
+
|
|
261
|
+
def __init__(
|
|
262
|
+
self,
|
|
263
|
+
ref: str,
|
|
264
|
+
genericArguments: Optional[List['NodeType']] = None,
|
|
265
|
+
property: Optional[str] = None
|
|
266
|
+
):
|
|
267
|
+
super().__init__("ref")
|
|
268
|
+
self._ref = ref
|
|
269
|
+
self._genericArguments = genericArguments
|
|
270
|
+
self._property = property
|
|
271
|
+
|
|
272
|
+
@property
|
|
273
|
+
def ref(self) -> str:
|
|
274
|
+
"""Name of the referenced Type"""
|
|
275
|
+
return self._ref
|
|
276
|
+
|
|
277
|
+
@ref.setter
|
|
278
|
+
def ref(self, value: str) -> None:
|
|
279
|
+
self._ref = value
|
|
280
|
+
|
|
281
|
+
@property
|
|
282
|
+
def genericArguments(self) -> Optional[List['NodeType']]:
|
|
283
|
+
"""Parameters to potentially fill in a generic when it is resolved"""
|
|
284
|
+
return self._genericArguments
|
|
285
|
+
|
|
286
|
+
@genericArguments.setter
|
|
287
|
+
def genericArguments(self, value: Optional[List['NodeType']]) -> None:
|
|
288
|
+
self._genericArguments = value
|
|
289
|
+
|
|
290
|
+
@property
|
|
291
|
+
def property(self) -> Optional[str]:
|
|
292
|
+
"""Optional property to access when the reference is resolved"""
|
|
293
|
+
return self._property
|
|
294
|
+
|
|
295
|
+
@property.setter
|
|
296
|
+
def property(self, value: Optional[str]) -> None:
|
|
297
|
+
self._property = value
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
class RefType(RefNode, Annotations):
|
|
301
|
+
"""Reference type with annotations"""
|
|
302
|
+
|
|
303
|
+
def __init__(
|
|
304
|
+
self,
|
|
305
|
+
ref: str,
|
|
306
|
+
genericArguments: Optional[List['NodeType']] = None,
|
|
307
|
+
property: Optional[str] = None,
|
|
308
|
+
**kwargs
|
|
309
|
+
):
|
|
310
|
+
RefNode.__init__(self, ref, genericArguments, property)
|
|
311
|
+
Annotations.__init__(self, **kwargs)
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
class ObjectProperty:
|
|
315
|
+
"""Object property definition"""
|
|
316
|
+
|
|
317
|
+
def __init__(self, required: bool, node: 'NodeType'):
|
|
318
|
+
self._required = required
|
|
319
|
+
self._node = node
|
|
320
|
+
|
|
321
|
+
@property
|
|
322
|
+
def required(self) -> bool:
|
|
323
|
+
"""If this property is required"""
|
|
324
|
+
return self._required
|
|
325
|
+
|
|
326
|
+
@required.setter
|
|
327
|
+
def required(self, value: bool) -> None:
|
|
328
|
+
self._required = value
|
|
329
|
+
|
|
330
|
+
@property
|
|
331
|
+
def node(self) -> 'NodeType':
|
|
332
|
+
"""The type of the property"""
|
|
333
|
+
return self._node
|
|
334
|
+
|
|
335
|
+
@node.setter
|
|
336
|
+
def node(self, value: 'NodeType') -> None:
|
|
337
|
+
self._node = value
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
class ObjectNode(TypeNode):
|
|
341
|
+
"""Object node implementation"""
|
|
342
|
+
|
|
343
|
+
def __init__(
|
|
344
|
+
self,
|
|
345
|
+
properties: Dict[str, ObjectProperty],
|
|
346
|
+
extends: Optional[RefType] = None,
|
|
347
|
+
additionalProperties: Union[bool, 'NodeType'] = False
|
|
348
|
+
):
|
|
349
|
+
super().__init__("object")
|
|
350
|
+
self._properties = properties
|
|
351
|
+
self._extends = extends
|
|
352
|
+
self._additionalProperties = additionalProperties
|
|
353
|
+
|
|
354
|
+
@property
|
|
355
|
+
def properties(self) -> Dict[str, ObjectProperty]:
|
|
356
|
+
"""The properties associated with an object"""
|
|
357
|
+
return self._properties
|
|
358
|
+
|
|
359
|
+
@properties.setter
|
|
360
|
+
def properties(self, value: Dict[str, ObjectProperty]) -> None:
|
|
361
|
+
self._properties = value
|
|
362
|
+
|
|
363
|
+
@property
|
|
364
|
+
def extends(self) -> Optional[RefType]:
|
|
365
|
+
"""A custom primitive that this object extends that is to be resolved when used"""
|
|
366
|
+
return self._extends
|
|
367
|
+
|
|
368
|
+
@extends.setter
|
|
369
|
+
def extends(self, value: Optional[RefType]) -> None:
|
|
370
|
+
self._extends = value
|
|
371
|
+
|
|
372
|
+
@property
|
|
373
|
+
def additionalProperties(self) -> Union[bool, 'NodeType']:
|
|
374
|
+
"""What type, if any, of additional properties are allowed on the object"""
|
|
375
|
+
return self._additionalProperties
|
|
376
|
+
|
|
377
|
+
@additionalProperties.setter
|
|
378
|
+
def additionalProperties(self, value: Union[bool, 'NodeType']) -> None:
|
|
379
|
+
self._additionalProperties = value
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
class ObjectType(ObjectNode, CommonTypeInfo, Annotations):
|
|
383
|
+
"""Object type with annotations"""
|
|
384
|
+
|
|
385
|
+
def __init__(
|
|
386
|
+
self,
|
|
387
|
+
properties: Dict[str, ObjectProperty],
|
|
388
|
+
extends: Optional[RefType] = None,
|
|
389
|
+
additionalProperties: Union[bool, 'NodeType'] = False,
|
|
390
|
+
**kwargs
|
|
391
|
+
):
|
|
392
|
+
ObjectNode.__init__(self, properties, extends, additionalProperties)
|
|
393
|
+
CommonTypeInfo.__init__(self, kwargs.get('const'), kwargs.get('enum'))
|
|
394
|
+
Annotations.__init__(self,
|
|
395
|
+
**{k: v for k, v in kwargs.items() if k not in ['const', 'enum']}
|
|
396
|
+
)
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
class ArrayNode(TypeNode):
|
|
400
|
+
"""Array node implementation"""
|
|
401
|
+
|
|
402
|
+
def __init__(self, elementType: 'NodeType'):
|
|
403
|
+
super().__init__("array")
|
|
404
|
+
self._elementType = elementType
|
|
405
|
+
|
|
406
|
+
@property
|
|
407
|
+
def elementType(self) -> 'NodeType':
|
|
408
|
+
"""What types are allowed in the array"""
|
|
409
|
+
return self._elementType
|
|
410
|
+
|
|
411
|
+
@elementType.setter
|
|
412
|
+
def elementType(self, value: 'NodeType') -> None:
|
|
413
|
+
self._elementType = value
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
class ArrayType(ArrayNode, CommonTypeInfo, Annotations):
|
|
417
|
+
"""Array type with annotations"""
|
|
418
|
+
|
|
419
|
+
def __init__(self, elementType: 'NodeType', **kwargs):
|
|
420
|
+
ArrayNode.__init__(self, elementType)
|
|
421
|
+
CommonTypeInfo.__init__(self, kwargs.get('const'), kwargs.get('enum'))
|
|
422
|
+
Annotations.__init__(self,
|
|
423
|
+
**{k: v for k, v in kwargs.items() if k not in ['const', 'enum']}
|
|
424
|
+
)
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
class ConditionalNode(TypeNode):
|
|
428
|
+
"""Conditional node implementation"""
|
|
429
|
+
|
|
430
|
+
def __init__(self, check: Mapping[str, 'NodeType'], value: Mapping[str, 'NodeType']):
|
|
431
|
+
super().__init__("conditional")
|
|
432
|
+
self._check = check
|
|
433
|
+
self._value = value
|
|
434
|
+
|
|
435
|
+
@property
|
|
436
|
+
def check(self) -> Mapping[str, 'NodeType']:
|
|
437
|
+
"""The check arguments"""
|
|
438
|
+
return self._check
|
|
439
|
+
|
|
440
|
+
@check.setter
|
|
441
|
+
def check(self, value: Mapping[str, 'NodeType']) -> None:
|
|
442
|
+
self._check = value
|
|
443
|
+
|
|
444
|
+
@property
|
|
445
|
+
def value(self) -> Mapping[str, 'NodeType']:
|
|
446
|
+
"""The resulting values to use"""
|
|
447
|
+
return self._value
|
|
448
|
+
|
|
449
|
+
@value.setter
|
|
450
|
+
def value(self, value: Mapping[str, 'NodeType']) -> None:
|
|
451
|
+
self._value = value
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
class ConditionalType(ConditionalNode, Annotations):
|
|
455
|
+
"""Conditional type with annotations"""
|
|
456
|
+
|
|
457
|
+
def __init__(self, check: Mapping[str, 'NodeType'], value: Mapping[str, 'NodeType'], **kwargs):
|
|
458
|
+
ConditionalNode.__init__(self, check, value)
|
|
459
|
+
Annotations.__init__(self, **kwargs)
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
class TupleMember:
|
|
463
|
+
"""Tuple member definition"""
|
|
464
|
+
|
|
465
|
+
def __init__(
|
|
466
|
+
self,
|
|
467
|
+
type: 'NodeType',
|
|
468
|
+
name: Optional[str] = None,
|
|
469
|
+
optional: Optional[bool] = None
|
|
470
|
+
):
|
|
471
|
+
self._name = name
|
|
472
|
+
self._type = type
|
|
473
|
+
self._optional = optional
|
|
474
|
+
|
|
475
|
+
@property
|
|
476
|
+
def name(self) -> Optional[str]:
|
|
477
|
+
"""Optional Name of the Tuple Member"""
|
|
478
|
+
return self._name
|
|
479
|
+
|
|
480
|
+
@name.setter
|
|
481
|
+
def name(self, value: Optional[str]) -> None:
|
|
482
|
+
self._name = value
|
|
483
|
+
|
|
484
|
+
@property
|
|
485
|
+
def type(self) -> 'NodeType':
|
|
486
|
+
"""Type constraint of the Tuple Member"""
|
|
487
|
+
return self._type
|
|
488
|
+
|
|
489
|
+
@type.setter
|
|
490
|
+
def type(self, value: 'NodeType') -> None:
|
|
491
|
+
self._type = value
|
|
492
|
+
|
|
493
|
+
@property
|
|
494
|
+
def optional(self) -> Optional[bool]:
|
|
495
|
+
"""Is the Tuple Member Optional"""
|
|
496
|
+
return self._optional
|
|
497
|
+
|
|
498
|
+
@optional.setter
|
|
499
|
+
def optional(self, value: Optional[bool]) -> None:
|
|
500
|
+
self._optional = value
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
class TupleNode(TypeNode):
|
|
504
|
+
"""Tuple node implementation"""
|
|
505
|
+
|
|
506
|
+
def __init__(
|
|
507
|
+
self,
|
|
508
|
+
elementTypes: List[TupleMember],
|
|
509
|
+
minItems: int,
|
|
510
|
+
additionalItems: Union[bool, 'NodeType'] = False
|
|
511
|
+
):
|
|
512
|
+
super().__init__("tuple")
|
|
513
|
+
self._elementTypes = elementTypes
|
|
514
|
+
self._minItems = minItems
|
|
515
|
+
self._additionalItems = additionalItems
|
|
516
|
+
|
|
517
|
+
@property
|
|
518
|
+
def elementTypes(self) -> List[TupleMember]:
|
|
519
|
+
"""The types in the tuple"""
|
|
520
|
+
return self._elementTypes
|
|
521
|
+
|
|
522
|
+
@elementTypes.setter
|
|
523
|
+
def elementTypes(self, value: List[TupleMember]) -> None:
|
|
524
|
+
self._elementTypes = value
|
|
525
|
+
|
|
526
|
+
@property
|
|
527
|
+
def minItems(self) -> int:
|
|
528
|
+
"""The minimum number of items"""
|
|
529
|
+
return self._minItems
|
|
530
|
+
|
|
531
|
+
@minItems.setter
|
|
532
|
+
def minItems(self, value: int) -> None:
|
|
533
|
+
self._minItems = value
|
|
534
|
+
|
|
535
|
+
@property
|
|
536
|
+
def additionalItems(self) -> Union[bool, 'NodeType']:
|
|
537
|
+
"""What, if any, additional types can be provided"""
|
|
538
|
+
return self._additionalItems
|
|
539
|
+
|
|
540
|
+
@additionalItems.setter
|
|
541
|
+
def additionalItems(self, value: Union[bool, 'NodeType']) -> None:
|
|
542
|
+
self._additionalItems = value
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
class TupleType(TupleNode, CommonTypeInfo, Annotations):
|
|
546
|
+
"""Tuple type with annotations"""
|
|
547
|
+
|
|
548
|
+
def __init__(
|
|
549
|
+
self,
|
|
550
|
+
elementTypes: List[TupleMember],
|
|
551
|
+
minItems: int,
|
|
552
|
+
additionalItems: Union[bool, 'NodeType'] = False,
|
|
553
|
+
**kwargs
|
|
554
|
+
):
|
|
555
|
+
TupleNode.__init__(self, elementTypes, minItems, additionalItems)
|
|
556
|
+
CommonTypeInfo.__init__(self, kwargs.get('const'), kwargs.get('enum'))
|
|
557
|
+
Annotations.__init__(self,
|
|
558
|
+
**{k: v for k, v in kwargs.items() if k not in ['const', 'enum']}
|
|
559
|
+
)
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
class AndType(TypeNode, Annotations):
|
|
563
|
+
"""And/Intersection type"""
|
|
564
|
+
|
|
565
|
+
def __init__(self, and_types: List['NodeType'], **kwargs):
|
|
566
|
+
super().__init__("and")
|
|
567
|
+
self._and = and_types
|
|
568
|
+
Annotations.__init__(self, **kwargs)
|
|
569
|
+
|
|
570
|
+
@property
|
|
571
|
+
def and_types(self) -> List['NodeType']:
|
|
572
|
+
"""Nodes in intersection"""
|
|
573
|
+
return self._and
|
|
574
|
+
|
|
575
|
+
@and_types.setter
|
|
576
|
+
def and_types(self, value: List['NodeType']) -> None:
|
|
577
|
+
self._and = value
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
class OrType(TypeNode, Annotations):
|
|
581
|
+
"""Or/Union type"""
|
|
582
|
+
|
|
583
|
+
def __init__(self, or_types: List['NodeType'], **kwargs):
|
|
584
|
+
super().__init__("or")
|
|
585
|
+
self._or = or_types
|
|
586
|
+
Annotations.__init__(self, **kwargs)
|
|
587
|
+
|
|
588
|
+
@property
|
|
589
|
+
def or_types(self) -> List['NodeType']:
|
|
590
|
+
"""Nodes in the union"""
|
|
591
|
+
return self._or
|
|
592
|
+
|
|
593
|
+
@or_types.setter
|
|
594
|
+
def or_types(self, value: List['NodeType']) -> None:
|
|
595
|
+
self._or = value
|
|
596
|
+
|
|
597
|
+
|
|
598
|
+
class TemplateLiteralType(TypeNode, Annotations):
|
|
599
|
+
"""Template literal type"""
|
|
600
|
+
|
|
601
|
+
def __init__(self, format: str, **kwargs):
|
|
602
|
+
super().__init__("template")
|
|
603
|
+
self._format = format
|
|
604
|
+
Annotations.__init__(self, **kwargs)
|
|
605
|
+
|
|
606
|
+
@property
|
|
607
|
+
def format(self) -> str:
|
|
608
|
+
"""String version of regex used to validate template"""
|
|
609
|
+
return self._format
|
|
610
|
+
|
|
611
|
+
@format.setter
|
|
612
|
+
def format(self, value: str) -> None:
|
|
613
|
+
self._format = value
|
|
614
|
+
|
|
615
|
+
|
|
616
|
+
class RecordType(TypeNode, Annotations):
|
|
617
|
+
"""Record type"""
|
|
618
|
+
|
|
619
|
+
def __init__(self, keyType: 'NodeType', valueType: 'NodeType', **kwargs):
|
|
620
|
+
super().__init__("record")
|
|
621
|
+
self._keyType = keyType
|
|
622
|
+
self._valueType = valueType
|
|
623
|
+
Annotations.__init__(self, **kwargs)
|
|
624
|
+
|
|
625
|
+
@property
|
|
626
|
+
def keyType(self) -> 'NodeType':
|
|
627
|
+
"""Key types for the Record"""
|
|
628
|
+
return self._keyType
|
|
629
|
+
|
|
630
|
+
@keyType.setter
|
|
631
|
+
def keyType(self, value: 'NodeType') -> None:
|
|
632
|
+
self._keyType = value
|
|
633
|
+
|
|
634
|
+
@property
|
|
635
|
+
def valueType(self) -> 'NodeType':
|
|
636
|
+
"""Value types for the Record"""
|
|
637
|
+
return self._valueType
|
|
638
|
+
|
|
639
|
+
@valueType.setter
|
|
640
|
+
def valueType(self, value: 'NodeType') -> None:
|
|
641
|
+
self._valueType = value
|
|
642
|
+
|
|
643
|
+
|
|
644
|
+
class FunctionTypeParameters:
|
|
645
|
+
"""Function type parameters"""
|
|
646
|
+
|
|
647
|
+
def __init__(
|
|
648
|
+
self,
|
|
649
|
+
name: str,
|
|
650
|
+
type: 'NodeType',
|
|
651
|
+
optional: Optional[bool] = None,
|
|
652
|
+
default: Optional['NodeType'] = None
|
|
653
|
+
):
|
|
654
|
+
self._name = name
|
|
655
|
+
self._type = type
|
|
656
|
+
self._optional = optional
|
|
657
|
+
self._default = default
|
|
658
|
+
|
|
659
|
+
@property
|
|
660
|
+
def name(self) -> str:
|
|
661
|
+
"""String name of the function parameter"""
|
|
662
|
+
return self._name
|
|
663
|
+
|
|
664
|
+
@name.setter
|
|
665
|
+
def name(self, value: str) -> None:
|
|
666
|
+
self._name = value
|
|
667
|
+
|
|
668
|
+
@property
|
|
669
|
+
def type(self) -> 'NodeType':
|
|
670
|
+
"""The type constraint of the parameter"""
|
|
671
|
+
return self._type
|
|
672
|
+
|
|
673
|
+
@type.setter
|
|
674
|
+
def type(self, value: 'NodeType') -> None:
|
|
675
|
+
self._type = value
|
|
676
|
+
|
|
677
|
+
@property
|
|
678
|
+
def optional(self) -> Optional[bool]:
|
|
679
|
+
"""Indicates that the parameter is optional"""
|
|
680
|
+
return self._optional
|
|
681
|
+
|
|
682
|
+
@optional.setter
|
|
683
|
+
def optional(self, value: Optional[bool]) -> None:
|
|
684
|
+
self._optional = value
|
|
685
|
+
|
|
686
|
+
@property
|
|
687
|
+
def default(self) -> Optional['NodeType']:
|
|
688
|
+
"""Default value for the parameter if nothing is supplied"""
|
|
689
|
+
return self._default
|
|
690
|
+
|
|
691
|
+
@default.setter
|
|
692
|
+
def default(self, value: Optional['NodeType']) -> None:
|
|
693
|
+
self._default = value
|
|
694
|
+
|
|
695
|
+
|
|
696
|
+
class FunctionType(TypeNode, Annotations):
|
|
697
|
+
"""Function type"""
|
|
698
|
+
|
|
699
|
+
def __init__(
|
|
700
|
+
self,
|
|
701
|
+
parameters: List[FunctionTypeParameters],
|
|
702
|
+
returnType: Optional['NodeType'] = None,
|
|
703
|
+
**kwargs
|
|
704
|
+
):
|
|
705
|
+
super().__init__("function")
|
|
706
|
+
self._parameters = parameters
|
|
707
|
+
self._returnType = returnType
|
|
708
|
+
Annotations.__init__(self, **kwargs)
|
|
709
|
+
|
|
710
|
+
@property
|
|
711
|
+
def parameters(self) -> List[FunctionTypeParameters]:
|
|
712
|
+
"""Types for the parameters, in order, for the function"""
|
|
713
|
+
return self._parameters
|
|
714
|
+
|
|
715
|
+
@parameters.setter
|
|
716
|
+
def parameters(self, value: List[FunctionTypeParameters]) -> None:
|
|
717
|
+
self._parameters = value
|
|
718
|
+
|
|
719
|
+
@property
|
|
720
|
+
def returnType(self) -> Optional['NodeType']:
|
|
721
|
+
"""Return type of the function"""
|
|
722
|
+
return self._returnType
|
|
723
|
+
|
|
724
|
+
@returnType.setter
|
|
725
|
+
def returnType(self, value: Optional['NodeType']) -> None:
|
|
726
|
+
self._returnType = value
|
|
727
|
+
|
|
728
|
+
|
|
729
|
+
class NamedType(Generic[T], Annotations):
|
|
730
|
+
"""Named type that can wrap any base XLR node with name and source information"""
|
|
731
|
+
|
|
732
|
+
def __init__(self, base_node: T, name: str, source: str, **kwargs):
|
|
733
|
+
super().__init__(**kwargs)
|
|
734
|
+
self._base_node = base_node
|
|
735
|
+
self._name = name # Using _name to avoid conflict with Annotations.name
|
|
736
|
+
self._source = source
|
|
737
|
+
|
|
738
|
+
def __getattribute__(self, attr):
|
|
739
|
+
try:
|
|
740
|
+
return object.__getattribute__(self, attr)
|
|
741
|
+
except AttributeError:
|
|
742
|
+
return self.base_node.__getattribute__(attr)
|
|
743
|
+
|
|
744
|
+
@property
|
|
745
|
+
def base_node(self) -> T:
|
|
746
|
+
"""The underlying XLR node that this named type wraps"""
|
|
747
|
+
return self._base_node
|
|
748
|
+
|
|
749
|
+
@base_node.setter
|
|
750
|
+
def base_node(self, value: T) -> None:
|
|
751
|
+
self._base_node = value
|
|
752
|
+
|
|
753
|
+
@property
|
|
754
|
+
def name(self) -> str:
|
|
755
|
+
"""Name of the exported interface/type"""
|
|
756
|
+
return self._name
|
|
757
|
+
|
|
758
|
+
@name.setter
|
|
759
|
+
def name(self, value: str) -> None: # type: ignore
|
|
760
|
+
self._name = value
|
|
761
|
+
|
|
762
|
+
@property
|
|
763
|
+
def source(self) -> str:
|
|
764
|
+
"""File the type was exported from"""
|
|
765
|
+
return self._source
|
|
766
|
+
|
|
767
|
+
@source.setter
|
|
768
|
+
def source(self, value: str) -> None:
|
|
769
|
+
self._source = value
|
|
770
|
+
|
|
771
|
+
# Delegate type property to base_node for compatibility
|
|
772
|
+
@property
|
|
773
|
+
def type(self) -> str:
|
|
774
|
+
"""The type of the underlying node"""
|
|
775
|
+
return self._base_node.type if hasattr(self._base_node, 'type') else ''
|
|
776
|
+
|
|
777
|
+
|
|
778
|
+
class ParamTypeNode:
|
|
779
|
+
"""Parameter type node for generics"""
|
|
780
|
+
|
|
781
|
+
def __init__(
|
|
782
|
+
self,
|
|
783
|
+
symbol: str,
|
|
784
|
+
constraints: Optional['NodeType'] = None,
|
|
785
|
+
default: Optional['NodeType'] = None
|
|
786
|
+
):
|
|
787
|
+
self._symbol = symbol
|
|
788
|
+
self._constraints = constraints
|
|
789
|
+
self._default = default
|
|
790
|
+
|
|
791
|
+
@property
|
|
792
|
+
def symbol(self) -> str:
|
|
793
|
+
"""Symbol used to identify the generic in the interface/type"""
|
|
794
|
+
return self._symbol
|
|
795
|
+
|
|
796
|
+
@symbol.setter
|
|
797
|
+
def symbol(self, value: str) -> None:
|
|
798
|
+
self._symbol = value
|
|
799
|
+
|
|
800
|
+
@property
|
|
801
|
+
def constraints(self) -> Optional['NodeType']:
|
|
802
|
+
"""The type constraint for the generic"""
|
|
803
|
+
return self._constraints
|
|
804
|
+
|
|
805
|
+
@constraints.setter
|
|
806
|
+
def constraints(self, value: Optional['NodeType']) -> None:
|
|
807
|
+
self._constraints = value
|
|
808
|
+
|
|
809
|
+
@property
|
|
810
|
+
def default(self) -> Optional['NodeType']:
|
|
811
|
+
"""The default value for the generic if no value is provided"""
|
|
812
|
+
return self._default
|
|
813
|
+
|
|
814
|
+
@default.setter
|
|
815
|
+
def default(self, value: Optional['NodeType']) -> None:
|
|
816
|
+
self._default = value
|
|
817
|
+
|
|
818
|
+
|
|
819
|
+
class NamedTypeWithGenerics(NamedType[T]):
|
|
820
|
+
"""Named type with generics that can wrap any base XLR node"""
|
|
821
|
+
|
|
822
|
+
def __init__(
|
|
823
|
+
self,
|
|
824
|
+
base_node: T,
|
|
825
|
+
name: str,
|
|
826
|
+
source: str,
|
|
827
|
+
genericTokens: List[ParamTypeNode],
|
|
828
|
+
**kwargs
|
|
829
|
+
):
|
|
830
|
+
super().__init__(base_node, name, source, **kwargs)
|
|
831
|
+
self._genericTokens = genericTokens
|
|
832
|
+
|
|
833
|
+
@property
|
|
834
|
+
def genericTokens(self) -> List[ParamTypeNode]:
|
|
835
|
+
"""Generics for the Named Type that need to be filled in"""
|
|
836
|
+
return self._genericTokens
|
|
837
|
+
|
|
838
|
+
@genericTokens.setter
|
|
839
|
+
def genericTokens(self, value: List[ParamTypeNode]) -> None:
|
|
840
|
+
self._genericTokens = value
|
|
841
|
+
|
|
842
|
+
|
|
843
|
+
class NodeTypeWithGenerics:
|
|
844
|
+
"""Node type with generics mixin"""
|
|
845
|
+
|
|
846
|
+
def __init__(self, genericTokens: List[ParamTypeNode]):
|
|
847
|
+
self._genericTokens = genericTokens
|
|
848
|
+
|
|
849
|
+
@property
|
|
850
|
+
def genericTokens(self) -> List[ParamTypeNode]:
|
|
851
|
+
"""Generics for the Node that need to be filled in"""
|
|
852
|
+
return self._genericTokens
|
|
853
|
+
|
|
854
|
+
@genericTokens.setter
|
|
855
|
+
def genericTokens(self, value: List[ParamTypeNode]) -> None:
|
|
856
|
+
self._genericTokens = value
|
|
857
|
+
|
|
858
|
+
|
|
859
|
+
# Type aliases for union types
|
|
860
|
+
PrimitiveTypes = Union[
|
|
861
|
+
NeverType,
|
|
862
|
+
NullType,
|
|
863
|
+
StringType,
|
|
864
|
+
NumberType,
|
|
865
|
+
BooleanType,
|
|
866
|
+
AnyType,
|
|
867
|
+
UnknownType,
|
|
868
|
+
UndefinedType,
|
|
869
|
+
VoidType
|
|
870
|
+
]
|
|
871
|
+
|
|
872
|
+
NodeType = Union[
|
|
873
|
+
AnyType, UnknownType, UndefinedType, NullType, NeverType, StringType, TemplateLiteralType,
|
|
874
|
+
NumberType, BooleanType, ObjectType, ArrayType, TupleType, RecordType, AndType, OrType,
|
|
875
|
+
RefType, FunctionType, ConditionalType, VoidType
|
|
876
|
+
]
|
|
877
|
+
|
|
878
|
+
# Update forward references
|
|
879
|
+
ObjectProperty.__annotations__['node'] = NodeType
|
|
880
|
+
RefNode.__annotations__['genericArguments'] = Optional[List[NodeType]]
|
|
881
|
+
ObjectNode.__annotations__['additionalProperties'] = Union[bool, NodeType]
|
|
882
|
+
ArrayNode.__annotations__['elementType'] = NodeType
|
|
883
|
+
ConditionalNode.__annotations__['check'] = Dict[str, NodeType]
|
|
884
|
+
ConditionalNode.__annotations__['value'] = Dict[str, NodeType]
|
|
885
|
+
TupleMember.__annotations__['type'] = NodeType
|
|
886
|
+
TupleNode.__annotations__['additionalItems'] = Union[bool, NodeType]
|
|
887
|
+
AndType.__annotations__['and_types'] = List[NodeType]
|
|
888
|
+
OrType.__annotations__['or_types'] = List[NodeType]
|
|
889
|
+
RecordType.__annotations__['keyType'] = NodeType
|
|
890
|
+
RecordType.__annotations__['valueType'] = NodeType
|
|
891
|
+
FunctionTypeParameters.__annotations__['type'] = NodeType
|
|
892
|
+
FunctionTypeParameters.__annotations__['default'] = Optional[NodeType]
|
|
893
|
+
FunctionType.__annotations__['returnType'] = Optional[NodeType]
|
|
894
|
+
ParamTypeNode.__annotations__['constraints'] = Optional[NodeType]
|
|
895
|
+
ParamTypeNode.__annotations__['default'] = Optional[NodeType]
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
xlr_lib_types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
xlr_lib_types/deserializer.py,sha256=rfh-xlUxO2V0Ispf7UJBEvwfu1lncSN0hWeZXu4yXjA,10969
|
|
3
|
+
xlr_lib_types/guards.py,sha256=d23bAKwPX6IqV1OSpfJlbWUMceqgsO7YJMyY3oJ003Q,5888
|
|
4
|
+
xlr_lib_types/nodes.py,sha256=qWgNjdzegJGMc8u7DXoZWY8CBzShwKT7O5VjQry8hxQ,26534
|
|
5
|
+
xlr_lib_types-0.1.1.dev9190.dist-info/WHEEL,sha256=sobxWSyDDkdg_rinUth-jxhXHqoNqlmNMJY3aTZn2Us,91
|
|
6
|
+
xlr_lib_types-0.1.1.dev9190.dist-info/METADATA,sha256=4HQ-0Ob7Aks-fsNIOhEXLh4xIWU1XT620Slq_aJOH7A,74
|
|
7
|
+
xlr_lib_types-0.1.1.dev9190.dist-info/RECORD,,
|