Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ lock refactor #64

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 26 additions & 26 deletions hatch_pip_compile/lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__)


Expand All @@ -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:
"""
Expand All @@ -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(
Expand All @@ -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("# - "):
Expand All @@ -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)
Expand All @@ -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
)
Expand All @@ -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

Expand Down Expand Up @@ -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
Expand All @@ -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]
10 changes: 1 addition & 9 deletions hatch_pip_compile/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -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":
Expand Down
Loading