datacosmos 0.0.1__py3-none-any.whl → 0.0.3__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.

Potentially problematic release.


This version of datacosmos might be problematic. Click here for more details.

Files changed (43) hide show
  1. config/__init__.py +5 -0
  2. config/config.py +195 -0
  3. config/models/__init__.py +1 -0
  4. config/models/m2m_authentication_config.py +23 -0
  5. config/models/url.py +35 -0
  6. datacosmos/exceptions/__init__.py +1 -0
  7. datacosmos/exceptions/datacosmos_exception.py +27 -0
  8. datacosmos/stac/__init__.py +5 -0
  9. datacosmos/stac/collection/__init__.py +4 -0
  10. datacosmos/stac/collection/collection_client.py +149 -0
  11. datacosmos/stac/collection/models/__init__.py +1 -0
  12. datacosmos/stac/collection/models/collection_update.py +46 -0
  13. datacosmos/stac/enums/__init__.py +1 -0
  14. datacosmos/stac/enums/level.py +15 -0
  15. datacosmos/stac/item/__init__.py +4 -0
  16. datacosmos/stac/item/item_client.py +186 -0
  17. datacosmos/stac/item/models/__init__.py +1 -0
  18. datacosmos/stac/item/models/asset.py +23 -0
  19. datacosmos/stac/item/models/datacosmos_item.py +55 -0
  20. datacosmos/stac/item/models/eo_band.py +15 -0
  21. datacosmos/stac/item/models/item_update.py +57 -0
  22. datacosmos/stac/item/models/raster_band.py +17 -0
  23. datacosmos/stac/item/models/search_parameters.py +58 -0
  24. datacosmos/stac/stac_client.py +12 -0
  25. datacosmos/uploader/__init__.py +1 -0
  26. datacosmos/uploader/dataclasses/__init__.py +1 -0
  27. datacosmos/uploader/dataclasses/upload_path.py +93 -0
  28. datacosmos/uploader/datacosmos_uploader.py +106 -0
  29. datacosmos/utils/__init__.py +1 -0
  30. datacosmos/utils/constants.py +16 -0
  31. datacosmos/utils/http_response/__init__.py +1 -0
  32. datacosmos/utils/http_response/check_api_response.py +34 -0
  33. datacosmos/utils/http_response/models/__init__.py +1 -0
  34. datacosmos/utils/http_response/models/datacosmos_error.py +26 -0
  35. datacosmos/utils/http_response/models/datacosmos_response.py +11 -0
  36. datacosmos/utils/missions.py +27 -0
  37. datacosmos/utils/url.py +60 -0
  38. {datacosmos-0.0.1.dist-info → datacosmos-0.0.3.dist-info}/METADATA +3 -2
  39. datacosmos-0.0.3.dist-info/RECORD +44 -0
  40. {datacosmos-0.0.1.dist-info → datacosmos-0.0.3.dist-info}/WHEEL +1 -1
  41. {datacosmos-0.0.1.dist-info → datacosmos-0.0.3.dist-info}/top_level.txt +1 -0
  42. datacosmos-0.0.1.dist-info/RECORD +0 -7
  43. {datacosmos-0.0.1.dist-info → datacosmos-0.0.3.dist-info/licenses}/LICENSE.md +0 -0
