1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
|
from stone.backends.python_helpers import class_name_for_data_type, fmt_namespace
from stone.ir import (
Alias,
ApiNamespace,
DataType,
List,
Map,
Nullable,
Timestamp,
UserDefined,
is_alias,
is_boolean_type,
is_bytes_type,
is_float_type,
is_integer_type,
is_list_type,
is_map_type,
is_nullable_type,
is_string_type,
is_timestamp_type,
is_user_defined_type,
is_void_type,
)
from stone.ir.data_types import String
from stone.typing_hacks import cast
MYPY = False
if MYPY:
import typing # noqa: F401 # pylint: disable=import-error,unused-import,useless-suppression
DataTypeCls = typing.Type[DataType]
# Unfortunately these are codependent, so I'll weakly type the Dict in Callback
Callback = typing.Callable[
[ApiNamespace, DataType, typing.Dict[typing.Any, typing.Any]],
str
]
OverrideDefaultTypesDict = typing.Dict[DataTypeCls, Callback]
else:
OverrideDefaultTypesDict = "OverrideDefaultTypesDict"
def map_stone_type_to_python_type(ns, data_type, override_dict=None):
# type: (ApiNamespace, DataType, typing.Optional[OverrideDefaultTypesDict]) -> typing.Text
"""
Args:
override_dict: lets you override the default behavior for a given type by hooking into
a callback. (Currently only hooked up for stone's List and Nullable)
"""
override_dict = override_dict or {}
if is_string_type(data_type):
string_override = override_dict.get(String, None)
if string_override:
return string_override(ns, data_type, override_dict)
return 'str'
elif is_bytes_type(data_type):
return 'bytes'
elif is_boolean_type(data_type):
return 'bool'
elif is_float_type(data_type):
return 'float'
elif is_integer_type(data_type):
return 'int'
elif is_void_type(data_type):
return 'None'
elif is_timestamp_type(data_type):
timestamp_override = override_dict.get(Timestamp, None)
if timestamp_override:
return timestamp_override(ns, data_type, override_dict)
return 'datetime.datetime'
elif is_alias(data_type):
alias_type = cast(Alias, data_type)
return map_stone_type_to_python_type(ns, alias_type.data_type, override_dict)
elif is_user_defined_type(data_type):
user_defined_type = cast(UserDefined, data_type)
class_name = class_name_for_data_type(user_defined_type)
if user_defined_type.namespace.name != ns.name:
return '{}.{}'.format(
fmt_namespace(user_defined_type.namespace.name), class_name)
else:
return class_name
elif is_list_type(data_type):
list_type = cast(List, data_type)
if List in override_dict:
return override_dict[List](ns, list_type.data_type, override_dict)
# PyCharm understands this description format for a list
return 'list of [{}]'.format(
map_stone_type_to_python_type(ns, list_type.data_type, override_dict)
)
elif is_map_type(data_type):
map_type = cast(Map, data_type)
if Map in override_dict:
return override_dict[Map](
ns,
data_type,
override_dict
)
return 'dict of [{}:{}]'.format(
map_stone_type_to_python_type(ns, map_type.key_data_type, override_dict),
map_stone_type_to_python_type(ns, map_type.value_data_type, override_dict)
)
elif is_nullable_type(data_type):
nullable_type = cast(Nullable, data_type)
if Nullable in override_dict:
return override_dict[Nullable](ns, nullable_type.data_type, override_dict)
return 'Optional[{}]'.format(
map_stone_type_to_python_type(ns, nullable_type.data_type, override_dict)
)
else:
raise TypeError('Unknown data type %r' % data_type)
|