summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Hunt <chrahunt@gmail.com>2019-11-09 09:57:03 +0800
committerGitHub <noreply@github.com>2019-11-09 09:57:03 +0800
commit7af704e3cf1dca12bdfbb51efb360ef5f58837de (patch)
treee6fc1c73aba0223583ad3bcb8d4562c5aad675f2
parente9cd20ca25f566bbc553df562b7d5edc9b819fa0 (diff)
parent6fa64a6b285ae8e5daaccbf346fb922bd023a494 (diff)
downloadpip-7af704e3cf1dca12bdfbb51efb360ef5f58837de.tar.gz
Merge pull request #7310 from chrahunt/refactor/scheme
Add Scheme model and use for wheel installation
-rw-r--r--src/pip/_internal/locations.py39
-rw-r--r--src/pip/_internal/models/scheme.py25
-rw-r--r--src/pip/_internal/req/req_install.py29
-rw-r--r--src/pip/_internal/wheel.py14
-rw-r--r--tests/unit/test_wheel.py25
5 files changed, 101 insertions, 31 deletions
diff --git a/src/pip/_internal/locations.py b/src/pip/_internal/locations.py
index 5dd10e814..b54b46bbe 100644
--- a/src/pip/_internal/locations.py
+++ b/src/pip/_internal/locations.py
@@ -16,6 +16,7 @@ from distutils import sysconfig as distutils_sysconfig
from distutils.command.install import SCHEME_KEYS # type: ignore
from distutils.command.install import install as distutils_install_command
+from pip._internal.models.scheme import Scheme
from pip._internal.utils import appdirs
from pip._internal.utils.compat import WINDOWS
from pip._internal.utils.typing import MYPY_CHECK_RUNNING, cast
@@ -153,3 +154,41 @@ def distutils_scheme(
)
return scheme
+
+
+def get_scheme(
+ dist_name, # type: str
+ user=False, # type: bool
+ home=None, # type: Optional[str]
+ root=None, # type: Optional[str]
+ isolated=False, # type: bool
+ prefix=None, # type: Optional[str]
+):
+ # type: (...) -> Scheme
+ """
+ Get the "scheme" corresponding to the input parameters. The distutils
+ documentation provides the context for the available schemes:
+ https://docs.python.org/3/install/index.html#alternate-installation
+
+ :param dist_name: the name of the package to retrieve the scheme for, used
+ in the headers scheme path
+ :param user: indicates to use the "user" scheme
+ :param home: indicates to use the "home" scheme and provides the base
+ directory for the same
+ :param root: root under which other directories are re-based
+ :param isolated: equivalent to --no-user-cfg, i.e. do not consider
+ ~/.pydistutils.cfg (posix) or ~/pydistutils.cfg (non-posix) for
+ scheme paths
+ :param prefix: indicates to use the "prefix" scheme and provides the
+ base directory for the same
+ """
+ scheme = distutils_scheme(
+ dist_name, user, home, root, isolated, prefix
+ )
+ return Scheme(
+ platlib=scheme["platlib"],
+ purelib=scheme["purelib"],
+ headers=scheme["headers"],
+ scripts=scheme["scripts"],
+ data=scheme["data"],
+ )
diff --git a/src/pip/_internal/models/scheme.py b/src/pip/_internal/models/scheme.py
new file mode 100644
index 000000000..af07b4078
--- /dev/null
+++ b/src/pip/_internal/models/scheme.py
@@ -0,0 +1,25 @@
+"""
+For types associated with installation schemes.
+
+For a general overview of available schemes and their context, see
+https://docs.python.org/3/install/index.html#alternate-installation.
+"""
+
+
+class Scheme(object):
+ """A Scheme holds paths which are used as the base directories for
+ artifacts associated with a Python package.
+ """
+ def __init__(
+ self,
+ platlib, # type: str
+ purelib, # type: str
+ headers, # type: str
+ scripts, # type: str
+ data, # type: str
+ ):
+ self.platlib = platlib
+ self.purelib = purelib
+ self.headers = headers
+ self.scripts = scripts
+ self.data = data
diff --git a/src/pip/_internal/req/req_install.py b/src/pip/_internal/req/req_install.py
index 8033c69a4..674545c9f 100644
--- a/src/pip/_internal/req/req_install.py
+++ b/src/pip/_internal/req/req_install.py
@@ -8,7 +8,6 @@ import logging
import os
import shutil
import sys
-import sysconfig
import zipfile
from distutils.util import change_root
@@ -22,7 +21,7 @@ from pip._vendor.pep517.wrappers import Pep517HookCaller
from pip._internal import pep425tags, wheel
from pip._internal.build_env import NoOpBuildEnvironment
from pip._internal.exceptions import InstallationError
-from pip._internal.locations import distutils_scheme
+from pip._internal.locations import get_scheme
from pip._internal.models.link import Link
from pip._internal.operations.build.metadata import generate_metadata
from pip._internal.operations.build.metadata_legacy import \
@@ -65,11 +64,12 @@ from pip._internal.vcs import vcs
if MYPY_CHECK_RUNNING:
from typing import (
- Any, Dict, Iterable, List, Mapping, Optional, Sequence, Union,
+ Any, Dict, Iterable, List, Optional, Sequence, Union,
)
from pip._internal.build_env import BuildEnvironment
from pip._internal.cache import WheelCache
from pip._internal.index.package_finder import PackageFinder
+ from pip._internal.models.scheme import Scheme
from pip._vendor.pkg_resources import Distribution
from pip._vendor.packaging.specifiers import SpecifierSet
from pip._vendor.packaging.markers import Marker
@@ -540,7 +540,7 @@ class InstallRequirement(object):
def move_wheel_files(
self,
wheeldir, # type: str
- scheme, # type: Mapping[str, str]
+ scheme, # type: Scheme
warn_script_location=True, # type: bool
pycompile=True # type: bool
):
@@ -852,6 +852,15 @@ class InstallRequirement(object):
pycompile=True # type: bool
):
# type: (...) -> None
+ scheme = get_scheme(
+ self.name,
+ user=use_user_site,
+ home=home,
+ root=root,
+ isolated=self.isolated,
+ prefix=prefix,
+ )
+
global_options = global_options if global_options is not None else []
if self.editable:
self.install_editable(
@@ -862,14 +871,11 @@ class InstallRequirement(object):
use_user_site=use_user_site,
)
return
+
if self.is_wheel:
version = wheel.wheel_version(self.source_dir)
wheel.check_compatibility(version, self.name)
- scheme = distutils_scheme(
- self.name, user=use_user_site, home=home, root=root,
- isolated=self.isolated, prefix=prefix,
- )
self.move_wheel_files(
self.source_dir,
scheme=scheme,
@@ -889,12 +895,7 @@ class InstallRequirement(object):
install_options = list(install_options) + \
self.options.get('install_options', [])
- header_dir = None # type: Optional[str]
- if running_under_virtualenv():
- py_ver_str = 'python' + sysconfig.get_python_version()
- header_dir = os.path.join(
- sys.prefix, 'include', 'site', py_ver_str, self.name
- )
+ header_dir = scheme.headers
with TempDirectory(kind="record") as temp_dir:
record_filename = os.path.join(temp_dir.path, 'install-record.txt')
diff --git a/src/pip/_internal/wheel.py b/src/pip/_internal/wheel.py
index 85a9e2b60..682a37e49 100644
--- a/src/pip/_internal/wheel.py
+++ b/src/pip/_internal/wheel.py
@@ -36,9 +36,11 @@ from pip._internal.utils.typing import MYPY_CHECK_RUNNING
if MYPY_CHECK_RUNNING:
from typing import (
- Dict, List, Optional, Sequence, Mapping, Tuple, IO, Text, Any,
+ Dict, List, Optional, Sequence, Tuple, IO, Text, Any,
Iterable, Callable, Set,
)
+
+ from pip._internal.models.scheme import Scheme
from pip._internal.pep425tags import Pep425Tag
InstalledCSVRow = Tuple[str, ...]
@@ -289,7 +291,7 @@ class PipScriptMaker(ScriptMaker):
def install_unpacked_wheel(
name, # type: str
wheeldir, # type: str
- scheme, # type: Mapping[str, str]
+ scheme, # type: Scheme
req_description, # type: str
pycompile=True, # type: bool
warn_script_location=True # type: bool
@@ -311,9 +313,9 @@ def install_unpacked_wheel(
# installation.
if root_is_purelib(name, wheeldir):
- lib_dir = scheme['purelib']
+ lib_dir = scheme.purelib
else:
- lib_dir = scheme['platlib']
+ lib_dir = scheme.platlib
info_dir = [] # type: List[str]
data_dirs = []
@@ -458,10 +460,10 @@ def install_unpacked_wheel(
fixer = fix_script
filter = is_entrypoint_wrapper
source = os.path.join(wheeldir, datadir, subdir)
- dest = scheme[subdir]
+ dest = getattr(scheme, subdir)
clobber(source, dest, False, fixer=fixer, filter=filter)
- maker = PipScriptMaker(None, scheme['scripts'])
+ maker = PipScriptMaker(None, scheme.scripts)
# Ensure old scripts are overwritten.
# See https://github.com/pypa/pip/issues/1800
diff --git a/tests/unit/test_wheel.py b/tests/unit/test_wheel.py
index 3153f2a82..ea145d722 100644
--- a/tests/unit/test_wheel.py
+++ b/tests/unit/test_wheel.py
@@ -11,8 +11,9 @@ from pip._vendor.packaging.requirements import Requirement
from pip._internal import pep425tags, wheel
from pip._internal.commands.wheel import WheelCommand
from pip._internal.exceptions import InvalidWheelFilename, UnsupportedWheel
-from pip._internal.locations import distutils_scheme
+from pip._internal.locations import get_scheme
from pip._internal.models.link import Link
+from pip._internal.models.scheme import Scheme
from pip._internal.req.req_install import InstallRequirement
from pip._internal.utils.compat import WINDOWS
from pip._internal.utils.misc import hash_file
@@ -482,29 +483,31 @@ class TestInstallUnpackedWheel(object):
self.src = os.path.join(tmpdir, 'src')
self.dest = os.path.join(tmpdir, 'dest')
unpack_file(self.wheelpath, self.src)
- self.scheme = {
- 'scripts': os.path.join(self.dest, 'bin'),
- 'purelib': os.path.join(self.dest, 'lib'),
- 'data': os.path.join(self.dest, 'data'),
- }
+ self.scheme = Scheme(
+ purelib=os.path.join(self.dest, 'lib'),
+ platlib=os.path.join(self.dest, 'lib'),
+ headers=os.path.join(self.dest, 'headers'),
+ scripts=os.path.join(self.dest, 'bin'),
+ data=os.path.join(self.dest, 'data'),
+ )
self.src_dist_info = os.path.join(
self.src, 'sample-1.2.0.dist-info')
self.dest_dist_info = os.path.join(
- self.scheme['purelib'], 'sample-1.2.0.dist-info')
+ self.scheme.purelib, 'sample-1.2.0.dist-info')
def assert_installed(self):
# lib
assert os.path.isdir(
- os.path.join(self.scheme['purelib'], 'sample'))
+ os.path.join(self.scheme.purelib, 'sample'))
# dist-info
metadata = os.path.join(self.dest_dist_info, 'METADATA')
assert os.path.isfile(metadata)
# data files
- data_file = os.path.join(self.scheme['data'], 'my_data', 'data_file')
+ data_file = os.path.join(self.scheme.data, 'my_data', 'data_file')
assert os.path.isfile(data_file)
# package data
pkg_data = os.path.join(
- self.scheme['purelib'], 'sample', 'package_data.dat')
+ self.scheme.purelib, 'sample', 'package_data.dat')
assert os.path.isfile(pkg_data)
def test_std_install(self, data, tmpdir):
@@ -520,7 +523,7 @@ class TestInstallUnpackedWheel(object):
def test_install_prefix(self, data, tmpdir):
prefix = os.path.join(os.path.sep, 'some', 'path')
self.prep(data, tmpdir)
- scheme = distutils_scheme(
+ scheme = get_scheme(
self.name,
user=False,
home=None,