adss 0.1__py3-none-any.whl → 1.1__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/utils.py ADDED
@@ -0,0 +1,107 @@
1
+ """
2
+ Utility functions for the Astronomy TAP Client.
3
+ """
4
+ import json
5
+ import pandas as pd
6
+ import pyarrow.parquet as pq
7
+ import io
8
+ from datetime import datetime
9
+ from typing import Dict, Any, Optional, Union, List
10
+
11
+ from .exceptions import (
12
+ ADSSClientError, AuthenticationError, PermissionDeniedError,
13
+ ResourceNotFoundError, QueryExecutionError, ServerError
14
+ )
15
+
16
+
17
+ def handle_response_errors(response):
18
+ """Handles HTTP response errors and raises appropriate exceptions."""
19
+ if 200 <= response.status_code < 300:
20
+ return response
21
+
22
+ try:
23
+ error_data = response.json()
24
+ error_message = error_data.get('detail', str(error_data))
25
+ except Exception:
26
+ error_message = response.text or f"HTTP Error {response.status_code}"
27
+
28
+ # For 401 errors, check if it's an anonymous query attempt
29
+ if response.status_code == 401:
30
+ # If the error mentions "authentication required for protected schemas"
31
+ # or similar, it's likely an anonymous query trying to access restricted data
32
+ if "protected" in error_message.lower() or "requires authentication" in error_message.lower():
33
+ raise PermissionDeniedError(f"This query requires authentication: {error_message}", response)
34
+ else:
35
+ raise AuthenticationError(error_message, response)
36
+ elif response.status_code == 403:
37
+ raise PermissionDeniedError(error_message, response)
38
+ elif response.status_code == 404:
39
+ raise ResourceNotFoundError(error_message, response)
40
+ elif response.status_code >= 500:
41
+ raise ServerError(f"Server error: {error_message}", response)
42
+ else:
43
+ raise ADSSClientError(error_message, response)
44
+
45
+ def parse_datetime(dt_str: Optional[str]) -> Optional[datetime]:
46
+ """
47
+ Parses a datetime string into a datetime object.
48
+ """
49
+ if not dt_str:
50
+ return None
51
+
52
+ try:
53
+ return datetime.fromisoformat(dt_str.replace('Z', '+00:00'))
54
+ except (ValueError, TypeError):
55
+ return None
56
+
57
+
58
+ def parquet_to_dataframe(parquet_data: bytes) -> pd.DataFrame:
59
+ """
60
+ Converts Parquet bytes to a pandas DataFrame.
61
+ """
62
+ try:
63
+ buffer = io.BytesIO(parquet_data)
64
+ table = pq.read_table(buffer)
65
+ return table.to_pandas()
66
+ except Exception as e:
67
+ raise ADSSClientError(f"Failed to convert Parquet data to DataFrame: {str(e)}")
68
+
69
+
70
+ def format_table_name(schema: str, table: str) -> str:
71
+ """
72
+ Formats a schema and table name into a fully qualified table name.
73
+ """
74
+ return f"{schema}.{table}"
75
+
76
+
77
+ def prepare_query_params(params: Dict[str, Any]) -> Dict[str, str]:
78
+ """
79
+ Prepares query parameters for API requests, handling different types.
80
+ """
81
+ processed_params = {}
82
+
83
+ for key, value in params.items():
84
+ if value is None:
85
+ continue
86
+ elif isinstance(value, bool):
87
+ processed_params[key] = str(value).lower()
88
+ elif isinstance(value, (list, dict)):
89
+ processed_params[key] = json.dumps(value)
90
+ else:
91
+ processed_params[key] = str(value)
92
+
93
+ return processed_params
94
+
95
+
96
+ def format_permission(permission_type: str) -> str:
97
+ """
98
+ Validates and formats a permission type (read, write, all).
99
+ """
100
+ valid_permissions = {'read', 'write', 'all'}
101
+ permission = permission_type.lower()
102
+
103
+ if permission not in valid_permissions:
104
+ raise ValueError(f"Invalid permission type: {permission_type}. "
105
+ f"Must be one of: {', '.join(valid_permissions)}")
106
+
107
+ return permission
@@ -0,0 +1,11 @@
1
+ Copyright <YEAR> <COPYRIGHT HOLDER>
2
+
3
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4
+
5
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6
+
7
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8
+
9
+ 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10
+
11
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: adss
3
- Version: 0.1
3
+ Version: 1.1
4
4
  Summary: Astronomical Data Smart System
5
5
  Home-page: https://github.com/schwarzam/adss
6
6
  Author: Gustavo Schwarz
7
7
  Author-email: gustavo.b.schwarz@gmail.com
8
8
  Classifier: Programming Language :: Python :: 3
9
9
  Classifier: License :: OSI Approved :: Apache Software License
10
+ License-File: LICENSE
10
11
  Requires-Dist: requests
11
12
  Requires-Dist: astropy
12
- Requires-Dist: pyvo
13
13
 
