Coverage for /home/jenkins/workspace/NDS/Zserio/NDS_ZSERIO-linux-build/compiler/extensions/python/runtime/src/zserio/typeinfo.py: 100%
118 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-12-13 15:12 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2023-12-13 15:12 +0000
1"""
2The module contains classes for type info.
3"""
5import typing
6import enum
8class TypeInfo:
9 """
10 Type info class which provides information about generated types.
11 """
13 def __init__(self, schema_name: str, py_type: typing.Type, *,
14 attributes: typing.Dict['TypeAttribute', typing.Any] = None):
15 """
16 Type info constructor.
18 :param schema_name: Zserio schema full type name.
19 :param py_type: Reference to the generated type.
20 :param attributes: List of type attributes.
21 """
23 self._schema_name = schema_name
24 self._py_type = py_type
25 self._attributes = attributes if attributes is not None else {}
27 @property
28 def schema_name(self) -> str:
29 """
30 Returns the full type name as is defined in Zserio schema.
32 :returns: Zserio schema full type name.
33 """
35 return self._schema_name
37 @property
38 def py_type(self) -> typing.Type:
39 """
40 Gets Python type generated for this Zserio type.
42 :returns: Python type.
43 """
45 return self._py_type
47 @property
48 def attributes(self) -> typing.Dict['TypeAttribute', typing.Any]:
49 """
50 Gets dictionary with type attributes.
52 Attribute is a an arbitrary value which type is given by the key, which is TypeAttribute enumeration.
54 * `(TypeAttribute.UNDERLYING_TYPE, TypeInfo(...))`
56 * denotes that the type has an underlying type (e.g. enum or bitmask),
57 the value is a TypeInfo of the underlying type
59 * `(TypeAttribute.UNDERLYING_TYPE_ARGUMENTS, [lambda: 5])`
61 * keeps type arguments of the underlying type when it is a dynamic bit field,
62 the value is a lambda function which returns the argument constant value
64 * `(TypeAttribute.ENUM_ITEMS, [ItemInfo(...), ItemInfo(...), ...])`
66 * denotes that the type is an enumeration, the value contains list of enum items ItemInfo
68 * `(TypeAttribute.BITMASK_VALUES, [ItemInfo(...), ItemInfo(...), ...])`
70 * denotes that the type is a bitmask, the value contains list of bitmask values ItemInfo
72 * `(TypeAttribute.FIELDS, [MemberInfo(...), MemberInfo(...), ...])`
74 * denotes that the type is a compound type, the value contains list of fields MemberInfo,
75 the attribute is present even for empty compounds and then it contains the empty list
77 * `(TypeAttribute.PARAMETERS, [MemberInfo(...), MemberInfo(...), ...])`
79 * denotes that the compound type is parameterized type, the value contains non-empty list of
80 parameters MemberInfo, for non-parameterized types the attribute is not present
82 * `(TypeAttribute.FUNCTIONS, [MemberInfo(...), MemberInfo(...), ...])`
84 * denotes that the compound type has functions, the value contains non-empty list of functions
85 MemberInfo, for compounds without functions the attribute is not present
87 * `(TypeAttribute.SELECTOR, None`) `(TypeAttribute.SELECTOR, lambda self: self.param1)`
89 * denotes that the type is either a union (when the value is None) or choice when the
90 value contains the selector expression as a lambda function taking single parent argument
92 * `(TypeAttribute.CASES, [CaseInfo(...), CaseInfo(...), ...])`
94 * denotes that the type is a choice, the value contains list of CaseInfo for each choice case
95 * note that the TypeAttribute.FIELDS attribute is present also in choices
97 * `(TypeAttribute.TEMPLATE_NAME, 'TemplatedStructure')`
99 * denotes that the type is a template instantiation, the value contains the template name
101 * `(TypeAttribute.TEMPLATE_ARGUMENTS, [test.TemplateArg.type_info(), ...])`
103 * present when the type is a template instantiation, the value contains list of template arguments
104 TypeInfo
106 * `(TypeAttribute.COLUMNS, [MemberInfo(...), MemberInfo(...), ...])`
108 * denotes that the type is a SQL table, the value contains list of columns MemberInfo
110 * `(TypeAttribute.TABLES, [MemberInfo(...), MemberInfo(...), ...])`
112 * denotes that the type is a SQL database, the value contain list of tables MemberInfo
114 * `(TypeAttribute.SQL_CONSTRAINT, 'PRIMARY KEY(columnA)')`
116 * denotes that the SQL table contains a SQL constraint
118 * `(TypeAttribute.VIRTUAL_TABLE_USING, 'fts4')`
120 * denotes that the SQL table is a virtual table, the value contains the used virtual table module
122 * `(TypeAttribute.WITHOUT_ROWID, None)`
124 * denotes that the SQL table is a WITHOUT ROWID table, the value is always None
126 * `(TypeAttribute.MESSAGES, [MemberInfo(...), MemberInfo(...), ...])`
128 * denotes that the type is a pub-sub, the value contains list of messages MemberInfo
130 * `(TypeAttribute.METHODS, [MemberInfo(...), MemberInfo(...), ...])`
132 * denotes that the type is a service, the value contains list of methods MemberInfo
134 :returns Type attributes.
135 """
137 return self._attributes
139class RecursiveTypeInfo:
140 """
141 Type info for recursive types used as a wrapper around generated static type_info method to prevent
142 infinite recursion in type info definition.
143 """
145 def __init__(self, type_info_func : typing.Callable[[], TypeInfo]):
146 """
147 Constructor.
149 :param type_info_func: Generated static type_info method to wrap.
150 """
152 self._type_info_func = type_info_func
153 self._type_info = None
155 @property
156 def schema_name(self) -> str:
157 """
158 See :py:attr:`TypeInfo.schema_name`.
159 """
161 return self._get_type_info().schema_name
163 @property
164 def py_type(self) -> typing.Type:
165 """
166 See :py:attr:`TypeInfo.py_type`.
167 """
169 return self._get_type_info().py_type
171 @property
172 def attributes(self) -> typing.Dict['TypeAttribute', typing.Any]:
173 """
174 See :py:attr:`TypeInfo.attributes`.
175 """
177 return self._get_type_info().attributes
179 def _get_type_info(self):
180 if self._type_info is None:
181 self._type_info = self._type_info_func()
182 return self._type_info
184class TypeAttribute(enum.Enum):
185 """
186 Type attribute type to be used in TypeInfo.
188 Determines type of the second element in the attribute tuple returned in attributes list from TypeInfo.
189 """
191 UNDERLYING_TYPE = enum.auto()
192 UNDERLYING_TYPE_ARGUMENTS = enum.auto()
193 ENUM_ITEMS = enum.auto()
194 BITMASK_VALUES = enum.auto()
195 FIELDS = enum.auto()
196 PARAMETERS = enum.auto()
197 FUNCTIONS = enum.auto()
198 SELECTOR = enum.auto()
199 CASES = enum.auto()
200 TEMPLATE_NAME = enum.auto()
201 TEMPLATE_ARGUMENTS= enum.auto()
202 COLUMNS = enum.auto()
203 TABLES = enum.auto()
204 SQL_CONSTRAINT = enum.auto()
205 VIRTUAL_TABLE_USING = enum.auto()
206 WITHOUT_ROWID = enum.auto()
207 MESSAGES = enum.auto()
208 METHODS = enum.auto()
210class MemberInfo:
211 """
212 Member info class which provides information about members of compound types.
213 """
215 def __init__(self, schema_name: str, typeinfo: typing.Union[TypeInfo, RecursiveTypeInfo], *,
216 attributes: typing.Dict['MemberAttribute', typing.Any] = None):
217 """
218 Member info constructor.
220 :param schema_name: Name of the member as is defined in Zserio schema.
221 :param type_info: Type info of the member.
222 :param attributes: List of member attributes.
223 """
225 self._schema_name = schema_name
226 self._type_info = typeinfo
227 self._attributes = attributes if attributes is not None else {}
229 @property
230 def schema_name(self) -> str:
231 """
232 Gets name of the member as is defined in Zserio schema.
234 :returns: Member name in Zserio schema.
235 """
237 return self._schema_name
239 @property
240 def type_info(self) -> typing.Union[TypeInfo, RecursiveTypeInfo]:
241 """
242 Gets type info of this member.
244 :returns: Type info.
245 """
247 return self._type_info
249 @property
250 def attributes(self) -> typing.Dict['MemberAttribute', typing.Any]:
251 """
252 Gets dictionary with member attributes.
254 Attribute is a an arbitrary value which type is given by the key, which is MemberAttribute enumeration.
255 All expressions are stored as strings.
257 **Possible attributes:**
259 * `(MemberAttribute.PROPERTY_NAME, 'field1')`
261 * contains name of the property generated in Python
263 * `(MemberAttribute.TYPE_ARGUMENTS, [(lambda self, zserio_index: self.field1), ...])`
265 * for compound type members, keeps type arguments for parameterized types or dynamic bit fields,
266 the value contains list of lambda functions evaluating particular arguments expression,
267 where the lambdas take parent and an element index (which can be None if not used) as arguments
269 * for members of sql tables, keeps type arguments for columns, the value contains list of
270 lambdas where the lambdas take either single explicit parameter argument for explicit parameters or
271 single 'self' argument, which is an object providing property-like getters for column names
272 used in expressions
274 * `(MemberAttribute.EXTENDED, None)`
276 * denotes that the member field is extended, the value is always None
278 * `(MemberAttribute.ALIGN, lambda: 8)`
280 * denotes that the member field has an alignment, the value is a lambda function which returns the
281 alignment constant value
283 * `(MemberAttribute.OFFSET, lambda self: self.offset_field)`
285 * denotes that the member field has an offset, the value contains the offset expression
286 as a lambda function taking single parent argument
288 * `(MemberAttribute.INITIALIZER, lambda: 10)`
290 * denotes that the member field has an initializer, the value is a lambda function which returns the
291 the initializer constant value
293 * `(MemberAttribute.OPTIONAL, None)`, `(MemberAttribute.OPTIONAL, lambda self: self.field1 != 0)`
295 * denotes that the member is an optional, when the value is None, then it's an auto optional,
296 otherwise it contains the optional clause as a lambda function taking single parent argument
298 * `(MemberAttribute.IS_USED_INDICATOR_NAME, 'is_field_used)`
300 * if the member is an optional, the value contains the "is_used" indicator name generated in Python
302 * `(MemberAttribute.IS_SET_INDICATOR_NAME, 'is_field_set)`
304 * if the member is an optional, the value contains the "is_set" indicator name generated in Python
306 * `(MemberAttribute.CONSTRAINT, lambda self: field > 10)`
308 * denotes that the member has a constraint, the value contains the constraint expression
309 as a lambda function taking single parent argument
311 * `(MemberAttribute.FUNCTION_NAME, 'function_name')`
313 * keeps the generated function name
315 * `MemberAttribute.FUNCTION_RESULT, lambda self: self.field1 + 5)`
317 * keeps the result expression of a function as a lambda function taking single parent argument
319 * `(MemberAttribute.ARRAY_LENGTH, None)`, `(MemberAttribute.ARRAY_LENGTH, lambda self: self.field1 + 1)`
321 * denotes that the member is an array, when the value is None, then it's an auto array,
322 otherwise it contains the length expression as a lambda function taking single parent argument
324 * `(MemberAttribute.IMPLICIT, None)`
326 * denotes that the member is an implicit array, the value is always None
328 * `(MemberAttribute.PACKED, None)`
330 * denotes that the member is a packed array, the value is always None
332 * `(MemberAttribute.SQL_TYPE_NAME, 'INTEGER')`
334 * keeps SQLite type name used for this column
336 * `(MemberAttribute.SQL_CONSTRAINT, 'PRIMARY KEY NOT NULL')`
338 * denotes that the member has a SQL constraint
340 * `(MemberAttribute.VIRTUAL, None)`
342 * denotes that the column in a SQL table is virtual
344 * `(MemberAttribute.TOPIC, 'topic/definition')`
346 * keeps the topic definition of a pub-sub message
348 * `(MemberAttribute.PUBLISH, 'publish_message_name')`
350 * denotes that the pub-sub message is published, the value contains the publishing method name
352 * `(MemberAttribute.SUBSCRIBE, 'subscribe_message_name')`
354 * denotes that the pub-sub message is subscribed, the value contains the subscribing method name
356 * `(MemberAttribute.CLIENT_METHOD_NAME, 'client_method_name')`
358 * keeps the name of the method in the generated Client class
360 * `(MemberAttribute.REQUEST_TYPE, request_type.type_info())`
362 * keeps the request type TypeInfo, note that response type is in the method TypeInfo
364 :returns: Member attributes.
365 """
367 return self._attributes
369class MemberAttribute(enum.Enum):
370 """
371 Member attribute type to be used in MemberInfo.
373 Determines type of the second element in the attribute tuple returned in attributes list from MemberInfo.
374 """
376 PROPERTY_NAME = enum.auto()
377 TYPE_ARGUMENTS = enum.auto()
378 EXTENDED = enum.auto()
379 ALIGN = enum.auto()
380 OFFSET = enum.auto()
381 INITIALIZER = enum.auto()
382 OPTIONAL = enum.auto()
383 IS_USED_INDICATOR_NAME = enum.auto()
384 IS_SET_INDICATOR_NAME = enum.auto()
385 CONSTRAINT = enum.auto()
386 FUNCTION_NAME = enum.auto()
387 FUNCTION_RESULT = enum.auto()
388 ARRAY_LENGTH = enum.auto()
389 IMPLICIT = enum.auto()
390 PACKED = enum.auto()
391 SQL_TYPE_NAME = enum.auto()
392 SQL_CONSTRAINT = enum.auto()
393 VIRTUAL = enum.auto()
394 TOPIC = enum.auto()
395 PUBLISH = enum.auto()
396 SUBSCRIBE = enum.auto()
397 CLIENT_METHOD_NAME = enum.auto()
398 REQUEST_TYPE = enum.auto()
400class CaseInfo:
401 """
402 Case info class which provides information about choice cases in generated choices.
403 """
405 def __init__(self, case_expressions: typing.List[typing.Any], field: typing.Optional[MemberInfo]):
406 """
407 Constructor.
409 :param case_expressions: List of case expression in the choice case. When empty, it's a default case.
410 :param field: Field associated with the choice case, can be empty.
411 """
413 self._case_expressions = case_expressions
414 self._field = field
416 @property
417 def case_expressions(self) -> typing.List[typing.Any]:
418 """
419 Gets case expressions in the choice case. An empty list denotes the default case.
421 :returns: List of case expressions as evaluated constant values.
422 """
424 return self._case_expressions
426 @property
427 def field(self) -> typing.Optional[MemberInfo]:
428 """
429 Gets field associated with the choice case. Can be empty.
431 :returns: Field MemberInfo.
432 """
434 return self._field
437class ItemInfo:
438 """
439 Item info class which provides information about items of generated enumerable types.
440 """
442 def __init__(self, schema_name: str, py_item: typing.Any, is_deprecated: bool, is_removed: bool):
443 """
444 Constructor.
446 :param schema_name: Name of the item as is defined in Zserio schema.
447 :param py_item: Reference to the generated item.
448 """
450 self._schema_name = schema_name
451 self._py_item = py_item
452 self._is_deprecated = is_deprecated
453 self._is_removed = is_removed
455 @property
456 def schema_name(self) -> str:
457 """
458 Gets name of the item as is defined in Zserio schema.
460 :returns: Item name in Zserio schema.
461 """
463 return self._schema_name
465 @property
466 def py_item(self) -> typing.Any:
467 """
468 Gets reference to the item generated in Python.
470 :returns: Python item.
471 """
473 return self._py_item
475 @property
476 def is_deprecated(self) -> bool:
477 """
478 Gets flag whether the item is deprecated.
480 :returns: True when the item is deprecated, false otherwise.
481 """
483 return self._is_deprecated
485 @property
486 def is_removed(self) -> bool:
487 """
488 Gets flag whether the item is removed.
490 :returns: True when the item is removed, false otherwise.
491 """
493 return self._is_removed