sentinelhub 3.11.1__py3-none-any.whl → 3.11.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.
@@ -1,6 +1,6 @@
1
1
  """
2
2
  Module implementing an interface with
3
- `Sentinel Hub Batch Processing API <https://docs.sentinel-hub.com/api/latest/api/batch/>`__.
3
+ `Batch Process V2 <https://docs.sentinel-hub.com/api/latest/api/batchv2/>`__.
4
4
  """
5
5
 
6
6
  # ruff: noqa: FA100
@@ -8,80 +8,73 @@ Module implementing an interface with
8
8
  import datetime as dt
9
9
  import logging
10
10
  from dataclasses import dataclass, field
11
- from enum import Enum
12
- from typing import Any, Dict, Iterator, List, Optional, Tuple, Union
11
+ from typing import Any, Dict, Iterator, Optional, Union
13
12
 
14
13
  from dataclasses_json import CatchAll, LetterCase, Undefined, dataclass_json
15
14
  from dataclasses_json import config as dataclass_config
15
+ from typing_extensions import Literal
16
16
 
17
17
  from ...constants import RequestType
18
- from ...data_collections import DataCollection
19
- from ...geometry import CRS, BBox, Geometry
20
18
  from ...types import Json, JsonDict
21
- from ..base import BaseCollection, SentinelHubFeatureIterator
19
+ from ..base import SentinelHubFeatureIterator
22
20
  from ..process import SentinelHubRequest
23
- from ..utils import datetime_config, enum_config, remove_undefined
24
- from .base import BaseBatchClient, BaseBatchRequest, BatchRequestStatus, BatchUserAction
21
+ from ..utils import AccessSpecification, datetime_config, enum_config, remove_undefined, s3_specification
22
+ from .base import BaseBatchClient, BaseBatchRequest, BatchRequestStatus, BatchUserAction, StoppedStatusReason
25
23
 
26
24
  LOGGER = logging.getLogger(__name__)
27
25
 
28
- BatchRequestType = Union[str, dict, "BatchRequest"]
29
- BatchCollectionType = Union[str, dict, "BatchCollection"]
26
+ BatchRequestType = Union[str, dict, "BatchProcessRequest"]
30
27
 
31
28
 
32
- class BatchTileStatus(Enum):
33
- """An enum class with all possible batch tile statuses"""
29
+ class BatchProcessClient(BaseBatchClient):
30
+ """An interface class for Sentinel Hub Batch API version 2.
34
31
 
35
- PENDING = "PENDING"
36
- SCHEDULED = "SCHEDULED"
37
- QUEUED = "QUEUED"
38
- PROCESSING = "PROCESSING"
39
- PROCESSED = "PROCESSED"
40
- FAILED = "FAILED"
41
-
42
-
43
- class SentinelHubBatch(BaseBatchClient):
44
- """An interface class for Sentinel Hub Batch API
45
-
46
- For more info check `Batch API reference <https://docs.sentinel-hub.com/api/latest/reference/#tag/batch_process>`__.
32
+ `Batch Process API <https://docs.sentinel-hub.com/api/latest/api/batchv2/>`__
47
33
  """
48
34
 
35
+ s3_specification = staticmethod(s3_specification)
36
+
49
37
  # pylint: disable=too-many-public-methods
50
38
  @staticmethod
51
39
  def _get_service_url(base_url: str) -> str:
52
40
  """Provides URL to Catalog API"""
53
- return f"{base_url}/api/v1/batch"
41
+ return f"{base_url}/api/v2/batch"
42
+
43
+ def _get_processing_url(self, request_id: Optional[str] = None) -> str:
44
+ """Creates a URL for process endpoint"""
45
+ url = f"{self.service_url}/process"
46
+ if request_id is None:
47
+ return url
48
+ return f"{url}/{request_id}"
54
49
 
55
50
  def create(
56
51
  self,
57
- sentinelhub_request: Union[SentinelHubRequest, JsonDict],
58
- tiling_grid: Dict[str, Any],
59
- output: Optional[Dict[str, Any]] = None,
60
- bucket_name: Optional[str] = None,
52
+ process_request: Union[SentinelHubRequest, JsonDict],
53
+ input: Dict[str, Any], # noqa: A002 #pylint: disable=redefined-builtin
54
+ output: Dict[str, Any],
55
+ instance_type: Literal["normal", "large"] = "normal",
61
56
  description: Optional[str] = None,
62
57
  **kwargs: Any,
63
- ) -> "BatchRequest":
58
+ ) -> "BatchProcessRequest":
64
59
  """Create a new batch request
