14
14
15
15
from __future__ import annotations
16
16
17
- import warnings
18
17
from dataclasses import dataclass
19
18
from typing import Any
20
19
21
20
from astrapy .data .info .table_descriptor .table_columns import TableAPISupportDescriptor
22
21
from astrapy .data .info .table_descriptor .type_creation import CreateTypeDefinition
23
- from astrapy .data .utils .table_types import TableUDTColumnType
22
+ from astrapy .data .utils .table_types import (
23
+ TableUDTColumnType ,
24
+ TableUnsupportedColumnType ,
25
+ )
24
26
from astrapy .utils .parsing import _warn_residual_keys
25
27
26
28
@@ -29,47 +31,78 @@ class ListTypeDescriptor:
29
31
"""
30
32
A structure describing a user-defined type (UDT) stored on the database.
31
33
32
- This description provides all information, including the UDT name as found
33
- on the database and possibly a sub-object detailing the allowed operations
34
- with the UDT. `ListTypeDescriptor` objects are used for the return
35
- type of the database `list_types` method.
34
+ This object is used for the items returned by the database `list_types` method.
35
+ `ListTypeDescriptor` expresses all information received by the Data API, including
36
+ (when provided) the UDT name as found on the database, the UDT name and possibly a
37
+ sub-object detailing the allowed operations with the UDT.
38
+
39
+ This object must be able to describe any item returned from the Data API:
40
+ this means it can describe "unsupported" UDTs as well (i.e. those which have been
41
+ created outside of the Data API). Unsupported UDTs lack some attributes compared
42
+ to the fully-supported ones.
36
43
37
44
Attributes:
45
+ udt_type: a value of either the TableUDTColumnType or
46
+ the TableUnsupportedColumnType enum, depending on the UDT support status.
38
47
udt_name: the name of the UDT as is stored in the database (and in a keyspace).
39
48
definition: the definition of the type, i.e. its fields and their types.
40
49
api_support: a structure detailing what operations the type supports.
41
50
"""
42
51
43
- udt_name : str
44
- definition : CreateTypeDefinition
52
+ udt_type : TableUDTColumnType | TableUnsupportedColumnType
53
+ udt_name : str | None
54
+ definition : CreateTypeDefinition | None
45
55
api_support : TableAPISupportDescriptor | None
46
56
47
57
def __init__ (
48
58
self ,
49
59
* ,
50
- udt_name : str ,
51
- definition : CreateTypeDefinition ,
60
+ udt_type : TableUDTColumnType | TableUnsupportedColumnType ,
61
+ udt_name : str | None ,
62
+ definition : CreateTypeDefinition | None ,
52
63
api_support : TableAPISupportDescriptor | None ,
53
64
) -> None :
65
+ self .udt_type = udt_type
54
66
self .udt_name = udt_name
55
67
self .definition = definition
56
68
self .api_support = api_support
57
69
58
70
def __repr__ (self ) -> str :
59
- return f"{ self .__class__ .__name__ } ({ self .udt_name } : { self .definition } )"
71
+ if isinstance (self .udt_type , TableUnsupportedColumnType ):
72
+ return f"{ self .__class__ .__name__ } ({ self .udt_type .value } )"
73
+ else :
74
+ return f"{ self .__class__ .__name__ } ({ self .udt_name } : { self .definition } )"
75
+
76
+ @staticmethod
77
+ def _is_valid_dict (raw_dict : dict [str , Any ]) -> bool :
78
+ """
79
+ Assess whether a dictionary can be converted into a ListTypeDescriptor.
80
+
81
+ This can be used by e.g. the database `list_types` method to filter
82
+ offending responses and issue warnings if needed.
83
+
84
+ Returns:
85
+ True if and only if the dict is valid, otherwise False.
86
+ """
87
+
88
+ return all (fld in raw_dict for fld in {"type" , "apiSupport" })
60
89
61
90
def as_dict (self ) -> dict [str , Any ]:
62
91
"""Recast this object into a dictionary."""
63
92
64
93
return {
65
- "type" : TableUDTColumnType .USERDEFINED .value ,
66
- "udtName" : self .udt_name ,
67
- "definition" : self .definition .as_dict (),
68
- ** (
69
- {"apiSupport" : self .api_support .as_dict ()}
94
+ k : v
95
+ for k , v in {
96
+ "type" : self .udt_type .value ,
97
+ "udtName" : self .udt_name ,
98
+ "definition" : self .definition .as_dict ()
99
+ if self .definition is not None
100
+ else None ,
101
+ "apiSupport" : self .api_support .as_dict ()
70
102
if self .api_support is not None
71
- else {}
72
- ),
103
+ else None ,
104
+ }.items ()
105
+ if v is not None
73
106
}
74
107
75
108
@classmethod
@@ -82,16 +115,17 @@ def _from_dict(cls, raw_dict: dict[str, Any]) -> ListTypeDescriptor:
82
115
_warn_residual_keys (
83
116
cls , raw_dict , {"type" , "udtName" , "definition" , "apiSupport" }
84
117
)
85
- if "type" in raw_dict :
86
- if raw_dict ["type" ] != TableUDTColumnType .USERDEFINED .value :
87
- warnings .warn (
88
- "Unexpected 'type' found in a UDT description from the Data API: "
89
- f"{ repr (raw_dict ['type' ])} "
90
- f"(for user-defined type '{ raw_dict .get ('udtName' )} ')."
91
- )
118
+ _udt_type : TableUDTColumnType | TableUnsupportedColumnType
119
+ if raw_dict ["type" ] in TableUDTColumnType :
120
+ _udt_type = TableUDTColumnType .coerce (raw_dict ["type" ])
121
+ else :
122
+ _udt_type = TableUnsupportedColumnType .coerce (raw_dict ["type" ])
92
123
return ListTypeDescriptor (
93
- udt_name = raw_dict ["udtName" ],
94
- definition = CreateTypeDefinition ._from_dict (raw_dict ["definition" ]),
124
+ udt_type = _udt_type ,
125
+ udt_name = raw_dict .get ("udtName" ),
126
+ definition = CreateTypeDefinition ._from_dict (raw_dict ["definition" ])
127
+ if "definition" in raw_dict
128
+ else None ,
95
129
api_support = TableAPISupportDescriptor ._from_dict (raw_dict ["apiSupport" ])
96
130
if "apiSupport" in raw_dict
97
131
else None ,
0 commit comments