diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 4ce430044..9c2413028 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -19,10 +19,10 @@ jobs: with: fetch-depth: 0 - - name: Set up Python 3.12 + - name: Set up Python 3.11 uses: actions/setup-python@v5 with: - python-version: 3.12 + python-version: 3.11 - name: Install dependencies run: | diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 43d14ae39..70835d175 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,7 +11,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ['3.10', '3.11', '3.12', '3.13'] + python-version: ['3.8', '3.10', '3.11', '3.12'] runs-on: ubuntu-latest @@ -32,7 +32,7 @@ jobs: - name: Setup Komodo run: | - pip install -U pip + pip install -U pip wheel setuptools pip install ".[dev]" - name: Unit tests @@ -48,13 +48,13 @@ jobs: run: | komodo-transpiler transpile \ --matrix-file="ci/${{env.RELEASE_NAME}}.yml" \ - --output ci --matrix-coordinates "{rhel: ['8'], py: ['${{matrix.python-version}}']}" + --output ci --matrix-coordinates "{rhel: ['7'], py: ['${{matrix.python-version}}']}" - name: Full integration test run: | py_version_number=$(echo "${{ matrix.python-version }}" | sed 's/\.//g') kmd \ - ci/${{env.RELEASE_NAME}}-py$py_version_number-rhel8.yml \ + ci/${{env.RELEASE_NAME}}-py$py_version_number-rhel7.yml \ ci/${{env.REPOSITORY}} \ --workspace ${{ runner.temp }}/kmd-ws \ --prefix ${{ runner.temp }}/prefix \ diff --git a/ci/release-matrix.yml b/ci/release-matrix.yml index 17657bda9..c80e6a745 100644 --- a/ci/release-matrix.yml +++ b/ci/release-matrix.yml @@ -1,8 +1,9 @@ numpy: + py38: 1.23.5 + py39: 1.23.5 py310: 1.23.5 py311: 1.23.5 py312: 1.26.4 - py313: 2.2.0 python: 3-builtin -setuptools: 75.6.0 -wheel: 0.45.1 +setuptools: 69.0.3 +wheel: 0.42.0 diff --git a/ci/repository.yml b/ci/repository.yml index ec1496265..4385d3c55 100644 --- a/ci/repository.yml +++ b/ci/repository.yml @@ -1,8 +1,4 @@ numpy: - 2.2.0: - source: pypi - make: pip - maintainer: ci 1.26.4: source: pypi make: pip @@ -20,13 +16,13 @@ python: makeopts: --virtualenv-interpreter python3 setuptools: - 75.6.0: + 69.0.3: source: pypi make: pip maintainer: ci wheel: - 0.45.1: + 0.42.0: source: pypi make: pip maintainer: ci diff --git a/komodo/build.py b/komodo/build.py index 20e18fefe..1b9af1b34 100644 --- a/komodo/build.py +++ b/komodo/build.py @@ -5,6 +5,7 @@ import re import stat from pathlib import Path +from typing import Dict import requests @@ -183,7 +184,7 @@ def pypaths(prefix, version): def make( - pkgs: dict[str, str], + pkgs: Dict[str, str], repo, data, prefix, @@ -227,7 +228,7 @@ def make( def resolve(input_str): return input_str.replace("$(prefix)", prefix) - for package_name, path in zip(pkgorder, pkgpaths, strict=False): + for package_name, path in zip(pkgorder, pkgpaths): ver = pkgs[package_name] current = repo[package_name][ver] make = current["make"] diff --git a/komodo/check_unused_package.py b/komodo/check_unused_package.py index 077cee04d..e01c34762 100644 --- a/komodo/check_unused_package.py +++ b/komodo/check_unused_package.py @@ -2,6 +2,7 @@ import argparse import os import sys +from typing import Dict import yaml @@ -15,7 +16,7 @@ def check_for_unused_package( release_file: ReleaseFile, package_status_file: str, repository: RepositoryFile, - builtin_python_versions: dict[str, str], + builtin_python_versions: Dict[str, str], ): package_status = load_yaml(package_status_file) public_and_plugin_packages = [ diff --git a/komodo/check_up_to_date_pypi.py b/komodo/check_up_to_date_pypi.py index 76f328a05..db22d7660 100644 --- a/komodo/check_up_to_date_pypi.py +++ b/komodo/check_up_to_date_pypi.py @@ -3,6 +3,7 @@ import pathlib import re import sys +from typing import Dict, List import requests import ruamel.yaml @@ -56,7 +57,7 @@ def get_python_requirement(sources: list): return "" -def is_platform_compatible(build_info: list[dict], platform: str) -> bool: +def is_platform_compatible(build_info: List[Dict], platform: str) -> bool: if platform == "darwin": platform = "macos" if platform == "linux2": @@ -72,7 +73,7 @@ def is_platform_compatible(build_info: list[dict], platform: str) -> bool: def compatible_versions( releases: dict, python_version, platform: str -) -> list[get_version.Version]: +) -> List[get_version.Version]: compatible_versions = [] for version_str, build_info in releases.items(): try: diff --git a/komodo/cleanup.py b/komodo/cleanup.py index d2cc080d8..8839cf193 100755 --- a/komodo/cleanup.py +++ b/komodo/cleanup.py @@ -1,11 +1,12 @@ #!/usr/bin/env python import sys +from typing import List from komodo.yaml_file_types import ReleaseFile, RepositoryFile -def cleanup(repository_file_path: str, release_files_path: list[str]): +def cleanup(repository_file_path: str, release_files_path: List[str]): repository_file = RepositoryFile()(repository_file_path) repository = repository_file.content diff --git a/komodo/cli.py b/komodo/cli.py index 2291e616b..e47e836bf 100755 --- a/komodo/cli.py +++ b/komodo/cli.py @@ -4,9 +4,8 @@ import os import sys import uuid -from collections.abc import Callable, Mapping, Sequence from pathlib import Path -from typing import Any +from typing import Any, Callable, Dict, List, Mapping, Optional, Sequence, Tuple, Union import jinja2 from ruamel.yaml import YAML @@ -41,7 +40,7 @@ class KomodoNamespace(argparse.Namespace): cmake: str pip: str workspace: str - extra_data_dirs: list[str] + extra_data_dirs: List[str] postinst: str @@ -89,7 +88,7 @@ def create_enable_scripts(komodo_prefix: str, komodo_release: str) -> None: def _print_timing( - timing_element: tuple[str, datetime.timedelta], + timing_element: Tuple[str, datetime.timedelta], adjust: bool = False, ) -> None: if adjust: @@ -126,10 +125,10 @@ def is_download_only(args: KomodoNamespace) -> bool: @profile_time("Fetching all packages") def download_packages( release_file_content: Mapping[str, str], - repository_file_content: Mapping[str, Mapping[str, str | Sequence[str]]], + repository_file_content: Mapping[str, Mapping[str, Union[str, Sequence[str]]]], download_destination: str, pip_executable: str = "pip", -) -> dict[str, str]: +) -> Dict[str, str]: """Downloads all PyPI packages to destination. Tries to download other packages to destination too. Git packages are collected, and a dict of all git hashes is returned. @@ -206,14 +205,14 @@ def generate_release_root(release_path: Path) -> Path: def generate_release_manifest( release_name: Path, release_file_content: Mapping[str, str], - repository_file_content: Mapping[str, Mapping[str, str | Sequence[str]]], - git_hashes: Mapping[str, str] | None = None, + repository_file_content: Mapping[str, Mapping[str, Union[str, Sequence[str]]]], + git_hashes: Optional[Mapping[str, str]] = None, ) -> None: releasedoc = Path(release_name) / Path(release_name) with open(releasedoc, mode="w", encoding="utf-8") as filehandle: - release: dict[str, dict[str, str]] = {} + release: Dict[str, Dict[str, str]] = {} for package, version in release_file_content.items(): - entry: dict[str, str] = repository_file_content[package][version] + entry: Dict[str, str] = repository_file_content[package][version] maintainer = repository_file_content[package][version]["maintainer"] if entry.get("fetch") == "git": version = git_hashes[package] @@ -251,7 +250,7 @@ def delete_old_previously_moved_releases(prefix_path: Path, release_name: Path) ) -def apply_fallback_tmpdir_for_pip_if_set(tmp_dir: str | None = None): +def apply_fallback_tmpdir_for_pip_if_set(tmp_dir: Optional[str] = None): """Allows e.g. pip to use this folder as a destination for "pip download", instead of in some cases falling back to /tmp, which is undesired when building on nfs. @@ -266,7 +265,7 @@ def apply_fallback_tmpdir_for_pip_if_set(tmp_dir: str | None = None): @profile_time("pip install to final destination") def install_previously_downloaded_pip_packages( release_file_content: Mapping[str, str], - repository_file_content: Mapping[str, Mapping[str, str | Sequence[str]]], + repository_file_content: Mapping[str, Mapping[str, Union[str, Sequence[str]]]], downloads_directory: str, pip_executable: str, release_root: Path, @@ -296,7 +295,7 @@ def install_previously_downloaded_pip_packages( def run_post_installation_scripts_if_set( - postinst: str | None, release_path: Path + postinst: Optional[str], release_path: Path ) -> None: if postinst: timing_func = profile_time("Running post-install scripts") @@ -329,7 +328,7 @@ def compile_python_bytecode_files_and_fix_permissions( compile_python_bytecode_files(release_root) -timings: list[tuple[str, datetime.timedelta]] = [] +timings: List[Tuple[str, datetime.timedelta]] = [] def _main(args: KomodoNamespace) -> None: @@ -417,7 +416,7 @@ def cli_main(): _main(args) -def parse_args(args: list[str]) -> KomodoNamespace: +def parse_args(args: List[str]) -> KomodoNamespace: """Parse the arguments from the command line into an `argparse.Namespace`. Having a separated function makes it easier to test the CLI. diff --git a/komodo/deployed.py b/komodo/deployed.py index 82997949a..73ae92af9 100644 --- a/komodo/deployed.py +++ b/komodo/deployed.py @@ -1,6 +1,7 @@ import argparse import json import os +from typing import List, Optional from komodo.matrix import get_matrix_base from komodo.yaml_file_types import ReleaseDir @@ -34,13 +35,13 @@ def _fetch_non_deployed_releases(install_root, release_folder): def fetch_non_deployed( install_root: str, releases_folder: str, - limit: int | None = None, -) -> list[str]: + limit: Optional[int] = None, +) -> List[str]: non_deployed = _fetch_non_deployed_releases(install_root, releases_folder) return non_deployed[:limit] -def output_formatter(release_list: list[str], do_json: bool = False) -> str: +def output_formatter(release_list: List[str], do_json: bool = False) -> str: if do_json: return json.dumps(release_list, separators=(",", ":")) return "\n".join(release_list) diff --git a/komodo/insert_proposals.py b/komodo/insert_proposals.py index a66c43752..500f1c96e 100644 --- a/komodo/insert_proposals.py +++ b/komodo/insert_proposals.py @@ -3,8 +3,8 @@ import difflib import os from base64 import b64decode -from collections.abc import Mapping, MutableSet from datetime import datetime +from typing import Dict, Mapping, MutableSet, Optional, Union import github from github import Github, UnknownObjectException @@ -21,8 +21,8 @@ def recursive_update( - to_be_upgraded: Mapping[str, str | Mapping[str, str]], - upgrades: Mapping[str, str | Mapping[str, str]] | None, + to_be_upgraded: Mapping[str, Union[str, Mapping[str, str]]], + upgrades: Optional[Mapping[str, Union[str, Mapping[str, str]]]], ) -> None: """Updates release in place with upgrades/additions of packages from upgrades. @@ -115,7 +115,7 @@ def get_upgrade_key(target: str) -> str: def validate_upgrades( - upgrade_section: dict[str, str], repofile: RepositoryFile + upgrade_section: Dict[str, str], repofile: RepositoryFile ) -> None: errors = set() for package_name, package_version in upgrade_section.items(): @@ -128,7 +128,7 @@ def validate_upgrades( def recursive_validate_package_entries( package_name, - package_version_or_matrix: str | Mapping | None, + package_version_or_matrix: Union[str, Mapping, None], repository_file: RepositoryFile, errors: MutableSet, ) -> None: @@ -151,7 +151,7 @@ def recursive_validate_package_entries( def generate_contents_of_new_release_matrix( base_release_matrix_content: Mapping, repofile: RepositoryFile, - upgrade: dict | None, + upgrade: Optional[Dict], ) -> str: if upgrade: validate_upgrades(upgrade, repofile) @@ -207,7 +207,7 @@ def create_pr_with_changes( tmp_target: str, tmp_ref: GitRef, pr_msg: str, - rhel8: bool | None = False, + rhel8: Optional[bool] = False, ): commit_title = ( f"Add release {target} (+rhel8)" if rhel8 else f"Add release {target}" @@ -258,7 +258,7 @@ def insert_proposals( git_ref: str, jobname: str, joburl: str, - rhel8: bool | None = False, + rhel8: Optional[bool] = False, ) -> None: tmp_target = target + ".tmp" @@ -274,7 +274,7 @@ def insert_proposals( base_file = f"releases/matrices/{base}.yml" release_file_yaml_string = load_yaml_from_repo(base_file, repo, git_ref) release_matrix_file = ReleaseMatrixFile.from_yaml_string(release_file_yaml_string) - upgrade: dict[str, str] = proposal_file.content.get(upgrade_key) + upgrade: Dict[str, str] = proposal_file.content.get(upgrade_key) repofile_yaml_string = load_yaml_from_repo("repository.yml", repo, git_ref) repofile = RepositoryFile().from_yaml_string(repofile_yaml_string) diff --git a/komodo/lint_maturity.py b/komodo/lint_maturity.py index e5ed25bb6..ec1779a23 100644 --- a/komodo/lint_maturity.py +++ b/komodo/lint_maturity.py @@ -3,6 +3,7 @@ import argparse import os import warnings +from typing import List import yaml from packaging.version import InvalidVersion, Version @@ -125,7 +126,7 @@ def get_release_version(release_basename, tag_exceptions_release): return release_version -def run(files_to_lint: list[str], tag_exceptions): +def run(files_to_lint: List[str], tag_exceptions): system_exit_msg = "" system_warning_msg = "" @@ -180,7 +181,7 @@ def read_yaml_file_and_convert_to_release_file(release_file_path: str) -> Releas return ReleaseFile().from_yaml_string(value=release_file_yaml_string) -def get_files_to_lint(release_folder: str, release_file: str) -> list[str]: +def get_files_to_lint(release_folder: str, release_file: str) -> List[str]: if release_folder is None: files_to_lint = [release_file] else: diff --git a/komodo/lint_symlink_config.py b/komodo/lint_symlink_config.py index fb9cd2021..aea691e7e 100644 --- a/komodo/lint_symlink_config.py +++ b/komodo/lint_symlink_config.py @@ -3,8 +3,8 @@ import os import re import sys -from collections.abc import Mapping from pathlib import Path +from typing import Mapping, Union from komodo.symlink.sanity_check import assert_root_nodes @@ -21,7 +21,7 @@ def parse_args(): return parser.parse_args() -def lint_symlink_config(link_dict: Mapping[str, Mapping | str]): +def lint_symlink_config(link_dict: Mapping[str, Union[Mapping, str]]): assert_root_nodes(link_dict) links = link_dict["links"] diff --git a/komodo/maintainer.py b/komodo/maintainer.py index 66d08c961..d2e9ff84b 100755 --- a/komodo/maintainer.py +++ b/komodo/maintainer.py @@ -6,10 +6,9 @@ def maintainers(pkgfile, repofile): - with ( - open(pkgfile, encoding="utf-8") as package_file_stream, - open(repofile, encoding="utf-8") as repository_file_stream, - ): + with open(pkgfile, encoding="utf-8") as package_file_stream, open( + repofile, encoding="utf-8" + ) as repository_file_stream: yml = YAML() pkgs, repo = yml.load(package_file_stream), yml.load(repository_file_stream) diff --git a/komodo/matrix.py b/komodo/matrix.py index c8d89621f..a1c3bee9f 100644 --- a/komodo/matrix.py +++ b/komodo/matrix.py @@ -6,13 +6,13 @@ import itertools import re -from collections.abc import Iterator, Sequence +from typing import Iterator, Sequence, Tuple def get_matrix( rhel_versions: Sequence[str], py_versions: Sequence[str], -) -> Iterator[tuple[str, str]]: +) -> Iterator[Tuple[str, str]]: """Return tuples of rhel version and Python version, representing the current release matrix. """ diff --git a/komodo/pypi_dependencies.py b/komodo/pypi_dependencies.py index eb13b7b9d..501584b70 100644 --- a/komodo/pypi_dependencies.py +++ b/komodo/pypi_dependencies.py @@ -3,6 +3,7 @@ import subprocess import sys from tempfile import TemporaryDirectory +from typing import Dict, List, Set, Tuple import pkginfo import yaml @@ -39,8 +40,8 @@ def format_full_version(info) -> str: class PypiDependencies: def __init__( self, - pypi_dependencies: dict[str, str], - to_install: dict[str, str], + pypi_dependencies: Dict[str, str], + to_install: Dict[str, str], python_version: str, cachefile: str = "./pypi_dependencies.yml", ) -> None: @@ -48,7 +49,7 @@ def __init__( environment["python_full_version"] = python_version environment["python_version"] = ".".join(python_version.split(".")[0:2]) self._satisfied_requirements = set() - self._failed_requirements: dict[Requirement, str] = {} + self._failed_requirements: Dict[Requirement, str] = {} self._used_packages = set() self._install_names = {canonicalize_name(name): name for name in to_install} @@ -110,7 +111,7 @@ def used_packages(self, packages=None): def add_user_specified( self, package_name: str, - depends: list[str], + depends: List[str], ) -> None: canonical = canonicalize_name(package_name) # It is necessary to set the version to the installed @@ -134,7 +135,7 @@ def dump_cache(self): def _get_requirements( self, package_name: str, package_version: str - ) -> list[Requirement]: + ) -> List[Requirement]: """ >>> from packaging.requirements import Requirement >>> PypiDependencies({}, {}, python_version="3.8.11")._get_requirements( @@ -218,8 +219,8 @@ def _is_necessary(self, requirement, extras): def _satisfied( self, - requirements: list[Requirement], - ) -> tuple[bool, list[tuple[list[Requirement], set[str]]]]: + requirements: List[Requirement], + ) -> Tuple[bool, List[Tuple[List[Requirement], Set[str]]]]: installed = self._to_install transient_requirements = [] for requirement in requirements: diff --git a/komodo/release_transpiler.py b/komodo/release_transpiler.py index eaba06244..dcfd8affa 100755 --- a/komodo/release_transpiler.py +++ b/komodo/release_transpiler.py @@ -2,7 +2,7 @@ import argparse import os -from collections.abc import Sequence +from typing import Dict, Sequence, Union import yaml @@ -56,7 +56,7 @@ def _pick_package_versions_for_release( def _check_version_exists_for_coordinates( - pkg_versions: dict | str, + pkg_versions: Union[dict, str], rhel_coordinate: str, py_coordinate: str, ) -> None: @@ -164,7 +164,7 @@ def transpile(args): transpile_releases(args.matrix_file, args.output_folder, args.matrix_coordinates) -def transpile_for_pip(args: dict): +def transpile_for_pip(args: Dict): transpile_releases_for_pip( args.matrix_file, args.output_folder, diff --git a/komodo/show_version.py b/komodo/show_version.py index dc1a10ee9..100eba833 100644 --- a/komodo/show_version.py +++ b/komodo/show_version.py @@ -6,6 +6,7 @@ import sys import textwrap from pathlib import Path +from typing import Dict, List, Optional, Union from ruamel.yaml import YAML @@ -43,7 +44,7 @@ def get_release() -> str: sys.exit(message) -def read_config(fname: str | Path) -> dict: +def read_config(fname: Union[str, Path]) -> dict: """Read an INI file (aka config file) that does not have sections. Sections are part of the INI file format specification and cannot be read by a `configparser.ConfigParser` without them. This function creates a @@ -113,7 +114,7 @@ def get_komodo_path(release: str) -> Path: return Path(path) -def get_version(pkg: str, manifest: dict | None = None) -> str: +def get_version(pkg: str, manifest: Optional[Dict] = None) -> str: """Get the release number (or git commit hash) for a package in a komodo release file. If no file is specified, the current release is used. If no environment is active, the path to the release @@ -153,7 +154,7 @@ def get_version(pkg: str, manifest: dict | None = None) -> str: return package.get("version") -def parse_args(args: list[str]) -> argparse.Namespace: +def parse_args(args: List[str]) -> argparse.Namespace: """Parse the arguments from the command line into an `argparse.Namespace`. Having a separated function makes it easier to test the CLI. diff --git a/komodo/snyk_reporting.py b/komodo/snyk_reporting.py index 462315b38..8ed3b6b00 100644 --- a/komodo/snyk_reporting.py +++ b/komodo/snyk_reporting.py @@ -2,7 +2,7 @@ import html import os import sys -from typing import Any +from typing import Any, Dict, List, Optional from snyk import SnykClient from snyk.models import Organization, Vulnerability @@ -41,7 +41,7 @@ def main() -> None: print(_format_console(vulnerabilities=vulnerabilities)) -def parse_args(args: list[str]) -> argparse.Namespace: +def parse_args(args: List[str]) -> argparse.Namespace: parser = argparse.ArgumentParser( description="Test a release for security and license issues.", formatter_class=argparse.ArgumentDefaultsHelpFormatter, @@ -81,9 +81,9 @@ def parse_args(args: list[str]) -> argparse.Namespace: def filter_pip_packages( - packages: dict[str, str], - repository: dict[str, Any], -) -> dict[str, str]: + packages: Dict[str, str], + repository: Dict[str, Any], +) -> Dict[str, str]: return { package_name: version for (package_name, version) in packages.items() @@ -91,13 +91,13 @@ def filter_pip_packages( } -def create_snyk_search_string(packages: dict[str, str]) -> str: +def create_snyk_search_string(packages: Dict[str, str]) -> str: return "\n".join( [f"{package_name}=={version}" for package_name, version in packages.items()], ) -def get_unique_issues(issues: list[Vulnerability]) -> list[Vulnerability]: +def get_unique_issues(issues: List[Vulnerability]) -> List[Vulnerability]: ids = set() result = [] for issue in issues: @@ -109,7 +109,7 @@ def get_unique_issues(issues: list[Vulnerability]) -> list[Vulnerability]: def filter_vulnerability_issues( - snyk_issues: list[Vulnerability], release_packages: dict[str, str] + snyk_issues: List[Vulnerability], release_packages: Dict[str, str] ): filtered_vulnerability_issues = [] for snyk_issue in snyk_issues: @@ -121,10 +121,10 @@ def filter_vulnerability_issues( def find_vulnerabilities( - releases: dict[str, dict[str, str]], - repository: dict[str, Any], + releases: Dict[str, Dict[str, str]], + repository: Dict[str, Any], org: Organization, -) -> dict[str, list[Vulnerability]]: +) -> Dict[str, List[Vulnerability]]: result = {} for release_name, packages in releases.items(): @@ -139,7 +139,7 @@ def find_vulnerabilities( return result -def _format_console(vulnerabilities: dict[str, list[Vulnerability]]) -> str: +def _format_console(vulnerabilities: Dict[str, List[Vulnerability]]) -> str: result = "Security Vulnerabilities:\n" for release, vulns in vulnerabilities.items(): result += release + "\n" @@ -160,7 +160,7 @@ def _format_console(vulnerabilities: dict[str, list[Vulnerability]]) -> str: return result -def _format_github(vulnerabilities: dict[str, list[Vulnerability]]) -> str: +def _format_github(vulnerabilities: Dict[str, List[Vulnerability]]) -> str: result = "Snyk Security Report\n==\n\n" for release, vulns in vulnerabilities.items(): result += f"{release}\n--\n" @@ -191,11 +191,11 @@ def _get_org(api_token: str, org_id: str) -> Organization: def snyk_main( - releases: dict[str, dict[str, str]], - repository: dict[str, Any], - api_token: str | None, + releases: Dict[str, Dict[str, str]], + repository: Dict[str, Any], + api_token: Optional[str], org_id: str, -) -> dict[str, list[Vulnerability]]: +) -> Dict[str, List[Vulnerability]]: if api_token is None: msg = "No api token given, please set the environment variable SNYK_API_TOKEN." raise ValueError( diff --git a/komodo/switch.py b/komodo/switch.py index 9345e3521..e1c282620 100644 --- a/komodo/switch.py +++ b/komodo/switch.py @@ -43,10 +43,11 @@ def create_activator_switch(data, prefix, release): os.makedirs(release_path) - with ( - open(os.path.join(release_path, "enable"), "w", encoding="utf-8") as activator, - open(data.get("activator_switch.tmpl"), encoding="utf-8") as activator_tmpl, - ): + with open( + os.path.join(release_path, "enable"), "w", encoding="utf-8" + ) as activator, open( + data.get("activator_switch.tmpl"), encoding="utf-8" + ) as activator_tmpl: activator.write( Template(activator_tmpl.read(), keep_trailing_newline=True).render( py_version=py_version, @@ -56,12 +57,11 @@ def create_activator_switch(data, prefix, release): ), ) - with ( - open( - os.path.join(release_path, "enable.csh"), "w", encoding="utf-8" - ) as activator, - open(data.get("activator_switch.csh.tmpl"), encoding="utf-8") as activator_tmpl, - ): + with open( + os.path.join(release_path, "enable.csh"), "w", encoding="utf-8" + ) as activator, open( + data.get("activator_switch.csh.tmpl"), encoding="utf-8" + ) as activator_tmpl: activator.write( Template(activator_tmpl.read(), keep_trailing_newline=True).render( py_version=py_version, diff --git a/komodo/symlink/create_links.py b/komodo/symlink/create_links.py index 3fb37942c..67766479d 100644 --- a/komodo/symlink/create_links.py +++ b/komodo/symlink/create_links.py @@ -3,6 +3,7 @@ import os import sys from contextlib import contextmanager +from typing import List from .sanity_check import verify_integrity @@ -17,7 +18,7 @@ def working_dir(path): os.chdir(prev_dir) -def get_implicitly_moved_symlinks(key: str, link_dict: dict) -> list[str]: +def get_implicitly_moved_symlinks(key: str, link_dict: dict) -> List[str]: sources = [src for src, dst in link_dict.items() if dst == key] implicitly_moved_symlinks = [] for source in sources: diff --git a/komodo/symlink/suggester/cli.py b/komodo/symlink/suggester/cli.py index 76d6dc4a2..698c18e50 100755 --- a/komodo/symlink/suggester/cli.py +++ b/komodo/symlink/suggester/cli.py @@ -5,6 +5,7 @@ import sys from base64 import b64decode from datetime import datetime +from typing import Optional from github import Github from github.GithubException import UnknownObjectException @@ -60,7 +61,7 @@ def _parse_args(): return parser.parse_args() -def _get_repo(token: str | None, fork: str, repo: str) -> Repository: +def _get_repo(token: Optional[str], fork: str, repo: str) -> Repository: client = Github(token) try: return client.get_repo(f"{fork}/{repo}") @@ -73,7 +74,7 @@ def suggest_symlink_configuration( args: argparse.Namespace, repo: Repository, dry_run: bool = False, -) -> Repository | None: +) -> Optional[Repository]: """Returns a pull request if the symlink configuration could be updated, or None if no update was possible. """ diff --git a/komodo/symlink/suggester/configuration.py b/komodo/symlink/suggester/configuration.py index 4152fb26f..153256e87 100644 --- a/komodo/symlink/suggester/configuration.py +++ b/komodo/symlink/suggester/configuration.py @@ -1,4 +1,5 @@ import json +from typing import List, Tuple from komodo.symlink.sanity_check import suggest_missing_roots from komodo.symlink.suggester.release import Release @@ -19,7 +20,7 @@ def _get_concrete_release(self, link): release = Release(self.links[repr(release)]) return release - def update(self, release, mode, python_versions: list[str]): + def update(self, release, mode, python_versions: List[str]): for python_version in python_versions: python_version = python_version.strip() release.set_python_version(python_version) @@ -65,8 +66,8 @@ def from_json(conf_json_str): def update( - symlink_configuration, release_id, mode, python_versions: list[str] = None -) -> tuple[str, bool]: + symlink_configuration, release_id, mode, python_versions: List[str] = None +) -> Tuple[str, bool]: """Return a tuple of a string representing the new symlink config json, and whether an update was made. This function assumes the release_id is in the yyyy.mm.[part ...] format and will look for python suffix (-py38, -py311) diff --git a/komodo/yaml_file_types.py b/komodo/yaml_file_types.py index ee2e13b3e..68746e71a 100644 --- a/komodo/yaml_file_types.py +++ b/komodo/yaml_file_types.py @@ -1,8 +1,8 @@ import argparse import os from collections import namedtuple -from collections.abc import Mapping, MutableSet, Sequence from pathlib import Path +from typing import Dict, List, Mapping, MutableSet, Sequence, Union from ruamel.yaml import YAML from ruamel.yaml.constructor import DuplicateKeyError @@ -137,7 +137,7 @@ def validate_release_matrix_file(release_matrix_file_content: Mapping) -> None: class ReleaseDir: - def __call__(self, value: str) -> dict[str, YamlFile]: + def __call__(self, value: str) -> Dict[str, YamlFile]: if not os.path.isdir(value): raise NotADirectoryError(value) result = {} @@ -155,7 +155,7 @@ def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.content: dict = None - def __call__(self, value: str) -> dict[str, dict[str, str]]: + def __call__(self, value: str) -> Dict[str, Dict[str, str]]: yml = super().__call__(value) self.validate_manifest_file(yml) return yml @@ -272,7 +272,7 @@ def validate_repository_file(self) -> None: handle_validation_errors(errors, message) - def validate_versions(self, package_name: str, versions: dict) -> list[str]: + def validate_versions(self, package_name: str, versions: dict) -> List[str]: """Validates versions-dictionary of a package and returns a list of error messages.""" errors = [] for version, version_metadata in versions.items(): @@ -308,7 +308,7 @@ def validate_package_properties( package_version: str, package_property: str, package_property_value: str, - ) -> list[str]: + ) -> List[str]: """Validates package properties of the specified package and returns a list of error messages. """ @@ -355,7 +355,7 @@ def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.content: dict = None - def __call__(self, value: str) -> dict[str, dict[str, str]]: + def __call__(self, value: str) -> Dict[str, Dict[str, str]]: yml = super().__call__(value) self.validate_upgrade_proposals_file(yml) self.content: dict = yml @@ -484,7 +484,7 @@ def validate_package_name(package_name: str) -> None: @staticmethod def validate_package_version( - package_name: str | None, + package_name: Union[str, None], package_version: str, is_matrix_file: bool = False, ) -> None: @@ -512,7 +512,7 @@ def validate_package_entry_with_errors( package_name: str, package_version: str, is_matrix_file: bool = False, - ) -> list[str]: + ) -> List[str]: """Validates package name and version, and returns a list of error messages.""" errors = [] try: @@ -541,7 +541,7 @@ def validate_package_importance(package_name: str, package_importance: str) -> N def validate_package_importance_with_errors( package_name, package_importance: str, - ) -> list[str]: + ) -> List[str]: """Validates package importance of a package and returns a list of error messages.""" errors = [] try: @@ -582,7 +582,7 @@ def validate_package_maturity(package_name: str, package_maturity: str) -> None: def validate_package_maturity_with_errors( package_name: str, package_maturity: str, - ) -> list[str]: + ) -> List[str]: """Validates package maturity of a package and returns a list of error messages.""" errors = [] try: @@ -614,7 +614,7 @@ def validate_package_make_with_errors( package_name: str, package_version: str, package_make: str, - ) -> list[str]: + ) -> List[str]: """Validates make of a package and returns a list of error messages.""" errors = [] try: @@ -641,7 +641,7 @@ def validate_package_maintainer_with_errors( package_name: str, package_version: str, package_maintainer: str, - ) -> list[str]: + ) -> List[str]: """Validates maintainer of a package and returns a list of error messages.""" errors = [] try: @@ -660,7 +660,7 @@ def validate_package_source( package_version: str, package_source: str, ) -> None: - if isinstance(package_source, (str | type(None))): + if isinstance(package_source, (str, type(None))): return msg = f"Package '{package_name}' version {package_version} has invalid source type ({package_source})" raise TypeError( @@ -672,7 +672,7 @@ def validate_package_source_with_errors( package_name: str, package_version: str, package_source: str, - ) -> list[str]: + ) -> List[str]: """Validates source of a package and returns a list of error messages.""" errors = [] try: @@ -718,7 +718,7 @@ def load_repository_file(repository_file_string): def _recursive_validate_version_matrix( - version_or_matrix: dict | str, package_name: str, errors: MutableSet + version_or_matrix: Union[dict, str], package_name: str, errors: MutableSet ) -> None: if isinstance(version_or_matrix, Mapping): for nested_version_or_matrix in version_or_matrix.values(): diff --git a/pyproject.toml b/pyproject.toml index 172e212a2..849fccebf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,17 +7,18 @@ name = "komodo" authors = [{ name="Equinor ASA", email="fg_sib-scout@equinor.com" },] description = "Komodo is a software distribution system." dynamic = ["version"] -requires-python = ">=3.10" +requires-python = ">=3.8" license = {file = "LICENSE"} readme = "README.md" classifiers = [ "Intended Audience :: Science/Research", "Development Status :: 4 - Beta", "Natural Language :: English", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", "License :: OSI Approved :: License :: OSI Approved :: GNU Affero General Public License v3", "Operating System :: OS Independent", ] diff --git a/tests/test_cleanup.py b/tests/test_cleanup.py index 33bdaa3d9..3dd2e3de6 100644 --- a/tests/test_cleanup.py +++ b/tests/test_cleanup.py @@ -1,6 +1,7 @@ import os import sys from contextlib import contextmanager +from typing import List import pytest @@ -71,8 +72,8 @@ def _write_file(file_path: str, file_content: str) -> str: def _create_tmp_test_files( repository_file_content: str, - release_files_contents: list[str], -) -> (str, list[str]): + release_files_contents: List[str], +) -> (str, List[str]): folder_name = os.path.join(os.getcwd(), "test_cleanup/") os.mkdir(folder_name) repository_file_path = _write_file( @@ -108,7 +109,7 @@ def _create_tmp_test_files( ) def test_cleanup_main( repository_file_content: str, - release_files_content: list[str], + release_files_content: List[str], expected_print, monkeypatch, tmpdir, @@ -145,7 +146,7 @@ def test_cleanup_main( ) def test_cleanup_main_invalid_input_files( repository_file_content: str, - release_files_content: list[str], + release_files_content: List[str], expectation, monkeypatch, tmpdir, diff --git a/tests/test_lint_maturity.py b/tests/test_lint_maturity.py index d5e8bb784..95c671230 100644 --- a/tests/test_lint_maturity.py +++ b/tests/test_lint_maturity.py @@ -294,12 +294,9 @@ def test_lint_maturity_run(tmpdir): """ # noqa for list_file in list_files: - with ( - pytest.raises(SystemExit) as exit_info, - warnings.catch_warnings( - record=True, - ) as warning_info, - ): + with pytest.raises(SystemExit) as exit_info, warnings.catch_warnings( + record=True, + ) as warning_info: lint_maturity.run( files_to_lint=[list_file], tag_exceptions={ diff --git a/tests/test_release_transpiler_argument_types.py b/tests/test_release_transpiler_argument_types.py index 82d647b7a..e9f312824 100644 --- a/tests/test_release_transpiler_argument_types.py +++ b/tests/test_release_transpiler_argument_types.py @@ -1,6 +1,7 @@ import sys from contextlib import contextmanager from os.path import abspath, dirname +from typing import List import pytest @@ -71,7 +72,7 @@ def does_not_raise(): ), ], ) -def test_transpile_py_matrix_file_type(args: list[str], expectation, monkeypatch): +def test_transpile_py_matrix_file_type(args: List[str], expectation, monkeypatch): monkeypatch.setattr( sys, "argv", @@ -130,7 +131,7 @@ def test_transpile_py_matrix_file_type(args: list[str], expectation, monkeypatch ), ], ) -def test_transpile_py_output_folder_type(args: list[str], expectation, monkeypatch): +def test_transpile_py_output_folder_type(args: List[str], expectation, monkeypatch): monkeypatch.setattr( sys, "argv", @@ -178,7 +179,7 @@ def test_transpile_py_output_folder_type(args: list[str], expectation, monkeypat ], ) def test_transpile_py_matrix_coordinates_type( - args: list[str], + args: List[str], expectation, monkeypatch, ): diff --git a/tests/test_snyk_reporting.py b/tests/test_snyk_reporting.py index bade721d2..fee4a46aa 100644 --- a/tests/test_snyk_reporting.py +++ b/tests/test_snyk_reporting.py @@ -1,4 +1,4 @@ -from collections.abc import Mapping, Sequence +from typing import Mapping, Sequence from unittest.mock import Mock, patch import pytest