Skip to content

Commit 3842f5f

Browse files
committed
Basic abstraction and one migration
1 parent 6594d8e commit 3842f5f

File tree

5 files changed

+111
-12
lines changed

5 files changed

+111
-12
lines changed
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from pip._internal.utils.compat import lru_cache
2+
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
3+
4+
if MYPY_CHECK_RUNNING:
5+
from typing import List, Optional
6+
7+
from .base import BaseEnvironment
8+
9+
10+
@lru_cache(maxsize=None)
11+
def get_environment(paths=None):
12+
# type: (Optional[List[str]]) -> BaseEnvironment
13+
from .pkg_resources import Environment
14+
if paths is None:
15+
return Environment.default()
16+
return Environment.from_paths(paths)

src/pip/_internal/metadata/base.py

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import abc
2+
3+
from pip._vendor.six import add_metaclass
4+
5+
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
6+
7+
if MYPY_CHECK_RUNNING:
8+
from typing import List, Optional
9+
10+
11+
@add_metaclass(abc.ABCMeta)
12+
class BaseDistribution(object):
13+
@property
14+
def installer(self):
15+
# type: () -> str
16+
raise NotImplementedError()
17+
18+
19+
@add_metaclass(abc.ABCMeta)
20+
class BaseEnvironment(object):
21+
"""An environment containing distributions to introspect.
22+
"""
23+
@classmethod
24+
def default(cls):
25+
# type: () -> BaseEnvironment
26+
raise NotImplementedError()
27+
28+
@classmethod
29+
def from_paths(cls, paths):
30+
# type: (List[str]) -> BaseEnvironment
31+
raise NotImplementedError()
32+
33+
def get_distribution(self, name):
34+
# type: (str) -> Optional[BaseDistribution]
35+
raise NotImplementedError()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
from pip._vendor import pkg_resources
2+
3+
from pip._internal.utils.packaging import get_installer
4+
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
5+
6+
from .base import BaseDistribution, BaseEnvironment
7+
8+
if MYPY_CHECK_RUNNING:
9+
from typing import List, Optional
10+
11+
12+
class Distribution(BaseDistribution):
13+
def __init__(self, dist):
14+
# type: (pkg_resources.Distribution) -> None
15+
self._dist = dist
16+
17+
@property
18+
def installer(self):
19+
# type: () -> str
20+
# TODO: Move get_installer() implementation here.
21+
return get_installer(self._dist)
22+
23+
24+
class Environment(BaseEnvironment):
25+
def __init__(self, ws):
26+
# type: (pkg_resources.WorkingSet) -> None
27+
self._ws = ws
28+
29+
@classmethod
30+
def default(cls):
31+
# type: () -> BaseEnvironment
32+
return cls(pkg_resources.working_set)
33+
34+
@classmethod
35+
def from_paths(cls, paths):
36+
# type: (List[str]) -> BaseEnvironment
37+
return cls(pkg_resources.WorkingSet(paths))
38+
39+
def get_distribution(self, name):
40+
# type: (str) -> Optional[BaseDistribution]
41+
req = pkg_resources.Requirement(name)
42+
try:
43+
dist = self._ws.find(req)
44+
except pkg_resources.DistributionNotFound:
45+
return None
46+
return Distribution(dist)

src/pip/_internal/self_outdated_check.py

+4-10
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,14 @@
1212

1313
from pip._internal.index.collector import LinkCollector
1414
from pip._internal.index.package_finder import PackageFinder
15+
from pip._internal.metadata import get_environment
1516
from pip._internal.models.selection_prefs import SelectionPreferences
1617
from pip._internal.utils.filesystem import (
1718
adjacent_tmp_file,
1819
check_path_owner,
1920
replace,
2021
)
21-
from pip._internal.utils.misc import (
22-
ensure_dir,
23-
get_distribution,
24-
get_installed_version,
25-
)
26-
from pip._internal.utils.packaging import get_installer
22+
from pip._internal.utils.misc import ensure_dir, get_installed_version
2723
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
2824

2925
if MYPY_CHECK_RUNNING:
@@ -113,10 +109,8 @@ def was_installed_by_pip(pkg):
113109
This is used not to display the upgrade message when pip is in fact
114110
installed by system package manager, such as dnf on Fedora.
115111
"""
116-
dist = get_distribution(pkg)
117-
if not dist:
118-
return False
119-
return "pip" == get_installer(dist)
112+
dist = get_environment().get_distribution(pkg)
113+
return dist is not None and "pip" == dist.installer
120114

121115

122116
def pip_self_version_check(session, options):

tests/unit/test_self_check_outdated.py

+10-2
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@ def get_metadata_lines(self, name):
5757
raise NotImplementedError('nope')
5858

5959

60+
class MockEnvironment(object):
61+
def __init__(self, installer):
62+
self.installer = installer
63+
64+
def get_distribution(self, name):
65+
return MockDistribution(self.installer)
66+
67+
6068
def _options():
6169
''' Some default options that we pass to
6270
self_outdated_check.pip_self_version_check '''
@@ -97,8 +105,8 @@ def test_pip_self_version_check(monkeypatch, stored_time, installed_ver,
97105
pretend.call_recorder(lambda *a, **kw: None))
98106
monkeypatch.setattr(logger, 'debug',
99107
pretend.call_recorder(lambda s, exc_info=None: None))
100-
monkeypatch.setattr(self_outdated_check, 'get_distribution',
101-
lambda name: MockDistribution(installer))
108+
monkeypatch.setattr(self_outdated_check, 'get_environment',
109+
lambda: MockEnvironment(installer))
102110

103111
fake_state = pretend.stub(
104112
state={"last_check": stored_time, 'pypi_version': installed_ver},

0 commit comments

Comments
 (0)