Skip to content

Commit a74df05

Browse files
authored
Release 3.10.3, Merge pull request #539 from sentinel-hub/develop
Release 3.10.3
2 parents f9f29c9 + 4f7074a commit a74df05

12 files changed

+69
-41
lines changed

.github/workflows/ci_action.yml

+10-10
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,13 @@ jobs:
107107
run: |
108108
pytest -m "not sh_integration and not aws_integration"
109109
110-
- name: Upload code coverage
111-
if: ${{ matrix.full_test_suite && github.event_name == 'push' }}
112-
uses: codecov/codecov-action@v2
113-
with:
114-
files: coverage.xml
115-
fail_ci_if_error: true
116-
verbose: false
110+
# - name: Upload code coverage
111+
# if: ${{ matrix.full_test_suite && github.event_name == 'push' }}
112+
# uses: codecov/codecov-action@v2
113+
# with:
114+
# files: coverage.xml
115+
# fail_ci_if_error: true
116+
# verbose: false
117117

118118
mirror-and-integration-test-on-gitlab:
119119
if: github.event_name == 'push'
@@ -123,11 +123,11 @@ jobs:
123123
- name: Mirror + trigger CI
124124
uses: SvanBoxel/gitlab-mirror-and-ci-action@master
125125
with:
126-
args: "https://git.sinergise.com/eo/code/sentinelhub-py-dev/"
126+
args: "https://hello.planet.com/code/eo/code/sentinelhub-py-dev/"
127127
env:
128128
FOLLOW_TAGS: "true"
129-
GITLAB_HOSTNAME: "git.sinergise.com"
129+
GITLAB_HOSTNAME: "hello.planet.com/code"
130130
GITLAB_USERNAME: "github-action"
131131
GITLAB_PASSWORD: ${{ secrets.GITLAB_PASSWORD }}
132-
GITLAB_PROJECT_ID: "354"
132+
GITLAB_PROJECT_ID: "9711"
133133
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/ci_trigger.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ jobs:
1616
-F ref=main \
1717
-F variables[CUSTOM_RUN_TAG]=auto \
1818
-F variables[LAYER_NAME]=dotai-eo \
19-
https://git.sinergise.com/api/v4/projects/1031/trigger/pipeline
19+
https://hello.planet.com/code/api/v4/projects/9723/trigger/pipeline

.gitlab-ci.yml

+14-6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
default:
2+
tags:
3+
- sinergise-lju
4+
5+
variables:
6+
BASE_IMAGE: $CI_REGISTRY_IMAGE/python-3.9-base:latest
7+
18
stages:
29
- update
310
- test
@@ -6,20 +13,21 @@ update_base_image:
613
stage: update
714
image: docker:latest
815
rules:
9-
- if: '$UPDATE_BASE_IMAGE == "true"'
16+
- if: $UPDATE_BASE_IMAGE == "true"
17+
1018
script:
11-
- docker login -u gitlab-ci-token -p "$CI_JOB_TOKEN" "$CI_REGISTRY"
12-
- docker build --file=".gitlab/docker/Dockerfile" --tag="$BASE_IMAGE" .
13-
- docker push "$BASE_IMAGE"
19+
- echo $CI_JOB_TOKEN | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin
20+
- docker build -f docker/Dockerfile -t $BASE_IMAGE .
21+
- docker push $BASE_IMAGE
1422

1523
run_sh_integration_tests:
1624
stage: test
17-
image: "$BASE_IMAGE"
25+
image: $BASE_IMAGE
1826
dependencies: []
1927
needs: []
2028
rules:
2129
- when: always
22-
if: '$UPDATE_BASE_IMAGE != "true"'
30+
if: $UPDATE_BASE_IMAGE != "true"
2331
script:
2432
- pip install -e .[AWS,DEV]
2533
- pytest -m "sh_integration"

.pre-commit-config.yaml

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,18 @@ repos:
1313
- id: debug-statements
1414

1515
- repo: https://github.com/psf/black
16-
rev: 24.4.0
16+
rev: 24.8.0
1717
hooks:
1818
- id: black
1919
language_version: python3
2020

2121
- repo: https://github.com/charliermarsh/ruff-pre-commit
22-
rev: "v0.4.1"
22+
rev: "v0.5.7"
2323
hooks:
2424
- id: ruff
2525

2626
- repo: https://github.com/nbQA-dev/nbQA
27-
rev: 1.8.5
27+
rev: 1.8.7
2828
hooks:
2929
- id: nbqa-black
3030
- id: nbqa-ruff

CHANGELOG.MD

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## [Version 3.10.3] - 2024-13-08
2+
3+
- Monitoring a batch job now concludes if the batch job is cancelled.
4+
- The monitoring function now waits for the status of the batch job to change (even if all tiles have completed) before finalization in order to return the correct status.
5+
6+
17
## [Version 3.10.2] - 2024-24-04
28

