From 803ffb35a426bee5ca83b2d4191e384557353a7b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 1 Dec 2024 09:06:14 -0600 Subject: [PATCH 1/6] Drop Python 3.8 support as it has reached EOL --- .github/workflows/ci-cd.yml | 3 +-- .github/workflows/reusable-linters.yml | 2 +- .pre-commit-config.yaml | 36 +++++++++++++------------- multidict/_abc.py | 12 ++------- multidict/_multidict.c | 23 ---------------- multidict/_multidict_py.py | 9 +------ setup.cfg | 3 +-- tests/conftest.py | 12 +-------- tests/test_types.py | 14 ---------- 9 files changed, 25 insertions(+), 89 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index df4b22531..4a221a93b 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -156,7 +156,6 @@ jobs: - 3.11 - "3.10" - 3.9 - - 3.8 no-extensions: ['', 'Y'] os: [ubuntu, macos, windows] exclude: @@ -169,7 +168,7 @@ jobs: - os: windows pyver: 3.13-freethreading # this is still tested within cibuildwheel include: - - pyver: pypy-3.8 + - pyver: pypy-3.9 no-extensions: Y os: ubuntu fail-fast: false diff --git a/.github/workflows/reusable-linters.yml b/.github/workflows/reusable-linters.yml index 5df7b9cab..5b98b9da8 100644 --- a/.github/workflows/reusable-linters.yml +++ b/.github/workflows/reusable-linters.yml @@ -66,9 +66,9 @@ jobs: token: ${{ secrets.codecov-token }} files: >- .tox/.tmp/.mypy/python-3.13/cobertura.xml, + .tox/.tmp/.mypy/python-3.12/cobertura.xml .tox/.tmp/.mypy/python-3.11/cobertura.xml, .tox/.tmp/.mypy/python-3.9/cobertura.xml, - .tox/.tmp/.mypy/python-3.8/cobertura.xml flags: >- CI-GHA, MyPy diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8ab162d4e..a08ba982d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -114,7 +114,7 @@ repos: - types-docutils - lxml # dep of `--txt-report`, `--cobertura-xml-report` & `--html-report` - pytest - - pytest_codspeed + - pytest_codspeed==2.2.1 - Sphinx >= 5.3.0 args: - --python-version=3.13 @@ -122,6 +122,21 @@ repos: - --cobertura-xml-report=.tox/.tmp/.mypy/python-3.13 - --html-report=.tox/.tmp/.mypy/python-3.13 pass_filenames: false + - id: mypy + alias: mypy-py312 + name: MyPy, for Python 3.12 + additional_dependencies: + - types-docutils + - lxml # dep of `--txt-report`, `--cobertura-xml-report` & `--html-report` + - pytest + - pytest_codspeed==2.2.1 + - Sphinx >= 5.3.0 + args: + - --python-version=3.12 + - --txt-report=.tox/.tmp/.mypy/python-3.12 + - --cobertura-xml-report=.tox/.tmp/.mypy/python-3.12 + - --html-report=.tox/.tmp/.mypy/python-3.12 + pass_filenames: false - id: mypy alias: mypy-py311 name: MyPy, for Python 3.11 @@ -129,7 +144,7 @@ repos: - types-docutils - lxml # dep of `--txt-report`, `--cobertura-xml-report` & `--html-report` - pytest - - pytest_codspeed + - pytest_codspeed==2.2.1 - Sphinx >= 5.3.0 args: - --python-version=3.11 @@ -144,7 +159,7 @@ repos: - types-docutils - lxml # dep of `--txt-report`, `--cobertura-xml-report` & `--html-report` - pytest - - pytest_codspeed + - pytest_codspeed==2.2.1 - Sphinx >= 5.3.0 args: - --python-version=3.9 @@ -152,20 +167,5 @@ repos: - --cobertura-xml-report=.tox/.tmp/.mypy/python-3.9 - --html-report=.tox/.tmp/.mypy/python-3.9 pass_filenames: false - - id: mypy - alias: mypy-py38 - name: MyPy, for Python 3.8 - additional_dependencies: - - types-docutils - - lxml # dep of `--txt-report`, `--cobertura-xml-report` & `--html-report` - - pytest - - pytest_codspeed - - Sphinx >= 5.3.0 - args: - - --python-version=3.8 - - --txt-report=.tox/.tmp/.mypy/python-3.8 - - --cobertura-xml-report=.tox/.tmp/.mypy/python-3.8 - - --html-report=.tox/.tmp/.mypy/python-3.8 - pass_filenames: false ... diff --git a/multidict/_abc.py b/multidict/_abc.py index 0603cdd24..718f86f92 100644 --- a/multidict/_abc.py +++ b/multidict/_abc.py @@ -1,5 +1,4 @@ import abc -import sys import types from collections.abc import Mapping, MutableMapping @@ -9,15 +8,8 @@ class _TypingMeta(abc.ABCMeta): # basically MultiMapping[str] and other generic-like type instantiations # are emulated. # Note: real type hints are provided by __init__.pyi stub file - if sys.version_info >= (3, 9): - - def __getitem__(self, key): - return types.GenericAlias(self, key) - - else: - - def __getitem__(self, key): - return self + def __getitem__(self, key): + return types.GenericAlias(self, key) class MultiMapping(Mapping, metaclass=_TypingMeta): diff --git a/multidict/_multidict.c b/multidict/_multidict.c index 1507d7b7f..100509bd9 100644 --- a/multidict/_multidict.c +++ b/multidict/_multidict.c @@ -775,21 +775,13 @@ static inline void multidict_tp_dealloc(MultiDictObject *self) { PyObject_GC_UnTrack(self); -#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 9 Py_TRASHCAN_BEGIN(self, multidict_tp_dealloc) -#else - Py_TRASHCAN_SAFE_BEGIN(self); -#endif if (self->weaklist != NULL) { PyObject_ClearWeakRefs((PyObject *)self); }; pair_list_dealloc(&self->pairs); Py_TYPE(self)->tp_free((PyObject *)self); -#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 9 Py_TRASHCAN_END // there should be no code after this -#else - Py_TRASHCAN_SAFE_END(self); -#endif } static inline int @@ -1236,16 +1228,7 @@ PyDoc_STRVAR(multidict_update_doc, "Update the dictionary from *other*, overwriting existing keys."); -#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 9 #define multidict_class_getitem Py_GenericAlias -#else -static inline PyObject * -multidict_class_getitem(PyObject *self, PyObject *arg) -{ - Py_INCREF(self); - return self; -} -#endif PyDoc_STRVAR(sizeof__doc__, @@ -1947,9 +1930,7 @@ getversion(PyObject *self, PyObject *md) static inline void module_free(void *m) { -#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 9 Py_CLEAR(multidict_str_lower); -#endif Py_CLEAR(collections_abc_mapping); Py_CLEAR(collections_abc_mut_mapping); Py_CLEAR(collections_abc_mut_multi_mapping); @@ -1978,12 +1959,10 @@ static PyModuleDef multidict_module = { PyMODINIT_FUNC PyInit__multidict(void) { -#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 9 multidict_str_lower = PyUnicode_InternFromString("lower"); if (multidict_str_lower == NULL) { goto fail; } -#endif PyObject *module = NULL, *reg_func_call_result = NULL; @@ -2122,9 +2101,7 @@ PyInit__multidict(void) return module; fail: -#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 9 Py_XDECREF(multidict_str_lower); -#endif Py_XDECREF(collections_abc_mapping); Py_XDECREF(collections_abc_mut_mapping); Py_XDECREF(collections_abc_mut_multi_mapping); diff --git a/multidict/_multidict_py.py b/multidict/_multidict_py.py index dc26a3eac..b9e16b092 100644 --- a/multidict/_multidict_py.py +++ b/multidict/_multidict_py.py @@ -7,13 +7,6 @@ _marker = object() -if sys.version_info >= (3, 9): - GenericAlias = types.GenericAlias -else: - - def GenericAlias(cls): - return cls - class istr(str): """Case insensitive str.""" @@ -140,7 +133,7 @@ def __repr__(self): body = ", ".join("'{}': {!r}".format(k, v) for k, v in self.items()) return "<{}({})>".format(self.__class__.__name__, body) - __class_getitem__ = classmethod(GenericAlias) + __class_getitem__ = classmethod(types.GenericAlias) class MultiDictProxy(_Base, MultiMapping): diff --git a/setup.cfg b/setup.cfg index c3b7cab5b..7d642fa66 100644 --- a/setup.cfg +++ b/setup.cfg @@ -34,7 +34,6 @@ classifiers = Programming Language :: Python Programming Language :: Python :: 3 - Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 @@ -42,7 +41,7 @@ classifiers = Programming Language :: Python :: 3.13 [options] -python_requires = >= 3.8 +python_requires = >= 3.9 install_requires = typing-extensions >= 4.1.0; python_version < '3.11' packages = diff --git a/tests/conftest.py b/tests/conftest.py index c7b266d82..77670636f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -5,7 +5,6 @@ from dataclasses import dataclass from functools import cached_property from importlib import import_module -from sys import version_info as _version_info from types import ModuleType from typing import Callable, Type @@ -14,7 +13,6 @@ from multidict import MultiMapping, MutableMultiMapping C_EXT_MARK = pytest.mark.c_extension -PY_38_AND_BELOW = _version_info < (3, 9) @dataclass(frozen=True) @@ -163,20 +161,12 @@ def pytest_addoption( parser.addoption( "--c-extensions", # disabled with `--no-c-extensions` - action="store_true" if PY_38_AND_BELOW else argparse.BooleanOptionalAction, + action=argparse.BooleanOptionalAction, default=True, dest="c_extensions", help="Test C-extensions (on by default)", ) - if PY_38_AND_BELOW: - parser.addoption( - "--no-c-extensions", - action="store_false", - dest="c_extensions", - help="Skip testing C-extensions (on by default)", - ) - def pytest_collection_modifyitems( session: pytest.Session, diff --git a/tests/test_types.py b/tests/test_types.py index ceaa391e3..6d84f72ea 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -1,4 +1,3 @@ -import sys import types import pytest @@ -85,19 +84,6 @@ def test_create_ci_multidict_proxy_from_multidict(multidict_module): multidict_module.CIMultiDictProxy(d) -@pytest.mark.skipif( - sys.version_info >= (3, 9), reason="Python 3.9 uses GenericAlias which is different" -) -def test_generic_exists(multidict_module) -> None: - assert multidict_module.MultiDict[int] is multidict_module.MultiDict - assert multidict_module.MultiDictProxy[int] is multidict_module.MultiDictProxy - assert multidict_module.CIMultiDict[int] is multidict_module.CIMultiDict - assert multidict_module.CIMultiDictProxy[int] is multidict_module.CIMultiDictProxy - - -@pytest.mark.skipif( - sys.version_info < (3, 9), reason="Python 3.9 is required for GenericAlias" -) def test_generic_alias(multidict_module) -> None: assert multidict_module.MultiDict[int] == types.GenericAlias( multidict_module.MultiDict, (int,) From 517c4d1aa2e6c9ce9c36ab59f0ab9f81ab6783e3 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 1 Dec 2024 09:08:08 -0600 Subject: [PATCH 2/6] changelog --- CHANGES/1036.breaking.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 CHANGES/1036.breaking.rst diff --git a/CHANGES/1036.breaking.rst b/CHANGES/1036.breaking.rst new file mode 100644 index 000000000..b01af1538 --- /dev/null +++ b/CHANGES/1036.breaking.rst @@ -0,0 +1 @@ +Dropped Python 3.8 support as it has reached EOL -- by :user:`bdraco`. From 1c54d951d7a0bbf8f3cb36ce1ce24f6f72445d7c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 3 Dec 2024 10:23:22 -0600 Subject: [PATCH 3/6] Update .pre-commit-config.yaml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a08ba982d..646df7ec3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -129,7 +129,7 @@ repos: - types-docutils - lxml # dep of `--txt-report`, `--cobertura-xml-report` & `--html-report` - pytest - - pytest_codspeed==2.2.1 + - pytest-codspeed == 2.2.1 - Sphinx >= 5.3.0 args: - --python-version=3.12 From 987d13a6880a7af77625c22910ffd4b6229d7d72 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 3 Dec 2024 10:23:27 -0600 Subject: [PATCH 4/6] Update .pre-commit-config.yaml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 646df7ec3..0c1c759e7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -144,7 +144,7 @@ repos: - types-docutils - lxml # dep of `--txt-report`, `--cobertura-xml-report` & `--html-report` - pytest - - pytest_codspeed==2.2.1 + - pytest-codspeed == 2.2.1 - Sphinx >= 5.3.0 args: - --python-version=3.11 From 98baff1b9a080ad0fec73bb318a24577ea1a81d2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 3 Dec 2024 10:23:31 -0600 Subject: [PATCH 5/6] Update .pre-commit-config.yaml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0c1c759e7..0a664c8a9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -159,7 +159,7 @@ repos: - types-docutils - lxml # dep of `--txt-report`, `--cobertura-xml-report` & `--html-report` - pytest - - pytest_codspeed==2.2.1 + - pytest-codspeed == 2.2.1 - Sphinx >= 5.3.0 args: - --python-version=3.9 From 112e14a34ee9e04e23faeb6a8633aec936d55f85 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 3 Dec 2024 10:23:36 -0600 Subject: [PATCH 6/6] Update .pre-commit-config.yaml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0a664c8a9..84ba292b2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -114,7 +114,7 @@ repos: - types-docutils - lxml # dep of `--txt-report`, `--cobertura-xml-report` & `--html-report` - pytest - - pytest_codspeed==2.2.1 + - pytest-codspeed == 2.2.1 - Sphinx >= 5.3.0 args: - --python-version=3.13