From 64844fb19c22d030aa510d5e4b2a132dcc2162a5 Mon Sep 17 00:00:00 2001 From: Matthew Davis Date: Mon, 25 May 2026 11:29:35 +1000 Subject: [PATCH 1/2] Reject raw_data_location=None with a clear UserInputError MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cherry-picked source change from #67 (commit 7e71e73). The companion tests/test_00_test_setup.py from the original commit is dropped — it asserted that defaults.raw_data_cache is set, which PR #72 made obsolete when the suite switched to fixture-scoped temp directories via nemosis_fixture. Without this check, passing raw_data_location=None falls through to os.path.isdir(None) and raises TypeError from inside the stdlib, with a message that doesn't mention the parameter. UserInputError is the contract for caller-input mistakes, and the message now names the parameter. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/nemosis/data_fetch_methods.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/nemosis/data_fetch_methods.py b/src/nemosis/data_fetch_methods.py index 8e06a67..3e6604c 100644 --- a/src/nemosis/data_fetch_methods.py +++ b/src/nemosis/data_fetch_methods.py @@ -63,6 +63,10 @@ def dynamic_data_compiler( Returns: all_data (pd.Dataframe): All data concatenated. """ + + if raw_data_location is None: + raise UserInputError("The raw_data_location provided is None.") + if not _os.path.isdir(raw_data_location): raise UserInputError("The raw_data_location provided does not exist.") @@ -186,6 +190,10 @@ def cache_compiler( Returns: Nothing """ + + if raw_data_location is None: + raise UserInputError("The raw_data_location provided is None.") + if not _os.path.isdir(raw_data_location): raise UserInputError("The raw_data_location provided does not exist.") From cd3a9089318692847c81ee4520ef09459b8f64cd Mon Sep 17 00:00:00 2001 From: nick-gorman Date: Mon, 25 May 2026 11:31:02 +1000 Subject: [PATCH 2/2] Extend None-check to static_table and add regression tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apply the same UserInputError("...is None") guard to static_table that the previous commit added to dynamic_data_compiler and cache_compiler. The original cherry-picked work (PR #67) didn't cover static_table, but it has the same `_os.path.isdir(raw_data_location)` line and the same TypeError-from-stdlib UX flaw on None input. Add three regression tests to tests/test_errors.py — one per public entrypoint — locking in the contract that None raises UserInputError with a message naming the parameter. The tests don't take the nemosis_fixture parameter because the None check fires before any disk or network access. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/nemosis/data_fetch_methods.py | 3 +++ tests/test_errors.py | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/nemosis/data_fetch_methods.py b/src/nemosis/data_fetch_methods.py index 3e6604c..008b07f 100644 --- a/src/nemosis/data_fetch_methods.py +++ b/src/nemosis/data_fetch_methods.py @@ -270,6 +270,9 @@ def static_table( Returns: data (pd.Dataframe) """ + if raw_data_location is None: + raise UserInputError("The raw_data_location provided is None.") + if not _os.path.isdir(raw_data_location): raise UserInputError("The raw_data_location provided does not exist.") diff --git a/tests/test_errors.py b/tests/test_errors.py index f2b6bdb..ca44d43 100644 --- a/tests/test_errors.py +++ b/tests/test_errors.py @@ -71,6 +71,17 @@ def test_dynamic_select_columns_all_requires_csv(nemosis_fixture): ) +def test_dynamic_raw_data_location_is_none(): + """Passing None as the cache path is a common caller mistake (forgot + to set it, config returned None). Reject with UserInputError rather + than the cryptic TypeError that os.path.isdir(None) would raise.""" + with pytest.raises(UserInputError, match="is None"): + dynamic_data_compiler( + "2018/05/01 00:00:00", "2018/05/01 01:00:00", + "DISPATCHPRICE", raw_data_location=None, + ) + + # --------------------------------------------------------------------------- # Argument-validation: cache_compiler # --------------------------------------------------------------------------- @@ -102,6 +113,14 @@ def test_cache_select_columns_requires_rebuild(nemosis_fixture): ) +def test_cache_raw_data_location_is_none(): + with pytest.raises(UserInputError, match="is None"): + cache_compiler( + "2018/05/01 00:00:00", "2018/05/01 01:00:00", + "DISPATCHPRICE", raw_data_location=None, + ) + + # --------------------------------------------------------------------------- # Argument-validation: static_table # --------------------------------------------------------------------------- @@ -121,6 +140,11 @@ def test_static_filter_col_not_in_select_columns(nemosis_fixture): ) +def test_static_raw_data_location_is_none(): + with pytest.raises(UserInputError, match="is None"): + static_table("VARIABLES_FCAS_4_SECOND", raw_data_location=None) + + # --------------------------------------------------------------------------- # Network / availability: NoDataToReturn # ---------------------------------------------------------------------------