From 2575bc2aa4530b71a636a9f45992082636b49281 Mon Sep 17 00:00:00 2001 From: Gavin Crooks Date: Fri, 22 Jan 2021 11:03:03 -0800 Subject: [PATCH] Remove python 3.7 support (#27) --- .github/workflows/python-build.yml | 2 +- README.md | 20 +++++++------------ .../.github/workflows/python-build.yml | 2 +- .../example_python_project/config.py | 15 ++++---------- example_python_project/setup.cfg | 4 +--- .../.github/workflows/python-build.yml | 2 +- {{cookiecutter.module_name}}/setup.cfg | 4 +--- .../{{cookiecutter.module_name}}/config.py | 15 ++++---------- 8 files changed, 20 insertions(+), 44 deletions(-) diff --git a/.github/workflows/python-build.yml b/.github/workflows/python-build.yml index 5e0db52..b1c32da 100644 --- a/.github/workflows/python-build.yml +++ b/.github/workflows/python-build.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.7', '3.8', '3.9'] + python-version: ['3.8', '3.9'] steps: - uses: actions/checkout@v2 diff --git a/README.md b/README.md index 3f7a812..0f57157 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # gecrooks-python-template: Minimal viable setup for an open source, github hosted, python package -![Build Status](https://github.com/gecrooks/gecrooks-python-template/workflows/Build/badge.svg) [![Documentation Status](https://readthedocs.org/projects/gecrooks-python-template/badge/?version=latest)](https://gecrooks-python-template.readthedocs.io/en/latest/?badge=latest) +![Build Status](https://github.com/gecrooks/gecrooks-python-template/workflows/Build/badge.svg) [Source](https://github.com/gecrooks/gecrooks-python-template) @@ -165,7 +165,6 @@ Classifiers= Natural Language :: English Operating System :: OS Independent Programming Language :: Python :: 3 - Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Topic :: Scientific/Engineering @@ -176,11 +175,10 @@ Classifiers= [options] zip_safe = True -python_requires = >= 3.7 +python_requires = >= 3.8 packages = find: install_requires = - importlib_metadata # required for python 3.7 numpy # example setup_requires = @@ -202,7 +200,7 @@ dev = ``` -It's good practice to support at least two consecutive versions of python. Starting with 3.9, python is moving to an annual [release schedule](https://www.python.org/dev/peps/pep-0602/). The initial 3.x.0 release will be in early October and the first bug patch 3.x.1 in early December, second in February, and so on. Since it takes many important packages some time to upgrade (e.g. numpy and tensorflow are often bottlenecks), one should probably plan to upgrade python support by February each year. Upgrading involves changing the python version numbers in the tests and `config.cfg`, and then cleaning up any `__future__` or conditional imports, or other hacks added to maintain compatibility with older python releases. +It's good practice to support at least two consecutive versions of python. Starting with 3.9, python is moving to an annual [release schedule](https://www.python.org/dev/peps/pep-0602/). The initial 3.x.0 release will be in early October and the first bug patch 3.x.1 in early December, second in February, and so on. Since it takes many important packages some time to upgrade (e.g. numpy and tensorflow are often bottlenecks), one should probably plan to upgrade python support around the beginning of each year. Upgrading involves changing the python version numbers in the tests and `config.cfg`, and then cleaning up any `__future__` or conditional imports, or other hacks added to maintain compatibility with older python releases. If you protected the master branch on github, and added required status checks, you'll need to update those too. We can now install our package (as editable -e, so that the code in our repo is live). @@ -223,12 +221,8 @@ My favored approach is use git tags as the source of truth (Option 7 in the abov The convention is that the version number of a python packages should be available as `packagename.__version__`. So we add the following code to `example_python_project/config.py` to extract the version number metadata. ``` -try: - # python >= 3.8 - from importlib import metadata as importlib_metadata # type: ignore -except ImportError: # pragma: no cover - # python == 3.7 - import importlib_metadata # type: ignore # noqa: F401 + +from importlib import metadata as importlib_metadata __all__ = ["__version__", "about"] @@ -250,7 +244,7 @@ from .config import __version__ as __version__ # noqa: F401 ``` We put the code to extract the version number in `config.py` and not `__init__.py`, because we don't want to pollute our top level package namespace. -The various pragmas in the code above ("pragma: no cover" and "type: ignore") are there because the conditional import needed for python 3.7 compatibility confuses both our type checker and code coverage tools. +The various pragmas in the code above ("pragma: no cover" and "type: ignore") are there because the conditional imports confuse both our type checker and code coverage tools. ## about @@ -527,7 +521,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.7', '3.8'] + python-version: ['3.8', '3.9'] steps: - uses: actions/checkout@v2 diff --git a/example_python_project/.github/workflows/python-build.yml b/example_python_project/.github/workflows/python-build.yml index 8d1ba89..38e64cf 100644 --- a/example_python_project/.github/workflows/python-build.yml +++ b/example_python_project/.github/workflows/python-build.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.7', '3.8', '3.9'] + python-version: ['3.8', '3.9'] steps: - uses: actions/checkout@v2 diff --git a/example_python_project/example_python_project/config.py b/example_python_project/example_python_project/config.py index dfb786d..6b7c6c8 100644 --- a/example_python_project/example_python_project/config.py +++ b/example_python_project/example_python_project/config.py @@ -11,14 +11,7 @@ import re import sys import typing - -try: - # python >= 3.8 - from importlib import metadata as importlib_metadata # type: ignore -except ImportError: # pragma: no cover - # python == 3.7 - import importlib_metadata # type: ignore # noqa: F401 - +from importlib import metadata as importlib_metadata __all__ = ["__version__", "about"] @@ -38,7 +31,7 @@ def about(file: typing.TextIO = None) -> None: Args: file: Output stream (Defaults to stdout) """ - metadata = importlib_metadata.metadata(__package__) # type: ignore + metadata = importlib_metadata.metadata(__package__) print(f"# {metadata['Name']}", file=file) print(f"{metadata['Summary']}", file=file) print(f"{metadata['Home-page']}", file=file) @@ -49,10 +42,10 @@ def about(file: typing.TextIO = None) -> None: versions[__package__] = __version__ versions["python"] = sys.version[0:5] - for req in importlib_metadata.requires(__package__): # type: ignore + for req in importlib_metadata.requires(__package__): name = re.split("[; =><]", req)[0] try: - versions[name] = importlib_metadata.version(name) # type: ignore + versions[name] = importlib_metadata.version(name) except Exception: # pragma: no cover pass diff --git a/example_python_project/setup.cfg b/example_python_project/setup.cfg index 185dd90..29e8710 100644 --- a/example_python_project/setup.cfg +++ b/example_python_project/setup.cfg @@ -30,7 +30,6 @@ Classifiers= Natural Language :: English Operating System :: OS Independent Programming Language :: Python :: 3 - Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Topic :: Scientific/Engineering @@ -43,11 +42,10 @@ Classifiers= [options] zip_safe = True -python_requires = >= 3.7 +python_requires = >= 3.8 packages = find: install_requires = - importlib_metadata # required for python 3.7 numpy # example setup_requires = diff --git a/{{cookiecutter.module_name}}/.github/workflows/python-build.yml b/{{cookiecutter.module_name}}/.github/workflows/python-build.yml index 6455867..82f5ed4 100644 --- a/{{cookiecutter.module_name}}/.github/workflows/python-build.yml +++ b/{{cookiecutter.module_name}}/.github/workflows/python-build.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.7', '3.8', '3.9'] + python-version: ['3.8', '3.9'] steps: - uses: actions/checkout@v2 diff --git a/{{cookiecutter.module_name}}/setup.cfg b/{{cookiecutter.module_name}}/setup.cfg index 1ce23de..4278324 100644 --- a/{{cookiecutter.module_name}}/setup.cfg +++ b/{{cookiecutter.module_name}}/setup.cfg @@ -30,7 +30,6 @@ Classifiers= Natural Language :: English Operating System :: OS Independent Programming Language :: Python :: 3 - Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Topic :: Scientific/Engineering @@ -43,11 +42,10 @@ Classifiers= [options] zip_safe = True -python_requires = >= 3.7 +python_requires = >= 3.8 packages = find: install_requires = - importlib_metadata # required for python 3.7 numpy # example setup_requires = diff --git a/{{cookiecutter.module_name}}/{{cookiecutter.module_name}}/config.py b/{{cookiecutter.module_name}}/{{cookiecutter.module_name}}/config.py index c47232a..591f8a5 100644 --- a/{{cookiecutter.module_name}}/{{cookiecutter.module_name}}/config.py +++ b/{{cookiecutter.module_name}}/{{cookiecutter.module_name}}/config.py @@ -11,14 +11,7 @@ import re import sys import typing - -try: - # python >= 3.8 - from importlib import metadata as importlib_metadata # type: ignore -except ImportError: # pragma: no cover - # python == 3.7 - import importlib_metadata # type: ignore # noqa: F401 - +from importlib import metadata as importlib_metadata __all__ = ["__version__", "about"] @@ -38,7 +31,7 @@ def about(file: typing.TextIO = None) -> None: Args: file: Output stream (Defaults to stdout) """ - metadata = importlib_metadata.metadata(__package__) # type: ignore + metadata = importlib_metadata.metadata(__package__) print(f"# {metadata['Name']}", file=file) print(f"{metadata['Summary']}", file=file) print(f"{metadata['Home-page']}", file=file) @@ -49,10 +42,10 @@ def about(file: typing.TextIO = None) -> None: versions[__package__] = __version__ versions["python"] = sys.version[0:5] - for req in importlib_metadata.requires(__package__): # type: ignore + for req in importlib_metadata.requires(__package__): name = re.split("[; =><]", req)[0] try: - versions[name] = importlib_metadata.version(name) # type: ignore + versions[name] = importlib_metadata.version(name) except Exception: # pragma: no cover pass