65
60
 
66
- `Batch API reference
67
- <https://docs.sentinel-hub.com/api/latest/reference/#operation/createNewBatchProcessingRequest>`__
61
+ `Batch Process V2 <https://docs.sentinel-hub.com/api/latest/api/batchv2/>`__
68
62
 
69
- :param sentinelhub_request: An instance of SentinelHubRequest class containing all request parameters.
63
+ :param process_request: An instance of SentinelHubRequest class containing all request parameters.
70
64
  Alternatively, it can also be just a payload dictionary for Process API request
71
- :param tiling_grid: A dictionary with tiling grid parameters. It can be built with `tiling_grid` method
72
- :param output: A dictionary with output parameters. It can be built with `output` method. Alternatively, one
73
- can set `bucket_name` parameter instead.
74
- :param bucket_name: A name of an S3 bucket where to save data. Alternatively, one can set `output` parameter
75
- to specify more output parameters.
65
+ :param input: A dictionary with input parameters. It can be built with `tiling_grid_input` or `geopackage_input`
66
+ methods.
67
+ :param output: A dictionary with output parameters. It can be built with `raster_output` or `zarr_output`
68
+ methods.
69
+ :param instance_type": Specifies which size of instances to use for the request.
76
70
  :param description: A description of a batch request
77
71
  :param kwargs: Any other arguments to be added to a dictionary of parameters.
78
- :return: An instance of `SentinelHubBatch` object that represents a newly created batch request.
79
72
  """
80
73
 
81
- if isinstance(sentinelhub_request, SentinelHubRequest):
82
- request_dict = sentinelhub_request.download_list[0].post_values
74
+ if isinstance(process_request, SentinelHubRequest):
75
+ request_dict = process_request.download_list[0].post_values
83
76
  else:
84
- request_dict = sentinelhub_request
77
+ request_dict = process_request
85
78
 
86
79
  if not isinstance(request_dict, dict):
87
80
  raise ValueError(
@@ -89,116 +82,133 @@ class SentinelHubBatch(BaseBatchClient):
89
82
  "dictionary with a request payload"
90
83
  )
91
84
 
92
- payload = {
93
- "processRequest": request_dict,
94
- "tilingGrid": tiling_grid,
95
- "output": output,
96
- "bucketName": bucket_name,
97
- "description": description,
98
- **kwargs,
99
- }
100
- payload = remove_undefined(payload)
85
+ payload = remove_undefined(
86
+ {
87
+ "processRequest": request_dict,
88
+ "input": input,
89
+ "output": output,
90
+ "instance_type": instance_type,
91
+ "description": description,
92
+ **kwargs,
93
+ }
94
+ )
95
+
96
+ request_info = self.client.get_json_dict(self._get_processing_url(), post_values=payload, use_session=True)
101
97
 
102
- url = self._get_processing_url()
103
- request_info = self.client.get_json_dict(url, post_values=payload, use_session=True)
98
+ return BatchProcessRequest.from_dict(request_info)
104
99
 
105
- return BatchRequest.from_dict(request_info)
100
+ @staticmethod
101
+ def geopackage_input(geopackage_specification: AccessSpecification) -> JsonDict:
102
+ """A helper method to build a suitable dictionary for the `input` field.
103
+
104
+ :param geopackage_specification: A specification of the S3 path for the Geopackage. Can be built using the
105
+ `s3_specification` helper method.
106
+ """
107
+ return {"type": "geopackage", "features": geopackage_specification}
106
108
 
107
109
  @staticmethod
108
- def tiling_grid(
109
- grid_id: int, resolution: float, buffer: Optional[Tuple[int, int]] = None, **kwargs: Any
110
+ def tiling_grid_input(
111
+ grid_id: int, resolution: float, buffer_x: Optional[int] = None, buffer_y: Optional[int] = None, **kwargs: Any
110
112
  ) -> JsonDict:
111
- """A helper method to build a dictionary with tiling grid parameters
113
+ """A helper method to build a dictionary with tiling grid parameters for the `input` field.
112
114
 
113
115
  :param grid_id: An ID of a tiling grid
114
116
  :param resolution: A grid resolution
115
- :param buffer: Optionally, a buffer around each tile can be defined. It can be defined with a tuple of integers
116
- `(buffer_x, buffer_y)`, which specifies a number of buffer pixels in horizontal and vertical directions.
117
+ :param buffer_x: Will expand each output tile horizontally (left and right) by specified number of pixels.
118
+ :param buffer_y: Will expand each output tile vertically (up and down) by specified number of pixels.
117
119
  :param kwargs: Any other arguments to be added to a dictionary of parameters
118
- :return: A dictionary with parameters
119
120
  """
