Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop support for Python 3.8 #2443

Merged
merged 7 commits into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [3.8, 3.9, "3.10", "3.11", "3.12"]
python-version: [3.9, "3.10", "3.11", "3.12"]
outputs:
python-key: ${{ steps.generate-python-key.outputs.key }}
steps:
Expand Down Expand Up @@ -138,7 +138,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [3.8, 3.9, "3.10", "3.11", "3.12"]
python-version: [3.9, "3.10", "3.11", "3.12"]
steps:
- name: Set temp directory
run: echo "TEMP=$env:USERPROFILE\AppData\Local\Temp" >> $env:GITHUB_ENV
Expand Down Expand Up @@ -192,7 +192,7 @@ jobs:
fail-fast: false
matrix:
# We only test on the lowest and highest supported PyPy versions
python-version: ["pypy3.8", "pypy3.10"]
python-version: ["pypy3.9", "pypy3.10"]
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.5
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ repos:
hooks:
- id: pyupgrade
exclude: tests/testdata
args: [--py38-plus]
args: [--py39-plus]
- repo: https://github.com/Pierre-Sassoulas/black-disable-checker/
rev: v1.1.3
hooks:
Expand Down
12 changes: 3 additions & 9 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,15 @@ What's New in astroid 3.3.0?
============================
Release date: TBA

* Remove support for Python 3.8.

Refs #2443


What's New in astroid 3.2.2?
============================
Release date: TBA

* Fix ``RecursionError`` in ``infer_call_result()`` for certain ``__call__`` methods.

Closes pylint-dev/pylint#9139

* Add ``AstroidManager.prefer_stubs`` attribute to control the astroid 3.2.0 feature that prefers stubs.

Refs pylint-dev/#9626
Refs pylint-dev/#9623

jacobtylerwalls marked this conversation as resolved.
Show resolved Hide resolved

What's New in astroid 3.2.1?
============================
Expand Down
6 changes: 1 addition & 5 deletions astroid/_backport_stdlib_names.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,11 +346,7 @@
}
)

if sys.version_info[:2] == (3, 7):
stdlib_module_names = PY_3_7
elif sys.version_info[:2] == (3, 8):
stdlib_module_names = PY_3_8
elif sys.version_info[:2] == (3, 9):
if sys.version_info[:2] == (3, 9):
stdlib_module_names = PY_3_9
else:
raise AssertionError("This module is only intended as a backport for Python <= 3.9")
jacobtylerwalls marked this conversation as resolved.
Show resolved Hide resolved
12 changes: 6 additions & 6 deletions astroid/brain/brain_builtin_inference.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
from __future__ import annotations

import itertools
from collections.abc import Callable, Iterable
from collections.abc import Callable, Iterable, Iterator
from functools import partial
from typing import TYPE_CHECKING, Any, Iterator, NoReturn, Type, Union, cast
from typing import TYPE_CHECKING, Any, NoReturn, Type, Union, cast

from astroid import arguments, helpers, inference_tip, nodes, objects, util
from astroid.builder import AstroidBuilder
Expand Down Expand Up @@ -40,10 +40,10 @@
]

BuiltContainers = Union[
Type[tuple],
Type[list],
Type[set],
Type[frozenset],
type[tuple],
type[list],
type[set],
type[frozenset],
]

