From 22b3fdd29503b8adf982af275ca6020924b68245 Mon Sep 17 00:00:00 2001 From: Jake Herrmann Date: Thu, 11 Dec 2025 13:32:17 -0900 Subject: [PATCH 01/11] update HyP3.update_jobs to use the new PATCH /jobs endpoint --- src/hyp3_sdk/hyp3.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/hyp3_sdk/hyp3.py b/src/hyp3_sdk/hyp3.py index 5d8253d..70141f4 100644 --- a/src/hyp3_sdk/hyp3.py +++ b/src/hyp3_sdk/hyp3.py @@ -709,6 +709,9 @@ def costs(self) -> dict: _raise_for_hyp3_status(response) return response.json() + # TODO: + # - need to return anything? + # - update tests def update_jobs(self, jobs: Batch | Job, **kwargs: object) -> Batch | Job: """Update the name of one or more previously-submitted jobs. @@ -720,16 +723,15 @@ def update_jobs(self, jobs: Batch | Job, **kwargs: object) -> Batch | Job: Returns: The updated job(s) """ - if isinstance(jobs, Batch): - batch = hyp3_sdk.Batch() - tqdm = hyp3_sdk.util.get_tqdm_progress_bar() - for job in tqdm(jobs): - batch += self.update_jobs(job, **kwargs) - return batch - - if not isinstance(jobs, Job): + if isinstance(jobs, Job): + job_ids = [jobs.job_id] + elif isinstance(jobs, Batch): + job_ids = [job.job_id for job in jobs] + else: raise TypeError(f"'jobs' has type {type(jobs)}, must be {Batch} or {Job}") - response = self.session.patch(self._get_endpoint_url(f'/jobs/{jobs.job_id}'), json=kwargs) - _raise_for_hyp3_status(response) - return Job.from_dict(response.json()) + tqdm = hyp3_sdk.util.get_tqdm_progress_bar() + for job_ids_chunk in tqdm(hyp3_sdk.util.chunk(job_ids, n=100)): + payload = {'job_ids': job_ids_chunk, **kwargs} + response = self.session.patch(self._get_endpoint_url('/jobs'), json=payload) + _raise_for_hyp3_status(response) From d7fd576b218535b0f9f23ed4d5085bb382cb2fbe Mon Sep 17 00:00:00 2001 From: Jake Herrmann Date: Mon, 15 Dec 2025 11:04:06 -0900 Subject: [PATCH 02/11] finish update_jobs implementation --- src/hyp3_sdk/hyp3.py | 42 +++++++++++++++++++++++++++--------------- src/hyp3_sdk/util.py | 3 ++- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/hyp3_sdk/hyp3.py b/src/hyp3_sdk/hyp3.py index 70141f4..37c23f3 100644 --- a/src/hyp3_sdk/hyp3.py +++ b/src/hyp3_sdk/hyp3.py @@ -1,16 +1,16 @@ import math import time import warnings +from copy import deepcopy from datetime import datetime, timezone from functools import singledispatchmethod from getpass import getpass from typing import Literal from urllib.parse import SplitResult, urlsplit, urlunsplit -from warnings import warn import hyp3_sdk import hyp3_sdk.util -from hyp3_sdk.exceptions import HyP3Error, _raise_for_hyp3_status +from hyp3_sdk.exceptions import HyP3Error, HyP3SDKError, _raise_for_hyp3_status from hyp3_sdk.jobs import Batch, Job @@ -693,7 +693,7 @@ def check_quota(self) -> float | int | None: Returns: Your remaining processing credits, or None if you have no processing limit """ - warn( + warnings.warn( 'This method is deprecated and will be removed in a future release.\n' 'Please use `HyP3.check_credits` instead.', DeprecationWarning, @@ -710,28 +710,40 @@ def costs(self) -> dict: return response.json() # TODO: - # - need to return anything? # - update tests - def update_jobs(self, jobs: Batch | Job, **kwargs: object) -> Batch | Job: + def update_jobs(self, jobs: Batch | Job, name: str | None) -> Batch | Job: """Update the name of one or more previously-submitted jobs. Args: jobs: The job(s) to update - kwargs: - name: The new name, or None to remove the name + name: The new name, or None to remove the name Returns: The updated job(s) """ - if isinstance(jobs, Job): - job_ids = [jobs.job_id] - elif isinstance(jobs, Batch): - job_ids = [job.job_id for job in jobs] - else: + if not isinstance(jobs, Job) and not isinstance(jobs, Batch): raise TypeError(f"'jobs' has type {type(jobs)}, must be {Batch} or {Job}") + jobs = deepcopy(jobs) + tqdm = hyp3_sdk.util.get_tqdm_progress_bar() - for job_ids_chunk in tqdm(hyp3_sdk.util.chunk(job_ids, n=100)): - payload = {'job_ids': job_ids_chunk, **kwargs} + batch = jobs if isinstance(jobs, Batch) else Batch([jobs]) + for jobs_chunk in tqdm(hyp3_sdk.util.chunk(batch, n=100)): + job_ids = [job.job_id for job in jobs_chunk] + payload = {'job_ids': job_ids, 'name': name} response = self.session.patch(self._get_endpoint_url('/jobs'), json=payload) - _raise_for_hyp3_status(response) + try: + _raise_for_hyp3_status(response) + except HyP3SDKError as e: + warnings.warn( + 'Something went wrong while updating your jobs. ' + 'The local state of your jobs may be out-of-date. ' + 'Please contact us if you need help resolving this issue: ' + 'https://hyp3-docs.asf.alaska.edu/contact/', + UserWarning, + ) + raise e + for job in jobs_chunk: + job.name = name + + return jobs diff --git a/src/hyp3_sdk/util.py b/src/hyp3_sdk/util.py index b7bb512..d4c057f 100644 --- a/src/hyp3_sdk/util.py +++ b/src/hyp3_sdk/util.py @@ -10,6 +10,7 @@ from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry +from hyp3_sdk import Batch from hyp3_sdk.exceptions import AuthenticationError @@ -44,7 +45,7 @@ def extract_zipped_product(zip_file: str | Path, delete: bool = True) -> Path: return zip_file.parent / zip_file.stem -def chunk(itr: Sequence[Any], n: int = 200) -> Generator[Sequence[Any], None, None]: +def chunk(itr: Sequence[Any] | Batch, n: int = 200) -> Generator[Sequence[Any], None, None]: """Split a sequence into small chunks Args: From 919e63139d0232b4615714bc1b74e9e41ce843c1 Mon Sep 17 00:00:00 2001 From: Jake Herrmann Date: Mon, 15 Dec 2025 14:56:09 -0900 Subject: [PATCH 03/11] error message --- src/hyp3_sdk/hyp3.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/hyp3_sdk/hyp3.py b/src/hyp3_sdk/hyp3.py index 37c23f3..5ffb1e6 100644 --- a/src/hyp3_sdk/hyp3.py +++ b/src/hyp3_sdk/hyp3.py @@ -735,11 +735,12 @@ def update_jobs(self, jobs: Batch | Job, name: str | None) -> Batch | Job: try: _raise_for_hyp3_status(response) except HyP3SDKError as e: + # TODO: check formatting in terminal warnings.warn( 'Something went wrong while updating your jobs. ' 'The local state of your jobs may be out-of-date. ' - 'Please contact us if you need help resolving this issue: ' - 'https://hyp3-docs.asf.alaska.edu/contact/', + 'You can refresh your jobs with the HyP3.refresh method, e.g: ' + 'jobs = hyp3.refresh(jobs)', UserWarning, ) raise e From d033c3c2bb4d8c94dc13183582f8ef281170705b Mon Sep 17 00:00:00 2001 From: Jake Herrmann Date: Tue, 16 Dec 2025 09:33:23 -0900 Subject: [PATCH 04/11] make Batch a Sequence --- src/hyp3_sdk/jobs.py | 5 +++-- src/hyp3_sdk/util.py | 3 +-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hyp3_sdk/jobs.py b/src/hyp3_sdk/jobs.py index 0d63e74..75628a3 100644 --- a/src/hyp3_sdk/jobs.py +++ b/src/hyp3_sdk/jobs.py @@ -1,4 +1,5 @@ from collections import Counter +from collections.abc import Sequence from datetime import datetime from pathlib import Path from typing import Union @@ -150,7 +151,7 @@ def download_files(self, location: Path | str = '.', create: bool = True) -> lis return downloaded_files -class Batch: +class Batch(Sequence): def __init__(self, jobs: list[Job] | None = None): if jobs is None: jobs = [] @@ -179,7 +180,7 @@ def __iter__(self): def __len__(self): return len(self.jobs) - def __contains__(self, job: Job): + def __contains__(self, job: object): return job in self.jobs def __eq__(self, other: object) -> bool: diff --git a/src/hyp3_sdk/util.py b/src/hyp3_sdk/util.py index d4c057f..b7bb512 100644 --- a/src/hyp3_sdk/util.py +++ b/src/hyp3_sdk/util.py @@ -10,7 +10,6 @@ from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry -from hyp3_sdk import Batch from hyp3_sdk.exceptions import AuthenticationError @@ -45,7 +44,7 @@ def extract_zipped_product(zip_file: str | Path, delete: bool = True) -> Path: return zip_file.parent / zip_file.stem -def chunk(itr: Sequence[Any] | Batch, n: int = 200) -> Generator[Sequence[Any], None, None]: +def chunk(itr: Sequence[Any], n: int = 200) -> Generator[Sequence[Any], None, None]: """Split a sequence into small chunks Args: From eaf99d8a378e7d94f2686bf24520c4bcc94a1dad Mon Sep 17 00:00:00 2001 From: Jake Herrmann Date: Tue, 16 Dec 2025 14:12:02 -0900 Subject: [PATCH 05/11] fix tqdm progress bar --- src/hyp3_sdk/hyp3.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/hyp3_sdk/hyp3.py b/src/hyp3_sdk/hyp3.py index 5ffb1e6..dea6530 100644 --- a/src/hyp3_sdk/hyp3.py +++ b/src/hyp3_sdk/hyp3.py @@ -728,14 +728,13 @@ def update_jobs(self, jobs: Batch | Job, name: str | None) -> Batch | Job: tqdm = hyp3_sdk.util.get_tqdm_progress_bar() batch = jobs if isinstance(jobs, Batch) else Batch([jobs]) - for jobs_chunk in tqdm(hyp3_sdk.util.chunk(batch, n=100)): + for jobs_chunk in tqdm(list(hyp3_sdk.util.chunk(batch, n=100))): job_ids = [job.job_id for job in jobs_chunk] payload = {'job_ids': job_ids, 'name': name} response = self.session.patch(self._get_endpoint_url('/jobs'), json=payload) try: _raise_for_hyp3_status(response) except HyP3SDKError as e: - # TODO: check formatting in terminal warnings.warn( 'Something went wrong while updating your jobs. ' 'The local state of your jobs may be out-of-date. ' From c578b70ff3f27145f1bbe73b1bda5e98e1ee330d Mon Sep 17 00:00:00 2001 From: Jake Herrmann Date: Tue, 16 Dec 2025 15:07:49 -0900 Subject: [PATCH 06/11] update test_update_jobs, refactor update_jobs --- src/hyp3_sdk/hyp3.py | 10 +++---- tests/test_hyp3.py | 62 +++++++++++++++++++------------------------- 2 files changed, 32 insertions(+), 40 deletions(-) diff --git a/src/hyp3_sdk/hyp3.py b/src/hyp3_sdk/hyp3.py index dea6530..213a7bb 100644 --- a/src/hyp3_sdk/hyp3.py +++ b/src/hyp3_sdk/hyp3.py @@ -725,12 +725,11 @@ def update_jobs(self, jobs: Batch | Job, name: str | None) -> Batch | Job: raise TypeError(f"'jobs' has type {type(jobs)}, must be {Batch} or {Job}") jobs = deepcopy(jobs) + batch = jobs if isinstance(jobs, Batch) else Batch([jobs]) tqdm = hyp3_sdk.util.get_tqdm_progress_bar() - batch = jobs if isinstance(jobs, Batch) else Batch([jobs]) for jobs_chunk in tqdm(list(hyp3_sdk.util.chunk(batch, n=100))): - job_ids = [job.job_id for job in jobs_chunk] - payload = {'job_ids': job_ids, 'name': name} + payload = {'job_ids': [job.job_id for job in jobs_chunk], 'name': name} response = self.session.patch(self._get_endpoint_url('/jobs'), json=payload) try: _raise_for_hyp3_status(response) @@ -743,7 +742,8 @@ def update_jobs(self, jobs: Batch | Job, name: str | None) -> Batch | Job: UserWarning, ) raise e - for job in jobs_chunk: - job.name = name + + for job in batch: + job.name = name return jobs diff --git a/tests/test_hyp3.py b/tests/test_hyp3.py index 87bbcd1..e5c0735 100644 --- a/tests/test_hyp3.py +++ b/tests/test_hyp3.py @@ -529,56 +529,48 @@ def test_costs(get_mock_hyp3): @responses.activate def test_update_jobs(get_mock_hyp3, get_mock_job): api = get_mock_hyp3() - job1_api_response = { - 'job_id': 'job1', - 'job_type': 'FOO', - 'request_time': '2020-06-04T18:00:03+00:00', - 'status_code': 'SUCCEEDED', - 'user_id': 'foo', - 'name': 'new_name', - } - job2_api_response = { - 'job_id': 'job2', - 'job_type': 'FOO', - 'request_time': '2020-06-04T18:00:03+00:00', - 'status_code': 'SUCCEEDED', - 'user_id': 'foo', - 'name': 'new_name', - } + responses.add( responses.PATCH, - urljoin(api.url, '/jobs/job1'), - match=[responses.matchers.json_params_matcher({'name': 'new_name'})], - json=job1_api_response, + urljoin(api.url, '/jobs'), + match=[responses.matchers.json_params_matcher({'job_ids': ['job1'], 'name': 'new'})], ) + job = get_mock_job(job_id='job1', name='old') + + assert api.update_jobs(job, name='new') == get_mock_job(job_id='job1', name='new') + assert job.name == 'old' + responses.add( responses.PATCH, - urljoin(api.url, '/jobs/job2'), - match=[responses.matchers.json_params_matcher({'name': 'new_name'})], - json=job2_api_response, + urljoin(api.url, '/jobs'), + match=[responses.matchers.json_params_matcher({'job_ids': [str(i) for i in range(100)], 'name': 'new'})], ) responses.add( responses.PATCH, - urljoin(api.url, '/jobs/job1'), - match=[responses.matchers.json_params_matcher({'foo': 'bar'})], - json={'detail': 'test error message'}, - status=400, + urljoin(api.url, '/jobs'), + match=[responses.matchers.json_params_matcher({'job_ids': [str(i) for i in range(100, 200)], 'name': 'new'})], ) + jobs = Batch([get_mock_job(job_id=str(i), name='old') for i in range(200)]) - job1 = get_mock_job(job_id='job1') - job2 = get_mock_job(job_id='job2') + assert api.update_jobs(jobs, name='new') == Batch([get_mock_job(job_id=str(i), name='new') for i in range(200)]) + assert {job.name for job in jobs} == {'old'} - assert api.update_jobs(job1, name='new_name') == Job.from_dict(job1_api_response) + with pytest.raises(TypeError): + api.update_jobs(1, name='new') - assert api.update_jobs(Batch([job1, job2]), name='new_name') == Batch( - [Job.from_dict(job1_api_response), Job.from_dict(job2_api_response)] + responses.add( + responses.PATCH, + urljoin(api.url, '/jobs'), + match=[responses.matchers.json_params_matcher({'job_ids': ['bad-job'], 'name': 'new'})], + json={'detail': 'job does not exist'}, + status=404, ) + bad_job = get_mock_job(job_id='bad-job', name='old') - with pytest.raises(TypeError): - api.update_jobs(1, name='new_name') + with pytest.raises(HyP3Error, match=r'^ job does not exist$'): + api.update_jobs(bad_job, name='new') - with pytest.raises(HyP3Error, match=r'^ test error message$'): - api.update_jobs(job1, foo='bar') + assert bad_job.name == 'old' def test_get_endpoint_url(get_mock_hyp3): From 464027dbf17b5057dd36f082aaf023331526def8 Mon Sep 17 00:00:00 2001 From: Jake Herrmann Date: Tue, 16 Dec 2025 15:30:42 -0900 Subject: [PATCH 07/11] changelog, remove todo --- CHANGELOG.md | 16 ++++++++++++++++ src/hyp3_sdk/hyp3.py | 2 -- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a09f5ba..80893a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [PEP 440](https://www.python.org/dev/peps/pep-0440/) and uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [7.7.6] + +### Changed +* The implementation of `HyP3.update_jobs` has been refactored to use the new `PATCH /jobs` endpoint that was added with [HyP3 v10.12.0](https://github.com/ASFHyP3/hyp3/releases/tag/v10.12.0), resulting in a significant performance improvement when renaming large batches of jobs. + + > [!WARNING] + > If one of your jobs fails to update for any reason, all of the jobs in the `Batch` that were updated before the failure will have the new name, while all of the remaining jobs will be left with the old name. Additionally, because `HyP3.update_jobs` returns a new copy of your updated jobs rather than updating them in-place, your local copy of the jobs will be out-of-date compared with HyP3's record of your jobs. You can refresh your jobs with the `HyP3.refresh` method, e.g: + > ```python + > >>> jobs = hyp3.refresh(jobs) + > ``` + +* `HyP3.update_jobs` now requires the `name` parameter and no longer accepts arbitrary keyword arguments. + +### Fixed +* `Batch` is now a subclass of `collections.abc.Sequence`, which allows `hyp3_sdk.util.chunk` to accept a `Batch` object without triggering warnings from static type checkers such as `mypy`. + ## [7.7.5] ### Changed diff --git a/src/hyp3_sdk/hyp3.py b/src/hyp3_sdk/hyp3.py index 213a7bb..2a13f04 100644 --- a/src/hyp3_sdk/hyp3.py +++ b/src/hyp3_sdk/hyp3.py @@ -709,8 +709,6 @@ def costs(self) -> dict: _raise_for_hyp3_status(response) return response.json() - # TODO: - # - update tests def update_jobs(self, jobs: Batch | Job, name: str | None) -> Batch | Job: """Update the name of one or more previously-submitted jobs. From 46e53216fe282c44ca24abef1e8c7bb524c52491 Mon Sep 17 00:00:00 2001 From: Jake Herrmann Date: Tue, 16 Dec 2025 15:33:31 -0900 Subject: [PATCH 08/11] fix markdown --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80893a9..ed42ac2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,9 +13,9 @@ and uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html). > [!WARNING] > If one of your jobs fails to update for any reason, all of the jobs in the `Batch` that were updated before the failure will have the new name, while all of the remaining jobs will be left with the old name. Additionally, because `HyP3.update_jobs` returns a new copy of your updated jobs rather than updating them in-place, your local copy of the jobs will be out-of-date compared with HyP3's record of your jobs. You can refresh your jobs with the `HyP3.refresh` method, e.g: - > ```python - > >>> jobs = hyp3.refresh(jobs) - > ``` + > ```python + > >>> jobs = hyp3.refresh(jobs) + > ``` * `HyP3.update_jobs` now requires the `name` parameter and no longer accepts arbitrary keyword arguments. From 330cc296b175c66e7677f3f10df121c2f1aa7d43 Mon Sep 17 00:00:00 2001 From: Jake Herrmann Date: Tue, 16 Dec 2025 15:34:21 -0900 Subject: [PATCH 09/11] try to fix markdown again --- CHANGELOG.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed42ac2..42e6cdf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,11 +11,11 @@ and uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Changed * The implementation of `HyP3.update_jobs` has been refactored to use the new `PATCH /jobs` endpoint that was added with [HyP3 v10.12.0](https://github.com/ASFHyP3/hyp3/releases/tag/v10.12.0), resulting in a significant performance improvement when renaming large batches of jobs. - > [!WARNING] - > If one of your jobs fails to update for any reason, all of the jobs in the `Batch` that were updated before the failure will have the new name, while all of the remaining jobs will be left with the old name. Additionally, because `HyP3.update_jobs` returns a new copy of your updated jobs rather than updating them in-place, your local copy of the jobs will be out-of-date compared with HyP3's record of your jobs. You can refresh your jobs with the `HyP3.refresh` method, e.g: - > ```python - > >>> jobs = hyp3.refresh(jobs) - > ``` +> [!WARNING] +> If one of your jobs fails to update for any reason, all of the jobs in the `Batch` that were updated before the failure will have the new name, while all of the remaining jobs will be left with the old name. Additionally, because `HyP3.update_jobs` returns a new copy of your updated jobs rather than updating them in-place, your local copy of the jobs will be out-of-date compared with HyP3's record of your jobs. You can refresh your jobs with the `HyP3.refresh` method, e.g: +> ```python +> >>> jobs = hyp3.refresh(jobs) +> ``` * `HyP3.update_jobs` now requires the `name` parameter and no longer accepts arbitrary keyword arguments. From af9cbefe4ac93bdcb3411e8da3d6a7ab249df6d8 Mon Sep 17 00:00:00 2001 From: Jake Herrmann Date: Tue, 16 Dec 2025 15:36:00 -0900 Subject: [PATCH 10/11] rearrange changelog entry --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42e6cdf..77b4e07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Changed * The implementation of `HyP3.update_jobs` has been refactored to use the new `PATCH /jobs` endpoint that was added with [HyP3 v10.12.0](https://github.com/ASFHyP3/hyp3/releases/tag/v10.12.0), resulting in a significant performance improvement when renaming large batches of jobs. +* `HyP3.update_jobs` now requires the `name` parameter and no longer accepts arbitrary keyword arguments. > [!WARNING] > If one of your jobs fails to update for any reason, all of the jobs in the `Batch` that were updated before the failure will have the new name, while all of the remaining jobs will be left with the old name. Additionally, because `HyP3.update_jobs` returns a new copy of your updated jobs rather than updating them in-place, your local copy of the jobs will be out-of-date compared with HyP3's record of your jobs. You can refresh your jobs with the `HyP3.refresh` method, e.g: @@ -17,8 +18,6 @@ and uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html). > >>> jobs = hyp3.refresh(jobs) > ``` -* `HyP3.update_jobs` now requires the `name` parameter and no longer accepts arbitrary keyword arguments. - ### Fixed * `Batch` is now a subclass of `collections.abc.Sequence`, which allows `hyp3_sdk.util.chunk` to accept a `Batch` object without triggering warnings from static type checkers such as `mypy`. From 40c8c349ab8cfa88364b12646618b3530c13ff41 Mon Sep 17 00:00:00 2001 From: Jake Herrmann Date: Tue, 16 Dec 2025 15:42:00 -0900 Subject: [PATCH 11/11] revise changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77b4e07..32ce2f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ and uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html). * `HyP3.update_jobs` now requires the `name` parameter and no longer accepts arbitrary keyword arguments. > [!WARNING] -> If one of your jobs fails to update for any reason, all of the jobs in the `Batch` that were updated before the failure will have the new name, while all of the remaining jobs will be left with the old name. Additionally, because `HyP3.update_jobs` returns a new copy of your updated jobs rather than updating them in-place, your local copy of the jobs will be out-of-date compared with HyP3's record of your jobs. You can refresh your jobs with the `HyP3.refresh` method, e.g: +> If one of your jobs fails to update for any reason, `HyP3.update_jobs` will raise an exception and all of the jobs that were updated before the failure will have the new name, while all of the remaining jobs will be left with the old name. Additionally, because `HyP3.update_jobs` returns a new copy of your updated jobs rather than updating them in-place, you will need to manually refresh your local copy of the jobs if you want to see which jobs were successfully updated. You can refresh your jobs with the `HyP3.refresh` method, e.g: > ```python > >>> jobs = hyp3.refresh(jobs) > ```