From 3ff19e4ca34fde316881d916f9df22d3104d6464 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Mon, 24 Apr 2023 22:36:24 +0200 Subject: Drop support for Python 3.7 (#8609) * Drop support for Python 3.7 * Update py-version + classifier * Update functional tests --- .github/workflows/primer_run_main.yaml | 2 +- .github/workflows/primer_run_pr.yaml | 2 +- .github/workflows/tests.yaml | 8 ++++---- .pre-commit-config.yaml | 2 +- README.rst | 2 +- doc/exts/pylint_extensions.py | 7 +------ doc/whatsnew/fragments/6306.breaking | 3 +++ pylint/checkers/__init__.py | 8 +------- pylint/checkers/base/basic_checker.py | 8 +------- pylint/checkers/base/docstring_checker.py | 7 +------ pylint/checkers/classes/class_checker.py | 7 +------ pylint/checkers/format.py | 7 +------ pylint/checkers/imports.py | 6 +----- pylint/checkers/logging.py | 8 +------- pylint/checkers/raw_metrics.py | 8 +------- pylint/checkers/refactoring/refactoring_checker.py | 7 +------ pylint/checkers/spelling.py | 8 +------- pylint/checkers/strings.py | 8 +------- pylint/checkers/typecheck.py | 11 ++--------- pylint/checkers/utils.py | 2 +- pylint/checkers/variables.py | 7 +------ pylint/config/_pylint_config/utils.py | 7 +------ pylint/config/argument.py | 9 +-------- pylint/lint/message_state_handler.py | 9 +-------- pylint/lint/pylinter.py | 8 +------- pylint/reporters/json_reporter.py | 8 +------- pylint/testutils/_primer/package_to_lint.py | 7 +------ pylint/testutils/_primer/primer_command.py | 8 +------- pylint/testutils/functional/test_file.py | 8 +------- pylint/testutils/pyreverse.py | 8 +------- pylint/testutils/unittest_linter.py | 8 +------- pylint/typing.py | 9 +++------ pylint/utils/file_state.py | 8 +------- pylint/utils/linterstats.py | 8 +------- pylint/utils/utils.py | 17 +++++++++++------ pylintrc | 3 ++- pyproject.toml | 3 +-- tests/functional/b/bad_reversed_sequence_py37.py | 4 ++-- tests/functional/b/bad_reversed_sequence_py37.rc | 4 ++-- tests/functional/b/bad_reversed_sequence_py37.txt | 1 - .../s/singledispatch/singledispatch_method_py37.rc | 4 ++-- .../s/star/star_needs_assignment_target_py37.py | 15 --------------- .../s/star/star_needs_assignment_target_py37.rc | 2 -- .../s/star/star_needs_assignment_target_py37.txt | 1 - .../s/star/star_needs_assignment_target_py38.py | 15 +++++++++++++++ .../s/star/star_needs_assignment_target_py38.rc | 2 ++ .../s/star/star_needs_assignment_target_py38.txt | 1 + tests/functional/u/undefined/undefined_loop_variable.py | 7 +------ .../functional/u/undefined/undefined_loop_variable.txt | 8 ++++---- tests/test_pylint_runners.py | 7 +------ tests/test_self.py | 10 +--------- tests/testutils/test_output_line.py | 7 +------ tox.ini | 2 +- 53 files changed, 89 insertions(+), 257 deletions(-) create mode 100644 doc/whatsnew/fragments/6306.breaking delete mode 100644 tests/functional/s/star/star_needs_assignment_target_py37.py delete mode 100644 tests/functional/s/star/star_needs_assignment_target_py37.rc delete mode 100644 tests/functional/s/star/star_needs_assignment_target_py37.txt create mode 100644 tests/functional/s/star/star_needs_assignment_target_py38.py create mode 100644 tests/functional/s/star/star_needs_assignment_target_py38.rc create mode 100644 tests/functional/s/star/star_needs_assignment_target_py38.txt diff --git a/.github/workflows/primer_run_main.yaml b/.github/workflows/primer_run_main.yaml index 1570f2ad5..dfb857424 100644 --- a/.github/workflows/primer_run_main.yaml +++ b/.github/workflows/primer_run_main.yaml @@ -29,7 +29,7 @@ jobs: timeout-minutes: 120 strategy: matrix: - python-version: ["3.7", "3.11"] + python-version: ["3.8", "3.11"] steps: - name: Check out code from GitHub uses: actions/checkout@v3.5.2 diff --git a/.github/workflows/primer_run_pr.yaml b/.github/workflows/primer_run_pr.yaml index 71bc8ec7b..d9583579e 100644 --- a/.github/workflows/primer_run_pr.yaml +++ b/.github/workflows/primer_run_pr.yaml @@ -38,7 +38,7 @@ jobs: timeout-minutes: 120 strategy: matrix: - python-version: ["3.7", "3.11"] + python-version: ["3.8", "3.11"] steps: - name: Check out code from GitHub uses: actions/checkout@v3.5.2 diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 3461fdab7..09beec919 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -31,7 +31,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.7, 3.8, 3.9, "3.10", "3.11"] + python-version: [3.8, 3.9, "3.10", "3.11"] outputs: python-key: ${{ steps.generate-python-key.outputs.key }} steps: @@ -175,7 +175,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.7, 3.8, 3.9, "3.10", "3.11"] + python-version: [3.8, 3.9, "3.10", "3.11"] steps: - name: Set temp directory run: echo "TEMP=$env:USERPROFILE\AppData\Local\Temp" >> $env:GITHUB_ENV @@ -225,7 +225,7 @@ jobs: fail-fast: false matrix: # We only run on the oldest supported version on Mac - python-version: [3.7] + python-version: [3.8] steps: - name: Check out code from GitHub uses: actions/checkout@v3.5.2 @@ -269,7 +269,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["pypy-3.7", "pypy-3.8", "pypy-3.9"] + python-version: ["pypy-3.8", "pypy-3.9"] steps: - name: Check out code from GitHub uses: actions/checkout@v3.5.2 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 556bccc60..c39b8c434 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -39,7 +39,7 @@ repos: rev: v3.3.1 hooks: - id: pyupgrade - args: [--py37-plus] + args: [--py38-plus] exclude: *fixtures - repo: https://github.com/PyCQA/isort rev: 5.12.0 diff --git a/README.rst b/README.rst index d4e3c83ee..740f7f308 100644 --- a/README.rst +++ b/README.rst @@ -45,7 +45,7 @@ What is Pylint? --------------- Pylint is a `static code analyser`_ for Python 2 or 3. The latest version supports Python -3.7.2 and above. +3.8.0 and above. .. _`static code analyser`: https://en.wikipedia.org/wiki/Static_code_analysis diff --git a/doc/exts/pylint_extensions.py b/doc/exts/pylint_extensions.py index 936bdbb6b..cadcbdcba 100755 --- a/doc/exts/pylint_extensions.py +++ b/doc/exts/pylint_extensions.py @@ -11,7 +11,7 @@ from __future__ import annotations import os import re import sys -from typing import Any +from typing import Any, TypedDict import sphinx from sphinx.application import Sphinx @@ -22,11 +22,6 @@ from pylint.lint import PyLinter from pylint.typing import MessageDefinitionTuple, OptionDict, ReportsCallable from pylint.utils import get_rst_title -if sys.version_info >= (3, 8): - from typing import TypedDict -else: - from typing_extensions import TypedDict - class _CheckerInfo(TypedDict): """Represents data about a checker.""" diff --git a/doc/whatsnew/fragments/6306.breaking b/doc/whatsnew/fragments/6306.breaking new file mode 100644 index 000000000..8338251b6 --- /dev/null +++ b/doc/whatsnew/fragments/6306.breaking @@ -0,0 +1,3 @@ +Remove support for Python 3.7. + +Refs #6306 diff --git a/pylint/checkers/__init__.py b/pylint/checkers/__init__.py index 8af4bae67..0f9985918 100644 --- a/pylint/checkers/__init__.py +++ b/pylint/checkers/__init__.py @@ -42,8 +42,7 @@ messages nor reports. XXX not true, emit a 07 report ! from __future__ import annotations -import sys -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Literal from pylint.checkers.base_checker import ( BaseChecker, @@ -53,11 +52,6 @@ from pylint.checkers.base_checker import ( from pylint.checkers.deprecated import DeprecatedMixin from pylint.utils import LinterStats, diff_string, register_plugins -if sys.version_info >= (3, 8): - from typing import Literal -else: - from typing_extensions import Literal - if TYPE_CHECKING: from pylint.lint import PyLinter diff --git a/pylint/checkers/base/basic_checker.py b/pylint/checkers/base/basic_checker.py index dd46d8553..627f3c603 100644 --- a/pylint/checkers/base/basic_checker.py +++ b/pylint/checkers/base/basic_checker.py @@ -8,9 +8,8 @@ from __future__ import annotations import collections import itertools -import sys from collections.abc import Iterator -from typing import TYPE_CHECKING, cast +from typing import TYPE_CHECKING, Literal, cast import astroid from astroid import nodes, objects, util @@ -24,11 +23,6 @@ from pylint.utils import LinterStats if TYPE_CHECKING: from pylint.lint.pylinter import PyLinter -if sys.version_info >= (3, 8): - from typing import Literal -else: - from typing_extensions import Literal - class _BasicChecker(BaseChecker): """Permits separating multiple checks with the same checker name into diff --git a/pylint/checkers/base/docstring_checker.py b/pylint/checkers/base/docstring_checker.py index 5a681eeb3..91b3e7d4a 100644 --- a/pylint/checkers/base/docstring_checker.py +++ b/pylint/checkers/base/docstring_checker.py @@ -7,7 +7,7 @@ from __future__ import annotations import re -import sys +from typing import Literal import astroid from astroid import nodes @@ -21,11 +21,6 @@ from pylint.checkers.utils import ( is_property_setter, ) -if sys.version_info >= (3, 8): - from typing import Literal -else: - from typing_extensions import Literal - # do not require a doc string on private/system methods NO_REQUIRED_DOC_RGX = re.compile("^_") diff --git a/pylint/checkers/classes/class_checker.py b/pylint/checkers/classes/class_checker.py index 9b0bd50b1..77a795bcb 100644 --- a/pylint/checkers/classes/class_checker.py +++ b/pylint/checkers/classes/class_checker.py @@ -7,9 +7,9 @@ from __future__ import annotations import collections -import sys from collections import defaultdict from collections.abc import Callable, Sequence +from functools import cached_property from itertools import chain, zip_longest from re import Pattern from typing import TYPE_CHECKING, Any, Union @@ -47,11 +47,6 @@ if TYPE_CHECKING: from pylint.lint.pylinter import PyLinter -if sys.version_info >= (3, 8): - from functools import cached_property -else: - from astroid.decorators import cachedproperty as cached_property - _AccessNodes = Union[nodes.Attribute, nodes.AssignAttr] INVALID_BASE_CLASSES = {"bool", "range", "slice", "memoryview"} diff --git a/pylint/checkers/format.py b/pylint/checkers/format.py index 62466a4fd..3e3cd3227 100644 --- a/pylint/checkers/format.py +++ b/pylint/checkers/format.py @@ -13,11 +13,10 @@ Some parts of the process_token method is based from The Tab Nanny std module. from __future__ import annotations -import sys import tokenize from functools import reduce from re import Match -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Literal from astroid import nodes @@ -31,10 +30,6 @@ from pylint.utils.pragma_parser import OPTION_PO, PragmaParserError, parse_pragm if TYPE_CHECKING: from pylint.lint import PyLinter -if sys.version_info >= (3, 8): - from typing import Literal -else: - from typing_extensions import Literal _KEYWORD_TOKENS = { "assert", diff --git a/pylint/checkers/imports.py b/pylint/checkers/imports.py index 6cc5d2164..42649f3d9 100644 --- a/pylint/checkers/imports.py +++ b/pylint/checkers/imports.py @@ -12,6 +12,7 @@ import os import sys from collections import defaultdict from collections.abc import ItemsView, Sequence +from functools import cached_property from typing import TYPE_CHECKING, Any, Dict, List, Union import astroid @@ -38,11 +39,6 @@ from pylint.utils.linterstats import LinterStats if TYPE_CHECKING: from pylint.lint import PyLinter -if sys.version_info >= (3, 8): - from functools import cached_property -else: - from astroid.decorators import cachedproperty as cached_property - # The dictionary with Any should actually be a _ImportTree again # but mypy doesn't support recursive types yet diff --git a/pylint/checkers/logging.py b/pylint/checkers/logging.py index e5fb1ae09..461047bdf 100644 --- a/pylint/checkers/logging.py +++ b/pylint/checkers/logging.py @@ -7,8 +7,7 @@ from __future__ import annotations import string -import sys -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Literal import astroid from astroid import bases, nodes @@ -19,11 +18,6 @@ from pylint.checkers import utils from pylint.checkers.utils import infer_all from pylint.typing import MessageDefinitionTuple -if sys.version_info >= (3, 8): - from typing import Literal -else: - from typing_extensions import Literal - if TYPE_CHECKING: from pylint.lint import PyLinter diff --git a/pylint/checkers/raw_metrics.py b/pylint/checkers/raw_metrics.py index 301e9d2e2..ef4535345 100644 --- a/pylint/checkers/raw_metrics.py +++ b/pylint/checkers/raw_metrics.py @@ -4,19 +4,13 @@ from __future__ import annotations -import sys import tokenize -from typing import TYPE_CHECKING, Any, cast +from typing import TYPE_CHECKING, Any, Literal, cast from pylint.checkers import BaseTokenChecker from pylint.reporters.ureports.nodes import Paragraph, Section, Table, Text from pylint.utils import LinterStats, diff_string -if sys.version_info >= (3, 8): - from typing import Literal -else: - from typing_extensions import Literal - if TYPE_CHECKING: from pylint.lint import PyLinter diff --git a/pylint/checkers/refactoring/refactoring_checker.py b/pylint/checkers/refactoring/refactoring_checker.py index 890b0e64d..5d0a2dd7a 100644 --- a/pylint/checkers/refactoring/refactoring_checker.py +++ b/pylint/checkers/refactoring/refactoring_checker.py @@ -7,10 +7,9 @@ from __future__ import annotations import collections import copy import itertools -import sys import tokenize from collections.abc import Iterator -from functools import reduce +from functools import cached_property, reduce from re import Pattern from typing import TYPE_CHECKING, Any, NamedTuple, Union, cast @@ -27,10 +26,6 @@ from pylint.interfaces import HIGH, INFERENCE, Confidence if TYPE_CHECKING: from pylint.lint import PyLinter -if sys.version_info >= (3, 8): - from functools import cached_property -else: - from astroid.decorators import cachedproperty as cached_property NodesWithNestedBlocks = Union[ nodes.TryExcept, nodes.TryFinally, nodes.While, nodes.For, nodes.If diff --git a/pylint/checkers/spelling.py b/pylint/checkers/spelling.py index 8ba4df4d5..91161c60d 100644 --- a/pylint/checkers/spelling.py +++ b/pylint/checkers/spelling.py @@ -7,21 +7,15 @@ from __future__ import annotations import re -import sys import tokenize from re import Pattern -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Any, Literal from astroid import nodes from pylint.checkers import BaseTokenChecker from pylint.checkers.utils import only_required_for_messages -if sys.version_info >= (3, 8): - from typing import Literal -else: - from typing_extensions import Literal - if TYPE_CHECKING: from pylint.lint import PyLinter diff --git a/pylint/checkers/strings.py b/pylint/checkers/strings.py index ce122e754..2cc780da5 100644 --- a/pylint/checkers/strings.py +++ b/pylint/checkers/strings.py @@ -8,11 +8,10 @@ from __future__ import annotations import collections import re -import sys import tokenize from collections import Counter from collections.abc import Iterable, Sequence -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Literal import astroid from astroid import bases, nodes, util @@ -26,11 +25,6 @@ from pylint.typing import MessageDefinitionTuple if TYPE_CHECKING: from pylint.lint import PyLinter -if sys.version_info >= (3, 8): - from typing import Literal -else: - from typing_extensions import Literal - _AST_NODE_STR_TYPES = ("__builtin__.unicode", "__builtin__.str", "builtins.str") # Prefixes for both strings and bytes literals per diff --git a/pylint/checkers/typecheck.py b/pylint/checkers/typecheck.py index 0298c81dc..fe29879c5 100644 --- a/pylint/checkers/typecheck.py +++ b/pylint/checkers/typecheck.py @@ -14,9 +14,9 @@ import shlex import sys import types from collections.abc import Callable, Iterable, Iterator, Sequence -from functools import singledispatch +from functools import cached_property, singledispatch from re import Pattern -from typing import TYPE_CHECKING, Any, TypeVar, Union +from typing import TYPE_CHECKING, Any, Literal, TypeVar, Union import astroid import astroid.exceptions @@ -53,13 +53,6 @@ from pylint.constants import PY310_PLUS from pylint.interfaces import HIGH, INFERENCE from pylint.typing import MessageDefinitionTuple -if sys.version_info >= (3, 8): - from functools import cached_property - from typing import Literal -else: - from astroid.decorators import cachedproperty as cached_property - from typing_extensions import Literal - if TYPE_CHECKING: from pylint.lint import PyLinter diff --git a/pylint/checkers/utils.py b/pylint/checkers/utils.py index 95a0e7b7b..6b66ad620 100644 --- a/pylint/checkers/utils.py +++ b/pylint/checkers/utils.py @@ -1942,7 +1942,7 @@ def is_typing_member(node: nodes.NodeNG, names_to_check: tuple[str, ...]) -> boo return False -@lru_cache() +@lru_cache def in_for_else_branch(parent: nodes.NodeNG, stmt: nodes.Statement) -> bool: """Returns True if stmt is inside the else branch for a parent For stmt.""" return isinstance(parent, nodes.For) and any( diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py index e1b82bb41..08797c93c 100644 --- a/pylint/checkers/variables.py +++ b/pylint/checkers/variables.py @@ -11,10 +11,10 @@ import copy import itertools import os import re -import sys from collections import defaultdict from collections.abc import Generator, Iterable, Iterator from enum import Enum +from functools import cached_property from typing import TYPE_CHECKING, Any, NamedTuple import astroid @@ -34,11 +34,6 @@ from pylint.constants import PY39_PLUS, TYPING_NEVER, TYPING_NORETURN from pylint.interfaces import CONTROL_FLOW, HIGH, INFERENCE, INFERENCE_FAILURE from pylint.typing import MessageDefinitionTuple -if sys.version_info >= (3, 8): - from functools import cached_property -else: - from astroid.decorators import cachedproperty as cached_property - if TYPE_CHECKING: from pylint.lint import PyLinter diff --git a/pylint/config/_pylint_config/utils.py b/pylint/config/_pylint_config/utils.py index 70b2a8092..f9185e8b1 100644 --- a/pylint/config/_pylint_config/utils.py +++ b/pylint/config/_pylint_config/utils.py @@ -9,12 +9,7 @@ from __future__ import annotations import sys from collections.abc import Callable from pathlib import Path -from typing import TypeVar - -if sys.version_info >= (3, 8): - from typing import Literal -else: - from typing_extensions import Literal +from typing import Literal, TypeVar if sys.version_info >= (3, 10): from typing import ParamSpec diff --git a/pylint/config/argument.py b/pylint/config/argument.py index 697629c13..d826cbd3e 100644 --- a/pylint/config/argument.py +++ b/pylint/config/argument.py @@ -13,10 +13,9 @@ import argparse import os import pathlib import re -import sys from collections.abc import Callable from glob import glob -from typing import Any, Pattern, Sequence, Tuple, Union +from typing import Any, Literal, Pattern, Sequence, Tuple, Union from pylint import interfaces from pylint import utils as pylint_utils @@ -24,12 +23,6 @@ from pylint.config.callback_actions import _CallbackAction, _ExtendAction from pylint.config.deprecation_actions import _NewNamesAction, _OldNamesAction from pylint.constants import PY38_PLUS -if sys.version_info >= (3, 8): - from typing import Literal -else: - from typing_extensions import Literal - - _ArgumentTypes = Union[ str, int, diff --git a/pylint/lint/message_state_handler.py b/pylint/lint/message_state_handler.py index 96d2412c5..26028f0fa 100644 --- a/pylint/lint/message_state_handler.py +++ b/pylint/lint/message_state_handler.py @@ -4,10 +4,9 @@ from __future__ import annotations -import sys import tokenize from collections import defaultdict -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Literal from pylint import exceptions, interfaces from pylint.constants import ( @@ -27,12 +26,6 @@ from pylint.utils.pragma_parser import ( parse_pragma, ) -if sys.version_info >= (3, 8): - from typing import Literal -else: - from typing_extensions import Literal - - if TYPE_CHECKING: from pylint.lint.pylinter import PyLinter diff --git a/pylint/lint/pylinter.py b/pylint/lint/pylinter.py index a0441e300..ed607aca5 100644 --- a/pylint/lint/pylinter.py +++ b/pylint/lint/pylinter.py @@ -18,7 +18,7 @@ from io import TextIOWrapper from pathlib import Path from re import Pattern from types import ModuleType -from typing import Any +from typing import Any, Protocol import astroid from astroid import nodes @@ -68,12 +68,6 @@ from pylint.typing import ( ) from pylint.utils import ASTWalker, FileState, LinterStats, utils -if sys.version_info >= (3, 8): - from typing import Protocol -else: - from typing_extensions import Protocol - - MANAGER = astroid.MANAGER diff --git a/pylint/reporters/json_reporter.py b/pylint/reporters/json_reporter.py index 74fa6672b..176946e72 100644 --- a/pylint/reporters/json_reporter.py +++ b/pylint/reporters/json_reporter.py @@ -7,19 +7,13 @@ from __future__ import annotations import json -import sys -from typing import TYPE_CHECKING, Optional +from typing import TYPE_CHECKING, Optional, TypedDict from pylint.interfaces import UNDEFINED from pylint.message import Message from pylint.reporters.base_reporter import BaseReporter from pylint.typing import MessageLocationTuple -if sys.version_info >= (3, 8): - from typing import TypedDict -else: - from typing_extensions import TypedDict - if TYPE_CHECKING: from pylint.lint.pylinter import PyLinter from pylint.reporters.ureports.nodes import Section diff --git a/pylint/testutils/_primer/package_to_lint.py b/pylint/testutils/_primer/package_to_lint.py index 11df63bd2..1f596f02b 100644 --- a/pylint/testutils/_primer/package_to_lint.py +++ b/pylint/testutils/_primer/package_to_lint.py @@ -5,18 +5,13 @@ from __future__ import annotations import logging -import sys from pathlib import Path +from typing import Literal from git import GitCommandError from git.cmd import Git from git.repo import Repo -if sys.version_info >= (3, 8): - from typing import Literal -else: - from typing_extensions import Literal - PRIMER_DIRECTORY_PATH = Path("tests") / ".pylint_primer_tests" diff --git a/pylint/testutils/_primer/primer_command.py b/pylint/testutils/_primer/primer_command.py index 08adedd4c..817c1a0d3 100644 --- a/pylint/testutils/_primer/primer_command.py +++ b/pylint/testutils/_primer/primer_command.py @@ -6,18 +6,12 @@ from __future__ import annotations import abc import argparse -import sys from pathlib import Path -from typing import Dict +from typing import Dict, TypedDict from pylint.reporters.json_reporter import OldJsonExport from pylint.testutils._primer import PackageToLint -if sys.version_info >= (3, 8): - from typing import TypedDict -else: - from typing_extensions import TypedDict - class PackageData(TypedDict): commit: str diff --git a/pylint/testutils/functional/test_file.py b/pylint/testutils/functional/test_file.py index 5b2e4efb6..16593b5c4 100644 --- a/pylint/testutils/functional/test_file.py +++ b/pylint/testutils/functional/test_file.py @@ -5,9 +5,9 @@ from __future__ import annotations import configparser -import sys from collections.abc import Callable from os.path import basename, exists, join +from typing import TypedDict def parse_python_version(ver_str: str) -> tuple[int, ...]: @@ -19,12 +19,6 @@ class NoFileError(Exception): pass -if sys.version_info >= (3, 8): - from typing import TypedDict -else: - from typing_extensions import TypedDict - - class TestFileOptions(TypedDict): min_pyver: tuple[int, ...] max_pyver: tuple[int, ...] diff --git a/pylint/testutils/pyreverse.py b/pylint/testutils/pyreverse.py index 24fddad77..c621f9e7a 100644 --- a/pylint/testutils/pyreverse.py +++ b/pylint/testutils/pyreverse.py @@ -7,17 +7,11 @@ from __future__ import annotations import argparse import configparser import shlex -import sys from pathlib import Path -from typing import NamedTuple +from typing import NamedTuple, TypedDict from pylint.pyreverse.main import DEFAULT_COLOR_PALETTE -if sys.version_info >= (3, 8): - from typing import TypedDict -else: - from typing_extensions import TypedDict - # This class could and should be replaced with a simple dataclass when support for Python < 3.7 is dropped. # A NamedTuple is not possible as some tests need to modify attributes during the test. diff --git a/pylint/testutils/unittest_linter.py b/pylint/testutils/unittest_linter.py index 84fc53bc8..a19afec56 100644 --- a/pylint/testutils/unittest_linter.py +++ b/pylint/testutils/unittest_linter.py @@ -6,8 +6,7 @@ from __future__ import annotations -import sys -from typing import Any +from typing import Any, Literal from astroid import nodes @@ -15,11 +14,6 @@ from pylint.interfaces import UNDEFINED, Confidence from pylint.lint import PyLinter from pylint.testutils.output_line import MessageTest -if sys.version_info >= (3, 8): - from typing import Literal -else: - from typing_extensions import Literal - class UnittestLinter(PyLinter): """A fake linter class to capture checker messages.""" diff --git a/pylint/typing.py b/pylint/typing.py index ac0beaaec..da11112b4 100644 --- a/pylint/typing.py +++ b/pylint/typing.py @@ -7,7 +7,6 @@ from __future__ import annotations import argparse -import sys from pathlib import Path from typing import ( TYPE_CHECKING, @@ -15,19 +14,17 @@ from typing import ( Callable, Dict, Iterable, + Literal, NamedTuple, Optional, Pattern, + Protocol, Tuple, Type, + TypedDict, Union, ) -if sys.version_info >= (3, 8): - from typing import Literal, Protocol, TypedDict -else: - from typing_extensions import Literal, Protocol, TypedDict - if TYPE_CHECKING: from pylint.config.callback_actions import _CallbackAction from pylint.pyreverse.inspector import Project diff --git a/pylint/utils/file_state.py b/pylint/utils/file_state.py index 54b98e4be..9ae5fb077 100644 --- a/pylint/utils/file_state.py +++ b/pylint/utils/file_state.py @@ -5,10 +5,9 @@ from __future__ import annotations import collections -import sys from collections import defaultdict from collections.abc import Iterator -from typing import TYPE_CHECKING, Dict +from typing import TYPE_CHECKING, Dict, Literal from astroid import nodes @@ -18,11 +17,6 @@ from pylint.constants import ( WarningScope, ) -if sys.version_info >= (3, 8): - from typing import Literal -else: - from typing_extensions import Literal - if TYPE_CHECKING: from pylint.message import MessageDefinition, MessageDefinitionStore diff --git a/pylint/utils/linterstats.py b/pylint/utils/linterstats.py index 01120115f..e7a088b7b 100644 --- a/pylint/utils/linterstats.py +++ b/pylint/utils/linterstats.py @@ -4,16 +4,10 @@ from __future__ import annotations -import sys -from typing import cast +from typing import Literal, TypedDict, cast from pylint.typing import MessageTypesFullName -if sys.version_info >= (3, 8): - from typing import Literal, TypedDict -else: - from typing_extensions import Literal, TypedDict - class BadNames(TypedDict): """TypedDict to store counts of node types with bad names.""" diff --git a/pylint/utils/utils.py b/pylint/utils/utils.py index 315811ebf..543d7cbb3 100644 --- a/pylint/utils/utils.py +++ b/pylint/utils/utils.py @@ -24,18 +24,23 @@ import tokenize import warnings from collections.abc import Sequence from io import BufferedReader, BytesIO -from typing import TYPE_CHECKING, Any, List, Pattern, TextIO, Tuple, TypeVar, Union +from typing import ( + TYPE_CHECKING, + Any, + List, + Literal, + Pattern, + TextIO, + Tuple, + TypeVar, + Union, +) from astroid import Module, modutils, nodes from pylint.constants import PY_EXTS from pylint.typing import OptionDict -if sys.version_info >= (3, 8): - from typing import Literal -else: - from typing_extensions import Literal - if TYPE_CHECKING: from pylint.lint import PyLinter diff --git a/pylintrc b/pylintrc index 791b16447..3896d4e35 100644 --- a/pylintrc +++ b/pylintrc @@ -54,7 +54,7 @@ unsafe-load-any-extension=no extension-pkg-allow-list= # Minimum supported python version -py-version = 3.7.2 +py-version = 3.8.0 # Control the amount of potential inferred values when inferring a single # object. This can help the performance when dealing with large functions or @@ -108,6 +108,7 @@ disable= format, # We anticipate #3512 where it will become optional fixme, + consider-using-assignment-expr, [REPORTS] diff --git a/pyproject.toml b/pyproject.toml index 940af4864..23da88675 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,7 +20,6 @@ classifiers = [ "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", @@ -32,7 +31,7 @@ classifiers = [ "Topic :: Software Development :: Testing", "Typing :: Typed" ] -requires-python = ">=3.7.2" +requires-python = ">=3.8.0" dependencies = [ "dill>=0.2;python_version<'3.11'", "dill>=0.3.6;python_version>='3.11'", diff --git a/tests/functional/b/bad_reversed_sequence_py37.py b/tests/functional/b/bad_reversed_sequence_py37.py index 5a0b2124c..4f132d945 100644 --- a/tests/functional/b/bad_reversed_sequence_py37.py +++ b/tests/functional/b/bad_reversed_sequence_py37.py @@ -1,8 +1,8 @@ """ Dictionaries are reversible starting on python 3.8""" - # pylint: disable=missing-docstring -reversed({'a': 1, 'b': 2}) # [bad-reversed-sequence] +# This can't be detected since changes to locals aren't backported +reversed({'a': 1, 'b': 2}) class InheritDict(dict): diff --git a/tests/functional/b/bad_reversed_sequence_py37.rc b/tests/functional/b/bad_reversed_sequence_py37.rc index 67a28a36a..77eb3be64 100644 --- a/tests/functional/b/bad_reversed_sequence_py37.rc +++ b/tests/functional/b/bad_reversed_sequence_py37.rc @@ -1,2 +1,2 @@ -[testoptions] -max_pyver=3.8 +[main] +py-version=3.7 diff --git a/tests/functional/b/bad_reversed_sequence_py37.txt b/tests/functional/b/bad_reversed_sequence_py37.txt index 6fbbd2c59..da511347b 100644 --- a/tests/functional/b/bad_reversed_sequence_py37.txt +++ b/tests/functional/b/bad_reversed_sequence_py37.txt @@ -1,2 +1 @@ -bad-reversed-sequence:5:0:5:26::The first reversed() argument is not a sequence:UNDEFINED bad-reversed-sequence:12:0:12:39::The first reversed() argument is not a sequence:UNDEFINED diff --git a/tests/functional/s/singledispatch/singledispatch_method_py37.rc b/tests/functional/s/singledispatch/singledispatch_method_py37.rc index 67a28a36a..77eb3be64 100644 --- a/tests/functional/s/singledispatch/singledispatch_method_py37.rc +++ b/tests/functional/s/singledispatch/singledispatch_method_py37.rc @@ -1,2 +1,2 @@ -[testoptions] -max_pyver=3.8 +[main] +py-version=3.7 diff --git a/tests/functional/s/star/star_needs_assignment_target_py37.py b/tests/functional/s/star/star_needs_assignment_target_py37.py deleted file mode 100644 index fb5eea86a..000000000 --- a/tests/functional/s/star/star_needs_assignment_target_py37.py +++ /dev/null @@ -1,15 +0,0 @@ -""" -Test PEP 0448 -- Additional Unpacking Generalizations -https://www.python.org/dev/peps/pep-0448/ -""" - -# pylint: disable=superfluous-parens, unnecessary-comprehension - -UNPACK_TUPLE = (*range(4), 4) -UNPACK_LIST = [*range(4), 4] -UNPACK_SET = {*range(4), 4} -UNPACK_DICT = {'a': 1, **{'b': '2'}} -UNPACK_DICT2 = {**UNPACK_DICT, "x": 1, "y": 2} -UNPACK_DICT3 = {**{'a': 1}, 'a': 2, **{'a': 3}} - -UNPACK_IN_COMP = {elem for elem in (*range(10))} # [star-needs-assignment-target] diff --git a/tests/functional/s/star/star_needs_assignment_target_py37.rc b/tests/functional/s/star/star_needs_assignment_target_py37.rc deleted file mode 100644 index 67a28a36a..000000000 --- a/tests/functional/s/star/star_needs_assignment_target_py37.rc +++ /dev/null @@ -1,2 +0,0 @@ -[testoptions] -max_pyver=3.8 diff --git a/tests/functional/s/star/star_needs_assignment_target_py37.txt b/tests/functional/s/star/star_needs_assignment_target_py37.txt deleted file mode 100644 index fb5a5faa6..000000000 --- a/tests/functional/s/star/star_needs_assignment_target_py37.txt +++ /dev/null @@ -1 +0,0 @@ -star-needs-assignment-target:15:36:15:46::Can use starred expression only in assignment target:UNDEFINED diff --git a/tests/functional/s/star/star_needs_assignment_target_py38.py b/tests/functional/s/star/star_needs_assignment_target_py38.py new file mode 100644 index 000000000..fb5eea86a --- /dev/null +++ b/tests/functional/s/star/star_needs_assignment_target_py38.py @@ -0,0 +1,15 @@ +""" +Test PEP 0448 -- Additional Unpacking Generalizations +https://www.python.org/dev/peps/pep-0448/ +""" + +# pylint: disable=superfluous-parens, unnecessary-comprehension + +UNPACK_TUPLE = (*range(4), 4) +UNPACK_LIST = [*range(4), 4] +UNPACK_SET = {*range(4), 4} +UNPACK_DICT = {'a': 1, **{'b': '2'}} +UNPACK_DICT2 = {**UNPACK_DICT, "x": 1, "y": 2} +UNPACK_DICT3 = {**{'a': 1}, 'a': 2, **{'a': 3}} + +UNPACK_IN_COMP = {elem for elem in (*range(10))} # [star-needs-assignment-target] diff --git a/tests/functional/s/star/star_needs_assignment_target_py38.rc b/tests/functional/s/star/star_needs_assignment_target_py38.rc new file mode 100644 index 000000000..d584aa959 --- /dev/null +++ b/tests/functional/s/star/star_needs_assignment_target_py38.rc @@ -0,0 +1,2 @@ +[testoptions] +max_pyver=3.9 diff --git a/tests/functional/s/star/star_needs_assignment_target_py38.txt b/tests/functional/s/star/star_needs_assignment_target_py38.txt new file mode 100644 index 000000000..fb5a5faa6 --- /dev/null +++ b/tests/functional/s/star/star_needs_assignment_target_py38.txt @@ -0,0 +1 @@ +star-needs-assignment-target:15:36:15:46::Can use starred expression only in assignment target:UNDEFINED diff --git a/tests/functional/u/undefined/undefined_loop_variable.py b/tests/functional/u/undefined/undefined_loop_variable.py index a00af5d79..10d6dc60b 100644 --- a/tests/functional/u/undefined/undefined_loop_variable.py +++ b/tests/functional/u/undefined/undefined_loop_variable.py @@ -1,11 +1,6 @@ # pylint: disable=missing-docstring,redefined-builtin, consider-using-f-string, unnecessary-direct-lambda-call, broad-exception-raised -import sys - -if sys.version_info >= (3, 8): - from typing import NoReturn -else: - from typing_extensions import NoReturn +from typing import NoReturn def do_stuff(some_random_list): diff --git a/tests/functional/u/undefined/undefined_loop_variable.txt b/tests/functional/u/undefined/undefined_loop_variable.txt index e10c9e002..78dc602ed 100644 --- a/tests/functional/u/undefined/undefined_loop_variable.txt +++ b/tests/functional/u/undefined/undefined_loop_variable.txt @@ -1,4 +1,4 @@ -undefined-loop-variable:14:11:14:14:do_stuff:Using possibly undefined loop variable 'var':UNDEFINED -undefined-loop-variable:33:7:33:11::Using possibly undefined loop variable 'var1':UNDEFINED -undefined-loop-variable:83:11:83:14:do_stuff_with_redefined_range:Using possibly undefined loop variable 'var':UNDEFINED -undefined-loop-variable:201:11:201:20:find_even_number:Using possibly undefined loop variable 'something':UNDEFINED +undefined-loop-variable:9:11:9:14:do_stuff:Using possibly undefined loop variable 'var':UNDEFINED +undefined-loop-variable:28:7:28:11::Using possibly undefined loop variable 'var1':UNDEFINED +undefined-loop-variable:78:11:78:14:do_stuff_with_redefined_range:Using possibly undefined loop variable 'var':UNDEFINED +undefined-loop-variable:196:11:196:20:find_even_number:Using possibly undefined loop variable 'something':UNDEFINED diff --git a/tests/test_pylint_runners.py b/tests/test_pylint_runners.py index 29c4f90e8..f3baee24b 100644 --- a/tests/test_pylint_runners.py +++ b/tests/test_pylint_runners.py @@ -12,7 +12,7 @@ import shlex import sys from collections.abc import Sequence from io import BufferedReader -from typing import Any, NoReturn +from typing import Any, NoReturn, Protocol from unittest.mock import MagicMock, mock_open, patch import pytest @@ -22,11 +22,6 @@ from pylint.testutils import GenericTestReporter as Reporter from pylint.testutils._run import _Run as Run from pylint.testutils.utils import _test_cwd -if sys.version_info >= (3, 8): - from typing import Protocol -else: - from typing_extensions import Protocol - class _RunCallable(Protocol): # pylint: disable=too-few-public-methods def __call__(self, argv: Sequence[str] | None = None) -> NoReturn | None: diff --git a/tests/test_self.py b/tests/test_self.py index 51a077665..48f914e35 100644 --- a/tests/test_self.py +++ b/tests/test_self.py @@ -10,7 +10,6 @@ import configparser import contextlib import json import os -import platform import re import subprocess import sys @@ -349,16 +348,9 @@ class TestRunTC: assert isinstance(output, list) assert len(output) == 1 assert isinstance(output[0], dict) - # So each version wants a different column number... - if platform.python_implementation() == "PyPy": - column = 9 - elif sys.version_info >= (3, 8): - column = 9 - else: - column = 15 expected = { "obj": "", - "column": column, + "column": 9, "line": 1, "type": "error", "symbol": "syntax-error", diff --git a/tests/testutils/test_output_line.py b/tests/testutils/test_output_line.py index c28c851ac..8e9cf2800 100644 --- a/tests/testutils/test_output_line.py +++ b/tests/testutils/test_output_line.py @@ -6,7 +6,7 @@ from __future__ import annotations -import sys +from typing import Protocol import pytest @@ -16,11 +16,6 @@ from pylint.message import Message from pylint.testutils.output_line import OutputLine from pylint.typing import MessageLocationTuple -if sys.version_info >= (3, 8): - from typing import Protocol -else: - from typing_extensions import Protocol - class _MessageCallable(Protocol): def __call__(self, confidence: Confidence = HIGH) -> Message: diff --git a/tox.ini b/tox.ini index 0c78b8798..924a72f0e 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] minversion = 3.0 -envlist = formatting, py37, py38, py39, py310, py311, pypy, benchmark +envlist = formatting, py38, py39, py310, py311, pypy, benchmark skip_missing_interpreters = true requires = pip >=21.3.1 isolated_build = true -- cgit v1.2.1