CopyResult = Union[
Expand Down
24 changes: 9 additions & 15 deletions astroid/brain/brain_collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

from astroid.brain.helpers import register_module_extender
from astroid.builder import extract_node, parse
from astroid.const import PY39_PLUS
from astroid.context import InferenceContext
from astroid.exceptions import AttributeInferenceError
from astroid.manager import AstroidManager
Expand Down Expand Up @@ -61,9 +60,7 @@ def __add__(self, other): pass
def __iadd__(self, other): pass
def __mul__(self, other): pass
def __imul__(self, other): pass
def __rmul__(self, other): pass"""
if PY39_PLUS:
base_deque_class += """
def __rmul__(self, other): pass
@classmethod
def __class_getitem__(self, item): return cls"""
return base_deque_class
Expand All @@ -73,9 +70,7 @@ def _ordered_dict_mock():
base_ordered_dict_class = """
class OrderedDict(dict):
def __reversed__(self): return self[::-1]
def move_to_end(self, key, last=False): pass"""
if PY39_PLUS:
base_ordered_dict_class += """
def move_to_end(self, key, last=False): pass
@classmethod
def __class_getitem__(cls, item): return cls"""
return base_ordered_dict_class
Expand Down Expand Up @@ -116,11 +111,10 @@ def easy_class_getitem_inference(node, context: InferenceContext | None = None):
def register(manager: AstroidManager) -> None:
register_module_extender(manager, "collections", _collections_transform)

if PY39_PLUS:
# Starting with Python39 some objects of the collection module are subscriptable
# thanks to the __class_getitem__ method but the way it is implemented in
# _collection_abc makes it difficult to infer. (We would have to handle AssignName inference in the
# getitem method of the ClassDef class) Instead we put here a mock of the __class_getitem__ method
manager.register_transform(
ClassDef, easy_class_getitem_inference, _looks_like_subscriptable
)
# Starting with Python39 some objects of the collection module are subscriptable
# thanks to the __class_getitem__ method but the way it is implemented in
# _collection_abc makes it difficult to infer. (We would have to handle AssignName inference in the
# getitem method of the ClassDef class) Instead we put here a mock of the __class_getitem__ method
manager.register_transform(
ClassDef, easy_class_getitem_inference, _looks_like_subscriptable
)
28 changes: 9 additions & 19 deletions astroid/brain/brain_dataclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
from __future__ import annotations

from collections.abc import Iterator
from typing import Literal, Tuple, Union
from typing import Literal, Union

from astroid import bases, context, nodes
from astroid.builder import parse
from astroid.const import PY39_PLUS, PY310_PLUS
from astroid.const import PY310_PLUS
from astroid.exceptions import AstroidSyntaxError, InferenceError, UseInferenceDefault
from astroid.inference_tip import inference_tip
from astroid.manager import AstroidManager
Expand All @@ -28,8 +28,8 @@

_FieldDefaultReturn = Union[
None,
Tuple[Literal["default"], nodes.NodeNG],
Tuple[Literal["default_factory"], nodes.Call],
tuple[Literal["default"], nodes.NodeNG],
tuple[Literal["default_factory"], nodes.Call],
]

DATACLASSES_DECORATORS = frozenset(("dataclass",))
Expand Down Expand Up @@ -539,22 +539,12 @@ def _get_field_default(field_call: nodes.Call) -> _FieldDefaultReturn:

def _is_class_var(node: nodes.NodeNG) -> bool:
"""Return True if node is a ClassVar, with or without subscripting."""
if PY39_PLUS:
try:
inferred = next(node.infer())
except (InferenceError, StopIteration):
return False

return getattr(inferred, "name", "") == "ClassVar"
try:
inferred = next(node.infer())
except (InferenceError, StopIteration):
return False

# Before Python 3.9, inference returns typing._SpecialForm instead of ClassVar.
# Our backup is to inspect the node's structure.
return isinstance(node, nodes.Subscript) and (
isinstance(node.value, nodes.Name)
and node.value.name == "ClassVar"
or isinstance(node.value, nodes.Attribute)
and node.value.attrname == "ClassVar"
)
return getattr(inferred, "name", "") == "ClassVar"


def _is_keyword_only_sentinel(node: nodes.NodeNG) -> bool:
Expand Down
3 changes: 1 addition & 2 deletions astroid/brain/brain_hashlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@

from astroid.brain.helpers import register_module_extender
from astroid.builder import parse
from astroid.const import PY39_PLUS
from astroid.manager import AstroidManager


def _hashlib_transform():
maybe_usedforsecurity = ", usedforsecurity=True" if PY39_PLUS else ""
maybe_usedforsecurity = ", usedforsecurity=True"
jacobtylerwalls marked this conversation as resolved.
Show resolved Hide resolved
init_signature = f"value=''{maybe_usedforsecurity}"
digest_signature = "self"
shake_digest_signature = "self, length"
Expand Down
7 changes: 3 additions & 4 deletions astroid/brain/brain_re.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from astroid import context, inference_tip, nodes
from astroid.brain.helpers import register_module_extender
from astroid.builder import _extract_single_node, parse
from astroid.const import PY39_PLUS, PY311_PLUS
from astroid.const import PY311_PLUS
from astroid.manager import AstroidManager


Expand Down Expand Up @@ -84,9 +84,8 @@ def infer_pattern_match(node: nodes.Call, ctx: context.InferenceContext | None =
end_lineno=node.end_lineno,
end_col_offset=node.end_col_offset,
)
if PY39_PLUS:
func_to_add = _extract_single_node(CLASS_GETITEM_TEMPLATE)
class_def.locals["__class_getitem__"] = [func_to_add]
func_to_add = _extract_single_node(CLASS_GETITEM_TEMPLATE)
class_def.locals["__class_getitem__"] = [func_to_add]
return iter([class_def])


Expand Down
6 changes: 2 additions & 4 deletions astroid/brain/brain_regex.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from astroid import context, inference_tip, nodes
from astroid.brain.helpers import register_module_extender
from astroid.builder import _extract_single_node, parse
from astroid.const import PY39_PLUS
from astroid.manager import AstroidManager


Expand Down Expand Up @@ -83,9 +82,8 @@ def infer_pattern_match(node: nodes.Call, ctx: context.InferenceContext | None =
end_lineno=node.end_lineno,
end_col_offset=node.end_col_offset,
)
if PY39_PLUS:
func_to_add = _extract_single_node(CLASS_GETITEM_TEMPLATE)
class_def.locals["__class_getitem__"] = [func_to_add]
func_to_add = _extract_single_node(CLASS_GETITEM_TEMPLATE)
class_def.locals["__class_getitem__"] = [func_to_add]
return iter([class_def])


Expand Down
10 changes: 4 additions & 6 deletions astroid/brain/brain_subprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from astroid.brain.helpers import register_module_extender
from astroid.builder import parse
from astroid.const import PY39_PLUS, PY310_PLUS, PY311_PLUS
from astroid.const import PY310_PLUS, PY311_PLUS
from astroid.manager import AstroidManager


Expand All @@ -17,10 +17,9 @@ def _subprocess_transform():
self, args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None,
preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None,
universal_newlines=None, startupinfo=None, creationflags=0, restore_signals=True,
start_new_session=False, pass_fds=(), *, encoding=None, errors=None, text=None"""
start_new_session=False, pass_fds=(), *, encoding=None, errors=None, text=None,
user=None, group=None, extra_groups=None, umask=-1"""

if PY39_PLUS:
args += ", user=None, group=None, extra_groups=None, umask=-1"
if PY310_PLUS:
args += ", pipesize=-1"
if PY311_PLUS:
Expand Down Expand Up @@ -89,8 +88,7 @@ def kill(self):
{ctx_manager}
"""
)
if PY39_PLUS:
code += """
code += """
@classmethod
def __class_getitem__(cls, item):
pass
jacobtylerwalls marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
8 changes: 3 additions & 5 deletions astroid/brain/brain_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
from __future__ import annotations

