From a1c5567a6477ba1351875dd60fe4bcbe07af0102 Mon Sep 17 00:00:00 2001 From: Nouhayla BAHADDOU Date: Mon, 29 Jun 2026 15:17:50 +0200 Subject: [PATCH 1/7] fix:add utc=true to datetime --- resourcecode/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resourcecode/client.py b/resourcecode/client.py index 81f26fd..e3acbba 100644 --- a/resourcecode/client.py +++ b/resourcecode/client.py @@ -276,7 +276,7 @@ def get_dataframe_from_criteria(self, criteria: Union[str, dict]) -> pd.DataFram return pd.DataFrame( result_array[:, 1:], columns=parsed_criteria["parameter"], - index=pd.to_datetime(index_array.astype(np.int64), unit="ms"), + index=pd.to_datetime(index_array.astype(np.int64), unit="ms",utc= True), ) def _get_rawdata_from_criteria(self, single_parameter_criteria): From e7aca6c932fa62fc55e9c9500e64e4277f2e0df2 Mon Sep 17 00:00:00 2001 From: Nouhayla BAHADDOU Date: Mon, 29 Jun 2026 15:33:31 +0200 Subject: [PATCH 2/7] fix:indentation --- resourcecode/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resourcecode/client.py b/resourcecode/client.py index e3acbba..f22dc31 100644 --- a/resourcecode/client.py +++ b/resourcecode/client.py @@ -276,7 +276,7 @@ def get_dataframe_from_criteria(self, criteria: Union[str, dict]) -> pd.DataFram return pd.DataFrame( result_array[:, 1:], columns=parsed_criteria["parameter"], - index=pd.to_datetime(index_array.astype(np.int64), unit="ms",utc= True), + index=pd.to_datetime(index_array.astype(np.int64), unit="ms", utc=True), ) def _get_rawdata_from_criteria(self, single_parameter_criteria): From b60f124d0cb41e618092d475fe3c14edd94c86af Mon Sep 17 00:00:00 2001 From: Nicolas Raillard Date: Mon, 29 Jun 2026 15:50:44 +0200 Subject: [PATCH 3/7] Fix: add UTC index in tests --- .gitignore | 6 +++++- resourcecode/client.py | 2 +- tests/test_client.py | 30 ++++++++++++++++++------------ 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index d40efb6..4fe7888 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,8 @@ uv.lock .venv/ # Jupyter checkpoints -**/.ipynb_checkpoints/ \ No newline at end of file +**/.ipynb_checkpoints/ + +/resourcecode/__pycache__ +/resourcecode/*/__pycache__ +*/__pycache__ diff --git a/resourcecode/client.py b/resourcecode/client.py index e3acbba..f22dc31 100644 --- a/resourcecode/client.py +++ b/resourcecode/client.py @@ -276,7 +276,7 @@ def get_dataframe_from_criteria(self, criteria: Union[str, dict]) -> pd.DataFram return pd.DataFrame( result_array[:, 1:], columns=parsed_criteria["parameter"], - index=pd.to_datetime(index_array.astype(np.int64), unit="ms",utc= True), + index=pd.to_datetime(index_array.astype(np.int64), unit="ms", utc=True), ) def _get_rawdata_from_criteria(self, single_parameter_criteria): diff --git a/tests/test_client.py b/tests/test_client.py index 901f74a..e3470a7 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -60,7 +60,9 @@ def mock_requests_get_raw_data(query_url, parameters): for date, value in data["result"]["data"]: # start_date and end_date must be multiplied by 1e3, because # cassandra returns milliseconds - if date is not None and (start_date is not None and date < start_date * 1e3): + if date is not None and ( + start_date is not None and date < start_date * 1e3 + ): continue if date and end_date is not None and date > end_date * 1e3: @@ -137,7 +139,9 @@ def test_get_raw_data(): parameter = "fp" client = resourcecode.Client() - with mock.patch("requests.get", side_effect=mock_requests_get_raw_data) as mock_requests_get: + with mock.patch( + "requests.get", side_effect=mock_requests_get_raw_data + ) as mock_requests_get: json_data = client._get_rawdata_from_criteria( { "parameter": [ @@ -146,7 +150,9 @@ def test_get_raw_data(): } ) - mock_requests_get.assert_called_once_with(client.cassandra_base_url + "api/timeseries", {"parameter": [parameter]}) + mock_requests_get.assert_called_once_with( + client.cassandra_base_url + "api/timeseries", {"parameter": [parameter]} + ) assert json_data["query"]["parameterCode"] == parameter dataset_size = json_data["result"]["dataSetSize"] @@ -158,8 +164,8 @@ def test_get_criteria_single_parameter(client): assert len(data) == 744 assert (data.columns == ["fp"]).all() - assert data.index[0] == pd.to_datetime("2017-01-01 00:00:00") - assert data.index[-1] == pd.to_datetime("2017-01-31 23:00:00") + assert data.index[0] == pd.to_datetime("2017-01-01 00:00:00", utc=True) + assert data.index[-1] == pd.to_datetime("2017-01-31 23:00:00", utc=True) assert data.fp[0] == pytest.approx(0.074) assert data.fp[-1] == pytest.approx(0.097) @@ -169,8 +175,8 @@ def test_get_criteria_single_tp_parameter(client): assert len(data) == 744 assert (data.columns == ["tp"]).all() - assert data.index[0] == pd.to_datetime("2017-01-01 00:00:00") - assert data.index[-1] == pd.to_datetime("2017-01-31 23:00:00") + assert data.index[0] == pd.to_datetime("2017-01-01 00:00:00", utc=True) + assert data.index[-1] == pd.to_datetime("2017-01-31 23:00:00", utc=True) assert data.tp[0] == pytest.approx(13.51351) assert data.tp[-1] == pytest.approx(10.30928) @@ -180,8 +186,8 @@ def test_get_criteria_multiple_parameters(client): assert len(data) == 744 assert (data.columns == ["fp", "hs"]).all() - assert data.index[0] == pd.to_datetime("2017-01-01 00:00:00") - assert data.index[-1] == pd.to_datetime("2017-01-31 23:00:00") + assert data.index[0] == pd.to_datetime("2017-01-01 00:00:00", utc=True) + assert data.index[-1] == pd.to_datetime("2017-01-31 23:00:00", utc=True) assert data.fp[0] == pytest.approx(0.074) assert data.fp[-1] == pytest.approx(0.097) assert data.hs[0] == pytest.approx(0.296) @@ -200,7 +206,7 @@ def test_get_criteria_multiple_parameters_and_none_values(client): assert pd.isnull(data.uust[0]) # the third value is not null. - assert data.index[2] == pd.to_datetime("2017-01-01 02:00:00") + assert data.index[2] == pd.to_datetime("2017-01-01 02:00:00", utc=True) assert data.uust[2] == pytest.approx(0.1699999962) data = client.get_dataframe_from_criteria('{"parameter": ["uust", "fp"]}') @@ -210,8 +216,8 @@ def test_get_criteria_multiple_parameters_and_none_values(client): # in that case, we have two variables. The second one, fp, is not null, # therefore the index can be completed despite that uust is null. - assert data.index[0] == pd.to_datetime("2017-01-01 00:00:00") - assert data.index[-1] == pd.to_datetime("2017-01-31 23:00:00") + assert data.index[0] == pd.to_datetime("2017-01-01 00:00:00", utc=True) + assert data.index[-1] == pd.to_datetime("2017-01-31 23:00:00", utc=True) assert data.fp[0] == pytest.approx(0.074) assert data.fp[-1] == pytest.approx(0.097) From 8de4e13347862279f1b23d81a84778b6960bc2b0 Mon Sep 17 00:00:00 2001 From: Nicolas Raillard Date: Mon, 29 Jun 2026 15:52:58 +0200 Subject: [PATCH 4/7] make lint happier --- tests/test_client.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/tests/test_client.py b/tests/test_client.py index e3470a7..7454f2d 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -60,9 +60,7 @@ def mock_requests_get_raw_data(query_url, parameters): for date, value in data["result"]["data"]: # start_date and end_date must be multiplied by 1e3, because # cassandra returns milliseconds - if date is not None and ( - start_date is not None and date < start_date * 1e3 - ): + if date is not None and (start_date is not None and date < start_date * 1e3): continue if date and end_date is not None and date > end_date * 1e3: @@ -139,9 +137,7 @@ def test_get_raw_data(): parameter = "fp" client = resourcecode.Client() - with mock.patch( - "requests.get", side_effect=mock_requests_get_raw_data - ) as mock_requests_get: + with mock.patch("requests.get", side_effect=mock_requests_get_raw_data) as mock_requests_get: json_data = client._get_rawdata_from_criteria( { "parameter": [ @@ -150,9 +146,7 @@ def test_get_raw_data(): } ) - mock_requests_get.assert_called_once_with( - client.cassandra_base_url + "api/timeseries", {"parameter": [parameter]} - ) + mock_requests_get.assert_called_once_with(client.cassandra_base_url + "api/timeseries", {"parameter": [parameter]}) assert json_data["query"]["parameterCode"] == parameter dataset_size = json_data["result"]["dataSetSize"] From de5f9d5c92e24a66d575cc47e462aa9f5e6f0df8 Mon Sep 17 00:00:00 2001 From: Nicolas Raillard Date: Mon, 29 Jun 2026 16:08:47 +0200 Subject: [PATCH 5/7] Update output in README.md --- .gitignore | 2 ++ README.md | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 4fe7888..00ad909 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ uv.lock /resourcecode/__pycache__ /resourcecode/*/__pycache__ */__pycache__ +/build +/resourcecode.egg-info diff --git a/README.md b/README.md index acd6e9b..5f123ba 100644 --- a/README.md +++ b/README.md @@ -85,18 +85,18 @@ See the following example: ... """) >>> data - fp hs -2017-01-01 00:00:00 0.412 0.246 -2017-01-01 01:00:00 0.410 0.212 -2017-01-01 02:00:00 0.414 0.172 -2017-01-01 03:00:00 0.437 0.138 -2017-01-01 04:00:00 0.464 0.102 -... ... ... -2017-03-19 02:00:00 0.088 0.056 -2017-03-19 03:00:00 0.088 0.066 -2017-03-19 04:00:00 0.089 0.078 -2017-03-19 05:00:00 0.090 0.084 -2017-03-19 06:00:00 0.732 0.086 + fp hs +2017-01-01 00:00:00+00:00 0.412 0.246 +2017-01-01 01:00:00+00:00 0.410 0.212 +2017-01-01 02:00:00+00:00 0.414 0.172 +2017-01-01 03:00:00+00:00 0.437 0.138 +2017-01-01 04:00:00+00:00 0.464 0.102 +... ... ... +2017-03-19 02:00:00+00:00 0.088 0.056 +2017-03-19 03:00:00+00:00 0.088 0.066 +2017-03-19 04:00:00+00:00 0.089 0.078 +2017-03-19 05:00:00+00:00 0.090 0.084 +2017-03-19 06:00:00+00:00 0.732 0.086 [1855 rows x 2 columns] From f43a1710d4af9b91994a38fb2b3d900ab3456cd8 Mon Sep 17 00:00:00 2001 From: Nicolas Raillard Date: Mon, 29 Jun 2026 16:39:33 +0200 Subject: [PATCH 6/7] Fix: opsplanning is not timezone aware --- .gitignore | 2 ++ resourcecode/opsplanning/__init__.py | 13 +++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 00ad909..d33fe4e 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,6 @@ uv.lock /resourcecode/*/__pycache__ */__pycache__ /build +/doc +/.doctrees /resourcecode.egg-info diff --git a/resourcecode/opsplanning/__init__.py b/resourcecode/opsplanning/__init__.py index 424b6a8..44460ae 100644 --- a/resourcecode/opsplanning/__init__.py +++ b/resourcecode/opsplanning/__init__.py @@ -156,12 +156,12 @@ def oplen_calc(critsubs, oplen, critical_operation=False, date=1, monstrt=True): Nominal length of the operation (if no downtime), in hours critical_operation : BOOLEAN - False for non-critical operations: - With this flag to False, it is assumed that the operation can be - halted for the duration of weather downtime and started again + With this flag to False, it is assumed that the operation can be + halted for the duration of weather downtime and started again - True is for continuous window search: - In this case operations can't be halted and if stopped due to - weather downtime have to restart from the beginning once the - conditions allow + In this case operations can't be halted and if stopped due to + weather downtime have to restart from the beginning once the + conditions allow The default is non critical operation. date : INT,DATETIME optional @@ -207,6 +207,7 @@ def oplen_calc(critsubs, oplen, critical_operation=False, date=1, monstrt=True): start=dt.datetime(yerng[0], morng[0], 1), end=dt.datetime(yerng[1], morng[1], 1), freq="MS", + tz="utc", ) daterng = daterng.shift(dayval - 1, freq="D") oplendetect = pd.Series(np.zeros(daterng.shape[0], dtype="timedelta64[s]"), index=daterng) @@ -215,7 +216,7 @@ def oplen_calc(critsubs, oplen, critical_operation=False, date=1, monstrt=True): daterng = pd.date_range(start=date, end=date) oplendetect = pd.Series(np.zeros(daterng.shape[0], dtype="timedelta64[s]"), index=daterng) else: - msg = "Variable date in single result calculation should be" " a datetime object" + msg = "Variable date in single result calculation should be a datetime object" raise NameError(msg) else: raise NameError("Input option monstrt should be boolean") From cea1d0abb3b2ff12067225ccbad225b05e28257b Mon Sep 17 00:00:00 2001 From: Nicolas Raillard Date: Mon, 29 Jun 2026 16:50:07 +0200 Subject: [PATCH 7/7] Fix tests in opsplanning --- tests/test_opsplanning.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_opsplanning.py b/tests/test_opsplanning.py index 7c08fa1..22f3483 100644 --- a/tests/test_opsplanning.py +++ b/tests/test_opsplanning.py @@ -34,6 +34,7 @@ def data(): parse_dates=True, dayfirst=True, ) + df = df.tz_localize("UTC") return df