diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 47b2df0f11..f67d62732a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -83,10 +83,10 @@ jobs: test-type: [serial, parallel] include: # minimum Python/conda combo - - python-version: '3.8' + - python-version: '3.9' conda-version: 23.7.0 test-type: serial - - python-version: '3.8' + - python-version: '3.9' conda-version: 23.7.0 test-type: parallel # maximum Python/conda combo @@ -245,7 +245,7 @@ jobs: fail-fast: false matrix: # test lower version (w/ stable conda) and upper version (w/ canary conda) - python-version: ['3.8'] + python-version: ['3.9'] conda-version: [release] test-type: [serial, parallel] include: @@ -349,7 +349,7 @@ jobs: fail-fast: false matrix: # test lower version (w/ stable conda) and upper version (w/ canary conda) - python-version: ['3.8'] + python-version: ['3.9'] conda-version: [release] test-type: [serial, parallel] include: diff --git a/conda_build/api.py b/conda_build/api.py index eaea8f50b8..0cb0f74267 100644 --- a/conda_build/api.py +++ b/conda_build/api.py @@ -15,9 +15,10 @@ # to conda-build's functionality. import os import sys +from collections.abc import Iterable from os.path import dirname, expanduser, join from pathlib import Path -from typing import TYPE_CHECKING, Iterable +from typing import TYPE_CHECKING # make the Config class available in the api namespace from .config import DEFAULT_PREFIX_LENGTH as _prefix_length diff --git a/conda_build/build.py b/conda_build/build.py index 4b6d8a3cf7..5ee6c43a58 100644 --- a/conda_build/build.py +++ b/conda_build/build.py @@ -91,7 +91,8 @@ from . import windows if TYPE_CHECKING: - from typing import Any, Iterable + from collections.abc import Iterable + from typing import Any if "bsd" in sys.platform: shell_path = "/bin/sh" diff --git a/conda_build/cli/main_build.py b/conda_build/cli/main_build.py index 13e129910d..48d70032b2 100644 --- a/conda_build/cli/main_build.py +++ b/conda_build/cli/main_build.py @@ -34,7 +34,7 @@ if TYPE_CHECKING: from argparse import ArgumentParser, Namespace - from typing import Sequence + from collections.abc import Sequence def parse_args(args: Sequence[str] | None) -> tuple[ArgumentParser, Namespace]: diff --git a/conda_build/cli/main_convert.py b/conda_build/cli/main_convert.py index d30b725b3d..935760284a 100644 --- a/conda_build/cli/main_convert.py +++ b/conda_build/cli/main_convert.py @@ -12,7 +12,7 @@ if TYPE_CHECKING: from argparse import ArgumentParser, Namespace - from typing import Sequence + from collections.abc import Sequence logging.basicConfig(level=logging.INFO) diff --git a/conda_build/cli/main_debug.py b/conda_build/cli/main_debug.py index 731f964217..2cc18fc51a 100644 --- a/conda_build/cli/main_debug.py +++ b/conda_build/cli/main_debug.py @@ -15,7 +15,7 @@ if TYPE_CHECKING: from argparse import ArgumentParser - from typing import Sequence + from collections.abc import Sequence logging.basicConfig(level=logging.INFO) diff --git a/conda_build/cli/main_develop.py b/conda_build/cli/main_develop.py index 9b680cbf5a..c056d15676 100644 --- a/conda_build/cli/main_develop.py +++ b/conda_build/cli/main_develop.py @@ -17,7 +17,7 @@ if TYPE_CHECKING: from argparse import ArgumentParser, Namespace - from typing import Sequence + from collections.abc import Sequence logging.basicConfig(level=logging.INFO) diff --git a/conda_build/cli/main_inspect.py b/conda_build/cli/main_inspect.py index b1c47c0586..af7e0a946c 100644 --- a/conda_build/cli/main_inspect.py +++ b/conda_build/cli/main_inspect.py @@ -20,7 +20,7 @@ if TYPE_CHECKING: from argparse import ArgumentParser, Namespace - from typing import Sequence + from collections.abc import Sequence logging.basicConfig(level=logging.INFO) diff --git a/conda_build/cli/main_metapackage.py b/conda_build/cli/main_metapackage.py index 91d2edcebb..996a56ecd4 100644 --- a/conda_build/cli/main_metapackage.py +++ b/conda_build/cli/main_metapackage.py @@ -18,7 +18,7 @@ if TYPE_CHECKING: from argparse import ArgumentParser, Namespace - from typing import Sequence + from collections.abc import Sequence logging.basicConfig(level=logging.INFO) diff --git a/conda_build/cli/main_render.py b/conda_build/cli/main_render.py index 6e6f2bfa41..0cc8d8dfdf 100644 --- a/conda_build/cli/main_render.py +++ b/conda_build/cli/main_render.py @@ -24,7 +24,7 @@ if TYPE_CHECKING: from argparse import ArgumentParser, Namespace - from typing import Sequence + from collections.abc import Sequence log = logging.getLogger(__name__) diff --git a/conda_build/cli/main_skeleton.py b/conda_build/cli/main_skeleton.py index 7013e2ffab..66a93cef63 100644 --- a/conda_build/cli/main_skeleton.py +++ b/conda_build/cli/main_skeleton.py @@ -16,7 +16,7 @@ if TYPE_CHECKING: from argparse import ArgumentParser, Namespace - from typing import Sequence + from collections.abc import Sequence thisdir = os.path.dirname(os.path.abspath(__file__)) logging.basicConfig(level=logging.INFO) diff --git a/conda_build/convert.py b/conda_build/convert.py index 628ba95109..f776105236 100644 --- a/conda_build/convert.py +++ b/conda_build/convert.py @@ -21,7 +21,7 @@ from .utils import ensure_list, filter_info_files, walk if TYPE_CHECKING: - from typing import Iterable + from collections.abc import Iterable def retrieve_c_extensions(file_path, show_imports=False): diff --git a/conda_build/environ.py b/conda_build/environ.py index 77acf51493..129b15871a 100644 --- a/conda_build/environ.py +++ b/conda_build/environ.py @@ -12,7 +12,7 @@ import sys import warnings from collections import defaultdict -from functools import lru_cache +from functools import cache from glob import glob from logging import getLogger from os.path import join, normpath @@ -58,8 +58,9 @@ from .variants import get_default_variant if TYPE_CHECKING: + from collections.abc import Iterable from pathlib import Path - from typing import Any, Iterable, TypedDict + from typing import Any, TypedDict from .config import Config from .metadata import MetaData @@ -120,7 +121,7 @@ def get_lua_include_dir(config): return join(config.host_prefix, "include") -@lru_cache(maxsize=None) +@cache def verify_git_repo( git_exe, git_dir, git_url, git_commits_since_tag, debug=False, expected_rev="HEAD" ): @@ -602,7 +603,7 @@ def meta_vars(meta: MetaData, skip_build_id=False): return d -@lru_cache(maxsize=None) +@cache def get_cpu_count(): if on_mac: # multiprocessing.cpu_count() is not reliable on OSX @@ -724,7 +725,7 @@ def osx_vars(m, get_default, prefix): get_default("BUILD", BUILD) -@lru_cache(maxsize=None) +@cache def _machine_and_architecture(): return platform.machine(), platform.architecture() diff --git a/conda_build/inspect_pkg.py b/conda_build/inspect_pkg.py index e87c94025f..fcc54c8db0 100644 --- a/conda_build/inspect_pkg.py +++ b/conda_build/inspect_pkg.py @@ -44,7 +44,8 @@ from conda_build.index import Index if TYPE_CHECKING: - from typing import Iterable, Literal + from collections.abc import Iterable + from typing import Literal log = get_logger(__name__) diff --git a/conda_build/metadata.py b/conda_build/metadata.py index bb5f4607bb..2854248761 100644 --- a/conda_build/metadata.py +++ b/conda_build/metadata.py @@ -11,7 +11,7 @@ import time import warnings from collections import OrderedDict -from functools import lru_cache +from functools import cache, lru_cache from os.path import isdir, isfile, join from typing import TYPE_CHECKING, NamedTuple, overload @@ -289,7 +289,7 @@ def eval_selector(selector_string, namespace, variants_in_place): return eval_selector(next_string, namespace, variants_in_place) -@lru_cache(maxsize=None) +@cache def _split_line_selector(text: str) -> tuple[tuple[str | None, str], ...]: lines: list[tuple[str | None, str]] = [] for line in text.splitlines(): @@ -1069,7 +1069,7 @@ def _filter_recipe_text(text, extract_pattern=None): return text -@lru_cache(maxsize=None) +@cache def read_meta_file(meta_path): with open(meta_path, "rb") as f: recipe_text = UnicodeDammit(f.read()).unicode_markup diff --git a/conda_build/os_utils/ldd.py b/conda_build/os_utils/ldd.py index 84e80b8e90..a144ed341f 100644 --- a/conda_build/os_utils/ldd.py +++ b/conda_build/os_utils/ldd.py @@ -4,7 +4,7 @@ import re import subprocess -from functools import lru_cache +from functools import cache from os.path import basename from pathlib import Path from typing import TYPE_CHECKING @@ -17,7 +17,7 @@ if TYPE_CHECKING: import os - from typing import Iterable + from collections.abc import Iterable from conda.models.records import PrefixRecord @@ -57,7 +57,7 @@ def get_linkages( return _get_linkages(tuple(obj_files), Path(prefix), sysroot) -@lru_cache(maxsize=None) +@cache def _get_linkages( obj_files: tuple[str], prefix: Path, @@ -111,7 +111,7 @@ def _get_linkages( return linkages -@lru_cache(maxsize=None) +@cache def get_package_obj_files( prec: PrefixRecord, prefix: str | os.PathLike | Path ) -> list[str]: @@ -122,7 +122,7 @@ def get_package_obj_files( ] -@lru_cache(maxsize=None) +@cache def get_untracked_obj_files(prefix: str | os.PathLike | Path) -> list[str]: return [ file diff --git a/conda_build/plugin.py b/conda_build/plugin.py index 17cbcad143..b4218d8c1f 100644 --- a/conda_build/plugin.py +++ b/conda_build/plugin.py @@ -7,7 +7,7 @@ import conda.plugins if TYPE_CHECKING: - from typing import Sequence + from collections.abc import Sequence # lazy-import to avoid nasty import-time side effects when not using conda-build diff --git a/conda_build/render.py b/conda_build/render.py index b9ef70355a..cb2a348c84 100644 --- a/conda_build/render.py +++ b/conda_build/render.py @@ -2,6 +2,7 @@ # SPDX-License-Identifier: BSD-3-Clause from __future__ import annotations +import functools import json import os import random @@ -12,7 +13,6 @@ import tarfile from collections import OrderedDict, defaultdict from contextlib import contextmanager -from functools import lru_cache from os.path import ( isabs, isdir, @@ -49,7 +49,8 @@ if TYPE_CHECKING: import os - from typing import Any, Iterable, Iterator + from collections.abc import Iterable, Iterator + from typing import Any from .config import Config @@ -281,7 +282,7 @@ def find_pkg_dir_or_file_in_pkgs_dirs( return None -@lru_cache(maxsize=None) +@functools.cache def _read_specs_from_package(pkg_loc, pkg_dist): specs = {} if pkg_loc and isdir(pkg_loc): diff --git a/conda_build/skeletons/cpan.py b/conda_build/skeletons/cpan.py index 090f77f9cd..f5ddcd82a5 100644 --- a/conda_build/skeletons/cpan.py +++ b/conda_build/skeletons/cpan.py @@ -15,7 +15,7 @@ import subprocess import sys import tempfile -from functools import lru_cache, partial +from functools import cache, partial from glob import glob from os import makedirs from os.path import basename, dirname, exists, join @@ -639,7 +639,7 @@ def skeletonize( f.write(CPAN_BLD_BAT.format(**d)) -@lru_cache(maxsize=None) +@cache def is_core_version(core_version, version): if core_version is None: return False @@ -695,7 +695,7 @@ def add_parser(repos): ) -@lru_cache(maxsize=None) +@cache def latest_pkg_version(pkg): """ :returns: the latest version of the specified conda package available @@ -1037,7 +1037,7 @@ def core_module_dict(core_modules, module): return None -@lru_cache(maxsize=None) +@cache def metacpan_api_is_core_version(cpan_url, module): if "FindBin" in module: print("debug") diff --git a/conda_build/skeletons/pypi.py b/conda_build/skeletons/pypi.py index 2daa8ea05b..6e33af5d89 100644 --- a/conda_build/skeletons/pypi.py +++ b/conda_build/skeletons/pypi.py @@ -50,7 +50,7 @@ from ..version import _parse as parse_version if TYPE_CHECKING: - from typing import Iterable + from collections.abc import Iterable pypi_example = """ Examples: diff --git a/conda_build/skeletons/rpm.py b/conda_build/skeletons/rpm.py index d44477171f..662011bff5 100644 --- a/conda_build/skeletons/rpm.py +++ b/conda_build/skeletons/rpm.py @@ -21,7 +21,7 @@ from .cran import yaml_quote_string if TYPE_CHECKING: - from typing import Iterable + from collections.abc import Iterable from ..config import Config diff --git a/conda_build/source.py b/conda_build/source.py index 983188dd5a..dd601d2485 100644 --- a/conda_build/source.py +++ b/conda_build/source.py @@ -40,7 +40,7 @@ ) if TYPE_CHECKING: - from typing import Iterable + from collections.abc import Iterable log = get_logger(__name__) @@ -811,9 +811,11 @@ def __exit__(self, exc, value, tb): fmts = OrderedDict(native=["--binary"], lf=[], crlf=[]) if patch_exe: # Good, we have a patch executable so we can perform some checks: - with noop_context( - retained_tmpdir - ) if retained_tmpdir else TemporaryDirectory() as tmpdir: + with ( + noop_context(retained_tmpdir) + if retained_tmpdir + else TemporaryDirectory() as tmpdir + ): # Make all the fmts. result["patches"] = {} for fmt, _ in fmts.items(): diff --git a/conda_build/utils.py b/conda_build/utils.py index 4b5fdcc8d2..8d13c76b95 100644 --- a/conda_build/utils.py +++ b/conda_build/utils.py @@ -21,7 +21,8 @@ import urllib.parse as urlparse import urllib.request as urllib from collections import OrderedDict, defaultdict -from functools import lru_cache +from collections.abc import Iterable +from functools import cache from glob import glob from io import StringIO from itertools import filterfalse @@ -42,7 +43,7 @@ ) from pathlib import Path from threading import Thread -from typing import TYPE_CHECKING, Iterable, overload +from typing import TYPE_CHECKING, overload import conda_package_handling.api import filelock @@ -69,7 +70,8 @@ from .exceptions import BuildLockError if TYPE_CHECKING: - from typing import Mapping, TypeVar + from collections.abc import Mapping + from typing import TypeVar from .metadata import MetaData @@ -113,7 +115,7 @@ VALID_METAS = ("meta.yaml", "meta.yml", "conda.yaml", "conda.yml") -@lru_cache(maxsize=None) +@cache def stat_file(path): return os.stat(path) diff --git a/conda_build/variants.py b/conda_build/variants.py index f407198e92..15feb9e687 100644 --- a/conda_build/variants.py +++ b/conda_build/variants.py @@ -10,7 +10,7 @@ import sys from collections import OrderedDict from copy import copy -from functools import lru_cache +from functools import cache from itertools import product from pathlib import Path from typing import TYPE_CHECKING @@ -22,7 +22,8 @@ from .version import _parse as parse_version if TYPE_CHECKING: - from typing import Any, Iterable + from collections.abc import Iterable + from typing import Any DEFAULT_VARIANTS = { "python": f"{sys.version_info.major}.{sys.version_info.minor}", @@ -103,7 +104,7 @@ } -@lru_cache(maxsize=None) +@cache def _get_default_compilers(platform, py_ver): compilers = DEFAULT_COMPILERS[platform].copy() if platform == "win": @@ -504,7 +505,7 @@ def filter_by_key_value(variants, key, values, source_name): return reduced_variants -@lru_cache(maxsize=None) +@cache def _split_str(string, char): return string.split(char) @@ -722,7 +723,7 @@ def get_vars( } -@lru_cache(maxsize=None) +@cache def find_used_variables_in_text(variant, recipe_text, selectors_only=False): used_variables = set() recipe_lines = recipe_text.splitlines() diff --git a/news/5525-py38 b/news/5525-py38 new file mode 100644 index 0000000000..4ddc1664ed --- /dev/null +++ b/news/5525-py38 @@ -0,0 +1,19 @@ +### Enhancements + +* + +### Bug fixes + +* + +### Deprecations + +* Require Python 3.9 or greater. (#5525) + +### Docs + +* + +### Other + +* diff --git a/pyproject.toml b/pyproject.toml index 28e7ee7cc2..c9ed538a16 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,7 +14,6 @@ classifiers = [ "License :: OSI Approved :: BSD License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", @@ -48,7 +47,7 @@ dynamic = ["version"] license = {file = "LICENSE"} name = "conda-build" readme = "README.md" -requires-python = ">=3.8" +requires-python = ">=3.9" [project.entry-points.conda] conda-build = "conda_build.plugin" @@ -146,7 +145,7 @@ norecursedirs = ["tests/test-recipes/*"] testpaths = ["tests"] [tool.ruff] -target-version = "py38" +target-version = "py39" [tool.ruff.lint] flake8-type-checking = {exempt-modules = [], strict = true} diff --git a/recipe/conda_build_config.yaml b/recipe/conda_build_config.yaml index 3959a519bd..31f08ac693 100644 --- a/recipe/conda_build_config.yaml +++ b/recipe/conda_build_config.yaml @@ -1,5 +1,4 @@ python: - - '3.8' - '3.9' - '3.10' - '3.11' diff --git a/tests/conftest.py b/tests/conftest.py index cd66dddb97..3694fa680b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -5,8 +5,8 @@ import sys import tempfile from collections import defaultdict +from collections.abc import Iterator from pathlib import Path -from typing import Iterator import pytest from conda.common.compat import on_mac, on_win diff --git a/tests/requirements.txt b/tests/requirements.txt index d6e46d9cea..aad6b706e8 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -13,7 +13,7 @@ packaging pkginfo psutil py-lief -python >=3.8 +python >=3.9 python-libarchive-c pytz pyyaml diff --git a/tests/test_api_skeleton_cran.py b/tests/test_api_skeleton_cran.py index 57e9d02550..6344e95c1e 100644 --- a/tests/test_api_skeleton_cran.py +++ b/tests/test_api_skeleton_cran.py @@ -5,8 +5,8 @@ conda_build.api.skeletonize and check the output files """ +from collections.abc import Sequence from pathlib import Path -from typing import Sequence import pytest diff --git a/tests/test_codesigned.py b/tests/test_codesigned.py index 3ed13086da..32489f40d3 100644 --- a/tests/test_codesigned.py +++ b/tests/test_codesigned.py @@ -3,7 +3,7 @@ from __future__ import annotations import os -from functools import lru_cache +from functools import cache from pathlib import Path from shutil import which from subprocess import CalledProcessError, check_output, run @@ -17,7 +17,7 @@ STUB_FOLDER = REPO_ROOT / "conda_build" -@lru_cache(maxsize=None) +@cache def find_signtool() -> str | None: """Tries to find signtool @@ -65,7 +65,7 @@ def find_signtool() -> str | None: return signtool_path -@lru_cache(maxsize=None) +@cache def signtool_unsupported_because() -> str: reason = "" if not on_win: diff --git a/tests/test_develop.py b/tests/test_develop.py index 498f1650c8..9efbb436fa 100644 --- a/tests/test_develop.py +++ b/tests/test_develop.py @@ -4,8 +4,8 @@ Simple tests for testing functions in develop module - lower level than going through API. """ +from collections.abc import Generator from pathlib import Path -from typing import Generator import pytest diff --git a/tests/test_metadata.py b/tests/test_metadata.py index 99b26dd424..d5feecf53c 100644 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -585,10 +585,14 @@ def test_select_lines_invalid(): ], ) def test_sanitize_source(keys: list[str], expected: dict[str, str] | None) -> None: - with pytest.raises( - CondaBuildUserError, - match=r"Multiple git_revs:", - ) if expected is None else nullcontext(): + with ( + pytest.raises( + CondaBuildUserError, + match=r"Multiple git_revs:", + ) + if expected is None + else nullcontext() + ): assert sanitize({"source": {key: "rev" for key in keys}}) == { "source": expected } @@ -606,10 +610,14 @@ def test_sanitize_source(keys: list[str], expected: dict[str, str] | None) -> No ], ) def test_check_bad_chrs(value: str, field: str, invalid: str) -> None: - with pytest.raises( - CondaBuildUserError, - match=rf"Bad character\(s\) \({invalid}\) in {field}: {value}\.", - ) if invalid else nullcontext(): + with ( + pytest.raises( + CondaBuildUserError, + match=rf"Bad character\(s\) \({invalid}\) in {field}: {value}\.", + ) + if invalid + else nullcontext() + ): check_bad_chrs(value, field) diff --git a/tests/utils.py b/tests/utils.py index 4d6803f09d..e3a4c58a15 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -14,7 +14,7 @@ from conda_build.metadata import MetaData if TYPE_CHECKING: - from typing import Generator + from collections.abc import Generator tests_path = Path(__file__).parent metadata_path = tests_path / "test-recipes" / "metadata"