120
- payload = {"id": grid_id, "resolution": resolution, **kwargs}
121
- if buffer:
122
- payload = {**payload, "bufferX": buffer[0], "bufferY": buffer[1]}
123
- return payload
121
+ return remove_undefined(
122
+ {
123
+ "type": "tiling-grid",
124
+ "id": grid_id,
125
+ "resolution": resolution,
126
+ "bufferX": buffer_x,
127
+ "bufferY": buffer_y,
128
+ **kwargs,
129
+ }
130
+ )
124
131
 
125
132
  @staticmethod
126
- def output(
133
+ def raster_output(
134
+ delivery: AccessSpecification,
127
135
  *,
128
- default_tile_path: Optional[str] = None,
129
136
  overwrite: Optional[bool] = None,
130
137
  skip_existing: Optional[bool] = None,
131
138
  cog_output: Optional[bool] = None,
132
139
  cog_parameters: Optional[Dict[str, Any]] = None,
133
140
  create_collection: Optional[bool] = None,
134
141
  collection_id: Optional[str] = None,
135
- responses: Optional[List[str]] = None,
136
142
  **kwargs: Any,
137
143
  ) -> Dict[str, Any]:
138
- """A helper method to build a dictionary with tiling grid parameters
144
+ """A helper method to build a dictionary specifying raster output
139
145
 
140
- :param default_tile_path: A path or a template on an s3 bucket where to store results. More info at Batch API
141
- documentation
146
+ :param delivery: An S3 access specification containing a path or a template on an s3 bucket where to store
147
+ results. You can use the `s3_specification` method for construction. For more information on templates see
148
+ documentation.
142
149
  :param overwrite: A flag specifying if a request should overwrite existing outputs without failing
143
150
  :param skip_existing: A flag specifying if existing outputs should be overwritten
144
- :param cog_output: A flag specifying if outputs should be written in COGs (cloud-optimized GeoTIFFs )or
151
+ :param cog_output: A flag specifying if outputs should be written in COGs (cloud-optimized GeoTIFFs) or
145
152
  normal GeoTIFFs
146
- :param cog_parameters: A dictionary specifying COG creation parameters
153
+ :param cog_parameters: A dictionary specifying COG creation parameters. See documentation for more info.
147
154
  :param create_collection: If True the results will be written in COGs and a batch collection will be created
148
155
  :param collection_id: If True results will be added to an existing collection
149
- :param responses: Specification of path template for individual outputs/responses
150
156
  :param kwargs: Any other arguments to be added to a dictionary of parameters
151
- :return: A dictionary of output parameters
152
157
  """
153
158
  return remove_undefined(
154
159
  {
155
- "defaultTilePath": default_tile_path,
160
+ "type": "raster",
161
+ "delivery": delivery,
156
162
  "overwrite": overwrite,
157
163
  "skipExisting": skip_existing,
158
164
  "cogOutput": cog_output,
159
165
  "cogParameters": cog_parameters,
160
166
  "createCollection": create_collection,
161
167
  "collectionId": collection_id,
162
- "responses": responses,
163
168
  **kwargs,
164
169
  }
165
170
  )
166
171
 
167
- def iter_tiling_grids(self, **kwargs: Any) -> SentinelHubFeatureIterator:
168
- """An iterator over tiling grids
169
-
170
- `Batch API reference
171
- <https://docs.sentinel-hub.com/api/latest/reference/#operation/getBatchTilingGridsProperties>`__
172
-
173
- :param kwargs: Any other request query parameters
174
- :return: An iterator over tiling grid definitions
172
+ @staticmethod
173
+ def zarr_output(
174
+ delivery: AccessSpecification,
175
+ *,
176
+ group: Optional[Dict[str, Any]] = None,
177
+ array_parameters: Optional[Dict[str, Any]] = None,
178
+ array_overrides: Optional[Dict[str, Any]] = None,
179
+ **kwargs: Any,
180
+ ) -> JsonDict:
181
+ """A helper method to build a dictionary specifying Zarr output. See documentation for more information on
182
+ each parameter.
183
+
184
+ `Batch Process V2 <https://docs.sentinel-hub.com/api/latest/api/batchv2/>`__
185
+
186
+ :param delivery: An S3 access specification containing a path or a template on an s3 bucket where to store
187
+ results. You can use the `s3_specification` method for construction. For more information on templates see
188
+ documentation.
189
+ :param group: Zarr group level parameters
190
+ :param array_parameters: Parameters that will be used for all output arrays, except where overriden with
191
+ `array_overrides`. Required unless `array_overrides` includes all required fields for all output arrays.
192
+ :param array_overrides: Overrides the values of `array_arameters` for individual arrays.
193
+ :param kwargs: Any other arguments to be added to a dictionary of parameters
175
194
  """
176
- return SentinelHubFeatureIterator(
177
- client=self.client,
178
- url=self._get_tiling_grids_url(),
179
- params=remove_undefined(kwargs),
180
- exception_message="Failed to obtain information about available tiling grids",
195
+ return remove_undefined(
196
+ {
197
+ "type": "zarr",
198
+ "delivery": delivery,
199
+ "group": group,
200
+ "arrayParameter": array_parameters,
201
+ "arrayOverrides": array_overrides,
202
+ **kwargs,
203
+ }
181
204
  )
182
205
 
183
- def get_tiling_grid(self, grid_id: Union[int, str]) -> JsonDict:
184
- """Provides a single tiling grid
185
-
186
- `Batch API reference
187
- <https://docs.sentinel-hub.com/api/latest/reference/#operation/getBatchTilingGridProperties>`__
188
-
189
- :param grid_id: An ID of a requested tiling grid
190
- :return: A tiling grid definition
191
- """
192
- url = self._get_tiling_grids_url(grid_id)
193
- return self.client.get_json_dict(url=url, use_session=True)
194
-
195
206
  def iter_requests(
196
207
  self, user_id: Optional[str] = None, search: Optional[str] = None, sort: Optional[str] = None, **kwargs: Any
197
- ) -> Iterator["BatchRequest"]:
208
+ ) -> Iterator["BatchProcessRequest"]:
198
209
  """Iterate existing batch requests
199
210
 
200
- `Batch API reference
201
- <https://docs.sentinel-hub.com/api/latest/reference/#operation/getAllBatchProcessRequests>`__
211
+ `Batch Process V2 <https://docs.sentinel-hub.com/api/latest/api/batchv2/>`__
202
212
 
203
213
  :param user_id: Filter requests by a user id who defined a request
204
214
  :param search: A search query to filter requests
@@ -211,366 +221,105 @@ class SentinelHubBatch(BaseBatchClient):
211
221
  client=self.client, url=self._get_processing_url(), params=params, exception_message="No requests found"
212
222
  )
213
223
  for request_info in feature_iterator:
214
- yield BatchRequest.from_dict(request_info)
224
+ yield BatchProcessRequest.from_dict(request_info)
215
225
 
216
- def get_latest_request(self) -> "BatchRequest":
217
- """Provides a batch request that has been created the latest
226
+ def get_request(self, batch_request: BatchRequestType) -> "BatchProcessRequest":
227
+ """Collects information about a single batch request.
218
228
 
219
- :return: Batch request info
220
- """
221
- latest_request_iter = self.iter_requests(sort="created:desc", count=1)
222
- try:
223
- return next(latest_request_iter)
224
- except StopIteration as exception:
225
- raise ValueError("No batch request is available") from exception
226
-
227
- def get_request(self, batch_request: BatchRequestType) -> "BatchRequest":
228
- """Collects information about a single batch request
229
-
230
- `Batch API reference
231
- <https://docs.sentinel-hub.com/api/latest/reference/#operation/getSingleBatchProcessRequestById>`__
232
-
233
- :return: Batch request info
229
+ `Batch Process V2 <https://docs.sentinel-hub.com/api/latest/api/batchv2/>`__
234
230
  """
235
231
  request_id = self._parse_request_id(batch_request)
236
232
  request_info = self.client.get_json_dict(url=self._get_processing_url(request_id), use_session=True)
237
- return BatchRequest.from_dict(request_info)
238
-
239
- def update_request(
240
- self,
241
- batch_request: BatchRequestType,
242
- output: Optional[Dict[str, Any]] = None,
243
- description: Optional[str] = None,
244
- **kwargs: Any,
245
- ) -> Json:
246
- """Update batch job request parameters
233
+ return BatchProcessRequest.from_dict(request_info)
247
234
 
248
- `Batch API reference
249
- <https://docs.sentinel-hub.com/api/latest/reference/#operation/updateBatchProcessRequest>`__
235
+ def update_request(self, batch_request: BatchRequestType, description: str) -> Json:
236
+ """Update certain batch job request parameters. Can only update requests that are not currently being processed.
250
237
 
251
- Similarly to `update_info` method, this method also updates local information in the current instance of
252
- `SentinelHubBatch`.
238
+ `Batch Process V2 <https://docs.sentinel-hub.com/api/latest/api/batchv2/>`__
253
239
 
254
- :param batch_request: It could be a batch request object, a raw batch request payload or only a batch
255
- request ID.
256
- :param output: A dictionary with output parameters to be updated.
240
+ :param batch_request: Batch request ID, a dictionary containing an "ID" field, or a BatchProcessRequest.
257
241
  :param description: A description of a batch request to be updated.
258
- :param kwargs: Any other arguments to be added to a dictionary of parameters.
259
242
  """
260
243
  request_id = self._parse_request_id(batch_request)
261
- payload = remove_undefined({"output": output, "description": description, **kwargs})
244
+
262
245
  return self.client.get_json(
263
246
  url=self._get_processing_url(request_id),
264
- post_values=payload,
247
+ post_values={"description": description},
265
248
  request_type=RequestType.PUT,
266
249
  use_session=True,
267
250
  )
268
251
 
269
- def delete_request(self, batch_request: BatchRequestType) -> Json:
270
- """Delete a batch job request
271
-
272
- `Batch API reference
273
- <https://docs.sentinel-hub.com/api/latest/reference/#operation/deleteBatchProcessRequest>`__
274
-
275
- :param batch_request: It could be a batch request object, a raw batch request payload or only a batch
276
- request ID.
277
- """
278
- request_id = self._parse_request_id(batch_request)
279
- return self.client.get_json(
280
- url=self._get_processing_url(request_id), request_type=RequestType.DELETE, use_session=True
281
- )
282
-
283
252
  def start_analysis(self, batch_request: BatchRequestType) -> Json:
284
253
  """Starts analysis of a batch job request
285
254
 
286
- `Batch API reference <https://docs.sentinel-hub.com/api/latest/reference/#operation/batchAnalyse>`__
287
-
288
- :param batch_request: It could be a batch request object, a raw batch request payload or only a batch
289
- request ID.
255
+ :param batch_request: Batch request ID, a dictionary containing an "ID" field, or a BatchProcessRequest.
290
256
  """
291
257
  return self._call_job(batch_request, "analyse")
292
258
 
293
259
  def start_job(self, batch_request: BatchRequestType) -> Json:
294
260
  """Starts running a batch job
295
261
 
296
- `Batch API reference <https://docs.sentinel-hub.com/api/latest/reference/#operation/batchStartProcessRequest>`__
297
-
298
- :param batch_request: It could be a batch request object, a raw batch request payload or only a batch
299
- request ID.
262
+ :param batch_request: Batch request ID, a dictionary containing an "ID" field, or a BatchProcessRequest.
300
263
  """
301
264
  return self._call_job(batch_request, "start")
302
265
 
303
- def cancel_job(self, batch_request: BatchRequestType) -> Json:
304
- """Cancels a batch job
305
-
306
- `Batch API reference
307
- <https://docs.sentinel-hub.com/api/latest/reference/#operation/batchCancelProcessRequest>`__
308
-
309
- :param batch_request: It could be a batch request object, a raw batch request payload or only a batch
310
- request ID.
311
- """
312
- return self._call_job(batch_request, "cancel")
313
-
314
- def restart_job(self, batch_request: BatchRequestType) -> Json:
315
- """Restarts only those parts of a job that failed
316
-
317
- `Batch API reference
318
- <https://docs.sentinel-hub.com/api/latest/reference/#operation/batchRestartPartialProcessRequest>`__
319
-
320
- :param batch_request: It could be a batch request object, a raw batch request payload or only a batch
321
- request ID.
322
- """
323
- return self._call_job(batch_request, "restartpartial")
324
-
325
- def iter_tiles(
326
- self, batch_request: BatchRequestType, status: Union[None, "BatchTileStatus", str] = None, **kwargs: Any
327
- ) -> SentinelHubFeatureIterator:
328
- """Iterate over info about batch request tiles
329
-
330
- `Batch API reference <https://docs.sentinel-hub.com/api/latest/reference/#operation/getAllBatchProcessTiles>`__
331
-
332
- :param batch_request: It could be a batch request object, a raw batch request payload or only a batch
333
- request ID.
334
- :param status: A filter to obtain only tiles with a certain status
335
- :param kwargs: Any additional parameters to include in a request query
336
- :return: An iterator over information about each tile
337
- """
338
- request_id = self._parse_request_id(batch_request)
339
- if isinstance(status, BatchTileStatus):
340
- status = status.value
341
-
342
- return SentinelHubFeatureIterator(
343
- client=self.client,
344
- url=self._get_tiles_url(request_id),
345
- params={"status": status, **kwargs},
346
- exception_message="No tiles found, please run analysis on batch request before calling this method",
347
- )
348
-
349
- def get_tile(self, batch_request: BatchRequestType, tile_id: Optional[int]) -> JsonDict:
350
- """Provides information about a single batch request tile
266
+ def stop_job(self, batch_request: BatchRequestType) -> Json:
267
+ """Stops a batch job
351
268
 
352
- `Batch API reference <https://docs.sentinel-hub.com/api/latest/reference/#operation/getBatchTileById>`__
353
-
354
- :param batch_request: It could be a batch request object, a raw batch request payload or only a batch
355
- request ID.
356
- :param tile_id: An ID of a tile
357
- :return: Information about a tile
269
+ :param batch_request: Batch request ID, a dictionary containing an "ID" field, or a BatchProcessRequest.
358
270
  """
359
- request_id = self._parse_request_id(batch_request)
360
- url = self._get_tiles_url(request_id, tile_id=tile_id)
361
- return self.client.get_json_dict(url, use_session=True)
271
+ return self._call_job(batch_request, "stop")
362
272
 
363
- def iter_collections(self, search: Optional[str] = None, **kwargs: Any) -> SentinelHubFeatureIterator:
364
- """Iterate over batch collections
273
+ def iter_tiling_grids(self, **kwargs: Any) -> SentinelHubFeatureIterator:
274
+ """An iterator over tiling grids
365
275
 
366
- `Batch API reference <https://docs.sentinel-hub.com/api/latest/reference/#operation/getAllBatchCollections>`__
276
+ `Batch Process V2 <https://docs.sentinel-hub.com/api/latest/api/batchv2/>`__
367
277
 
368
- :param search: A search query to filter collections
369
- :param kwargs: Any additional parameters to include in a request query
370
- :return: An iterator over existing batch collections
278
+ :param kwargs: Any other request query parameters
279
+ :return: An iterator over tiling grid definitions
371
280
  """
372
281
  return SentinelHubFeatureIterator(
373
282
  client=self.client,
374
- url=self._get_collections_url(),
375
- params={"search": search, **kwargs},
376
- exception_message="Failed to obtain information about available Batch collections",
377
- )
378
-
379
- def get_collection(self, collection_id: str) -> JsonDict:
380
- """Get batch collection by its id
381
-
382
- `Batch API reference
383
- <https://docs.sentinel-hub.com/api/latest/reference/#operation/getSingleBatchCollectionById>`__
384
-
385
- :param collection_id: A batch collection id
386
- :return: A dictionary of the collection parameters
387
- """
388
- url = self._get_collections_url(collection_id)
389
- return self.client.get_json_dict(url=url, use_session=True, extract_key="data")
390
-
391
- def create_collection(self, collection: Union["BatchCollection", dict]) -> JsonDict:
392
- """Create a new batch collection
393
-
394
- `Batch API reference <https://docs.sentinel-hub.com/api/latest/reference/#operation/createNewBatchCollection>`__
395
-
396
- :param collection: Batch collection definition
397
- :return: A dictionary of a newly created collection
398
- """
399
- collection_payload = self._parse_collection_to_dict(collection)
400
- url = self._get_collections_url()
401
- return self.client.get_json_dict(url=url, post_values=collection_payload, use_session=True, extract_key="data")
402
-
403
- def update_collection(self, collection: Union["BatchCollection", dict]) -> Json:
404
- """Update an existing batch collection
405
-
406
- `Batch API reference <https://docs.sentinel-hub.com/api/latest/reference/#operation/updateBatchCollection>`__
407
-
408
- :param collection: Batch collection definition
409
- """
410
- collection_id = self._parse_collection_id(collection)
411
- return self.client.get_json(
412
- url=self._get_collections_url(collection_id),
413
- post_values=self._parse_collection_to_dict(collection),
414
- request_type=RequestType.PUT,
415
- use_session=True,
283
+ url=f"{self.service_url}/tilinggrids",
284
+ params=remove_undefined(kwargs),
285
+ exception_message="Failed to obtain information about available tiling grids",
416
286
  )
417
287
 
418
- def delete_collection(self, collection: BatchCollectionType) -> Json:
419
- """Delete an existing batch collection
288
+ def get_tiling_grid(self, grid_id: int) -> JsonDict:
289
+ """Provides a single tiling grid
420
290
 
421
- `Batch API reference <https://docs.sentinel-hub.com/api/latest/reference/#operation/deleteBatchCollection>`__
291
+ `Batch Process V2 <https://docs.sentinel-hub.com/api/latest/api/batchv2/>`__
422
292
 
423
- :param collection: Batch collection id or object
293
+ :param grid_id: An ID of a requested tiling grid
294
+ :return: A tiling grid definition
424
295
  """
425
- collection_id = self._parse_collection_id(collection)
426
- return self.client.get_json(
427
- url=self._get_collections_url(collection_id), request_type=RequestType.DELETE, use_session=True
428
- )
429
-
430
- def _get_processing_url(self, request_id: Optional[str] = None) -> str:
431
- """Creates a URL for process endpoint"""
432
- url = f"{self.service_url}/process"
433
- if request_id is None:
434
- return url
435
- return f"{url}/{request_id}"
436
-
437
- def _get_tiles_url(self, request_id: str, tile_id: Union[None, str, int] = None) -> str:
438
- """Creates a URL for tiles endpoint"""
439
- url = f"{self._get_processing_url(request_id)}/tiles"
440
- if tile_id is None:
441
- return url
442
- return f"{url}/{tile_id}"
443
-
444
- def _get_tiling_grids_url(self, grid_id: Union[None, str, int] = None) -> str:
445
- """Creates a URL for tiling grids endpoint"""
446
- url = f"{self.service_url}/tilinggrids"
447
- if grid_id is None:
448
- return url
449
- return f"{url}/{grid_id}"
450
-
451
- def _get_collections_url(self, collection_id: Optional[str] = None) -> str:
452
- """Creates a URL for batch collections endpoint"""
453
- url = f"{self.service_url}/collections"
454
- if collection_id is None:
455
- return url
456
- return f"{url}/{collection_id}"
457
-
458
- @staticmethod
459
- def _parse_collection_id(data: BatchCollectionType) -> Optional[str]:
460
- """Parses batch collection id from multiple possible inputs"""
461
- if isinstance(data, (BatchCollection, DataCollection)):
462
- return data.collection_id
463
- if isinstance(data, dict):
464
- return data["id"]
465
- if isinstance(data, str):
466
- return data
467
- raise ValueError(f"Expected a BatchCollection dataclass, dictionary or a string, got {data}.")
468
-
469
- @staticmethod
470
- def _parse_collection_to_dict(data: Union["BatchCollection", dict]) -> dict:
471
- """Constructs a dictionary from given object"""
472
- if isinstance(data, BatchCollection):
473
- return data.to_dict() # type: ignore[attr-defined]
474
- if isinstance(data, dict):
475
- return data
476
- raise ValueError(f"Expected either a BatchCollection or a dict, got {data}.")
296
+ url = f"{self.service_url}/tilinggrids/{grid_id}"
297
+ return self.client.get_json_dict(url=url, use_session=True)
477
298
 
478
299
 
479
300
  @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.INCLUDE)
