sentinelhub 3.10.3__tar.gz → 3.11.0__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.
Files changed (63) hide show
  1. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/PKG-INFO +1 -1
  2. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/pyproject.toml +2 -0
  3. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/__init__.py +4 -0
  4. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/_version.py +1 -1
  5. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/api/__init__.py +4 -0
  6. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/api/batch/__init__.py +3 -0
  7. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/api/batch/base.py +8 -0
  8. sentinelhub-3.11.0/sentinelhub/api/batch/process_v2.py +325 -0
  9. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/api/batch/statistical.py +1 -1
  10. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/api/batch/utils.py +76 -0
  11. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/api/process.py +1 -1
  12. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/.gitignore +0 -0
  13. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/LICENSE.md +0 -0
  14. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/README.md +0 -0
  15. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/.utmzones.geojson +0 -0
  16. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/api/base.py +0 -0
  17. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/api/base_request.py +0 -0
  18. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/api/batch/process.py +0 -0
  19. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/api/byoc.py +0 -0
  20. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/api/catalog.py +0 -0
  21. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/api/fis.py +0 -0
  22. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/api/ogc.py +0 -0
  23. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/api/opensearch.py +0 -0
  24. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/api/statistical.py +0 -0
  25. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/api/utils.py +0 -0
  26. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/api/wfs.py +0 -0
  27. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/areas.py +0 -0
  28. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/aws/__init__.py +0 -0
  29. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/aws/batch.py +0 -0
  30. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/aws/client.py +0 -0
  31. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/aws/commands.py +0 -0
  32. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/aws/constants.py +0 -0
  33. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/aws/data.py +0 -0
  34. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/aws/data_safe.py +0 -0
  35. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/aws/request.py +0 -0
  36. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/base.py +0 -0
  37. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/commands.py +0 -0
  38. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/config.py +0 -0
  39. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/constants.py +0 -0
  40. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/data_collections.py +0 -0
  41. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/data_collections_bands.py +0 -0
  42. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/data_utils.py +0 -0
  43. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/decoding.py +0 -0
  44. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/download/__init__.py +0 -0
  45. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/download/client.py +0 -0
  46. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/download/handlers.py +0 -0
  47. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/download/models.py +0 -0
  48. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/download/rate_limit.py +0 -0
  49. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/download/sentinelhub_client.py +0 -0
  50. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/download/sentinelhub_statistical_client.py +0 -0
  51. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/download/session.py +0 -0
  52. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/evalscript.py +0 -0
  53. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/exceptions.py +0 -0
  54. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/geo_utils.py +0 -0
  55. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/geometry.py +0 -0
  56. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/geopedia/__init__.py +0 -0
  57. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/geopedia/core.py +0 -0
  58. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/geopedia/request.py +0 -0
  59. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/io_utils.py +0 -0
  60. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/py.typed +0 -0
  61. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/testing_utils.py +0 -0
  62. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/time_utils.py +0 -0
  63. {sentinelhub-3.10.3 → sentinelhub-3.11.0}/sentinelhub/types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: sentinelhub
3
- Version: 3.10.3
3
+ Version: 3.11.0
4
4
  Summary: Python API for Sentinel Hub
5
5
  Project-URL: Homepage, https://github.com/sentinel-hub/sentinelhub-py
6
6
  Project-URL: Documentation, https://sentinelhub-py.readthedocs.io
@@ -152,6 +152,7 @@ lint.fixable = [
152
152
  "FA100", # import future annotations where necessary (not autofixable ATM)
153
153
  ]