39
- Added `max_retries` parameter to `SHConfig` class. It controls how many times the client will attempt to re-download before raising `OutOfRequestsException`. It is set to `None` by default, in which case it never stops trying. Contributed by @Regan-Koopmans.
File renamed without changes.

pyproject.toml

+5-5
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ preview = true
110110
[tool.ruff]
111111
line-length = 120
112112
target-version = "py38"
113-
select = [
113+
lint.select = [
114114
"F", # pyflakes
115115
"E", # pycodestyle
116116
"W", # pycodestyle
@@ -143,15 +143,15 @@ select = [
143143
"RUF", # ruff rules
144144
]
145145
fix = true
146-
fixable = [
146+
lint.fixable = [
147147
"I", # sort imports
148148
"F401", # remove redundant imports
149149
"UP007", # use new-style union type annotations
150150
"UP006", # use new-style built-in type annotations
151151
"UP037", # remove quotes around types when not necessary
152152
"FA100", # import future annotations where necessary (not autofixable ATM)
153153
]
154-
ignore = [
154+
lint.ignore = [
155155
"C408", # complains about `dict()` calls, we use them to avoid too many " in the code
156156
"SIM108", # tries to aggresively inline `if`, not always readable
157157
"COM812", # trailing comma missing, fights with black
@@ -162,11 +162,11 @@ ignore = [
162162
"B028", # always demands a stacklevel argument when warning
163163
"PT011", # complains for `pytest.raises(ValueError)` but we use it a lot
164164
]
165-
per-file-ignores = { "__init__.py" = ["F401"], "conf.py" = ["FA100"] }
165+
lint.per-file-ignores = { "__init__.py" = ["F401"], "conf.py" = ["FA100"] }
166166
exclude = [".git", "__pycache__", "build", "dist", "sentinelhub/aws/*"]
167167

168168

169-
[tool.ruff.isort]
169+
[tool.ruff.lint.isort]
170170
section-order = [
171171
"future",
172172
"standard-library",

sentinelhub/_version.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""Version of the sentinelhub package."""
22

3-
__version__ = "3.10.2"
3+
__version__ = "3.10.3"

sentinelhub/api/batch/utils.py

+11-1
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,12 @@ def monitor_batch_job(
7373

7474
progress_bar = tqdm(total=batch_request.tile_count, initial=finished_count, desc="Progress rate")
7575
success_bar = tqdm(total=finished_count, initial=success_count, desc="Success rate")
76+
77+
monitoring_status = [BatchRequestStatus.ANALYSIS_DONE, BatchRequestStatus.PROCESSING]
7678
with progress_bar, success_bar:
77-
while finished_count < batch_request.tile_count:
79+
while finished_count < batch_request.tile_count and batch_request.status in monitoring_status:
7880
time.sleep(sleep_time)
81+
batch_request = batch_client.get_request(batch_request)
7982

8083
tiles_per_status = _get_batch_tiles_per_status(batch_request, batch_client)
8184
new_success_count = len(tiles_per_status[BatchTileStatus.PROCESSED])
@@ -93,6 +96,13 @@ def monitor_batch_job(
9396
failed_tiles_num = finished_count - success_count
9497
if failed_tiles_num:
9598
LOGGER.info("Batch job failed for %d tiles", failed_tiles_num)
99+
100+
while batch_request.status is BatchRequestStatus.PROCESSING:
101+
LOGGER.info("Waiting on batch job status update.")
102+
time.sleep(sleep_time)
103+
batch_request = batch_client.get_request(batch_request)
104+
105+
LOGGER.info("Batch job finished with status %s", batch_request.status.value)
96106
return tiles_per_status
97107

98108

sentinelhub/constants.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def __new__(mcs, cls, bases, classdict): # type: ignore[no-untyped-def] # noqa:
8181

8282
return super().__new__(mcs, cls, bases, classdict)
8383

84-
def __call__(cls, crs_value, *args, **kwargs): # type: ignore[no-untyped-def] # noqa: N805
84+
def __call__(cls, crs_value, *args, **kwargs): # type: ignore[no-untyped-def]
8585
"""This is executed whenever CRS('something') is called"""
8686
# pylint: disable=signature-differs
8787
crs_value = cls._parse_crs(crs_value)
@@ -201,7 +201,7 @@ def is_utm(self) -> bool:
201201
"""
202202
return self.name.startswith("UTM")
203203

204-
@functools.lru_cache(maxsize=128) # noqa: B019
204+
@functools.lru_cache(maxsize=128)
205205
def projection(self) -> pyproj.Proj:
206206
"""Returns a projection in form of pyproj class.
207207
@@ -212,7 +212,7 @@ def projection(self) -> pyproj.Proj:
212212
"""
213213
return pyproj.Proj(self._get_pyproj_projection_def(), preserve_units=True)
214214

215-
@functools.lru_cache(maxsize=128) # noqa: B019
215+
@functools.lru_cache(maxsize=128)
216216
def pyproj_crs(self) -> pyproj.CRS:
217217
"""Returns a pyproj CRS class.
218218
@@ -223,7 +223,7 @@ def pyproj_crs(self) -> pyproj.CRS:
223223
"""
224224
return pyproj.CRS(self._get_pyproj_projection_def())
225225

226-
@functools.lru_cache(maxsize=512) # noqa: B019
226+
@functools.lru_cache(maxsize=512)
227227
def get_transform_function(self, other: CRS, always_xy: bool = True) -> Callable[..., tuple]:
228228
"""Returns a function for transforming geometrical objects from one CRS to another. The function will support
229229
transformations between any objects that pyproj supports.

tests/api/batch/test_utils.py

+12-8
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,18 @@ def test_monitor_batch_process_job(
6767
len(tiles) == tile_count for tiles in tiles_sequence
6868
), "There should be the same number of tiles in each step. Fix tile_status_sequence parameter of this test."
6969

70-
batch_request = BatchRequest(
71-
request_id="mocked-request", process_request={}, tile_count=tile_count, status=batch_status
72-
)
70+
batch_kwargs = dict(request_id="mocked-request", process_request={}, tile_count=tile_count)
71+
batch_request = BatchRequest(**batch_kwargs, status=batch_status)
72+
updated_batch_request = BatchRequest(**batch_kwargs, status=BatchRequestStatus.DONE)
73+
7374
monitor_analysis_mock = mocker.patch("sentinelhub.api.batch.utils.monitor_batch_analysis")
7475
monitor_analysis_mock.return_value = batch_request
7576

77+
# keep returning the same batch request until the last step (simulate batch job status update)
78+
progress_loop_counts = len(tile_status_sequence) - 1
79+
batch_request_update_mock = mocker.patch("sentinelhub.SentinelHubBatch.get_request")
80+
batch_request_update_mock.side_effect = progress_loop_counts * [batch_request] + [updated_batch_request]
81+
7682
batch_tiles_mock = mocker.patch("sentinelhub.SentinelHubBatch.iter_tiles")
7783
batch_tiles_mock.side_effect = tiles_sequence
7884

@@ -88,18 +94,16 @@ def test_monitor_batch_process_job(
8894
assert len(results[tile_status]) == tile_status_sequence[-1].get(tile_status, 0)
8995

9096
assert monitor_analysis_mock.call_count == 1
91-
92-
progress_loop_counts = len(tile_status_sequence) - 1
93-
9497
assert batch_tiles_mock.call_count == progress_loop_counts + 1
9598
assert all(call.args == (batch_request,) and call.kwargs == {} for call in batch_tiles_mock.mock_calls)
9699

97-
assert sleep_mock.call_count == progress_loop_counts
100+
additional_calls = 1 if batch_status is BatchRequestStatus.PROCESSING else 0
101+
assert sleep_mock.call_count == progress_loop_counts + additional_calls
98102
assert all(call.args == (sleep_time,) and call.kwargs == {} for call in sleep_mock.mock_calls)
99103

100104
is_processing_logged = batch_status is BatchRequestStatus.PROCESSING
101105
is_failure_logged = BatchTileStatus.FAILED in tile_status_sequence[-1]
102-
assert logging_mock.call_count == int(is_processing_logged) + int(is_failure_logged)
106+
assert logging_mock.call_count == int(is_processing_logged) + int(is_failure_logged) + additional_calls + 1
103107

104108

105109
def _tile_status_counts_to_tiles(tile_status_counts: dict[BatchTileStatus, int]) -> list[dict[str, str]]:

tests/download/test_sentinelhub_client.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,14 @@ def test_session_caching_and_clearing(
5757
client_object: SentinelHubDownloadClient | type[SentinelHubDownloadClient], session: SentinelHubSession
5858
) -> None:
5959
client_object.clear_cache()
60-
assert {} == SentinelHubDownloadClient._CACHED_SESSIONS
60+
assert SentinelHubDownloadClient._CACHED_SESSIONS == {}
6161

6262
client_object.cache_session(session)
6363
assert len(SentinelHubDownloadClient._CACHED_SESSIONS) == 1
6464
assert list(SentinelHubDownloadClient._CACHED_SESSIONS.values()) == [session]
6565

6666
client_object.clear_cache()
67-
assert {} == SentinelHubDownloadClient._CACHED_SESSIONS
67+
assert SentinelHubDownloadClient._CACHED_SESSIONS == {}
6868

6969

7070
@pytest.mark.sh_integration()

0 commit comments

Comments
 (0)