@@ -0,0 +1,34 @@
1
+ """Validates an API response and raises a DatacosmosException if an error occurs."""
2
+
3
+ from pydantic import ValidationError
4
+ from requests import Response
5
+
6
+ from datacosmos.exceptions.datacosmos_exception import DatacosmosException
7
+ from datacosmos.utils.http_response.models.datacosmos_response import DatacosmosResponse
8
+
9
+
10
+ def check_api_response(response: Response) -> None:
11
+ """Validates an API response and raises a DatacosmosException if an error occurs.
12
+
13
+ Args:
14
+ resp (requests.Response): The response object.
15
+
16
+ Raises:
17
+ DatacosmosException: If the response status code indicates an error.
18
+ """
19
+ if 200 <= response.status_code < 400:
20
+ return
21
+
22
+ try:
23
+ response = DatacosmosResponse.model_validate_json(response.text)
24
+ msg = response.errors[0].human_readable()
25
+ if len(response.errors) > 1:
26
+ msg = "\n * " + "\n * ".join(
27
+ error.human_readable() for error in response.errors
28
+ )
29
+ raise DatacosmosException(msg, response=response)
30
+
31
+ except ValidationError:
32
+ raise DatacosmosException(
33
+ f"HTTP {response.status_code}: {response.text}", response=response
34
+ )
@@ -0,0 +1 @@
1
+ """Models for validation of API response."""
@@ -0,0 +1,26 @@
1
+ """Structured API error message for Datacosmos."""
2
+
3
+ from pydantic import BaseModel
4
+
5
+
6
+ class DatacosmosError(BaseModel):
7
+ """Structured API error message for Datacosmos."""
8
+
9
+ message: str
10
+ field: str | None = None
11
+ type: str | None = None
12
+ source: str | None = None
13
+ trace_id: str | None = None
14
+
15
+ def human_readable(self) -> str:
16
+ """Formats the error message into a readable format."""
17
+ msg = self.message
18
+ if self.type:
19
+ msg += f" (type: {self.type})"
20
+ if self.field:
21
+ msg += f" (field: {self.field})"
22
+ if self.source:
23
+ msg += f" (source: {self.source})"
24
+ if self.trace_id:
25
+ msg += f" (trace_id: {self.trace_id})"
26
+ return msg
@@ -0,0 +1,11 @@
1
+ """Structured response for Datacosmos handling multiple API errors."""
2
+
3
+ from pydantic import BaseModel
4
+
5
+ from datacosmos.utils.http_response.models.datacosmos_error import DatacosmosError
6
+
7
+
8
+ class DatacosmosResponse(BaseModel):
9
+ """Structured response for Datacosmos handling multiple API errors."""
10
+
11
+ errors: list[DatacosmosError]
@@ -0,0 +1,27 @@
1
+ """Package for storing mission specific information."""
2
+
3
+ from datacosmos.utils.constants import PROD_MISSION_NAMES, TEST_MISSION_NAMES
4
+
5
+
6
+ def get_mission_name(mission: int, env: str) -> str:
7
+ """Get the mission name from the mission number."""
8
+ if env == "test" or env == "local":
9
+ return TEST_MISSION_NAMES[mission]
10
+ elif env == "prod":
11
+ return PROD_MISSION_NAMES[mission]
12
+ else:
13
+ raise ValueError(f"Unsupported environment: {env}")
14
+
15
+
16
+ def get_mission_id(mission_name: str, env: str) -> int:
17
+ """Get the mission number from the mission name."""
18
+ if env == "test" or env == "local":
19
+ return {v.upper(): k for k, v in TEST_MISSION_NAMES.items()}[
20
+ mission_name.upper()
21
+ ]
22
+ elif env == "prod":
23
+ return {v.upper(): k for k, v in PROD_MISSION_NAMES.items()}[
24
+ mission_name.upper()
25
+ ]
26
+ else:
27
+ raise ValueError(f"Unsupported environment: {env}")
@@ -0,0 +1,60 @@
1
+ """URL utility class for building and handling URLs in the SDK."""
2
+
3
+
4
+ class URL:
5
+ """Class to represent and build URLs in a convenient way."""
6
+
7
+ def __init__(self, protocol: str, host: str, port: int, base: str):
8
+ """Creates a new basis to build URLs.
9
+
10
+ Args:
11
+ protocol (str): Protocol to use in the URL (http/https).
12
+ host (str): Hostname (e.g., example.com).
13
+ port (int): Port number.
14
+ base (str): Base path (e.g., /api/v1).
15
+ """
16
+ self.protocol = protocol
17
+ self.host = host
18
+ self.port = port
19
+ self.base = base
20
+
21
+ def string(self) -> str:
22
+ """Returns the full URL as a string."""
23
+ port = "" if self.port in [80, 443] else f":{self.port}"
24
+ base = f"/{self.base.lstrip('/')}" if self.base else ""
25
+ return f"{self.protocol}://{self.host}{port}{base}"
26
+
27
+ def with_suffix(self, suffix: str) -> str:
28
+ """Appends a suffix to the URL, ensuring proper formatting.
29
+
30
+ Args:
31
+ suffix (str): The path to append.
32
+
33
+ Returns:
34
+ str: Full URL with the suffix.
35
+ """
36
+ base = self.string()
37
+ return f"{base.rstrip('/')}/{suffix.lstrip('/')}"
38
+
39
+ def with_base(self, url: str) -> str:
40
+ """Replaces the base of the url with the base stored in the URL object. (migrates url from one base to another).
41
+
42
+ Args:
43
+ url (str): url to migrate to the base of the URL object
44
+
45
+ Returns (str):
46
+ url with the base of the URL object
47
+ """
48
+ split_url = url.split("/")
49
+ if len(split_url) < 3 or url.find("://") == -1:
50
+ raise ValueError(f"URL '{url}' does not meet the minimum requirements")
51
+ # get the whole path
52
+ url_path = "/".join(split_url[3:])
53
+ # simple case, matching self.base at url
54
+ b = self.base.lstrip("/")
55
+ if (base_pos := url_path.find(b)) != -1:
56
+ # remove the base from the url
57
+ url_suffix = url_path[len(b) + base_pos :]
58
+ else:
59
+ url_suffix = url_path
60
+ return self.with_suffix(url_suffix)
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: datacosmos
3
- Version: 0.0.1
3
+ Version: 0.0.3
4
4
  Summary: A library for interacting with DataCosmos from Python code
