diff --git a/clients/client-python/gravitino/api/type.py b/clients/client-python/gravitino/api/type.py index 5855fe7867..cf9d9003cc 100644 --- a/clients/client-python/gravitino/api/type.py +++ b/clients/client-python/gravitino/api/type.py @@ -116,50 +116,64 @@ class Name(Enum): EXTERNAL = "EXTERNAL" """ The external type. An external type represents a type that is not supported. """ + # Define the Type interface (abstract base class) class Type(ABC): @abstractmethod def name(self) -> Name: - """ Returns the generic name of the type. """ + """Returns the generic name of the type.""" pass @abstractmethod def simpleString(self) -> str: - """ Returns a readable string representation of the type. """ + """Returns a readable string representation of the type.""" pass + # Define base classes class PrimitiveType(Type, ABC): - """ Base class for all primitive types. """ + """Base class for all primitive types.""" + pass + class NumericType(PrimitiveType, ABC): - """ Base class for all numeric types. """ + """Base class for all numeric types.""" + pass + class DateTimeType(PrimitiveType, ABC): - """ Base class for all date/time types. """ + """Base class for all date/time types.""" + pass + class IntervalType(PrimitiveType, ABC): - """ Base class for all interval types. """ + """Base class for all interval types.""" + pass + class ComplexType(Type, ABC): - """ Base class for all complex types, including struct, list, map, and union. """ + """Base class for all complex types, including struct, list, map, and union.""" + pass + # Define IntegralType class class IntegralType(NumericType, ABC): def __init__(self, signed: bool): self._signed = signed def signed(self) -> bool: - """ Returns True if the integer type is signed, False otherwise. """ + """Returns True if the integer type is signed, False otherwise.""" return self._signed + # Define FractionType class class FractionType(NumericType, ABC): - """ Base class for all fractional types. """ + """Base class for all fractional types.""" + def __init__(self): super().__init__() diff --git a/clients/client-python/gravitino/api/types.py b/clients/client-python/gravitino/api/types.py index 5f10fdaf6d..601a198f56 100644 --- a/clients/client-python/gravitino/api/types.py +++ b/clients/client-python/gravitino/api/types.py @@ -14,13 +14,24 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -from .type import Type, Name, PrimitiveType, IntegralType, FractionType, DateTimeType, IntervalType, ComplexType +from .type import ( + Type, + Name, + PrimitiveType, + IntegralType, + FractionType, + DateTimeType, + IntervalType, + ComplexType, +) """ The helper class for Type. """ + + class Types: + """The data type representing `NULL` values.""" - """ The data type representing `NULL` values. """ class NullType(Type): _instance = None @@ -46,6 +57,7 @@ def simpleString(self) -> str: return "null" """ The boolean type in Gravitino. """ + class BooleanType(PrimitiveType): _instance = None @@ -71,6 +83,7 @@ def simpleString(self) -> str: return "boolean" """ The byte type in Gravitino. """ + class ByteType(IntegralType): _instance = None _unsigned_instance = None @@ -112,6 +125,7 @@ def simpleString(self) -> str: return "byte" if self.signed() else "byte unsigned" """ The short type in Gravitino. """ + class ShortType(IntegralType): _instance = None _unsigned_instance = None @@ -153,6 +167,7 @@ def simpleString(self) -> str: return "short" if self.signed() else "short unsigned" """ The integer type in Gravitino. """ + class IntegerType(IntegralType): _instance = None _unsigned_instance = None @@ -194,6 +209,7 @@ def simpleString(self) -> str: return "integer" if self.signed() else "integer unsigned" """ The long type in Gravitino. """ + class LongType(IntegralType): _instance = None _unsigned_instance = None @@ -235,6 +251,7 @@ def simpleString(self) -> str: return "long" if self.signed() else "long unsigned" """ The float type in Gravitino. """ + class FloatType(FractionType): _instance = None @@ -260,6 +277,7 @@ def simpleString(self) -> str: return "float" """ The double type in Gravitino. """ + class DoubleType(FractionType): _instance = None @@ -285,6 +303,7 @@ def simpleString(self) -> str: return "double" """ The decimal type in Gravitino. """ + class DecimalType(FractionType): @classmethod def of(cls, precision: int, scale: int): @@ -312,9 +331,13 @@ def check_precision_scale(precision: int, scale: int): @param scale: The scale of the decimal. """ if not (1 <= precision <= 38): - raise ValueError(f"Decimal precision must be in range [1, 38]: {precision}") + raise ValueError( + f"Decimal precision must be in range [1, 38]: {precision}" + ) if not (0 <= scale <= precision): - raise ValueError(f"Decimal scale must be in range [0, precision ({precision})]: {scale}") + raise ValueError( + f"Decimal scale must be in range [0, precision ({precision})]: {scale}" + ) def name(self) -> Name: """ @@ -339,11 +362,11 @@ def simpleString(self) -> str: @return A readable string representation of the Decimal type. """ return f"decimal({self._precision},{self._scale})" - + def __eq__(self, other): """ Compares two DecimalType objects for equality. - + @param other: The other DecimalType to compare with. @return: True if both objects have the same precision and scale, False otherwise. """ @@ -358,6 +381,7 @@ def __hash__(self): return hash((self._precision, self._scale)) """ The date time type in Gravitino. """ + class DateType(DateTimeType): _instance = None @@ -383,6 +407,7 @@ def simpleString(self) -> str: return "date" """ The time type in Gravitino. """ + class TimeType(DateTimeType): _instance = None @@ -408,6 +433,7 @@ def simpleString(self) -> str: return "time" """ The timestamp type in Gravitino. """ + class TimestampType(DateTimeType): _instance_with_tz = None _instance_without_tz = None @@ -455,6 +481,7 @@ def simpleString(self) -> str: return "timestamp_tz" if self._with_time_zone else "timestamp" """ The interval year type in Gravitino. """ + class IntervalYearType(IntervalType): _instance = None @@ -478,8 +505,9 @@ def simpleString(self) -> str: @return A readable string representation of the IntervalYear type. """ return "interval_year" - + """ The interval day type in Gravitino. """ + class IntervalDayType(IntervalType): _instance = None @@ -505,6 +533,7 @@ def simpleString(self) -> str: return "interval_day" """ The string type in Gravitino, equivalent to varchar(MAX), where the MAX is determined by the underlying catalog. """ + class StringType(PrimitiveType): _instance = None @@ -530,6 +559,7 @@ def simpleString(self) -> str: return "string" """ The UUID type in Gravitino. """ + class UUIDType(PrimitiveType): _instance = None @@ -555,6 +585,7 @@ def simpleString(self) -> str: return "uuid" """ Fixed-length byte array type. Use BinaryType for variable-length byte arrays. """ + class FixedType(PrimitiveType): def __init__(self, length: int): """ @@ -608,6 +639,7 @@ def __hash__(self): return hash(self._length) """ The varchar type in Gravitino. """ + class VarCharType(PrimitiveType): def __init__(self, length: int): """ @@ -661,6 +693,7 @@ def __hash__(self): return hash(self._length) """ The fixed char type in Gravitino. """ + class FixedCharType(PrimitiveType): def __init__(self, length: int): """ @@ -714,6 +747,7 @@ def __hash__(self): return hash(self._length) """ The binary type in Gravitino. """ + class BinaryType(PrimitiveType): _instance = None @@ -739,6 +773,7 @@ def simpleString(self) -> str: return "binary" """ The struct type in Gravitino. Note, this type is not supported in the current version of Gravitino.""" + class StructType(ComplexType): def __init__(self, fields): """ @@ -774,7 +809,9 @@ def simpleString(self) -> str: """ @return: A readable string representation of the struct type. """ - return f"struct<{', '.join(field.simpleString() for field in self._fields)}>" + return ( + f"struct<{', '.join(field.simpleString() for field in self._fields)}>" + ) def __eq__(self, other): """ @@ -794,6 +831,7 @@ def __hash__(self): return hash(tuple(self._fields)) """ A field of a struct type. """ + class Field: def __init__(self, name, type, nullable, comment=None): """ @@ -866,8 +904,12 @@ def __eq__(self, other): """ if not isinstance(other, Types.StructType.Field): return False - return (self._name == other._name and self._type == other._type and - self._nullable == other._nullable and self._comment == other._comment) + return ( + self._name == other._name + and self._type == other._type + and self._nullable == other._nullable + and self._comment == other._comment + ) def __hash__(self): """ @@ -884,6 +926,7 @@ def simpleString(self) -> str: return f"{self._name}: {self._type.simpleString()} {nullable_str}{comment_str}" """ A list type. Note, this type is not supported in the current version of Gravitino. """ + class ListType(ComplexType): def __init__(self, elementType: Type, elementNullable: bool): """ @@ -950,7 +993,11 @@ def simpleString(self) -> str: """ @return: A readable string representation of the list type. """ - return f"list<{self._elementType.simpleString()}>" if self._elementNullable else f"list<{self._elementType.simpleString()}, NOT NULL>" + return ( + f"list<{self._elementType.simpleString()}>" + if self._elementNullable + else f"list<{self._elementType.simpleString()}, NOT NULL>" + ) def __eq__(self, other): """ @@ -961,7 +1008,10 @@ def __eq__(self, other): """ if not isinstance(other, Types.ListType): return False - return self._elementNullable == other._elementNullable and self._elementType == other._elementType + return ( + self._elementNullable == other._elementNullable + and self._elementType == other._elementType + ) def __hash__(self): """ @@ -970,6 +1020,7 @@ def __hash__(self): return hash((self._elementType, self._elementNullable)) """ The map type in Gravitino. Note, this type is not supported in the current version of Gravitino. """ + class MapType(ComplexType): def __init__(self, keyType: Type, valueType: Type, valueNullable: bool): """ @@ -1045,7 +1096,9 @@ def simpleString(self) -> str: """ @return: A readable string representation of the map type. """ - return f"map<{self._keyType.simpleString()}, {self._valueType.simpleString()}>" + return ( + f"map<{self._keyType.simpleString()}, {self._valueType.simpleString()}>" + ) def __eq__(self, other): """ @@ -1056,7 +1109,11 @@ def __eq__(self, other): """ if not isinstance(other, Types.MapType): return False - return self._valueNullable == other._valueNullable and self._keyType == other._keyType and self._valueType == other._valueType + return ( + self._valueNullable == other._valueNullable + and self._keyType == other._keyType + and self._valueType == other._valueType + ) def __hash__(self): """ @@ -1065,6 +1122,7 @@ def __hash__(self): return hash((self._keyType, self._valueType, self._valueNullable)) """ The union type in Gravitino. Note, this type is not supported in the current version of Gravitino. """ + class UnionType(ComplexType): def __init__(self, types: list): """ @@ -1120,6 +1178,7 @@ def __hash__(self): return hash(tuple(self._types)) """ Represents a type that is not parsed yet. The parsed type is represented by other types of Types. """ + class UnparsedType(Type): def __init__(self, unparsedType: str): """ @@ -1181,6 +1240,7 @@ def __str__(self): return self._unparsedType """ Represents a type that is defined in an external catalog. """ + class ExternalType(Type): def __init__(self, catalogString: str): """ @@ -1250,4 +1310,3 @@ def allowAutoIncrement(dataType: Type) -> bool: @return: True if the given data type is allowed to be an auto-increment column, False otherwise. """ return isinstance(dataType, (Types.IntegerType, Types.LongType)) - diff --git a/clients/client-python/tests/unittests/test_types.py b/clients/client-python/tests/unittests/test_types.py index 270bfdf811..f4210c6314 100644 --- a/clients/client-python/tests/unittests/test_types.py +++ b/clients/client-python/tests/unittests/test_types.py @@ -20,25 +20,33 @@ class TestTypes(unittest.TestCase): - + # Test NullType singleton and methods def test_null_type(self): null_type_1 = Types.NullType.get() null_type_2 = Types.NullType.get() - - self.assertIs(null_type_1, null_type_2, "NullType should return the same singleton instance") + + self.assertIs( + null_type_1, + null_type_2, + "NullType should return the same singleton instance", + ) self.assertEqual(null_type_1.name(), Name.NULL) self.assertEqual(null_type_1.simpleString(), "null") - + # Test BooleanType singleton and methods def test_boolean_type(self): boolean_type_1 = Types.BooleanType.get() boolean_type_2 = Types.BooleanType.get() - self.assertIs(boolean_type_1, boolean_type_2, "BooleanType should return the same singleton instance") + self.assertIs( + boolean_type_1, + boolean_type_2, + "BooleanType should return the same singleton instance", + ) self.assertEqual(boolean_type_1.name(), Name.BOOLEAN) self.assertEqual(boolean_type_1.simpleString(), "boolean") - + # Test ByteType for signed and unsigned versions def test_byte_type(self): signed_byte = Types.ByteType.get() @@ -56,7 +64,7 @@ def test_short_type(self): self.assertEqual(signed_short.name(), Name.SHORT) self.assertEqual(signed_short.simpleString(), "short") self.assertEqual(unsigned_short.simpleString(), "short unsigned") - + # Test IntegerType for signed and unsigned versions def test_integer_type(self): signed_int = Types.IntegerType.get() @@ -65,7 +73,7 @@ def test_integer_type(self): self.assertEqual(signed_int.name(), Name.INTEGER) self.assertEqual(signed_int.simpleString(), "integer") self.assertEqual(unsigned_int.simpleString(), "integer unsigned") - + # Test DecimalType and its methods def test_decimal_type(self): decimal_type_1 = Types.DecimalType.of(10, 2) @@ -74,34 +82,58 @@ def test_decimal_type(self): self.assertEqual(decimal_type_1.name(), Name.DECIMAL) self.assertEqual(decimal_type_1.simpleString(), "decimal(10,2)") - self.assertEqual(decimal_type_1, decimal_type_2, "Decimal types with the same precision and scale should be equal") - self.assertNotEqual(decimal_type_1, decimal_type_3, "Decimal types with different precision/scale should not be equal") - self.assertNotEqual(hash(decimal_type_1), hash(decimal_type_3), "Different decimal types should have different hash codes") + self.assertEqual( + decimal_type_1, + decimal_type_2, + "Decimal types with the same precision and scale should be equal", + ) + self.assertNotEqual( + decimal_type_1, + decimal_type_3, + "Decimal types with different precision/scale should not be equal", + ) + self.assertNotEqual( + hash(decimal_type_1), + hash(decimal_type_3), + "Different decimal types should have different hash codes", + ) # Test DateType singleton and methods def test_date_type(self): date_type_1 = Types.DateType.get() date_type_2 = Types.DateType.get() - self.assertIs(date_type_1, date_type_2, "DateType should return the same singleton instance") + self.assertIs( + date_type_1, + date_type_2, + "DateType should return the same singleton instance", + ) self.assertEqual(date_type_1.name(), Name.DATE) self.assertEqual(date_type_1.simpleString(), "date") - + # Test TimeType singleton and methods def test_time_type(self): time_type_1 = Types.TimeType.get() time_type_2 = Types.TimeType.get() - self.assertIs(time_type_1, time_type_2, "TimeType should return the same singleton instance") + self.assertIs( + time_type_1, + time_type_2, + "TimeType should return the same singleton instance", + ) self.assertEqual(time_type_1.name(), Name.TIME) self.assertEqual(time_type_1.simpleString(), "time") - + # Test StringType singleton and methods def test_string_type(self): string_type_1 = Types.StringType.get() string_type_2 = Types.StringType.get() - self.assertIs(string_type_1, string_type_2, "StringType should return the same singleton instance") + self.assertIs( + string_type_1, + string_type_2, + "StringType should return the same singleton instance", + ) self.assertEqual(string_type_1.name(), Name.STRING) self.assertEqual(string_type_1.simpleString(), "string") @@ -110,7 +142,11 @@ def test_uuid_type(self): uuid_type_1 = Types.UUIDType.get() uuid_type_2 = Types.UUIDType.get() - self.assertIs(uuid_type_1, uuid_type_2, "UUIDType should return the same singleton instance") + self.assertIs( + uuid_type_1, + uuid_type_2, + "UUIDType should return the same singleton instance", + ) self.assertEqual(uuid_type_1.name(), Name.UUID) self.assertEqual(uuid_type_1.simpleString(), "uuid") @@ -144,4 +180,4 @@ def test_allow_auto_increment(self): self.assertTrue(Types.allowAutoIncrement(integer_type)) self.assertTrue(Types.allowAutoIncrement(long_type)) - self.assertFalse(Types.allowAutoIncrement(boolean_type)) \ No newline at end of file + self.assertFalse(Types.allowAutoIncrement(boolean_type))