480
301
  @dataclass(repr=False)
481
- class BatchRequest(BaseBatchRequest): # pylint: disable=abstract-method
302
+ class BatchProcessRequest(BaseBatchRequest): # pylint: disable=abstract-method
482
303
  """A dataclass object that holds information about a batch request"""
483
304
 
484
305
  # dataclass_json doesn't handle parameter inheritance correctly
485
- # pylint: disable=duplicate-code
306
+ # pylint: disable=invalid-name
486
307
 
487
308
  request_id: str = field(metadata=dataclass_config(field_name="id"))
488
- process_request: dict
489
- tile_count: int
309
+ request: dict
310
+ domain_account_id: str
490
311
  status: BatchRequestStatus = field(metadata=enum_config(BatchRequestStatus))
491
- user_id: Optional[str] = None
492
- created: Optional[dt.datetime] = field(metadata=datetime_config, default=None)
493
- tiling_grid: dict = field(default_factory=dict)
494
- output: dict = field(default_factory=dict)
495
- bucket_name: Optional[str] = None
496
- description: Optional[str] = None
497
- value_estimate: Optional[float] = None
498
- tile_width_px: Optional[int] = None
499
- tile_height_px: Optional[int] = None
500
- user_action: Optional[BatchUserAction] = field(metadata=enum_config(BatchUserAction), default=None)
501
- user_action_updated: Optional[str] = field(metadata=datetime_config, default=None)
502
312
  error: Optional[str] = None
