From d3fd836f5e9b87cac8c61c2578de92796b967800 Mon Sep 17 00:00:00 2001 From: "Uwe L. Korn" Date: Thu, 5 Dec 2024 13:30:42 +0100 Subject: [PATCH] Update to python>=3.9 (#2180) * Update to py>=3.9; add pyupgrade * Update .pre-commit-config.yaml * Update news/python3.9.rst Co-authored-by: jaimergp --------- Co-authored-by: Matthew R. Becker Co-authored-by: jaimergp --- conda_smithy/azure_ci_utils.py | 9 ++-- conda_smithy/cirun_utils.py | 16 +++---- conda_smithy/configure_feedstock.py | 3 +- conda_smithy/github.py | 16 +++---- conda_smithy/lint_recipe.py | 4 +- conda_smithy/linter/conda_recipe_v1_linter.py | 26 +++++------ conda_smithy/linter/hints.py | 8 ++-- conda_smithy/linter/lints.py | 44 +++++++++---------- conda_smithy/linter/utils.py | 6 +-- conda_smithy/schema.py | 44 +++++++++---------- conda_smithy/utils.py | 14 +++--- conda_smithy/validate_schema.py | 3 +- conda_smithy/variant_algebra.py | 24 +++++----- news/python3.9.rst | 3 ++ pyproject.toml | 2 +- 15 files changed, 110 insertions(+), 112 deletions(-) create mode 100644 news/python3.9.rst diff --git a/conda_smithy/azure_ci_utils.py b/conda_smithy/azure_ci_utils.py index 6758c198f..bd073dc9b 100644 --- a/conda_smithy/azure_ci_utils.py +++ b/conda_smithy/azure_ci_utils.py @@ -1,5 +1,4 @@ import os -import typing import warnings from msrest.authentication import Authentication, BasicAuthentication @@ -85,7 +84,7 @@ def get_service_endpoint(config: AzureConfig = default_config): service_endpoint_client = ServiceEndpointClient( base_url=config.instance_base_url, creds=config.credentials ) - endpoints: typing.List[ServiceEndpoint] = ( + endpoints: list[ServiceEndpoint] = ( service_endpoint_client.get_service_endpoints( project=config.project_name, type="GitHub" ) @@ -99,7 +98,7 @@ def get_service_endpoint(config: AzureConfig = default_config): def get_queues( config: AzureConfig = default_config, -) -> typing.List[TaskAgentQueue]: +) -> list[TaskAgentQueue]: aclient = TaskAgentClient(config.instance_base_url, config.credentials) return aclient.get_agent_queues(config.project_name) @@ -227,7 +226,7 @@ def register_repo(github_org, repo_name, config: AzureConfig = default_config): ) # clean up existing builds for the same feedstock if present - existing_definitions: typing.List[BuildDefinitionReference] = ( + existing_definitions: list[BuildDefinitionReference] = ( bclient.get_definitions(project=config.project_name, name=repo_name) ) if existing_definitions: @@ -253,7 +252,7 @@ def build_client(config: AzureConfig = default_config) -> BuildClient: def repo_registered( github_org: str, repo_name: str, config: AzureConfig = default_config ) -> bool: - existing_definitions: typing.List[BuildDefinitionReference] = build_client( + existing_definitions: list[BuildDefinitionReference] = build_client( config ).get_definitions(project=config.project_name, name=repo_name) diff --git a/conda_smithy/cirun_utils.py b/conda_smithy/cirun_utils.py index 27b6192c4..e5d8294e1 100644 --- a/conda_smithy/cirun_utils.py +++ b/conda_smithy/cirun_utils.py @@ -3,7 +3,7 @@ """ from functools import lru_cache -from typing import Any, Dict, List, Optional +from typing import Any, Optional from cirun import Cirun @@ -29,7 +29,7 @@ def get_cirun_installation_id(owner: str) -> int: raise ValueError(f"cirun not found for owner {owner}") -def enable_cirun_for_project(owner: str, repo: str) -> Dict[str, Any]: +def enable_cirun_for_project(owner: str, repo: str) -> dict[str, Any]: """Enable the cirun.io Github Application for a particular repository.""" print(f"Enabling cirun for {owner}/{repo} ...") cirun = _get_cirun_client() @@ -41,15 +41,15 @@ def enable_cirun_for_project(owner: str, repo: str) -> Dict[str, Any]: def add_repo_to_cirun_resource( owner: str, repo: str, - resources: List[str], - teams: List, - roles: List, + resources: list[str], + teams: list, + roles: list, users_from_json: Optional[str] = None, - cirun_policy_args: Optional[List[str]] = None, -) -> Dict[str, Any]: + cirun_policy_args: Optional[list[str]] = None, +) -> dict[str, Any]: """Grant access to a cirun resource to a particular repository, with a particular policy.""" cirun = _get_cirun_client() - policy_args: Optional[Dict[str, Any]] = None + policy_args: Optional[dict[str, Any]] = None if cirun_policy_args and "pull_request" in cirun_policy_args: policy_args = {"pull_request": True} print( diff --git a/conda_smithy/configure_feedstock.py b/conda_smithy/configure_feedstock.py index 6998aef19..15ab0d70c 100644 --- a/conda_smithy/configure_feedstock.py +++ b/conda_smithy/configure_feedstock.py @@ -16,7 +16,6 @@ from itertools import chain, product from os import fspath from pathlib import Path, PurePath -from typing import Dict import requests import yaml @@ -697,7 +696,7 @@ def _sanitize_remote_ci_setup(remote_ci_setup): def _sanitize_build_tool_deps_as_dict( forge_dir, forge_config -) -> Dict[str, str]: +) -> dict[str, str]: """ Aggregates different sources of build tool dependencies in mapping of package names to OR-merged version constraints. diff --git a/conda_smithy/github.py b/conda_smithy/github.py index df987a334..c3eac9ee4 100644 --- a/conda_smithy/github.py +++ b/conda_smithy/github.py @@ -267,9 +267,9 @@ def configure_github_team(meta, gh_repo, org, feedstock_name, remove=True): ] maintainers = set(meta.meta.get("extra", {}).get("recipe-maintainers", [])) - maintainers = set(maintainer.lower() for maintainer in maintainers) - maintainer_teams = set(m for m in maintainers if "/" in m) - maintainers = set(m for m in maintainers if "/" not in m) + maintainers = {maintainer.lower() for maintainer in maintainers} + maintainer_teams = {m for m in maintainers if "/" in m} + maintainers = {m for m in maintainers if "/" not in m} # Try to get team or create it if it doesn't exist. team_name = feedstock_name @@ -287,7 +287,7 @@ def configure_github_team(meta, gh_repo, org, feedstock_name, remove=True): ) fs_team.add_to_repos(gh_repo) - current_maintainers = set([e.login.lower() for e in fs_team.get_members()]) + current_maintainers = {e.login.lower() for e in fs_team.get_members()} # Get the all-members team description = f"All of the awesome {org.login} contributors!" @@ -309,17 +309,15 @@ def configure_github_team(meta, gh_repo, org, feedstock_name, remove=True): remove_membership(fs_team, old_maintainer) # Add any new maintainer teams - maintainer_teams = set( + maintainer_teams = { m.split("/")[1] for m in maintainer_teams if m.startswith(str(org.login)) - ) + } current_maintainer_team_objs = { team.slug: team for team in current_maintainer_teams } - current_maintainer_teams = set( - [team.slug for team in current_maintainer_teams] - ) + current_maintainer_teams = {team.slug for team in current_maintainer_teams} for new_team in maintainer_teams - current_maintainer_teams: team = org.get_team_by_slug(new_team) team.add_to_repos(gh_repo) diff --git a/conda_smithy/lint_recipe.py b/conda_smithy/lint_recipe.py index 6bef14ce5..82313497a 100644 --- a/conda_smithy/lint_recipe.py +++ b/conda_smithy/lint_recipe.py @@ -8,7 +8,7 @@ from inspect import cleandoc from pathlib import Path from textwrap import indent -from typing import Any, List, Optional, Tuple +from typing import Any, Optional import github import github.Auth @@ -113,7 +113,7 @@ def lintify_meta_yaml( recipe_dir: Optional[str] = None, conda_forge: bool = False, recipe_version: int = 0, -) -> Tuple[List[str], List[str]]: +) -> tuple[list[str], list[str]]: lints = [] hints = [] major_sections = list(meta.keys()) diff --git a/conda_smithy/linter/conda_recipe_v1_linter.py b/conda_smithy/linter/conda_recipe_v1_linter.py index 9f42b1aa7..1a5792e2a 100644 --- a/conda_smithy/linter/conda_recipe_v1_linter.py +++ b/conda_smithy/linter/conda_recipe_v1_linter.py @@ -1,5 +1,5 @@ import re -from typing import Any, Dict, List, Optional +from typing import Any, Optional from rattler_build_conda_compat.jinja.jinja import ( RecipeWithContext, @@ -39,10 +39,10 @@ def lint_recipe_tests( recipe_dir: Optional[str], - test_section: List[Dict[str, Any]], - outputs_section: List[Dict[str, Any]], - lints: List[str], - hints: List[str], + test_section: list[dict[str, Any]], + outputs_section: list[dict[str, Any]], + lints: list[str], + hints: list[str], ): tests_lints = [] tests_hints = [] @@ -72,9 +72,9 @@ def lint_recipe_tests( def hint_noarch_usage( - build_section: Dict[str, Any], - requirement_section: Dict[str, Any], - hints: List[str], + build_section: dict[str, Any], + requirement_section: dict[str, Any], + hints: list[str], ): build_reqs = requirement_section.get("build", None) if ( @@ -131,7 +131,7 @@ def get_recipe_version(recipe_content: RecipeWithContext) -> Optional[str]: def lint_recipe_name( recipe_content: RecipeWithContext, - lints: List[str], + lints: list[str], ) -> None: name = get_recipe_name(recipe_content) @@ -142,7 +142,7 @@ def lint_recipe_name( def lint_package_version( recipe_content: RecipeWithContext, - lints: List[str], + lints: list[str], ) -> None: version = get_recipe_version(recipe_content) @@ -154,10 +154,10 @@ def lint_package_version( def lint_usage_of_selectors_for_noarch( noarch_value: str, - requirements_section: Dict[str, Any], - build_section: Dict[str, Any], + requirements_section: dict[str, Any], + build_section: dict[str, Any], noarch_platforms: bool, - lints: List[str], + lints: list[str], ): for section in requirements_section: section_requirements = requirements_section[section] diff --git a/conda_smithy/linter/hints.py b/conda_smithy/linter/hints.py index 41cad5c40..bffe3c4f6 100644 --- a/conda_smithy/linter/hints.py +++ b/conda_smithy/linter/hints.py @@ -4,7 +4,7 @@ import subprocess import sys from glob import glob -from typing import Any, Dict, List +from typing import Any from conda_smithy.linter import conda_recipe_v1_linter from conda_smithy.linter.errors import HINT_NO_ARCH @@ -31,7 +31,7 @@ def hint_pip_usage(build_section, hints): def hint_sources_should_not_mention_pypi_io_but_pypi_org( - sources_section: List[Dict[str, Any]], hints: List[str] + sources_section: list[dict[str, Any]], hints: list[str] ): """ Grayskull and conda-forge default recipe used to have pypi.io as a default, @@ -181,12 +181,12 @@ def hint_check_spdx(about_section, hints): with open(os.path.join(os.path.dirname(__file__), "licenses.txt")) as f: expected_licenses = f.readlines() - expected_licenses = set([li.strip() for li in expected_licenses]) + expected_licenses = {li.strip() for li in expected_licenses} with open( os.path.join(os.path.dirname(__file__), "license_exceptions.txt") ) as f: expected_exceptions = f.readlines() - expected_exceptions = set([li.strip() for li in expected_exceptions]) + expected_exceptions = {li.strip() for li in expected_exceptions} if set(filtered_licenses) - expected_licenses: hints.append( "License is not an SPDX identifier (or a custom LicenseRef) nor an SPDX license expression.\n\n" diff --git a/conda_smithy/linter/lints.py b/conda_smithy/linter/lints.py index 31b1f2981..d800381b1 100644 --- a/conda_smithy/linter/lints.py +++ b/conda_smithy/linter/lints.py @@ -4,7 +4,7 @@ import re import tempfile from collections.abc import Sequence -from typing import Any, Dict, List, Literal, Optional +from typing import Any, Literal, Optional from conda.exceptions import InvalidVersionSpec from conda.models.version import VersionOrder @@ -33,8 +33,8 @@ def lint_section_order( - major_sections: List[str], - lints: List[str], + major_sections: list[str], + lints: list[str], recipe_version: int = 0, ): if recipe_version == 0: @@ -89,10 +89,10 @@ def lint_recipe_maintainers(extra_section, lints): def lint_recipe_have_tests( recipe_dir: str, - test_section: List[Dict[str, Any]], - outputs_section: List[Dict[str, Any]], - lints: List[str], - hints: List[str], + test_section: list[dict[str, Any]], + outputs_section: list[dict[str, Any]], + lints: list[str], + hints: list[str], recipe_version: int = 0, ): if recipe_version == 1: @@ -203,7 +203,7 @@ def lint_build_section_should_be_before_run(requirements_section, lints): def lint_sources_should_have_hash( - sources_section: List[Dict[str, Any]], lints: List[str] + sources_section: list[dict[str, Any]], lints: list[str] ): for source_section in sources_section: if "url" in source_section and not ( @@ -249,10 +249,10 @@ def lint_should_be_empty_line(meta_fname, lints): def lint_license_family_should_be_valid( - about_section: Dict[str, Any], + about_section: dict[str, Any], license: str, - needed_families: List[str], - lints: List[str], + needed_families: list[str], + lints: list[str], recipe_version: int = 0, ) -> None: lint_msg = "license_file entry is missing, but is required." @@ -269,8 +269,8 @@ def lint_license_family_should_be_valid( def lint_recipe_name( - package_section: Dict[str, Any], - lints: List[str], + package_section: dict[str, Any], + lints: list[str], ): recipe_name = package_section.get("name", "").strip() lint_msg = _lint_recipe_name(recipe_name) @@ -326,10 +326,10 @@ def lint_noarch(noarch_value: Optional[str], lints): def lint_recipe_v1_noarch_and_runtime_dependencies( noarch_value: Optional[Literal["python", "generic"]], - raw_requirements_section: Dict[str, Any], - build_section: Dict[str, Any], + raw_requirements_section: dict[str, Any], + build_section: dict[str, Any], noarch_platforms: bool, - lints: List[str], + lints: list[str], ) -> None: if noarch_value: conda_recipe_v1_linter.lint_usage_of_selectors_for_noarch( @@ -702,8 +702,8 @@ def lint_check_usage_of_whls(meta_fname, noarch_value, lints, hints): def lint_rust_licenses_are_bundled( - build_reqs: Optional[List[str]], - lints: List[str], + build_reqs: Optional[list[str]], + lints: list[str], recipe_version: int = 0, ): if not build_reqs: @@ -722,8 +722,8 @@ def lint_rust_licenses_are_bundled( def lint_go_licenses_are_bundled( - build_reqs: Optional[List[str]], - lints: List[str], + build_reqs: Optional[list[str]], + lints: list[str], recipe_version: int = 0, ): if not build_reqs: @@ -1008,8 +1008,8 @@ def sort_osx(versions): def lint_recipe_is_parsable( recipe_text: str, - lints: List[str], - hints: List[str], + lints: list[str], + hints: list[str], recipe_version: int = 0, ): parse_results = {} diff --git a/conda_smithy/linter/utils.py b/conda_smithy/linter/utils.py index c224262c6..93c731463 100644 --- a/conda_smithy/linter/utils.py +++ b/conda_smithy/linter/utils.py @@ -6,7 +6,7 @@ from collections.abc import Mapping, Sequence from functools import lru_cache from glob import glob -from typing import Dict, List, Optional, Union +from typing import Optional, Union import requests from conda.models.version import InvalidVersionSpec, VersionOrder @@ -97,7 +97,7 @@ def get_meta_section(parent, name, lints): return section -def get_recipe_v1_section(meta, name) -> Union[Dict, List[Dict]]: +def get_recipe_v1_section(meta, name) -> Union[dict, list[dict]]: if name == "requirements": return rattler_loader.load_all_requirements(meta) elif name == "tests": @@ -231,7 +231,7 @@ def load_linter_toml_metdata_internal(time_salt): return tomllib.loads(hints_toml_str) -def flatten_v1_if_else(requirements: List[str | Dict]) -> List[str]: +def flatten_v1_if_else(requirements: list[str | dict]) -> list[str]: flattened_requirements = [] for req in requirements: if isinstance(req, dict): diff --git a/conda_smithy/schema.py b/conda_smithy/schema.py index 7135ef538..56687dd25 100644 --- a/conda_smithy/schema.py +++ b/conda_smithy/schema.py @@ -4,7 +4,7 @@ import json from enum import Enum from inspect import cleandoc -from typing import Any, Dict, List, Literal, Optional, Union +from typing import Any, Literal, Optional, Union import yaml from conda.base.constants import KNOWN_SUBDIRS @@ -108,7 +108,7 @@ class AzureRunnerSettings(BaseModel): model_config: ConfigDict = ConfigDict(extra="allow") - pool: Optional[Dict[str, str]] = Field( + pool: Optional[dict[str, str]] = Field( default_factory=lambda: {"vmImage": "ubuntu-latest"}, description="The pool of self-hosted runners, e.g. 'vmImage': 'ubuntu-latest'", ) @@ -123,7 +123,7 @@ class AzureRunnerSettings(BaseModel): alias="timeoutInMinutes", ) - variables: Optional[Dict[str, str]] = Field( + variables: Optional[dict[str, str]] = Field( default_factory=dict, description="Variables" ) @@ -155,7 +155,7 @@ class AzureConfig(BaseModel): ) free_disk_space: Optional[ - Union[bool, Nullable, List[Literal["apt", "cache", "docker"]]] + Union[bool, Nullable, list[Literal["apt", "cache", "docker"]]] ] = Field( default=False, description=cleandoc( @@ -303,7 +303,7 @@ class GithubActionsConfig(BaseModel): ) free_disk_space: Optional[ - Union[bool, Nullable, List[Literal["apt", "cache", "docker"]]] + Union[bool, Nullable, list[Literal["apt", "cache", "docker"]]] ] = Field( default=False, description=cleandoc( @@ -362,13 +362,13 @@ class BotConfigVersionUpdates(BaseModel): description="Fraction of versions to keep for frequently updated packages", ) - exclude: Optional[List[str]] = Field( + exclude: Optional[list[str]] = Field( default=[], description="List of versions to exclude. " "Make sure branch names are `str` by quoting the value.", ) - sources: Optional[List[BotConfigVersionUpdatesSourcesChoice]] = Field( + sources: Optional[list[BotConfigVersionUpdatesSourcesChoice]] = Field( None, description=cleandoc( """ @@ -431,7 +431,7 @@ class BotConfig(BaseModel): description="Method for generating hints or updating recipe", ) - abi_migration_branches: Optional[List[str]] = Field( + abi_migration_branches: Optional[list[str]] = Field( default=[], description="List of branches for additional bot migration PRs. " "Make sure branch names are `str` by quoting the value.", @@ -480,7 +480,7 @@ class CondaBuildConfig(BaseModel): class LinterConfig(BaseModel): - skip: Optional[List[Lints]] = Field( + skip: Optional[list[Lints]] = Field( default_factory=list, description="List of lints to skip", ) @@ -565,7 +565,7 @@ class DefaultTestPlatforms(StrEnum): }, ) -ProviderType = Union[List[CIservices], CIservices, bool, Nullable] +ProviderType = Union[list[CIservices], CIservices, bool, Nullable] Provider = create_model( "provider", @@ -785,7 +785,7 @@ class ConfigModel(BaseModel): ), ) - choco: Optional[List[str]] = Field( + choco: Optional[list[str]] = Field( default_factory=list, description=cleandoc( """ @@ -839,7 +839,7 @@ class ConfigModel(BaseModel): ), ) - noarch_platforms: Optional[Union[Platforms, List[Platforms]]] = Field( + noarch_platforms: Optional[Union[Platforms, list[Platforms]]] = Field( default_factory=lambda: ["linux_64"], description=cleandoc( """ @@ -972,7 +972,7 @@ class ConfigModel(BaseModel): ), ) - remote_ci_setup: Optional[Union[str, List[str]]] = Field( + remote_ci_setup: Optional[Union[str, list[str]]] = Field( default_factory=lambda: [ "conda-forge-ci-setup=4", "conda-build>=24.1", @@ -1006,7 +1006,7 @@ class ConfigModel(BaseModel): ), ) - skip_render: Optional[List[str]] = Field( + skip_render: Optional[list[str]] = Field( default_factory=list, description=cleandoc( """ @@ -1025,7 +1025,7 @@ class ConfigModel(BaseModel): ), ) - templates: Optional[Dict[str, str]] = Field( + templates: Optional[dict[str, str]] = Field( default_factory=dict, description=cleandoc( """ @@ -1198,7 +1198,7 @@ class ConfigModel(BaseModel): ), ) - secrets: Optional[List[str]] = Field( + secrets: Optional[list[str]] = Field( default_factory=list, description=cleandoc( """ @@ -1220,7 +1220,7 @@ class ConfigModel(BaseModel): ################################### #### CI Providers #### ################################### - travis: Optional[Dict[str, Any]] = Field( + travis: Optional[dict[str, Any]] = Field( default_factory=dict, description=cleandoc( """ @@ -1230,7 +1230,7 @@ class ConfigModel(BaseModel): ), ) - circle: Optional[Dict[str, Any]] = Field( + circle: Optional[dict[str, Any]] = Field( default_factory=dict, description=cleandoc( """ @@ -1240,7 +1240,7 @@ class ConfigModel(BaseModel): ), ) - appveyor: Optional[Dict[str, Any]] = Field( + appveyor: Optional[dict[str, Any]] = Field( default_factory=lambda: {"image": "Visual Studio 2017"}, description=cleandoc( """ @@ -1309,7 +1309,7 @@ class ConfigModel(BaseModel): ), ) - drone: Optional[Dict[str, str]] = Field( + drone: Optional[dict[str, str]] = Field( default_factory=dict, description=cleandoc( """ @@ -1329,7 +1329,7 @@ class ConfigModel(BaseModel): ), ) - woodpecker: Optional[Dict[str, str]] = Field( + woodpecker: Optional[dict[str, str]] = Field( default_factory=dict, description=cleandoc( """ @@ -1357,7 +1357,7 @@ class ConfigModel(BaseModel): ), ) - matrix: Optional[Dict[str, Any]] = Field( + matrix: Optional[dict[str, Any]] = Field( default_factory=dict, exclude=True, deprecated=True, diff --git a/conda_smithy/utils.py b/conda_smithy/utils.py index 5eb7869b7..2fbec1f9f 100644 --- a/conda_smithy/utils.py +++ b/conda_smithy/utils.py @@ -8,7 +8,7 @@ from collections import defaultdict from contextlib import contextmanager from pathlib import Path -from typing import Any, Dict, Union +from typing import Any, Union import jinja2 import jinja2.sandbox @@ -25,7 +25,7 @@ def _get_metadata_from_feedstock_dir( feedstock_directory: Union[str, os.PathLike], - forge_config: Dict[str, Any], + forge_config: dict[str, Any], conda_forge_pinning_file: Union[str, os.PathLike, None] = None, ) -> Union[MetaData, RattlerBuildMetaData]: """ @@ -117,7 +117,7 @@ def __getitem__(self, name): class MockOS(dict): def __init__(self): - self.environ = defaultdict(lambda: "") + self.environ = defaultdict(str) self.sep = "/" @@ -151,10 +151,10 @@ def render_meta_yaml(text): pin_subpackage=stub_subpackage_pin, pin_compatible=stub_compatible_pin, cdt=lambda *args, **kwargs: "cdt_stub", - load_file_regex=lambda *args, **kwargs: defaultdict(lambda: ""), - load_file_data=lambda *args, **kwargs: defaultdict(lambda: ""), - load_setup_py_data=lambda *args, **kwargs: defaultdict(lambda: ""), - load_str_data=lambda *args, **kwargs: defaultdict(lambda: ""), + load_file_regex=lambda *args, **kwargs: defaultdict(str), + load_file_data=lambda *args, **kwargs: defaultdict(str), + load_setup_py_data=lambda *args, **kwargs: defaultdict(str), + load_str_data=lambda *args, **kwargs: defaultdict(str), datetime=datetime, time=time, target_platform="linux-64", diff --git a/conda_smithy/validate_schema.py b/conda_smithy/validate_schema.py index 555de599a..6722bad23 100644 --- a/conda_smithy/validate_schema.py +++ b/conda_smithy/validate_schema.py @@ -1,6 +1,5 @@ import json from pathlib import Path -from typing import List, Tuple from jsonschema import Draft202012Validator, validators from jsonschema.exceptions import ValidationError @@ -40,7 +39,7 @@ def get_validator_class(): def validate_json_schema( config, schema_file: str = None -) -> Tuple[List[ValidationError], List[ValidationError]]: +) -> tuple[list[ValidationError], list[ValidationError]]: # Validate the merged configuration against a JSON schema if not schema_file: schema_file = CONDA_FORGE_YAML_SCHEMA_FILE diff --git a/conda_smithy/variant_algebra.py b/conda_smithy/variant_algebra.py index 43a14541a..0c143d4d5 100644 --- a/conda_smithy/variant_algebra.py +++ b/conda_smithy/variant_algebra.py @@ -14,7 +14,7 @@ """ from functools import partial -from typing import Any, Dict, List, Optional, Union +from typing import Any, Optional, Union import conda_build.variants as variants import tlz @@ -26,14 +26,14 @@ def parse_variant( variant_file_content: str, config: Optional[Config] = None -) -> Dict[ +) -> dict[ str, Union[ - List[str], + list[str], float, - List[List[str]], - Dict[str, Dict[str, str]], - Dict[str, Dict[str, List[str]]], + list[list[str]], + dict[str, dict[str, str]], + dict[str, dict[str, list[str]]], ], ]: """ @@ -59,7 +59,7 @@ def parse_variant( def _version_order( - v: Union[str, float], ordering: Optional[List[str]] = None + v: Union[str, float], ordering: Optional[list[str]] = None ) -> Union[int, VersionOrder, float]: if ordering is not None: return ordering.index(v) @@ -74,10 +74,10 @@ def _version_order( def variant_key_add( k: str, - v_left: Union[List[str], List[float]], - v_right: Union[List[str], List[float]], - ordering: Optional[List[str]] = None, -) -> Union[List[str], List[float]]: + v_left: Union[list[str], list[float]], + v_right: Union[list[str], list[float]], + ordering: Optional[list[str]] = None, +) -> Union[list[str], list[float]]: """Version summation adder. This takes the higher version of the two things. @@ -268,7 +268,7 @@ def op_variant_key_remove(v1: dict, v2: dict): } -def variant_add(v1: dict, v2: dict) -> Dict[str, Any]: +def variant_add(v1: dict, v2: dict) -> dict[str, Any]: """Adds the two variants together. Present this assumes mostly flat dictionaries. diff --git a/news/python3.9.rst b/news/python3.9.rst new file mode 100644 index 000000000..026e710ab --- /dev/null +++ b/news/python3.9.rst @@ -0,0 +1,3 @@ +**Changed:** + +* Set minimal Python version to 3.9. (#2180) diff --git a/pyproject.toml b/pyproject.toml index 02a7e84eb..54830b79c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ authors = [ ] description = "A package to create repositories for conda recipes, and automate their building with CI tools on Linux, OSX and Windows." dynamic = ["version"] -requires-python = ">=3.8" +requires-python = ">=3.9" [project.urls] home = "https://github.com/conda-forge/conda-smithy"