55
66import numpy as np
77
8- from .attribute_type import get_adapter
9- from .attribute_type import AttributeType
8+ from .codecs import lookup_codec
9+ from .codecs import Codec
1010from .declare import (
1111 CORE_TYPE_NAMES ,
1212 SPECIAL_TYPES ,
1515from .errors import DataJointError
1616
1717
18- class _MissingType (AttributeType ):
19- """Placeholder for missing/unregistered attribute types . Raises error on use."""
18+ class _MissingType (Codec , register = False ):
19+ """Placeholder for missing/unregistered codecs . Raises error on use."""
2020
21- def __init__ (self , name : str ):
22- self ._name = name
21+ name = None # Don't auto-register
22+
23+ def __init__ (self , codec_name : str ):
24+ self ._codec_name = codec_name
2325
2426 @property
2527 def type_name (self ) -> str :
26- return self ._name
28+ return self ._codec_name
2729
28- @property
29- def dtype (self ) -> str :
30+ def get_dtype (self , is_external : bool ) -> str :
3031 raise DataJointError (
31- f"Attribute type <{ self ._name } > is not registered. "
32- "Register it with @dj.register_type or include it in the schema context."
32+ f"Codec <{ self ._codec_name } > is not registered. " f"Define a Codec subclass with name='{ self ._codec_name } '."
3333 )
3434
35- def encode (self , value , * , key = None ):
35+ def encode (self , value , * , key = None , store_name = None ):
3636 raise DataJointError (
37- f"Attribute type <{ self ._name } > is not registered. "
38- "Register it with @dj.register_type or include it in the schema context."
37+ f"Codec <{ self ._codec_name } > is not registered. " f"Define a Codec subclass with name='{ self ._codec_name } '."
3938 )
4039
4140 def decode (self , stored , * , key = None ):
4241 raise DataJointError (
43- f"Attribute type <{ self ._name } > is not registered. "
44- "Register it with @dj.register_type or include it in the schema context."
42+ f"Codec <{ self ._codec_name } > is not registered. " f"Define a Codec subclass with name='{ self ._codec_name } '."
4543 )
4644
4745
@@ -62,7 +60,7 @@ def decode(self, stored, *, key=None):
6260 json = None ,
6361 is_blob = False ,
6462 is_hidden = False ,
65- adapter = None ,
63+ codec = None ,
6664 store = None ,
6765 unsupported = False ,
6866 attribute_expression = None ,
@@ -286,7 +284,7 @@ def _init_from_database(self):
286284 is_blob = any (TYPE_PATTERN [t ].match (attr ["type" ]) for t in ("BYTES" , "NATIVE_BLOB" )),
287285 uuid = False ,
288286 json = bool (TYPE_PATTERN ["JSON" ].match (attr ["type" ])),
289- adapter = None ,
287+ codec = None ,
290288 store = None ,
291289 attribute_expression = None ,
292290 is_hidden = attr ["name" ].startswith ("_" ),
@@ -311,26 +309,24 @@ def _init_from_database(self):
311309 # Store the original type name for display but keep db_type for SQL
312310 attr ["original_type" ] = special ["type" ]
313311
314- # process AttributeTypes (adapted types in angle brackets)
312+ # process Codecs (adapted types in angle brackets)
315313 if special and TYPE_PATTERN ["ADAPTED" ].match (attr ["type" ]):
316314 # Context can be None for built-in types that are globally registered
317- adapter_name = special ["type" ]
315+ codec_spec = special ["type" ]
318316 try :
319- adapter_result = get_adapter (context , adapter_name )
320- # get_adapter returns (adapter, store_name) tuple
321- if isinstance (adapter_result , tuple ):
322- attr ["adapter" ], attr ["store" ] = adapter_result
323- else :
324- attr ["adapter" ] = adapter_result
317+ codec_instance , codec_store = lookup_codec (codec_spec )
318+ attr ["codec" ] = codec_instance
319+ if codec_store is not None :
320+ attr ["store" ] = codec_store
325321 except DataJointError :
326- # if no adapter , then delay the error until the first invocation
327- attr ["adapter " ] = _MissingType (adapter_name )
322+ # if no codec , then delay the error until the first invocation
323+ attr ["codec " ] = _MissingType (codec_spec )
328324 else :
329325 # Determine if external storage based on store presence
330326 is_external = attr .get ("store" ) is not None
331- attr ["type" ] = attr ["adapter " ].get_dtype (is_external = is_external )
327+ attr ["type" ] = attr ["codec " ].get_dtype (is_external = is_external )
332328 if not any (r .match (attr ["type" ]) for r in TYPE_PATTERN .values ()):
333- raise DataJointError (f"Invalid dtype '{ attr ['type' ]} ' in attribute type < { adapter_name } >." )
329+ raise DataJointError (f"Invalid dtype '{ attr ['type' ]} ' in codec < { codec_spec } >." )
334330 # Update is_blob based on resolved dtype (check both BYTES and NATIVE_BLOB patterns)
335331 attr ["is_blob" ] = any (TYPE_PATTERN [t ].match (attr ["type" ]) for t in ("BYTES" , "NATIVE_BLOB" ))
336332
@@ -367,7 +363,7 @@ def _init_from_database(self):
367363
368364 # fill out dtype. All floats and non-nullable integers are turned into specific dtypes
369365 attr ["dtype" ] = object
370- if attr ["numeric" ] and not attr ["adapter " ]:
366+ if attr ["numeric" ] and not attr ["codec " ]:
371367 is_integer = TYPE_PATTERN ["INTEGER" ].match (attr ["type" ])
372368 is_float = TYPE_PATTERN ["FLOAT" ].match (attr ["type" ])
373369 if is_integer and not attr ["nullable" ] or is_float :
@@ -377,9 +373,9 @@ def _init_from_database(self):
377373 assert (t , is_unsigned ) in numeric_types , "dtype not found for type %s" % t
378374 attr ["dtype" ] = numeric_types [(t , is_unsigned )]
379375
380- if attr ["adapter " ]:
381- # restore adapted type name for display
382- attr ["type" ] = adapter_name
376+ if attr ["codec " ]:
377+ # restore codec type name for display
378+ attr ["type" ] = codec_spec
383379
384380 self ._attributes = dict (((q ["name" ], Attribute (** q )) for q in attributes ))
385381
0 commit comments