File: local.py

package info (click to toggle)
firefox 144.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,637,504 kB
  • sloc: cpp: 7,576,692; javascript: 6,430,831; ansic: 3,748,119; python: 1,398,978; xml: 628,810; asm: 438,679; java: 186,194; sh: 63,212; makefile: 19,159; objc: 13,086; perl: 12,986; yacc: 4,583; cs: 3,846; pascal: 3,448; lex: 1,720; ruby: 1,003; exp: 762; php: 436; lisp: 258; awk: 247; sql: 66; sed: 53; csh: 10
file content (105 lines) | stat: -rw-r--r-- 3,703 bytes parent folder | download | duplicates (17)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
from __future__ import annotations

import optparse
from contextlib import contextmanager
from typing import Iterator, Mapping, cast

from pip._internal.commands.install import InstallCommand
from pip._internal.index.package_finder import PackageFinder
from pip._internal.models.candidate import InstallationCandidate
from pip._internal.network.session import PipSession
from pip._internal.req import InstallRequirement
from pip._internal.utils.hashes import FAVORITE_HASH

from piptools.utils import as_tuple, key_from_ireq, make_install_requirement

from .base import BaseRepository
from .pypi import PyPIRepository


def ireq_satisfied_by_existing_pin(
    ireq: InstallRequirement, existing_pin: InstallationCandidate
) -> bool:
    """
    Return True if the given InstallationRequirement is satisfied by the
    previously encountered version pin.
    """
    version = next(iter(existing_pin.req.specifier)).version
    result = ireq.req.specifier.contains(
        version, prereleases=existing_pin.req.specifier.prereleases
    )
    return cast(bool, result)


class LocalRequirementsRepository(BaseRepository):
    """
    The LocalRequirementsRepository proxied the _real_ repository by first
    checking if a requirement can be satisfied by existing pins (i.e. the
    result of a previous compile step).

    In effect, if a requirement can be satisfied with a version pinned in the
    requirements file, we prefer that version over the best match found in
    PyPI.  This keeps updates to the requirements.txt down to a minimum.
    """

    def __init__(
        self,
        existing_pins: Mapping[str, InstallationCandidate],
        proxied_repository: PyPIRepository,
        reuse_hashes: bool = True,
    ):
        self._reuse_hashes = reuse_hashes
        self.repository = proxied_repository
        self.existing_pins = existing_pins

    @property
    def options(self) -> optparse.Values:
        return self.repository.options

    @property
    def finder(self) -> PackageFinder:
        return self.repository.finder

    @property
    def session(self) -> PipSession:
        return self.repository.session

    @property
    def command(self) -> InstallCommand:
        """Return an install command instance."""
        return self.repository.command

    def clear_caches(self) -> None:
        self.repository.clear_caches()

    def find_best_match(
        self, ireq: InstallRequirement, prereleases: bool | None = None
    ) -> InstallationCandidate:
        key = key_from_ireq(ireq)
        existing_pin = self.existing_pins.get(key)
        if existing_pin and ireq_satisfied_by_existing_pin(ireq, existing_pin):
            project, version, _ = as_tuple(existing_pin)
            return make_install_requirement(project, version, ireq)
        else:
            return self.repository.find_best_match(ireq, prereleases)

    def get_dependencies(self, ireq: InstallRequirement) -> set[InstallRequirement]:
        return self.repository.get_dependencies(ireq)

    def get_hashes(self, ireq: InstallRequirement) -> set[str]:
        existing_pin = self._reuse_hashes and self.existing_pins.get(
            key_from_ireq(ireq)
        )
        if existing_pin and ireq_satisfied_by_existing_pin(ireq, existing_pin):
            hashes = existing_pin.hash_options
            hexdigests = hashes.get(FAVORITE_HASH)
            if hexdigests:
                return {
                    ":".join([FAVORITE_HASH, hexdigest]) for hexdigest in hexdigests
                }
        return self.repository.get_hashes(ireq)

    @contextmanager
    def allow_all_wheels(self) -> Iterator[None]:
        with self.repository.allow_all_wheels():
            yield