diff --git a/hatch_pip_compile/lock.py b/hatch_pip_compile/lock.py index c350155..fdacbba 100644 --- a/hatch_pip_compile/lock.py +++ b/hatch_pip_compile/lock.py @@ -2,21 +2,25 @@ hatch-pip-compile header operations """ +from __future__ import annotations + import hashlib import logging import pathlib import re from dataclasses import dataclass from textwrap import dedent -from typing import Iterable, List, Optional +from typing import TYPE_CHECKING, Iterable -from hatch.env.virtual import VirtualEnv from packaging.requirements import Requirement from packaging.version import Version from piptools._compat.pip_compat import PipSession, parse_requirements from hatch_pip_compile.exceptions import LockFileError +if TYPE_CHECKING: + from hatch_pip_compile.plugin import PipCompileEnvironment + logger = logging.getLogger(__name__) @@ -26,13 +30,7 @@ class PipCompileLock: Pip Compile Lock File Operations """ - lock_file: pathlib.Path - dependencies: List[str] - project_root: pathlib.Path - constraints_file: Optional[pathlib.Path] - env_name: str - project_name: str - virtualenv: Optional[VirtualEnv] = None + environment: PipCompileEnvironment def process_lock(self, lockfile: pathlib.Path) -> None: """ @@ -45,18 +43,20 @@ def process_lock(self, lockfile: pathlib.Path) -> None: # """ prefix = dedent(raw_prefix).strip() - joined_dependencies = "\n".join([f"# - {dep}" for dep in self.dependencies]) + joined_dependencies = "\n".join([f"# - {dep}" for dep in self.environment.dependencies]) lockfile_text = lockfile.read_text() cleaned_input_file = re.sub( - rf"-r \S*/{self.env_name}\.in", - f"hatch.envs.{self.env_name}", + rf"-r \S*/{self.environment.name}\.in", + f"hatch.envs.{self.environment.name}", lockfile_text, ) - if self.constraints_file is not None: - lockfile_contents = self.constraints_file.read_bytes() + if self.environment.piptools_constraints_file is not None: + lockfile_contents = self.environment.piptools_constraints_file.read_bytes() cross_platform_contents = lockfile_contents.replace(b"\r\n", b"\n") constraint_sha = hashlib.sha256(cross_platform_contents).hexdigest() - constraints_path = self.constraints_file.relative_to(self.project_root).as_posix() + constraints_path = self.environment.piptools_constraints_file.relative_to( + self.environment.root + ).as_posix() constraints_line = f"# [constraints] {constraints_path} (SHA256: {constraint_sha})" joined_dependencies = "\n".join([constraints_line, "#", joined_dependencies]) cleaned_input_file = re.sub( @@ -68,11 +68,11 @@ def process_lock(self, lockfile: pathlib.Path) -> None: new_text = prefix + "\n\n" + cleaned_input_file lockfile.write_text(new_text) - def read_header_requirements(self) -> List[Requirement]: + def read_header_requirements(self) -> list[Requirement]: """ Read requirements from lock file header """ - lock_file_text = self.lock_file.read_text() + lock_file_text = self.environment.piptools_lock_file.read_text() parsed_requirements = [] for line in lock_file_text.splitlines(): if line.startswith("# - "): @@ -90,8 +90,8 @@ def current_python_version(self) -> Version: In the case of running as a hatch plugin, the `virtualenv` will be set, otherwise it will be None and the Python version will be read differently. """ - if self.virtualenv is not None: - return Version(self.virtualenv.environment["python_version"]) + if self.environment.virtual_env is not None: + return Version(self.environment.virtual_env.environment["python_version"]) else: msg = "VirtualEnv is not set" raise NotImplementedError(msg) @@ -101,7 +101,7 @@ def lock_file_version(self) -> Version: """ Get lock file version """ - lock_file_text = self.lock_file.read_text() + lock_file_text = self.environment.piptools_lock_file.read_text() match = re.search( r"# This file is autogenerated by hatch-pip-compile with Python (.*)", lock_file_text ) @@ -110,7 +110,7 @@ def lock_file_version(self) -> Version: raise LockFileError(msg) return Version(match.group(1)) - def compare_python_versions(self, verbose: Optional[bool] = None) -> bool: + def compare_python_versions(self, verbose: bool | None = None) -> bool: """ Compare python versions @@ -148,7 +148,7 @@ def compare_constraint_sha(self, sha: str) -> bool: """ Compare SHA to the SHA on the lockfile """ - lock_file_text = self.lock_file.read_text() + lock_file_text = self.environment.piptools_lock_file.read_text() match = re.search(r"# \[constraints\] \S* \(SHA256: (.*)\)", lock_file_text) if match is None: return False @@ -158,18 +158,18 @@ def get_file_content_hash(self) -> str: """ Get hash of lock file """ - lockfile_contents = self.lock_file.read_bytes() + lockfile_contents = self.environment.piptools_lock_file.read_bytes() cross_platform_contents = lockfile_contents.replace(b"\r\n", b"\n") return hashlib.sha256(cross_platform_contents).hexdigest() - def read_lock_requirements(self) -> List[Requirement]: + def read_lock_requirements(self) -> list[Requirement]: """ Read all requirements from lock file """ - if not self.dependencies: + if not self.environment.dependencies: return [] install_requirements = parse_requirements( - str(self.lock_file), + str(self.environment.piptools_lock_file), session=PipSession(), ) return [ireq.req for ireq in install_requirements] # type: ignore[misc] diff --git a/hatch_pip_compile/plugin.py b/hatch_pip_compile/plugin.py index 9930cd4..cfa00c8 100644 --- a/hatch_pip_compile/plugin.py +++ b/hatch_pip_compile/plugin.py @@ -54,15 +54,7 @@ def __init__(self, *args, **kwargs) -> None: with self.metadata.context.apply_context(self.context): lock_filename = self.metadata.context.format(lock_filename_config) self.piptools_lock_file = self.root / lock_filename - self.piptools_lock = PipCompileLock( - lock_file=self.piptools_lock_file, - dependencies=self.dependencies, - virtualenv=self.virtual_env, - constraints_file=self.piptools_constraints_file, - project_root=self.root, - env_name=self.name, - project_name=self.metadata.name, - ) + self.piptools_lock = PipCompileLock(environment=self) install_method = self.config.get("pip-compile-installer", "pip") self.installer: PluginInstaller if install_method == "pip":