From acfe51d49d001f7c5ef1bd22f56c44610703551d Mon Sep 17 00:00:00 2001 From: YUN SUN Date: Tue, 29 Oct 2024 22:08:15 -0500 Subject: [PATCH 1/9] [#5200]Update the type.py for python client. --- clients/client-python/gravitino/api/type.py | 148 ++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 clients/client-python/gravitino/api/type.py diff --git a/clients/client-python/gravitino/api/type.py b/clients/client-python/gravitino/api/type.py new file mode 100644 index 0000000000..c2399aa290 --- /dev/null +++ b/clients/client-python/gravitino/api/type.py @@ -0,0 +1,148 @@ +from abc import ABC, abstractmethod +from enum import Enum + +from enum import Enum + +class Name(Enum): + """ + The root type name of this type, representing all data types supported. + """ + + BOOLEAN = "BOOLEAN" + """ The boolean type. """ + + BYTE = "BYTE" + """ The byte type. """ + + SHORT = "SHORT" + """ The short type. """ + + INTEGER = "INTEGER" + """ The integer type. """ + + LONG = "LONG" + """ The long type. """ + + FLOAT = "FLOAT" + """ The float type. """ + + DOUBLE = "DOUBLE" + """ The double type. """ + + DECIMAL = "DECIMAL" + """ The decimal type. """ + + DATE = "DATE" + """ The date type. """ + + TIME = "TIME" + """ The time type. """ + + TIMESTAMP = "TIMESTAMP" + """ The timestamp type. """ + + INTERVAL_YEAR = "INTERVAL_YEAR" + """ The interval year type. """ + + INTERVAL_DAY = "INTERVAL_DAY" + """ The interval day type. """ + + STRING = "STRING" + """ The string type. """ + + VARCHAR = "VARCHAR" + """ The varchar type. """ + + FIXEDCHAR = "FIXEDCHAR" + """ The char type with fixed length. """ + + UUID = "UUID" + """ The UUID type. """ + + FIXED = "FIXED" + """ The binary type with fixed length. """ + + BINARY = "BINARY" + """ The binary type with variable length. The length is specified in the type itself. """ + + STRUCT = "STRUCT" + """ + The struct type. + A struct type is a complex type that contains a set of named fields, each with a type, + and optionally a comment. + """ + + LIST = "LIST" + """ + The list type. + A list type is a complex type that contains a set of elements, each with the same type. + """ + + MAP = "MAP" + """ + The map type. + A map type is a complex type that contains a set of key-value pairs, each with a key type + and a value type. + """ + + UNION = "UNION" + """ + The union type. + A union type is a complex type that contains a set of types. + """ + + NULL = "NULL" + """ The null type. A null type represents a value that is null. """ + + UNPARSED = "UNPARSED" + """ The unparsed type. An unparsed type represents an unresolvable type. """ + + 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. """ + pass + + @abstractmethod + def simpleString(self) -> str: + """ Returns a readable string representation of the type. """ + pass + +# Define base classes +class PrimitiveType(Type, ABC): + """ Base class for all primitive types. """ + pass + +class NumericType(PrimitiveType, ABC): + """ Base class for all numeric types. """ + pass + +class DateTimeType(PrimitiveType, ABC): + """ Base class for all date/time types. """ + pass + +class IntervalType(PrimitiveType, ABC): + """ Base class for all interval types. """ + pass + +class ComplexType(Type, ABC): + """ 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. """ + return self._signed + +# Define FractionType class +class FractionType(NumericType, ABC): + """ Base class for all fractional types. """ + pass From aff35d6941a25cd45684ca007edc0777de83fa49 Mon Sep 17 00:00:00 2001 From: YUN SUN Date: Tue, 29 Oct 2024 23:18:33 -0500 Subject: [PATCH 2/9] Update the types.java in python client --- clients/client-python/gravitino/api/type.py | 1238 ++++++++++++++++++- 1 file changed, 1236 insertions(+), 2 deletions(-) diff --git a/clients/client-python/gravitino/api/type.py b/clients/client-python/gravitino/api/type.py index c2399aa290..760692304b 100644 --- a/clients/client-python/gravitino/api/type.py +++ b/clients/client-python/gravitino/api/type.py @@ -1,7 +1,6 @@ from abc import ABC, abstractmethod from enum import Enum - -from enum import Enum +from typing import Optional class Name(Enum): """ @@ -146,3 +145,1238 @@ def signed(self) -> bool: class FractionType(NumericType, ABC): """ Base class for all fractional types. """ pass + +""" The helper class for Type. """ +class Types: + + """ The data type representing `NULL` values. """ + class NullType(Type): + _instance = None + + @classmethod + def get(cls): + """ + @return The singleton instance of NullType. + """ + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def name(self) -> Name: + """ + @return The name of the Null type. + """ + return Name.NULL + + def simpleString(self) -> str: + """ + @return A readable string representation of the Null type. + """ + return "null" + + """ The boolean type in Gravitino. """ + class BooleanType(PrimitiveType): + _instance = None + + @classmethod + def get(cls): + """ + @return The singleton instance of BooleanType. + """ + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def name(self) -> Name: + """ + @return The name of the Boolean type. + """ + return Name.BOOLEAN + + def simpleString(self) -> str: + """ + @return A readable string representation of the Boolean type. + """ + return "boolean" + + """ The byte type in Gravitino. """ + class ByteType(IntegralType): + _instance = None + _unsigned_instance = None + + @classmethod + def get(cls): + """ + @return The singleton instance of ByteType. + """ + if cls._instance is None: + cls._instance = cls(True) + return cls._instance + + @classmethod + def unsigned(cls): + """ + @return The singleton instance of unsigned ByteType. + """ + if cls._unsigned_instance is None: + cls._unsigned_instance = cls(False) + return cls._unsigned_instance + + def __init__(self, signed: bool): + """ + @param signed: True if the byte type is signed, False otherwise. + """ + super().__init__(signed) + + def name(self) -> Name: + """ + @return The name of the Byte type. + """ + return Name.BYTE + + def simpleString(self) -> str: + """ + @return A readable string representa + """ + return "byte" if self.signed() else "byte unsigned" + + """ The short type in Gravitino. """ + class ShortType(IntegralType): + _instance = None + _unsigned_instance = None + + @classmethod + def get(cls): + """ + @return The singleton instance of ShortType. + """ + if cls._instance is None: + cls._instance = cls(True) + return cls._instance + + @classmethod + def unsigned(cls): + """ + @return The singleton instance of unsigned ShortType. + """ + if cls._unsigned_instance is None: + cls._unsigned_instance = cls(False) + return cls._unsigned_instance + + def __init__(self, signed: bool): + """ + @param signed: True if the short type is signed, False otherwise. + """ + super().__init__(signed) + + def name(self) -> Name: + """ + @return The name of the Short type. + """ + return Name.SHORT + + def simpleString(self) -> str: + """ + @return A readable string representation of the Short type. + """ + return "short" if self.signed() else "short unsigned" + + """ The integer type in Gravitino. """ + class IntegerType(IntegralType): + _instance = None + _unsigned_instance = None + + @classmethod + def get(cls): + """ + @return The singleton instance of IntegerType. + """ + if cls._instance is None: + cls._instance = cls(True) + return cls._instance + + @classmethod + def unsigned(cls): + """ + @return The singleton instance of unsigned IntegerType. + """ + if cls._unsigned_instance is None: + cls._unsigned_instance = cls(False) + return cls._unsigned_instance + + def __init__(self, signed: bool): + """ + @param signed: True if the integer type is signed, False otherwise. + """ + super().__init__(signed) + + def name(self) -> Name: + """ + @return The name of the Integer type. + """ + return Name.INTEGER + + def simpleString(self) -> str: + """ + @return A readable string representation of the Integer type. + """ + return "integer" if self.signed() else "integer unsigned" + + """ The long type in Gravitino. """ + class LongType(IntegralType): + _instance = None + _unsigned_instance = None + + @classmethod + def get(cls): + """ + @return The singleton instance of LongType. + """ + if cls._instance is None: + cls._instance = cls(True) + return cls._instance + + @classmethod + def unsigned(cls): + """ + @return The singleton instance of unsigned LongType. + """ + if cls._unsigned_instance is None: + cls._unsigned_instance = cls(False) + return cls._unsigned_instance + + def __init__(self, signed: bool): + """ + @param signed: True if the long type is signed, False otherwise. + """ + super().__init__(signed) + + def name(self) -> Name: + """ + @return The name of the Long type. + """ + return Name.LONG + + def simpleString(self) -> str: + """ + @return A readable string representation of the Long type. + """ + return "long" if self.signed() else "long unsigned" + + """ The float type in Gravitino. """ + class FloatType(FractionType): + _instance = None + + @classmethod + def get(cls): + """ + @return The singleton instance of FloatType. + """ + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def name(self) -> Name: + """ + @return The name of the Float type. + """ + return Name.FLOAT + + def simpleString(self) -> str: + """ + @return A readable string representation of the Float type. + """ + return "float" + + """ The double type in Gravitino. """ + class DoubleType(FractionType): + _instance = None + + @classmethod + def get(cls): + """ + @return The singleton instance of DoubleType. + """ + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def name(self) -> Name: + """ + @return The name of the Double type. + """ + return Name.DOUBLE + + def simpleString(self) -> str: + """ + @return A readable string representation of the Double type. + """ + return "double" + + """ The decimal type in Gravitino. """ + class DecimalType(FractionType): + @classmethod + def of(cls, precision: int, scale: int): + """ + @param precision: The precision of the decimal type. + @param scale: The scale of the decimal type. + @return A DecimalType with the given precision and scale. + """ + return cls(precision, scale) + + def __init__(self, precision: int, scale: int): + """ + @param precision: The precision of the decimal type. + @param scale: The scale of the decimal type. + """ + self.check_precision_scale(precision, scale) + self._precision = precision + self._scale = scale + + @staticmethod + def check_precision_scale(precision: int, scale: int): + """ + Ensures the precision and scale values are within valid range. + @param precision: The precision of the decimal. + @param scale: The scale of the decimal. + """ + if not (1 <= precision <= 38): + 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}") + + def name(self) -> Name: + """ + @return The name of the Decimal type. + """ + return Name.DECIMAL + + def precision(self) -> int: + """ + @return The precision of the decimal type. + """ + return self._precision + + def scale(self) -> int: + """ + @return The scale of the decimal type. + """ + return self._scale + + 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. + """ + if not isinstance(other, Types.DecimalType): + return False + return self._precision == other._precision and self._scale == other._scale + + def __hash__(self): + """ + @return: A hash code for the DecimalType based on its precision and scale. + """ + return hash((self._precision, self._scale)) + + """ The date time type in Gravitino. """ + class DateType(DateTimeType): + _instance = None + + @classmethod + def get(cls): + """ + @return The singleton instance of DateType. + """ + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def name(self) -> Name: + """ + @return The name of the Date type. + """ + return Name.DATE + + def simpleString(self) -> str: + """ + @return A readable string representation of the Date type. + """ + return "date" + + """ The time type in Gravitino. """ + class TimeType(DateTimeType): + _instance = None + + @classmethod + def get(cls): + """ + @return The singleton instance of TimeType. + """ + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def name(self) -> Name: + """ + @return The name of the Time type. + """ + return Name.TIME + + def simpleString(self) -> str: + """ + @return A readable string representation of the Time type. + """ + return "time" + + """ The timestamp type in Gravitino. """ + class TimestampType(DateTimeType): + _instance_with_tz = None + _instance_without_tz = None + + @classmethod + def withTimeZone(cls): + """ + @return A TimestampType with time zone. + """ + if cls._instance_with_tz is None: + cls._instance_with_tz = cls(True) + return cls._instance_with_tz + + @classmethod + def withoutTimeZone(cls): + """ + @return A TimestampType without time zone. + """ + if cls._instance_without_tz is None: + cls._instance_without_tz = cls(False) + return cls._instance_without_tz + + def __init__(self, with_time_zone: bool): + """ + @param with_time_zone: True if the timestamp type has a time zone, False otherwise. + """ + self._with_time_zone = with_time_zone + + def hasTimeZone(self) -> bool: + """ + @return True if the timestamp type has a time zone, False otherwise. + """ + return self._with_time_zone + + def name(self) -> Name: + """ + @return The name of the Timestamp type. + """ + return Name.TIMESTAMP + + def simpleString(self) -> str: + """ + @return A readable string representation of the Timestamp type. + """ + return "timestamp_tz" if self._with_time_zone else "timestamp" + + """ The interval year type in Gravitino. """ + class IntervalYearType(IntervalType): + _instance = None + + @classmethod + def get(cls): + """ + @return The singleton instance of IntervalYearType. + """ + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def name(self) -> Name: + """ + @return The name of the IntervalYear type. + """ + return Name.INTERVAL_YEAR + + 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 + + @classmethod + def get(cls): + """ + @return: The singleton instance of IntervalDayType. + """ + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def name(self) -> Name: + """ + @return: The name of the interval day type. + """ + return Name.INTERVAL_DAY + + def simpleString(self) -> str: + """ + @return: A readable string representation of the interval day type. + """ + 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 + + @classmethod + def get(cls): + """ + @return: The singleton instance of StringType. + """ + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def name(self) -> Name: + """ + @return: The name of the string type. + """ + return Name.STRING + + def simpleString(self) -> str: + """ + @return: A readable string representation of the string type. + """ + return "string" + + """ The UUID type in Gravitino. """ + class UUIDType(PrimitiveType): + _instance = None + + @classmethod + def get(cls): + """ + @return: The singleton instance of UUIDType. + """ + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def name(self) -> Name: + """ + @return: The name of the UUID type. + """ + return Name.UUID + + def simpleString(self) -> str: + """ + @return: A readable string representation of the UUID type. + """ + return "uuid" + + """ Fixed-length byte array type. Use BinaryType for variable-length byte arrays. """ + class FixedType(PrimitiveType): + def __init__(self, length: int): + """ + Initializes the FixedType with the given length. + + @param length: The length of the fixed type. + """ + self._length = length + + @classmethod + def of(cls, length: int): + """ + @param length: The length of the fixed type. + @return: A FixedType instance with the given length. + """ + return cls(length) + + def name(self) -> Name: + """ + @return: The name of the fixed type. + """ + return Name.FIXED + + def length(self) -> int: + """ + @return: The length of the fixed type. + """ + return self._length + + def simpleString(self) -> str: + """ + @return: A readable string representation of the fixed type. + """ + return f"fixed({self._length})" + + def __eq__(self, other): + """ + Compares two FixedType objects for equality. + + @param other: The other FixedType object to compare with. + @return: True if both FixedType objects have the same length, False otherwise. + """ + if not isinstance(other, Types.FixedType): + return False + return self._length == other._length + + def __hash__(self): + """ + @return: A hash code for the FixedType based on its length. + """ + return hash(self._length) + + """ The varchar type in Gravitino. """ + class VarCharType(PrimitiveType): + def __init__(self, length: int): + """ + Initializes the VarCharType with the given length. + + @param length: The length of the varchar type. + """ + self._length = length + + @classmethod + def of(cls, length: int): + """ + @param length: The length of the varchar type. + @return: A VarCharType instance with the given length. + """ + return cls(length) + + def name(self) -> Name: + """ + @return: The name of the varchar type. + """ + return Name.VARCHAR + + def length(self) -> int: + """ + @return: The length of the varchar type. + """ + return self._length + + def simpleString(self) -> str: + """ + @return: A readable string representation of the varchar type. + """ + return f"varchar({self._length})" + + def __eq__(self, other): + """ + Compares two VarCharType objects for equality. + + @param other: The other VarCharType object to compare with. + @return: True if both VarCharType objects have the same length, False otherwise. + """ + if not isinstance(other, Types.VarCharType): + return False + return self._length == other._length + + def __hash__(self): + """ + @return: A hash code for the VarCharType based on its length. + """ + return hash(self._length) + + """ The fixed char type in Gravitino. """ + class FixedCharType(PrimitiveType): + def __init__(self, length: int): + """ + Initializes the FixedCharType with the given length. + + @param length: The length of the fixed char type. + """ + self._length = length + + @classmethod + def of(cls, length: int): + """ + @param length: The length of the fixed char type. + @return: A FixedCharType instance with the given length. + """ + return cls(length) + + def name(self) -> Name: + """ + @return: The name of the fixed char type. + """ + return Name.FIXEDCHAR + + def length(self) -> int: + """ + @return: The length of the fixed char type. + """ + return self._length + + def simpleString(self) -> str: + """ + @return: A readable string representation of the fixed char type. + """ + return f"char({self._length})" + + def __eq__(self, other): + """ + Compares two FixedCharType objects for equality. + + @param other: The other FixedCharType object to compare with. + @return: True if both FixedCharType objects have the same length, False otherwise. + """ + if not isinstance(other, Types.FixedCharType): + return False + return self._length == other._length + + def __hash__(self): + """ + @return: A hash code for the FixedCharType based on its length. + """ + return hash(self._length) + + """ The binary type in Gravitino. """ + class BinaryType(PrimitiveType): + _instance = None + + @classmethod + def get(cls): + """ + @return: The singleton instance of BinaryType. + """ + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def name(self) -> Name: + """ + @return: The name of the binary type. + """ + return Name.BINARY + + def simpleString(self) -> str: + """ + @return: A readable string representation of the binary type. + """ + 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): + """ + Initializes the StructType with the given fields. + + @param fields: The fields of the struct type. + """ + if not fields or len(fields) == 0: + raise ValueError("fields cannot be null or empty") + self._fields = fields + + @classmethod + def of(cls, *fields): + """ + @param fields: The fields of the struct type. + @return: A StructType instance with the given fields. + """ + return cls(fields) + + def fields(self): + """ + @return: The fields of the struct type. + """ + return self._fields + + def name(self) -> Name: + """ + @return: The name of the struct type. + """ + return Name.STRUCT + + def simpleString(self) -> str: + """ + @return: A readable string representation of the struct type. + """ + return f"struct<{', '.join(field.simpleString() for field in self._fields)}>" + + def __eq__(self, other): + """ + Compares two StructType objects for equality. + + @param other: The other StructType object to compare with. + @return: True if both StructType objects have the same fields, False otherwise. + """ + if not isinstance(other, Types.StructType): + return False + return self._fields == other._fields + + def __hash__(self): + """ + @return: A hash code for the StructType based on its fields. + """ + return hash(tuple(self._fields)) + + """ A field of a struct type. """ + class Field: + def __init__(self, name, type, nullable, comment=None): + """ + Initializes the Field with the given name, type, nullable flag, and comment. + + @param name: The name of the field. + @param type: The type of the field. + @param nullable: Whether the field is nullable. + @param comment: The comment of the field (optional). + """ + if name is None: + raise ValueError("name cannot be null") + if type is None: + raise ValueError("type cannot be null") + self._name = name + self._type = type + self._nullable = nullable + self._comment = comment + + @classmethod + def notNullField(cls, name, type, comment=None): + """ + @param name: The name of the field. + @param type: The type of the field. + @param comment: The comment of the field. + @return: A NOT NULL Field instance with the given name, type, and comment. + """ + return cls(name, type, False, comment) + + @classmethod + def nullableField(cls, name, type, comment=None): + """ + @param name: The name of the field. + @param type: The type of the field. + @param comment: The comment of the field. + @return: A nullable Field instance with the given name, type, and comment. + """ + return cls(name, type, True, comment) + + def name(self): + """ + @return: The name of the field. + """ + return self._name + + def type(self): + """ + @return: The type of the field. + """ + return self._type + + def nullable(self): + """ + @return: Whether the field is nullable. + """ + return self._nullable + + def comment(self): + """ + @return: The comment of the field, or None if not set. + """ + return self._comment + + def __eq__(self, other): + """ + Compares two Field objects for equality. + + @param other: The other Field object to compare with. + @return: True if both Field objects have the same attributes, False otherwise. + """ + 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) + + def __hash__(self): + """ + @return: A hash code for the Field based on its attributes. + """ + return hash((self._name, self._type, self._nullable)) + + def simpleString(self) -> str: + """ + @return: The simple string representation of the field. + """ + nullable_str = "NULL" if self._nullable else "NOT NULL" + comment_str = f" COMMENT '{self._comment}'" if self._comment else "" + 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): + """ + Create a new ListType with the given element type and the type is nullable. + + @param elementType: The element type of the list. + @param elementNullable: Whether the element of the list is nullable. + """ + if elementType is None: + raise ValueError("elementType cannot be null") + self._elementType = elementType + self._elementNullable = elementNullable + + @classmethod + def nullable(cls, elementType: Type): + """ + Create a new ListType with the given element type and the type is nullable. + + @param elementType: The element type of the list. + @return: A new ListType instance. + """ + return cls.of(elementType, True) + + @classmethod + def notNull(cls, elementType: Type): + """ + Create a new ListType with the given element type. + + @param elementType: The element type of the list. + @return: A new ListType instance. + """ + return cls.of(elementType, False) + + @classmethod + def of(cls, elementType: Type, elementNullable: bool): + """ + Create a new ListType with the given element type and whether the element is nullable. + + @param elementType: The element type of the list. + @param elementNullable: Whether the element of the list is nullable. + @return: A new ListType instance. + """ + return cls(elementType, elementNullable) + + def elementType(self) -> Type: + """ + @return: The element type of the list. + """ + return self._elementType + + def elementNullable(self) -> bool: + """ + @return: Whether the element of the list is nullable. + """ + return self._elementNullable + + def name(self) -> Name: + """ + @return: The name of the list type. + """ + return Name.LIST + + 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>" + + def __eq__(self, other): + """ + Compares two ListType objects for equality. + + @param other: The other ListType object to compare with. + @return: True if both ListType objects have the same element type and nullability, False otherwise. + """ + if not isinstance(other, Types.ListType): + return False + return self._elementNullable == other._elementNullable and self._elementType == other._elementType + + def __hash__(self): + """ + @return: A hash code for the ListType based on its element type and nullability. + """ + 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): + """ + Create a new MapType with the given key type, value type and the value is nullable. + + @param keyType: The key type of the map. + @param valueType: The value type of the map. + @param valueNullable: Whether the value of the map is nullable. + """ + self._keyType = keyType + self._valueType = valueType + self._valueNullable = valueNullable + + @classmethod + def valueNullable(cls, keyType: Type, valueType: Type): + """ + Create a new MapType with the given key type, value type, and the value is nullable. + + @param keyType: The key type of the map. + @param valueType: The value type of the map. + @return: A new MapType instance. + """ + return cls.of(keyType, valueType, True) + + @classmethod + def valueNotNull(cls, keyType: Type, valueType: Type): + """ + Create a new MapType with the given key type, value type, and the value is not nullable. + + @param keyType: The key type of the map. + @param valueType: The value type of the map. + @return: A new MapType instance. + """ + return cls.of(keyType, valueType, False) + + @classmethod + def of(cls, keyType: Type, valueType: Type, valueNullable: bool): + """ + Create a new MapType with the given key type, value type, and whether the value is nullable. + + @param keyType: The key type of the map. + @param valueType: The value type of the map. + @param valueNullable: Whether the value of the map is nullable. + @return: A new MapType instance. + """ + return cls(keyType, valueType, valueNullable) + + def keyType(self) -> Type: + """ + @return: The key type of the map. + """ + return self._keyType + + def valueType(self) -> Type: + """ + @return: The value type of the map. + """ + return self._valueType + + def valueNullable(self) -> bool: + """ + @return: Whether the value of the map is nullable. + """ + return self._valueNullable + + def name(self) -> Name: + """ + @return: The name of the map type. + """ + return Name.MAP + + def simpleString(self) -> str: + """ + @return: A readable string representation of the map type. + """ + return f"map<{self._keyType.simpleString()}, {self._valueType.simpleString()}>" + + def __eq__(self, other): + """ + Compares two MapType objects for equality. + + @param other: The other MapType object to compare with. + @return: True if both MapType objects have the same key type, value type, and nullability, False otherwise. + """ + if not isinstance(other, Types.MapType): + return False + return self._valueNullable == other._valueNullable and self._keyType == other._keyType and self._valueType == other._valueType + + def __hash__(self): + """ + @return: A hash code for the MapType based on its key type, value type, and nullability. + """ + 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): + """ + Create a new UnionType with the given types. + + @param types: The types of the union. + """ + self._types = types + + @classmethod + def of(cls, *types: Type): + """ + Create a new UnionType with the given types. + + @param types: The types of the union. + @return: A new UnionType instance. + """ + return cls(types) + + def types(self) -> list: + """ + @return: The types of the union. + """ + return self._types + + def name(self) -> Name: + """ + @return: The name of the union type. + """ + return Name.UNION + + def simpleString(self) -> str: + """ + @return: A readable string representation of the union type. + """ + return f"union<{', '.join(t.simpleString() for t in self._types)}>" + + def __eq__(self, other): + """ + Compares two UnionType objects for equality. + + @param other: The other UnionType object to compare with. + @return: True if both UnionType objects have the same types, False otherwise. + """ + if not isinstance(other, Types.UnionType): + return False + return self._types == other._types + + def __hash__(self): + """ + @return: A hash code for the UnionType based on its types. + """ + 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): + """ + Initializes an UnparsedType instance. + + @param unparsedType: The unparsed type as a string. + """ + self._unparsedType = unparsedType + + @classmethod + def of(cls, unparsedType: str): + """ + Creates a new UnparsedType with the given unparsed type. + + @param unparsedType: The unparsed type. + @return: A new UnparsedType instance. + """ + return cls(unparsedType) + + def unparsedType(self) -> str: + """ + @return: The unparsed type as a string. + """ + return self._unparsedType + + def name(self) -> Name: + """ + @return: The name of the unparsed type. + """ + return Name.UNPARSED + + def simpleString(self) -> str: + """ + @return: A readable string representation of the unparsed type. + """ + return f"unparsed({self._unparsedType})" + + def __eq__(self, other): + """ + Compares two UnparsedType objects for equality. + + @param other: The other UnparsedType object to compare with. + @return: True if both UnparsedType objects have the same unparsed type string, False otherwise. + """ + if not isinstance(other, Types.UnparsedType): + return False + return self._unparsedType == other._unparsedType + + def __hash__(self): + """ + @return: A hash code for the UnparsedType based on its unparsed type string. + """ + return hash(self._unparsedType) + + def __str__(self): + """ + @return: The unparsed type string representation. + """ + return self._unparsedType + + """ Represents a type that is defined in an external catalog. """ + class ExternalType(Type): + def __init__(self, catalogString: str): + """ + Initializes an ExternalType instance. + + @param catalogString: The string representation of this type in the catalog. + """ + self._catalogString = catalogString + + @classmethod + def of(cls, catalogString: str): + """ + Creates a new ExternalType with the given catalog string. + + @param catalogString: The string representation of this type in the catalog. + @return: A new ExternalType instance. + """ + return cls(catalogString) + + def catalogString(self) -> str: + """ + @return: The string representation of this type in external catalog. + """ + return self._catalogString + + def name(self) -> Name: + """ + @return: The name of the external type. + """ + return Name.EXTERNAL + + def simpleString(self) -> str: + """ + @return: A readable string representation of the external type. + """ + return f"external({self._catalogString})" + + def __eq__(self, other): + """ + Compares two ExternalType objects for equality. + + @param other: The other ExternalType object to compare with. + @return: True if both ExternalType objects have the same catalog string, False otherwise. + """ + if not isinstance(other, Types.ExternalType): + return False + return self._catalogString == other._catalogString + + def __hash__(self): + """ + @return: A hash code for the ExternalType based on its catalog string. + """ + return hash(self._catalogString) + + def __str__(self): + """ + @return: The string representation of the external type. + """ + return self.simpleString() + + @staticmethod + def allowAutoIncrement(dataType: Type) -> bool: + """ + Checks if the given data type is allowed to be an auto-increment column. + + @param dataType: The data type to check. + @return: True if the given data type is allowed to be an auto-increment column, False otherwise. + """ + return isinstance(dataType, (Types.IntegerType, Types.LongType)) + From 2e5c47b6d798a3d0602b7029d600afa73689b83d Mon Sep 17 00:00:00 2001 From: YUN SUN Date: Tue, 29 Oct 2024 23:31:25 -0500 Subject: [PATCH 3/9] Separate to type.py and types.py --- clients/client-python/gravitino/api/type.py | 1258 +----------------- clients/client-python/gravitino/api/types.py | 1254 +++++++++++++++++ 2 files changed, 1276 insertions(+), 1236 deletions(-) create mode 100644 clients/client-python/gravitino/api/types.py diff --git a/clients/client-python/gravitino/api/type.py b/clients/client-python/gravitino/api/type.py index 760692304b..c32b6215bd 100644 --- a/clients/client-python/gravitino/api/type.py +++ b/clients/client-python/gravitino/api/type.py @@ -1,7 +1,27 @@ +""" +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +""" + from abc import ABC, abstractmethod from enum import Enum from typing import Optional + class Name(Enum): """ The root type name of this type, representing all data types supported. @@ -144,1239 +164,5 @@ def signed(self) -> bool: # Define FractionType class class FractionType(NumericType, ABC): """ Base class for all fractional types. """ - pass - -""" The helper class for Type. """ -class Types: - - """ The data type representing `NULL` values. """ - class NullType(Type): - _instance = None - - @classmethod - def get(cls): - """ - @return The singleton instance of NullType. - """ - if cls._instance is None: - cls._instance = cls() - return cls._instance - - def name(self) -> Name: - """ - @return The name of the Null type. - """ - return Name.NULL - - def simpleString(self) -> str: - """ - @return A readable string representation of the Null type. - """ - return "null" - - """ The boolean type in Gravitino. """ - class BooleanType(PrimitiveType): - _instance = None - - @classmethod - def get(cls): - """ - @return The singleton instance of BooleanType. - """ - if cls._instance is None: - cls._instance = cls() - return cls._instance - - def name(self) -> Name: - """ - @return The name of the Boolean type. - """ - return Name.BOOLEAN - - def simpleString(self) -> str: - """ - @return A readable string representation of the Boolean type. - """ - return "boolean" - - """ The byte type in Gravitino. """ - class ByteType(IntegralType): - _instance = None - _unsigned_instance = None - - @classmethod - def get(cls): - """ - @return The singleton instance of ByteType. - """ - if cls._instance is None: - cls._instance = cls(True) - return cls._instance - - @classmethod - def unsigned(cls): - """ - @return The singleton instance of unsigned ByteType. - """ - if cls._unsigned_instance is None: - cls._unsigned_instance = cls(False) - return cls._unsigned_instance - - def __init__(self, signed: bool): - """ - @param signed: True if the byte type is signed, False otherwise. - """ - super().__init__(signed) - - def name(self) -> Name: - """ - @return The name of the Byte type. - """ - return Name.BYTE - - def simpleString(self) -> str: - """ - @return A readable string representa - """ - return "byte" if self.signed() else "byte unsigned" - - """ The short type in Gravitino. """ - class ShortType(IntegralType): - _instance = None - _unsigned_instance = None - - @classmethod - def get(cls): - """ - @return The singleton instance of ShortType. - """ - if cls._instance is None: - cls._instance = cls(True) - return cls._instance - - @classmethod - def unsigned(cls): - """ - @return The singleton instance of unsigned ShortType. - """ - if cls._unsigned_instance is None: - cls._unsigned_instance = cls(False) - return cls._unsigned_instance - - def __init__(self, signed: bool): - """ - @param signed: True if the short type is signed, False otherwise. - """ - super().__init__(signed) - - def name(self) -> Name: - """ - @return The name of the Short type. - """ - return Name.SHORT - - def simpleString(self) -> str: - """ - @return A readable string representation of the Short type. - """ - return "short" if self.signed() else "short unsigned" - - """ The integer type in Gravitino. """ - class IntegerType(IntegralType): - _instance = None - _unsigned_instance = None - - @classmethod - def get(cls): - """ - @return The singleton instance of IntegerType. - """ - if cls._instance is None: - cls._instance = cls(True) - return cls._instance - - @classmethod - def unsigned(cls): - """ - @return The singleton instance of unsigned IntegerType. - """ - if cls._unsigned_instance is None: - cls._unsigned_instance = cls(False) - return cls._unsigned_instance - - def __init__(self, signed: bool): - """ - @param signed: True if the integer type is signed, False otherwise. - """ - super().__init__(signed) - - def name(self) -> Name: - """ - @return The name of the Integer type. - """ - return Name.INTEGER - - def simpleString(self) -> str: - """ - @return A readable string representation of the Integer type. - """ - return "integer" if self.signed() else "integer unsigned" - - """ The long type in Gravitino. """ - class LongType(IntegralType): - _instance = None - _unsigned_instance = None - - @classmethod - def get(cls): - """ - @return The singleton instance of LongType. - """ - if cls._instance is None: - cls._instance = cls(True) - return cls._instance - - @classmethod - def unsigned(cls): - """ - @return The singleton instance of unsigned LongType. - """ - if cls._unsigned_instance is None: - cls._unsigned_instance = cls(False) - return cls._unsigned_instance - - def __init__(self, signed: bool): - """ - @param signed: True if the long type is signed, False otherwise. - """ - super().__init__(signed) - - def name(self) -> Name: - """ - @return The name of the Long type. - """ - return Name.LONG - - def simpleString(self) -> str: - """ - @return A readable string representation of the Long type. - """ - return "long" if self.signed() else "long unsigned" - - """ The float type in Gravitino. """ - class FloatType(FractionType): - _instance = None - - @classmethod - def get(cls): - """ - @return The singleton instance of FloatType. - """ - if cls._instance is None: - cls._instance = cls() - return cls._instance - - def name(self) -> Name: - """ - @return The name of the Float type. - """ - return Name.FLOAT - - def simpleString(self) -> str: - """ - @return A readable string representation of the Float type. - """ - return "float" - - """ The double type in Gravitino. """ - class DoubleType(FractionType): - _instance = None - - @classmethod - def get(cls): - """ - @return The singleton instance of DoubleType. - """ - if cls._instance is None: - cls._instance = cls() - return cls._instance - - def name(self) -> Name: - """ - @return The name of the Double type. - """ - return Name.DOUBLE - - def simpleString(self) -> str: - """ - @return A readable string representation of the Double type. - """ - return "double" - - """ The decimal type in Gravitino. """ - class DecimalType(FractionType): - @classmethod - def of(cls, precision: int, scale: int): - """ - @param precision: The precision of the decimal type. - @param scale: The scale of the decimal type. - @return A DecimalType with the given precision and scale. - """ - return cls(precision, scale) - - def __init__(self, precision: int, scale: int): - """ - @param precision: The precision of the decimal type. - @param scale: The scale of the decimal type. - """ - self.check_precision_scale(precision, scale) - self._precision = precision - self._scale = scale - - @staticmethod - def check_precision_scale(precision: int, scale: int): - """ - Ensures the precision and scale values are within valid range. - @param precision: The precision of the decimal. - @param scale: The scale of the decimal. - """ - if not (1 <= precision <= 38): - 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}") - - def name(self) -> Name: - """ - @return The name of the Decimal type. - """ - return Name.DECIMAL - - def precision(self) -> int: - """ - @return The precision of the decimal type. - """ - return self._precision - - def scale(self) -> int: - """ - @return The scale of the decimal type. - """ - return self._scale - - 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. - """ - if not isinstance(other, Types.DecimalType): - return False - return self._precision == other._precision and self._scale == other._scale - - def __hash__(self): - """ - @return: A hash code for the DecimalType based on its precision and scale. - """ - return hash((self._precision, self._scale)) - - """ The date time type in Gravitino. """ - class DateType(DateTimeType): - _instance = None - - @classmethod - def get(cls): - """ - @return The singleton instance of DateType. - """ - if cls._instance is None: - cls._instance = cls() - return cls._instance - - def name(self) -> Name: - """ - @return The name of the Date type. - """ - return Name.DATE - - def simpleString(self) -> str: - """ - @return A readable string representation of the Date type. - """ - return "date" - - """ The time type in Gravitino. """ - class TimeType(DateTimeType): - _instance = None - - @classmethod - def get(cls): - """ - @return The singleton instance of TimeType. - """ - if cls._instance is None: - cls._instance = cls() - return cls._instance - - def name(self) -> Name: - """ - @return The name of the Time type. - """ - return Name.TIME - - def simpleString(self) -> str: - """ - @return A readable string representation of the Time type. - """ - return "time" - - """ The timestamp type in Gravitino. """ - class TimestampType(DateTimeType): - _instance_with_tz = None - _instance_without_tz = None - - @classmethod - def withTimeZone(cls): - """ - @return A TimestampType with time zone. - """ - if cls._instance_with_tz is None: - cls._instance_with_tz = cls(True) - return cls._instance_with_tz - - @classmethod - def withoutTimeZone(cls): - """ - @return A TimestampType without time zone. - """ - if cls._instance_without_tz is None: - cls._instance_without_tz = cls(False) - return cls._instance_without_tz - - def __init__(self, with_time_zone: bool): - """ - @param with_time_zone: True if the timestamp type has a time zone, False otherwise. - """ - self._with_time_zone = with_time_zone - - def hasTimeZone(self) -> bool: - """ - @return True if the timestamp type has a time zone, False otherwise. - """ - return self._with_time_zone - - def name(self) -> Name: - """ - @return The name of the Timestamp type. - """ - return Name.TIMESTAMP - - def simpleString(self) -> str: - """ - @return A readable string representation of the Timestamp type. - """ - return "timestamp_tz" if self._with_time_zone else "timestamp" - - """ The interval year type in Gravitino. """ - class IntervalYearType(IntervalType): - _instance = None - - @classmethod - def get(cls): - """ - @return The singleton instance of IntervalYearType. - """ - if cls._instance is None: - cls._instance = cls() - return cls._instance - - def name(self) -> Name: - """ - @return The name of the IntervalYear type. - """ - return Name.INTERVAL_YEAR - - 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 - - @classmethod - def get(cls): - """ - @return: The singleton instance of IntervalDayType. - """ - if cls._instance is None: - cls._instance = cls() - return cls._instance - - def name(self) -> Name: - """ - @return: The name of the interval day type. - """ - return Name.INTERVAL_DAY - - def simpleString(self) -> str: - """ - @return: A readable string representation of the interval day type. - """ - 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 - - @classmethod - def get(cls): - """ - @return: The singleton instance of StringType. - """ - if cls._instance is None: - cls._instance = cls() - return cls._instance - - def name(self) -> Name: - """ - @return: The name of the string type. - """ - return Name.STRING - - def simpleString(self) -> str: - """ - @return: A readable string representation of the string type. - """ - return "string" - - """ The UUID type in Gravitino. """ - class UUIDType(PrimitiveType): - _instance = None - - @classmethod - def get(cls): - """ - @return: The singleton instance of UUIDType. - """ - if cls._instance is None: - cls._instance = cls() - return cls._instance - - def name(self) -> Name: - """ - @return: The name of the UUID type. - """ - return Name.UUID - - def simpleString(self) -> str: - """ - @return: A readable string representation of the UUID type. - """ - return "uuid" - - """ Fixed-length byte array type. Use BinaryType for variable-length byte arrays. """ - class FixedType(PrimitiveType): - def __init__(self, length: int): - """ - Initializes the FixedType with the given length. - - @param length: The length of the fixed type. - """ - self._length = length - - @classmethod - def of(cls, length: int): - """ - @param length: The length of the fixed type. - @return: A FixedType instance with the given length. - """ - return cls(length) - - def name(self) -> Name: - """ - @return: The name of the fixed type. - """ - return Name.FIXED - - def length(self) -> int: - """ - @return: The length of the fixed type. - """ - return self._length - - def simpleString(self) -> str: - """ - @return: A readable string representation of the fixed type. - """ - return f"fixed({self._length})" - - def __eq__(self, other): - """ - Compares two FixedType objects for equality. - - @param other: The other FixedType object to compare with. - @return: True if both FixedType objects have the same length, False otherwise. - """ - if not isinstance(other, Types.FixedType): - return False - return self._length == other._length - - def __hash__(self): - """ - @return: A hash code for the FixedType based on its length. - """ - return hash(self._length) - - """ The varchar type in Gravitino. """ - class VarCharType(PrimitiveType): - def __init__(self, length: int): - """ - Initializes the VarCharType with the given length. - - @param length: The length of the varchar type. - """ - self._length = length - - @classmethod - def of(cls, length: int): - """ - @param length: The length of the varchar type. - @return: A VarCharType instance with the given length. - """ - return cls(length) - - def name(self) -> Name: - """ - @return: The name of the varchar type. - """ - return Name.VARCHAR - - def length(self) -> int: - """ - @return: The length of the varchar type. - """ - return self._length - - def simpleString(self) -> str: - """ - @return: A readable string representation of the varchar type. - """ - return f"varchar({self._length})" - - def __eq__(self, other): - """ - Compares two VarCharType objects for equality. - - @param other: The other VarCharType object to compare with. - @return: True if both VarCharType objects have the same length, False otherwise. - """ - if not isinstance(other, Types.VarCharType): - return False - return self._length == other._length - - def __hash__(self): - """ - @return: A hash code for the VarCharType based on its length. - """ - return hash(self._length) - - """ The fixed char type in Gravitino. """ - class FixedCharType(PrimitiveType): - def __init__(self, length: int): - """ - Initializes the FixedCharType with the given length. - - @param length: The length of the fixed char type. - """ - self._length = length - - @classmethod - def of(cls, length: int): - """ - @param length: The length of the fixed char type. - @return: A FixedCharType instance with the given length. - """ - return cls(length) - - def name(self) -> Name: - """ - @return: The name of the fixed char type. - """ - return Name.FIXEDCHAR - - def length(self) -> int: - """ - @return: The length of the fixed char type. - """ - return self._length - - def simpleString(self) -> str: - """ - @return: A readable string representation of the fixed char type. - """ - return f"char({self._length})" - - def __eq__(self, other): - """ - Compares two FixedCharType objects for equality. - - @param other: The other FixedCharType object to compare with. - @return: True if both FixedCharType objects have the same length, False otherwise. - """ - if not isinstance(other, Types.FixedCharType): - return False - return self._length == other._length - - def __hash__(self): - """ - @return: A hash code for the FixedCharType based on its length. - """ - return hash(self._length) - - """ The binary type in Gravitino. """ - class BinaryType(PrimitiveType): - _instance = None - - @classmethod - def get(cls): - """ - @return: The singleton instance of BinaryType. - """ - if cls._instance is None: - cls._instance = cls() - return cls._instance - - def name(self) -> Name: - """ - @return: The name of the binary type. - """ - return Name.BINARY - - def simpleString(self) -> str: - """ - @return: A readable string representation of the binary type. - """ - 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): - """ - Initializes the StructType with the given fields. - - @param fields: The fields of the struct type. - """ - if not fields or len(fields) == 0: - raise ValueError("fields cannot be null or empty") - self._fields = fields - - @classmethod - def of(cls, *fields): - """ - @param fields: The fields of the struct type. - @return: A StructType instance with the given fields. - """ - return cls(fields) - - def fields(self): - """ - @return: The fields of the struct type. - """ - return self._fields - - def name(self) -> Name: - """ - @return: The name of the struct type. - """ - return Name.STRUCT - - def simpleString(self) -> str: - """ - @return: A readable string representation of the struct type. - """ - return f"struct<{', '.join(field.simpleString() for field in self._fields)}>" - - def __eq__(self, other): - """ - Compares two StructType objects for equality. - - @param other: The other StructType object to compare with. - @return: True if both StructType objects have the same fields, False otherwise. - """ - if not isinstance(other, Types.StructType): - return False - return self._fields == other._fields - - def __hash__(self): - """ - @return: A hash code for the StructType based on its fields. - """ - return hash(tuple(self._fields)) - - """ A field of a struct type. """ - class Field: - def __init__(self, name, type, nullable, comment=None): - """ - Initializes the Field with the given name, type, nullable flag, and comment. - - @param name: The name of the field. - @param type: The type of the field. - @param nullable: Whether the field is nullable. - @param comment: The comment of the field (optional). - """ - if name is None: - raise ValueError("name cannot be null") - if type is None: - raise ValueError("type cannot be null") - self._name = name - self._type = type - self._nullable = nullable - self._comment = comment - - @classmethod - def notNullField(cls, name, type, comment=None): - """ - @param name: The name of the field. - @param type: The type of the field. - @param comment: The comment of the field. - @return: A NOT NULL Field instance with the given name, type, and comment. - """ - return cls(name, type, False, comment) - - @classmethod - def nullableField(cls, name, type, comment=None): - """ - @param name: The name of the field. - @param type: The type of the field. - @param comment: The comment of the field. - @return: A nullable Field instance with the given name, type, and comment. - """ - return cls(name, type, True, comment) - - def name(self): - """ - @return: The name of the field. - """ - return self._name - - def type(self): - """ - @return: The type of the field. - """ - return self._type - - def nullable(self): - """ - @return: Whether the field is nullable. - """ - return self._nullable - - def comment(self): - """ - @return: The comment of the field, or None if not set. - """ - return self._comment - - def __eq__(self, other): - """ - Compares two Field objects for equality. - - @param other: The other Field object to compare with. - @return: True if both Field objects have the same attributes, False otherwise. - """ - 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) - - def __hash__(self): - """ - @return: A hash code for the Field based on its attributes. - """ - return hash((self._name, self._type, self._nullable)) - - def simpleString(self) -> str: - """ - @return: The simple string representation of the field. - """ - nullable_str = "NULL" if self._nullable else "NOT NULL" - comment_str = f" COMMENT '{self._comment}'" if self._comment else "" - 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): - """ - Create a new ListType with the given element type and the type is nullable. - - @param elementType: The element type of the list. - @param elementNullable: Whether the element of the list is nullable. - """ - if elementType is None: - raise ValueError("elementType cannot be null") - self._elementType = elementType - self._elementNullable = elementNullable - - @classmethod - def nullable(cls, elementType: Type): - """ - Create a new ListType with the given element type and the type is nullable. - - @param elementType: The element type of the list. - @return: A new ListType instance. - """ - return cls.of(elementType, True) - - @classmethod - def notNull(cls, elementType: Type): - """ - Create a new ListType with the given element type. - - @param elementType: The element type of the list. - @return: A new ListType instance. - """ - return cls.of(elementType, False) - - @classmethod - def of(cls, elementType: Type, elementNullable: bool): - """ - Create a new ListType with the given element type and whether the element is nullable. - - @param elementType: The element type of the list. - @param elementNullable: Whether the element of the list is nullable. - @return: A new ListType instance. - """ - return cls(elementType, elementNullable) - - def elementType(self) -> Type: - """ - @return: The element type of the list. - """ - return self._elementType - - def elementNullable(self) -> bool: - """ - @return: Whether the element of the list is nullable. - """ - return self._elementNullable - - def name(self) -> Name: - """ - @return: The name of the list type. - """ - return Name.LIST - - 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>" - - def __eq__(self, other): - """ - Compares two ListType objects for equality. - - @param other: The other ListType object to compare with. - @return: True if both ListType objects have the same element type and nullability, False otherwise. - """ - if not isinstance(other, Types.ListType): - return False - return self._elementNullable == other._elementNullable and self._elementType == other._elementType - - def __hash__(self): - """ - @return: A hash code for the ListType based on its element type and nullability. - """ - 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): - """ - Create a new MapType with the given key type, value type and the value is nullable. - - @param keyType: The key type of the map. - @param valueType: The value type of the map. - @param valueNullable: Whether the value of the map is nullable. - """ - self._keyType = keyType - self._valueType = valueType - self._valueNullable = valueNullable - - @classmethod - def valueNullable(cls, keyType: Type, valueType: Type): - """ - Create a new MapType with the given key type, value type, and the value is nullable. - - @param keyType: The key type of the map. - @param valueType: The value type of the map. - @return: A new MapType instance. - """ - return cls.of(keyType, valueType, True) - - @classmethod - def valueNotNull(cls, keyType: Type, valueType: Type): - """ - Create a new MapType with the given key type, value type, and the value is not nullable. - - @param keyType: The key type of the map. - @param valueType: The value type of the map. - @return: A new MapType instance. - """ - return cls.of(keyType, valueType, False) - - @classmethod - def of(cls, keyType: Type, valueType: Type, valueNullable: bool): - """ - Create a new MapType with the given key type, value type, and whether the value is nullable. - - @param keyType: The key type of the map. - @param valueType: The value type of the map. - @param valueNullable: Whether the value of the map is nullable. - @return: A new MapType instance. - """ - return cls(keyType, valueType, valueNullable) - - def keyType(self) -> Type: - """ - @return: The key type of the map. - """ - return self._keyType - - def valueType(self) -> Type: - """ - @return: The value type of the map. - """ - return self._valueType - - def valueNullable(self) -> bool: - """ - @return: Whether the value of the map is nullable. - """ - return self._valueNullable - - def name(self) -> Name: - """ - @return: The name of the map type. - """ - return Name.MAP - - def simpleString(self) -> str: - """ - @return: A readable string representation of the map type. - """ - return f"map<{self._keyType.simpleString()}, {self._valueType.simpleString()}>" - - def __eq__(self, other): - """ - Compares two MapType objects for equality. - - @param other: The other MapType object to compare with. - @return: True if both MapType objects have the same key type, value type, and nullability, False otherwise. - """ - if not isinstance(other, Types.MapType): - return False - return self._valueNullable == other._valueNullable and self._keyType == other._keyType and self._valueType == other._valueType - - def __hash__(self): - """ - @return: A hash code for the MapType based on its key type, value type, and nullability. - """ - 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): - """ - Create a new UnionType with the given types. - - @param types: The types of the union. - """ - self._types = types - - @classmethod - def of(cls, *types: Type): - """ - Create a new UnionType with the given types. - - @param types: The types of the union. - @return: A new UnionType instance. - """ - return cls(types) - - def types(self) -> list: - """ - @return: The types of the union. - """ - return self._types - - def name(self) -> Name: - """ - @return: The name of the union type. - """ - return Name.UNION - - def simpleString(self) -> str: - """ - @return: A readable string representation of the union type. - """ - return f"union<{', '.join(t.simpleString() for t in self._types)}>" - - def __eq__(self, other): - """ - Compares two UnionType objects for equality. - - @param other: The other UnionType object to compare with. - @return: True if both UnionType objects have the same types, False otherwise. - """ - if not isinstance(other, Types.UnionType): - return False - return self._types == other._types - - def __hash__(self): - """ - @return: A hash code for the UnionType based on its types. - """ - 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): - """ - Initializes an UnparsedType instance. - - @param unparsedType: The unparsed type as a string. - """ - self._unparsedType = unparsedType - - @classmethod - def of(cls, unparsedType: str): - """ - Creates a new UnparsedType with the given unparsed type. - - @param unparsedType: The unparsed type. - @return: A new UnparsedType instance. - """ - return cls(unparsedType) - - def unparsedType(self) -> str: - """ - @return: The unparsed type as a string. - """ - return self._unparsedType - - def name(self) -> Name: - """ - @return: The name of the unparsed type. - """ - return Name.UNPARSED - - def simpleString(self) -> str: - """ - @return: A readable string representation of the unparsed type. - """ - return f"unparsed({self._unparsedType})" - - def __eq__(self, other): - """ - Compares two UnparsedType objects for equality. - - @param other: The other UnparsedType object to compare with. - @return: True if both UnparsedType objects have the same unparsed type string, False otherwise. - """ - if not isinstance(other, Types.UnparsedType): - return False - return self._unparsedType == other._unparsedType - - def __hash__(self): - """ - @return: A hash code for the UnparsedType based on its unparsed type string. - """ - return hash(self._unparsedType) - - def __str__(self): - """ - @return: The unparsed type string representation. - """ - return self._unparsedType - - """ Represents a type that is defined in an external catalog. """ - class ExternalType(Type): - def __init__(self, catalogString: str): - """ - Initializes an ExternalType instance. - - @param catalogString: The string representation of this type in the catalog. - """ - self._catalogString = catalogString - - @classmethod - def of(cls, catalogString: str): - """ - Creates a new ExternalType with the given catalog string. - - @param catalogString: The string representation of this type in the catalog. - @return: A new ExternalType instance. - """ - return cls(catalogString) - - def catalogString(self) -> str: - """ - @return: The string representation of this type in external catalog. - """ - return self._catalogString - - def name(self) -> Name: - """ - @return: The name of the external type. - """ - return Name.EXTERNAL - - def simpleString(self) -> str: - """ - @return: A readable string representation of the external type. - """ - return f"external({self._catalogString})" - - def __eq__(self, other): - """ - Compares two ExternalType objects for equality. - - @param other: The other ExternalType object to compare with. - @return: True if both ExternalType objects have the same catalog string, False otherwise. - """ - if not isinstance(other, Types.ExternalType): - return False - return self._catalogString == other._catalogString - - def __hash__(self): - """ - @return: A hash code for the ExternalType based on its catalog string. - """ - return hash(self._catalogString) - - def __str__(self): - """ - @return: The string representation of the external type. - """ - return self.simpleString() - - @staticmethod - def allowAutoIncrement(dataType: Type) -> bool: - """ - Checks if the given data type is allowed to be an auto-increment column. - - @param dataType: The data type to check. - @return: True if the given data type is allowed to be an auto-increment column, False otherwise. - """ - return isinstance(dataType, (Types.IntegerType, Types.LongType)) - + def __init__(self): + super().__init__() diff --git a/clients/client-python/gravitino/api/types.py b/clients/client-python/gravitino/api/types.py new file mode 100644 index 0000000000..60650c53e5 --- /dev/null +++ b/clients/client-python/gravitino/api/types.py @@ -0,0 +1,1254 @@ +""" +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +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 + +""" The helper class for Type. """ +class Types: + + """ The data type representing `NULL` values. """ + class NullType(Type): + _instance = None + + @classmethod + def get(cls): + """ + @return The singleton instance of NullType. + """ + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def name(self) -> Name: + """ + @return The name of the Null type. + """ + return Name.NULL + + def simpleString(self) -> str: + """ + @return A readable string representation of the Null type. + """ + return "null" + + """ The boolean type in Gravitino. """ + class BooleanType(PrimitiveType): + _instance = None + + @classmethod + def get(cls): + """ + @return The singleton instance of BooleanType. + """ + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def name(self) -> Name: + """ + @return The name of the Boolean type. + """ + return Name.BOOLEAN + + def simpleString(self) -> str: + """ + @return A readable string representation of the Boolean type. + """ + return "boolean" + + """ The byte type in Gravitino. """ + class ByteType(IntegralType): + _instance = None + _unsigned_instance = None + + @classmethod + def get(cls): + """ + @return The singleton instance of ByteType. + """ + if cls._instance is None: + cls._instance = cls(True) + return cls._instance + + @classmethod + def unsigned(cls): + """ + @return The singleton instance of unsigned ByteType. + """ + if cls._unsigned_instance is None: + cls._unsigned_instance = cls(False) + return cls._unsigned_instance + + def __init__(self, signed: bool): + """ + @param signed: True if the byte type is signed, False otherwise. + """ + super().__init__(signed) + + def name(self) -> Name: + """ + @return The name of the Byte type. + """ + return Name.BYTE + + def simpleString(self) -> str: + """ + @return A readable string representa + """ + return "byte" if self.signed() else "byte unsigned" + + """ The short type in Gravitino. """ + class ShortType(IntegralType): + _instance = None + _unsigned_instance = None + + @classmethod + def get(cls): + """ + @return The singleton instance of ShortType. + """ + if cls._instance is None: + cls._instance = cls(True) + return cls._instance + + @classmethod + def unsigned(cls): + """ + @return The singleton instance of unsigned ShortType. + """ + if cls._unsigned_instance is None: + cls._unsigned_instance = cls(False) + return cls._unsigned_instance + + def __init__(self, signed: bool): + """ + @param signed: True if the short type is signed, False otherwise. + """ + super().__init__(signed) + + def name(self) -> Name: + """ + @return The name of the Short type. + """ + return Name.SHORT + + def simpleString(self) -> str: + """ + @return A readable string representation of the Short type. + """ + return "short" if self.signed() else "short unsigned" + + """ The integer type in Gravitino. """ + class IntegerType(IntegralType): + _instance = None + _unsigned_instance = None + + @classmethod + def get(cls): + """ + @return The singleton instance of IntegerType. + """ + if cls._instance is None: + cls._instance = cls(True) + return cls._instance + + @classmethod + def unsigned(cls): + """ + @return The singleton instance of unsigned IntegerType. + """ + if cls._unsigned_instance is None: + cls._unsigned_instance = cls(False) + return cls._unsigned_instance + + def __init__(self, signed: bool): + """ + @param signed: True if the integer type is signed, False otherwise. + """ + super().__init__(signed) + + def name(self) -> Name: + """ + @return The name of the Integer type. + """ + return Name.INTEGER + + def simpleString(self) -> str: + """ + @return A readable string representation of the Integer type. + """ + return "integer" if self.signed() else "integer unsigned" + + """ The long type in Gravitino. """ + class LongType(IntegralType): + _instance = None + _unsigned_instance = None + + @classmethod + def get(cls): + """ + @return The singleton instance of LongType. + """ + if cls._instance is None: + cls._instance = cls(True) + return cls._instance + + @classmethod + def unsigned(cls): + """ + @return The singleton instance of unsigned LongType. + """ + if cls._unsigned_instance is None: + cls._unsigned_instance = cls(False) + return cls._unsigned_instance + + def __init__(self, signed: bool): + """ + @param signed: True if the long type is signed, False otherwise. + """ + super().__init__(signed) + + def name(self) -> Name: + """ + @return The name of the Long type. + """ + return Name.LONG + + def simpleString(self) -> str: + """ + @return A readable string representation of the Long type. + """ + return "long" if self.signed() else "long unsigned" + + """ The float type in Gravitino. """ + class FloatType(FractionType): + _instance = None + + @classmethod + def get(cls): + """ + @return The singleton instance of FloatType. + """ + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def name(self) -> Name: + """ + @return The name of the Float type. + """ + return Name.FLOAT + + def simpleString(self) -> str: + """ + @return A readable string representation of the Float type. + """ + return "float" + + """ The double type in Gravitino. """ + class DoubleType(FractionType): + _instance = None + + @classmethod + def get(cls): + """ + @return The singleton instance of DoubleType. + """ + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def name(self) -> Name: + """ + @return The name of the Double type. + """ + return Name.DOUBLE + + def simpleString(self) -> str: + """ + @return A readable string representation of the Double type. + """ + return "double" + + """ The decimal type in Gravitino. """ + class DecimalType(FractionType): + @classmethod + def of(cls, precision: int, scale: int): + """ + @param precision: The precision of the decimal type. + @param scale: The scale of the decimal type. + @return A DecimalType with the given precision and scale. + """ + return cls(precision, scale) + + def __init__(self, precision: int, scale: int): + """ + @param precision: The precision of the decimal type. + @param scale: The scale of the decimal type. + """ + self.check_precision_scale(precision, scale) + self._precision = precision + self._scale = scale + + @staticmethod + def check_precision_scale(precision: int, scale: int): + """ + Ensures the precision and scale values are within valid range. + @param precision: The precision of the decimal. + @param scale: The scale of the decimal. + """ + if not (1 <= precision <= 38): + 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}") + + def name(self) -> Name: + """ + @return The name of the Decimal type. + """ + return Name.DECIMAL + + def precision(self) -> int: + """ + @return The precision of the decimal type. + """ + return self._precision + + def scale(self) -> int: + """ + @return The scale of the decimal type. + """ + return self._scale + + 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. + """ + if not isinstance(other, Types.DecimalType): + return False + return self._precision == other._precision and self._scale == other._scale + + def __hash__(self): + """ + @return: A hash code for the DecimalType based on its precision and scale. + """ + return hash((self._precision, self._scale)) + + """ The date time type in Gravitino. """ + class DateType(DateTimeType): + _instance = None + + @classmethod + def get(cls): + """ + @return The singleton instance of DateType. + """ + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def name(self) -> Name: + """ + @return The name of the Date type. + """ + return Name.DATE + + def simpleString(self) -> str: + """ + @return A readable string representation of the Date type. + """ + return "date" + + """ The time type in Gravitino. """ + class TimeType(DateTimeType): + _instance = None + + @classmethod + def get(cls): + """ + @return The singleton instance of TimeType. + """ + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def name(self) -> Name: + """ + @return The name of the Time type. + """ + return Name.TIME + + def simpleString(self) -> str: + """ + @return A readable string representation of the Time type. + """ + return "time" + + """ The timestamp type in Gravitino. """ + class TimestampType(DateTimeType): + _instance_with_tz = None + _instance_without_tz = None + + @classmethod + def withTimeZone(cls): + """ + @return A TimestampType with time zone. + """ + if cls._instance_with_tz is None: + cls._instance_with_tz = cls(True) + return cls._instance_with_tz + + @classmethod + def withoutTimeZone(cls): + """ + @return A TimestampType without time zone. + """ + if cls._instance_without_tz is None: + cls._instance_without_tz = cls(False) + return cls._instance_without_tz + + def __init__(self, with_time_zone: bool): + """ + @param with_time_zone: True if the timestamp type has a time zone, False otherwise. + """ + self._with_time_zone = with_time_zone + + def hasTimeZone(self) -> bool: + """ + @return True if the timestamp type has a time zone, False otherwise. + """ + return self._with_time_zone + + def name(self) -> Name: + """ + @return The name of the Timestamp type. + """ + return Name.TIMESTAMP + + def simpleString(self) -> str: + """ + @return A readable string representation of the Timestamp type. + """ + return "timestamp_tz" if self._with_time_zone else "timestamp" + + """ The interval year type in Gravitino. """ + class IntervalYearType(IntervalType): + _instance = None + + @classmethod + def get(cls): + """ + @return The singleton instance of IntervalYearType. + """ + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def name(self) -> Name: + """ + @return The name of the IntervalYear type. + """ + return Name.INTERVAL_YEAR + + 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 + + @classmethod + def get(cls): + """ + @return: The singleton instance of IntervalDayType. + """ + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def name(self) -> Name: + """ + @return: The name of the interval day type. + """ + return Name.INTERVAL_DAY + + def simpleString(self) -> str: + """ + @return: A readable string representation of the interval day type. + """ + 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 + + @classmethod + def get(cls): + """ + @return: The singleton instance of StringType. + """ + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def name(self) -> Name: + """ + @return: The name of the string type. + """ + return Name.STRING + + def simpleString(self) -> str: + """ + @return: A readable string representation of the string type. + """ + return "string" + + """ The UUID type in Gravitino. """ + class UUIDType(PrimitiveType): + _instance = None + + @classmethod + def get(cls): + """ + @return: The singleton instance of UUIDType. + """ + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def name(self) -> Name: + """ + @return: The name of the UUID type. + """ + return Name.UUID + + def simpleString(self) -> str: + """ + @return: A readable string representation of the UUID type. + """ + return "uuid" + + """ Fixed-length byte array type. Use BinaryType for variable-length byte arrays. """ + class FixedType(PrimitiveType): + def __init__(self, length: int): + """ + Initializes the FixedType with the given length. + + @param length: The length of the fixed type. + """ + self._length = length + + @classmethod + def of(cls, length: int): + """ + @param length: The length of the fixed type. + @return: A FixedType instance with the given length. + """ + return cls(length) + + def name(self) -> Name: + """ + @return: The name of the fixed type. + """ + return Name.FIXED + + def length(self) -> int: + """ + @return: The length of the fixed type. + """ + return self._length + + def simpleString(self) -> str: + """ + @return: A readable string representation of the fixed type. + """ + return f"fixed({self._length})" + + def __eq__(self, other): + """ + Compares two FixedType objects for equality. + + @param other: The other FixedType object to compare with. + @return: True if both FixedType objects have the same length, False otherwise. + """ + if not isinstance(other, Types.FixedType): + return False + return self._length == other._length + + def __hash__(self): + """ + @return: A hash code for the FixedType based on its length. + """ + return hash(self._length) + + """ The varchar type in Gravitino. """ + class VarCharType(PrimitiveType): + def __init__(self, length: int): + """ + Initializes the VarCharType with the given length. + + @param length: The length of the varchar type. + """ + self._length = length + + @classmethod + def of(cls, length: int): + """ + @param length: The length of the varchar type. + @return: A VarCharType instance with the given length. + """ + return cls(length) + + def name(self) -> Name: + """ + @return: The name of the varchar type. + """ + return Name.VARCHAR + + def length(self) -> int: + """ + @return: The length of the varchar type. + """ + return self._length + + def simpleString(self) -> str: + """ + @return: A readable string representation of the varchar type. + """ + return f"varchar({self._length})" + + def __eq__(self, other): + """ + Compares two VarCharType objects for equality. + + @param other: The other VarCharType object to compare with. + @return: True if both VarCharType objects have the same length, False otherwise. + """ + if not isinstance(other, Types.VarCharType): + return False + return self._length == other._length + + def __hash__(self): + """ + @return: A hash code for the VarCharType based on its length. + """ + return hash(self._length) + + """ The fixed char type in Gravitino. """ + class FixedCharType(PrimitiveType): + def __init__(self, length: int): + """ + Initializes the FixedCharType with the given length. + + @param length: The length of the fixed char type. + """ + self._length = length + + @classmethod + def of(cls, length: int): + """ + @param length: The length of the fixed char type. + @return: A FixedCharType instance with the given length. + """ + return cls(length) + + def name(self) -> Name: + """ + @return: The name of the fixed char type. + """ + return Name.FIXEDCHAR + + def length(self) -> int: + """ + @return: The length of the fixed char type. + """ + return self._length + + def simpleString(self) -> str: + """ + @return: A readable string representation of the fixed char type. + """ + return f"char({self._length})" + + def __eq__(self, other): + """ + Compares two FixedCharType objects for equality. + + @param other: The other FixedCharType object to compare with. + @return: True if both FixedCharType objects have the same length, False otherwise. + """ + if not isinstance(other, Types.FixedCharType): + return False + return self._length == other._length + + def __hash__(self): + """ + @return: A hash code for the FixedCharType based on its length. + """ + return hash(self._length) + + """ The binary type in Gravitino. """ + class BinaryType(PrimitiveType): + _instance = None + + @classmethod + def get(cls): + """ + @return: The singleton instance of BinaryType. + """ + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def name(self) -> Name: + """ + @return: The name of the binary type. + """ + return Name.BINARY + + def simpleString(self) -> str: + """ + @return: A readable string representation of the binary type. + """ + 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): + """ + Initializes the StructType with the given fields. + + @param fields: The fields of the struct type. + """ + if not fields or len(fields) == 0: + raise ValueError("fields cannot be null or empty") + self._fields = fields + + @classmethod + def of(cls, *fields): + """ + @param fields: The fields of the struct type. + @return: A StructType instance with the given fields. + """ + return cls(fields) + + def fields(self): + """ + @return: The fields of the struct type. + """ + return self._fields + + def name(self) -> Name: + """ + @return: The name of the struct type. + """ + return Name.STRUCT + + def simpleString(self) -> str: + """ + @return: A readable string representation of the struct type. + """ + return f"struct<{', '.join(field.simpleString() for field in self._fields)}>" + + def __eq__(self, other): + """ + Compares two StructType objects for equality. + + @param other: The other StructType object to compare with. + @return: True if both StructType objects have the same fields, False otherwise. + """ + if not isinstance(other, Types.StructType): + return False + return self._fields == other._fields + + def __hash__(self): + """ + @return: A hash code for the StructType based on its fields. + """ + return hash(tuple(self._fields)) + + """ A field of a struct type. """ + class Field: + def __init__(self, name, type, nullable, comment=None): + """ + Initializes the Field with the given name, type, nullable flag, and comment. + + @param name: The name of the field. + @param type: The type of the field. + @param nullable: Whether the field is nullable. + @param comment: The comment of the field (optional). + """ + if name is None: + raise ValueError("name cannot be null") + if type is None: + raise ValueError("type cannot be null") + self._name = name + self._type = type + self._nullable = nullable + self._comment = comment + + @classmethod + def notNullField(cls, name, type, comment=None): + """ + @param name: The name of the field. + @param type: The type of the field. + @param comment: The comment of the field. + @return: A NOT NULL Field instance with the given name, type, and comment. + """ + return cls(name, type, False, comment) + + @classmethod + def nullableField(cls, name, type, comment=None): + """ + @param name: The name of the field. + @param type: The type of the field. + @param comment: The comment of the field. + @return: A nullable Field instance with the given name, type, and comment. + """ + return cls(name, type, True, comment) + + def name(self): + """ + @return: The name of the field. + """ + return self._name + + def type(self): + """ + @return: The type of the field. + """ + return self._type + + def nullable(self): + """ + @return: Whether the field is nullable. + """ + return self._nullable + + def comment(self): + """ + @return: The comment of the field, or None if not set. + """ + return self._comment + + def __eq__(self, other): + """ + Compares two Field objects for equality. + + @param other: The other Field object to compare with. + @return: True if both Field objects have the same attributes, False otherwise. + """ + 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) + + def __hash__(self): + """ + @return: A hash code for the Field based on its attributes. + """ + return hash((self._name, self._type, self._nullable)) + + def simpleString(self) -> str: + """ + @return: The simple string representation of the field. + """ + nullable_str = "NULL" if self._nullable else "NOT NULL" + comment_str = f" COMMENT '{self._comment}'" if self._comment else "" + 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): + """ + Create a new ListType with the given element type and the type is nullable. + + @param elementType: The element type of the list. + @param elementNullable: Whether the element of the list is nullable. + """ + if elementType is None: + raise ValueError("elementType cannot be null") + self._elementType = elementType + self._elementNullable = elementNullable + + @classmethod + def nullable(cls, elementType: Type): + """ + Create a new ListType with the given element type and the type is nullable. + + @param elementType: The element type of the list. + @return: A new ListType instance. + """ + return cls.of(elementType, True) + + @classmethod + def notNull(cls, elementType: Type): + """ + Create a new ListType with the given element type. + + @param elementType: The element type of the list. + @return: A new ListType instance. + """ + return cls.of(elementType, False) + + @classmethod + def of(cls, elementType: Type, elementNullable: bool): + """ + Create a new ListType with the given element type and whether the element is nullable. + + @param elementType: The element type of the list. + @param elementNullable: Whether the element of the list is nullable. + @return: A new ListType instance. + """ + return cls(elementType, elementNullable) + + def elementType(self) -> Type: + """ + @return: The element type of the list. + """ + return self._elementType + + def elementNullable(self) -> bool: + """ + @return: Whether the element of the list is nullable. + """ + return self._elementNullable + + def name(self) -> Name: + """ + @return: The name of the list type. + """ + return Name.LIST + + 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>" + + def __eq__(self, other): + """ + Compares two ListType objects for equality. + + @param other: The other ListType object to compare with. + @return: True if both ListType objects have the same element type and nullability, False otherwise. + """ + if not isinstance(other, Types.ListType): + return False + return self._elementNullable == other._elementNullable and self._elementType == other._elementType + + def __hash__(self): + """ + @return: A hash code for the ListType based on its element type and nullability. + """ + 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): + """ + Create a new MapType with the given key type, value type and the value is nullable. + + @param keyType: The key type of the map. + @param valueType: The value type of the map. + @param valueNullable: Whether the value of the map is nullable. + """ + self._keyType = keyType + self._valueType = valueType + self._valueNullable = valueNullable + + @classmethod + def valueNullable(cls, keyType: Type, valueType: Type): + """ + Create a new MapType with the given key type, value type, and the value is nullable. + + @param keyType: The key type of the map. + @param valueType: The value type of the map. + @return: A new MapType instance. + """ + return cls.of(keyType, valueType, True) + + @classmethod + def valueNotNull(cls, keyType: Type, valueType: Type): + """ + Create a new MapType with the given key type, value type, and the value is not nullable. + + @param keyType: The key type of the map. + @param valueType: The value type of the map. + @return: A new MapType instance. + """ + return cls.of(keyType, valueType, False) + + @classmethod + def of(cls, keyType: Type, valueType: Type, valueNullable: bool): + """ + Create a new MapType with the given key type, value type, and whether the value is nullable. + + @param keyType: The key type of the map. + @param valueType: The value type of the map. + @param valueNullable: Whether the value of the map is nullable. + @return: A new MapType instance. + """ + return cls(keyType, valueType, valueNullable) + + def keyType(self) -> Type: + """ + @return: The key type of the map. + """ + return self._keyType + + def valueType(self) -> Type: + """ + @return: The value type of the map. + """ + return self._valueType + + def valueNullable(self) -> bool: + """ + @return: Whether the value of the map is nullable. + """ + return self._valueNullable + + def name(self) -> Name: + """ + @return: The name of the map type. + """ + return Name.MAP + + def simpleString(self) -> str: + """ + @return: A readable string representation of the map type. + """ + return f"map<{self._keyType.simpleString()}, {self._valueType.simpleString()}>" + + def __eq__(self, other): + """ + Compares two MapType objects for equality. + + @param other: The other MapType object to compare with. + @return: True if both MapType objects have the same key type, value type, and nullability, False otherwise. + """ + if not isinstance(other, Types.MapType): + return False + return self._valueNullable == other._valueNullable and self._keyType == other._keyType and self._valueType == other._valueType + + def __hash__(self): + """ + @return: A hash code for the MapType based on its key type, value type, and nullability. + """ + 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): + """ + Create a new UnionType with the given types. + + @param types: The types of the union. + """ + self._types = types + + @classmethod + def of(cls, *types: Type): + """ + Create a new UnionType with the given types. + + @param types: The types of the union. + @return: A new UnionType instance. + """ + return cls(types) + + def types(self) -> list: + """ + @return: The types of the union. + """ + return self._types + + def name(self) -> Name: + """ + @return: The name of the union type. + """ + return Name.UNION + + def simpleString(self) -> str: + """ + @return: A readable string representation of the union type. + """ + return f"union<{', '.join(t.simpleString() for t in self._types)}>" + + def __eq__(self, other): + """ + Compares two UnionType objects for equality. + + @param other: The other UnionType object to compare with. + @return: True if both UnionType objects have the same types, False otherwise. + """ + if not isinstance(other, Types.UnionType): + return False + return self._types == other._types + + def __hash__(self): + """ + @return: A hash code for the UnionType based on its types. + """ + 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): + """ + Initializes an UnparsedType instance. + + @param unparsedType: The unparsed type as a string. + """ + self._unparsedType = unparsedType + + @classmethod + def of(cls, unparsedType: str): + """ + Creates a new UnparsedType with the given unparsed type. + + @param unparsedType: The unparsed type. + @return: A new UnparsedType instance. + """ + return cls(unparsedType) + + def unparsedType(self) -> str: + """ + @return: The unparsed type as a string. + """ + return self._unparsedType + + def name(self) -> Name: + """ + @return: The name of the unparsed type. + """ + return Name.UNPARSED + + def simpleString(self) -> str: + """ + @return: A readable string representation of the unparsed type. + """ + return f"unparsed({self._unparsedType})" + + def __eq__(self, other): + """ + Compares two UnparsedType objects for equality. + + @param other: The other UnparsedType object to compare with. + @return: True if both UnparsedType objects have the same unparsed type string, False otherwise. + """ + if not isinstance(other, Types.UnparsedType): + return False + return self._unparsedType == other._unparsedType + + def __hash__(self): + """ + @return: A hash code for the UnparsedType based on its unparsed type string. + """ + return hash(self._unparsedType) + + def __str__(self): + """ + @return: The unparsed type string representation. + """ + return self._unparsedType + + """ Represents a type that is defined in an external catalog. """ + class ExternalType(Type): + def __init__(self, catalogString: str): + """ + Initializes an ExternalType instance. + + @param catalogString: The string representation of this type in the catalog. + """ + self._catalogString = catalogString + + @classmethod + def of(cls, catalogString: str): + """ + Creates a new ExternalType with the given catalog string. + + @param catalogString: The string representation of this type in the catalog. + @return: A new ExternalType instance. + """ + return cls(catalogString) + + def catalogString(self) -> str: + """ + @return: The string representation of this type in external catalog. + """ + return self._catalogString + + def name(self) -> Name: + """ + @return: The name of the external type. + """ + return Name.EXTERNAL + + def simpleString(self) -> str: + """ + @return: A readable string representation of the external type. + """ + return f"external({self._catalogString})" + + def __eq__(self, other): + """ + Compares two ExternalType objects for equality. + + @param other: The other ExternalType object to compare with. + @return: True if both ExternalType objects have the same catalog string, False otherwise. + """ + if not isinstance(other, Types.ExternalType): + return False + return self._catalogString == other._catalogString + + def __hash__(self): + """ + @return: A hash code for the ExternalType based on its catalog string. + """ + return hash(self._catalogString) + + def __str__(self): + """ + @return: The string representation of the external type. + """ + return self.simpleString() + + @staticmethod + def allowAutoIncrement(dataType: Type) -> bool: + """ + Checks if the given data type is allowed to be an auto-increment column. + + @param dataType: The data type to check. + @return: True if the given data type is allowed to be an auto-increment column, False otherwise. + """ + return isinstance(dataType, (Types.IntegerType, Types.LongType)) + From 666a0b36f6c686723f2db32744387500643a5f88 Mon Sep 17 00:00:00 2001 From: YUN SUN Date: Tue, 29 Oct 2024 23:41:15 -0500 Subject: [PATCH 4/9] Update the unit test for the types --- clients/client-python/gravitino/api/type.py | 35 ++-- clients/client-python/gravitino/api/types.py | 35 ++-- .../tests/unittests/test_types.py | 151 ++++++++++++++++++ 3 files changed, 184 insertions(+), 37 deletions(-) create mode 100644 clients/client-python/tests/unittests/test_types.py diff --git a/clients/client-python/gravitino/api/type.py b/clients/client-python/gravitino/api/type.py index c32b6215bd..5855fe7867 100644 --- a/clients/client-python/gravitino/api/type.py +++ b/clients/client-python/gravitino/api/type.py @@ -1,22 +1,19 @@ -""" -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. -""" - +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. from abc import ABC, abstractmethod from enum import Enum from typing import Optional diff --git a/clients/client-python/gravitino/api/types.py b/clients/client-python/gravitino/api/types.py index 60650c53e5..5f10fdaf6d 100644 --- a/clients/client-python/gravitino/api/types.py +++ b/clients/client-python/gravitino/api/types.py @@ -1,23 +1,22 @@ -""" -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. -""" +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# 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 + """ The helper class for Type. """ class Types: diff --git a/clients/client-python/tests/unittests/test_types.py b/clients/client-python/tests/unittests/test_types.py new file mode 100644 index 0000000000..d0cb5b5227 --- /dev/null +++ b/clients/client-python/tests/unittests/test_types.py @@ -0,0 +1,151 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +import unittest + +from gravitino.api.types import Types, Name + + +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.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.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() + unsigned_byte = Types.ByteType.unsigned() + + self.assertEqual(signed_byte.name(), Name.BYTE) + self.assertEqual(signed_byte.simpleString(), "byte") + self.assertEqual(unsigned_byte.simpleString(), "byte unsigned") + + # Test ShortType for signed and unsigned versions + def test_short_type(self): + signed_short = Types.ShortType.get() + unsigned_short = Types.ShortType.unsigned() + + 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() + unsigned_int = Types.IntegerType.unsigned() + + 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) + decimal_type_2 = Types.DecimalType.of(10, 2) + decimal_type_3 = Types.DecimalType.of(12, 3) + + 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") + + # 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.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.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.assertEqual(string_type_1.name(), Name.STRING) + self.assertEqual(string_type_1.simpleString(), "string") + + # Test UUIDType singleton and methods + 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.assertEqual(uuid_type_1.name(), Name.UUID) + self.assertEqual(uuid_type_1.simpleString(), "uuid") + + # Test FixedType creation and equality + def test_fixed_type(self): + fixed_type_1 = Types.FixedType.of(16) + fixed_type_2 = Types.FixedType.of(16) + fixed_type_3 = Types.FixedType.of(32) + + self.assertEqual(fixed_type_1.name(), Name.FIXED) + self.assertEqual(fixed_type_1.simpleString(), "fixed(16)") + self.assertEqual(fixed_type_1, fixed_type_2) + self.assertNotEqual(fixed_type_1, fixed_type_3) + + # Test VarCharType creation and equality + def test_varchar_type(self): + varchar_type_1 = Types.VarCharType.of(255) + varchar_type_2 = Types.VarCharType.of(255) + varchar_type_3 = Types.VarCharType.of(512) + + self.assertEqual(varchar_type_1.name(), Name.VARCHAR) + self.assertEqual(varchar_type_1.simpleString(), "varchar(255)") + self.assertEqual(varchar_type_1, varchar_type_2) + self.assertNotEqual(varchar_type_1, varchar_type_3) + + # Test allowAutoIncrement method for IntegerType and LongType + def test_allow_auto_increment(self): + integer_type = Types.IntegerType.get() + long_type = Types.LongType.get() + boolean_type = Types.BooleanType.get() + + self.assertTrue(Types.allowAutoIncrement(integer_type)) + self.assertTrue(Types.allowAutoIncrement(long_type)) + self.assertFalse(Types.allowAutoIncrement(boolean_type)) + + +if __name__ == "__main__": + unittest.main() From 5abeb8cabfe7cc09d57af2840dae263e203a8df9 Mon Sep 17 00:00:00 2001 From: YUN SUN Date: Tue, 29 Oct 2024 23:42:36 -0500 Subject: [PATCH 5/9] Update unit test file --- clients/client-python/tests/unittests/test_types.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/clients/client-python/tests/unittests/test_types.py b/clients/client-python/tests/unittests/test_types.py index d0cb5b5227..270bfdf811 100644 --- a/clients/client-python/tests/unittests/test_types.py +++ b/clients/client-python/tests/unittests/test_types.py @@ -144,8 +144,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)) - - -if __name__ == "__main__": - unittest.main() + self.assertFalse(Types.allowAutoIncrement(boolean_type)) \ No newline at end of file From 28bfa05db7498a89b4016418f0b6563e23657c53 Mon Sep 17 00:00:00 2001 From: YUN SUN Date: Wed, 30 Oct 2024 09:34:00 -0500 Subject: [PATCH 6/9] Update the format --- clients/client-python/gravitino/api/type.py | 32 +++++-- clients/client-python/gravitino/api/types.py | 89 +++++++++++++++---- .../tests/unittests/test_types.py | 72 +++++++++++---- 3 files changed, 151 insertions(+), 42 deletions(-) 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)) From a4323d76916f67fb26db4c630b9e469bf8fcc603 Mon Sep 17 00:00:00 2001 From: YUN SUN Date: Wed, 30 Oct 2024 22:44:37 -0500 Subject: [PATCH 7/9] Update the format to pass pylint --- clients/client-python/gravitino/api/type.py | 6 +- clients/client-python/gravitino/api/types.py | 701 ++++--------------- 2 files changed, 157 insertions(+), 550 deletions(-) diff --git a/clients/client-python/gravitino/api/type.py b/clients/client-python/gravitino/api/type.py index cf9d9003cc..4d077dab44 100644 --- a/clients/client-python/gravitino/api/type.py +++ b/clients/client-python/gravitino/api/type.py @@ -16,7 +16,6 @@ # under the License. from abc import ABC, abstractmethod from enum import Enum -from typing import Optional class Name(Enum): @@ -125,7 +124,7 @@ def name(self) -> Name: pass @abstractmethod - def simpleString(self) -> str: + def simple_string(self) -> str: """Returns a readable string representation of the type.""" pass @@ -175,5 +174,4 @@ def signed(self) -> bool: class FractionType(NumericType, ABC): """Base class for all fractional types.""" - def __init__(self): - super().__init__() + pass diff --git a/clients/client-python/gravitino/api/types.py b/clients/client-python/gravitino/api/types.py index 601a198f56..ebd1cd295a 100644 --- a/clients/client-python/gravitino/api/types.py +++ b/clients/client-python/gravitino/api/types.py @@ -26,292 +26,175 @@ ) -""" The helper class for Type. """ - - class Types: - """The data type representing `NULL` values.""" class NullType(Type): _instance = None @classmethod def get(cls): - """ - @return The singleton instance of NullType. - """ if cls._instance is None: cls._instance = cls() return cls._instance def name(self) -> Name: - """ - @return The name of the Null type. - """ return Name.NULL - def simpleString(self) -> str: - """ - @return A readable string representation of the Null type. - """ + def simple_string(self) -> str: return "null" - """ The boolean type in Gravitino. """ - class BooleanType(PrimitiveType): _instance = None @classmethod def get(cls): - """ - @return The singleton instance of BooleanType. - """ if cls._instance is None: cls._instance = cls() return cls._instance def name(self) -> Name: - """ - @return The name of the Boolean type. - """ return Name.BOOLEAN - def simpleString(self) -> str: - """ - @return A readable string representation of the Boolean type. - """ + def simple_string(self) -> str: return "boolean" - """ The byte type in Gravitino. """ - class ByteType(IntegralType): _instance = None _unsigned_instance = None + def __init__(self, signed: bool): + super().__init__(signed) + self._signed = signed + @classmethod def get(cls): - """ - @return The singleton instance of ByteType. - """ if cls._instance is None: cls._instance = cls(True) return cls._instance @classmethod def unsigned(cls): - """ - @return The singleton instance of unsigned ByteType. - """ if cls._unsigned_instance is None: cls._unsigned_instance = cls(False) return cls._unsigned_instance - def __init__(self, signed: bool): - """ - @param signed: True if the byte type is signed, False otherwise. - """ - super().__init__(signed) - def name(self) -> Name: - """ - @return The name of the Byte type. - """ return Name.BYTE - def simpleString(self) -> str: - """ - @return A readable string representa - """ + def simple_string(self) -> str: return "byte" if self.signed() else "byte unsigned" - """ The short type in Gravitino. """ - class ShortType(IntegralType): _instance = None _unsigned_instance = None + def __init__(self, signed: bool): + super().__init__(signed) + self._signed = signed + @classmethod def get(cls): - """ - @return The singleton instance of ShortType. - """ if cls._instance is None: cls._instance = cls(True) return cls._instance @classmethod def unsigned(cls): - """ - @return The singleton instance of unsigned ShortType. - """ if cls._unsigned_instance is None: cls._unsigned_instance = cls(False) return cls._unsigned_instance - def __init__(self, signed: bool): - """ - @param signed: True if the short type is signed, False otherwise. - """ - super().__init__(signed) - def name(self) -> Name: - """ - @return The name of the Short type. - """ return Name.SHORT - def simpleString(self) -> str: - """ - @return A readable string representation of the Short type. - """ + def simple_string(self) -> str: return "short" if self.signed() else "short unsigned" - """ The integer type in Gravitino. """ - class IntegerType(IntegralType): _instance = None _unsigned_instance = None + def __init__(self, signed: bool): + super().__init__(signed) + self._signed = signed + @classmethod def get(cls): - """ - @return The singleton instance of IntegerType. - """ if cls._instance is None: cls._instance = cls(True) return cls._instance @classmethod def unsigned(cls): - """ - @return The singleton instance of unsigned IntegerType. - """ if cls._unsigned_instance is None: cls._unsigned_instance = cls(False) return cls._unsigned_instance - def __init__(self, signed: bool): - """ - @param signed: True if the integer type is signed, False otherwise. - """ - super().__init__(signed) - def name(self) -> Name: - """ - @return The name of the Integer type. - """ return Name.INTEGER - def simpleString(self) -> str: - """ - @return A readable string representation of the Integer type. - """ + def simple_string(self) -> str: return "integer" if self.signed() else "integer unsigned" - """ The long type in Gravitino. """ - class LongType(IntegralType): _instance = None _unsigned_instance = None + def __init__(self, signed: bool): + super().__init__(signed) + self._signed = signed + @classmethod def get(cls): - """ - @return The singleton instance of LongType. - """ if cls._instance is None: cls._instance = cls(True) return cls._instance @classmethod def unsigned(cls): - """ - @return The singleton instance of unsigned LongType. - """ if cls._unsigned_instance is None: cls._unsigned_instance = cls(False) return cls._unsigned_instance - def __init__(self, signed: bool): - """ - @param signed: True if the long type is signed, False otherwise. - """ - super().__init__(signed) - def name(self) -> Name: - """ - @return The name of the Long type. - """ return Name.LONG - def simpleString(self) -> str: - """ - @return A readable string representation of the Long type. - """ + def simple_string(self) -> str: return "long" if self.signed() else "long unsigned" - """ The float type in Gravitino. """ - class FloatType(FractionType): _instance = None @classmethod def get(cls): - """ - @return The singleton instance of FloatType. - """ if cls._instance is None: cls._instance = cls() return cls._instance def name(self) -> Name: - """ - @return The name of the Float type. - """ return Name.FLOAT - def simpleString(self) -> str: - """ - @return A readable string representation of the Float type. - """ + def simple_string(self) -> str: return "float" - """ The double type in Gravitino. """ - class DoubleType(FractionType): _instance = None @classmethod def get(cls): - """ - @return The singleton instance of DoubleType. - """ if cls._instance is None: cls._instance = cls() return cls._instance def name(self) -> Name: - """ - @return The name of the Double type. - """ return Name.DOUBLE - def simpleString(self) -> str: - """ - @return A readable string representation of the Double type. - """ + def simple_string(self) -> str: return "double" - """ The decimal type in Gravitino. """ - class DecimalType(FractionType): @classmethod def of(cls, precision: int, scale: int): - """ - @param precision: The precision of the decimal type. - @param scale: The scale of the decimal type. - @return A DecimalType with the given precision and scale. - """ return cls(precision, scale) def __init__(self, precision: int, scale: int): @@ -319,6 +202,7 @@ def __init__(self, precision: int, scale: int): @param precision: The precision of the decimal type. @param scale: The scale of the decimal type. """ + super().__init__() self.check_precision_scale(precision, scale) self._precision = precision self._scale = scale @@ -330,37 +214,25 @@ def check_precision_scale(precision: int, scale: int): @param precision: The precision of the decimal. @param scale: The scale of the decimal. """ - if not (1 <= precision <= 38): + if not 1 <= precision <= 38: raise ValueError( f"Decimal precision must be in range [1, 38]: {precision}" ) - if not (0 <= scale <= precision): + if not 0 <= scale <= precision: raise ValueError( f"Decimal scale must be in range [0, precision ({precision})]: {scale}" ) def name(self) -> Name: - """ - @return The name of the Decimal type. - """ return Name.DECIMAL def precision(self) -> int: - """ - @return The precision of the decimal type. - """ return self._precision def scale(self) -> int: - """ - @return The scale of the decimal type. - """ return self._scale - def simpleString(self) -> str: - """ - @return A readable string representation of the Decimal type. - """ + def simple_string(self) -> str: return f"decimal({self._precision},{self._scale})" def __eq__(self, other): @@ -375,217 +247,126 @@ def __eq__(self, other): return self._precision == other._precision and self._scale == other._scale def __hash__(self): - """ - @return: A hash code for the DecimalType based on its precision and scale. - """ return hash((self._precision, self._scale)) - """ The date time type in Gravitino. """ - class DateType(DateTimeType): _instance = None @classmethod def get(cls): - """ - @return The singleton instance of DateType. - """ if cls._instance is None: cls._instance = cls() return cls._instance def name(self) -> Name: - """ - @return The name of the Date type. - """ return Name.DATE - def simpleString(self) -> str: - """ - @return A readable string representation of the Date type. - """ + def simple_string(self) -> str: return "date" - """ The time type in Gravitino. """ - class TimeType(DateTimeType): _instance = None @classmethod def get(cls): - """ - @return The singleton instance of TimeType. - """ if cls._instance is None: cls._instance = cls() return cls._instance def name(self) -> Name: - """ - @return The name of the Time type. - """ return Name.TIME - def simpleString(self) -> str: - """ - @return A readable string representation of the Time type. - """ + def simple_string(self) -> str: return "time" - """ The timestamp type in Gravitino. """ - class TimestampType(DateTimeType): _instance_with_tz = None _instance_without_tz = None @classmethod - def withTimeZone(cls): - """ - @return A TimestampType with time zone. - """ + def with_time_zone(cls): if cls._instance_with_tz is None: cls._instance_with_tz = cls(True) return cls._instance_with_tz @classmethod - def withoutTimeZone(cls): - """ - @return A TimestampType without time zone. - """ + def without_time_zone(cls): if cls._instance_without_tz is None: cls._instance_without_tz = cls(False) return cls._instance_without_tz def __init__(self, with_time_zone: bool): - """ - @param with_time_zone: True if the timestamp type has a time zone, False otherwise. - """ self._with_time_zone = with_time_zone - def hasTimeZone(self) -> bool: - """ - @return True if the timestamp type has a time zone, False otherwise. - """ + def has_time_zone(self) -> bool: return self._with_time_zone def name(self) -> Name: - """ - @return The name of the Timestamp type. - """ return Name.TIMESTAMP - def simpleString(self) -> str: - """ - @return A readable string representation of the Timestamp type. - """ + def simple_string(self) -> str: return "timestamp_tz" if self._with_time_zone else "timestamp" - """ The interval year type in Gravitino. """ - class IntervalYearType(IntervalType): _instance = None @classmethod def get(cls): - """ - @return The singleton instance of IntervalYearType. - """ if cls._instance is None: cls._instance = cls() return cls._instance def name(self) -> Name: - """ - @return The name of the IntervalYear type. - """ return Name.INTERVAL_YEAR - def simpleString(self) -> str: - """ - @return A readable string representation of the IntervalYear type. - """ + def simple_string(self) -> str: return "interval_year" - """ The interval day type in Gravitino. """ - class IntervalDayType(IntervalType): _instance = None @classmethod def get(cls): - """ - @return: The singleton instance of IntervalDayType. - """ if cls._instance is None: cls._instance = cls() return cls._instance def name(self) -> Name: - """ - @return: The name of the interval day type. - """ return Name.INTERVAL_DAY - def simpleString(self) -> str: - """ - @return: A readable string representation of the interval day type. - """ + def simple_string(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 @classmethod def get(cls): - """ - @return: The singleton instance of StringType. - """ if cls._instance is None: cls._instance = cls() return cls._instance def name(self) -> Name: - """ - @return: The name of the string type. - """ return Name.STRING - def simpleString(self) -> str: - """ - @return: A readable string representation of the string type. - """ + def simple_string(self) -> str: return "string" - """ The UUID type in Gravitino. """ - class UUIDType(PrimitiveType): _instance = None @classmethod def get(cls): - """ - @return: The singleton instance of UUIDType. - """ if cls._instance is None: cls._instance = cls() return cls._instance def name(self) -> Name: - """ - @return: The name of the UUID type. - """ return Name.UUID - def simpleString(self) -> str: - """ - @return: A readable string representation of the UUID type. - """ + def simple_string(self) -> str: return "uuid" - """ Fixed-length byte array type. Use BinaryType for variable-length byte arrays. """ - class FixedType(PrimitiveType): def __init__(self, length: int): """ @@ -604,21 +385,12 @@ def of(cls, length: int): return cls(length) def name(self) -> Name: - """ - @return: The name of the fixed type. - """ return Name.FIXED def length(self) -> int: - """ - @return: The length of the fixed type. - """ return self._length - def simpleString(self) -> str: - """ - @return: A readable string representation of the fixed type. - """ + def simple_string(self) -> str: return f"fixed({self._length})" def __eq__(self, other): @@ -633,13 +405,8 @@ def __eq__(self, other): return self._length == other._length def __hash__(self): - """ - @return: A hash code for the FixedType based on its length. - """ return hash(self._length) - """ The varchar type in Gravitino. """ - class VarCharType(PrimitiveType): def __init__(self, length: int): """ @@ -658,21 +425,12 @@ def of(cls, length: int): return cls(length) def name(self) -> Name: - """ - @return: The name of the varchar type. - """ return Name.VARCHAR def length(self) -> int: - """ - @return: The length of the varchar type. - """ return self._length - def simpleString(self) -> str: - """ - @return: A readable string representation of the varchar type. - """ + def simple_string(self) -> str: return f"varchar({self._length})" def __eq__(self, other): @@ -687,13 +445,8 @@ def __eq__(self, other): return self._length == other._length def __hash__(self): - """ - @return: A hash code for the VarCharType based on its length. - """ return hash(self._length) - """ The fixed char type in Gravitino. """ - class FixedCharType(PrimitiveType): def __init__(self, length: int): """ @@ -712,21 +465,12 @@ def of(cls, length: int): return cls(length) def name(self) -> Name: - """ - @return: The name of the fixed char type. - """ return Name.FIXEDCHAR def length(self) -> int: - """ - @return: The length of the fixed char type. - """ return self._length - def simpleString(self) -> str: - """ - @return: A readable string representation of the fixed char type. - """ + def simple_string(self) -> str: return f"char({self._length})" def __eq__(self, other): @@ -741,39 +485,23 @@ def __eq__(self, other): return self._length == other._length def __hash__(self): - """ - @return: A hash code for the FixedCharType based on its length. - """ return hash(self._length) - """ The binary type in Gravitino. """ - class BinaryType(PrimitiveType): _instance = None @classmethod def get(cls): - """ - @return: The singleton instance of BinaryType. - """ if cls._instance is None: cls._instance = cls() return cls._instance def name(self) -> Name: - """ - @return: The name of the binary type. - """ return Name.BINARY - def simpleString(self) -> str: - """ - @return: A readable string representation of the binary type. - """ + def simple_string(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): """ @@ -794,23 +522,14 @@ def of(cls, *fields): return cls(fields) def fields(self): - """ - @return: The fields of the struct type. - """ return self._fields def name(self) -> Name: - """ - @return: The name of the struct type. - """ return Name.STRUCT - def simpleString(self) -> str: - """ - @return: A readable string representation of the struct type. - """ + def simple_string(self) -> str: return ( - f"struct<{', '.join(field.simpleString() for field in self._fields)}>" + f"struct<{', '.join(field.simple_string() for field in self._fields)}>" ) def __eq__(self, other): @@ -825,20 +544,15 @@ def __eq__(self, other): return self._fields == other._fields def __hash__(self): - """ - @return: A hash code for the StructType based on its fields. - """ return hash(tuple(self._fields)) - """ A field of a struct type. """ - class Field: - def __init__(self, name, type, nullable, comment=None): + def __init__(self, name, field_type, nullable, comment=None): """ Initializes the Field with the given name, type, nullable flag, and comment. @param name: The name of the field. - @param type: The type of the field. + @param field_type: The type of the field. @param nullable: Whether the field is nullable. @param comment: The comment of the field (optional). """ @@ -847,52 +561,40 @@ def __init__(self, name, type, nullable, comment=None): if type is None: raise ValueError("type cannot be null") self._name = name - self._type = type + self._field_type = field_type self._nullable = nullable self._comment = comment @classmethod - def notNullField(cls, name, type, comment=None): + def not_null_field(cls, name, field_type, comment=None): """ @param name: The name of the field. - @param type: The type of the field. + @param field_type: The type of the field. @param comment: The comment of the field. - @return: A NOT NULL Field instance with the given name, type, and comment. + @return: A NOT NULL Field instance with the given name, field_type, and comment. """ - return cls(name, type, False, comment) + return cls(name, field_type, False, comment) @classmethod - def nullableField(cls, name, type, comment=None): + def nullable_field(cls, name, field_type, comment=None): """ @param name: The name of the field. - @param type: The type of the field. + @param field_type: The type of the field. @param comment: The comment of the field. - @return: A nullable Field instance with the given name, type, and comment. + @return: A nullable Field instance with the given name, field_type, and comment. """ - return cls(name, type, True, comment) + return cls(name, field_type, True, comment) def name(self): - """ - @return: The name of the field. - """ return self._name def type(self): - """ - @return: The type of the field. - """ return self._type def nullable(self): - """ - @return: Whether the field is nullable. - """ return self._nullable def comment(self): - """ - @return: The comment of the field, or None if not set. - """ return self._comment def __eq__(self, other): @@ -912,91 +614,71 @@ def __eq__(self, other): ) def __hash__(self): - """ - @return: A hash code for the Field based on its attributes. - """ return hash((self._name, self._type, self._nullable)) - def simpleString(self) -> str: - """ - @return: The simple string representation of the field. - """ + def simple_string(self) -> str: nullable_str = "NULL" if self._nullable else "NOT NULL" comment_str = f" COMMENT '{self._comment}'" if self._comment else "" - 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. """ + return f"{self._name}: {self._type.simple_string()} {nullable_str}{comment_str}" class ListType(ComplexType): - def __init__(self, elementType: Type, elementNullable: bool): + def __init__(self, element_type: Type, element_nullable: bool): """ Create a new ListType with the given element type and the type is nullable. - @param elementType: The element type of the list. - @param elementNullable: Whether the element of the list is nullable. + @param element_type: The element type of the list. + @param element_nullable: Whether the element of the list is nullable. """ - if elementType is None: - raise ValueError("elementType cannot be null") - self._elementType = elementType - self._elementNullable = elementNullable + if element_type is None: + raise ValueError("element_type cannot be null") + self._element_type = element_type + self._element_nullable = element_nullable @classmethod - def nullable(cls, elementType: Type): + def nullable(cls, element_type: Type): """ Create a new ListType with the given element type and the type is nullable. - @param elementType: The element type of the list. + @param element_type: The element type of the list. @return: A new ListType instance. """ - return cls.of(elementType, True) + return cls.of(element_type, True) @classmethod - def notNull(cls, elementType: Type): + def not_null(cls, element_type: Type): """ Create a new ListType with the given element type. - @param elementType: The element type of the list. + @param element_type: The element type of the list. @return: A new ListType instance. """ - return cls.of(elementType, False) + return cls.of(element_type, False) @classmethod - def of(cls, elementType: Type, elementNullable: bool): + def of(cls, element_type: Type, element_nullable: bool): """ Create a new ListType with the given element type and whether the element is nullable. - @param elementType: The element type of the list. - @param elementNullable: Whether the element of the list is nullable. + @param element_type: The element type of the list. + @param element_nullable: Whether the element of the list is nullable. @return: A new ListType instance. """ - return cls(elementType, elementNullable) + return cls(element_type, element_nullable) - def elementType(self) -> Type: - """ - @return: The element type of the list. - """ - return self._elementType + def element_type(self) -> Type: + return self._element_type - def elementNullable(self) -> bool: - """ - @return: Whether the element of the list is nullable. - """ - return self._elementNullable + def element_nullable(self) -> bool: + return self._element_nullable def name(self) -> Name: - """ - @return: The name of the list type. - """ return Name.LIST - def simpleString(self) -> str: - """ - @return: A readable string representation of the list type. - """ + def simple_string(self) -> str: return ( - f"list<{self._elementType.simpleString()}>" - if self._elementNullable - else f"list<{self._elementType.simpleString()}, NOT NULL>" + f"list<{self._element_type.simple_string()}>" + if self._element_nullable + else f"list<{self._element_type.simple_string()}, NOT NULL>" ) def __eq__(self, other): @@ -1009,96 +691,74 @@ def __eq__(self, other): if not isinstance(other, Types.ListType): return False return ( - self._elementNullable == other._elementNullable - and self._elementType == other._elementType + self._element_nullable == other._element_nullable + and self._element_type == other._element_type ) def __hash__(self): - """ - @return: A hash code for the ListType based on its element type and nullability. - """ - return hash((self._elementType, self._elementNullable)) - - """ The map type in Gravitino. Note, this type is not supported in the current version of Gravitino. """ + return hash((self._element_type, self._element_nullable)) class MapType(ComplexType): - def __init__(self, keyType: Type, valueType: Type, valueNullable: bool): + def __init__(self, key_type: Type, value_type: Type, value_nullable: bool): """ Create a new MapType with the given key type, value type and the value is nullable. - @param keyType: The key type of the map. - @param valueType: The value type of the map. - @param valueNullable: Whether the value of the map is nullable. + @param key_type: The key type of the map. + @param value_type: The value type of the map. + @param value_nullable: Whether the value of the map is nullable. """ - self._keyType = keyType - self._valueType = valueType - self._valueNullable = valueNullable + self._key_type = key_type + self._value_type = value_type + self._value_nullable = value_nullable @classmethod - def valueNullable(cls, keyType: Type, valueType: Type): + def value_nullable(cls, key_type: Type, value_type: Type): """ Create a new MapType with the given key type, value type, and the value is nullable. - @param keyType: The key type of the map. - @param valueType: The value type of the map. + @param key_type: The key type of the map. + @param value_type: The value type of the map. @return: A new MapType instance. """ - return cls.of(keyType, valueType, True) + return cls.of(key_type, value_type, True) @classmethod - def valueNotNull(cls, keyType: Type, valueType: Type): + def value_not_null(cls, key_type: Type, value_type: Type): """ Create a new MapType with the given key type, value type, and the value is not nullable. - @param keyType: The key type of the map. - @param valueType: The value type of the map. + @param key_type: The key type of the map. + @param value_type: The value type of the map. @return: A new MapType instance. """ - return cls.of(keyType, valueType, False) + return cls.of(key_type, value_type, False) @classmethod - def of(cls, keyType: Type, valueType: Type, valueNullable: bool): + def of(cls, key_type: Type, value_type: Type, value_nullable: bool): """ Create a new MapType with the given key type, value type, and whether the value is nullable. - @param keyType: The key type of the map. - @param valueType: The value type of the map. - @param valueNullable: Whether the value of the map is nullable. + @param key_type: The key type of the map. + @param value_type: The value type of the map. + @param value_nullable: Whether the value of the map is nullable. @return: A new MapType instance. """ - return cls(keyType, valueType, valueNullable) + return cls(key_type, value_type, value_nullable) - def keyType(self) -> Type: - """ - @return: The key type of the map. - """ - return self._keyType + def key_type(self) -> Type: + return self._key_type - def valueType(self) -> Type: - """ - @return: The value type of the map. - """ - return self._valueType + def value_type(self) -> Type: + return self._value_type - def valueNullable(self) -> bool: - """ - @return: Whether the value of the map is nullable. - """ - return self._valueNullable + def is_value_nullable(self) -> bool: + return self._value_nullable def name(self) -> Name: - """ - @return: The name of the map type. - """ return Name.MAP - def simpleString(self) -> str: - """ - @return: A readable string representation of the map type. - """ - return ( - f"map<{self._keyType.simpleString()}, {self._valueType.simpleString()}>" - ) + def simple_string(self) -> str: + return f"map<{self._key_type.simple_string()}, {self._value_type.simple_string()}>" def __eq__(self, other): """ @@ -1110,18 +770,13 @@ 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 + self._value_nullable == other._value_nullable + and self._key_type == other._key_type + and self._value_type == other._value_type ) def __hash__(self): - """ - @return: A hash code for the MapType based on its key type, value type, and nullability. - """ - 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. """ + return hash((self._key_type, self._value_type, self._value_nullable)) class UnionType(ComplexType): def __init__(self, types: list): @@ -1143,22 +798,13 @@ def of(cls, *types: Type): return cls(types) def types(self) -> list: - """ - @return: The types of the union. - """ return self._types def name(self) -> Name: - """ - @return: The name of the union type. - """ return Name.UNION - def simpleString(self) -> str: - """ - @return: A readable string representation of the union type. - """ - return f"union<{', '.join(t.simpleString() for t in self._types)}>" + def simple_string(self) -> str: + return f"union<{', '.join(t.simple_string() for t in self._types)}>" def __eq__(self, other): """ @@ -1172,111 +818,80 @@ def __eq__(self, other): return self._types == other._types def __hash__(self): - """ - @return: A hash code for the UnionType based on its types. - """ 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): + def __init__(self, unparsed_type: str): """ - Initializes an UnparsedType instance. + Initializes an unparsed_type instance. - @param unparsedType: The unparsed type as a string. + @param unparsed_type: The unparsed type as a string. """ - self._unparsedType = unparsedType + self._unparsed_type = unparsed_type @classmethod - def of(cls, unparsedType: str): + def of(cls, unparsed_type: str): """ - Creates a new UnparsedType with the given unparsed type. + Creates a new unparsed_type with the given unparsed type. - @param unparsedType: The unparsed type. - @return: A new UnparsedType instance. + @param unparsed_type: The unparsed type. + @return: A new unparsed_type instance. """ - return cls(unparsedType) + return cls(unparsed_type) - def unparsedType(self) -> str: - """ - @return: The unparsed type as a string. - """ - return self._unparsedType + def unparsed_type(self) -> str: + return self._unparsed_type def name(self) -> Name: - """ - @return: The name of the unparsed type. - """ return Name.UNPARSED - def simpleString(self) -> str: - """ - @return: A readable string representation of the unparsed type. - """ - return f"unparsed({self._unparsedType})" + def simple_string(self) -> str: + return f"unparsed({self._unparsed_type})" def __eq__(self, other): """ - Compares two UnparsedType objects for equality. + Compares two unparsed_type objects for equality. - @param other: The other UnparsedType object to compare with. - @return: True if both UnparsedType objects have the same unparsed type string, False otherwise. + @param other: The other unparsed_type object to compare with. + @return: True if both unparsed_type objects have the same unparsed type string, False otherwise. """ - if not isinstance(other, Types.UnparsedType): + if not isinstance(other, Types.unparsed_type): return False - return self._unparsedType == other._unparsedType + return self._unparsed_type == other._unparsed_type def __hash__(self): - """ - @return: A hash code for the UnparsedType based on its unparsed type string. - """ - return hash(self._unparsedType) + return hash(self._unparsed_type) def __str__(self): - """ - @return: The unparsed type string representation. - """ - return self._unparsedType - - """ Represents a type that is defined in an external catalog. """ + return self._unparsed_type class ExternalType(Type): - def __init__(self, catalogString: str): + def __init__(self, catalog_string: str): """ Initializes an ExternalType instance. - @param catalogString: The string representation of this type in the catalog. + @param catalog_string: The string representation of this type in the catalog. """ - self._catalogString = catalogString + self._catalog_string = catalog_string @classmethod - def of(cls, catalogString: str): + def of(cls, catalog_string: str): """ Creates a new ExternalType with the given catalog string. - @param catalogString: The string representation of this type in the catalog. + @param catalog_string: The string representation of this type in the catalog. @return: A new ExternalType instance. """ - return cls(catalogString) + return cls(catalog_string) - def catalogString(self) -> str: - """ - @return: The string representation of this type in external catalog. - """ - return self._catalogString + def catalog_string(self) -> str: + return self._catalog_string def name(self) -> Name: - """ - @return: The name of the external type. - """ return Name.EXTERNAL - def simpleString(self) -> str: - """ - @return: A readable string representation of the external type. - """ - return f"external({self._catalogString})" + def simple_string(self) -> str: + return f"external({self._catalog_string})" def __eq__(self, other): """ @@ -1287,26 +902,20 @@ def __eq__(self, other): """ if not isinstance(other, Types.ExternalType): return False - return self._catalogString == other._catalogString + return self._catalog_string == other._catalog_string def __hash__(self): - """ - @return: A hash code for the ExternalType based on its catalog string. - """ - return hash(self._catalogString) + return hash(self._catalog_string) def __str__(self): - """ - @return: The string representation of the external type. - """ - return self.simpleString() + return self.simple_string() @staticmethod - def allowAutoIncrement(dataType: Type) -> bool: + def allow_auto_increment(data_type: Type) -> bool: """ Checks if the given data type is allowed to be an auto-increment column. - @param dataType: The data type to check. + @param data_type: The data type to check. @return: True if the given data type is allowed to be an auto-increment column, False otherwise. """ - return isinstance(dataType, (Types.IntegerType, Types.LongType)) + return isinstance(data_type, (Types.IntegerType, Types.LongType)) From 8a513a7df2773a8066036d8bfecbf541dabf64d0 Mon Sep 17 00:00:00 2001 From: YUN SUN Date: Wed, 30 Oct 2024 23:00:10 -0500 Subject: [PATCH 8/9] Update the unite test --- .../tests/unittests/test_types.py | 283 +++++++++--------- 1 file changed, 146 insertions(+), 137 deletions(-) diff --git a/clients/client-python/tests/unittests/test_types.py b/clients/client-python/tests/unittests/test_types.py index f4210c6314..549fd8759b 100644 --- a/clients/client-python/tests/unittests/test_types.py +++ b/clients/client-python/tests/unittests/test_types.py @@ -21,163 +21,172 @@ 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() + instance = Types.NullType.get() + self.assertIsInstance(instance, Types.NullType) + self.assertEqual(instance.name(), Name.NULL) + self.assertEqual(instance.simple_string(), "null") + self.assertIs(instance, Types.NullType.get()) # Singleton check - 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.assertEqual(boolean_type_1.name(), Name.BOOLEAN) - self.assertEqual(boolean_type_1.simpleString(), "boolean") + instance = Types.BooleanType.get() + self.assertIsInstance(instance, Types.BooleanType) + self.assertEqual(instance.name(), Name.BOOLEAN) + self.assertEqual(instance.simple_string(), "boolean") + self.assertIs(instance, Types.BooleanType.get()) # Singleton check - # Test ByteType for signed and unsigned versions def test_byte_type(self): - signed_byte = Types.ByteType.get() - unsigned_byte = Types.ByteType.unsigned() + signed_instance = Types.ByteType.get() + unsigned_instance = Types.ByteType.unsigned() + self.assertIsInstance(signed_instance, Types.ByteType) + self.assertEqual(signed_instance.name(), Name.BYTE) + self.assertEqual(signed_instance.simple_string(), "byte") + self.assertEqual(unsigned_instance.simple_string(), "byte unsigned") - self.assertEqual(signed_byte.name(), Name.BYTE) - self.assertEqual(signed_byte.simpleString(), "byte") - self.assertEqual(unsigned_byte.simpleString(), "byte unsigned") - - # Test ShortType for signed and unsigned versions def test_short_type(self): - signed_short = Types.ShortType.get() - unsigned_short = Types.ShortType.unsigned() - - self.assertEqual(signed_short.name(), Name.SHORT) - self.assertEqual(signed_short.simpleString(), "short") - self.assertEqual(unsigned_short.simpleString(), "short unsigned") + signed_instance = Types.ShortType.get() + unsigned_instance = Types.ShortType.unsigned() + self.assertIsInstance(signed_instance, Types.ShortType) + self.assertEqual(signed_instance.simple_string(), "short") + self.assertEqual(unsigned_instance.simple_string(), "short unsigned") - # Test IntegerType for signed and unsigned versions def test_integer_type(self): - signed_int = Types.IntegerType.get() - unsigned_int = Types.IntegerType.unsigned() - - self.assertEqual(signed_int.name(), Name.INTEGER) - self.assertEqual(signed_int.simpleString(), "integer") - self.assertEqual(unsigned_int.simpleString(), "integer unsigned") + signed_instance = Types.IntegerType.get() + unsigned_instance = Types.IntegerType.unsigned() + self.assertIsInstance(signed_instance, Types.IntegerType) + self.assertEqual(signed_instance.simple_string(), "integer") + self.assertEqual(unsigned_instance.simple_string(), "integer unsigned") + + def test_long_type(self): + signed_instance = Types.LongType.get() + unsigned_instance = Types.LongType.unsigned() + self.assertIsInstance(signed_instance, Types.LongType) + self.assertEqual(signed_instance.simple_string(), "long") + self.assertEqual(unsigned_instance.simple_string(), "long unsigned") + + def test_float_type(self): + instance = Types.FloatType.get() + self.assertEqual(instance.name(), Name.FLOAT) + self.assertEqual(instance.simple_string(), "float") + + def test_double_type(self): + instance = Types.DoubleType.get() + self.assertEqual(instance.name(), Name.DOUBLE) + self.assertEqual(instance.simple_string(), "double") - # Test DecimalType and its methods def test_decimal_type(self): - decimal_type_1 = Types.DecimalType.of(10, 2) - decimal_type_2 = Types.DecimalType.of(10, 2) - decimal_type_3 = Types.DecimalType.of(12, 3) + instance = Types.DecimalType.of(10, 2) + self.assertEqual(instance.name(), Name.DECIMAL) + self.assertEqual(instance.precision(), 10) + self.assertEqual(instance.scale(), 2) + self.assertEqual(instance.simple_string(), "decimal(10,2)") + with self.assertRaises(ValueError): + Types.DecimalType.of(39, 2) # Precision out of range + with self.assertRaises(ValueError): + Types.DecimalType.of(10, 11) # Scale out of range - 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", - ) - - # 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.assertEqual(date_type_1.name(), Name.DATE) - self.assertEqual(date_type_1.simpleString(), "date") + instance = Types.DateType.get() + self.assertEqual(instance.name(), Name.DATE) + self.assertEqual(instance.simple_string(), "date") - # Test TimeType singleton and methods def test_time_type(self): - time_type_1 = Types.TimeType.get() - time_type_2 = Types.TimeType.get() + instance = Types.TimeType.get() + self.assertEqual(instance.name(), Name.TIME) + self.assertEqual(instance.simple_string(), "time") + + def test_timestamp_type(self): + instance_with_tz = Types.TimestampType.with_time_zone() + instance_without_tz = Types.TimestampType.without_time_zone() + self.assertTrue(instance_with_tz.has_time_zone()) + self.assertFalse(instance_without_tz.has_time_zone()) + self.assertEqual(instance_with_tz.simple_string(), "timestamp_tz") + self.assertEqual(instance_without_tz.simple_string(), "timestamp") + + def test_interval_types(self): + year_instance = Types.IntervalYearType.get() + day_instance = Types.IntervalDayType.get() + self.assertEqual(year_instance.name(), Name.INTERVAL_YEAR) + self.assertEqual(day_instance.name(), Name.INTERVAL_DAY) + self.assertEqual(year_instance.simple_string(), "interval_year") + self.assertEqual(day_instance.simple_string(), "interval_day") - 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.assertEqual(string_type_1.name(), Name.STRING) - self.assertEqual(string_type_1.simpleString(), "string") + instance = Types.StringType.get() + self.assertEqual(instance.name(), Name.STRING) + self.assertEqual(instance.simple_string(), "string") - # Test UUIDType singleton and methods def test_uuid_type(self): - uuid_type_1 = Types.UUIDType.get() - uuid_type_2 = Types.UUIDType.get() + instance = Types.UUIDType.get() + self.assertEqual(instance.name(), Name.UUID) + self.assertEqual(instance.simple_string(), "uuid") - 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") - - # Test FixedType creation and equality def test_fixed_type(self): - fixed_type_1 = Types.FixedType.of(16) - fixed_type_2 = Types.FixedType.of(16) - fixed_type_3 = Types.FixedType.of(32) - - self.assertEqual(fixed_type_1.name(), Name.FIXED) - self.assertEqual(fixed_type_1.simpleString(), "fixed(16)") - self.assertEqual(fixed_type_1, fixed_type_2) - self.assertNotEqual(fixed_type_1, fixed_type_3) + instance = Types.FixedType.of(5) + self.assertEqual(instance.name(), Name.FIXED) + self.assertEqual(instance.length(), 5) + self.assertEqual(instance.simple_string(), "fixed(5)") - # Test VarCharType creation and equality def test_varchar_type(self): - varchar_type_1 = Types.VarCharType.of(255) - varchar_type_2 = Types.VarCharType.of(255) - varchar_type_3 = Types.VarCharType.of(512) - - self.assertEqual(varchar_type_1.name(), Name.VARCHAR) - self.assertEqual(varchar_type_1.simpleString(), "varchar(255)") - self.assertEqual(varchar_type_1, varchar_type_2) - self.assertNotEqual(varchar_type_1, varchar_type_3) - - # Test allowAutoIncrement method for IntegerType and LongType - def test_allow_auto_increment(self): - integer_type = Types.IntegerType.get() - long_type = Types.LongType.get() - boolean_type = Types.BooleanType.get() - - self.assertTrue(Types.allowAutoIncrement(integer_type)) - self.assertTrue(Types.allowAutoIncrement(long_type)) - self.assertFalse(Types.allowAutoIncrement(boolean_type)) + instance = Types.VarCharType.of(10) + self.assertEqual(instance.name(), Name.VARCHAR) + self.assertEqual(instance.length(), 10) + self.assertEqual(instance.simple_string(), "varchar(10)") + + def test_fixed_char_type(self): + instance = Types.FixedCharType.of(3) + self.assertEqual(instance.name(), Name.FIXEDCHAR) + self.assertEqual(instance.length(), 3) + self.assertEqual(instance.simple_string(), "char(3)") + + def test_binary_type(self): + instance = Types.BinaryType.get() + self.assertEqual(instance.name(), Name.BINARY) + self.assertEqual(instance.simple_string(), "binary") + + def test_struct_type(self): + field1 = Types.StructType.Field( + "name", Types.StringType.get(), True, "User's name" + ) + field2 = Types.StructType.Field( + "age", Types.IntegerType.get(), False, "User's age" + ) + struct = Types.StructType.of(field1, field2) + self.assertEqual( + struct.simple_string(), + "struct", + ) + + def test_list_type(self): + instance = Types.ListType.of(Types.StringType.get(), True) + self.assertEqual(instance.name(), Name.LIST) + self.assertTrue(instance.element_nullable()) + self.assertEqual(instance.simple_string(), "list") + + def test_map_type(self): + instance = Types.MapType.of( + Types.StringType.get(), Types.IntegerType.get(), True + ) + self.assertEqual(instance.name(), Name.MAP) + self.assertTrue(instance.is_value_nullable()) + self.assertEqual(instance.simple_string(), "map") + + def test_union_type(self): + instance = Types.UnionType.of(Types.StringType.get(), Types.IntegerType.get()) + self.assertEqual(instance.name(), Name.UNION) + self.assertEqual(instance.simple_string(), "union") + + def test_unparsed_type(self): + instance = Types.UnparsedType.of("custom_type") + self.assertEqual(instance.name(), Name.UNPARSED) + self.assertEqual(instance.simple_string(), "unparsed(custom_type)") + + def test_external_type(self): + instance = Types.ExternalType.of("external_type") + self.assertEqual(instance.name(), Name.EXTERNAL) + self.assertEqual(instance.simple_string(), "external(external_type)") + + def test_auto_increment_check(self): + self.assertTrue(Types.allow_auto_increment(Types.IntegerType.get())) + self.assertTrue(Types.allow_auto_increment(Types.LongType.get())) + self.assertFalse(Types.allow_auto_increment(Types.StringType.get())) From cc02a5487ab635373110454ed5f57fb4c0c9bfcd Mon Sep 17 00:00:00 2001 From: YUN SUN Date: Thu, 31 Oct 2024 01:13:45 -0500 Subject: [PATCH 9/9] Fix the bug --- clients/client-python/gravitino/api/types.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/clients/client-python/gravitino/api/types.py b/clients/client-python/gravitino/api/types.py index ebd1cd295a..25e30bfef4 100644 --- a/clients/client-python/gravitino/api/types.py +++ b/clients/client-python/gravitino/api/types.py @@ -588,8 +588,8 @@ def nullable_field(cls, name, field_type, comment=None): def name(self): return self._name - def type(self): - return self._type + def field_type(self): + return self._field_type def nullable(self): return self._nullable @@ -608,18 +608,18 @@ def __eq__(self, other): return False return ( self._name == other._name - and self._type == other._type + and self._field_type == other._field_type and self._nullable == other._nullable and self._comment == other._comment ) def __hash__(self): - return hash((self._name, self._type, self._nullable)) + return hash((self._name, self._field_type, self._nullable)) def simple_string(self) -> str: nullable_str = "NULL" if self._nullable else "NOT NULL" comment_str = f" COMMENT '{self._comment}'" if self._comment else "" - return f"{self._name}: {self._type.simple_string()} {nullable_str}{comment_str}" + return f"{self._name}: {self._field_type.simple_string()} {nullable_str}{comment_str}" class ListType(ComplexType): def __init__(self, element_type: Type, element_nullable: bool):