@@ -0,0 +1,30 @@
1
+ adss/__init__.py,sha256=TqNjMZ7PuNXc-FnOlVKSNHSAp9ZqcLMdHDuRYt47_Y8,834
2
+ adss/adss_manager.py,sha256=vaS6y1IycVW8AjpAQeG58VwjCDLyMBUylJzYSeg6D9o,2068
3
+ adss/auth.py,sha256=Lx-9Kf_WnFmv5Rnh3q16bTdbcXCuf0_JyZ7jR68LA8k,4013
4
+ adss/client.py,sha256=mV3CYunp0X8zdapigqUw81taaHsBlzR3WY1TFbqco8o,29577
5
+ adss/exceptions.py,sha256=YeN-xRHvlSmwyS8ni2jOEhhgZK9J1jsG11pOedy3Gfg,1482
6
+ adss/table.py,sha256=Ua663njPk2sg8BtQPo1wZ-V09YvnjrEyIb_SmBhdOYY,13383
7
+ adss/utils.py,sha256=ecrGVabwo0RJlObkrM_F4pAyMfoVjbR9HNX3Z_IU5FA,3554
8
+ adss/variables.py,sha256=kmbwxJBDC97yKakrnBvONRh1FVvSXU4YKqnjExAU2ZA,51
9
+ adss/endpoints/__init__.py,sha256=Pr29901fT8ClCS2GasTjTiBNyn7DfVfxILpYDFsMvPA,488
10
+ adss/endpoints/admin.py,sha256=S6ZrkeA_Lh_LCpF1NHyfMKqjbIiylYXUSV65H_WKg1U,16391
11
+ adss/endpoints/images.py,sha256=yv_doU-rHIx8bnzYC8YGWkTy80u4DZdYcUGweNUZd-A,35771
12
+ adss/endpoints/metadata.py,sha256=67P-458Wjl6RVMk15_QZpvC-fdbI-8dDj6KHZQWB3zE,8232
13
+ adss/endpoints/queries.py,sha256=LJy1yyvHXGJrL9tXij0AOwgTiat6wXcs2ks268hOJg4,17277
14
+ adss/endpoints/users.py,sha256=OwC-rhW9tcFydsNC07ecgXiIDKR9ymks5XrJCwsFEac,10802
15
+ adss/executors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
+ adss/executors/async_query.py,sha256=qmSm-Ex8ZJSjn8lmm_F5BufVpDV-w6vOqXie7krCp7k,3977
17
+ adss/executors/sync_query.py,sha256=3e-ALG3GnA906o_oefci5XHNcdnoPWuc67ml-YATMKE,1243
18
+ adss/models/__init__.py,sha256=ADWVaGy4dkpEMH3iS_6EnRSBlEgoM5Vy9zORQr-UG6w,404
19
+ adss/models/metadata.py,sha256=6fdH_0BenVRmeXkkKbsG2B68O-N2FXTTRgxsEhAHRoU,4058
20
+ adss/models/query.py,sha256=fAM3qXb11tAYfKbFGBY85COFRjzaj7ubPebyjP7XwDs,4290
21
+ adss/models/user.py,sha256=03B_zxdo5gYfNQ4GlW55FFGW8QhyPQCZqi4KWlUm5dM,3490
22
+ adss/operations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
+ adss/operations/cone_search.py,sha256=qfdFA2TGqnzuggz4nep21_y4LgmHP4ZMpVupxn87dB0,706
24
+ adss/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
+ adss/utils/format_table.py,sha256=UYCQ6Xum3dPHrh0cAh_KCj6vHShAvdHlV0rtIv7J09Q,3695
26
+ adss-1.1.dist-info/LICENSE,sha256=1aYqcyqjrdNXY9hqgZkCWprcoA112oKvdrfPyvMYPTc,1468
27
+ adss-1.1.dist-info/METADATA,sha256=5QC0d6SaMmjdXj-oKnuxyCrfRX15H6JWt3SkgiFCL-4,378
28
+ adss-1.1.dist-info/WHEEL,sha256=Wyh-_nZ0DJYolHNn1_hMa4lM7uDedD_RGVwbmTjyItk,91
29
+ adss-1.1.dist-info/top_level.txt,sha256=ebD44L3R0PEvEFoRCJ-RjTIsQ9Yjpo2aAYC1BMtueLg,5
30
+ adss-1.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (72.1.0)
2
+ Generator: setuptools (71.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
adss-0.1.dist-info/RECORD DELETED
@@ -1,11 +0,0 @@
1
- adss/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- adss/variables.py,sha256=kmbwxJBDC97yKakrnBvONRh1FVvSXU4YKqnjExAU2ZA,51
3
- adss/executors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- adss/executors/async_query.py,sha256=2xVnnVp-0-dFR8GbDzG2be3dT2s8DpPN1ja59o4d_bM,3904
5
- adss/executors/sync_query.py,sha256=s-t95UtFCdkyBTpnrDgCrVS9wSFXdgIvtDLfNJ21BUA,974
6
- adss/operations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- adss/operations/cone_search.py,sha256=qfdFA2TGqnzuggz4nep21_y4LgmHP4ZMpVupxn87dB0,706
8
- adss-0.1.dist-info/METADATA,sha256=ilpdvMwhIRDpROZuVhtJTKueu5KvQEfMEQVUKpwQvv8,376
9
- adss-0.1.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
10
- adss-0.1.dist-info/top_level.txt,sha256=ebD44L3R0PEvEFoRCJ-RjTIsQ9Yjpo2aAYC1BMtueLg,5
11
- adss-0.1.dist-info/RECORD,,
File without changes