Skip to content

Commit

Permalink
Drop workarounds for Python 3.7 and 3.8.
Browse files Browse the repository at this point in the history
Python 3.7 reached end of life 2023-06-27, and Python 3.8 reached end of
life 2023-10-07. Support for these versions was already dropped in #64,
but we can simplify the code by removing workarounds for library bugs in
those releases.
  • Loading branch information
bcmills committed Jan 22, 2025
1 parent 47fd781 commit 20f54b4
Show file tree
Hide file tree
Showing 7 changed files with 8 additions and 115 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/hatch_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9", "3.10", "3.13"]
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]

steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/mypy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9", "3.10", "3.13"]
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]

steps:
- uses: actions/checkout@v4
Expand Down
47 changes: 0 additions & 47 deletions minject/asyncio_extensions.py

This file was deleted.

2 changes: 1 addition & 1 deletion minject/inject.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import itertools
import os
from asyncio import to_thread
from typing import (
Any,
Callable,
Expand All @@ -17,7 +18,6 @@

from typing_extensions import TypeGuard, assert_type

from minject.asyncio_extensions import to_thread
from minject.types import _AsyncContext

from .metadata import _INJECT_METADATA_ATTR, RegistryMetadata, _gen_meta, _get_meta
Expand Down
52 changes: 4 additions & 48 deletions minject/inject_attrs.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import inspect
from collections import defaultdict
from dataclasses import dataclass
from sys import version_info
from typing import Any, DefaultDict, Dict, List, Optional, Type, TypeVar

from attr import define, field
Expand Down Expand Up @@ -59,17 +58,9 @@ def _get_compatible_attrs_define_kwargs() -> Dict[str, bool]:
"""
get kwargs compatible with current running version of attrs
"""
# if you are running python 3.8 or greater, use importlib.metadata
# to get the version of attrs. Otherwise, use the __version__ attribute
if version_info >= (3, 8):
from importlib.metadata import version as importlib_version # type: ignore
from importlib.metadata import version as importlib_version

attr_version = importlib_version("attrs")
else:
# this is deprecated, but we still support python 3.7
from attr import __version__ as _attr_version

attr_version = _attr_version
attr_version = importlib_version("attrs")

parsed_attr_version = version.parse(attr_version)
attrs_define_kwargs: Dict[str, bool] = {}
Expand Down Expand Up @@ -123,13 +114,6 @@ def inject_field(binding=_T, **attr_field_kwargs) -> Any:
# (If not, our inferred field name is probably wrong too!)
class_frame = stack[2]
class_lineno = _class_lineno_from_context(class_frame.code_context, class_frame.lineno)
if class_lineno is None and version_info < (3, 8):
# Python 3.7's inspect.stack is missing the stack frame for a class
# declaration with a decorator: it gives the line for the decorator
# invocation, but no line for the class declaration proper.
# As a workaround, we can scan the source file starting from the
# decorator line to find the actual class keyword.
class_lineno = _class_lineno_from_file(class_frame.filename, class_frame.lineno)
if class_lineno is None:
raise ValueError(
"Could not find the line containing the class declaration. Are you calling inject_field properly?"
Expand Down Expand Up @@ -157,36 +141,8 @@ def inject_define(
def inject_define_inner(cls: Type[_P]) -> Type[_P]:
# Identify the line containing the "class" keyword for cls: that is
# the line number that we used in the binding key for its fields.
#
# Ideally we would only use inspect.getsourcelines for this.
# Unfortunately, getsourcelines before Python 3.9 is broken for nested
# class definitions and/or class definitions with multiline strings (see
# https://github.com/python/cpython/issues/68266,
# https://github.com/python/cpython/issues/79294), so on those versions
# we fall back to reading from the source file at the line indicated by
# the stack traceback.
filename = None
class_lineno = None
if version_info < (3, 9):
stack = inspect.stack()
# The first frame is the call to inject_define_inner.
# The second frame is either inject_define itself or the
# invocation of the decorator in the user's source file.
if stack[1].function == "inject_define":
frame = stack[2]
else:
frame = stack[1]
filename = frame.filename
# In Python 3.7, the stack frame reports the line for the decorator.
# In 3.8 it reports the line for the class declaration, so we may be
# able to get it from the stack context without needing to open the
# file.
class_lineno = _class_lineno_from_context(frame.code_context, frame.lineno)
if class_lineno is None:
class_lineno = _class_lineno_from_file(frame.filename, frame.lineno)
else:
filename = inspect.getsourcefile(cls)
class_lineno = _class_lineno_from_context(*inspect.getsourcelines(cls))
filename = inspect.getsourcefile(cls)
class_lineno = _class_lineno_from_context(*inspect.getsourcelines(cls))
if filename is None or class_lineno is None:
raise ValueError(
"Could not find line containing class declaration. Are you calling inject_define properly?"
Expand Down
2 changes: 1 addition & 1 deletion minject/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

import functools
import logging
from asyncio import to_thread
from contextlib import AsyncExitStack
from textwrap import dedent
from threading import RLock
from typing import Any, Callable, Dict, Generic, Iterable, List, Optional, TypeVar, Union, cast

from typing_extensions import Concatenate, ParamSpec

from minject.asyncio_extensions import to_thread
from minject.inject import _is_key_async, _RegistryReference, reference

from .config import RegistryConfigWrapper, RegistryInitConfig
Expand Down
16 changes: 0 additions & 16 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,6 @@ dependencies = [
"typing",
]

[tool.hatch.envs.hatch-test]
dependencies = [
# The default hatch-test dependencies are not compatible with Python 3.7, a version we want to test against. Hence
# we need to specify our own dependencies here.
# https://github.com/pypa/hatch/blob/3adae6c0dfd5c20dfe9bf6bae19b44a696c22a43/src/hatch/env/internal/test.py
"coverage[toml]",
'coverage-enable-subprocess',
'pytest',
'pytest-asyncio',
'pytest-mock',
'pytest-randomly',
'pytest-asyncio',
'pytest-rerunfailures',
'pytest-xdist[psutil]',
]

[[tool.hatch.envs.hatch-test.matrix]]
python = ["3.9", "3.10", "3.11", "3.12", "3.13"]

Expand Down

0 comments on commit 20f54b4

Please sign in to comment.