Skip to content

Instantly share code, notes, and snippets.

@shininglion
Created December 30, 2018 05:14
Show Gist options
  • Save shininglion/2f04c752b55a0aa40203f09db2d5655d to your computer and use it in GitHub Desktop.
Save shininglion/2f04c752b55a0aa40203f09db2d5655d to your computer and use it in GitHub Desktop.
Create a user-defined type family that allow composition
from enum import Enum
class DatabaseType(Enum):
INTEGER = 'INTEGER'
REAL = 'REAL'
TEXT = 'TEXT'
LIST = 'LIST'
MAP = 'MAP'
class TypeInterface:
def __init__(self):
raise TypeError("Try to create an object with forbid type")
def __str__(self):
raise NotImplementedError("Method '__str__' has no implementation")
def __repr__(self):
raise NotImplementedError("Method '__repr__' has no implementation")
def type(self):
raise NotImplementedError("Method 'type' has no implementation")
def to_str(self, type2str = None):
raise NotImplementedError("Method 'to_str' has no implementation")
class IntegerType(TypeInterface):
def __init__(self):
self.__type = DatabaseType.INTEGER
def __str__(self):
return self.__type.value
def __repr__(self):
return self.__type.name
def type(self):
return self.__type
def to_str(self, type2str = None):
if type2str is None:
return self.__str__()
else:
return type2str[self.__type]
class RealType(TypeInterface):
def __init__(self):
self.__type = DatabaseType.REAL
def __str__(self):
return self.__type.value
def __repr__(self):
return self.__type.name
def type(self):
return self.__type
def to_str(self, type2str = None):
if type2str is None:
return self.__str__()
else:
return type2str[self.__type]
class TextType(TypeInterface):
def __init__(self):
self.__type = DatabaseType.TEXT
def __str__(self):
return self.__type.value
def __repr__(self):
return self.__type.name
def type(self):
return self.__type
def to_str(self, type2str = None):
if type2str is None:
return self.__str__()
else:
return type2str[self.__type]
class ListType(TypeInterface):
def __init__(self, elem_type : DatabaseType):
# exclude collection types
if (elem_type == DatabaseType.LIST) or (elem_type == DatabaseType.MAP):
raise TypeError("Element type of type '{}' cannot be collection types".format(DatabaseType.LIST.name))
# initialize
self.__type = DatabaseType.LIST
self.__elem_type = elem_type
def __str__(self):
return "{}<{}>".format(self.__type.value, self.__elem_type.value)
def __repr__(self):
return self.__type.name
def type(self):
return self.__type
def to_str(self, type2str = None):
if type2str is None:
return self.__str__()
else:
return "{}<{}>".format(self.__type.value, type2str[self.__elem_type])
class MapType(TypeInterface):
def __init__(self, key_type : DatabaseType, val_type : DatabaseType):
# exclude collection types
if (key_type == DatabaseType.LIST) or (key_type == DatabaseType.MAP):
raise TypeError("Key type of type '{}' cannot be collection types".format(DatabaseType.MAP.name))
if (val_type == DatabaseType.LIST) or (val_type == DatabaseType.MAP):
raise TypeError("Value type of type '{}' cannot be collection types".format(DatabaseType.MAP.name))
# initialize
self.__type = DatabaseType.MAP
self.__key_type = key_type
self.__val_type = val_type
def __str__(self):
return "{}<{},{}>".format(self.__type.value, self.__key_type.value, self.__val_type.value)
def __repr__(self):
return self.__type.name
def type(self):
return self.__type
def to_str(self, type2str = None):
if type2str is None:
return self.__str__()
else:
return "{}<{},{}>".format(self.__type.value, type2str[self.__key_type], type2str[self.__val_type])
# test: correct
type2str = { DatabaseType.INTEGER: 'bigint', DatabaseType.REAL: 'double', DatabaseType.TEXT: 'string' }
int_type = IntegerType()
real_type = RealType()
text_type = TextType()
print("integer: {}\t{}".format(int_type.to_str(), int_type.to_str(type2str)))
print("real: {}\t{}".format(real_type.to_str(), real_type.to_str(type2str)))
print("text: {}\t{}".format(text_type.to_str(), text_type.to_str(type2str)))
print("direct use: {}\t{}".format(IntegerType().to_str(), RealType().to_str(type2str)))
list_t1 = ListType(DatabaseType.INTEGER)
list_t2 = ListType(DatabaseType.REAL)
list_t3 = ListType(DatabaseType.TEXT)
print("list: {}\t{}".format(list_t1.to_str(), list_t1.to_str(type2str)))
print("list: {}\t{}".format(list_t2.to_str(), list_t2.to_str(type2str)))
print("list: {}\t{}".format(list_t3.to_str(), list_t3.to_str(type2str)))
map_t1 = MapType(DatabaseType.INTEGER, DatabaseType.INTEGER)
map_t2 = MapType(DatabaseType.REAL, DatabaseType.REAL)
map_t3 = MapType(DatabaseType.TEXT, DatabaseType.TEXT)
map_t4 = MapType(DatabaseType.INTEGER, DatabaseType.REAL)
map_t5 = MapType(DatabaseType.INTEGER, DatabaseType.TEXT)
map_t6 = MapType(DatabaseType.REAL, DatabaseType.TEXT)
print("map: {}\t{}".format(map_t1.to_str(), map_t1.to_str(type2str)))
print("map: {}\t{}".format(map_t2.to_str(), map_t2.to_str(type2str)))
print("map: {}\t{}".format(map_t3.to_str(), map_t3.to_str(type2str)))
print("map: {}\t{}".format(map_t4.to_str(), map_t4.to_str(type2str)))
print("map: {}\t{}".format(map_t5.to_str(), map_t5.to_str(type2str)))
print("map: {}\t{}".format(map_t6.to_str(), map_t6.to_str(type2str)))
# test: exception
#new_type = TypeInterface()
#new_type = ListType(DatabaseType.LIST)
#new_type = ListType(DatabaseType.MAP)
#new_type = MapType(DatabaseType.LIST, DatabaseType.LIST)
#new_type = MapType(DatabaseType.MAP, DatabaseType.MAP)
#new_type = MapType(DatabaseType.LIST, DatabaseType.INTEGER)
#new_type = MapType(DatabaseType.REAL, DatabaseType.MAP)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment