From ac5ae95369a7ae2aa5231fea8e4eb45f919e2d9f Mon Sep 17 00:00:00 2001 From: Kevin Veen-Birkenbach Date: Fri, 12 Dec 2025 19:02:54 +0100 Subject: [PATCH] fix(py39): replace PEP 604 union types with Optional for Python 3.9 compatibility - Replaced all `X | None` type hints with `Optional[X]` - Adjusted typing imports across modules - Fixed import order and removed invalid future-import placements - Ensured code runs correctly on Python 3.9 https://chatgpt.com/share/693c58e1-ce70-800f-9088-5864571e024a --- src/pkgmgr/actions/branch/close_branch.py | 1 - src/pkgmgr/actions/branch/drop_branch.py | 1 - src/pkgmgr/actions/branch/open_branch.py | 1 - src/pkgmgr/actions/install/__init__.py | 4 ++-- src/pkgmgr/actions/install/capabilities.py | 8 ++++---- src/pkgmgr/actions/install/installers/base.py | 4 ++-- .../install/installers/os_packages/debian_control.py | 4 ++-- src/pkgmgr/actions/mirror/git_remote.py | 2 +- src/pkgmgr/actions/release/workflow.py | 1 + src/pkgmgr/cli/commands/changelog.py | 1 + src/pkgmgr/cli/commands/config.py | 4 ++-- src/pkgmgr/cli/commands/version.py | 1 + src/pkgmgr/core/command/resolve.py | 1 + src/pkgmgr/core/command/run.py | 1 + src/pkgmgr/core/config/load.py | 6 +++--- 15 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/pkgmgr/actions/branch/close_branch.py b/src/pkgmgr/actions/branch/close_branch.py index ffe5c2a..991f1ca 100644 --- a/src/pkgmgr/actions/branch/close_branch.py +++ b/src/pkgmgr/actions/branch/close_branch.py @@ -1,5 +1,4 @@ from __future__ import annotations - from typing import Optional from pkgmgr.core.git import run_git, GitError, get_current_branch from .utils import _resolve_base_branch diff --git a/src/pkgmgr/actions/branch/drop_branch.py b/src/pkgmgr/actions/branch/drop_branch.py index 0ec9416..420f300 100644 --- a/src/pkgmgr/actions/branch/drop_branch.py +++ b/src/pkgmgr/actions/branch/drop_branch.py @@ -1,5 +1,4 @@ from __future__ import annotations - from typing import Optional from pkgmgr.core.git import run_git, GitError, get_current_branch from .utils import _resolve_base_branch diff --git a/src/pkgmgr/actions/branch/open_branch.py b/src/pkgmgr/actions/branch/open_branch.py index bac12e0..90c511f 100644 --- a/src/pkgmgr/actions/branch/open_branch.py +++ b/src/pkgmgr/actions/branch/open_branch.py @@ -1,5 +1,4 @@ from __future__ import annotations - from typing import Optional from pkgmgr.core.git import run_git, GitError from .utils import _resolve_base_branch diff --git a/src/pkgmgr/actions/install/__init__.py b/src/pkgmgr/actions/install/__init__.py index ac32f1f..fedaf63 100644 --- a/src/pkgmgr/actions/install/__init__.py +++ b/src/pkgmgr/actions/install/__init__.py @@ -15,7 +15,7 @@ Responsibilities: from __future__ import annotations import os -from typing import Any, Dict, List +from typing import Any, Dict, List, Optional from pkgmgr.core.repository.identifier import get_repo_identifier from pkgmgr.core.repository.dir import get_repo_dir @@ -63,7 +63,7 @@ def _ensure_repo_dir( no_verification: bool, clone_mode: str, identifier: str, -) -> str | None: +) -> Optional[str]: """ Compute and, if necessary, clone the repository directory. diff --git a/src/pkgmgr/actions/install/capabilities.py b/src/pkgmgr/actions/install/capabilities.py index 0532cb0..1a0a90f 100644 --- a/src/pkgmgr/actions/install/capabilities.py +++ b/src/pkgmgr/actions/install/capabilities.py @@ -35,7 +35,7 @@ from __future__ import annotations import glob import os from abc import ABC, abstractmethod -from typing import Iterable, TYPE_CHECKING +from typing import Iterable, TYPE_CHECKING, Optional if TYPE_CHECKING: from pkgmgr.actions.install.context import RepoContext @@ -46,7 +46,7 @@ if TYPE_CHECKING: # --------------------------------------------------------------------------- -def _read_text_if_exists(path: str) -> str | None: +def _read_text_if_exists(path: str) -> Optional[str]: """Read a file as UTF-8 text, returning None if it does not exist or fails.""" if not os.path.exists(path): return None @@ -75,7 +75,7 @@ def _scan_files_for_patterns(files: Iterable[str], patterns: Iterable[str]) -> b return False -def _first_spec_file(repo_dir: str) -> str | None: +def _first_spec_file(repo_dir: str) -> Optional[str]: """Return the first *.spec file in repo_dir, if any.""" matches = glob.glob(os.path.join(repo_dir, "*.spec")) if not matches: @@ -360,7 +360,7 @@ def detect_capabilities( def resolve_effective_capabilities( ctx: "RepoContext", - layers: Iterable[str] | None = None, + layers: Optional[Iterable[str]] = None, ) -> dict[str, set[str]]: """ Resolve *effective* capabilities for each layer using a bottom-up strategy. diff --git a/src/pkgmgr/actions/install/installers/base.py b/src/pkgmgr/actions/install/installers/base.py index 9a4a8b7..df052be 100644 --- a/src/pkgmgr/actions/install/installers/base.py +++ b/src/pkgmgr/actions/install/installers/base.py @@ -6,7 +6,7 @@ Base interface for all installer components in the pkgmgr installation pipeline. """ from abc import ABC, abstractmethod -from typing import Set +from typing import Set, Optional from pkgmgr.actions.install.context import RepoContext from pkgmgr.actions.install.capabilities import CAPABILITY_MATCHERS @@ -24,7 +24,7 @@ class BaseInstaller(ABC): # Examples: "nix", "python", "makefile". # This is used by capability matchers to decide which patterns to # search for in the repository. - layer: str | None = None + layer: Optional[str] = None def discover_capabilities(self, ctx: RepoContext) -> Set[str]: """ diff --git a/src/pkgmgr/actions/install/installers/os_packages/debian_control.py b/src/pkgmgr/actions/install/installers/os_packages/debian_control.py index 5eff16b..bcdf935 100644 --- a/src/pkgmgr/actions/install/installers/os_packages/debian_control.py +++ b/src/pkgmgr/actions/install/installers/os_packages/debian_control.py @@ -17,7 +17,7 @@ apt/dpkg tooling are available. import glob import os import shutil -from typing import List +from typing import List, Optional from pkgmgr.actions.install.context import RepoContext from pkgmgr.actions.install.installers.base import BaseInstaller @@ -67,7 +67,7 @@ class DebianControlInstaller(BaseInstaller): pattern = os.path.join(parent, "*.deb") return sorted(glob.glob(pattern)) - def _privileged_prefix(self) -> str | None: + def _privileged_prefix(self) -> Optional[str]: """ Determine how to run privileged commands: diff --git a/src/pkgmgr/actions/mirror/git_remote.py b/src/pkgmgr/actions/mirror/git_remote.py index 9087deb..ca531b8 100644 --- a/src/pkgmgr/actions/mirror/git_remote.py +++ b/src/pkgmgr/actions/mirror/git_remote.py @@ -1,10 +1,10 @@ from __future__ import annotations import os -from typing import List, Optional, Set from pkgmgr.core.command.run import run_command from pkgmgr.core.git import GitError, run_git +from typing import List, Optional, Set from .types import MirrorMap, RepoMirrorContext, Repository diff --git a/src/pkgmgr/actions/release/workflow.py b/src/pkgmgr/actions/release/workflow.py index 32dbcfc..c3159a6 100644 --- a/src/pkgmgr/actions/release/workflow.py +++ b/src/pkgmgr/actions/release/workflow.py @@ -1,4 +1,5 @@ from __future__ import annotations +from typing import Optional import os import sys diff --git a/src/pkgmgr/cli/commands/changelog.py b/src/pkgmgr/cli/commands/changelog.py index 2c16222..3b5c477 100644 --- a/src/pkgmgr/cli/commands/changelog.py +++ b/src/pkgmgr/cli/commands/changelog.py @@ -1,4 +1,5 @@ from __future__ import annotations +from typing import Optional import os import sys diff --git a/src/pkgmgr/cli/commands/config.py b/src/pkgmgr/cli/commands/config.py index a22830b..93ab621 100644 --- a/src/pkgmgr/cli/commands/config.py +++ b/src/pkgmgr/cli/commands/config.py @@ -7,7 +7,7 @@ import os import sys import shutil from pathlib import Path -from typing import Any, Dict +from typing import Any, Dict, Optional import yaml @@ -36,7 +36,7 @@ def _load_user_config(user_config_path: str) -> Dict[str, Any]: return {"repositories": []} -def _find_defaults_source_dir() -> str | None: +def _find_defaults_source_dir() -> Optional[str]: """ Find the directory inside the installed pkgmgr package OR the project root that contains default config files. diff --git a/src/pkgmgr/cli/commands/version.py b/src/pkgmgr/cli/commands/version.py index cdf05c0..490ae3e 100644 --- a/src/pkgmgr/cli/commands/version.py +++ b/src/pkgmgr/cli/commands/version.py @@ -1,4 +1,5 @@ from __future__ import annotations +from typing import Optional import os import sys diff --git a/src/pkgmgr/core/command/resolve.py b/src/pkgmgr/core/command/resolve.py index 023dab2..ef589fc 100644 --- a/src/pkgmgr/core/command/resolve.py +++ b/src/pkgmgr/core/command/resolve.py @@ -1,3 +1,4 @@ +from typing import Optional import os import shutil from typing import Optional, List, Dict, Any diff --git a/src/pkgmgr/core/command/run.py b/src/pkgmgr/core/command/run.py index b108183..04ec114 100644 --- a/src/pkgmgr/core/command/run.py +++ b/src/pkgmgr/core/command/run.py @@ -1,3 +1,4 @@ +from typing import Optional # pkgmgr/run_command.py import subprocess import sys diff --git a/src/pkgmgr/core/config/load.py b/src/pkgmgr/core/config/load.py index e754fde..34571e0 100644 --- a/src/pkgmgr/core/config/load.py +++ b/src/pkgmgr/core/config/load.py @@ -40,7 +40,7 @@ from __future__ import annotations import os from pathlib import Path -from typing import Any, Dict, List, Tuple +from typing import Any, Dict, List, Tuple, Optional import yaml @@ -83,7 +83,7 @@ def _repo_key(repo: Repo) -> Tuple[str, str, str]: def _merge_repo_lists( base_list: List[Repo], new_list: List[Repo], - category_name: str | None = None, + category_name: Optional[str] = None, ) -> List[Repo]: """ Merge two repository lists, matching by (provider, account, repository). @@ -143,7 +143,7 @@ def _load_yaml_file(path: Path) -> Dict[str, Any]: def _load_layer_dir( config_dir: Path, - skip_filename: str | None = None, + skip_filename: Optional[str] = None, ) -> Dict[str, Any]: """ Load all *.yml/*.yaml from a directory as layered defaults.