datacosmos 0.0.3__tar.gz → 0.0.4__tar.gz

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 (56) hide show
  1. {datacosmos-0.0.3/datacosmos.egg-info → datacosmos-0.0.4}/PKG-INFO +2 -1
  2. {datacosmos-0.0.3 → datacosmos-0.0.4}/README.md +164 -5
  3. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/collection/collection_client.py +6 -2
  4. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/collection/models/collection_update.py +1 -0
  5. datacosmos-0.0.4/datacosmos/stac/constants/__init__.py +1 -0
  6. datacosmos-0.0.4/datacosmos/stac/constants/satellite_name_mapping.py +20 -0
  7. datacosmos-0.0.4/datacosmos/stac/enums/processing_level.py +15 -0
  8. datacosmos-0.0.4/datacosmos/stac/enums/product_type.py +11 -0
  9. datacosmos-0.0.4/datacosmos/stac/enums/season.py +14 -0
  10. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/item/item_client.py +9 -3
  11. datacosmos-0.0.4/datacosmos/stac/item/models/catalog_search_parameters.py +132 -0
  12. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/item/models/datacosmos_item.py +3 -3
  13. {datacosmos-0.0.3 → datacosmos-0.0.4/datacosmos.egg-info}/PKG-INFO +2 -1
  14. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos.egg-info/SOURCES.txt +6 -1
  15. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos.egg-info/requires.txt +1 -0
  16. {datacosmos-0.0.3 → datacosmos-0.0.4}/pyproject.toml +3 -2
  17. datacosmos-0.0.3/datacosmos/stac/enums/level.py +0 -15
  18. {datacosmos-0.0.3 → datacosmos-0.0.4}/LICENSE.md +0 -0
  19. {datacosmos-0.0.3 → datacosmos-0.0.4}/config/__init__.py +0 -0
  20. {datacosmos-0.0.3 → datacosmos-0.0.4}/config/config.py +0 -0
  21. {datacosmos-0.0.3 → datacosmos-0.0.4}/config/models/__init__.py +0 -0
  22. {datacosmos-0.0.3 → datacosmos-0.0.4}/config/models/m2m_authentication_config.py +0 -0
  23. {datacosmos-0.0.3 → datacosmos-0.0.4}/config/models/url.py +0 -0
  24. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/__init__.py +0 -0
  25. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/datacosmos_client.py +0 -0
  26. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/exceptions/__init__.py +0 -0
  27. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/exceptions/datacosmos_exception.py +0 -0
  28. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/__init__.py +0 -0
  29. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/collection/__init__.py +0 -0
  30. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/collection/models/__init__.py +0 -0
  31. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/enums/__init__.py +0 -0
  32. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/item/__init__.py +0 -0
  33. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/item/models/__init__.py +0 -0
  34. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/item/models/asset.py +0 -0
  35. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/item/models/eo_band.py +0 -0
  36. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/item/models/item_update.py +0 -0
  37. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/item/models/raster_band.py +0 -0
  38. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/item/models/search_parameters.py +0 -0
  39. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/stac_client.py +0 -0
  40. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/uploader/__init__.py +0 -0
  41. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/uploader/dataclasses/__init__.py +0 -0
  42. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/uploader/dataclasses/upload_path.py +0 -0
  43. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/uploader/datacosmos_uploader.py +0 -0
  44. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/utils/__init__.py +0 -0
  45. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/utils/constants.py +0 -0
  46. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/utils/http_response/__init__.py +0 -0
  47. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/utils/http_response/check_api_response.py +0 -0
  48. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/utils/http_response/models/__init__.py +0 -0
  49. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/utils/http_response/models/datacosmos_error.py +0 -0
  50. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/utils/http_response/models/datacosmos_response.py +0 -0
  51. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/utils/missions.py +0 -0
  52. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/utils/url.py +0 -0
  53. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos.egg-info/dependency_links.txt +0 -0
  54. {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos.egg-info/top_level.txt +0 -0
  55. {datacosmos-0.0.3 → datacosmos-0.0.4}/setup.cfg +0 -0
  56. {datacosmos-0.0.3 → datacosmos-0.0.4}/tests/test_pass.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datacosmos
3
- Version: 0.0.3
3
+ Version: 0.0.4
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
@@ -13,6 +13,7 @@ Requires-Dist: oauthlib==3.2.0
13
13
  Requires-Dist: requests-oauthlib==1.3.1
14
14
  Requires-Dist: pydantic==2.10.6
15
15
  Requires-Dist: pystac==1.12.1
16
+ Requires-Dist: pyyaml==6.0.2
16
17
  Provides-Extra: dev
17
18
  Requires-Dist: black==22.3.0; extra == "dev"
18
19
  Requires-Dist: ruff==0.9.5; extra == "dev"
@@ -102,23 +102,165 @@ stac_client = STACClient(client)
102
102
 
103
103
  ### STACClient Methods
104
104
 
105
- #### 1. Fetch a Collection
105
+ #### 1. **Search Items**
106
+ ```python
107
+ from datacosmos.stac.item.models.catalog_search_parameters import CatalogSearchParameters
108
+ from datacosmos.datacosmos_client import DatacosmosClient
109
+ from datacosmos.stac.stac_client import STACClient
110
+
111
+ client = DatacosmosClient()
112
+ stac_client = STACClient(client)
113
+
114
+ params = CatalogSearchParameters(
115
+ start_date="2/9/2025",
116
+ end_date="2/9/2025",
117
+ satellite=["MANTIS"],
118
+ product_type=["Satellite"],
119
+ processing_level=["L1A"]
120
+ )
121
+
122
+ items = list(stac_client.search_items(parameters=params, project_id="your-project-id"))
123
+ ```
124
+
125
+ #### 2. **Fetch a Single Item**
126
+ ```python
127
+ from datacosmos.datacosmos_client import DatacosmosClient
128
+ from datacosmos.stac.stac_client import STACClient
129
+
130
+ client = DatacosmosClient()
131
+ stac_client = STACClient(client)
132
+
133
+ item = stac_client.fetch_item(item_id="example-item", collection_id="example-collection")
134
+ ```
135
+
136
+ #### 3. **Fetch All Items in a Collection**
137
+ ```python
138
+ from datacosmos.datacosmos_client import DatacosmosClient
139
+ from datacosmos.stac.stac_client import STACClient
140
+
141
+ client = DatacosmosClient()
142
+ stac_client = STACClient(client)
143
+
144
+ items = stac_client.fetch_collection_items(collection_id="example-collection")
145
+ ```
146
+
147
+ #### 4. **Create a New STAC Item**
148
+ ```python
149
+ from pystac import Item, Asset
150
+ from datetime import datetime
151
+
152
+ from datacosmos.datacosmos_client import DatacosmosClient
153
+ from datacosmos.stac.stac_client import STACClient
154
+
155
+ client = DatacosmosClient()
156
+ stac_client = STACClient(client)
157
+
158
+ stac_item = Item(
159
+ id="new-item",
160
+ geometry={"type": "Point", "coordinates": [102.0, 0.5]},
161
+ bbox=[101.0, 0.0, 103.0, 1.0],
162
+ datetime=datetime.utcnow(),
163
+ properties={},
164
+ collection="example-collection"
165
+ )
166
+
167
+ stac_item.add_asset(
168
+ "image",
169
+ Asset(
170
+ href="https://example.com/sample-image.tiff",
171
+ media_type="image/tiff",
172
+ roles=["data"],
173
+ title="Sample Image"
174
+ )
175
+ )
176
+
177
+ stac_client.create_item(collection_id="example-collection", item=stac_item)
178
+ ```
179
+
180
+ #### 5. **Update an Existing STAC Item**
181
+ ```python
182
+ from datacosmos.stac.models.item_update import ItemUpdate
183
+ from pystac import Asset, Link
184
+
185
+ from datacosmos.datacosmos_client import DatacosmosClient
186
+ from datacosmos.stac.stac_client import STACClient
187
+
188
+ client = DatacosmosClient()
189
+ stac_client = STACClient(client)
190
+
191
+ update_payload = ItemUpdate(
192
+ properties={
193
+ "new_property": "updated_value",
194
+ "datetime": "2024-11-10T14:58:00Z"
195
+ },
196
+ assets={
197
+ "image": Asset(
198
+ href="https://example.com/updated-image.tiff",
199
+ media_type="image/tiff"
200
+ )
201
+ },
202
+ links=[
203
+ Link(rel="self", target="https://example.com/updated-image.tiff")
204
+ ],
205
+ geometry={
206
+ "type": "Point",
207
+ "coordinates": [10, 20]
208
+ },
209
+ bbox=[10.0, 20.0, 30.0, 40.0]
210
+ )
106
211
 
212
+ stac_client.update_item(item_id="new-item", collection_id="example-collection", update_data=update_payload)
213
+ ```
214
+
215
+ #### 6. **Delete an Item**
107
216
  ```python
217
+
218
+ from datacosmos.datacosmos_client import DatacosmosClient
219
+ from datacosmos.stac.stac_client import STACClient
220
+
221
+ client = DatacosmosClient()
222
+ stac_client = STACClient(client)
223
+
224
+ stac_client.delete_item(item_id="new-item", collection_id="example-collection")
225
+ ```
226
+
227
+ #### 7. Fetch a Collection
228
+
229
+ ```python
230
+
231
+ from datacosmos.datacosmos_client import DatacosmosClient
232
+ from datacosmos.stac.stac_client import STACClient
233
+
234
+ client = DatacosmosClient()
235
+ stac_client = STACClient(client)
236
+
108
237
  collection = stac_client.fetch_collection("test-collection")
109
238
  ```
110
239
 
111
- #### 2. Fetch All Collections
240
+ #### 8. Fetch All Collections
112
241
 
113
242
  ```python
243
+
244
+ from datacosmos.datacosmos_client import DatacosmosClient
245
+ from datacosmos.stac.stac_client import STACClient
246
+
247
+ client = DatacosmosClient()
248
+ stac_client = STACClient(client)
249
+
114
250
  collections = list(stac_client.fetch_all_collections())
115
251
  ```
116
252
 
117
- #### 3. Create a Collection
253
+ #### 9. Create a Collection
118
254
 
119
255
  ```python
120
256
  from pystac import Collection
121
257
 
258
+ from datacosmos.datacosmos_client import DatacosmosClient
259
+ from datacosmos.stac.stac_client import STACClient
260
+
261
+ client = DatacosmosClient()
262
+ stac_client = STACClient(client)
263
+
122
264
  new_collection = Collection(
123
265
  id="test-collection",
124
266
  title="Test Collection",
@@ -133,11 +275,17 @@ new_collection = Collection(
133
275
  stac_client.create_collection(new_collection)
134
276
  ```
135
277
 
136
- #### 4. Update a Collection
278
+ #### 10. Update a Collection
137
279
 
138
280
  ```python
139
281
  from datacosmos.stac.collection.models.collection_update import CollectionUpdate
140
282
 
283
+ from datacosmos.datacosmos_client import DatacosmosClient
284
+ from datacosmos.stac.stac_client import STACClient
285
+
286
+ client = DatacosmosClient()
287
+ stac_client = STACClient(client)
288
+
141
289
  update_data = CollectionUpdate(
142
290
  title="Updated Collection Title",
143
291
  description="Updated description",
@@ -146,9 +294,16 @@ update_data = CollectionUpdate(
146
294
  stac_client.update_collection("test-collection", update_data)
147
295
  ```
148
296
 
149
- #### 5. Delete a Collection
297
+ #### 11. Delete a Collection
150
298
 
151
299
  ```python
300
+
301
+ from datacosmos.datacosmos_client import DatacosmosClient
302
+ from datacosmos.stac.stac_client import STACClient
303
+
304
+ client = DatacosmosClient()
305
+ stac_client = STACClient(client)
306
+
152
307
  stac_client.delete_collection("test-collection")
153
308
  ```
154
309
 
@@ -161,6 +316,10 @@ You can use the `DatacosmosUploader` class to upload files to the DataCosmos clo
161
316
  ```python
162
317
  from datacosmos.uploader.datacosmos_uploader import DatacosmosUploader
163
318
 
319
+ from datacosmos.datacosmos_client import DatacosmosClient
320
+
321
+ client = DatacosmosClient()
322
+
164
323
  uploader = DatacosmosUploader(client)
165
324
  item_json_file_path = "/path/to/stac_item.json"
166
325
  uploader.upload_and_register_item(item_json_file_path)
@@ -6,6 +6,7 @@ from pystac import Collection, Extent, SpatialExtent, TemporalExtent
6
6
  from pystac.utils import str_to_datetime
7
7
 
8
8
  from datacosmos.datacosmos_client import DatacosmosClient
9
+ from datacosmos.exceptions.datacosmos_exception import DatacosmosException
9
10
  from datacosmos.stac.collection.models.collection_update import CollectionUpdate
10
11
  from datacosmos.utils.http_response.check_api_response import check_api_response
11
12
 
@@ -145,5 +146,8 @@ class CollectionClient:
145
146
  """
146
147
  try:
147
148
  return next_href.split("?")[1].split("=")[-1]
148
- except (IndexError, AttributeError):
149
- raise InvalidRequest(f"Failed to parse pagination token from {next_href}")
149
+ except (IndexError, AttributeError) as e:
150
+ raise DatacosmosException(
151
+ f"Failed to parse pagination token from {next_href}",
152
+ response=e.response,
153
+ ) from e
@@ -2,6 +2,7 @@
2
2
 
3
3
  Allows partial updates where only the provided fields are modified.
4
4
  """
5
+
5
6
  from typing import Any, Dict, List, Optional
6
7
 
7
8
  from pydantic import BaseModel, Field
@@ -0,0 +1 @@
1
+ """Constants for STAC."""
@@ -0,0 +1,20 @@
1
+ """Satellite name mapping."""
2
+
3
+ SATELLITE_NAME_MAPPING = {
4
+ "GEOSAT-2": "2014-033D",
5
+ "SUPERVIEW-1-01": "2016-083A",
6
+ "SUPERVIEW-1-02": "2016-083B",
7
+ "SUPERVIEW-1-03": "2018-002A",
8
+ "SUPERVIEW-1-04": "2018-002B",
9
+ "MANTIS": "2023-174B",
10
+ "MENUT": "2023-001B",
11
+ "HAMMER": "2024-043BC",
12
+ "HAMMER-EM": "COSPAR-HAMMER-EM-TBD",
13
+ "Alisio": "2023-185M",
14
+ "Platero": "2023-174G",
15
+ "PHISAT-2": "2024-149C",
16
+ "PHISAT-2 EM": "COSPAR-PHISAT2-EM-TBD",
17
+ "Sentinel-2A": "2015-028A",
18
+ "Sentinel-2B": "2017-013A",
19
+ "Sentinel-2C": "2024-157A",
20
+ }
@@ -0,0 +1,15 @@
1
+ """Level enum class."""
2
+
3
+ from enum import Enum
4
+
5
+
6
+ class ProcessingLevel(Enum):
7
+ """Enum class for the processing levels of the data."""
8
+
9
+ L0 = "L0"
10
+ L1A = "L1A"
11
+ L2A = "L2A"
12
+ L1B = "L1B"
13
+ L1C = "L1C"
14
+ L1D = "L1D"
15
+ L3 = "L3"
@@ -0,0 +1,11 @@
1
+ """Product type enum class."""
2
+
3
+ from enum import Enum
4
+
5
+
6
+ class ProductType(str, Enum):
7
+ """Different product types."""
8
+
9
+ SATELLITE = "Satellite"
10
+ VECTOR = "Vector"
11
+ INSIGHT = "Insight"
@@ -0,0 +1,14 @@
1
+ """Season enum class."""
2
+
3
+ from enum import Enum
4
+
5
+
6
+ class Season(str, Enum):
7
+ """Different Open Cosmos seasons."""
8
+
9
+ SUMMER = "Summer"
10
+ WINTER = "Winter"
11
+ AUTUMN = "Autumn"
12
+ SPRING = "Spring"
13
+ RAINY = "Rainy"
14
+ DRY = "Dry"
@@ -9,6 +9,9 @@ from pystac import Item
9
9
 
10
10
  from datacosmos.datacosmos_client import DatacosmosClient
11
11
  from datacosmos.exceptions.datacosmos_exception import DatacosmosException
12
+ from datacosmos.stac.item.models.catalog_search_parameters import (
13
+ CatalogSearchParameters,
14
+ )
12
15
  from datacosmos.stac.item.models.datacosmos_item import DatacosmosItem
13
16
  from datacosmos.stac.item.models.item_update import ItemUpdate
14
17
  from datacosmos.stac.item.models.search_parameters import SearchParameters
@@ -59,17 +62,20 @@ class ItemClient:
59
62
 
60
63
  return self.search_items(parameters)
61
64
 
62
- def search_items(self, parameters: SearchParameters) -> Generator[Item, None, None]:
65
+ def search_items(
66
+ self, parameters: CatalogSearchParameters, project_id: str
67
+ ) -> Generator[Item, None, None]:
63
68
  """Query the STAC catalog using the POST endpoint with filtering and pagination.
64
69
 
65
70
  Args:
66
- parameters (SearchParameters): The search parameters.
71
+ parameters (CatalogSearchParameters): The search parameters.
67
72
 
68
73
  Yields:
69
74
  Item: Parsed STAC item.
70
75
  """
71
76
  url = self.base_url.with_suffix("/search")
72
- body = parameters.model_dump(by_alias=True, exclude_none=True)
77
+ parameters_query = parameters.to_query()
78
+ body = {"project": project_id, "limit": 50, "query": parameters_query}
73
79
  return self._paginate_items(url, body)
74
80
 
75
81
  def create_item(self, collection_id: str, item: Item | DatacosmosItem) -> None:
@@ -0,0 +1,132 @@
1
+ """Query parameters for catalog search."""
2
+
3
+ from datetime import datetime, timedelta
4
+ from typing import Any, List, Optional
5
+
6
+ from pydantic import BaseModel, field_validator, model_validator
7
+
8
+ from datacosmos.stac.constants.satellite_name_mapping import SATELLITE_NAME_MAPPING
9
+ from datacosmos.stac.enums.processing_level import ProcessingLevel
10
+ from datacosmos.stac.enums.product_type import ProductType
11
+ from datacosmos.stac.enums.season import Season
12
+
13
+
14
+ class CatalogSearchParameters(BaseModel):
15
+ """Query parameters for catalog search."""
16
+
17
+ start_date: Optional[str] = None
18
+ end_date: Optional[str] = None
19
+ seasons: Optional[List[Season]] = None
20
+ satellite: Optional[List[str]] = None
21
+ product_type: Optional[List[ProductType]] = None
22
+ processing_level: Optional[List[ProcessingLevel]] = None
23
+
24
+ # --- Field Validators ---
25
+
26
+ @field_validator("seasons", mode="before")
27
+ @classmethod
28
+ def parse_seasons(cls, value):
29
+ """Parses seasons values into a list of Season object."""
30
+ if value is None:
31
+ return None
32
+ return [Season(v) if not isinstance(v, Season) else v for v in value]
33
+
34
+ @field_validator("product_type", mode="before")
35
+ @classmethod
36
+ def parse_product_types(cls, value):
37
+ """Parses product types values into a list of ProductType object."""
38
+ if value is None:
39
+ return None
40
+ return [ProductType(v) if not isinstance(v, ProductType) else v for v in value]
41
+
42
+ @field_validator("processing_level", mode="before")
43
+ @classmethod
44
+ def parse_processing_levels(cls, value):
45
+ """Parses processing levels values into a list of ProcessingLevel object."""
46
+ if value is None:
47
+ return None
48
+ return [
49
+ ProcessingLevel(v) if not isinstance(v, ProcessingLevel) else v
50
+ for v in value
51
+ ]
52
+
53
+ @field_validator("start_date", mode="before")
54
+ @classmethod
55
+ def parse_start_date(cls, value: Any) -> Optional[str]:
56
+ """Validations on start_date."""
57
+ if value is None:
58
+ return None
59
+ try:
60
+ dt = datetime.strptime(value, "%m/%d/%Y")
61
+ if dt < datetime(2015, 5, 15):
62
+ raise ValueError("Date must be 5/15/2015 or later.")
63
+ return dt.isoformat() + "Z"
64
+ except ValueError:
65
+ raise ValueError(
66
+ "Invalid start_date format. Use mm/dd/yyyy (e.g., 05/15/2024)"
67
+ )
68
+
69
+ @field_validator("end_date", mode="before")
70
+ @classmethod
71
+ def parse_end_date(cls, value: Any) -> Optional[str]:
72
+ """Validations on end_date."""
73
+ if value is None:
74
+ return None
75
+ try:
76
+ dt = datetime.strptime(value, "%m/%d/%Y")
77
+ if dt < datetime(2015, 5, 15):
78
+ raise ValueError("Date must be 5/15/2015 or later.")
79
+ dt = dt + timedelta(days=1) - timedelta(milliseconds=1)
80
+ return dt.isoformat() + "Z"
81
+ except ValueError:
82
+ raise ValueError(
83
+ "Invalid end_date format. Use mm/dd/yyyy (e.g., 05/15/2024)"
84
+ )
85
+
86
+ # --- Model Validator ---
87
+
88
+ @model_validator(mode="after")
89
+ def validate_date_range(self) -> "CatalogSearchParameters":
90
+ """Checks if end_date is after the start_date."""
91
+ if self.start_date and self.end_date:
92
+ start_dt = datetime.fromisoformat(self.start_date.rstrip("Z"))
93
+ end_dt = datetime.fromisoformat(self.end_date.rstrip("Z"))
94
+ if start_dt > end_dt:
95
+ raise ValueError("end_date cannot be before start_date.")
96
+ return self
97
+
98
+ # --- Query Mapper ---
99
+
100
+ def to_query(self) -> dict:
101
+ """Map user-friendly input to STAC query structure."""
102
+ query = {}
103
+
104
+ if self.start_date or self.end_date:
105
+ query["datetime"] = {"gte": self.start_date, "lte": self.end_date}
106
+
107
+ if self.seasons:
108
+ query["opencosmos:season"] = {
109
+ "in": [seasons.value for seasons in self.seasons]
110
+ }
111
+
112
+ if self.product_type:
113
+ query["opencosmos:product_type"] = {
114
+ "in": [product_type.value for product_type in self.product_type]
115
+ }
116
+
117
+ if self.processing_level:
118
+ query["processing:level"] = {
119
+ "in": [
120
+ processing_level.value for processing_level in self.processing_level
121
+ ]
122
+ }
123
+
124
+ if self.satellite:
125
+ cospars = [
126
+ SATELLITE_NAME_MAPPING[ui]
127
+ for ui in self.satellite
128
+ if ui in SATELLITE_NAME_MAPPING
129
+ ]
130
+ query["sat:platform_international_designator"] = {"in": cospars}
131
+
132
+ return query
@@ -4,7 +4,7 @@ from datetime import datetime
4
4
 
5
5
  from pydantic import BaseModel
6
6
 
7
- from datacosmos.stac.enums.level import Level
7
+ from datacosmos.stac.enums.processing_level import ProcessingLevel
8
8
  from datacosmos.stac.item.models.asset import Asset
9
9
 
10
10
 
@@ -36,9 +36,9 @@ class DatacosmosItem(BaseModel):
36
36
  return datetime.strptime(self.properties["datetime"], "%Y-%m-%dT%H:%M:%SZ")
37
37
 
38
38
  @property
39
- def level(self) -> Level:
39
+ def level(self) -> ProcessingLevel:
40
40
  """Get the processing level of the Datacosmos item."""
41
- return Level(self.properties["processing:level"].lower())
41
+ return ProcessingLevel(self.properties["processing:level"].lower())
42
42
 
43
43
  @property
44
44
  def sat_int_designator(self) -> str:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datacosmos
3
- Version: 0.0.3
3
+ Version: 0.0.4
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
@@ -13,6 +13,7 @@ Requires-Dist: oauthlib==3.2.0
13
13
  Requires-Dist: requests-oauthlib==1.3.1
14
14
  Requires-Dist: pydantic==2.10.6
15
15
  Requires-Dist: pystac==1.12.1
16
+ Requires-Dist: pyyaml==6.0.2
16
17
  Provides-Extra: dev
17
18
  Requires-Dist: black==22.3.0; extra == "dev"
18
19
  Requires-Dist: ruff==0.9.5; extra == "dev"
@@ -21,12 +21,17 @@ datacosmos/stac/collection/__init__.py
21
21
  datacosmos/stac/collection/collection_client.py
22
22
  datacosmos/stac/collection/models/__init__.py
23
23
  datacosmos/stac/collection/models/collection_update.py
24
+ datacosmos/stac/constants/__init__.py
25
+ datacosmos/stac/constants/satellite_name_mapping.py
24
26
  datacosmos/stac/enums/__init__.py
25
- datacosmos/stac/enums/level.py
27
+ datacosmos/stac/enums/processing_level.py
28
+ datacosmos/stac/enums/product_type.py
29
+ datacosmos/stac/enums/season.py
26
30
  datacosmos/stac/item/__init__.py
27
31
  datacosmos/stac/item/item_client.py
28
32
  datacosmos/stac/item/models/__init__.py
29
33
  datacosmos/stac/item/models/asset.py
34
+ datacosmos/stac/item/models/catalog_search_parameters.py
30
35
  datacosmos/stac/item/models/datacosmos_item.py
31
36
  datacosmos/stac/item/models/eo_band.py
32
37
  datacosmos/stac/item/models/item_update.py
@@ -4,6 +4,7 @@ oauthlib==3.2.0
4
4
  requests-oauthlib==1.3.1
5
5
  pydantic==2.10.6
6
6
  pystac==1.12.1
7
+ pyyaml==6.0.2
7
8
 
8
9
  [dev]
9
10
  black==22.3.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "datacosmos"
7
- version = "0.0.3"
7
+ version = "0.0.4"
8
8
  authors = [
9
9
  { name="Open Cosmos", email="support@open-cosmos.com" },
10
10
  ]
@@ -20,7 +20,8 @@ dependencies = [
20
20
  "oauthlib==3.2.0",
21
21
  "requests-oauthlib==1.3.1",
22
22
  "pydantic==2.10.6",
23
- "pystac==1.12.1"
23
+ "pystac==1.12.1",
24
+ "pyyaml==6.0.2"
24
25
  ]
25
26
 
26
27
  [project.optional-dependencies]
@@ -1,15 +0,0 @@
1
- """Level enum class."""
2
-
3
- from enum import Enum
4
-
5
-
6
- class Level(Enum):
7
- """Enum class for the processing levels of the data."""
8
-
9
- L0 = "l0"
10
- L1A = "l1a"
11
- L2A = "l2a"
12
- L1B = "l1b"
13
- L1C = "l1c"
14
- L1D = "l1d"
15
- L3 = "l3"
File without changes
File without changes
File without changes