CLN: Use pandas.compat instead of sys.version_info for Python version checks
State: closed

Hopefully this will make code changes related to dropping support for specific versions of Python slightly easier to identify.

Summary:
  - Replaced instances `sys.version_info` with equivalent checks from `pandas.compat`
  - Removed code blocks specific to unsupported versions of Python (<2.7, 3.0-3.4)

<br />
There were some very specific examples that I left as-is:

https://github.com/pandas-dev/pandas/blob/c4b4a81f56205082ec7f12bf77766e3b74d27c37/pandas/tests/io/formats/test_to_csv.py#L13

Didn't change any Cython related code, as it appears that we want to avoid imports from outside `_libs`:
https://github.com/pandas-dev/pandas/blob/c4b4a81f56205082ec7f12bf77766e3b74d27c37/pandas/_libs/tslibs/parsing.pyx#L25-L26

Labels:
name: Testing
description: pandas testing functions or related to the test suite
name: Compat
description: pandas objects compatability with Numpy or Python functions

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

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

```diff
@@            Coverage Diff             @@
##           master   #20545      +/-   ##
==========================================
- Coverage   91.84%   91.81%   -0.03%     
==========================================
  Files         152      152              
  Lines       49268    49266       -2     
==========================================
- Hits        45250    45236      -14     
- Misses       4018     4030      +12
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `90.2% <100%> (-0.03%)` | :arrow_down: |
| #single | `41.89% <100%> (-0.01%)` | :arrow_down: |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/20545?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/io/formats/terminal.py](https://codecov.io/gh/pandas-dev/pandas/pull/20545/diff?src=pr&el=tree#diff-cGFuZGFzL2lvL2Zvcm1hdHMvdGVybWluYWwucHk=) | `20.98% <100%> (ø)` | :arrow_up: |
| [pandas/util/testing.py](https://codecov.io/gh/pandas-dev/pandas/pull/20545/diff?src=pr&el=tree#diff-cGFuZGFzL3V0aWwvdGVzdGluZy5weQ==) | `84.73% <100%> (ø)` | :arrow_up: |
| [pandas/compat/\_\_init\_\_.py](https://codecov.io/gh/pandas-dev/pandas/pull/20545/diff?src=pr&el=tree#diff-cGFuZGFzL2NvbXBhdC9fX2luaXRfXy5weQ==) | `57.74% <100%> (ø)` | :arrow_up: |
| [pandas/io/clipboard/clipboards.py](https://codecov.io/gh/pandas-dev/pandas/pull/20545/diff?src=pr&el=tree#diff-cGFuZGFzL2lvL2NsaXBib2FyZC9jbGlwYm9hcmRzLnB5) | `30.58% <100%> (-1.6%)` | :arrow_down: |
| [pandas/plotting/\_converter.py](https://codecov.io/gh/pandas-dev/pandas/pull/20545/diff?src=pr&el=tree#diff-cGFuZGFzL3Bsb3R0aW5nL19jb252ZXJ0ZXIucHk=) | `65.07% <0%> (-1.74%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/20545?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/20545?src=pr&el=footer). Last update [d7a4f5b...6cf2e98](https://codecov.io/gh/pandas-dev/pandas/pull/20545?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

lgtm. the only thing would add is if you can fail ``lint.sh`` on a grep for ``sys.version_info`` would be great (might need to exclude the .pyx for now on that though)
I can add a check for this to `lint.sh`.  There are a situations where `sys.version_info` is still valid though, as there are some very specific checks that probably don't make sense to encode in `pandas.compat`, eg:
https://github.com/pandas-dev/pandas/blob/c4b4a81f56205082ec7f12bf77766e3b74d27c37/pandas/tests/io/formats/test_to_csv.py#L13

This would get caught by `lint.sh`, but I'm guessing we'd rather be more aggressive here, and selectively allow failing cases to be merged when appropriate?  I'm assuming (possibly mistakenly) that `lint.sh` only runs over newly added code?  If it hits the entire codebase, we might not want to do this since the corner cases will fail every time.  I suppose I could try checking for specific examples that are clearly invalid if this is the case, though it seems like that could get out of sync as support for versions are added/dropped.
we have a PY35 already. guess could just exclude this file) The lint check just enforces that the code all uses the same pattern, don't like to have people making up ways to do very standard things (and docs on how to do things like this, while helpful, get out of date), better to have an actual check.

no ``lint.sh`` runs over ALL code. as i said, you might need to exclude ``.pyx`` files as we (can't) import ``pandas.compat`` there, but otherwise I see no reason not to enforce this (and if there is a specific case pls point it out).
The example I showed is actually different than `PY35`.  It's only skipping for 3.5-3.6.4; the test should pass for 2.7 and 3.6.5+.  Something like `PY2 or PY365` would work, so it'd be a matter of adding `PY365`.

That actually looks like the only oddly specific case of a version check.  The only other non-`pandas.compat` instance of `sys.version_info` that I can't get rid of is in `util/_print_versions.py`:
https://github.com/pandas-dev/pandas/blob/0a003651a67854b9776c46469a18e20ffd61f141/pandas/util/_print_versions.py#L41

Could either skip that file or create a variable like `PYVERSION = sys.version_info` in `pandas.compat` and import; seems like `PYVERSION` could just be abused like `sys.version_info` though, so will go with the skip route unless told otherwise. 
yeah have special cases is a bit annoying. how about you just remove the remaining ones that are possible? and leave lint.sh alone is ok.
Added some small fixes for the remaining easily removable instances of `sys.version_info`.
great. can you rebase. just merged a patch which conflicts. 
rebased and made the requested change
thanks!