Bitesize offsets
State: closed

This is the first of several PRs cleaning up `tseries.offsets`.  The ultimate goals of this series of PRs are:

- Fix slow implementation of `DateOffset.__eq__`, as that gets called by `Period.__eq__`.
- Make `DateOffset` immutable, since it is attached to a `Period` object which is supposed to be immutable (TODO: fill in the appropriate GH issue)
- Move `tseries.offsets` into cython so that `_libs.period` and `_libs.tslib` can import it guilt-free and not need to do run-time imports.  See TODO comment in `_libs.__init__`:

```
# TODO
# period is directly dependent on tslib and imports python
# modules, so exposing Period as an alias is currently not possible
```

The biggest impediment to the immutability goal is the `kwds` attribute, which is just a `dict`.  The first couple of steps in this sequence is focused on whittling down the number of attributes set at runtime.

This PR is mainly fixing typos and removing redundant methods.


- [x] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`


Labels:
name: Internals
description: Related to non-user accessible pandas implementation
name: Frequency
description: DateOffsets
name: Clean

Comments:
Hello @jbrockmendel! Thanks for updating the PR.







Cheers ! There are no PEP8 issues in this Pull Request. :beers: 

##### Comment last updated on September 23, 2017 at 16:21 Hours UTC
# [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/17318?src=pr&el=h1) Report
> Merging [#17318](https://codecov.io/gh/pandas-dev/pandas/pull/17318?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/2bec750b21b8715e3f55e71a6c69f2abef54d08b?src=pr&el=desc) will **increase** coverage by `0.01%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/pandas-dev/pandas/pull/17318/graphs/tree.svg?width=650&height=150&src=pr&token=eZ4WkYLtcO)](https://codecov.io/gh/pandas-dev/pandas/pull/17318?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master   #17318      +/-   ##
==========================================
+ Coverage   91.01%   91.02%   +0.01%     
==========================================
  Files         162      162              
  Lines       49558    49564       +6     
==========================================
+ Hits        45105    45116      +11     
+ Misses       4453     4448       -5
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `88.8% <100%> (+0.02%)` | :arrow_up: |
| #single | `40.26% <66.66%> (-0.05%)` | :arrow_down: |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/17318?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/tseries/offsets.py](https://codecov.io/gh/pandas-dev/pandas/pull/17318?src=pr&el=tree#diff-cGFuZGFzL3RzZXJpZXMvb2Zmc2V0cy5weQ==) | `97.28% <100%> (+0.13%)` | :arrow_up: |
| [pandas/io/gbq.py](https://codecov.io/gh/pandas-dev/pandas/pull/17318?src=pr&el=tree#diff-cGFuZGFzL2lvL2dicS5weQ==) | `25% <0%> (-58.34%)` | :arrow_down: |
| [pandas/core/frame.py](https://codecov.io/gh/pandas-dev/pandas/pull/17318?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZnJhbWUucHk=) | `97.72% <0%> (-0.1%)` | :arrow_down: |
| [pandas/errors/\_\_init\_\_.py](https://codecov.io/gh/pandas-dev/pandas/pull/17318?src=pr&el=tree#diff-cGFuZGFzL2Vycm9ycy9fX2luaXRfXy5weQ==) | `100% <0%> (ø)` | :arrow_up: |
| [pandas/plotting/\_converter.py](https://codecov.io/gh/pandas-dev/pandas/pull/17318?src=pr&el=tree#diff-cGFuZGFzL3Bsb3R0aW5nL19jb252ZXJ0ZXIucHk=) | `65.05% <0%> (+1.81%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/17318?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/17318?src=pr&el=footer). Last update [2bec750...c66b842](https://codecov.io/gh/pandas-dev/pandas/pull/17318?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

# [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/17318?src=pr&el=h1) Report
> Merging [#17318](https://codecov.io/gh/pandas-dev/pandas/pull/17318?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/e2757a2db0faa7878858b36f602235daa936a674?src=pr&el=desc) will **decrease** coverage by `<.01%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/pandas-dev/pandas/pull/17318/graphs/tree.svg?width=650&height=150&src=pr&token=eZ4WkYLtcO)](https://codecov.io/gh/pandas-dev/pandas/pull/17318?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master   #17318      +/-   ##
==========================================
- Coverage   91.22%   91.21%   -0.01%     
==========================================
  Files         163      163              
  Lines       49655    49673      +18     
==========================================
+ Hits        45296    45308      +12     
- Misses       4359     4365       +6
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `89% <100%> (+0.01%)` | :arrow_up: |
| #single | `40.19% <64%> (-0.05%)` | :arrow_down: |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/17318?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/tseries/frequencies.py](https://codecov.io/gh/pandas-dev/pandas/pull/17318?src=pr&el=tree#diff-cGFuZGFzL3RzZXJpZXMvZnJlcXVlbmNpZXMucHk=) | `96.11% <ø> (ø)` | :arrow_up: |
| [pandas/tseries/offsets.py](https://codecov.io/gh/pandas-dev/pandas/pull/17318?src=pr&el=tree#diff-cGFuZGFzL3RzZXJpZXMvb2Zmc2V0cy5weQ==) | `97.14% <100%> (+0.14%)` | :arrow_up: |
| [pandas/io/gbq.py](https://codecov.io/gh/pandas-dev/pandas/pull/17318?src=pr&el=tree#diff-cGFuZGFzL2lvL2dicS5weQ==) | `25% <0%> (-58.34%)` | :arrow_down: |
| [pandas/core/frame.py](https://codecov.io/gh/pandas-dev/pandas/pull/17318?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZnJhbWUucHk=) | `97.77% <0%> (-0.1%)` | :arrow_down: |
| [pandas/core/series.py](https://codecov.io/gh/pandas-dev/pandas/pull/17318?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvc2VyaWVzLnB5) | `94.92% <0%> (ø)` | :arrow_up: |
| [pandas/core/generic.py](https://codecov.io/gh/pandas-dev/pandas/pull/17318?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZ2VuZXJpYy5weQ==) | `91.99% <0%> (ø)` | :arrow_up: |
| [pandas/core/indexes/datetimes.py](https://codecov.io/gh/pandas-dev/pandas/pull/17318?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvaW5kZXhlcy9kYXRldGltZXMucHk=) | `95.53% <0%> (+0.09%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/17318?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/17318?src=pr&el=footer). Last update [e2757a2...e52a791](https://codecov.io/gh/pandas-dev/pandas/pull/17318?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

I think this test error is unrelated.  Pls confirm.
this was a while ago, rebase and we will see
needs a rebase
> can you run the freq asv's to make sure nothing has changed here.

Begrudgingly...
```
$ asv continuous -f 1.1 -E virtualenv master HEAD -b freq
[...]
       before           after         ratio
     [2bec750b]       [d1e9161b]
+          72.9ms            126ms     1.73  timeseries.DatetimeIndex.time_infer_freq_none
-          57.9ms           45.0ms     0.78  timeseries.DatetimeIndex.time_infer_freq_business
-          44.7ms           34.3ms     0.77  timeseries.DatetimeIndex.time_infer_freq_daily

SOME BENCHMARKS HAVE CHANGED SIGNIFICANTLY.

$ asv continuous -f 1.1 -E virtualenv master HEAD -b freq
[...]
     [2bec750b]       [d1e9161b]
+          31.7ms           43.8ms     1.38  timeseries.DatetimeIndex.time_infer_freq_business
+     1.52±0.04μs      1.99±0.05μs     1.30  timestamp.TimestampProperties.time_freqstr
+          43.1ms           50.4ms     1.17  timeseries.DatetimeIndex.time_infer_freq_none

SOME BENCHMARKS HAVE CHANGED SIGNIFICANTLY.

$ asv continuous -f 1.1 -E virtualenv master HEAD -b freq
[...]
     [2bec750b]       [d1e9161b]
+          25.6ms           30.7ms     1.20  timeseries.DatetimeIndex.time_infer_freq_business
-          27.2ms           24.3ms     0.89  timeseries.DatetimeIndex.time_infer_freq_daily

SOME BENCHMARKS HAVE CHANGED SIGNIFICANTLY.

$ asv continuous -f 1.1 -E virtualenv master HEAD -b freq
[...]
      before           after         ratio
     [2bec750b]       [d1e9161b]
-          60.6ms           53.9ms     0.89  timeseries.DatetimeIndex.time_infer_freq_none
-          34.6ms           28.7ms     0.83  timeseries.DatetimeIndex.time_infer_freq_business
-          30.9ms           23.4ms     0.76  timeseries.DatetimeIndex.time_infer_freq_daily
-      2.87±0.3μs      2.14±0.07μs     0.75  timestamp.TimestampProperties.time_freqstr

SOME BENCHMARKS HAVE CHANGED SIGNIFICANTLY.
```
This is repeatable.
```
    before     after       ratio
  [f797c1dc] [d1e9161b]
+  529.00μs    12.36ms     23.36  timeseries.DatetimeIndex.time_infer_freq_business
+   20.68ms    24.21ms      1.17  timeseries.DatetimeIndex.time_infer_freq_none

SOME BENCHMARKS HAVE CHANGED SIGNIFICANTLY.

```
``[2bec750b]`` is a pretty old commit, FYI
After updating, I get the same timings too.  But it looks like this may be due to a bug in master.  Manually stepping through the benchmark, `timeseries.DatetimeIndex` includes the code

```
rng8 = date_range(start='1/1/1700', freq='B', periods=100000)
```
which for me (py27, ubuntu...) is giving:

```
OverflowError: Python int too large to convert to C long
Exception OverflowError: 'Python int too large to convert to C long' in 'pandas._libs.tslib._delta_to_nanoseconds' ignored
```
and the resulting `rng8` object is a `DatetimeIndex` object with 5 entries.  Before anything else, can you reproduce this?

Same on py35
git bisect tells me the first bad commit was b59f107a529ac9b1e2859217ea58f7e26b6749d0
yeah looks like this was a bug introduced there, hmm.
let me see if I can work around: https://github.com/pandas-dev/pandas/issues/17637
After #17637, benchmarks are now unaffected.
> After #17637, benchmarks are now unaffected.

does this mean they are the same (worse) or the same as master?
```
asv continuous -f 1.1 -E virtualenv master HEAD -b freq
[...]
BENCHMARKS NOT SIGNIFICANTLY CHANGED.
```
Just pushed.  Besides the requested docstring, had to edit the asv to avoid the new OverflowError.
lgtm. ping on green.

side note, I believe you can make ``_params`` readonly_cached if i read it correctly (another PR of course :>)
> side note, I believe you can make _params readonly_cached if i read it correctly (another PR of course :>)

That is pretty much the original motivation here.  There are a couple more steps between here and there, since until we get `kwds` locked down (see WIP #17458) and make relevant attrs immutable, cache invalidation is a PITA.
thanks!