From 84f92510ab0900b656bc0e79d012000aa3c206b6 Mon Sep 17 00:00:00 2001 From: Jirka Borovec <6035284+Borda@users.noreply.github.com> Date: Mon, 16 Dec 2024 14:58:08 +0900 Subject: [PATCH] bump: min Python 3.9 (#331) * bump min Python 3.9 * --unsafe-fixes * move fire * Fire # type: ignore[import-untyped] * 0.12.0dev --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .github/scripts/find-unused-caches.py | 3 +-- .github/workflows/check-package.yml | 2 +- .github/workflows/ci-testing.yml | 2 +- .github/workflows/ci-use-checks.yaml | 2 +- docs/source/conf.py | 3 +-- pyproject.toml | 3 +-- requirements/typing.txt | 2 ++ scripts/adjust-torch-versions.py | 8 ++++---- setup.py | 2 +- src/lightning_utilities/__about__.py | 2 +- src/lightning_utilities/cli/__main__.py | 2 +- src/lightning_utilities/cli/dependencies.py | 3 ++- src/lightning_utilities/core/apply_func.py | 17 +++++++++-------- src/lightning_utilities/core/enums.py | 4 ++-- src/lightning_utilities/core/imports.py | 6 +++--- src/lightning_utilities/core/inheritance.py | 8 ++++---- src/lightning_utilities/core/overrides.py | 3 +-- src/lightning_utilities/docs/formatting.py | 7 ++++--- src/lightning_utilities/docs/retriever.py | 5 ++--- src/lightning_utilities/install/requirements.py | 5 +++-- src/lightning_utilities/test/warning.py | 5 +++-- tests/unittests/core/test_apply_func.py | 4 ++-- tests/unittests/mocks.py | 3 ++- tests/unittests/test/test_warnings.py | 7 ++++--- 24 files changed, 56 insertions(+), 52 deletions(-) diff --git a/.github/scripts/find-unused-caches.py b/.github/scripts/find-unused-caches.py index 02b653a3..e539a1a8 100644 --- a/.github/scripts/find-unused-caches.py +++ b/.github/scripts/find-unused-caches.py @@ -2,10 +2,9 @@ import os from datetime import timedelta -from typing import List -def fetch_all_caches(repository: str, token: str, per_page: int = 100, max_pages: int = 100) -> List[dict]: +def fetch_all_caches(repository: str, token: str, per_page: int = 100, max_pages: int = 100) -> list[dict]: """Fetch list of al caches from a given repository. Args: diff --git a/.github/workflows/check-package.yml b/.github/workflows/check-package.yml index 64361321..517ccebb 100644 --- a/.github/workflows/check-package.yml +++ b/.github/workflows/check-package.yml @@ -47,7 +47,7 @@ on: default: | { "os": ["ubuntu-20.04", "macos-11", "windows-2022"], - "python-version": ["3.8", "3.9"] + "python-version": ["3.9", "3.12"] } env-vars: description: "custom environment variables in json format" diff --git a/.github/workflows/ci-testing.yml b/.github/workflows/ci-testing.yml index 61c86dbe..174204de 100644 --- a/.github/workflows/ci-testing.yml +++ b/.github/workflows/ci-testing.yml @@ -17,7 +17,7 @@ jobs: fail-fast: false matrix: os: ["ubuntu-22.04", "macos-13", "windows-2022"] - python-version: ["3.8", "3.10", "3.12"] + python-version: ["3.9", "3.10", "3.12"] requires: ["oldest", "latest"] exclude: - { requires: "oldest", python-version: "3.12" } diff --git a/.github/workflows/ci-use-checks.yaml b/.github/workflows/ci-use-checks.yaml index bfafc9c7..c6ce84c2 100644 --- a/.github/workflows/ci-use-checks.yaml +++ b/.github/workflows/ci-use-checks.yaml @@ -52,7 +52,7 @@ jobs: testing-matrix: | { "os": ["ubuntu-22.04", "macos-13", "windows-2022"], - "python-version": ["3.8", "3.12"] + "python-version": ["3.9", "3.12"] } check-package-extras: diff --git a/docs/source/conf.py b/docs/source/conf.py index fd67f5ce..a76b593c 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -7,7 +7,6 @@ import glob import os import re -from typing import List import pt_lightning_sphinx_theme @@ -272,7 +271,7 @@ def setup(app): # Ignoring Third-party packages # https://stackoverflow.com/questions/15889621/sphinx-how-to-exclude-imports-in-automodule -def _package_list_from_file(file: str) -> List[str]: +def _package_list_from_file(file: str) -> list[str]: list_pkgs = [] with open(file) as fp: lines = fp.readlines() diff --git a/pyproject.toml b/pyproject.toml index 0abe1f60..2d0f8afa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ requires = [ ] [tool.ruff] -target-version = "py38" +target-version = "py39" line-length = 120 format.preview = true @@ -152,4 +152,3 @@ files = [ "src/lightning_utilities", ] disallow_untyped_defs = true -ignore_missing_imports = true diff --git a/requirements/typing.txt b/requirements/typing.txt index 432605a4..30803664 100644 --- a/requirements/typing.txt +++ b/requirements/typing.txt @@ -1,3 +1,5 @@ mypy>=1.0.0 types-setuptools + +fire diff --git a/scripts/adjust-torch-versions.py b/scripts/adjust-torch-versions.py index 311e6530..227b461f 100644 --- a/scripts/adjust-torch-versions.py +++ b/scripts/adjust-torch-versions.py @@ -7,7 +7,7 @@ import os import re import sys -from typing import Dict, List, Optional +from typing import Optional def _determine_torchaudio(torch_version: str) -> str: @@ -103,7 +103,7 @@ def _determine_torchvision(torch_version: str) -> str: return ".".join(map(str, tv_ver_array)) -def find_latest(ver: str) -> Dict[str, str]: +def find_latest(ver: str) -> dict[str, str]: """Find the latest version. >>> from pprint import pprint @@ -136,7 +136,7 @@ def find_latest(ver: str) -> Dict[str, str]: } -def adjust(requires: List[str], pytorch_version: Optional[str] = None) -> List[str]: +def adjust(requires: list[str], pytorch_version: Optional[str] = None) -> list[str]: """Adjust the versions to be paired within pytorch ecosystem. >>> from pprint import pprint @@ -175,7 +175,7 @@ def adjust(requires: List[str], pytorch_version: Optional[str] = None) -> List[s return requires_ -def _offset_print(reqs: List[str], offset: str = "\t|\t") -> str: +def _offset_print(reqs: list[str], offset: str = "\t|\t") -> str: """Adding offset to each line for the printing requirements.""" reqs = [offset + r for r in reqs] return os.linesep.join(reqs) diff --git a/setup.py b/setup.py index 5aaefef1..27d36c93 100755 --- a/setup.py +++ b/setup.py @@ -62,7 +62,7 @@ def _requirement_extras(path_req: str = _PATH_REQUIRE) -> dict: include_package_data=True, zip_safe=False, keywords=["Utilities", "DevOps", "CI/CD"], - python_requires=">=3.8", + python_requires=">=3.9", setup_requires=[], install_requires=requirements, extras_require=_requirement_extras(), diff --git a/src/lightning_utilities/__about__.py b/src/lightning_utilities/__about__.py index 024e1ebc..06cb8f30 100644 --- a/src/lightning_utilities/__about__.py +++ b/src/lightning_utilities/__about__.py @@ -1,6 +1,6 @@ import time -__version__ = "0.11.9" +__version__ = "0.12.0dev" __author__ = "Lightning AI et al." __author_email__ = "pytorch@lightning.ai" __license__ = "Apache-2.0" diff --git a/src/lightning_utilities/cli/__main__.py b/src/lightning_utilities/cli/__main__.py index a0416b5f..9cdf708d 100644 --- a/src/lightning_utilities/cli/__main__.py +++ b/src/lightning_utilities/cli/__main__.py @@ -9,7 +9,7 @@ def main() -> None: """CLI entry point.""" - from fire import Fire + from fire import Fire # type: ignore[import-untyped] Fire({ "requirements": { diff --git a/src/lightning_utilities/cli/dependencies.py b/src/lightning_utilities/cli/dependencies.py index 6b891120..c7ff21ae 100644 --- a/src/lightning_utilities/cli/dependencies.py +++ b/src/lightning_utilities/cli/dependencies.py @@ -4,8 +4,9 @@ # import glob import os.path +from collections.abc import Sequence from pprint import pprint -from typing import Sequence, Union +from typing import Union REQUIREMENT_ROOT = "requirements.txt" REQUIREMENT_FILES_ALL: list = glob.glob(os.path.join("requirements", "*.txt")) diff --git a/src/lightning_utilities/core/apply_func.py b/src/lightning_utilities/core/apply_func.py index 213cce62..d51ec33b 100644 --- a/src/lightning_utilities/core/apply_func.py +++ b/src/lightning_utilities/core/apply_func.py @@ -4,8 +4,9 @@ # import dataclasses from collections import OrderedDict, defaultdict +from collections.abc import Mapping, Sequence from copy import deepcopy -from typing import Any, Callable, List, Mapping, Optional, Sequence, Tuple, Union +from typing import Any, Callable, Optional, Union def is_namedtuple(obj: object) -> bool: @@ -22,10 +23,10 @@ def is_dataclass_instance(obj: object) -> bool: def apply_to_collection( data: Any, - dtype: Union[type, Any, Tuple[Union[type, Any]]], + dtype: Union[type, Any, tuple[Union[type, Any]]], function: Callable, *args: Any, - wrong_dtype: Optional[Union[type, Tuple[type, ...]]] = None, + wrong_dtype: Optional[Union[type, tuple[type, ...]]] = None, include_none: bool = True, allow_frozen: bool = False, **kwargs: Any, @@ -83,10 +84,10 @@ def apply_to_collection( def _apply_to_collection_slow( data: Any, - dtype: Union[type, Any, Tuple[Union[type, Any]]], + dtype: Union[type, Any, tuple[Union[type, Any]]], function: Callable, *args: Any, - wrong_dtype: Optional[Union[type, Tuple[type, ...]]] = None, + wrong_dtype: Optional[Union[type, tuple[type, ...]]] = None, include_none: bool = True, allow_frozen: bool = False, **kwargs: Any, @@ -181,10 +182,10 @@ def _apply_to_collection_slow( def apply_to_collections( data1: Optional[Any], data2: Optional[Any], - dtype: Union[type, Any, Tuple[Union[type, Any]]], + dtype: Union[type, Any, tuple[Union[type, Any]]], function: Callable, *args: Any, - wrong_dtype: Optional[Union[type, Tuple[type]]] = None, + wrong_dtype: Optional[Union[type, tuple[type]]] = None, **kwargs: Any, ) -> Any: """Zips two collections and applies a function to their items of a certain dtype. @@ -252,7 +253,7 @@ def apply_to_collections( # but do not deepcopy mapped fields since the computation would # be wasted on values that likely get immediately overwritten data = [data1, data2] - fields: List[dict] = [{}, {}] + fields: list[dict] = [{}, {}] memo: dict = {} for i in range(len(data)): for field in dataclasses.fields(data[i]): diff --git a/src/lightning_utilities/core/enums.py b/src/lightning_utilities/core/enums.py index ff14f74d..945e0ef5 100644 --- a/src/lightning_utilities/core/enums.py +++ b/src/lightning_utilities/core/enums.py @@ -4,7 +4,7 @@ # import warnings from enum import Enum -from typing import List, Optional +from typing import Optional from typing_extensions import Literal @@ -67,7 +67,7 @@ def try_from_str(cls, value: str, source: Literal["key", "value", "any"] = "key" return None @classmethod - def _allowed_matches(cls, source: str) -> List[str]: + def _allowed_matches(cls, source: str) -> list[str]: keys, vals = [], [] for enum_key, enum_val in cls.__members__.items(): keys.append(enum_key) diff --git a/src/lightning_utilities/core/imports.py b/src/lightning_utilities/core/imports.py index 1b141c9a..51a8a2b8 100644 --- a/src/lightning_utilities/core/imports.py +++ b/src/lightning_utilities/core/imports.py @@ -11,7 +11,7 @@ from importlib.metadata import version as _version from importlib.util import find_spec from types import ModuleType -from typing import Any, Callable, List, Optional, TypeVar +from typing import Any, Callable, Optional, TypeVar from packaging.requirements import Requirement from packaging.version import InvalidVersion, Version @@ -187,7 +187,7 @@ def _check_extras_available(self, requirement: Requirement) -> bool: return True - def _get_extra_requirements(self, requirement: Requirement) -> List[Requirement]: + def _get_extra_requirements(self, requirement: Requirement) -> list[Requirement]: dist = distribution(requirement.name) # Get the required dependencies for the specified extras extra_requirements = dist.metadata.get_all("Requires-Dist") or [] @@ -272,7 +272,7 @@ def __getattr__(self, item: str) -> Any: return getattr(self._module, item) - def __dir__(self) -> List[str]: + def __dir__(self) -> list[str]: """Overwrite attribute access for dictionary.""" if self._module is None: self._import_module() diff --git a/src/lightning_utilities/core/inheritance.py b/src/lightning_utilities/core/inheritance.py index 4b498405..895ab5fc 100644 --- a/src/lightning_utilities/core/inheritance.py +++ b/src/lightning_utilities/core/inheritance.py @@ -2,13 +2,13 @@ # Licensed under the Apache License, Version 2.0 (the "License"); # http://www.apache.org/licenses/LICENSE-2.0 # -from typing import Iterator, Set, Type +from collections.abc import Iterator -def get_all_subclasses_iterator(cls: Type) -> Iterator[Type]: +def get_all_subclasses_iterator(cls: type) -> Iterator[type]: """Iterate over all subclasses.""" - def recurse(cl: Type) -> Iterator[Type]: + def recurse(cl: type) -> Iterator[type]: for subclass in cl.__subclasses__(): yield subclass yield from recurse(subclass) @@ -16,6 +16,6 @@ def recurse(cl: Type) -> Iterator[Type]: yield from recurse(cls) -def get_all_subclasses(cls: Type) -> Set[Type]: +def get_all_subclasses(cls: type) -> set[type]: """List all subclasses of a class.""" return set(get_all_subclasses_iterator(cls)) diff --git a/src/lightning_utilities/core/overrides.py b/src/lightning_utilities/core/overrides.py index f9f2286a..5dc4636d 100644 --- a/src/lightning_utilities/core/overrides.py +++ b/src/lightning_utilities/core/overrides.py @@ -3,11 +3,10 @@ # http://www.apache.org/licenses/LICENSE-2.0 # from functools import partial -from typing import Type from unittest.mock import Mock -def is_overridden(method_name: str, instance: object, parent: Type[object]) -> bool: +def is_overridden(method_name: str, instance: object, parent: type[object]) -> bool: """Check if a method of a given object was overwritten.""" instance_attr = getattr(instance, method_name, None) if instance_attr is None: diff --git a/src/lightning_utilities/docs/formatting.py b/src/lightning_utilities/docs/formatting.py index acaaff04..b3cff5f3 100644 --- a/src/lightning_utilities/docs/formatting.py +++ b/src/lightning_utilities/docs/formatting.py @@ -8,7 +8,8 @@ import os import re import sys -from typing import Iterable, List, Optional, Tuple, Union +from collections.abc import Iterable +from typing import Optional, Union def _transform_changelog(path_in: str, path_out: str) -> None: @@ -41,7 +42,7 @@ def _linkcode_resolve( main_branch: str = "master", stable_branch: str = "release/stable", ) -> str: - def find_source() -> Tuple[str, int, int]: + def find_source() -> tuple[str, int, int]: # try to find the file and line number, based on code from numpy: # https://github.com/numpy/numpy/blob/master/doc/source/conf.py#L286 obj = sys.modules[info["module"]] @@ -76,7 +77,7 @@ def find_source() -> Tuple[str, int, int]: return f"https://github.com/{github_user}/{github_repo}/blob/{filename}" -def _load_pypi_versions(package_name: str) -> List[str]: +def _load_pypi_versions(package_name: str) -> list[str]: """Load the versions of the package from PyPI. >>> _load_pypi_versions("numpy") # doctest: +ELLIPSIS diff --git a/src/lightning_utilities/docs/retriever.py b/src/lightning_utilities/docs/retriever.py index 99e3b425..4de873bf 100644 --- a/src/lightning_utilities/docs/retriever.py +++ b/src/lightning_utilities/docs/retriever.py @@ -5,7 +5,6 @@ import logging import os import re -from typing import List, Tuple import requests @@ -23,7 +22,7 @@ def _download_file(file_url: str, folder: str) -> str: return fname -def _search_all_occurrences(list_files: List[str], pattern: str) -> List[str]: +def _search_all_occurrences(list_files: list[str], pattern: str) -> list[str]: """Search for all occurrences of specific pattern in a collection of files. Args: @@ -40,7 +39,7 @@ def _search_all_occurrences(list_files: List[str], pattern: str) -> List[str]: return collected -def _replace_remote_with_local(file_path: str, docs_folder: str, pairs_url_path: List[Tuple[str, str]]) -> None: +def _replace_remote_with_local(file_path: str, docs_folder: str, pairs_url_path: list[tuple[str, str]]) -> None: """Replace all URL with local files in a given file. Args: diff --git a/src/lightning_utilities/install/requirements.py b/src/lightning_utilities/install/requirements.py index 0622d7d7..cd11ccb4 100644 --- a/src/lightning_utilities/install/requirements.py +++ b/src/lightning_utilities/install/requirements.py @@ -2,9 +2,10 @@ # http://www.apache.org/licenses/LICENSE-2.0 # import re +from collections.abc import Iterable, Iterator from distutils.version import LooseVersion from pathlib import Path -from typing import Any, Iterable, Iterator, List, Optional, Union +from typing import Any, Optional, Union from pkg_resources import Requirement, yield_lines @@ -103,7 +104,7 @@ def _parse_requirements(strs: Union[str, Iterable[str]]) -> Iterator[_Requiremen pip_argument = None -def load_requirements(path_dir: str, file_name: str = "base.txt", unfreeze: str = "all") -> List[str]: +def load_requirements(path_dir: str, file_name: str = "base.txt", unfreeze: str = "all") -> list[str]: """Load requirements from a file. >>> import os diff --git a/src/lightning_utilities/test/warning.py b/src/lightning_utilities/test/warning.py index 7d01b3da..eec3a216 100644 --- a/src/lightning_utilities/test/warning.py +++ b/src/lightning_utilities/test/warning.py @@ -3,12 +3,13 @@ # import re import warnings +from collections.abc import Generator from contextlib import contextmanager -from typing import Generator, Optional, Type +from typing import Optional @contextmanager -def no_warning_call(expected_warning: Type[Warning] = Warning, match: Optional[str] = None) -> Generator: +def no_warning_call(expected_warning: type[Warning] = Warning, match: Optional[str] = None) -> Generator: """Check that no warning was raised/emitted under this context manager.""" with warnings.catch_warnings(record=True) as record: yield diff --git a/tests/unittests/core/test_apply_func.py b/tests/unittests/core/test_apply_func.py index a769f8f0..f3faa84c 100644 --- a/tests/unittests/core/test_apply_func.py +++ b/tests/unittests/core/test_apply_func.py @@ -2,7 +2,7 @@ import numbers from collections import OrderedDict, defaultdict, namedtuple from dataclasses import InitVar -from typing import Any, ClassVar, List, Optional +from typing import Any, ClassVar, Optional import pytest from unittests.mocks import torch @@ -27,7 +27,7 @@ def __eq__(self, o: object) -> bool: @dataclasses.dataclass class ModelExample: - example_ids: List[str] + example_ids: list[str] feature: Feature label: torch.Tensor some_constant: int = dataclasses.field(init=False) diff --git a/tests/unittests/mocks.py b/tests/unittests/mocks.py index f047085e..9c2a9e13 100644 --- a/tests/unittests/mocks.py +++ b/tests/unittests/mocks.py @@ -1,4 +1,5 @@ -from typing import Any, Iterable +from collections.abc import Iterable +from typing import Any from lightning_utilities.core.imports import package_available diff --git a/tests/unittests/test/test_warnings.py b/tests/unittests/test/test_warnings.py index 9f0ee25e..0a4f0fc3 100644 --- a/tests/unittests/test/test_warnings.py +++ b/tests/unittests/test/test_warnings.py @@ -18,7 +18,8 @@ def test_no_warning_call(): class MyDeprecationWarning(DeprecationWarning): ... - with pytest.raises( - AssertionError, match=escape("`DeprecationWarning` was raised: MyDeprecationWarning('bar')") - ), no_warning_call(DeprecationWarning): + with ( + pytest.raises(AssertionError, match=escape("`DeprecationWarning` was raised: MyDeprecationWarning('bar')")), + no_warning_call(DeprecationWarning), + ): warnings.warn("bar", category=MyDeprecationWarning)