From c054c3d82af40e918fdaf0ebae35376b45f45c5e Mon Sep 17 00:00:00 2001 From: PiotrekB416 Date: Thu, 28 Sep 2023 23:10:00 +0200 Subject: [PATCH 01/13] FIX `date_range` inclusive --- pandas/core/arrays/datetimes.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index b520f9f4a6deb..807962e47cc00 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -494,17 +494,11 @@ def _generate_range( # type: ignore[override] # to overflow and cast to e.g. f8, but if it does we need to cast i8values = i8values.astype("i8") - if start == end: - if not left_inclusive and not right_inclusive: - i8values = i8values[1:-1] - else: - start_i8 = Timestamp(start)._value - end_i8 = Timestamp(end)._value - if not left_inclusive or not right_inclusive: - if not left_inclusive and len(i8values) and i8values[0] == start_i8: - i8values = i8values[1:] - if not right_inclusive and len(i8values) and i8values[-1] == end_i8: - i8values = i8values[:-1] + if not left_inclusive: + i8values = i8values[1:] + + if not right_inclusive: + i8values = i8values[:-1] dt64_values = i8values.view(f"datetime64[{unit}]") dtype = tz_to_dtype(tz, unit=unit) From 5aa1ca5afcf4537d3dd97b951241b4b0b3244999 Mon Sep 17 00:00:00 2001 From: PiotrekB416 Date: Fri, 29 Sep 2023 11:48:25 +0200 Subject: [PATCH 02/13] FIX tests --- pandas/core/arrays/datetimes.py | 13 +++++++ .../indexes/datetimes/test_date_range.py | 38 ++++++++++--------- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 807962e47cc00..9b43a37e71cf6 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -493,6 +493,19 @@ def _generate_range( # type: ignore[override] # 2022-01-09 I (brock) am not sure if it is possible for this # to overflow and cast to e.g. f8, but if it does we need to cast i8values = i8values.astype("i8") + """ + if start == end: + if not left_inclusive or not right_inclusive: + i8values = i8values[1:-1] + else: + start_i8 = Timestamp(start)._value + end_i8 = Timestamp(end)._value + if not left_inclusive or not right_inclusive: + if not left_inclusive and len(i8values): + i8values = i8values[1:] + if not right_inclusive and len(i8values): + i8values = i8values[:-1] + """ if not left_inclusive: i8values = i8values[1:] diff --git a/pandas/tests/indexes/datetimes/test_date_range.py b/pandas/tests/indexes/datetimes/test_date_range.py index b93aee1d988de..ba583039de952 100644 --- a/pandas/tests/indexes/datetimes/test_date_range.py +++ b/pandas/tests/indexes/datetimes/test_date_range.py @@ -51,7 +51,9 @@ def _get_expected_range( left_match = begin_to_match == both_range[0] right_match = end_to_match == both_range[-1] - if inclusive_endpoints == "left" and right_match: + print(begin_to_match, both_range[0], sep='\n') + + """if inclusive_endpoints == "left" and right_match: expected_range = both_range[:-1] elif inclusive_endpoints == "right" and left_match: expected_range = both_range[1:] @@ -63,6 +65,17 @@ def _get_expected_range( expected_range = both_range[1:] elif inclusive_endpoints == "both": expected_range = both_range[:] + else: + expected_range = both_range[:]""" + + if inclusive_endpoints == "left": + expected_range = both_range[:-1] + elif inclusive_endpoints == "right": + expected_range = both_range[1:] + elif inclusive_endpoints == "both": + expected_range = both_range[:] + elif inclusive_endpoints == "neither": + expected_range = both_range[1:-1] else: expected_range = both_range[:] @@ -96,7 +109,7 @@ def test_date_range_timestamp_equiv_explicit_pytz(self): ts = Timestamp("20090415", tz=pytz.timezone("US/Eastern")) assert ts == stamp - @td.skip_if_windows + #@td.skip_if_windowsdate_range inclusive def test_date_range_timestamp_equiv_explicit_dateutil(self): from pandas._libs.tslibs.timezones import dateutil_gettz as gettz @@ -729,18 +742,9 @@ def test_range_closed_boundary(self, inclusive_endpoints_fixture): inclusive=inclusive_endpoints_fixture, ) - expected_right = both_boundary - expected_left = both_boundary - expected_both = both_boundary - - if inclusive_endpoints_fixture == "right": - expected_left = both_boundary[1:] - elif inclusive_endpoints_fixture == "left": - expected_right = both_boundary[:-1] - elif inclusive_endpoints_fixture == "both": - expected_right = both_boundary[1:] - expected_left = both_boundary[:-1] - + expected_right = both_boundary[1:] + expected_left = both_boundary[:-1] + expected_both = both_boundary[:] expected_neither = both_boundary[1:-1] tm.assert_index_equal(right_boundary, expected_right) @@ -808,9 +812,9 @@ def test_range_where_start_equal_end(self, inclusive_endpoints_fixture): ) both_range = date_range(start=start, end=end, freq="D", inclusive="both") - if inclusive_endpoints_fixture == "neither": + if inclusive_endpoints_fixture in ("neither", "left", "right"): expected = both_range[1:-1] - elif inclusive_endpoints_fixture in ("left", "right", "both"): + elif inclusive_endpoints_fixture == "both": expected = both_range[:] tm.assert_index_equal(result, expected) @@ -1076,7 +1080,7 @@ def test_bdays_and_open_boundaries(self, inclusive): bday_start = "2018-07-23" # Monday bday_end = "2018-07-27" # Friday - expected = date_range(bday_start, bday_end, freq="D") + expected = date_range(bday_start, bday_end, freq="D", inclusive=inclusive) tm.assert_index_equal(result, expected) # Note: we do _not_ expect the freqs to match here From 01373497fd16a34b652c71af33117f2714896df3 Mon Sep 17 00:00:00 2001 From: Piotr Bartoszewicz <89194651+PiotrekB416@users.noreply.github.com> Date: Fri, 29 Sep 2023 11:55:44 +0200 Subject: [PATCH 03/13] Update datetimes.py --- pandas/core/arrays/datetimes.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 9b43a37e71cf6..807962e47cc00 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -493,19 +493,6 @@ def _generate_range( # type: ignore[override] # 2022-01-09 I (brock) am not sure if it is possible for this # to overflow and cast to e.g. f8, but if it does we need to cast i8values = i8values.astype("i8") - """ - if start == end: - if not left_inclusive or not right_inclusive: - i8values = i8values[1:-1] - else: - start_i8 = Timestamp(start)._value - end_i8 = Timestamp(end)._value - if not left_inclusive or not right_inclusive: - if not left_inclusive and len(i8values): - i8values = i8values[1:] - if not right_inclusive and len(i8values): - i8values = i8values[:-1] - """ if not left_inclusive: i8values = i8values[1:] From 1edced569dbaef316c936e2608349b64ebfe895a Mon Sep 17 00:00:00 2001 From: PiotrekB416 Date: Fri, 29 Sep 2023 12:49:06 +0200 Subject: [PATCH 04/13] Update test_date_range.py --- .../indexes/datetimes/test_date_range.py | 23 +++---------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/pandas/tests/indexes/datetimes/test_date_range.py b/pandas/tests/indexes/datetimes/test_date_range.py index ba583039de952..fdb2e215277b7 100644 --- a/pandas/tests/indexes/datetimes/test_date_range.py +++ b/pandas/tests/indexes/datetimes/test_date_range.py @@ -48,25 +48,6 @@ def _get_expected_range( inclusive_endpoints, ): """Helper to get expected range from a both inclusive range""" - left_match = begin_to_match == both_range[0] - right_match = end_to_match == both_range[-1] - - print(begin_to_match, both_range[0], sep='\n') - - """if inclusive_endpoints == "left" and right_match: - expected_range = both_range[:-1] - elif inclusive_endpoints == "right" and left_match: - expected_range = both_range[1:] - elif inclusive_endpoints == "neither" and left_match and right_match: - expected_range = both_range[1:-1] - elif inclusive_endpoints == "neither" and right_match: - expected_range = both_range[:-1] - elif inclusive_endpoints == "neither" and left_match: - expected_range = both_range[1:] - elif inclusive_endpoints == "both": - expected_range = both_range[:] - else: - expected_range = both_range[:]""" if inclusive_endpoints == "left": expected_range = both_range[:-1] @@ -77,7 +58,9 @@ def _get_expected_range( elif inclusive_endpoints == "neither": expected_range = both_range[1:-1] else: - expected_range = both_range[:] + raise ValueError( + "Inclusive has to be either 'both', 'neither', 'left' or 'right'" + ) return expected_range From a2d8ae6116b8e9dc31cab3d941c8b399d0d9dd8c Mon Sep 17 00:00:00 2001 From: Piotr Bartoszewicz <89194651+PiotrekB416@users.noreply.github.com> Date: Fri, 29 Sep 2023 12:50:52 +0200 Subject: [PATCH 05/13] Update test_date_range.py --- pandas/tests/indexes/datetimes/test_date_range.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/indexes/datetimes/test_date_range.py b/pandas/tests/indexes/datetimes/test_date_range.py index fdb2e215277b7..88c74904132dc 100644 --- a/pandas/tests/indexes/datetimes/test_date_range.py +++ b/pandas/tests/indexes/datetimes/test_date_range.py @@ -92,7 +92,7 @@ def test_date_range_timestamp_equiv_explicit_pytz(self): ts = Timestamp("20090415", tz=pytz.timezone("US/Eastern")) assert ts == stamp - #@td.skip_if_windowsdate_range inclusive + @td.skip_if_windowsdate_range inclusive def test_date_range_timestamp_equiv_explicit_dateutil(self): from pandas._libs.tslibs.timezones import dateutil_gettz as gettz From 048e00fc74fbd1616d612448453881d578c5ca7d Mon Sep 17 00:00:00 2001 From: PiotrekB416 Date: Fri, 29 Sep 2023 13:14:29 +0200 Subject: [PATCH 06/13] Fixed random paste --- pandas/tests/indexes/datetimes/test_date_range.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/indexes/datetimes/test_date_range.py b/pandas/tests/indexes/datetimes/test_date_range.py index 88c74904132dc..0f88d85fcffc8 100644 --- a/pandas/tests/indexes/datetimes/test_date_range.py +++ b/pandas/tests/indexes/datetimes/test_date_range.py @@ -92,7 +92,7 @@ def test_date_range_timestamp_equiv_explicit_pytz(self): ts = Timestamp("20090415", tz=pytz.timezone("US/Eastern")) assert ts == stamp - @td.skip_if_windowsdate_range inclusive + @td.skip_if_windows def test_date_range_timestamp_equiv_explicit_dateutil(self): from pandas._libs.tslibs.timezones import dateutil_gettz as gettz From 09d5b94f9c230271fc758ec0955390564a9a2da0 Mon Sep 17 00:00:00 2001 From: PiotrekB416 Date: Tue, 31 Oct 2023 10:32:56 +0100 Subject: [PATCH 07/13] Update whatsnew --- doc/source/whatsnew/v2.1.3.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v2.1.3.rst b/doc/source/whatsnew/v2.1.3.rst index 1359123ef153e..2a064dbaed3e5 100644 --- a/doc/source/whatsnew/v2.1.3.rst +++ b/doc/source/whatsnew/v2.1.3.rst @@ -21,7 +21,7 @@ Fixed regressions Bug fixes ~~~~~~~~~ -- +- Fixed bug in :meth:`DatetimeArray._generate_range` where ``inclusive`` argument behavior did not match interval notation (:issue:`55293`,:issue:`46331`) - .. --------------------------------------------------------------------------- From fed521d34619769577b2d03091b0cafef6fbfd4b Mon Sep 17 00:00:00 2001 From: PiotrekB416 Date: Sat, 18 Nov 2023 17:12:19 +0100 Subject: [PATCH 08/13] Minor refactoring in tests --- pandas/tests/indexes/datetimes/test_date_range.py | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/pandas/tests/indexes/datetimes/test_date_range.py b/pandas/tests/indexes/datetimes/test_date_range.py index 9207524a0c644..ebfe9f749b0bc 100644 --- a/pandas/tests/indexes/datetimes/test_date_range.py +++ b/pandas/tests/indexes/datetimes/test_date_range.py @@ -43,13 +43,10 @@ def _get_expected_range( - begin_to_match, - end_to_match, both_range, inclusive_endpoints, ): """Helper to get expected range from a both inclusive range""" - if inclusive_endpoints == "left": expected_range = both_range[:-1] elif inclusive_endpoints == "right": @@ -656,7 +653,7 @@ def test_range_closed(self, freq, inclusive_endpoints_fixture): ) both_range = date_range(begin, end, inclusive="both", freq=freq) expected_range = _get_expected_range( - begin, end, both_range, inclusive_endpoints_fixture + both_range, inclusive_endpoints_fixture ) tm.assert_index_equal(expected_range, result_range) @@ -674,8 +671,6 @@ def test_range_closed_with_tz_aware_start_end( ) both_range = date_range(begin, end, inclusive="both", freq=freq) expected_range = _get_expected_range( - begin, - end, both_range, inclusive_endpoints_fixture, ) @@ -702,8 +697,6 @@ def test_range_with_tz_closed_with_tz_aware_start_end( begin, end, inclusive="both", freq=freq, tz="US/Eastern" ) expected_range = _get_expected_range( - begintz, - endtz, both_range, inclusive_endpoints_fixture, ) @@ -807,10 +800,7 @@ def test_range_where_start_equal_end(self, inclusive_endpoints_fixture): ) both_range = date_range(start=start, end=end, freq="D", inclusive="both") - if inclusive_endpoints_fixture in ("neither", "left", "right"): - expected = both_range[1:-1] - elif inclusive_endpoints_fixture == "both": - expected = both_range[:] + expected = _get_expected_range(both_range, inclusive_endpoints_fixture) tm.assert_index_equal(result, expected) From dc339f4e0af3f322b559aaa58cfe54916a06a055 Mon Sep 17 00:00:00 2001 From: Piotr Bartoszewicz <89194651+PiotrekB416@users.noreply.github.com> Date: Sat, 18 Nov 2023 17:31:17 +0100 Subject: [PATCH 09/13] Update Dockerfile --- Dockerfile | 2 -- 1 file changed, 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index b88bda4b7e623..7230dcab20f6e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,8 +7,6 @@ RUN apt-get install -y build-essential # hdf5 needed for pytables installation RUN apt-get install -y libhdf5-dev -RUN apt-get install -y openssh-server - RUN python -m pip install --upgrade pip RUN python -m pip install \ -r https://raw.githubusercontent.com/pandas-dev/pandas/main/requirements-dev.txt From 24856e791292f4c185853aa002634c535ddc280e Mon Sep 17 00:00:00 2001 From: Piotr Bartoszewicz <89194651+PiotrekB416@users.noreply.github.com> Date: Sat, 18 Nov 2023 17:31:46 +0100 Subject: [PATCH 10/13] Update .devcontainer.json --- .devcontainer.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.devcontainer.json b/.devcontainer.json index d715f3d563e2c..7c5d009260c64 100644 --- a/.devcontainer.json +++ b/.devcontainer.json @@ -12,10 +12,10 @@ "python.pythonPath": "/usr/local/bin/python", "python.formatting.provider": "black", "python.linting.enabled": true, - "python.linting.flake8Enabled": false, + "python.linting.flake8Enabled": true, "python.linting.pylintEnabled": false, - "python.linting.mypyEnabled": false, - "python.testing.pytestEnabled":false, + "python.linting.mypyEnabled": true, + "python.testing.pytestEnabled": true, "python.testing.pytestArgs": [ "pandas" ] From a2bcae5585ec48aa9e92ed65939770bf3d675a3c Mon Sep 17 00:00:00 2001 From: Piotr Bartoszewicz <89194651+PiotrekB416@users.noreply.github.com> Date: Sat, 18 Nov 2023 17:32:54 +0100 Subject: [PATCH 11/13] Update test_date_range.py --- pandas/tests/indexes/datetimes/test_date_range.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/tests/indexes/datetimes/test_date_range.py b/pandas/tests/indexes/datetimes/test_date_range.py index 6c67be7db5ae7..ca64921b9ddfd 100644 --- a/pandas/tests/indexes/datetimes/test_date_range.py +++ b/pandas/tests/indexes/datetimes/test_date_range.py @@ -606,8 +606,8 @@ def test_range_with_tz_closed_with_tz_aware_start_end( ): begin = Timestamp("2011/1/1") end = Timestamp("2014/1/1") - begintz = Timestamp("2011/1/1", tz="US/Eastern") - endtz = Timestamp("2014/1/1", tz="US/Eastern") + #begintz = Timestamp("2011/1/1", tz="US/Eastern") + #endtz = Timestamp("2014/1/1", tz="US/Eastern") result_range = date_range( begin, From 584dc2fd4deba0bd32db3e0ca97cb4e88d378b08 Mon Sep 17 00:00:00 2001 From: PiotrekB416 Date: Sat, 18 Nov 2023 18:28:03 +0100 Subject: [PATCH 12/13] fix formatting --- pandas/tests/indexes/datetimes/test_date_range.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pandas/tests/indexes/datetimes/test_date_range.py b/pandas/tests/indexes/datetimes/test_date_range.py index ca64921b9ddfd..4db8658970d20 100644 --- a/pandas/tests/indexes/datetimes/test_date_range.py +++ b/pandas/tests/indexes/datetimes/test_date_range.py @@ -575,9 +575,7 @@ def test_range_closed(self, freq, tz, inclusive_endpoints_fixture): begin, end, inclusive=inclusive_endpoints_fixture, freq=freq ) both_range = date_range(begin, end, inclusive="both", freq=freq) - expected_range = _get_expected_range( - both_range, inclusive_endpoints_fixture - ) + expected_range = _get_expected_range(both_range, inclusive_endpoints_fixture) tm.assert_index_equal(expected_range, result_range) @@ -606,8 +604,8 @@ def test_range_with_tz_closed_with_tz_aware_start_end( ): begin = Timestamp("2011/1/1") end = Timestamp("2014/1/1") - #begintz = Timestamp("2011/1/1", tz="US/Eastern") - #endtz = Timestamp("2014/1/1", tz="US/Eastern") + # begintz = Timestamp("2011/1/1", tz="US/Eastern") + # endtz = Timestamp("2014/1/1", tz="US/Eastern") result_range = date_range( begin, From 94f8039951000d42ec09ae47d883ce4748f29382 Mon Sep 17 00:00:00 2001 From: PiotrekB416 Date: Sat, 18 Nov 2023 19:17:03 +0100 Subject: [PATCH 13/13] fixed Y is deprected use YE instead --- pandas/tests/indexes/datetimes/test_date_range.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/tests/indexes/datetimes/test_date_range.py b/pandas/tests/indexes/datetimes/test_date_range.py index 4db8658970d20..b3a6bdb85acdb 100644 --- a/pandas/tests/indexes/datetimes/test_date_range.py +++ b/pandas/tests/indexes/datetimes/test_date_range.py @@ -579,7 +579,7 @@ def test_range_closed(self, freq, tz, inclusive_endpoints_fixture): tm.assert_index_equal(expected_range, result_range) - @pytest.mark.parametrize("freq", ["1D", "3D", "2ME", "7W", "3h", "Y"]) + @pytest.mark.parametrize("freq", ["1D", "3D", "2ME", "7W", "3h", "YE"]) def test_range_closed_with_tz_aware_start_end( self, freq, inclusive_endpoints_fixture ): @@ -598,7 +598,7 @@ def test_range_closed_with_tz_aware_start_end( tm.assert_index_equal(expected_range, result_range) - @pytest.mark.parametrize("freq", ["1D", "3D", "2ME", "7W", "3h", "Y"]) + @pytest.mark.parametrize("freq", ["1D", "3D", "2ME", "7W", "3h", "YE"]) def test_range_with_tz_closed_with_tz_aware_start_end( self, freq, inclusive_endpoints_fixture ):