-
Notifications
You must be signed in to change notification settings - Fork 9
feat(spider-py): Define TDL types; Add support for converting Python types into TDL types. #187
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 134 commits
d2ac198
cc8a097
7f68bdc
2394649
6ff3e33
7ae8a78
56502f9
6f6becf
a74523d
2345d22
77ee494
38b86c8
3698339
369e9f1
90aa5a2
1769c95
edaa834
7faac8f
f494a90
eb01bb2
ff2fe1c
d476e42
850126d
65841a0
8564fc2
a6e7d29
573b448
6ad72c3
ba7c6e5
209acb1
406b514
66892f5
80f0a10
3186a42
0925938
6936a9b
7407090
6a95b24
f29dcba
453f209
d1011c7
a7dc642
a7d92c2
1c6213b
0f13d07
14d6326
55a727a
c98fea1
ef64454
09ba8ad
4e7237e
1f944d0
68992fc
1127b22
4c51c91
56878b2
bb428c9
944bd5e
d75bc15
4b7eca2
8ddbda7
0d998ec
6004d64
bcab5db
a50d25a
fbebb96
0322bd5
2a08155
0b62f73
7384158
70ef90a
b09515c
bad9675
e009ff4
a0407a7
aa9a8de
3c7e794
b4d6576
23f31cd
0167ac0
f447614
a84de83
2d1b6fc
061d101
de149ee
d332dbe
80b6772
f2ebaa6
8c27b16
b7f1884
a7aa6b0
95b98c8
5765acf
427dd6b
213d2fc
a1a86f3
97af71b
74f31e2
7d95706
96b5324
14ea6fb
854cd11
5565c9e
2504429
7ea4928
01dd0c6
4cec09b
e022404
8894b90
7753153
dd59915
ac1d4ee
0d38c43
438f6e7
2caad5d
c6815ce
61e0651
8b13abd
50b2b25
519dcd8
8e2786b
a8c8641
9fabc44
e558f67
0eea922
edb3212
6eda1bd
dac6d62
70f2a6b
e280a79
0713c0d
3b8cfe9
f3e41f9
c9cb4b6
412a2b5
bab4806
096eda9
be05c38
5cd5699
bdf1d8f
5602b11
0696cac
d6e32b3
e916cb9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,12 @@ | ||
| """Spider package root.""" | ||
|
|
||
| from spider_py.type import Double, Float, Int8, Int16, Int32, Int64 | ||
|
|
||
| __all__ = [ | ||
| "Double", | ||
| "Float", | ||
| "Int8", | ||
| "Int16", | ||
| "Int32", | ||
| "Int64", | ||
| ] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| """Spider type package.""" | ||
|
|
||
| from spider_py.type.tdl_convert import to_tdl_type_str | ||
| from spider_py.type.type import Double, Float, Int8, Int16, Int32, Int64 | ||
|
|
||
| __all__ = ["Double", "Float", "Int8", "Int16", "Int32", "Int64", "to_tdl_type_str"] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| """Converts native types to TDL types.""" | ||
|
|
||
| from collections.abc import Collection | ||
| from types import GenericAlias | ||
| from typing import get_args, get_origin | ||
|
|
||
| from spider_py.type.tdl_type import ( | ||
| BoolType, | ||
| ClassType, | ||
| DoubleType, | ||
| FloatType, | ||
| Int8Type, | ||
| Int16Type, | ||
| Int32Type, | ||
| Int64Type, | ||
| ListType, | ||
| MapType, | ||
| TdlType, | ||
| ) | ||
| from spider_py.type.type import Double, Float, Int8, Int16, Int32, Int64 | ||
| from spider_py.type.utils import get_class_name | ||
|
|
||
|
|
||
| def to_primitive_tdl_type(native_type: type | GenericAlias) -> TdlType | None: | ||
| """ | ||
| Converts a native type to primitive TDL type. | ||
| :param native_type: | ||
| :return: Converted TDL primitive. None if `native_type` is not a supported primitive type. | ||
sitaowang1998 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| """ | ||
| tdl_type: TdlType | None = None | ||
| if native_type is Int8: | ||
| tdl_type = Int8Type() | ||
| elif native_type is Int16: | ||
| tdl_type = Int16Type() | ||
| elif native_type is Int32: | ||
| tdl_type = Int32Type() | ||
| elif native_type is Int64: | ||
| tdl_type = Int64Type() | ||
| elif native_type is Float: | ||
| tdl_type = FloatType() | ||
| elif native_type is Double: | ||
| tdl_type = DoubleType() | ||
| elif native_type is bool: | ||
| tdl_type = BoolType() | ||
| return tdl_type | ||
|
|
||
|
|
||
| def to_tdl_type(native_type: type | GenericAlias) -> TdlType: | ||
| """ | ||
| Converts a Python type to TDL type. | ||
| :param native_type: | ||
| :return: | ||
sitaowang1998 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| :raise: TypeError if `native_type` is not a valid TDL type. | ||
| """ | ||
| primitive_tdl_type = to_primitive_tdl_type(native_type) | ||
| if primitive_tdl_type is not None: | ||
| return primitive_tdl_type | ||
|
|
||
| if native_type in (int, float, str, complex, bytes): | ||
| msg = f"{native_type} is not a valid TDL type." | ||
| raise TypeError(msg) | ||
|
||
|
|
||
| if isinstance(native_type, GenericAlias): | ||
sitaowang1998 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| origin = get_origin(native_type) | ||
| if origin is list: | ||
| arg = get_args(native_type) | ||
| if arg is None: | ||
sitaowang1998 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| msg = "List does not have a key type." | ||
sitaowang1998 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| raise TypeError(msg) | ||
| arg = arg[0] | ||
sitaowang1998 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return ListType(to_tdl_type(arg)) | ||
|
|
||
| if origin is dict: | ||
| arg = get_args(native_type) | ||
| msg = "Dict does not have a key/value type." | ||
| if arg is None: | ||
| raise TypeError(msg) | ||
| if len(arg) != 2: # noqa: PLR2004 | ||
| raise TypeError(msg) | ||
| key = arg[0] | ||
| value = arg[1] | ||
| return MapType(to_tdl_type(key), to_tdl_type(value)) | ||
|
|
||
| msg = f"{native_type} is not a valid TDL type." | ||
| raise TypeError(msg) | ||
|
|
||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if issubclass(native_type, Collection): | ||
| msg = f"{native_type} is not a valid TDL type." | ||
| raise TypeError(msg) | ||
|
|
||
| return ClassType(get_class_name(native_type)) | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
|
|
||
| def to_tdl_type_str(native_type: type | GenericAlias) -> str: | ||
| """ | ||
| :param native_type: A Python native type. | ||
| :return: A string representation of the TDL type. | ||
| :raise: TypeError if `native_type` is not a valid TDL type. | ||
| """ | ||
| return to_tdl_type(native_type).type_str() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| """Spider TDL types.""" | ||
|
|
||
| from abc import ABC, abstractmethod | ||
|
|
||
| from typing_extensions import override | ||
|
|
||
|
|
||
| class TdlType(ABC): | ||
| """Abstract base class for all TDL types.""" | ||
|
|
||
| @abstractmethod | ||
| def type_str(self) -> str: | ||
| """:return: String representation of the TDL type.""" | ||
|
|
||
|
|
||
| class DoubleType(TdlType): | ||
| """TDL double type.""" | ||
|
|
||
| @override | ||
| def type_str(self) -> str: | ||
| return "double" | ||
|
|
||
|
|
||
| class FloatType(TdlType): | ||
| """TDL float type.""" | ||
|
|
||
| @override | ||
| def type_str(self) -> str: | ||
| return "float" | ||
|
|
||
|
|
||
| class Int8Type(TdlType): | ||
| """TDL int8 type.""" | ||
|
|
||
| @override | ||
| def type_str(self) -> str: | ||
| return "int8" | ||
|
|
||
|
|
||
| class Int16Type(TdlType): | ||
| """TDL int16 type.""" | ||
|
|
||
| @override | ||
| def type_str(self) -> str: | ||
| return "int16" | ||
|
|
||
|
|
||
| class Int32Type(TdlType): | ||
| """TDL int32 type.""" | ||
|
|
||
| @override | ||
| def type_str(self) -> str: | ||
| return "int32" | ||
|
|
||
|
|
||
| class Int64Type(TdlType): | ||
| """TDL int64 type.""" | ||
|
|
||
| @override | ||
| def type_str(self) -> str: | ||
| return "int64" | ||
|
|
||
|
|
||
| class BoolType(TdlType): | ||
| """TDL bool type.""" | ||
|
|
||
| @override | ||
| def type_str(self) -> str: | ||
| return "bool" | ||
|
|
||
|
|
||
| class ClassType(TdlType): | ||
| """TDL Custom class type.""" | ||
|
|
||
| def __init__(self, name: str) -> None: | ||
| """ | ||
| Creates a TDL custom class type. | ||
| :param name: The name of the class. | ||
| """ | ||
| self._name = name | ||
|
|
||
| @override | ||
| def type_str(self) -> str: | ||
| return self._name | ||
|
|
||
|
|
||
| class ListType(TdlType): | ||
| """TDL List type.""" | ||
|
|
||
| def __init__(self, element_type: TdlType) -> None: | ||
| """Creates a TDL list type.""" | ||
sitaowang1998 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| self.element_type = element_type | ||
|
|
||
| @override | ||
| def type_str(self) -> str: | ||
| return f"List<{self.element_type.type_str()}>" | ||
|
|
||
|
|
||
| def is_integral(tdl_type: TdlType) -> bool: | ||
| """:return: If TDL type is an integral type.""" | ||
sitaowang1998 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return isinstance(tdl_type, (Int8Type, Int16Type, Int32Type, Int64Type)) | ||
|
|
||
|
|
||
| def is_string(tdl_type: TdlType) -> bool: | ||
| """:return: If TDL type is a string type, i.e. List<int8>.""" | ||
sitaowang1998 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return isinstance(tdl_type, ListType) and isinstance(tdl_type.element_type, Int8Type) | ||
|
|
||
|
|
||
| def is_map_key(tdl_type: TdlType) -> bool: | ||
| """:return: If TDL type is a valid type for map key.""" | ||
sitaowang1998 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return is_integral(tdl_type) or is_string(tdl_type) | ||
|
|
||
|
|
||
| class MapType(TdlType): | ||
| """TDL Map type.""" | ||
|
|
||
| def __init__(self, key_type: TdlType, value_type: TdlType) -> None: | ||
| """ | ||
| Creates a TDL map type. | ||
sitaowang1998 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| :raises TypeError: If key is not a supported type. | ||
| """ | ||
| if not is_map_key(key_type): | ||
| msg = f"{key_type} is not a supported type for map key." | ||
| raise TypeError(msg) | ||
| self.key_type = key_type | ||
| self.value_type = value_type | ||
|
|
||
| @override | ||
| def type_str(self) -> str: | ||
| return f"Map<{self.key_type.type_str()},{self.value_type.type_str()}>" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| """Custom type module for Spider.""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| from typing import cast | ||
|
|
||
|
|
||
| class BoundedInt(int): | ||
| """Bounded integer type.""" | ||
|
|
||
| def __new__(cls, value: int, bits: int = 32) -> BoundedInt: | ||
| """Creates a bounded integer.""" | ||
| min_val = -(1 << (bits - 1)) | ||
| max_val = (1 << (bits - 1)) - 1 | ||
sitaowang1998 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
sitaowang1998 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| if bits not in (8, 16, 32, 64): | ||
| msg = f"Unsupported bits size: {bits}. Supported sizes are 8, 16, 32, or 64." | ||
| raise ValueError(msg) | ||
|
|
||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if not (min_val <= value and value <= max_val): | ||
| msg = f"Bounded integer value ({value}) must be between {min_val} and {max_val}" | ||
sitaowang1998 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| raise ValueError(msg) | ||
|
||
|
|
||
| return super().__new__(cls, value) | ||
|
|
||
|
|
||
| class Int8(BoundedInt): | ||
| """8 bits integer type.""" | ||
|
|
||
| def __new__(cls, value: int) -> Int8: | ||
| """Creates an int8 integer.""" | ||
| return cast("Int8", super().__new__(cls, value, bits=8)) | ||
|
|
||
|
|
||
| class Int16(BoundedInt): | ||
| """16 bits integer type.""" | ||
|
|
||
| def __new__(cls, value: int) -> Int16: | ||
| """Creates an int16 integer.""" | ||
| return cast("Int16", super().__new__(cls, value, bits=16)) | ||
|
|
||
|
|
||
| class Int32(BoundedInt): | ||
| """32 bits integer type.""" | ||
|
|
||
| def __new__(cls, value: int) -> Int32: | ||
| """Creates an int32 integer.""" | ||
| return cast("Int32", super().__new__(cls, value, bits=32)) | ||
|
|
||
|
|
||
| class Int64(BoundedInt): | ||
| """64 bits integer type.""" | ||
|
|
||
| def __new__(cls, value: int) -> Int64: | ||
| """Creates an int64 integer.""" | ||
| return cast("Int64", super().__new__(cls, value, bits=64)) | ||
|
|
||
|
|
||
| class Float(float): | ||
| """Float type.""" | ||
|
|
||
| def __new__(cls, value: float) -> Float: | ||
| """Creates a float number.""" | ||
| return super().__new__(cls, value) | ||
|
|
||
|
|
||
| class Double(float): | ||
| """Double type.""" | ||
|
|
||
| def __new__(cls, value: float) -> Double: | ||
| """Creates a double number.""" | ||
| return super().__new__(cls, value) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| """Utility for TDL types.""" | ||
|
|
||
|
|
||
| def get_class_name(cls: type) -> str: | ||
| """ | ||
| :param cls: | ||
| :return: Full name of `cls`. | ||
| """ | ||
| return f"{cls.__module__}.{cls.__qualname__}" |
Uh oh!
There was an error while loading. Please reload this page.