5
5
  Author-email: Open Cosmos <support@open-cosmos.com>
6
6
  Classifier: Programming Language :: Python :: 3
@@ -20,3 +20,4 @@ Requires-Dist: pytest==7.2.0; extra == "dev"
20
20
  Requires-Dist: bandit[toml]==1.7.4; extra == "dev"
21
21
  Requires-Dist: isort==5.11.4; extra == "dev"
22
22
  Requires-Dist: pydocstyle==6.1.1; extra == "dev"
23
+ Dynamic: license-file
@@ -0,0 +1,44 @@
1
+ config/__init__.py,sha256=KCsaTb9-ZgFui1GM8wZFIPLJy0D0O8l8Z1Sv3NRD9UM,140
2
+ config/config.py,sha256=h5XwNSA6QFBCDyennyFDNMAmbQOdtg8DsFAvjHlSEx4,7233
3
+ config/models/__init__.py,sha256=r3lThPkyKjBjUZXRNscFzOrmn_-m_i9DvG3RePfCFYc,41
4
+ config/models/m2m_authentication_config.py,sha256=1eJ_9df7Twn5WeWPbqMuR63ZdxhnTpBtKzqAPMnzP_k,565
5
+ config/models/url.py,sha256=fwr2C06e_RDS8AWxOV_orVxMWhc57bzYoWSjFxQbkwg,835
6
+ datacosmos/__init__.py,sha256=dVHKpbz5FVtfoJAWHRdsUENG6H-vs4UrkuwnIvOGJr4,66
7
+ datacosmos/datacosmos_client.py,sha256=sivVYf45QEHTkUO62fnb1fnObKVmUngTR1Ga-ZRnoQE,4967
8
+ datacosmos/exceptions/__init__.py,sha256=Crz8W7mOvPUXYcfDVotvjUt_3HKawBpmJA_-uel9UJk,45
9
+ datacosmos/exceptions/datacosmos_exception.py,sha256=rKjJvQDvCEbxXWWccxB5GI_sth662bW8Yml0hX-vRw4,923
10
+ datacosmos/stac/__init__.py,sha256=B4x_Mr4X7TzQoYtRC-VzI4W-fEON5WUOaz8cWJbk3Fc,214
11
+ datacosmos/stac/stac_client.py,sha256=Cz_p96RmAgWX8t7Sye4OJRanQpCLihKStvfEw7IgYZc,472
12
+ datacosmos/stac/collection/__init__.py,sha256=VQMLnsU3sER5kh4YxHrHP7XCA3DG1y0n9yoSmvycOY0,212
13
+ datacosmos/stac/collection/collection_client.py,sha256=XTO2s309-cktJosvnwnFFXHDVmJc4vjvbEsZjpsCDmY,5904
14
+ datacosmos/stac/collection/models/__init__.py,sha256=TQaihUS_CM9Eaekm4SbzFTNfv7BmabHv3Z-f37Py5Qs,40
15
+ datacosmos/stac/collection/models/collection_update.py,sha256=Tqmfg4H4UQj5jsgy1dpKJCR59NSfWeiCSi9y8CY8-Cg,1656
16
+ datacosmos/stac/enums/__init__.py,sha256=GUEL2xGtdjsrszrxivs0X6daxkaZs2JsTu2JoBtsvB4,22
17
+ datacosmos/stac/enums/level.py,sha256=dqrkSRtoutMTWatGyRRUz3uNKVlNXn3qa_ubXNbw618,237
18
+ datacosmos/stac/item/__init__.py,sha256=lRuD_yp-JxoLqBA23q0XMkCNImf4T-X3BJnSw9u_3Yk,200
19
+ datacosmos/stac/item/item_client.py,sha256=E6zHf3ANzVXd5Di_u05mLen5-EOKTdCs0VKcXXJ6lUc,6826
20
+ datacosmos/stac/item/models/__init__.py,sha256=bcOrOcIxGxGBrRVIyQVxSM3C3Xj_qzxIHgQeWo6f7Q8,34
21
+ datacosmos/stac/item/models/asset.py,sha256=mvg_fenYCGOTMGwXXpK2nyqBk5RMsUYxl6KhQTWW_b0,631
22
+ datacosmos/stac/item/models/datacosmos_item.py,sha256=jHuOkNvbVXUHdpplClPnA5mR4mcrfYQNm51EgQaVtNk,1704
23
+ datacosmos/stac/item/models/eo_band.py,sha256=YC3Scn_wFhIo51pIVcJeuJienF7JGWoEv39JngDM6rI,309
24
+ datacosmos/stac/item/models/item_update.py,sha256=_CpjQn9SsfedfuxlHSiGeptqY4M-p15t9YX__mBRueI,2088
25
+ datacosmos/stac/item/models/raster_band.py,sha256=CoEVs-YyPE5Fse0He9DdOs4dGZpzfCsCuVzOcdXa_UM,354
26
+ datacosmos/stac/item/models/search_parameters.py,sha256=yMmcb-Tr2as8585MD5wuZLWcqzwtRRkj07WBkootVS0,2022
27
+ datacosmos/uploader/__init__.py,sha256=ZtfCVJ_pWKKh2F1r_NArnbG3_JtpcEiXcA_tmSwSKmQ,128
28
+ datacosmos/uploader/datacosmos_uploader.py,sha256=LUtBDvAjZI7AYxKnC9TZQDP4z6lV2aHusz92XqivFGw,4398
29
+ datacosmos/uploader/dataclasses/__init__.py,sha256=IjcyA8Vod-z1_Gi1FMZhK58Owman0foL25Hs0YtkYYs,43
30
+ datacosmos/uploader/dataclasses/upload_path.py,sha256=WPl9u-oB-ti07ssKNDjL4vRQXhlOmLCgjt8MxFGrf3A,3153
31
+ datacosmos/utils/__init__.py,sha256=XQbAnoqJrPpnSpEzAbjh84yqYWw8cBM8mNp8ynTG-54,50
32
+ datacosmos/utils/constants.py,sha256=f7pOqCpdXk7WFGoaTyuCpr65jb-TtfhoVGuYTz3_T6Y,272
33
+ datacosmos/utils/missions.py,sha256=7GOnrjxB8V11C_Jr3HHI4vpXifgkOSeirNjIDx17C58,940
34
+ datacosmos/utils/url.py,sha256=iQwZr6mYRoePqUZg-k3KQSV9o2wju5ZuCa5WS_GyJo4,2114
35
+ datacosmos/utils/http_response/__init__.py,sha256=BvOWwC5coYqq_kFn8gIw5m54TLpdfJKlW9vgRkfhXiA,33
36
+ datacosmos/utils/http_response/check_api_response.py,sha256=dKWW01jn2_lWV0xpOBABhEP42CFSsx9dP0iSxykbN54,1186
37
+ datacosmos/utils/http_response/models/__init__.py,sha256=Wj8YT6dqw7rAz_rctllxo5Or_vv8DwopvQvBzwCTvpw,45
38
+ datacosmos/utils/http_response/models/datacosmos_error.py,sha256=Uqi2uM98nJPeCbM7zngV6vHSk97jEAb_nkdDEeUjiQM,740
39
+ datacosmos/utils/http_response/models/datacosmos_response.py,sha256=oV4n-sue7K1wwiIQeHpxdNU8vxeqF3okVPE2rydw5W0,336
40
+ datacosmos-0.0.3.dist-info/licenses/LICENSE.md,sha256=vpbRI-UUbZVQfr3VG_CXt9HpRnL1b5kt8uTVbirxeyI,1486
41
+ datacosmos-0.0.3.dist-info/METADATA,sha256=ejuFFFnmdaInVXwXQtO6m35BQdTyotYYMLDVT-oWec4,843
42
+ datacosmos-0.0.3.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
43
+ datacosmos-0.0.3.dist-info/top_level.txt,sha256=Iu5b533Fmdfz0rFKTnuBPjSUOQL2lEkTfHxsokP72s4,18
44
+ datacosmos-0.0.3.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.8.0)
2
+ Generator: setuptools (78.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,7 +0,0 @@
1
- datacosmos/__init__.py,sha256=dVHKpbz5FVtfoJAWHRdsUENG6H-vs4UrkuwnIvOGJr4,66
2
- datacosmos/datacosmos_client.py,sha256=sivVYf45QEHTkUO62fnb1fnObKVmUngTR1Ga-ZRnoQE,4967
3
- datacosmos-0.0.1.dist-info/LICENSE.md,sha256=vpbRI-UUbZVQfr3VG_CXt9HpRnL1b5kt8uTVbirxeyI,1486
4
- datacosmos-0.0.1.dist-info/METADATA,sha256=N8KMHCWaO8ED0OYT0hUikP31GgD1fB6SDpFuNAhL924,821
5
- datacosmos-0.0.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
6
- datacosmos-0.0.1.dist-info/top_level.txt,sha256=ueobs5CNeyDbPMgXPcVV0d0yNdm8CvGtDT3CaksRVtA,11
7
- datacosmos-0.0.1.dist-info/RECORD,,