From aa0014f7340803dbfd7c6070c3fcfd0e15b68472 Mon Sep 17 00:00:00 2001 From: Isuru Fernando Date: Sun, 16 Feb 2025 14:23:14 -0600 Subject: [PATCH 01/13] Fix python requirement --- .github/workflows/tests.yml | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1d6267e76..a61853c54 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -28,7 +28,7 @@ jobs: micromamba-version: 1.5.12-0 cache-environment: true create-args: >- - python=3.11 + python=3.10 coverage coveralls conda-recipe-manager>=0.4.1 diff --git a/pyproject.toml b/pyproject.toml index 54830b79c..b7a7b6178 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.9" +requires-python = ">=3.10" [project.urls] home = "https://github.com/conda-forge/conda-smithy" From 6f97f1520ce01a56fc5d90b14d5ae548308f0f2f Mon Sep 17 00:00:00 2001 From: Isuru Fernando Date: Sun, 16 Feb 2025 14:41:48 -0600 Subject: [PATCH 02/13] Fix local testing --- tests/test_lint_recipe.py | 73 +++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/tests/test_lint_recipe.py b/tests/test_lint_recipe.py index 768607550..c78a2ff6b 100644 --- a/tests/test_lint_recipe.py +++ b/tests/test_lint_recipe.py @@ -18,6 +18,12 @@ _thisdir = os.path.abspath(os.path.dirname(__file__)) +try: + import conda_recipe_manager.parser.recipe_parser + has_conda_recipe_manager = True +except ImportError: + has_conda_recipe_manager = False + @contextmanager def get_recipe_in_dir(recipe_name: str) -> Path: @@ -1908,6 +1914,9 @@ def test_maintainer_exists_no_token(self): if gh_token is not None: os.environ["GH_TOKEN"] = gh_token + @pytest.mark.skipif( + "GH_TOKEN" not in os.environ, reason="github token not found" + ) def test_maintainer_team_exists(self): lints, _ = linter.lintify_meta_yaml( { @@ -3941,12 +3950,13 @@ def test_lint_recipe_parses_forblock(): ) for hint in hints ), hints - assert any( - hint.startswith( - "The recipe is not parsable by parser `conda-recipe-manager" - ) - for hint in hints - ), hints + if has_conda_recipe_manager: + assert any( + hint.startswith( + "The recipe is not parsable by parser `conda-recipe-manager" + ) + for hint in hints + ), hints assert not any( hint.startswith( "The recipe is not parsable by parser `conda-souschef" @@ -3993,12 +4003,13 @@ def test_lint_recipe_parses_spacing(): ) for hint in hints ), hints - assert not any( - hint.startswith( - "The recipe is not parsable by parser `conda-recipe-manager" - ) - for hint in hints - ), hints + if has_conda_recipe_manager: + assert not any( + hint.startswith( + "The recipe is not parsable by parser `conda-recipe-manager" + ) + for hint in hints + ), hints assert not any( hint.startswith( "The recipe is not parsable by parser `conda-souschef" @@ -4039,12 +4050,13 @@ def test_lint_recipe_parses_v1_spacing(): ) for lint in lints ), lints - assert any( - hint.startswith( - "The recipe is not parsable by parser `conda-recipe-manager" - ) - for hint in hints - ), hints + if has_conda_recipe_manager: + assert any( + hint.startswith( + "The recipe is not parsable by parser `conda-recipe-manager" + ) + for hint in hints + ), hints assert not any( hint.startswith( "The recipe is not parsable by parser `ruamel.yaml" @@ -4080,18 +4092,19 @@ def test_lint_recipe_parses_v1_duplicate_keys(): ) ) lints, hints = linter.main(tmpdir, return_hints=True, conda_forge=True) - assert not any( - lint.startswith( - "The recipe is not parsable by any of the known recipe parsers" - ) - for lint in lints - ), lints - assert not any( - hint.startswith( - "The recipe is not parsable by parser `conda-recipe-manager" - ) - for hint in hints - ), hints + if has_conda_recipe_manager: + assert not any( + lint.startswith( + "The recipe is not parsable by any of the known recipe parsers" + ) + for lint in lints + ), lints + assert not any( + hint.startswith( + "The recipe is not parsable by parser `conda-recipe-manager" + ) + for hint in hints + ), hints assert any( hint.startswith( "The recipe is not parsable by parser `ruamel.yaml" From 1058544270bfc0bfca7434dd6cca6acb5b612abd Mon Sep 17 00:00:00 2001 From: Isuru Fernando Date: Sun, 16 Feb 2025 14:43:10 -0600 Subject: [PATCH 03/13] run tests without github token --- .github/workflows/tests.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a61853c54..dfbaa53e0 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -31,7 +31,6 @@ jobs: python=3.10 coverage coveralls - conda-recipe-manager>=0.4.1 conda-souschef conda-forge-tick @@ -65,6 +64,10 @@ jobs: python -m pip install -v --no-build-isolation -e . + - name: run tests without token + run: | + pytest tests + - name: run tests run: | pytest tests --cov conda_smithy --cov-report lcov --cov-report term-missing From 5a91847d9cc4259f13cf393291616aa244c5dbfb Mon Sep 17 00:00:00 2001 From: Isuru Fernando Date: Sun, 16 Feb 2025 14:47:34 -0600 Subject: [PATCH 04/13] matrix of jobs --- .github/workflows/tests.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index dfbaa53e0..a0da250eb 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,6 +17,9 @@ jobs: tests: name: tests runs-on: "ubuntu-latest" + strategy: + matrix: + python_version: [3.10, 3.11] steps: - uses: actions/checkout@v4 with: @@ -28,11 +31,16 @@ jobs: micromamba-version: 1.5.12-0 cache-environment: true create-args: >- - python=3.10 + python=${{ matrix.python_version }} coverage coveralls conda-souschef - conda-forge-tick + + - name: install conda-forge-tick and conda-forge-recipe-manager + run: | + if [[ "${{ matrix.python_version }}" != "3.10" ]]; then + conda install conda-forge-recipe-manager conda-forge-tick + fi - name: install conda-smithy run: | From cacd0bc4a045419863c9b060611ffe83c6daf806 Mon Sep 17 00:00:00 2001 From: Isuru Fernando Date: Sun, 16 Feb 2025 14:48:38 -0600 Subject: [PATCH 05/13] fix conda-recipe-manager requirement --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a0da250eb..1862c8c38 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -39,7 +39,7 @@ jobs: - name: install conda-forge-tick and conda-forge-recipe-manager run: | if [[ "${{ matrix.python_version }}" != "3.10" ]]; then - conda install conda-forge-recipe-manager conda-forge-tick + conda install "conda-forge-recipe-manager>=0.4.1" conda-forge-tick fi - name: install conda-smithy From 0b36ce88569d4321a901a98482e51fae59ff11b4 Mon Sep 17 00:00:00 2001 From: Isuru Fernando Date: Sun, 16 Feb 2025 14:49:55 -0600 Subject: [PATCH 06/13] use strings --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1862c8c38..a7bf3b6f3 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -19,7 +19,7 @@ jobs: runs-on: "ubuntu-latest" strategy: matrix: - python_version: [3.10, 3.11] + python_version: ["3.10", "3.11"] steps: - uses: actions/checkout@v4 with: From e130df8374ddd97021cf7052272bd508f4758ada Mon Sep 17 00:00:00 2001 From: Isuru Fernando Date: Sun, 16 Feb 2025 14:51:56 -0600 Subject: [PATCH 07/13] fix uninstalling conda-smithy --- .github/workflows/tests.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a7bf3b6f3..a81cd0b53 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -44,7 +44,9 @@ jobs: - name: install conda-smithy run: | - conda uninstall --force --yes conda-smithy + if [[ "${{ matrix.python_version }}" != "3.10" ]]; then + conda uninstall --force --yes conda-smithy + fi python -m pip install -v --no-build-isolation -e . git config --global user.email "smithy@smithy.smithy" git config --global user.name "smithy" From c68997ce51b1d36827bc4ccdc6312e466bd4e9ac Mon Sep 17 00:00:00 2001 From: Isuru Fernando Date: Sun, 16 Feb 2025 14:55:45 -0600 Subject: [PATCH 08/13] fix typo --- .github/workflows/tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a81cd0b53..af181432c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -36,10 +36,10 @@ jobs: coveralls conda-souschef - - name: install conda-forge-tick and conda-forge-recipe-manager + - name: install conda-forge-tick and conda-recipe-manager run: | if [[ "${{ matrix.python_version }}" != "3.10" ]]; then - conda install "conda-forge-recipe-manager>=0.4.1" conda-forge-tick + conda install "conda-recipe-manager>=0.4.1" conda-forge-tick fi - name: install conda-smithy From 458db88c80ca4d1ec40cdb462aaccc56f2685478 Mon Sep 17 00:00:00 2001 From: Isuru Fernando Date: Sun, 16 Feb 2025 15:04:02 -0600 Subject: [PATCH 09/13] no cancel in progress --- .github/workflows/tests.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index af181432c..23e1002f8 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -6,9 +6,6 @@ on: - main pull_request: null -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true defaults: run: shell: bash -el {0} @@ -39,7 +36,7 @@ jobs: - name: install conda-forge-tick and conda-recipe-manager run: | if [[ "${{ matrix.python_version }}" != "3.10" ]]; then - conda install "conda-recipe-manager>=0.4.1" conda-forge-tick + conda install "conda-recipe-manager>=0.4.1" conda-forge-tick --yes --quiet fi - name: install conda-smithy From 33549f7ab5ef8ab7ec94f33a7d95fa0496697f4f Mon Sep 17 00:00:00 2001 From: Isuru Fernando Date: Sun, 16 Feb 2025 15:14:33 -0600 Subject: [PATCH 10/13] disable cancel in progress --- .github/workflows/tests.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 23e1002f8..7c67c1c97 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -6,6 +6,10 @@ on: - main pull_request: null +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false + defaults: run: shell: bash -el {0} From 662ccec134e395bca4464f0f3e9b3917b5eee30f Mon Sep 17 00:00:00 2001 From: Isuru Fernando Date: Sun, 16 Feb 2025 15:18:42 -0600 Subject: [PATCH 11/13] macos --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7c67c1c97..edb458148 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,7 +17,7 @@ defaults: jobs: tests: name: tests - runs-on: "ubuntu-latest" + runs-on: "macos-latest" strategy: matrix: python_version: ["3.10", "3.11"] From fed61e078b72689165e2fa37acb65b00d7136465 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 16 Feb 2025 23:03:27 +0000 Subject: [PATCH 12/13] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- conda_smithy/cirun_utils.py | 8 +- conda_smithy/cli.py | 7 +- conda_smithy/lint_recipe.py | 8 +- conda_smithy/linter/conda_recipe_v1_linter.py | 6 +- conda_smithy/linter/lints.py | 10 +- conda_smithy/linter/utils.py | 9 +- conda_smithy/schema.py | 186 +++++++++--------- conda_smithy/utils.py | 10 +- conda_smithy/variant_algebra.py | 24 +-- tests/test_lint_recipe.py | 1 + 10 files changed, 128 insertions(+), 141 deletions(-) diff --git a/conda_smithy/cirun_utils.py b/conda_smithy/cirun_utils.py index e5d8294e1..058b09441 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, Optional +from typing import Any from cirun import Cirun @@ -44,12 +44,12 @@ def add_repo_to_cirun_resource( resources: list[str], teams: list, roles: list, - users_from_json: Optional[str] = None, - cirun_policy_args: Optional[list[str]] = None, + users_from_json: str | None = None, + cirun_policy_args: list[str] | None = 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: dict[str, Any] | None = None if cirun_policy_args and "pull_request" in cirun_policy_args: policy_args = {"pull_request": True} print( diff --git a/conda_smithy/cli.py b/conda_smithy/cli.py index af862f7c4..774a4aa12 100644 --- a/conda_smithy/cli.py +++ b/conda_smithy/cli.py @@ -6,7 +6,6 @@ import tempfile import time from textwrap import dedent -from typing import Optional, Union import conda # noqa from conda_build.metadata import MetaData @@ -35,7 +34,7 @@ def default_feedstock_config_path(feedstock_directory): def generate_feedstock_content( - target_directory, source_recipe_dir, conda_build_tool: Optional[str] = None + target_directory, source_recipe_dir, conda_build_tool: str | None = None ): target_directory = os.path.abspath(target_directory) recipe_dir = "recipe" @@ -130,7 +129,7 @@ def __call__(self, args): # Get some information about the source recipe. # detect if it's old recipe or new one - meta: Union[MetaData, RattlerMetaData] + meta: MetaData | RattlerMetaData build_tool = CONDA_BUILD @@ -143,7 +142,7 @@ def __call__(self, args): else: meta = RattlerMetaData(args.recipe_directory) - conda_build_tool: Optional[str] = ( + conda_build_tool: str | None = ( RATTLER_BUILD if isinstance(meta, RattlerMetaData) else None ) diff --git a/conda_smithy/lint_recipe.py b/conda_smithy/lint_recipe.py index f5716c42a..63e2368e7 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, Optional +from typing import Any import github import github.Auth @@ -84,7 +84,7 @@ NEEDED_FAMILIES = ["gpl", "bsd", "mit", "apache", "psf"] -def _get_forge_yaml(recipe_dir: Optional[str] = None) -> dict: +def _get_forge_yaml(recipe_dir: str | None = None) -> dict: if recipe_dir: forge_yaml_filename = ( glob(os.path.join(recipe_dir, "..", "conda-forge.yml")) @@ -106,7 +106,7 @@ def _get_forge_yaml(recipe_dir: Optional[str] = None) -> dict: return forge_yaml -def lintify_forge_yaml(recipe_dir: Optional[str] = None) -> (list, list): +def lintify_forge_yaml(recipe_dir: str | None = None) -> (list, list): forge_yaml = _get_forge_yaml(recipe_dir) # This is where we validate against the jsonschema and execute our custom validators. return validate_json_schema(forge_yaml) @@ -114,7 +114,7 @@ def lintify_forge_yaml(recipe_dir: Optional[str] = None) -> (list, list): def lintify_meta_yaml( meta: Any, - recipe_dir: Optional[str] = None, + recipe_dir: str | None = None, conda_forge: bool = False, recipe_version: int = 0, ) -> tuple[list[str], list[str]]: diff --git a/conda_smithy/linter/conda_recipe_v1_linter.py b/conda_smithy/linter/conda_recipe_v1_linter.py index 53be7cc1c..4be547928 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, Optional +from typing import Any from rattler_build_conda_compat.jinja.jinja import ( RecipeWithContext, @@ -40,7 +40,7 @@ def lint_recipe_tests( - recipe_dir: Optional[str], + recipe_dir: str | None, test_section: list[dict[str, Any]], outputs_section: list[dict[str, Any]], lints: list[str], @@ -117,7 +117,7 @@ def get_recipe_name(recipe_content: RecipeWithContext) -> str: return package_name or recipe_name -def get_recipe_version(recipe_content: RecipeWithContext) -> Optional[str]: +def get_recipe_version(recipe_content: RecipeWithContext) -> str | None: rendered_context_recipe = render_recipe_with_context(recipe_content) package_version = rendered_context_recipe.get("package", {}).get("version") recipe_version = rendered_context_recipe.get("recipe", {}).get("version") diff --git a/conda_smithy/linter/lints.py b/conda_smithy/linter/lints.py index 562dbe236..253796d1d 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, Literal, Optional +from typing import Any, Literal from conda.models.version import VersionOrder from rattler_build_conda_compat.jinja.jinja import render_recipe_with_context @@ -329,7 +329,7 @@ def lint_subheaders(major_sections, meta, lints): ) -def lint_noarch(noarch_value: Optional[str], lints): +def lint_noarch(noarch_value: str | None, lints): if noarch_value is not None: valid_noarch_values = ["python", "generic"] if noarch_value not in valid_noarch_values: @@ -340,7 +340,7 @@ def lint_noarch(noarch_value: Optional[str], lints): def lint_recipe_v1_noarch_and_runtime_dependencies( - noarch_value: Optional[Literal["python", "generic"]], + noarch_value: Literal["python", "generic"] | None, raw_requirements_section: dict[str, Any], build_section: dict[str, Any], noarch_platforms: bool, @@ -711,7 +711,7 @@ def lint_check_usage_of_whls(meta_fname, noarch_value, lints, hints): def lint_rust_licenses_are_bundled( - build_reqs: Optional[list[str]], + build_reqs: list[str] | None, lints: list[str], recipe_version: int = 0, ): @@ -731,7 +731,7 @@ def lint_rust_licenses_are_bundled( def lint_go_licenses_are_bundled( - build_reqs: Optional[list[str]], + build_reqs: list[str] | None, lints: list[str], recipe_version: int = 0, ): diff --git a/conda_smithy/linter/utils.py b/conda_smithy/linter/utils.py index 5153bc6b9..8f2ee730a 100644 --- a/conda_smithy/linter/utils.py +++ b/conda_smithy/linter/utils.py @@ -6,7 +6,6 @@ from collections.abc import Mapping, Sequence from functools import lru_cache from glob import glob -from typing import Optional, Union import requests from conda.models.version import InvalidVersionSpec, VersionOrder @@ -99,7 +98,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) -> dict | list[dict]: if name == "requirements": return rattler_loader.load_all_requirements(meta) elif name == "tests": @@ -128,7 +127,7 @@ def get_list_section(parent, name, lints, allow_single=False): return [{}] -def find_local_config_file(recipe_dir: str, filename: str) -> Optional[str]: +def find_local_config_file(recipe_dir: str, filename: str) -> str | None: # support # 1. feedstocks # 2. staged-recipes with custom conda-forge.yaml in recipe @@ -195,7 +194,7 @@ def jinja_lines(lines): yield line, i -def _lint_recipe_name(recipe_name: str) -> Optional[str]: +def _lint_recipe_name(recipe_name: str) -> str | None: wrong_recipe_name = "Recipe name has invalid characters. only lowercase alpha, numeric, underscores, hyphens and dots allowed" if re.match(r"^[a-z0-9_\-.]+$", recipe_name) is None: @@ -204,7 +203,7 @@ def _lint_recipe_name(recipe_name: str) -> Optional[str]: return None -def _lint_package_version(version: Optional[str]) -> Optional[str]: +def _lint_package_version(version: str | None) -> str | None: no_package_version = "Package version is missing." invalid_version = "Package version {ver} doesn't match conda spec: {err}" diff --git a/conda_smithy/schema.py b/conda_smithy/schema.py index c735a2013..f4057f2ed 100644 --- a/conda_smithy/schema.py +++ b/conda_smithy/schema.py @@ -110,27 +110,27 @@ class AzureRunnerSettings(BaseModel): model_config: ConfigDict = ConfigDict(extra="allow") - pool: Optional[dict[str, str]] = Field( + pool: dict[str, str] | None = Field( default_factory=lambda: {"vmImage": "ubuntu-latest"}, description="The pool of self-hosted runners, e.g. 'vmImage': 'ubuntu-latest'", ) - swapfile_size: Optional[Union[str, Nullable]] = Field( + swapfile_size: str | Nullable | None = Field( default=None, description="Swapfile size in GiB" ) - timeout_in_minutes: Optional[int] = Field( + timeout_in_minutes: int | None = Field( default=360, description="Timeout in minutes for the job", alias="timeoutInMinutes", ) - variables: Optional[dict[str, str]] = Field( + variables: dict[str, str] | None = Field( default_factory=dict, description="Variables" ) # windows only - install_atl: Optional[bool] = Field( + install_atl: bool | None = Field( default=False, description="Whether to install ATL components for MSVC" ) @@ -151,14 +151,12 @@ class AzureConfig(BaseModel): model_config: ConfigDict = ConfigDict(extra="forbid") - force: Optional[bool] = Field( + force: bool | None = Field( default=False, description="Force building all supported providers", ) - free_disk_space: Optional[ - Union[bool, Nullable, list[Literal["apt", "cache", "docker"]]] - ] = Field( + free_disk_space: bool | Nullable | list[Literal["apt", "cache", "docker"]] | None = Field( default=False, description=cleandoc( """ @@ -170,22 +168,22 @@ class AzureConfig(BaseModel): ), ) - max_parallel: Optional[int] = Field( + max_parallel: int | None = Field( default=50, description="Limit the amount of CI jobs running concurrently at a given time", ) - project_id: Optional[str] = Field( + project_id: str | None = Field( default="84710dde-1620-425b-80d0-4cf5baca359d", description="The ID of the Azure Pipelines project", ) - project_name: Optional[str] = Field( + project_name: str | None = Field( default="feedstock-builds", description="The name of the Azure Pipelines project", ) - build_id: Optional[int] = Field( + build_id: int | None = Field( default=None, description=cleandoc( """ @@ -197,7 +195,7 @@ class AzureConfig(BaseModel): ), ) - upload_packages: Optional[bool] = Field( + upload_packages: bool | None = Field( default=True, description="Whether to upload the packages to Anaconda.org. Useful for testing.", ) @@ -248,7 +246,7 @@ class AzureConfig(BaseModel): ), ) - user_or_org: Optional[Union[str, Nullable]] = Field( + user_or_org: str | Nullable | None = Field( default=None, description="The name of the Azure user or organization. Defaults to the " "value of github: user_or_org.", @@ -256,13 +254,13 @@ class AzureConfig(BaseModel): # set or not ) - store_build_artifacts: Optional[bool] = Field( + store_build_artifacts: bool | None = Field( default=False, description="Store the conda build_artifacts directory as an \ Azure pipeline artifact", ) - timeout_minutes: Optional[Union[int, Nullable]] = Field( + timeout_minutes: int | Nullable | None = Field( default=None, description="The maximum amount of time (in minutes) that a \ job can run before it is automatically canceled", @@ -272,19 +270,19 @@ class AzureConfig(BaseModel): class GithubConfig(BaseModel): model_config: ConfigDict = ConfigDict(extra="forbid") - user_or_org: Optional[str] = Field( + user_or_org: str | None = Field( description="The name of the GitHub user or organization", default="conda-forge", ) - repo_name: Optional[str] = Field( + repo_name: str | None = Field( description="The name of the repository", default="", ) - branch_name: Optional[str] = Field( + branch_name: str | None = Field( description="The name of the branch to execute on", default="main", ) - tooling_branch_name: Optional[str] = Field( + tooling_branch_name: str | None = Field( description="The name of the branch to use for rerender+webservices \ github actions and conda-forge-ci-setup-feedstock references", default="main", @@ -294,19 +292,17 @@ class GithubConfig(BaseModel): class GithubActionsConfig(BaseModel): model_config: ConfigDict = ConfigDict(extra="forbid") - artifact_retention_days: Optional[int] = Field( + artifact_retention_days: int | None = Field( description="The number of days to retain artifacts", default=14, ) - cancel_in_progress: Optional[bool] = Field( + cancel_in_progress: bool | None = Field( description="Whether to cancel jobs in the same build if one fails.", default=True, ) - free_disk_space: Optional[ - Union[bool, Nullable, list[Literal["apt", "cache", "docker"]]] - ] = Field( + free_disk_space: bool | Nullable | list[Literal["apt", "cache", "docker"]] | None = Field( default=False, description=cleandoc( """ @@ -318,34 +314,34 @@ class GithubActionsConfig(BaseModel): ), ) - max_parallel: Optional[Union[int, Nullable]] = Field( + max_parallel: int | Nullable | None = Field( description="The maximum number of jobs to run in parallel", default=None, ) - self_hosted: Optional[bool] = Field( + self_hosted: bool | None = Field( description="Whether to use self-hosted runners", default=False, ) - store_build_artifacts: Optional[bool] = Field( + store_build_artifacts: bool | None = Field( description="Whether to store build artifacts", default=False, ) - timeout_minutes: Optional[int] = Field( + timeout_minutes: int | None = Field( default=360, description="The maximum amount of time (in minutes) that a \ job can run before it is automatically canceled", ) - triggers: Optional[list] = Field( + triggers: list | None = Field( default=[], description="Triggers for Github Actions. Defaults to push, pull_request, \ when not self-hosted and push when self-hosted", ) - upload_packages: Optional[bool] = Field( + upload_packages: bool | None = Field( default=True, description="Whether to upload the packages to Anaconda.org. Useful for testing.", ) @@ -359,18 +355,18 @@ class BotConfigVersionUpdates(BaseModel): model_config: ConfigDict = ConfigDict(extra="forbid") - random_fraction_to_keep: Optional[float] = Field( + random_fraction_to_keep: float | None = Field( None, description="Fraction of versions to keep for frequently updated packages", ) - exclude: Optional[list[str]] = Field( + exclude: list[str] | None = Field( default=[], description="List of versions to exclude. " "Make sure branch names are `str` by quoting the value.", ) - sources: Optional[list[BotConfigVersionUpdatesSourcesChoice]] = Field( + sources: list[BotConfigVersionUpdatesSourcesChoice] | None = Field( None, description=cleandoc( """ @@ -402,7 +398,7 @@ class BotConfigVersionUpdates(BaseModel): ), ) - skip: Optional[bool] = Field( + skip: bool | None = Field( default=False, description="Skip automatic version updates. " "Useful in cases where the source project's version numbers don't conform to " @@ -418,33 +414,33 @@ class BotConfig(BaseModel): model_config: ConfigDict = ConfigDict(extra="forbid") - automerge: Optional[Union[bool, BotConfigAutoMergeChoice]] = Field( + automerge: bool | BotConfigAutoMergeChoice | None = Field( False, description="Automatically merge PRs if possible", ) - check_solvable: Optional[bool] = Field( + check_solvable: bool | None = Field( default=True, description="Open PRs only if resulting environment is solvable.", ) - inspection: Optional[BotConfigInspectionChoice] = Field( + inspection: BotConfigInspectionChoice | None = Field( default="hint", description="Method for generating hints or updating recipe", ) - abi_migration_branches: Optional[list[str]] = Field( + abi_migration_branches: list[str] | None = Field( default=[], description="List of branches for additional bot migration PRs. " "Make sure branch names are `str` by quoting the value.", ) - run_deps_from_wheel: Optional[bool] = Field( + run_deps_from_wheel: bool | None = Field( default=False, description="Update run dependencies from the pip wheel", ) - version_updates: Optional[BotConfigVersionUpdates] = Field( + version_updates: BotConfigVersionUpdates | None = Field( default_factory=BotConfigVersionUpdates, description="Bot config for version update PRs", ) @@ -453,12 +449,12 @@ class BotConfig(BaseModel): class CondaBuildConfig(BaseModel): model_config: ConfigDict = ConfigDict(extra="allow") - pkg_format: Optional[Literal["tar", 1, 2, "1", "2"]] = Field( + pkg_format: Literal["tar", 1, 2, "1", "2"] | None = Field( description="The package version format for conda build.", default=2, ) - zstd_compression_level: Optional[int] = Field( + zstd_compression_level: int | None = Field( default=16, description=cleandoc( """The compression level for the zstd compression algorithm for @@ -467,7 +463,7 @@ class CondaBuildConfig(BaseModel): ), ) - error_overlinking: Optional[bool] = Field( + error_overlinking: bool | None = Field( default=False, description=cleandoc( """ @@ -482,7 +478,7 @@ class CondaBuildConfig(BaseModel): class LinterConfig(BaseModel): - skip: Optional[list[Lints]] = Field( + skip: list[Lints] | None = Field( default_factory=list, description="List of lints to skip", ) @@ -491,23 +487,23 @@ class LinterConfig(BaseModel): class CondaForgeDocker(BaseModel): model_config: ConfigDict = ConfigDict(extra="forbid") - executable: Optional[str] = Field( + executable: str | None = Field( description="The executable for Docker", default="docker" ) - fallback_image: Optional[str] = Field( + fallback_image: str | None = Field( description="The fallback image for Docker", default="quay.io/condaforge/linux-anvil-comp7", ) - command: Optional[str] = Field( + command: str | None = Field( description="The command to run in Docker", default="bash" ) ######################################### #### Deprecated Docker configuration #### ######################################### - interactive: Optional[Union[bool, Nullable]] = Field( + interactive: bool | Nullable | None = Field( description="Whether to run Docker in interactive mode", default=None, deprecated=True, @@ -600,7 +596,7 @@ class ConfigModel(BaseModel): # the model dump with the default conda-forge.yml file used for smithy # or to avoid deprecated values been rendered. - conda_build: Optional[CondaBuildConfig] = Field( + conda_build: CondaBuildConfig | None = Field( default_factory=CondaBuildConfig, description=cleandoc( """ @@ -617,7 +613,7 @@ class ConfigModel(BaseModel): ), ) - linter: Optional[LinterConfig] = Field( + linter: LinterConfig | None = Field( default_factory=LinterConfig, description=cleandoc( """ @@ -633,7 +629,7 @@ class ConfigModel(BaseModel): ), ) - conda_build_tool: Optional[conda_build_tools] = Field( + conda_build_tool: conda_build_tools | None = Field( default="conda-build", description=cleandoc( """ @@ -642,9 +638,7 @@ class ConfigModel(BaseModel): ), ) - conda_install_tool: Optional[ - Literal["conda", "mamba", "micromamba", "pixi"] - ] = Field( + conda_install_tool: Literal["conda", "mamba", "micromamba", "pixi"] | None = Field( default="micromamba", description=cleandoc( """ @@ -659,7 +653,7 @@ class ConfigModel(BaseModel): ), ) - conda_forge_output_validation: Optional[bool] = Field( + conda_forge_output_validation: bool | None = Field( default=False, description=cleandoc( """ @@ -670,7 +664,7 @@ class ConfigModel(BaseModel): ), ) - conda_solver: Optional[Union[Literal["libmamba", "classic"], Nullable]] = ( + conda_solver: Literal["libmamba", "classic"] | Nullable | None = ( Field( default="libmamba", description=cleandoc( @@ -681,7 +675,7 @@ class ConfigModel(BaseModel): ) ) - github: Optional[GithubConfig] = Field( + github: GithubConfig | None = Field( default_factory=GithubConfig, description=cleandoc( """ @@ -698,7 +692,7 @@ class ConfigModel(BaseModel): ), ) - bot: Optional[BotConfig] = Field( + bot: BotConfig | None = Field( default_factory=BotConfig, description=cleandoc( """ @@ -747,7 +741,7 @@ class ConfigModel(BaseModel): ), ) - build_platform: Optional[BuildPlatform] = Field( + build_platform: BuildPlatform | None = Field( default_factory=BuildPlatform, description=cleandoc( """ @@ -775,7 +769,7 @@ class ConfigModel(BaseModel): ), ) - channel_priority: Optional[ChannelPriorityConfig] = Field( + channel_priority: ChannelPriorityConfig | None = Field( default="strict", description=cleandoc( """ @@ -787,7 +781,7 @@ class ConfigModel(BaseModel): ), ) - choco: Optional[list[str]] = Field( + choco: list[str] | None = Field( default_factory=list, description=cleandoc( """ @@ -811,7 +805,7 @@ class ConfigModel(BaseModel): ), ) - docker: Optional[CondaForgeDocker] = Field( + docker: CondaForgeDocker | None = Field( default_factory=CondaForgeDocker, description=cleandoc( """ @@ -827,7 +821,7 @@ class ConfigModel(BaseModel): ), ) - idle_timeout_minutes: Optional[Union[int, Nullable]] = Field( + idle_timeout_minutes: int | Nullable | None = Field( default=None, description=cleandoc( """ @@ -841,7 +835,7 @@ class ConfigModel(BaseModel): ), ) - noarch_platforms: Optional[Union[Platforms, list[Platforms]]] = Field( + noarch_platforms: Platforms | list[Platforms] | None = Field( default_factory=lambda: ["linux_64"], description=cleandoc( """ @@ -864,7 +858,7 @@ class ConfigModel(BaseModel): ), ) - os_version: Optional[OSVersion] = Field( + os_version: OSVersion | None = Field( default_factory=OSVersion, description=cleandoc( """ @@ -888,7 +882,7 @@ class ConfigModel(BaseModel): ), ) - provider: Optional[Provider] = Field( + provider: Provider | None = Field( default_factory=Provider, description=cleandoc( """ @@ -955,13 +949,13 @@ class ConfigModel(BaseModel): ), ) - package: Optional[Union[str, Nullable]] = Field( + package: str | Nullable | None = Field( default=None, exclude=True, # Will not be rendered in the model dump description="Default location for a package feedstock directory basename.", ) - recipe_dir: Optional[str] = Field( + recipe_dir: str | None = Field( default="recipe", description=cleandoc( """ @@ -974,7 +968,7 @@ class ConfigModel(BaseModel): ), ) - remote_ci_setup: Optional[Union[str, list[str]]] = Field( + remote_ci_setup: str | list[str] | None = Field( default_factory=lambda: [ "conda-forge-ci-setup=4", "conda-build>=24.1", @@ -992,7 +986,7 @@ class ConfigModel(BaseModel): ), ) - shellcheck: Optional[Union[ShellCheck, Nullable]] = Field( + shellcheck: ShellCheck | Nullable | None = Field( default_factory=lambda: {"enabled": False}, description=cleandoc( """ @@ -1008,7 +1002,7 @@ class ConfigModel(BaseModel): ), ) - skip_render: Optional[list[str]] = Field( + skip_render: list[str] | None = Field( default_factory=list, description=cleandoc( """ @@ -1027,7 +1021,7 @@ class ConfigModel(BaseModel): ), ) - templates: Optional[dict[str, str]] = Field( + templates: dict[str, str] | None = Field( default_factory=dict, description=cleandoc( """ @@ -1037,7 +1031,7 @@ class ConfigModel(BaseModel): ), ) - test_on_native_only: Optional[bool] = Field( + test_on_native_only: bool | None = Field( default=False, deprecated=True, description=cleandoc( @@ -1052,7 +1046,7 @@ class ConfigModel(BaseModel): ), ) - test: Optional[Union[DefaultTestPlatforms, Nullable]] = Field( + test: DefaultTestPlatforms | Nullable | None = Field( default=None, description=cleandoc( """ @@ -1073,7 +1067,7 @@ class ConfigModel(BaseModel): ), ) - upload_on_branch: Optional[Union[str, Nullable]] = Field( + upload_on_branch: str | Nullable | None = Field( default=None, exclude=True, # Will not be rendered in the model dump description=cleandoc( @@ -1091,7 +1085,7 @@ class ConfigModel(BaseModel): ), ) - config_version: Optional[str] = Field( + config_version: str | None = Field( default="2", description=cleandoc( """ @@ -1101,7 +1095,7 @@ class ConfigModel(BaseModel): ), ) - exclusive_config_file: Optional[Union[str, Nullable]] = Field( + exclusive_config_file: str | Nullable | None = Field( default=None, exclude=True, # Will not be rendered in the model dump description=cleandoc( @@ -1112,7 +1106,7 @@ class ConfigModel(BaseModel): ), ) - compiler_stack: Optional[str] = Field( + compiler_stack: str | None = Field( default="comp7", deprecated=True, description=cleandoc( @@ -1127,7 +1121,7 @@ class ConfigModel(BaseModel): ), ) - min_py_ver: Optional[str] = Field( + min_py_ver: str | None = Field( default="27", deprecated=True, description=cleandoc( @@ -1142,7 +1136,7 @@ class ConfigModel(BaseModel): ), ) - max_py_ver: Optional[str] = Field( + max_py_ver: str | None = Field( default="37", deprecated=True, description=cleandoc( @@ -1157,7 +1151,7 @@ class ConfigModel(BaseModel): ), ) - min_r_ver: Optional[str] = Field( + min_r_ver: str | None = Field( default="34", deprecated=True, description=cleandoc( @@ -1172,7 +1166,7 @@ class ConfigModel(BaseModel): ), ) - max_r_ver: Optional[str] = Field( + max_r_ver: str | None = Field( default="34", deprecated=True, description=cleandoc( @@ -1187,7 +1181,7 @@ class ConfigModel(BaseModel): ), ) - private_upload: Optional[bool] = Field( + private_upload: bool | None = Field( default=False, description=cleandoc( """ @@ -1200,7 +1194,7 @@ class ConfigModel(BaseModel): ), ) - secrets: Optional[list[str]] = Field( + secrets: list[str] | None = Field( default_factory=list, description=cleandoc( """ @@ -1210,7 +1204,7 @@ class ConfigModel(BaseModel): ), ) - clone_depth: Optional[Union[int, Nullable]] = Field( + clone_depth: int | Nullable | None = Field( default=None, description=cleandoc( """ @@ -1222,7 +1216,7 @@ class ConfigModel(BaseModel): ################################### #### CI Providers #### ################################### - travis: Optional[dict[str, Any]] = Field( + travis: dict[str, Any] | None = Field( default_factory=dict, description=cleandoc( """ @@ -1232,7 +1226,7 @@ class ConfigModel(BaseModel): ), ) - circle: Optional[dict[str, Any]] = Field( + circle: dict[str, Any] | None = Field( default_factory=dict, description=cleandoc( """ @@ -1242,7 +1236,7 @@ class ConfigModel(BaseModel): ), ) - appveyor: Optional[dict[str, Any]] = Field( + appveyor: dict[str, Any] | None = Field( default_factory=lambda: {"image": "Visual Studio 2017"}, description=cleandoc( """ @@ -1252,7 +1246,7 @@ class ConfigModel(BaseModel): ), ) - azure: Optional[AzureConfig] = Field( + azure: AzureConfig | None = Field( default_factory=AzureConfig, description=cleandoc( """ @@ -1311,7 +1305,7 @@ class ConfigModel(BaseModel): ), ) - drone: Optional[dict[str, str]] = Field( + drone: dict[str, str] | None = Field( default_factory=dict, description=cleandoc( """ @@ -1321,7 +1315,7 @@ class ConfigModel(BaseModel): ), ) - github_actions: Optional[GithubActionsConfig] = Field( + github_actions: GithubActionsConfig | None = Field( default_factory=GithubActionsConfig, description=cleandoc( """ @@ -1331,7 +1325,7 @@ class ConfigModel(BaseModel): ), ) - woodpecker: Optional[dict[str, str]] = Field( + woodpecker: dict[str, str] | None = Field( default_factory=dict, description=cleandoc( """ @@ -1348,7 +1342,7 @@ class ConfigModel(BaseModel): # Deprecated values, only present for validation will not show up in # the model dump, due to exclude=True - build_with_mambabuild: Optional[bool] = Field( + build_with_mambabuild: bool | None = Field( default=True, exclude=True, deprecated=True, @@ -1359,7 +1353,7 @@ class ConfigModel(BaseModel): ), ) - matrix: Optional[dict[str, Any]] = Field( + matrix: dict[str, Any] | None = Field( default_factory=dict, exclude=True, deprecated=True, diff --git a/conda_smithy/utils.py b/conda_smithy/utils.py index fee4a6439..6f9a0525a 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, Union +from typing import Any import jinja2 import jinja2.sandbox @@ -24,10 +24,10 @@ def _get_metadata_from_feedstock_dir( - feedstock_directory: Union[str, os.PathLike], + feedstock_directory: str | os.PathLike, forge_config: dict[str, Any], - conda_forge_pinning_file: Union[str, os.PathLike, None] = None, -) -> Union[MetaData, RattlerBuildMetaData]: + conda_forge_pinning_file: str | os.PathLike | None = None, +) -> MetaData | RattlerBuildMetaData: """ Return either the conda-build metadata or rattler-build metadata from the feedstock directory based on conda_build_tool value from forge_config. @@ -56,7 +56,7 @@ def _get_metadata_from_feedstock_dir( def get_feedstock_name_from_meta( - meta: Union[MetaData, RattlerBuildMetaData], + meta: MetaData | RattlerBuildMetaData, ) -> str: """Get the feedstock name from a parsed meta.yaml or recipe.yaml.""" if "feedstock-name" in meta.meta["extra"]: diff --git a/conda_smithy/variant_algebra.py b/conda_smithy/variant_algebra.py index 0c143d4d5..89c398abf 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, Optional, Union +from typing import Any import conda_build.variants as variants import tlz @@ -25,16 +25,10 @@ def parse_variant( - variant_file_content: str, config: Optional[Config] = None + variant_file_content: str, config: Config | None = None ) -> dict[ str, - Union[ - list[str], - float, - list[list[str]], - dict[str, dict[str, str]], - dict[str, dict[str, list[str]]], - ], + list[str] | float | list[list[str]] | dict[str, dict[str, str]] | dict[str, dict[str, list[str]]], ]: """ Parameters @@ -59,8 +53,8 @@ def parse_variant( def _version_order( - v: Union[str, float], ordering: Optional[list[str]] = None -) -> Union[int, VersionOrder, float]: + v: str | float, ordering: list[str] | None = None +) -> int | VersionOrder | float: if ordering is not None: return ordering.index(v) else: @@ -74,10 +68,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: list[str] | list[float], + v_right: list[str] | list[float], + ordering: list[str] | None = None, +) -> list[str] | list[float]: """Version summation adder. This takes the higher version of the two things. diff --git a/tests/test_lint_recipe.py b/tests/test_lint_recipe.py index c78a2ff6b..6f3d19966 100644 --- a/tests/test_lint_recipe.py +++ b/tests/test_lint_recipe.py @@ -20,6 +20,7 @@ try: import conda_recipe_manager.parser.recipe_parser + has_conda_recipe_manager = True except ImportError: has_conda_recipe_manager = False From 627b73488816a1232d273fcb1be51b4d4754c73d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 16 Feb 2025 23:12:02 +0000 Subject: [PATCH 13/13] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- conda_smithy/schema.py | 24 ++++++++++++++---------- conda_smithy/variant_algebra.py | 6 +++++- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/conda_smithy/schema.py b/conda_smithy/schema.py index f4057f2ed..1ce2d19db 100644 --- a/conda_smithy/schema.py +++ b/conda_smithy/schema.py @@ -156,7 +156,9 @@ class AzureConfig(BaseModel): description="Force building all supported providers", ) - free_disk_space: bool | Nullable | list[Literal["apt", "cache", "docker"]] | None = Field( + free_disk_space: ( + bool | Nullable | list[Literal["apt", "cache", "docker"]] | None + ) = Field( default=False, description=cleandoc( """ @@ -302,7 +304,9 @@ class GithubActionsConfig(BaseModel): default=True, ) - free_disk_space: bool | Nullable | list[Literal["apt", "cache", "docker"]] | None = Field( + free_disk_space: ( + bool | Nullable | list[Literal["apt", "cache", "docker"]] | None + ) = Field( default=False, description=cleandoc( """ @@ -638,7 +642,9 @@ class ConfigModel(BaseModel): ), ) - conda_install_tool: Literal["conda", "mamba", "micromamba", "pixi"] | None = Field( + conda_install_tool: ( + Literal["conda", "mamba", "micromamba", "pixi"] | None + ) = Field( default="micromamba", description=cleandoc( """ @@ -664,15 +670,13 @@ class ConfigModel(BaseModel): ), ) - conda_solver: Literal["libmamba", "classic"] | Nullable | None = ( - Field( - default="libmamba", - description=cleandoc( - """ + conda_solver: Literal["libmamba", "classic"] | Nullable | None = Field( + default="libmamba", + description=cleandoc( + """ Choose which `conda` solver plugin to use for feedstock builds. """ - ), - ) + ), ) github: GithubConfig | None = Field( diff --git a/conda_smithy/variant_algebra.py b/conda_smithy/variant_algebra.py index 89c398abf..fc12c88cf 100644 --- a/conda_smithy/variant_algebra.py +++ b/conda_smithy/variant_algebra.py @@ -28,7 +28,11 @@ def parse_variant( variant_file_content: str, config: Config | None = None ) -> dict[ str, - list[str] | float | list[list[str]] | dict[str, dict[str, str]] | dict[str, dict[str, list[str]]], + list[str] + | float + | list[list[str]] + | dict[str, dict[str, str]] + | dict[str, dict[str, list[str]]], ]: """ Parameters