1212from typing import TYPE_CHECKING
1313from typing import TypeVar
1414
15+ from typing_extensions import Self
16+
1517from ulid import base32
1618from ulid import constants
1719
@@ -51,9 +53,6 @@ def wrapped(cls: Any, value: T) -> R:
5153 return wrapped
5254
5355
54- U = TypeVar ("U" , bound = "ULID" )
55-
56-
5756@functools .total_ordering
5857class ULID :
5958 """The :class:`ULID` object consists of a timestamp part of 48 bits and of 80 random bits.
@@ -89,7 +88,7 @@ def __init__(self, value: bytes | None = None) -> None:
8988
9089 @classmethod
9190 @validate_type (datetime )
92- def from_datetime (cls : type [ U ] , value : datetime ) -> U :
91+ def from_datetime (cls , value : datetime ) -> Self :
9392 """Create a new :class:`ULID`-object from a :class:`datetime`. The timestamp part of the
9493 `ULID` will be set to the corresponding timestamp of the datetime.
9594
@@ -103,7 +102,7 @@ def from_datetime(cls: type[U], value: datetime) -> U:
103102
104103 @classmethod
105104 @validate_type (int , float )
106- def from_timestamp (cls : type [ U ] , value : float ) -> U :
105+ def from_timestamp (cls , value : float ) -> Self :
107106 """Create a new :class:`ULID`-object from a timestamp. The timestamp can be either a
108107 `float` representing the time in seconds (as it would be returned by :func:`time.time()`)
109108 or an `int` in milliseconds.
@@ -122,7 +121,7 @@ def from_timestamp(cls: type[U], value: float) -> U:
122121
123122 @classmethod
124123 @validate_type (uuid .UUID )
125- def from_uuid (cls : type [ U ] , value : uuid .UUID ) -> U :
124+ def from_uuid (cls , value : uuid .UUID ) -> Self :
126125 """Create a new :class:`ULID`-object from a :class:`uuid.UUID`. The timestamp part will be
127126 random in that case.
128127
@@ -136,37 +135,37 @@ def from_uuid(cls: type[U], value: uuid.UUID) -> U:
136135
137136 @classmethod
138137 @validate_type (bytes )
139- def from_bytes (cls : type [ U ] , bytes_ : bytes ) -> U :
138+ def from_bytes (cls , bytes_ : bytes ) -> Self :
140139 """Create a new :class:`ULID`-object from sequence of 16 bytes."""
141140 return cls (bytes_ )
142141
143142 @classmethod
144143 @validate_type (str )
145- def from_hex (cls : type [ U ] , value : str ) -> U :
144+ def from_hex (cls , value : str ) -> Self :
146145 """Create a new :class:`ULID`-object from 32 character string of hex values."""
147146 return cls .from_bytes (bytes .fromhex (value ))
148147
149148 @classmethod
150149 @validate_type (str )
151- def from_str (cls : type [ U ] , string : str ) -> U :
150+ def from_str (cls , string : str ) -> Self :
152151 """Create a new :class:`ULID`-object from a 26 char long string representation."""
153152 return cls (base32 .decode (string ))
154153
155154 @classmethod
156155 @validate_type (int )
157- def from_int (cls : type [ U ] , value : int ) -> U :
156+ def from_int (cls , value : int ) -> Self :
158157 """Create a new :class:`ULID`-object from an `int`."""
159158 return cls (int .to_bytes (value , constants .BYTES_LEN , "big" ))
160159
161160 @classmethod
162- def parse (cls : type [ U ] , value : Any ) -> U :
161+ def parse (cls , value : Any ) -> Self :
163162 """Create a new :class:`ULID`-object from a given value.
164163
165164 .. note:: This method should only be used when the caller is trying to parse a ULID from
166165 a value when they're unsure what format/primitive type it will be given in.
167166 """
168167 if isinstance (value , ULID ):
169- return cast (U , value )
168+ return cast (Self , value )
170169 if isinstance (value , uuid .UUID ):
171170 return cls .from_uuid (value )
172171 if isinstance (value , str ):
@@ -309,6 +308,7 @@ def __get_pydantic_core_schema__(cls, source: Any, handler: GetCoreSchemaHandler
309308 def _pydantic_validate (cls , value : Any , handler : ValidatorFunctionWrapHandler ) -> Any :
310309 from pydantic_core import PydanticCustomError
311310
311+ ulid : ULID
312312 try :
313313 if isinstance (value , int ):
314314 ulid = cls .from_int (value )
0 commit comments