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.
- {datacosmos-0.0.3/datacosmos.egg-info → datacosmos-0.0.4}/PKG-INFO +2 -1
- {datacosmos-0.0.3 → datacosmos-0.0.4}/README.md +164 -5
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/collection/collection_client.py +6 -2
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/collection/models/collection_update.py +1 -0
- datacosmos-0.0.4/datacosmos/stac/constants/__init__.py +1 -0
- datacosmos-0.0.4/datacosmos/stac/constants/satellite_name_mapping.py +20 -0
- datacosmos-0.0.4/datacosmos/stac/enums/processing_level.py +15 -0
- datacosmos-0.0.4/datacosmos/stac/enums/product_type.py +11 -0
- datacosmos-0.0.4/datacosmos/stac/enums/season.py +14 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/item/item_client.py +9 -3
- datacosmos-0.0.4/datacosmos/stac/item/models/catalog_search_parameters.py +132 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/item/models/datacosmos_item.py +3 -3
- {datacosmos-0.0.3 → datacosmos-0.0.4/datacosmos.egg-info}/PKG-INFO +2 -1
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos.egg-info/SOURCES.txt +6 -1
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos.egg-info/requires.txt +1 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/pyproject.toml +3 -2
- datacosmos-0.0.3/datacosmos/stac/enums/level.py +0 -15
- {datacosmos-0.0.3 → datacosmos-0.0.4}/LICENSE.md +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/config/__init__.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/config/config.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/config/models/__init__.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/config/models/m2m_authentication_config.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/config/models/url.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/__init__.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/datacosmos_client.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/exceptions/__init__.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/exceptions/datacosmos_exception.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/__init__.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/collection/__init__.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/collection/models/__init__.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/enums/__init__.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/item/__init__.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/item/models/__init__.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/item/models/asset.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/item/models/eo_band.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/item/models/item_update.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/item/models/raster_band.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/item/models/search_parameters.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/stac/stac_client.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/uploader/__init__.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/uploader/dataclasses/__init__.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/uploader/dataclasses/upload_path.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/uploader/datacosmos_uploader.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/utils/__init__.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/utils/constants.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/utils/http_response/__init__.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/utils/http_response/check_api_response.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/utils/http_response/models/__init__.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/utils/http_response/models/datacosmos_error.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/utils/http_response/models/datacosmos_response.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/utils/missions.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/utils/url.py +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos.egg-info/dependency_links.txt +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos.egg-info/top_level.txt +0 -0
- {datacosmos-0.0.3 → datacosmos-0.0.4}/setup.cfg +0 -0
- {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
|
+
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.
|
|
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
|
-
####
|
|
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
|
-
####
|
|
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
|
-
####
|
|
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
|
-
####
|
|
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
|
|
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
|
|
@@ -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
|
+
}
|
|
@@ -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(
|
|
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 (
|
|
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
|
-
|
|
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.
|
|
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) ->
|
|
39
|
+
def level(self) -> ProcessingLevel:
|
|
40
40
|
"""Get the processing level of the Datacosmos item."""
|
|
41
|
-
return
|
|
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
|
+
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/
|
|
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,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "datacosmos"
|
|
7
|
-
version = "0.0.
|
|
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]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/utils/http_response/models/datacosmos_error.py
RENAMED
|
File without changes
|
{datacosmos-0.0.3 → datacosmos-0.0.4}/datacosmos/utils/http_response/models/datacosmos_response.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|