from astroid import extract_node, inference_tip, nodes
from astroid.const import PY39_PLUS
from astroid.context import InferenceContext
from astroid.exceptions import UseInferenceDefault
from astroid.manager import AstroidManager
Expand Down Expand Up @@ -64,7 +63,6 @@ def __class_getitem__(cls, key):


def register(manager: AstroidManager) -> None:
if PY39_PLUS:
manager.register_transform(
nodes.Name, inference_tip(infer_type_sub), _looks_like_type_subscript
)
manager.register_transform(
nodes.Name, inference_tip(infer_type_sub), _looks_like_type_subscript
)
45 changes: 11 additions & 34 deletions astroid/brain/brain_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from astroid import context, extract_node, inference_tip
from astroid.brain.helpers import register_module_extender
from astroid.builder import AstroidBuilder, _extract_single_node
from astroid.const import PY39_PLUS, PY312_PLUS
from astroid.const import PY312_PLUS
from astroid.exceptions import (
AstroidSyntaxError,
AttributeInferenceError,
Expand All @@ -33,7 +33,6 @@
Name,
NodeNG,
Subscript,
Tuple,
)
from astroid.nodes.scoped_nodes import ClassDef, FunctionDef

Expand Down Expand Up @@ -314,13 +313,7 @@ def infer_typing_alias(
class_def.postinit(bases=[res], body=[], decorators=None)

maybe_type_var = node.args[1]
if (
not PY39_PLUS
and not (isinstance(maybe_type_var, Tuple) and not maybe_type_var.elts)
or PY39_PLUS
and isinstance(maybe_type_var, Const)
and maybe_type_var.value > 0
):
if isinstance(maybe_type_var, Const) and maybe_type_var.value > 0:
# If typing alias is subscriptable, add `__class_getitem__` to ClassDef
func_to_add = _extract_single_node(CLASS_GETITEM_TEMPLATE)
class_def.locals["__class_getitem__"] = [func_to_add]
Expand Down Expand Up @@ -348,23 +341,12 @@ def _looks_like_special_alias(node: Call) -> bool:
PY39: Callable = _CallableType(collections.abc.Callable, 2)
"""
return isinstance(node.func, Name) and (
not PY39_PLUS
and node.func.name == "_VariadicGenericAlias"
and (
isinstance(node.args[0], Name)
and node.args[0].name == "tuple"
or isinstance(node.args[0], Attribute)
and node.args[0].as_string() == "collections.abc.Callable"
)
or PY39_PLUS
and (
node.func.name == "_TupleType"
and isinstance(node.args[0], Name)
and node.args[0].name == "tuple"
or node.func.name == "_CallableType"
and isinstance(node.args[0], Attribute)
and node.args[0].as_string() == "collections.abc.Callable"
)
node.func.name == "_TupleType"
and isinstance(node.args[0], Name)
and node.args[0].name == "tuple"
or node.func.name == "_CallableType"
and isinstance(node.args[0], Attribute)
and node.args[0].as_string() == "collections.abc.Callable"
)


Expand Down Expand Up @@ -472,14 +454,9 @@ def register(manager: AstroidManager) -> None:
Call, inference_tip(infer_typing_cast), _looks_like_typing_cast
)

if PY39_PLUS:
manager.register_transform(
FunctionDef, inference_tip(infer_typedDict), _looks_like_typedDict
)
else:
manager.register_transform(
ClassDef, inference_tip(infer_old_typedDict), _looks_like_typedDict
)
jacobtylerwalls marked this conversation as resolved.
Show resolved Hide resolved
manager.register_transform(
FunctionDef, inference_tip(infer_typedDict), _looks_like_typedDict
)

manager.register_transform(
Call, inference_tip(infer_typing_alias), _looks_like_typing_alias
Expand Down
Loading
Loading