55
66from __future__ import annotations
77
8+ import warnings
89from dataclasses import dataclass , field
910from typing import Any , ClassVar , Dict , Iterator , KeysView , List , Optional
1011
@@ -63,6 +64,38 @@ class ColumnInfo:
6364 max_length : Optional [int ] = None
6465 metadata_id : Optional [str ] = None
6566
67+ # ---------------------------------------------- deprecated property aliases
68+
69+ @property
70+ def type (self ) -> str :
71+ """Column type name (deprecated, use ``attribute_type_name`` or ``attribute_type``)."""
72+ warnings .warn (
73+ "ColumnInfo.type is deprecated. Use attribute_type_name or attribute_type instead." ,
74+ DeprecationWarning ,
75+ stacklevel = 2 ,
76+ )
77+ return self .attribute_type_name or self .attribute_type
78+
79+ @property
80+ def is_primary (self ) -> bool :
81+ """Whether this is the primary name column (deprecated, use ``is_primary_name``)."""
82+ warnings .warn (
83+ "ColumnInfo.is_primary is deprecated. Use is_primary_name instead." ,
84+ DeprecationWarning ,
85+ stacklevel = 2 ,
86+ )
87+ return self .is_primary_name
88+
89+ @property
90+ def is_required (self ) -> bool :
91+ """Whether the column is required (deprecated, use ``required_level``)."""
92+ warnings .warn (
93+ "ColumnInfo.is_required is deprecated. Use required_level instead." ,
94+ DeprecationWarning ,
95+ stacklevel = 2 ,
96+ )
97+ return self .required_level not in (None , "" , "None" )
98+
6699 @classmethod
67100 def from_api_response (cls , data : Dict [str , Any ]) -> ColumnInfo :
68101 """Create from a raw Dataverse ``AttributeMetadata`` API response.
@@ -154,6 +187,10 @@ class TableInfo:
154187 description : Optional [str ] = None
155188 columns : Optional [List [ColumnInfo ]] = field (default = None , repr = False )
156189 columns_created : Optional [List [str ]] = field (default = None , repr = False )
190+ one_to_many_relationships : Optional [List [Dict [str , Any ]]] = field (default = None , repr = False )
191+ many_to_one_relationships : Optional [List [Dict [str , Any ]]] = field (default = None , repr = False )
192+ many_to_many_relationships : Optional [List [Dict [str , Any ]]] = field (default = None , repr = False )
193+ _extra : Dict [str , Any ] = field (default_factory = dict , repr = False , compare = False )
157194
158195 # Maps legacy dict keys (used by existing code) to attribute names.
159196 _LEGACY_KEY_MAP : ClassVar [Dict [str , str ]] = {
@@ -171,16 +208,24 @@ def _resolve_key(self, key: str) -> str:
171208 return self ._LEGACY_KEY_MAP .get (key , key )
172209
173210 def __getitem__ (self , key : str ) -> Any :
211+ if key in self ._extra :
212+ return self ._extra [key ]
174213 attr = self ._resolve_key (key )
175214 if hasattr (self , attr ):
176- return getattr (self , attr )
215+ val = getattr (self , attr )
216+ if val is not None or key in self ._LEGACY_KEY_MAP :
217+ return val
177218 raise KeyError (key )
178219
179220 def __contains__ (self , key : object ) -> bool :
180221 if not isinstance (key , str ):
181222 return False
223+ if key in self ._extra :
224+ return True
182225 attr = self ._resolve_key (key )
183- return hasattr (self , attr )
226+ if not hasattr (self , attr ):
227+ return False
228+ return getattr (self , attr ) is not None
184229
185230 def __iter__ (self ) -> Iterator [str ]:
186231 return iter (self ._LEGACY_KEY_MAP )
@@ -246,13 +291,22 @@ def from_api_response(cls, response_data: Dict[str, Any]) -> TableInfo:
246291 desc_label = desc_obj .get ("UserLocalizedLabel" ) or {}
247292 description = desc_label .get ("Label" )
248293
294+ # Parse columns if Attributes are present
295+ columns = None
296+ if "Attributes" in response_data :
297+ columns = [ColumnInfo .from_api_response (a ) for a in response_data ["Attributes" ]]
298+
249299 return cls (
250300 schema_name = response_data .get ("SchemaName" , "" ),
251301 logical_name = response_data .get ("LogicalName" , "" ),
252302 entity_set_name = response_data .get ("EntitySetName" , "" ),
253303 metadata_id = response_data .get ("MetadataId" , "" ),
254304 display_name = display_name ,
255305 description = description ,
306+ columns = columns ,
307+ one_to_many_relationships = response_data .get ("OneToManyRelationships" ),
308+ many_to_one_relationships = response_data .get ("ManyToOneRelationships" ),
309+ many_to_many_relationships = response_data .get ("ManyToManyRelationships" ),
256310 )
257311
258312 # -------------------------------------------------------------- conversion
0 commit comments