From a9d608e3c26ffcf75e4c00f22e11bd2e57db9ea7 Mon Sep 17 00:00:00 2001 From: Gui-FernandesBR Date: Tue, 3 Nov 2026 13:54:05 -0300 Subject: [PATCH 1/3] TST: write generic surface CSV fixtures to pathlib paths pandas 3 treats py.path.local as a writable buffer and each chunk overwrites the file, leaving only the last row; tmp_path_factory avoids it. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01XDW574AQLHTSeBM9K172TX --- .../generic_surfaces/generic_surfaces_fixtures.py | 10 ++++++---- .../linear_generic_surfaces_fixtures.py | 8 ++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/tests/fixtures/generic_surfaces/generic_surfaces_fixtures.py b/tests/fixtures/generic_surfaces/generic_surfaces_fixtures.py index e3aa869ea..51fd0ad1d 100644 --- a/tests/fixtures/generic_surfaces/generic_surfaces_fixtures.py +++ b/tests/fixtures/generic_surfaces/generic_surfaces_fixtures.py @@ -3,10 +3,12 @@ @pytest.fixture(scope="session") -def filename_valid_coeff(tmpdir_factory): +def filename_valid_coeff(tmp_path_factory): """Creates temporary files used to test if generic surfaces initializes correctly from CSV files""" - filename = tmpdir_factory.mktemp("aero_surface_data").join("valid_coefficients.csv") + filename = tmp_path_factory.mktemp("aero_surface_data").joinpath( + "valid_coefficients.csv" + ) pd.DataFrame( { "alpha": [0, 1, 2, 3, 0.1], @@ -31,10 +33,10 @@ def filename_valid_coeff(tmpdir_factory): }, ) ) -def filename_invalid_coeff(tmpdir_factory, request): +def filename_invalid_coeff(tmp_path_factory, request): """Creates temporary CSV files used to test if generic surfaces raises errors when initialized incorrectly from CSV files""" - filename = tmpdir_factory.mktemp("aero_surface_data").join( + filename = tmp_path_factory.mktemp("aero_surface_data").joinpath( "tmp_invalid_coefficients.csv" ) pd.DataFrame(request.param).to_csv(filename, index=False) diff --git a/tests/fixtures/generic_surfaces/linear_generic_surfaces_fixtures.py b/tests/fixtures/generic_surfaces/linear_generic_surfaces_fixtures.py index 35ab9c1a2..990baf279 100644 --- a/tests/fixtures/generic_surfaces/linear_generic_surfaces_fixtures.py +++ b/tests/fixtures/generic_surfaces/linear_generic_surfaces_fixtures.py @@ -3,10 +3,10 @@ @pytest.fixture(scope="session") -def filename_valid_coeff_linear_generic_surface(tmpdir_factory): +def filename_valid_coeff_linear_generic_surface(tmp_path_factory): """Creates temporary files used to test if a linear generic surface initializes correctly from CSV files""" - filename = tmpdir_factory.mktemp("aero_surface_data").join( + filename = tmp_path_factory.mktemp("aero_surface_data").joinpath( "valid_coefficients_lgs.csv" ) pd.DataFrame( @@ -33,10 +33,10 @@ def filename_valid_coeff_linear_generic_surface(tmpdir_factory): }, ) ) -def filename_invalid_coeff_linear_generic_surface(tmpdir_factory, request): +def filename_invalid_coeff_linear_generic_surface(tmp_path_factory, request): """Creates temporary CSV files used to test if a linear generic surface raises errors when initialized incorrectly from CSV files""" - filename = tmpdir_factory.mktemp("aero_surface_data").join( + filename = tmp_path_factory.mktemp("aero_surface_data").joinpath( "tmp_invalid_coefficients_lgs.csv" ) pd.DataFrame(request.param).to_csv(filename, index=False) From a9c02dc5841f03a0283b87520cab9cc201c80feb Mon Sep 17 00:00:00 2001 From: Gui-FernandesBR Date: Tue, 3 Nov 2026 13:58:19 -0300 Subject: [PATCH 2/3] MNT: silence pylint 4 abstract-method false positives Optional methods that raise NotImplementedError (polations, sensors, plots) are now reported as abstract; also move the broad-exception pragma onto the except line. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01XDW574AQLHTSeBM9K172TX --- .pylintrc | 1 + rocketpy/tools.py | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pylintrc b/.pylintrc index 64e096c20..47da22ed3 100644 --- a/.pylintrc +++ b/.pylintrc @@ -501,6 +501,7 @@ disable=raw-checker-failed, method-cache-max-size-none, no-else-raise, # pointless unnecessary-lambda-assignment, # ruff already checks this + abstract-method, # NotImplementedError marks optional methods (polations, sensors, plots) diff --git a/rocketpy/tools.py b/rocketpy/tools.py index 381f51b00..35d5a4aea 100644 --- a/rocketpy/tools.py +++ b/rocketpy/tools.py @@ -1203,8 +1203,7 @@ def wrapper(*args, **kwargs): for i in range(max_attempts): try: return func(*args, **kwargs) - # pylint: disable=broad-except - except Exception as e: # pragma: no cover + except Exception as e: # pragma: no cover # pylint: disable=broad-exception-caught if i == max_attempts - 1: raise e from None delay = min(delay * 2, max_delay) From e96d0ff4d8dc2d1bdabbfce237075381a4495200 Mon Sep 17 00:00:00 2001 From: Gui-FernandesBR Date: Tue, 3 Nov 2026 14:38:00 -0300 Subject: [PATCH 3/3] BUG: raise RuntimeError when Open-Elevation returns an error payload The API answers {"code": "temporarily_unavailable", ...} without "results", which leaked a KeyError instead of the documented RuntimeError. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01XDW574AQLHTSeBM9K172TX --- rocketpy/environment/fetchers/elevation_fetcher.py | 2 ++ tests/unit/environment/test_fetchers.py | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/rocketpy/environment/fetchers/elevation_fetcher.py b/rocketpy/environment/fetchers/elevation_fetcher.py index c7a379b08..54ab28f30 100644 --- a/rocketpy/environment/fetchers/elevation_fetcher.py +++ b/rocketpy/environment/fetchers/elevation_fetcher.py @@ -39,5 +39,7 @@ def fetch_open_elevation(lat, lon): except ( requests.exceptions.RequestException, requests.exceptions.JSONDecodeError, + KeyError, + IndexError, ) as e: raise RuntimeError("Unable to reach Open-Elevation API servers.") from e diff --git a/tests/unit/environment/test_fetchers.py b/tests/unit/environment/test_fetchers.py index d6c9eb406..225f53e5d 100644 --- a/tests/unit/environment/test_fetchers.py +++ b/tests/unit/environment/test_fetchers.py @@ -501,3 +501,14 @@ def test_resolve_noaa_collection_path_rejects_unknown_model(): """Unknown shortcuts must fail with an actionable ValueError.""" with pytest.raises(ValueError, match="Unknown NOAA model collection"): fetchers.resolve_noaa_collection_path("not-a-model") + + +def test_fetch_open_elevation_error_payload_raises_runtime_error(monkeypatch): + """An error payload (no ``results``) must surface as the documented RuntimeError.""" + payload = {"code": "temporarily_unavailable", "error": "Retry shortly."} + monkeypatch.setattr( + fetchers.requests, "get", lambda *a, **k: _FakeResponse(payload) + ) + monkeypatch.setattr("rocketpy.tools.time.sleep", lambda _: None) + with pytest.raises(RuntimeError, match="Open-Elevation"): + fetchers.fetch_open_elevation(48.858844, 2.294351)