adss 1.0__py3-none-any.whl → 1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- adss/__init__.py +24 -0
- adss/auth.py +121 -0
- adss/client.py +671 -0
- adss/endpoints/__init__.py +14 -0
- adss/endpoints/admin.py +433 -0
- adss/endpoints/images.py +898 -0
- adss/endpoints/metadata.py +216 -0
- adss/endpoints/queries.py +498 -0
- adss/endpoints/users.py +311 -0
- adss/exceptions.py +57 -0
- adss/models/__init__.py +13 -0
- adss/models/metadata.py +138 -0
- adss/models/query.py +134 -0
- adss/models/user.py +123 -0
- adss/utils.py +107 -0
- {adss-1.0.dist-info → adss-1.2.dist-info}/METADATA +1 -1
- adss-1.2.dist-info/RECORD +30 -0
- {adss-1.0.dist-info → adss-1.2.dist-info}/WHEEL +1 -1
- adss-1.0.dist-info/RECORD +0 -16
- {adss-1.0.dist-info → adss-1.2.dist-info}/LICENSE +0 -0
- {adss-1.0.dist-info → adss-1.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,216 @@
|
|
1
|
+
"""
|
2
|
+
Database metadata functionality for the Astronomy TAP Client.
|
3
|
+
"""
|
4
|
+
import requests
|
5
|
+
from typing import Dict, List, Optional, Any
|
6
|
+
|
7
|
+
from ..exceptions import (
|
8
|
+
AuthenticationError, ResourceNotFoundError, PermissionDeniedError
|
9
|
+
)
|
10
|
+
from adss.utils import handle_response_errors
|
11
|
+
from adss.models.metadata import Column, Table, Schema, DatabaseMetadata
|
12
|
+
|
13
|
+
|
14
|
+
class MetadataEndpoint:
|
15
|
+
"""
|
16
|
+
Handles database metadata discovery.
|
17
|
+
"""
|
18
|
+
|
19
|
+
def __init__(self, base_url: str, auth_manager):
|
20
|
+
"""
|
21
|
+
Initialize the Metadata endpoint.
|
22
|
+
|
23
|
+
Args:
|
24
|
+
base_url: The base URL of the API server
|
25
|
+
auth_manager: Authentication manager providing auth headers
|
26
|
+
"""
|
27
|
+
self.base_url = base_url.rstrip('/')
|
28
|
+
self.auth_manager = auth_manager
|
29
|
+
|
30
|
+
def get_schemas(self, **kwargs) -> List[str]:
|
31
|
+
"""
|
32
|
+
Get a list of accessible database schemas.
|
33
|
+
|
34
|
+
Args:
|
35
|
+
**kwargs: Additional keyword arguments to pass to the request (e.g., verify=False)
|
36
|
+
|
37
|
+
Returns:
|
38
|
+
List of schema names accessible to the current user
|
39
|
+
|
40
|
+
Raises:
|
41
|
+
AuthenticationError: If not authenticated (for protected schemas)
|
42
|
+
"""
|
43
|
+
try:
|
44
|
+
response = self.auth_manager.request(
|
45
|
+
method="GET",
|
46
|
+
url="/adss/v1/metadata/schemas",
|
47
|
+
**kwargs
|
48
|
+
)
|
49
|
+
handle_response_errors(response)
|
50
|
+
|
51
|
+
return response.json()
|
52
|
+
|
53
|
+
except Exception as e:
|
54
|
+
# Authentication error only if trying to access protected schemas
|
55
|
+
# Anonymous users should still see public schemas
|
56
|
+
if hasattr(e, 'response') and e.response.status_code == 401:
|
57
|
+
raise AuthenticationError("Authentication required for protected schemas")
|
58
|
+
raise
|
59
|
+
|
60
|
+
def get_tables(self, schema_name: str, **kwargs) -> List[str]:
|
61
|
+
"""
|
62
|
+
Get a list of accessible tables in a schema.
|
63
|
+
|
64
|
+
Args:
|
65
|
+
schema_name: Name of the schema
|
66
|
+
**kwargs: Additional keyword arguments to pass to the request (e.g., verify=False)
|
67
|
+
|
68
|
+
Returns:
|
69
|
+
List of table names in the schema accessible to the current user
|
70
|
+
|
71
|
+
Raises:
|
72
|
+
AuthenticationError: If not authenticated (for protected schemas)
|
73
|
+
PermissionDeniedError: If the user doesn't have access to the schema
|
74
|
+
ResourceNotFoundError: If the schema doesn't exist
|
75
|
+
"""
|
76
|
+
try:
|
77
|
+
response = self.auth_manager.request(
|
78
|
+
method="GET",
|
79
|
+
url=f"/adss/v1/metadata/schemas/{schema_name}/tables",
|
80
|
+
**kwargs
|
81
|
+
)
|
82
|
+
handle_response_errors(response)
|
83
|
+
|
84
|
+
return response.json()
|
85
|
+
|
86
|
+
except Exception as e:
|
87
|
+
if hasattr(e, 'response'):
|
88
|
+
if e.response.status_code == 401:
|
89
|
+
raise AuthenticationError("Authentication required for protected schemas")
|
90
|
+
elif e.response.status_code == 403:
|
91
|
+
raise PermissionDeniedError(f"Access denied to schema: {schema_name}")
|
92
|
+
elif e.response.status_code == 404:
|
93
|
+
raise ResourceNotFoundError(f"Schema not found: {schema_name}")
|
94
|
+
raise
|
95
|
+
|
96
|
+
def get_columns(self, schema_name: str, table_name: str, **kwargs) -> List[Column]:
|
97
|
+
"""
|
98
|
+
Get a list of columns in a table.
|
99
|
+
|
100
|
+
Args:
|
101
|
+
schema_name: Name of the schema
|
102
|
+
table_name: Name of the table
|
103
|
+
**kwargs: Additional keyword arguments to pass to the request (e.g., verify=False)
|
104
|
+
|
105
|
+
Returns:
|
106
|
+
List of Column objects in the table
|
107
|
+
|
108
|
+
Raises:
|
109
|
+
AuthenticationError: If not authenticated (for protected schemas)
|
110
|
+
PermissionDeniedError: If the user doesn't have access to the table
|
111
|
+
ResourceNotFoundError: If the schema or table doesn't exist
|
112
|
+
"""
|
113
|
+
try:
|
114
|
+
response = self.auth_manager.request(
|
115
|
+
method="GET",
|
116
|
+
url=f"/adss/v1/metadata/schemas/{schema_name}/tables/{table_name}/columns",
|
117
|
+
**kwargs
|
118
|
+
)
|
119
|
+
handle_response_errors(response)
|
120
|
+
|
121
|
+
columns_data = response.json()
|
122
|
+
return [Column.from_dict(col_data) for col_data in columns_data]
|
123
|
+
|
124
|
+
except Exception as e:
|
125
|
+
if hasattr(e, 'response'):
|
126
|
+
if e.response.status_code == 401:
|
127
|
+
raise AuthenticationError("Authentication required for protected schemas")
|
128
|
+
elif e.response.status_code == 403:
|
129
|
+
raise PermissionDeniedError(f"Access denied to table: {schema_name}.{table_name}")
|
130
|
+
elif e.response.status_code == 404:
|
131
|
+
raise ResourceNotFoundError(f"Table not found: {schema_name}.{table_name}")
|
132
|
+
raise
|
133
|
+
|
134
|
+
def get_database_metadata(self, **kwargs) -> DatabaseMetadata:
|
135
|
+
"""
|
136
|
+
Get comprehensive database metadata for accessible schemas and tables.
|
137
|
+
|
138
|
+
Args:
|
139
|
+
**kwargs: Additional keyword arguments to pass to the request (e.g., verify=False)
|
140
|
+
|
141
|
+
Returns:
|
142
|
+
DatabaseMetadata object containing all accessible schema and table information
|
143
|
+
|
144
|
+
Raises:
|
145
|
+
AuthenticationError: If not authenticated (for protected schemas)
|
146
|
+
"""
|
147
|
+
try:
|
148
|
+
response = self.auth_manager.request(
|
149
|
+
method="GET",
|
150
|
+
url="/adss/v1/metadata/database",
|
151
|
+
**kwargs
|
152
|
+
)
|
153
|
+
handle_response_errors(response)
|
154
|
+
|
155
|
+
metadata = response.json()
|
156
|
+
return DatabaseMetadata.from_dict(metadata)
|
157
|
+
|
158
|
+
except Exception as e:
|
159
|
+
if hasattr(e, 'response') and e.response.status_code == 401:
|
160
|
+
raise AuthenticationError("Authentication required for protected schemas")
|
161
|
+
raise
|
162
|
+
|
163
|
+
def get_table_info(self, schema_name: str, table_name: str, **kwargs) -> Table:
|
164
|
+
"""
|
165
|
+
Get detailed information about a specific table.
|
166
|
+
|
167
|
+
Args:
|
168
|
+
schema_name: Name of the schema
|
169
|
+
table_name: Name of the table
|
170
|
+
**kwargs: Additional keyword arguments to pass to the request (e.g., verify=False)
|
171
|
+
|
172
|
+
Returns:
|
173
|
+
Table object with column information
|
174
|
+
|
175
|
+
Raises:
|
176
|
+
AuthenticationError: If not authenticated (for protected schemas)
|
177
|
+
PermissionDeniedError: If the user doesn't have access to the table
|
178
|
+
ResourceNotFoundError: If the schema or table doesn't exist
|
179
|
+
"""
|
180
|
+
# Get columns for the table
|
181
|
+
columns = self.get_columns(schema_name, table_name, **kwargs)
|
182
|
+
|
183
|
+
# Create and return Table object
|
184
|
+
return Table(name=table_name, columns=columns)
|
185
|
+
|
186
|
+
def get_schema_info(self, schema_name: str, **kwargs) -> Schema:
|
187
|
+
"""
|
188
|
+
Get detailed information about a specific schema.
|
189
|
+
|
190
|
+
Args:
|
191
|
+
schema_name: Name of the schema
|
192
|
+
**kwargs: Additional keyword arguments to pass to the request (e.g., verify=False)
|
193
|
+
|
194
|
+
Returns:
|
195
|
+
Schema object with table information
|
196
|
+
|
197
|
+
Raises:
|
198
|
+
AuthenticationError: If not authenticated (for protected schemas)
|
199
|
+
PermissionDeniedError: If the user doesn't have access to the schema
|
200
|
+
ResourceNotFoundError: If the schema doesn't exist
|
201
|
+
"""
|
202
|
+
# Get tables in the schema
|
203
|
+
table_names = self.get_tables(schema_name, **kwargs)
|
204
|
+
|
205
|
+
# Get information for each table
|
206
|
+
tables = []
|
207
|
+
for table_name in table_names:
|
208
|
+
try:
|
209
|
+
table = self.get_table_info(schema_name, table_name, **kwargs)
|
210
|
+
tables.append(table)
|
211
|
+
except PermissionDeniedError:
|
212
|
+
# Skip tables we don't have access to
|
213
|
+
continue
|
214
|
+
|
215
|
+
# Create and return Schema object
|
216
|
+
return Schema(name=schema_name, tables=tables)
|