From a2ba41621f6dd27b8d0d5fe7e1f2d78943da623d Mon Sep 17 00:00:00 2001 From: Brock Date: Mon, 15 Jun 2020 20:49:40 -0700 Subject: [PATCH 1/3] REF: remove libfrequencies --- pandas/_libs/tslibs/dtypes.pxd | 2 + pandas/_libs/tslibs/dtypes.pyx | 19 +++++++++ pandas/_libs/tslibs/frequencies.pxd | 1 - pandas/_libs/tslibs/frequencies.pyx | 40 ------------------- pandas/_libs/tslibs/period.pyx | 4 +- pandas/_libs/tslibs/resolution.pyx | 2 +- pandas/core/arrays/period.py | 10 ++--- pandas/plotting/_matplotlib/timeseries.py | 2 +- .../tseries/frequencies/test_freq_code.py | 7 ++-- pandas/tests/tslibs/test_api.py | 1 - setup.py | 2 - 11 files changed, 33 insertions(+), 57 deletions(-) delete mode 100644 pandas/_libs/tslibs/frequencies.pxd delete mode 100644 pandas/_libs/tslibs/frequencies.pyx diff --git a/pandas/_libs/tslibs/dtypes.pxd b/pandas/_libs/tslibs/dtypes.pxd index 71b4eeabbaaf5..9b9c0cdba43c4 100644 --- a/pandas/_libs/tslibs/dtypes.pxd +++ b/pandas/_libs/tslibs/dtypes.pxd @@ -74,3 +74,5 @@ cdef enum PeriodDtypeCode: cdef class PeriodDtypeBase: cdef readonly: PeriodDtypeCode _dtype_code + + cpdef PeriodDtypeCode get_to_timestamp_base(self) diff --git a/pandas/_libs/tslibs/dtypes.pyx b/pandas/_libs/tslibs/dtypes.pyx index 143eac7f1ef6e..a2751c9a6a7c7 100644 --- a/pandas/_libs/tslibs/dtypes.pyx +++ b/pandas/_libs/tslibs/dtypes.pyx @@ -45,6 +45,25 @@ cdef class PeriodDtypeBase: code = offset._period_dtype_code return cls(code) + cpdef PeriodDtypeCode get_to_timestamp_base(self): + """ + Return frequency code group used for base of to_timestamp against + frequency code. + + Return day freq code against longer freq than day. + Return second freq code against hour between second. + + Returns + ------- + PeriodDtypeCode + """ + base = self._dtype_code + if base < FreqGroup.FR_BUS: + return c_FreqGroup.FR_DAY + elif FreqGroup.FR_HR <= base <= FreqGroup.FR_SEC: + return c_FreqGroup.FR_SEC + return base + _period_code_map = { # Annual freqs with various fiscal year ends. diff --git a/pandas/_libs/tslibs/frequencies.pxd b/pandas/_libs/tslibs/frequencies.pxd deleted file mode 100644 index b3ad6e6c19ee3..0000000000000 --- a/pandas/_libs/tslibs/frequencies.pxd +++ /dev/null @@ -1 +0,0 @@ -cpdef int get_to_timestamp_base(int base) diff --git a/pandas/_libs/tslibs/frequencies.pyx b/pandas/_libs/tslibs/frequencies.pyx deleted file mode 100644 index fd28240abd882..0000000000000 --- a/pandas/_libs/tslibs/frequencies.pyx +++ /dev/null @@ -1,40 +0,0 @@ - -from .dtypes import FreqGroup - -# ---------------------------------------------------------------------- - - -cpdef int get_to_timestamp_base(int base): - """ - Return frequency code group used for base of to_timestamp against - frequency code. - - Parameters - ---------- - base : int (member of FreqGroup) - - Returns - ------- - base : int - - Examples - -------- - # Return day freq code against longer freq than day - >>> get_to_timestamp_base(get_freq_code('D')[0]) - 6000 - >>> get_to_timestamp_base(get_freq_code('W')[0]) - 6000 - >>> get_to_timestamp_base(get_freq_code('M')[0]) - 6000 - - # Return second freq code against hour between second - >>> get_to_timestamp_base(get_freq_code('H')[0]) - 9000 - >>> get_to_timestamp_base(get_freq_code('S')[0]) - 9000 - """ - if base < FreqGroup.FR_BUS: - return FreqGroup.FR_DAY - elif FreqGroup.FR_HR <= base <= FreqGroup.FR_SEC: - return FreqGroup.FR_SEC - return base diff --git a/pandas/_libs/tslibs/period.pyx b/pandas/_libs/tslibs/period.pyx index 30caddf81b6e8..d66ccf99b32e5 100644 --- a/pandas/_libs/tslibs/period.pyx +++ b/pandas/_libs/tslibs/period.pyx @@ -74,7 +74,6 @@ from pandas._libs.tslibs.dtypes cimport ( attrname_to_abbrevs, ) -from pandas._libs.tslibs.frequencies cimport get_to_timestamp_base from pandas._libs.tslibs.parsing cimport get_rule_month from pandas._libs.tslibs.parsing import parse_time_string from pandas._libs.tslibs.nattype cimport ( @@ -1734,8 +1733,7 @@ cdef class _Period: return endpoint - Timedelta(1, 'ns') if freq is None: - base = self._dtype._dtype_code - freq = get_to_timestamp_base(base) + freq = self._dtype.get_to_timestamp_base() base = freq else: freq = self._maybe_convert_freq(freq) diff --git a/pandas/_libs/tslibs/resolution.pyx b/pandas/_libs/tslibs/resolution.pyx index 55522e99459cb..b441f884e2555 100644 --- a/pandas/_libs/tslibs/resolution.pyx +++ b/pandas/_libs/tslibs/resolution.pyx @@ -6,9 +6,9 @@ from numpy cimport ndarray, int64_t, int32_t from pandas._libs.tslibs.util cimport get_nat from pandas._libs.tslibs.dtypes cimport attrname_to_abbrevs +from pandas._libs.tslibs.dtypes import FreqGroup from pandas._libs.tslibs.np_datetime cimport ( npy_datetimestruct, dt64_to_dtstruct) -from pandas._libs.tslibs.frequencies import FreqGroup from pandas._libs.tslibs.timezones cimport ( is_utc, is_tzlocal, maybe_get_tz, get_dst_info) from pandas._libs.tslibs.ccalendar cimport get_days_in_month, c_MONTH_NUMBERS diff --git a/pandas/core/arrays/period.py b/pandas/core/arrays/period.py index 0d866aa7eae26..fa529ac540415 100644 --- a/pandas/core/arrays/period.py +++ b/pandas/core/arrays/period.py @@ -9,11 +9,11 @@ NaTType, Timedelta, delta_to_nanoseconds, - frequencies as libfrequencies, iNaT, period as libperiod, to_offset, ) +from pandas._libs.tslibs.dtypes import FreqGroup from pandas._libs.tslibs.fields import isleapyear_arr from pandas._libs.tslibs.offsets import Tick, delta_to_tick from pandas._libs.tslibs.period import ( @@ -23,6 +23,7 @@ get_period_field_arr, period_asfreq_arr, ) + from pandas._typing import AnyArrayLike from pandas.util._decorators import cache_readonly @@ -440,8 +441,7 @@ def to_timestamp(self, freq=None, how="start"): return (self + self.freq).to_timestamp(how="start") - adjust if freq is None: - base = self.freq._period_dtype_code - freq = libfrequencies.get_to_timestamp_base(base) + freq = self.dtype.get_to_timestamp_base() base = freq else: freq = Period._maybe_convert_freq(freq) @@ -1027,11 +1027,11 @@ def _range_from_fields( if quarter is not None: if freq is None: freq = to_offset("Q") - base = libfrequencies.FreqGroup.FR_QTR + base = FreqGroup.FR_QTR else: freq = to_offset(freq) base = libperiod.freq_to_dtype_code(freq) - if base != libfrequencies.FreqGroup.FR_QTR: + if base != FreqGroup.FR_QTR: raise AssertionError("base must equal FR_QTR") year, quarter = _make_field_arrays(year, quarter) diff --git a/pandas/plotting/_matplotlib/timeseries.py b/pandas/plotting/_matplotlib/timeseries.py index fa8051954e435..8ffd30567b9ac 100644 --- a/pandas/plotting/_matplotlib/timeseries.py +++ b/pandas/plotting/_matplotlib/timeseries.py @@ -6,7 +6,7 @@ import numpy as np from pandas._libs.tslibs import Period, to_offset -from pandas._libs.tslibs.frequencies import FreqGroup +from pandas._libs.tslibs.dtypes import FreqGroup from pandas._typing import FrameOrSeriesUnion from pandas.core.dtypes.generic import ( diff --git a/pandas/tests/tseries/frequencies/test_freq_code.py b/pandas/tests/tseries/frequencies/test_freq_code.py index 5383c1ff1c2c9..99118a5247583 100644 --- a/pandas/tests/tseries/frequencies/test_freq_code.py +++ b/pandas/tests/tseries/frequencies/test_freq_code.py @@ -1,8 +1,7 @@ import pytest from pandas._libs.tslibs import Resolution, to_offset -from pandas._libs.tslibs.dtypes import _attrname_to_abbrevs -from pandas._libs.tslibs.frequencies import get_to_timestamp_base +from pandas._libs.tslibs.dtypes import _attrname_to_abbrevs, PeriodDtypeBase @pytest.mark.parametrize( @@ -12,7 +11,9 @@ def test_get_to_timestamp_base(freqstr, exp_freqstr): left_code = to_offset(freqstr)._period_dtype_code exp_code = to_offset(exp_freqstr)._period_dtype_code - assert get_to_timestamp_base(left_code) == exp_code + + result_code = PeriodDtypeBase(left_code).get_to_timestamp_base() + assert result_code == exp_code @pytest.mark.parametrize( diff --git a/pandas/tests/tslibs/test_api.py b/pandas/tests/tslibs/test_api.py index b0c524a257684..a119db6c68635 100644 --- a/pandas/tests/tslibs/test_api.py +++ b/pandas/tests/tslibs/test_api.py @@ -11,7 +11,6 @@ def test_namespace(): "conversion", "dtypes", "fields", - "frequencies", "nattype", "np_datetime", "offsets", diff --git a/setup.py b/setup.py index 3caea5c5e79da..e9d305d831653 100755 --- a/setup.py +++ b/setup.py @@ -319,7 +319,6 @@ class CheckSDist(sdist_class): "pandas/_libs/tslibs/conversion.pyx", "pandas/_libs/tslibs/fields.pyx", "pandas/_libs/tslibs/offsets.pyx", - "pandas/_libs/tslibs/frequencies.pyx", "pandas/_libs/tslibs/resolution.pyx", "pandas/_libs/tslibs/parsing.pyx", "pandas/_libs/tslibs/tzconversion.pyx", @@ -615,7 +614,6 @@ def srcpath(name=None, suffix=".pyx", subdir="src"): "pyxfile": "_libs/tslibs/fields", "depends": tseries_depends, }, - "_libs.tslibs.frequencies": {"pyxfile": "_libs/tslibs/frequencies"}, "_libs.tslibs.nattype": {"pyxfile": "_libs/tslibs/nattype"}, "_libs.tslibs.np_datetime": { "pyxfile": "_libs/tslibs/np_datetime", From 93c44ee5cd09eedd103a3e887067e6077bfdbea2 Mon Sep 17 00:00:00 2001 From: Brock Date: Tue, 16 Jun 2020 10:27:11 -0700 Subject: [PATCH 2/3] REF: make _get_to_timestamp_base a PeriodMixin method --- pandas/_libs/tslibs/dtypes.pxd | 2 -- pandas/_libs/tslibs/dtypes.pyx | 19 ------------- pandas/_libs/tslibs/period.pyx | 27 +++++++++++++++++-- pandas/core/arrays/period.py | 6 ++--- .../tseries/frequencies/test_freq_code.py | 9 ++++--- 5 files changed, 33 insertions(+), 30 deletions(-) diff --git a/pandas/_libs/tslibs/dtypes.pxd b/pandas/_libs/tslibs/dtypes.pxd index 9b9c0cdba43c4..71b4eeabbaaf5 100644 --- a/pandas/_libs/tslibs/dtypes.pxd +++ b/pandas/_libs/tslibs/dtypes.pxd @@ -74,5 +74,3 @@ cdef enum PeriodDtypeCode: cdef class PeriodDtypeBase: cdef readonly: PeriodDtypeCode _dtype_code - - cpdef PeriodDtypeCode get_to_timestamp_base(self) diff --git a/pandas/_libs/tslibs/dtypes.pyx b/pandas/_libs/tslibs/dtypes.pyx index aa6985158b1a4..70acb42712201 100644 --- a/pandas/_libs/tslibs/dtypes.pyx +++ b/pandas/_libs/tslibs/dtypes.pyx @@ -46,25 +46,6 @@ cdef class PeriodDtypeBase: code = offset._period_dtype_code return cls(code) - cpdef PeriodDtypeCode get_to_timestamp_base(self): - """ - Return frequency code group used for base of to_timestamp against - frequency code. - - Return day freq code against longer freq than day. - Return second freq code against hour between second. - - Returns - ------- - PeriodDtypeCode - """ - base = self._dtype_code - if base < FreqGroup.FR_BUS: - return c_FreqGroup.FR_DAY - elif FreqGroup.FR_HR <= base <= FreqGroup.FR_SEC: - return c_FreqGroup.FR_SEC - return base - _period_code_map = { # Annual freqs with various fiscal year ends. diff --git a/pandas/_libs/tslibs/period.pyx b/pandas/_libs/tslibs/period.pyx index d66ccf99b32e5..535a18086d290 100644 --- a/pandas/_libs/tslibs/period.pyx +++ b/pandas/_libs/tslibs/period.pyx @@ -1477,7 +1477,30 @@ class IncompatibleFrequency(ValueError): pass -cdef class _Period: +cdef class PeriodMixin: + # Methods shared between PeriodArray + + cpdef int _get_to_timestamp_base(self): + """ + Return frequency code group used for base of to_timestamp against + frequency code. + + Return day freq code against longer freq than day. + Return second freq code against hour between second. + + Returns + ------- + int + """ + base = self._dtype._dtype_code + if base < FR_BUS: + return FR_DAY + elif FR_HR <= base <= FR_SEC: + return FR_SEC + return base + + +cdef class _Period(PeriodMixin): cdef readonly: int64_t ordinal @@ -1733,7 +1756,7 @@ cdef class _Period: return endpoint - Timedelta(1, 'ns') if freq is None: - freq = self._dtype.get_to_timestamp_base() + freq = self._get_to_timestamp_base() base = freq else: freq = self._maybe_convert_freq(freq) diff --git a/pandas/core/arrays/period.py b/pandas/core/arrays/period.py index fa529ac540415..7902dd0410910 100644 --- a/pandas/core/arrays/period.py +++ b/pandas/core/arrays/period.py @@ -20,10 +20,10 @@ DIFFERENT_FREQ, IncompatibleFrequency, Period, + PeriodMixin, get_period_field_arr, period_asfreq_arr, ) - from pandas._typing import AnyArrayLike from pandas.util._decorators import cache_readonly @@ -62,7 +62,7 @@ def f(self): return property(f) -class PeriodArray(dtl.DatetimeLikeArrayMixin, dtl.DatelikeOps): +class PeriodArray(PeriodMixin, dtl.DatetimeLikeArrayMixin, dtl.DatelikeOps): """ Pandas ExtensionArray for storing Period data. @@ -441,7 +441,7 @@ def to_timestamp(self, freq=None, how="start"): return (self + self.freq).to_timestamp(how="start") - adjust if freq is None: - freq = self.dtype.get_to_timestamp_base() + freq = self._get_to_timestamp_base() base = freq else: freq = Period._maybe_convert_freq(freq) diff --git a/pandas/tests/tseries/frequencies/test_freq_code.py b/pandas/tests/tseries/frequencies/test_freq_code.py index 99118a5247583..20cadde45e7a0 100644 --- a/pandas/tests/tseries/frequencies/test_freq_code.py +++ b/pandas/tests/tseries/frequencies/test_freq_code.py @@ -1,7 +1,7 @@ import pytest -from pandas._libs.tslibs import Resolution, to_offset -from pandas._libs.tslibs.dtypes import _attrname_to_abbrevs, PeriodDtypeBase +from pandas._libs.tslibs import Period, Resolution, to_offset +from pandas._libs.tslibs.dtypes import _attrname_to_abbrevs @pytest.mark.parametrize( @@ -9,10 +9,11 @@ [("D", "D"), ("W", "D"), ("M", "D"), ("S", "S"), ("T", "S"), ("H", "S")], ) def test_get_to_timestamp_base(freqstr, exp_freqstr): - left_code = to_offset(freqstr)._period_dtype_code + off = to_offset(freqstr) + per = Period._from_ordinal(1, off) exp_code = to_offset(exp_freqstr)._period_dtype_code - result_code = PeriodDtypeBase(left_code).get_to_timestamp_base() + result_code = per._get_to_timestamp_base() assert result_code == exp_code From 7c6a8b1cb5b6485b81020c5be6be621dc2aec5c9 Mon Sep 17 00:00:00 2001 From: Brock Date: Tue, 16 Jun 2020 10:27:52 -0700 Subject: [PATCH 3/3] comment fixup --- pandas/_libs/tslibs/period.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/_libs/tslibs/period.pyx b/pandas/_libs/tslibs/period.pyx index 535a18086d290..a2250234dbd14 100644 --- a/pandas/_libs/tslibs/period.pyx +++ b/pandas/_libs/tslibs/period.pyx @@ -1478,7 +1478,7 @@ class IncompatibleFrequency(ValueError): cdef class PeriodMixin: - # Methods shared between PeriodArray + # Methods shared between Period and PeriodArray cpdef int _get_to_timestamp_base(self): """