503
- other_data: CatchAll = field(default_factory=dict)
504
-
505
- _REPR_PARAM_NAMES = (
506
- "request_id",
507
- "description",
508
- "bucket_name",
509
- "created",
510
- "status",
511
- "user_action",
512
- "value_estimate",
513
- "tile_count",
313
+ user_action: Optional[BatchUserAction] = field(metadata=enum_config(BatchUserAction), default=None)
314
+ user_action_updated: Optional[dt.datetime] = field(metadata=datetime_config, default=None)
315
+ created: Optional[dt.datetime] = field(metadata=datetime_config, default=None)
316
+ completion_percentage: float = 0
317
+ last_updated: Optional[dt.datetime] = field(metadata=datetime_config, default=None)
318
+ cost_PU: Optional[float] = field(metadata=dataclass_config(field_name="costPU"), default=None) # noqa: N815
319
+ stopped_status_reason: Optional[StoppedStatusReason] = field(
320
+ metadata=enum_config(StoppedStatusReason), default=None
514
321
  )
515
322
 
516
- @property
517
- def evalscript(self) -> str:
518
- """Provides an evalscript used by a batch request
519
-
520
- :return: An evalscript
521
- """
522
- return self.process_request["evalscript"]
523
-
524
- @property
525
- def bbox(self) -> Optional[BBox]:
526
- """Provides a bounding box used by a batch request
527
-
528
- :return: An area bounding box together with CRS
529
- :raises: ValueError
530
- """
531
- bbox, _, crs = self._parse_bounds_payload()
532
- return None if bbox is None else BBox(bbox, crs) # type: ignore[arg-type]
533
-
534
- @property
535
- def geometry(self) -> Optional[Geometry]:
536
- """Provides a geometry used by a batch request
537
-
538
- :return: An area geometry together with CRS
539
- :raises: ValueError
540
- """
541
- _, geometry, crs = self._parse_bounds_payload()
542
- return None if geometry is None else Geometry(geometry, crs)
543
-
544
- def _parse_bounds_payload(self) -> Tuple[Optional[List[float]], Optional[list], CRS]:
545
- """Parses bbox, geometry and crs from batch request payload. If bbox or geometry don't exist it returns None
546
- instead.
547
- """
548
- bounds_definition = self.process_request["input"]["bounds"]
549
- crs = CRS(bounds_definition["properties"]["crs"].rsplit("/", 1)[-1])
550
-
551
- return bounds_definition.get("bbox"), bounds_definition.get("geometry"), crs
552
-
553
-
554
- @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.INCLUDE)
555
- @dataclass
556
- class BatchCollectionBatchData:
557
- """Dataclass to hold batch collection batchData part of the payload"""
558
-
559
- tiling_grid_id: Optional[int] = None
560
- other_data: CatchAll = field(default_factory=dict)
561
-
562
-
563
- @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.INCLUDE)
564
- @dataclass
565
- class BatchCollectionAdditionalData:
566
- """Dataclass to hold batch collection additionalData part of the payload"""
567
-
568
- bands: Optional[Dict[str, Any]] = None
569
323
  other_data: CatchAll = field(default_factory=dict)
570
324
 
571
-
572
- class BatchCollection(BaseCollection):
573
- """Dataclass for batch collections"""
574
-
575
- batch_data: Optional[BatchCollectionBatchData] = None
576
- additional_data: Optional[BatchCollectionAdditionalData] = None
325
+ _REPR_PARAM_NAMES = ("request_id", "created", "status", "completion_percentage", "user_action", "cost_PU")