154
154
  lint.ignore = [
155
+ "G004", # f-strings in logging
155
156
  "C408", # complains about `dict()` calls, we use them to avoid too many " in the code
156
157
  "SIM108", # tries to aggresively inline `if`, not always readable
157
158
  "COM812", # trailing comma missing, fights with black
@@ -191,6 +192,7 @@ disable = [
191
192
  "unspecified-encoding",
192
193
  "unnecessary-ellipsis",
193
194
  "use-dict-literal",
195
+ "R0801",
194
196
  ]
195
197
 
196
198
  [tool.pylint.design]
@@ -6,6 +6,8 @@ from ._version import __version__
6
6
  from .api import (
7
7
  AsyncProcessRequest,
8
8
  BatchCollection,
9
+ BatchProcessClient,
10
+ BatchProcessRequest,
9
11
  BatchRequest,
10
12
  BatchRequestStatus,
11
13
  BatchStatisticalRequest,
@@ -28,6 +30,8 @@ from .api import (
28
30
  get_async_running_status,
29
31
  monitor_batch_analysis,
30
32
  monitor_batch_job,
33
+ monitor_batch_process_analysis,
34
+ monitor_batch_process_job,
31
35
  monitor_batch_statistical_analysis,
32
36
  monitor_batch_statistical_job,
33
37
  opensearch,
@@ -1,3 +1,3 @@
1
1
  """Version of the sentinelhub package."""
2
2
 
3
- __version__ = "3.10.3"
3
+ __version__ = "3.11.0"
@@ -4,6 +4,8 @@ The part of the package that implements interface with Sentinel Hub services.
4
4
 
5
5
  from .batch import (
6
6
  BatchCollection,
7
+ BatchProcessClient,
8
+ BatchProcessRequest,
7
9
  BatchRequest,
8
10
  BatchRequestStatus,
9
11
  BatchStatisticalRequest,
@@ -13,6 +15,8 @@ from .batch import (
13
15
  SentinelHubBatchStatistical,
14
16
  monitor_batch_analysis,
15
17
  monitor_batch_job,
18
+ monitor_batch_process_analysis,
19
+ monitor_batch_process_job,
16
20
  monitor_batch_statistical_analysis,
17
21
  monitor_batch_statistical_job,
18
22
  )
@@ -4,10 +4,13 @@ The part of the package that implements interface with Sentinel Hub services.
4
4
 
5
5
  from .base import BatchRequestStatus, BatchUserAction
6
6
  from .process import BatchCollection, BatchRequest, BatchTileStatus, SentinelHubBatch
7
+ from .process_v2 import BatchProcessClient, BatchProcessRequest
7
8
  from .statistical import BatchStatisticalRequest, SentinelHubBatchStatistical
8
9
  from .utils import (
9
10
  monitor_batch_analysis,
10
11
  monitor_batch_job,
12
+ monitor_batch_process_analysis,
13
+ monitor_batch_process_job,
11
14
  monitor_batch_statistical_analysis,
12
15
  monitor_batch_statistical_job,
13
16
  )
@@ -41,6 +41,14 @@ class BatchUserAction(Enum):
41
41
  STOP = "STOP"
42
42
 
43
43
 
44
+ class StoppedStatusReason(Enum):
45
+ """Description of why job status is STOPPED"""
46
+
47
+ OUT_OF_PU = "OUT_OF_PU"
48
+ USER_ACTION = "USER_ACTION"
49
+ UNHEALTHY = "UNHEALTHY"
50
+
51
+
44
52
  class BaseBatchClient(SentinelHubService, Generic[BatchRequestType], metaclass=ABCMeta):
45
53
  """Class containing common methods and helper functions for Batch Client classes"""
46
54
 
@@ -0,0 +1,325 @@
1
+ """
2
+ Module implementing an interface with
3
+ `Batch Process V2 <https://docs.sentinel-hub.com/api/latest/api/batchv2/>`__.
4
+ """
5
+
6
+ # ruff: noqa: FA100
7
+ # do not use `from __future__ import annotations`, it clashes with `dataclass_json`
8
+ import datetime as dt
9
+ import logging
10
+ from dataclasses import dataclass, field
11
+ from typing import Any, Dict, Iterator, Optional, Union
12
+
13
+ from dataclasses_json import CatchAll, LetterCase, Undefined, dataclass_json
14
+ from dataclasses_json import config as dataclass_config
15
+ from typing_extensions import Literal
16
+
17
+ from ...constants import RequestType
18
+ from ...types import Json, JsonDict
19
+ from ..base import SentinelHubFeatureIterator
20
+ from ..process import SentinelHubRequest
21
+ from ..utils import AccessSpecification, datetime_config, enum_config, remove_undefined, s3_specification
22
+ from .base import BaseBatchClient, BaseBatchRequest, BatchRequestStatus, BatchUserAction, StoppedStatusReason
23
+
24
+ LOGGER = logging.getLogger(__name__)
25
+
26
+ BatchRequestType = Union[str, dict, "BatchProcessRequest"]
27
+
28
+
29
+ class BatchProcessClient(BaseBatchClient):
30
+ """An interface class for Sentinel Hub Batch API version 2.
31
+
32
+ `Batch Process API <https://docs.sentinel-hub.com/api/latest/api/batchv2/>`__
33
+ """
34
+
35
+ s3_specification = staticmethod(s3_specification)
36
+
37
+ # pylint: disable=too-many-public-methods
38
+ @staticmethod
39
+ def _get_service_url(base_url: str) -> str:
40
+ """Provides URL to Catalog API"""
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}"
49
+
50
+ def create(
51
+ self,
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",
56
+ description: Optional[str] = None,
57
+ **kwargs: Any,
58
+ ) -> "BatchProcessRequest":
59
+ """Create a new batch request
60
+
61
+ `Batch Process V2 <https://docs.sentinel-hub.com/api/latest/api/batchv2/>`__
62
+
63
+ :param process_request: An instance of SentinelHubRequest class containing all request parameters.
64
+ Alternatively, it can also be just a payload dictionary for Process API request
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.
70
+ :param description: A description of a batch request
71
+ :param kwargs: Any other arguments to be added to a dictionary of parameters.
72
+ """
73
+
74
+ if isinstance(process_request, SentinelHubRequest):
75
+ request_dict = process_request.download_list[0].post_values
76
+ else:
77
+ request_dict = process_request
78
+
79
+ if not isinstance(request_dict, dict):
80
+ raise ValueError(
81
+ "Parameter sentinelhub_request should be an instance of SentinelHubRequest or a "
82
+ "dictionary with a request payload"
83
+ )
84
+
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)
97
+
98
+ return BatchProcessRequest.from_dict(request_info)
99
+
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}
108
+
109
+ @staticmethod
110
+ def tiling_grid_input(
111
+ grid_id: int, resolution: float, buffer_x: Optional[int] = None, buffer_y: Optional[int] = None, **kwargs: Any
112
+ ) -> JsonDict:
113
+ """A helper method to build a dictionary with tiling grid parameters for the `input` field.
114
+
115
+ :param grid_id: An ID of a tiling grid
116
+ :param resolution: A grid resolution
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.
119
+ :param kwargs: Any other arguments to be added to a dictionary of parameters
120
+ """
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
+ )
131
+
132
+ @staticmethod
133
+ def raster_output(
134
+ delivery: AccessSpecification,
135
+ *,
136
+ overwrite: Optional[bool] = None,
137
+ skip_existing: Optional[bool] = None,
138
+ cog_output: Optional[bool] = None,
139
+ cog_parameters: Optional[Dict[str, Any]] = None,
140
+ create_collection: Optional[bool] = None,
141
+ collection_id: Optional[str] = None,
142
+ **kwargs: Any,
143
+ ) -> Dict[str, Any]:
144
+ """A helper method to build a dictionary specifying raster output
145
+
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.
149
+ :param overwrite: A flag specifying if a request should overwrite existing outputs without failing
150
+ :param skip_existing: A flag specifying if existing outputs should be overwritten
151
+ :param cog_output: A flag specifying if outputs should be written in COGs (cloud-optimized GeoTIFFs) or
152
+ normal GeoTIFFs
153
+ :param cog_parameters: A dictionary specifying COG creation parameters. See documentation for more info.
154
+ :param create_collection: If True the results will be written in COGs and a batch collection will be created
155
+ :param collection_id: If True results will be added to an existing collection
156
+ :param kwargs: Any other arguments to be added to a dictionary of parameters
157
+ """
158
+ return remove_undefined(
159
+ {
160
+ "type": "raster",
161
+ "delivery": delivery,
162
+ "overwrite": overwrite,
163
+ "skipExisting": skip_existing,
164
+ "cogOutput": cog_output,
165
+ "cogParameters": cog_parameters,
166
+ "createCollection": create_collection,
167
+ "collectionId": collection_id,
168
+ **kwargs,
169
+ }
170
+ )
171
+
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
194
+ """
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
+ }
204
+ )
205
+
206
+ def iter_requests(
207
+ self, user_id: Optional[str] = None, search: Optional[str] = None, sort: Optional[str] = None, **kwargs: Any
208
+ ) -> Iterator["BatchProcessRequest"]:
209
+ """Iterate existing batch requests
210
+
211
+ `Batch Process V2 <https://docs.sentinel-hub.com/api/latest/api/batchv2/>`__
212
+
213
+ :param user_id: Filter requests by a user id who defined a request
214
+ :param search: A search query to filter requests
215
+ :param sort: A sort query
216
+ :param kwargs: Any additional parameters to include in a request query
217
+ :return: An iterator over existing batch requests
218
+ """
219
+ params = remove_undefined({"userid": user_id, "search": search, "sort": sort, **kwargs})
220
+ feature_iterator = SentinelHubFeatureIterator(
221
+ client=self.client, url=self._get_processing_url(), params=params, exception_message="No requests found"
222
+ )
223
+ for request_info in feature_iterator:
224
+ yield BatchProcessRequest.from_dict(request_info)
225
+
226
+ def get_request(self, batch_request: BatchRequestType) -> "BatchProcessRequest":
227
+ """Collects information about a single batch request.
228
+
229
+ `Batch Process V2 <https://docs.sentinel-hub.com/api/latest/api/batchv2/>`__
230
+ """
231
+ request_id = self._parse_request_id(batch_request)
232
+ request_info = self.client.get_json_dict(url=self._get_processing_url(request_id), use_session=True)
233
+ return BatchProcessRequest.from_dict(request_info)
234
+
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.
237
+
238
+ `Batch Process V2 <https://docs.sentinel-hub.com/api/latest/api/batchv2/>`__
239
+
240
+ :param batch_request: Batch request ID, a dictionary containing an "ID" field, or a BatchProcessRequest.
241
+ :param description: A description of a batch request to be updated.
242
+ """
243
+ request_id = self._parse_request_id(batch_request)
244
+
245
+ return self.client.get_json(
246
+ url=self._get_processing_url(request_id),
247
+ post_values={"description": description},
248
+ request_type=RequestType.PUT,
249
+ use_session=True,
250
+ )
251
+
252
+ def start_analysis(self, batch_request: BatchRequestType) -> Json:
253
+ """Starts analysis of a batch job request
254
+
255
+ :param batch_request: Batch request ID, a dictionary containing an "ID" field, or a BatchProcessRequest.
256
+ """
257
+ return self._call_job(batch_request, "analyse")
258
+
259
+ def start_job(self, batch_request: BatchRequestType) -> Json:
260
+ """Starts running a batch job
261
+
262
+ :param batch_request: Batch request ID, a dictionary containing an "ID" field, or a BatchProcessRequest.
263
+ """
264
+ return self._call_job(batch_request, "start")
265
+
266
+ def stop_job(self, batch_request: BatchRequestType) -> Json:
267
+ """Stops a batch job
268
+
269
+ :param batch_request: Batch request ID, a dictionary containing an "ID" field, or a BatchProcessRequest.
270
+ """
271
+ return self._call_job(batch_request, "stop")
272
+
273
+ def iter_tiling_grids(self, **kwargs: Any) -> SentinelHubFeatureIterator:
274
+ """An iterator over tiling grids
275
+
276
+ `Batch Process V2 <https://docs.sentinel-hub.com/api/latest/api/batchv2/>`__
277
+
278
+ :param kwargs: Any other request query parameters
279
+ :return: An iterator over tiling grid definitions
280
+ """
281
+ return SentinelHubFeatureIterator(
282
+ client=self.client,
283
+ url=f"{self.service_url}/tilinggrids",
284
+ params=remove_undefined(kwargs),
285
+ exception_message="Failed to obtain information about available tiling grids",
286
+ )
287
+
288
+ def get_tiling_grid(self, grid_id: int) -> JsonDict:
289
+ """Provides a single tiling grid
290
+
291
+ `Batch Process V2 <https://docs.sentinel-hub.com/api/latest/api/batchv2/>`__
292
+
293
+ :param grid_id: An ID of a requested tiling grid
294
+ :return: A tiling grid definition
295
+ """
296
+ url = f"{self.service_url}/tilinggrids/{grid_id}"
297
+ return self.client.get_json_dict(url=url, use_session=True)
298
+
299
+
300
+ @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.INCLUDE)
301
+ @dataclass(repr=False)
302
+ class BatchProcessRequest(BaseBatchRequest): # pylint: disable=abstract-method
303
+ """A dataclass object that holds information about a batch request"""
304
+
305
+ # dataclass_json doesn't handle parameter inheritance correctly
306
+ # pylint: disable=invalid-name
307
+
308
+ request_id: str = field(metadata=dataclass_config(field_name="id"))
309
+ request: dict
310
+ domain_account_id: str
311
+ status: BatchRequestStatus = field(metadata=enum_config(BatchRequestStatus))
312
+ error: Optional[str] = None
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
321
+ )
322
+
323
+ other_data: CatchAll = field(default_factory=dict)
324
+
325
+ _REPR_PARAM_NAMES = ("request_id", "created", "status", "completion_percentage", "user_action", "cost_PU")
@@ -33,7 +33,7 @@ class SentinelHubBatchStatistical(BaseBatchClient["BatchStatisticalRequest"]):
33
33
  information.
