From 8ca4c43537fa7a5fbd91165233ab18a71fa95b3d Mon Sep 17 00:00:00 2001 From: Rahul Devikar Date: Sat, 14 Feb 2026 14:35:03 -0800 Subject: [PATCH] Replace ty: ignore with proper type declarations for inheritance patterns --- src/virtualenv/create/creator.py | 10 ++++++++-- src/virtualenv/create/via_global_ref/api.py | 15 ++++++++++++--- .../via_global_ref/builtin/cpython/mac_os.py | 2 +- .../via_global_ref/builtin/graalpy/__init__.py | 12 +++++++++--- .../via_global_ref/builtin/via_global_self_do.py | 6 ++++-- 5 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/virtualenv/create/creator.py b/src/virtualenv/create/creator.py index 746a3b112..19d3ab6f2 100644 --- a/src/virtualenv/create/creator.py +++ b/src/virtualenv/create/creator.py @@ -10,6 +10,7 @@ from ast import literal_eval from collections import OrderedDict from pathlib import Path +from typing import TYPE_CHECKING from virtualenv.discovery.cached_py_info import LogCmd from virtualenv.util.path import safe_delete @@ -47,6 +48,11 @@ def __init__(self, options, interpreter) -> None: self.app_data = options.app_data self.env = options.env + if TYPE_CHECKING: + + @property + def exe(self) -> Path: ... + def __repr__(self) -> str: return f"{self.__class__.__name__}({', '.join(f'{k}={v}' for k, v in self._args())})" @@ -197,8 +203,8 @@ def setup_ignore_vcs(self): @property def debug(self): """:return: debug information about the virtual environment (only valid after :meth:`create` has run)""" - if self._debug is None and self.exe is not None: # ty: ignore[unresolved-attribute] - self._debug = get_env_debug_info(self.exe, self.debug_script(), self.app_data, self.env) # ty: ignore[unresolved-attribute] + if self._debug is None and self.exe is not None: + self._debug = get_env_debug_info(self.exe, self.debug_script(), self.app_data, self.env) return self._debug @staticmethod diff --git a/src/virtualenv/create/via_global_ref/api.py b/src/virtualenv/create/via_global_ref/api.py index 49b935428..f9ff6f004 100644 --- a/src/virtualenv/create/via_global_ref/api.py +++ b/src/virtualenv/create/via_global_ref/api.py @@ -4,6 +4,7 @@ import os from abc import ABC from pathlib import Path +from typing import TYPE_CHECKING from virtualenv.create.creator import Creator, CreatorMeta from virtualenv.info import fs_supports_symlink @@ -34,6 +35,14 @@ def __init__(self, options, interpreter) -> None: self.symlinks = self._should_symlink(options) self.enable_system_site_package = options.system_site + if TYPE_CHECKING: + + @property + def purelib(self) -> Path: ... + + @property + def script_dir(self) -> Path: ... + @staticmethod def _should_symlink(options): # Priority of where the option is set to follow the order: CLI, env var, file, hardcoded. @@ -94,10 +103,10 @@ def create(self): def install_patch(self): text = self.env_patch_text() if text: - pth = self.purelib / "_virtualenv.pth" # ty: ignore[unresolved-attribute] + pth = self.purelib / "_virtualenv.pth" LOGGER.debug("create virtualenv import hook file %s", pth) pth.write_text("import _virtualenv", encoding="utf-8") - dest_path = self.purelib / "_virtualenv.py" # ty: ignore[unresolved-attribute] + dest_path = self.purelib / "_virtualenv.py" LOGGER.debug("create %s", dest_path) dest_path.write_text(text, encoding="utf-8") @@ -106,7 +115,7 @@ def env_patch_text(self): with self.app_data.ensure_extracted(Path(__file__).parent / "_virtualenv.py") as resolved_path: text = resolved_path.read_text(encoding="utf-8") # script_dir and purelib are defined in subclasses - return text.replace('"__SCRIPT_DIR__"', repr(os.path.relpath(str(self.script_dir), str(self.purelib)))) # ty: ignore[unresolved-attribute] + return text.replace('"__SCRIPT_DIR__"', repr(os.path.relpath(str(self.script_dir), str(self.purelib)))) def _args(self): return [*super()._args(), ("global", self.enable_system_site_package)] diff --git a/src/virtualenv/create/via_global_ref/builtin/cpython/mac_os.py b/src/virtualenv/create/via_global_ref/builtin/cpython/mac_os.py index 9284933fc..7e2e49934 100644 --- a/src/virtualenv/create/via_global_ref/builtin/cpython/mac_os.py +++ b/src/virtualenv/create/via_global_ref/builtin/cpython/mac_os.py @@ -34,7 +34,7 @@ def create(self): # change the install_name of the copied python executables target = self.desired_mach_o_image_path() current = self.current_mach_o_image_path() - for src in self._sources: # ty: ignore[not-iterable] + for src in self._sources: if isinstance(src, ExePathRefToDest) and (src.must == RefMust.COPY or not self.symlinks): exes = [self.bin_dir / src.base] if not self.symlinks: diff --git a/src/virtualenv/create/via_global_ref/builtin/graalpy/__init__.py b/src/virtualenv/create/via_global_ref/builtin/graalpy/__init__.py index 69732b7de..341bc11fc 100644 --- a/src/virtualenv/create/via_global_ref/builtin/graalpy/__init__.py +++ b/src/virtualenv/create/via_global_ref/builtin/graalpy/__init__.py @@ -1,6 +1,6 @@ from __future__ import annotations -from abc import ABC +from abc import ABC, abstractmethod from pathlib import Path from virtualenv.create.describe import PosixSupports, WindowsSupports @@ -9,6 +9,12 @@ class GraalPy(ViaGlobalRefVirtualenvBuiltin, ABC): + @classmethod + @abstractmethod + def _native_lib(cls, lib_dir: Path, platform: str) -> Path: + """Return the path to the native library for this platform.""" + raise NotImplementedError + @classmethod def can_describe(cls, interpreter): return interpreter.implementation == "GraalVM" and super().can_describe(interpreter) @@ -39,7 +45,7 @@ def sources(cls, interpreter): if python_dir.name in {"bin", "Scripts"}: python_dir = python_dir.parent - native_lib = cls._native_lib(python_dir / "lib", interpreter.platform) # ty: ignore[unresolved-attribute] + native_lib = cls._native_lib(python_dir / "lib", interpreter.platform) if native_lib.exists(): yield PathRefToDest(native_lib, dest=lambda self, s: self.bin_dir.parent / "lib" / s.name) @@ -72,7 +78,7 @@ def _native_lib(cls, lib_dir, platform): class GraalPyWindows(GraalPy, WindowsSupports): @classmethod - def _native_lib(cls, lib_dir, _platform): + def _native_lib(cls, lib_dir, platform): # noqa: ARG003 return lib_dir / "pythonvm.dll" def set_pyenv_cfg(self): diff --git a/src/virtualenv/create/via_global_ref/builtin/via_global_self_do.py b/src/virtualenv/create/via_global_ref/builtin/via_global_self_do.py index 35d0a76f4..de359070d 100644 --- a/src/virtualenv/create/via_global_ref/builtin/via_global_self_do.py +++ b/src/virtualenv/create/via_global_ref/builtin/via_global_self_do.py @@ -22,7 +22,9 @@ def __init__(self) -> None: class ViaGlobalRefVirtualenvBuiltin(ViaGlobalRefApi, VirtualenvBuiltin, ABC): def __init__(self, options, interpreter) -> None: super().__init__(options, interpreter) - self._sources = getattr(options.meta, "sources", None) # if we're created as a describer this might be missing + self._sources: list = ( + getattr(options.meta, "sources", None) or [] + ) # if created as a describer this might be missing @classmethod def can_create(cls, interpreter): @@ -86,7 +88,7 @@ def create(self): true_system_site = self.enable_system_site_package try: self.enable_system_site_package = False - for src in self._sources: # ty: ignore[not-iterable] + for src in self._sources: if ( src.when == RefWhen.ANY or (src.when == RefWhen.SYMLINK and self.symlinks is True)