GithubHelp home page GithubHelp logo

asottile-archive / flake8-2020 Goto Github PK

View Code? Open in Web Editor NEW
63.0 4.0 6.0 183 KB

flake8 plugin which checks for misuse of `sys.version` or `sys.version_info`

License: MIT License

Python 100.00%
flake8

flake8-2020's Introduction

ARCHIVED

3.10 is old news now and I don't plan on updating it further


build status pre-commit.ci status

flake8-2020

flake8 plugin which checks for misuse of sys.version or sys.version_info

this will become a problem when python3.10 or python4.0 exists (presumably during the year 2020).

you might also find an early build of python3.10 useful

installation

pip install flake8-2020

flake8 codes

Code Description
YTT101 sys.version[:3] referenced (python3.10)
YTT102 sys.version[2] referenced (python3.10)
YTT103 sys.version compared to string (python3.10)
YTT201 sys.version_info[0] == 3 referenced (python4)
YTT202 six.PY3 referenced (python4)
YTT203 sys.version_info[1] compared to integer (python4)
YTT204 sys.version_info.minor compared to integer (python4)
YTT301 sys.version[0] referenced (python10)
YTT302 sys.version compared to string (python10)
YTT303 sys.version[:1] referenced (python10)

rationale

lots of code incorrectly references the sys.version and sys.version_info members. in particular, this will cause some issues when the version of python after python3.9 is released. my current recommendation is 3.10 since I believe it breaks less code, here's a few patterns that will cause issues:

# in python3.10 this will report as '3.1' (should be '3.10')
python_version = sys.version[:3]  # YTT101
# in python3.10 this will report as '1' (should be '10')
py_minor = sys.version[2]
# in python3.10 this will be False (which goes against developer intention)
sys.version >= '3.5'  # YTT103


# correct way to do this
python_version = '{}.{}'.format(*sys.version_info)
py_minor = str(sys.version_info[1])
sys.version_info >= (3, 5)
# in python4 this will report as `False` (and suddenly run python2 code!)
is_py3 = sys.version_info[0] == 3  # YTT201

# in python4 this will report as `False` (six violates YTT201!)
if six.PY3:  # YTT202
    print('python3!')

if sys.version_info[0] >= 3 and sys.version_info[1] >= 5:  # YTT203
    print('py35+')

if sys.version_info.major >= 3 and sys.version_info.minor >= 6:  # YTT204
    print('py36+')

# correct way to do this
is_py3 = sys.version_info >= (3,)

if not six.PY2:
    print('python3!')

if sys.version_info >= (3, 5):
    print('py35+')

if sys.version_info >= (3, 6):
    print('py36+')
# in python10 this will report as '1'
python_major_version = sys.version[0]  # YTT301
# in python10 this will be False
if sys.version >= '3':  # YTT302
    print('python3!')
# in python10 this will be False
if sys.version[:1] >= '3':  # YTT303
    print('python3!')


# correct way to do this
python_major_version = str(sys.version_info[0])

if sys.version_info >= (3,):
    print('python3!')

if sys.version_info >= (3,):
    print('python3!')

as a pre-commit hook

See pre-commit for instructions

Sample .pre-commit-config.yaml:

-   repo: https://github.com/pycqa/flake8
    rev: 3.7.8
    hooks:
    -   id: flake8
        additional_dependencies: [flake8-2020==1.6.1]

flake8-2020's People

Contributors

adamchainz avatar asottile avatar hugovk avatar mxr avatar pre-commit-ci[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

flake8-2020's Issues

version_info.major >= 3 and version_info.minor >= 5

This is used in three places in scipy, and I've seen this sort of thing in other repos too:

if sys.version_info.major >= 3 and sys.version_info.minor >= 5:
    from math import gcd
else:
    from fractions import gcd

The if is incorrectly False for 4.0 - 4.4, 5.0 - 5.4, etc.

To fix:

-if sys.version_info.major >= 3 and sys.version_info.minor >= 5:
+if sys.version_info >= (3, 5):
     from math import gcd
 else:
     from fractions import gcd

Can this easily be detected?

Versioning is not following SemVer

Not sure whether this can be properly fixed now, but at least I'm going post is as feedback item.

I do expect libraries to follow at least some kind of semver-alike versioning. If there are breaking changes, I do expect major version to be bumped. However it's not the case with flake8-2020, we got an error when trying to update 1.6.1 -> 1.7.0:

flake8-2020 1.7.0 depends on flake8>=5

We do use flake8 less than 5, because there are other plugins (namely, wemake-python-styleguide) which require older flake8. And changing to the newer flake8 is a major version bump. This was really unexpected when flake8-2020 got a major change breaking backward compatibility without bumping its major version.

Could you please check and maybe at least somehow improve the release process to avoid such issues in the future? Ideally would be to fix current releases, but I understand this is unlikely to happen....

string comparison with `sys.version` (python3.10)

I haven't seen this one in the wild, but I think it's ~reasonably well defined for 3.0 - 3.9 so it's possible:

Python 3.5.7 (default, Mar 30 2019, 01:05:18) 
[GCC 7.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.version >= '3.5'
True
Python 3.10.0a0 (default, Jul 18 2019, 06:46:14) 
[GCC 7.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.version >= '3.5'
False

Small optimisation of YTT202

With this code:

import six
if not six.PY3:
    pass

The plugin correctly gives:

$ flake8 --select YTT 1.py
1.py:2:8: YTT202: `six.PY3` referenced (python4), use `not six.PY2`

Perhaps it could detect the not before six.PY3, and suggest a clean six.PY2 instead?

For example:

$ flake8 --select YTT 1.py
1.py:2:X: YTT20X: `not six.PY3` referenced (python4), use `six.PY2`

That is:

# Bad
if not six.PY3:

# Better (sort of)
if not not six.PY2:

# Best
if six.PY2:

Add check for float(sys.version_info.major)

I got this in a PR today:

python_version = float(sys.version_info.major) + 0.1 * float(
    sys.version_info.minor,
)

flake8-2020 doesn't catch this, would it be a welcome addition?

Add check for platform.python_version_tuple

I have observed code using platform.python_version_tuple to check version numbers, but since it is a tuple of strings it gets tripped up by Python 3.10:

>>> platform.python_version_tuple()
('3', '10', '0a3')
>>> platform.python_version_tuple() > ("3", "3")
False
>>> "10" > "3"
False
>>> platform.python_version_tuple()
('3', '8', '5')
>>> platform.python_version_tuple() > ("3", "3")
True
>>> 
>>> "8" > "3"
True

Would you be interested in having a check for this?

Check for platform.python_version[:3] (python3.10)

Very similar to YTT101, but for platform.python_version:

Python 3.10.0a2+ (heads/master:bbeb2d2, Nov 13 2020, 10:34:11)
[GCC 7.5.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import platform
>>> platform.python_version()[:3]
'3.1'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.