34
34
  """
35
35
 
36
- s3_specification = s3_specification
36
+ s3_specification = staticmethod(s3_specification)
37
37
 
38
38
  @staticmethod
39
39
  def _get_service_url(base_url: str) -> str:
@@ -15,6 +15,7 @@ from ...config import SHConfig
15
15
  from ...types import JsonDict
16
16
  from .base import BatchRequestStatus
17
17
  from .process import BatchRequest, BatchTileStatus, SentinelHubBatch
18
+ from .process_v2 import BatchProcessClient, BatchProcessRequest
18
19
  from .statistical import BatchStatisticalRequest, SentinelHubBatchStatistical
19
20
 
20
21
  LOGGER = logging.getLogger(__name__)
@@ -106,6 +107,54 @@ def monitor_batch_job(
106
107
  return tiles_per_status
107
108
 
108
109
 
110
+ def monitor_batch_process_job(
111
+ request: BatchProcessRequest,
112
+ client: BatchProcessClient,
113
+ sleep_time: int = _DEFAULT_SLEEP_TIME,
114
+ analysis_sleep_time: int = _DEFAULT_ANALYSIS_SLEEP_TIME,
115
+ ) -> BatchProcessRequest:
116
+ """A utility function that keeps checking the progress of the batch processing job. Returns an updated version of
117
+ the request
118
+
119
+ Notes:
120
+
121
+ - Before calling this function make sure to start a batch job by calling `BatchProcessingClient.start_job` method.
122
+ In case a batch job is still being analysed this function will wait until the analysis ends.
123
+ - This function will be continuously collecting information from Sentinel Hub service. To avoid making too many
124
+ requests please make sure to adjust `sleep_time` parameter.
125
+
126
+ :param request: The request to monitor.
127
+ :param client: A batch processing client with appropriate configuration that is used to monitor the batch job.
128
+ :param sleep_time: Number of seconds to sleep between consecutive progress bar updates.
129
+ :param analysis_sleep_time: Number of seconds between consecutive status updates during analysis phase.
130
+ """
131
+ if sleep_time < _MIN_SLEEP_TIME:
132
+ raise ValueError(f"To avoid making too many service requests please set sleep_time>={_MIN_SLEEP_TIME}")
133
+
134
+ batch_request: BatchProcessRequest = monitor_batch_process_analysis(request, client, sleep_time=analysis_sleep_time)
135
+ if batch_request.status is BatchRequestStatus.PROCESSING:
136
+ LOGGER.info("Batch job is running")
137
+
138
+ completion = batch_request.completion_percentage
139
+ progress_bar = tqdm(total=100, initial=completion, desc="Completion percentage")
140
+
141
+ monitoring_status = [BatchRequestStatus.ANALYSIS_DONE, BatchRequestStatus.PROCESSING]
142
+ with progress_bar:
143
+ while completion < 100 and batch_request.status in monitoring_status:
144
+ time.sleep(sleep_time)
145
+ batch_request = client.get_request(batch_request)
146
+ progress_bar.update(batch_request.completion_percentage - completion)
147
+ completion = batch_request.completion_percentage
148
+
149
+ while batch_request.status in monitoring_status:
150
+ LOGGER.info("Waiting on batch job status update, currently %s", batch_request.status)
151
+ time.sleep(sleep_time)
152
+ batch_request = client.get_request(batch_request)
153
+
154
+ LOGGER.info("Batch job finished with status %s", batch_request.status.value)
155
+ return batch_request
156
+
157
+
109
158
  def _get_batch_tiles_per_status(
110
159
  batch_request: BatchRequest, batch_client: SentinelHubBatch
111
160
  ) -> defaultdict[BatchTileStatus, list[dict]]:
@@ -200,6 +249,33 @@ def monitor_batch_analysis(
200
249
  return batch_request
201
250
 
202
251
 
252
+ def monitor_batch_process_analysis(
253
+ request: BatchProcessRequest,
254
+ client: BatchProcessClient,
255
+ sleep_time: int = _DEFAULT_ANALYSIS_SLEEP_TIME,
256
+ ) -> BatchProcessRequest:
257
+ """A utility function that is waiting until analysis phase of a batch job finishes and regularly checks its status.
258
+ In case analysis phase failed it raises an error at the end.
259
+
260
+ :param request: The request to monitor.
261
+ :param client: A batch processing client with appropriate configuration that is used to monitor the batch job.
262
+ :param sleep_time: Number of seconds between consecutive status updates during analysis phase.
263
+ """
264
+ if sleep_time < _MIN_ANALYSIS_SLEEP_TIME:
265
+ raise ValueError(
266
+ f"To avoid making too many service requests please set analysis sleep time >={_MIN_ANALYSIS_SLEEP_TIME}"
267
+ )
268
+
269
+ batch_request = client.get_request(request)
270
+ while batch_request.status in [BatchRequestStatus.CREATED, BatchRequestStatus.ANALYSING]:
271
+ LOGGER.info("Batch job has a status %s, sleeping for %d seconds", batch_request.status.value, sleep_time)
272
+ time.sleep(sleep_time)
273
+ batch_request = client.get_request(batch_request)
274
+
275
+ batch_request.raise_for_status(status=[BatchRequestStatus.FAILED, BatchRequestStatus.CANCELED])
276
+ return batch_request
277
+
278
+
203
279
  def monitor_batch_statistical_analysis(
204
280
  batch_request: BatchStatisticalRequestSpec,
205
281
  config: SHConfig | None = None,
@@ -205,7 +205,7 @@ class AsyncProcessRequest(SentinelHubBaseApiRequest):
205
205
 
206
206
  super().__init__(SentinelHubDownloadClient, **kwargs)
207
207
 
208
- s3_specification = s3_specification
208
+ s3_specification = staticmethod(s3_specification)
209
209
 
210
210
  @property
211
211
  def mime_type(self) -> MimeType:
File without changes
File without changes
File without changes