Skip to content

Commit

Permalink
Separate default and ad-hoc environment APIs
Browse files Browse the repository at this point in the history
pkg_resources performs annoying caching that needs to be worked around
in some parts of pip. This makes it easier to represent the difference
between environments backend by WorkingSet() and working_set.
  • Loading branch information
uranusjr committed Jan 19, 2021
1 parent 349bb73 commit 11e37aa
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 12 deletions.
23 changes: 20 additions & 3 deletions src/pip/_internal/metadata/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,27 @@
from .base import BaseEnvironment


def get_environment(paths=None):
def get_default_environment():
# type: () -> BaseEnvironment
"""Get the default representation for the current environment.
This returns an Environment instance from the chosen backend. The default
Environment instance should be built from ``sys.path`` and may use caching
to share instance state accorss calls.
"""
from .pkg_resources import Environment

return Environment.default()


def get_environment(paths):
# type: (Optional[List[str]]) -> BaseEnvironment
"""Get a representation of the environment specified by ``paths``.
This returns an Environment instance from the chosen backend based on the
given import paths. The backend must build a fresh instance representing
the state of installed distributions when this function is called.
"""
from .pkg_resources import Environment

if paths is None:
return Environment.default()
return Environment.from_paths(paths)
2 changes: 1 addition & 1 deletion src/pip/_internal/metadata/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def default(cls):

@classmethod
def from_paths(cls, paths):
# type: (List[str]) -> BaseEnvironment
# type: (Optional[List[str]]) -> BaseEnvironment
raise NotImplementedError()

def get_distribution(self, name):
Expand Down
2 changes: 1 addition & 1 deletion src/pip/_internal/metadata/pkg_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def default(cls):

@classmethod
def from_paths(cls, paths):
# type: (List[str]) -> BaseEnvironment
# type: (Optional[List[str]]) -> BaseEnvironment
return cls(pkg_resources.WorkingSet(paths))

def _search_distribution(self, name):
Expand Down
4 changes: 2 additions & 2 deletions src/pip/_internal/self_outdated_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

from pip._internal.index.collector import LinkCollector
from pip._internal.index.package_finder import PackageFinder
from pip._internal.metadata import get_environment
from pip._internal.metadata import get_default_environment
from pip._internal.models.selection_prefs import SelectionPreferences
from pip._internal.utils.filesystem import adjacent_tmp_file, check_path_owner, replace
from pip._internal.utils.misc import ensure_dir, get_installed_version
Expand Down Expand Up @@ -103,7 +103,7 @@ def was_installed_by_pip(pkg):
This is used not to display the upgrade message when pip is in fact
installed by system package manager, such as dnf on Fedora.
"""
dist = get_environment().get_distribution(pkg)
dist = get_default_environment().get_distribution(pkg)
return dist is not None and "pip" == dist.installer


Expand Down
13 changes: 9 additions & 4 deletions src/pip/_internal/utils/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -405,9 +405,14 @@ def get_installed_distributions(
Left for compatibility until direct pkg_resources uses are refactored out.
"""
from pip._internal.metadata import get_environment
from pip._internal.metadata import get_default_environment, get_environment
from pip._internal.metadata.pkg_resources import Distribution as _Dist
dists = get_environment(paths).iter_installed_distributions(

if paths is None:
env = get_default_environment()
else:
env = get_environment(paths)
dists = env.iter_installed_distributions(
local_only=local_only,
skip=skip,
include_editables=include_editables,
Expand All @@ -426,9 +431,9 @@ def get_distribution(req_name):
Left for compatibility until direct pkg_resources uses are refactored out.
"""
from pip._internal.metadata import get_environment
from pip._internal.metadata import get_default_environment
from pip._internal.metadata.pkg_resources import Distribution as _Dist
dist = get_environment().get_distribution(req_name)
dist = get_default_environment().get_distribution(req_name)
if dist is None:
return None
return cast(_Dist, dist)._dist
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/test_self_check_outdated.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def test_pip_self_version_check(monkeypatch, stored_time, installed_ver,
pretend.call_recorder(lambda *a, **kw: None))
monkeypatch.setattr(logger, 'debug',
pretend.call_recorder(lambda s, exc_info=None: None))
monkeypatch.setattr(self_outdated_check, 'get_environment',
monkeypatch.setattr(self_outdated_check, 'get_default_environment',
lambda: MockEnvironment(installer))

fake_state = pretend.stub(
Expand Down

0 comments on commit 11e37aa

Please sign in to comment.