Skip to content

Instantly share code, notes, and snippets.

@sloria sloria/dropping_py2.md
Last active Sep 16, 2019

Embed
What would you like to do?
Checklist for dropping Python 2 in my libraries
  • Add pyupgrade to .pre-commit-config.yaml.

If supporting py35, use --py3-plus instead of --py36-plus.

- repo: https://github.com/asottile/pyupgrade
  rev: ...latest version...
  hooks:
  - id: pyupgrade
    args: [--py36-plus]
  • Run pre-commit (usually tox -e lint in my projects).
  • Remove unnecessary __future__ imports.
  • Update setup.py: remove classifiers and add/update python_requires
    python_requires=">=3.6",
  • Remove conditional installs e.g. 'flake8-bugbear==19.8.0; python_version >= "3.5"' from setup.py and pre-commit-config.yaml.
  • Update tox.ini and CI config (azure-pipelines.yml or .travis.yml).
  • Update installation/requirements and contributing docs.
  • Update pyproject.yml (black) if it exists.
  • Remove compatibility code: compat.py, sys.version_info checks, try:..except ImportError:
  • Use keyword-only arguments where sensible.
  • Update changelog.
@hugovk

This comment has been minimized.

Copy link

hugovk commented Sep 15, 2019

  • Remove compat code (e.g. compat.py) if it exists.

Some things for this:

  • Replace and remove use of six.py
  • Check try/except blocks for things like:
try:
    # Python 2
    from urlparse import urljoin
except ImportError:
    # Python 3
    from urllib.parse import urljoin

try:
    # Python 2
    basestring
except NameError:
    # Python 3
    basestring = str
@hugovk

This comment has been minimized.

Copy link

hugovk commented Sep 15, 2019

  • Remove conditional installs e.g. 'flake8-bugbear==19.8.0; python_version >= "3.5"' from setup.py and pre-commit-config.yaml.

Also check in other code for things like sys.version_info:

    @pytest.mark.skipif(
        sys.version_info < (3, 4), reason="pathlib available in >= 3.4."
    )
    def test_pathlike_path(self):
PY3 = sys.version_info[0] == 3

# Python 2.X and 3.X compatibility
if PY3:
    basestring = str
    from html import escape
else:
    from codecs import open
    from cgi import escape

I have this ugly yet useful thing in my dotfiles:

function grepv () {
if [ -z "$1" ]
  then
    # No argument supplied
    git grep -rE "version_info|python_version_tuple|python_version|PY_MAJOR_VERSION|PY_VERSION_HEX|hexversion" . "${@:3}"
else
  git grep -rIE "(py(thon)?( )?)?$1(\.?|(, ?))$2|0x0${1}0${2}0000" . "${@:3}"
fi
}

Can run it like this:

$ grepv
Tests/test_image_access.py:#if PY_MAJOR_VERSION >= 3
Tests/test_image_access.py:#if PY_MAJOR_VERSION >= 3
...

$ grepv 2 7
.appveyor.yml:  - PYTHON: C:/Python27-x64
.appveyor.yml:  - PYTHON: C:/Python27
...
@sloria

This comment has been minimized.

Copy link
Owner Author

sloria commented Sep 16, 2019

Thanks @hugovk. I don't use six in my projects, but good reminder about sys.version_info and try-excepts. Updated the list with a note about those.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.