3030from typing import Any , Generic , Type
3131from uuid import UUID
3232
33- from pyiceberg .typedef import L
33+ from pydantic import Field , model_serializer
34+
35+ from pyiceberg .typedef import IcebergRootModel , L
3436from pyiceberg .types import (
3537 BinaryType ,
3638 BooleanType ,
5254 date_str_to_days ,
5355 date_to_days ,
5456 datetime_to_micros ,
57+ days_to_date ,
5558 micros_to_days ,
59+ micros_to_timestamp ,
5660 time_str_to_micros ,
5761 time_to_micros ,
5862 timestamp_to_micros ,
6468UUID_BYTES_LENGTH = 16
6569
6670
67- class Literal (Generic [L ], ABC ):
71+ class Literal (IcebergRootModel [ L ], Generic [L ], ABC ): # type: ignore
6872 """Literal which has a value and can be converted between types."""
6973
70- _value : L
74+ root : L = Field ()
75+
76+ def __init__ (self , value : L , value_type : Type [L ], / , ** data ): # type: ignore
77+ if value is None :
78+ raise TypeError ("Invalid literal value: None" )
7179
72- def __init__ ( self , value : L , value_type : Type [ L ]):
80+ super (). __init__ ( value )
7381 if value is None or not isinstance (value , value_type ):
7482 raise TypeError (f"Invalid literal value: { value !r} (not a { value_type } )" )
7583 if isinstance (value , float ) and isnan (value ):
7684 raise ValueError ("Cannot create expression literal from NaN." )
77- self ._value = value
7885
7986 @property
8087 def value (self ) -> L :
81- return self ._value
88+ return self .root
8289
8390 @singledispatchmethod
8491 @abstractmethod
@@ -136,25 +143,25 @@ def literal(value: L) -> Literal[L]:
136143 LongLiteral(123)
137144 """
138145 if isinstance (value , float ):
139- return DoubleLiteral (value ) # type: ignore
146+ return DoubleLiteral (value )
140147 elif isinstance (value , bool ):
141148 return BooleanLiteral (value )
142149 elif isinstance (value , int ):
143150 return LongLiteral (value )
144151 elif isinstance (value , str ):
145152 return StringLiteral (value )
146153 elif isinstance (value , UUID ):
147- return UUIDLiteral (value .bytes ) # type: ignore
154+ return UUIDLiteral (value .bytes )
148155 elif isinstance (value , bytes ):
149156 return BinaryLiteral (value )
150157 elif isinstance (value , Decimal ):
151158 return DecimalLiteral (value )
152159 elif isinstance (value , datetime ):
153- return TimestampLiteral (datetime_to_micros (value )) # type: ignore
160+ return TimestampLiteral (datetime_to_micros (value ))
154161 elif isinstance (value , date ):
155- return DateLiteral (date_to_days (value )) # type: ignore
162+ return DateLiteral (date_to_days (value ))
156163 elif isinstance (value , time ):
157- return TimeLiteral (time_to_micros (value )) # type: ignore
164+ return TimeLiteral (time_to_micros (value ))
158165 else :
159166 raise TypeError (f"Invalid literal value: { repr (value )} " )
160167
@@ -411,6 +418,10 @@ class DateLiteral(Literal[int]):
411418 def __init__ (self , value : int ) -> None :
412419 super ().__init__ (value , int )
413420
421+ @model_serializer
422+ def ser_model (self ) -> date :
423+ return days_to_date (self .root )
424+
414425 def increment (self ) -> Literal [int ]:
415426 return DateLiteral (self .value + 1 )
416427
@@ -443,6 +454,10 @@ class TimestampLiteral(Literal[int]):
443454 def __init__ (self , value : int ) -> None :
444455 super ().__init__ (value , int )
445456
457+ @model_serializer
458+ def ser_model (self ) -> str :
459+ return micros_to_timestamp (self .root ).isoformat ()
460+
446461 def increment (self ) -> Literal [int ]:
447462 return TimestampLiteral (self .value + 1 )
448463
@@ -635,6 +650,10 @@ class UUIDLiteral(Literal[bytes]):
635650 def __init__ (self , value : bytes ) -> None :
636651 super ().__init__ (value , bytes )
637652
653+ @model_serializer
654+ def ser_model (self ) -> UUID :
655+ return UUID (bytes = self .root )
656+
638657 @singledispatchmethod
639658 def to (self , type_var : IcebergType ) -> Literal : # type: ignore
640659 raise TypeError (f"Cannot convert UUIDLiteral into { type_var } " )
@@ -661,6 +680,10 @@ class FixedLiteral(Literal[bytes]):
661680 def __init__ (self , value : bytes ) -> None :
662681 super ().__init__ (value , bytes )
663682
683+ @model_serializer
684+ def ser_model (self ) -> str :
685+ return self .root .hex ()
686+
664687 @singledispatchmethod
665688 def to (self , type_var : IcebergType ) -> Literal : # type: ignore
666689 raise TypeError (f"Cannot convert FixedLiteral into { type_var } " )
@@ -692,6 +715,10 @@ class BinaryLiteral(Literal[bytes]):
692715 def __init__ (self , value : bytes ) -> None :
693716 super ().__init__ (value , bytes )
694717
718+ @model_serializer
719+ def ser_model (self ) -> str :
720+ return self .root .hex ()
721+
695722 @singledispatchmethod
696723 def to (self , type_var : IcebergType ) -> Literal : # type: ignore
697724 raise TypeError (f"Cannot convert BinaryLiteral into { type_var } " )
0 commit comments