Fix environment extras installation for sdist

use pkg_resources.Distribution.requires instead of
Requirements.requirements to have environment markers parsing for free
It also unifies a little the process for wheel and non-wheel installs

closes #2174
This commit is contained in:
Xavier Fernandez 2014-12-07 23:51:46 +01:00
parent 4ea7937264
commit 06da6c07ec
6 changed files with 86 additions and 68 deletions

View File

@ -491,23 +491,6 @@ exec(compile(
_requirements_section_re = re.compile(r'\[(.*?)\]')
def requirements(self, extras=()):
if self.satisfied_by:
for r in self.satisfied_by.requires(extras):
yield str(r)
return
in_extra = None
for line in self.egg_info_lines('requires.txt'):
match = self._requirements_section_re.match(line.lower())
if match:
in_extra = match.group(1)
continue
if in_extra and in_extra not in extras:
logger.debug('skipping extra %s', in_extra)
# Skip requirement for an extra we aren't requiring
continue
yield line
@property
def installed_version(self):
if self.is_wheel:
@ -989,6 +972,17 @@ exec(compile(
isolated=self.isolated,
)
def get_dist(self):
"""Return a pkg_resources.Distribution built from self.egg_info_path"""
egg_info = self.egg_info_path('')
base_dir = os.path.dirname(egg_info)
metadata = pkg_resources.PathMetadata(base_dir, egg_info)
dist_name = os.path.splitext(os.path.basename(egg_info))[0]
return pkg_resources.Distribution(
os.path.dirname(egg_info),
project_name=dist_name,
metadata=metadata)
def _strip_postfix(req):
"""

View File

@ -410,67 +410,44 @@ class RequirementSet(object):
# ###################### #
# # parse dependencies # #
# ###################### #
if (req_to_install.extras):
logger.info(
"Installing extra requirements: %r",
','.join(req_to_install.extras),
)
if is_wheel:
dist = list(
pkg_resources.find_distributions(location)
)[0]
if not req_to_install.req:
req_to_install.req = dist.as_requirement()
self.add_requirement(req_to_install)
if not self.ignore_dependencies:
for subreq in dist.requires(
req_to_install.extras):
if self.has_requirement(
subreq.project_name):
continue
subreq = InstallRequirement(
str(subreq),
req_to_install,
isolated=self.isolated,
)
reqs.append(subreq)
self.add_requirement(subreq)
# sdists
else:
else: # sdists
# FIXME: shouldn't be globally added:
finder.add_dependency_links(
req_to_install.dependency_links
)
if (req_to_install.extras):
logger.info(
"Installing extra requirements: %r",
','.join(req_to_install.extras),
if req_to_install.satisfied_by:
dist = req_to_install.satisfied_by
else:
dist = req_to_install.get_dist()
if not self.ignore_dependencies:
for subreq in dist.requires(
req_to_install.extras):
if self.has_requirement(
subreq.project_name):
# FIXME: check for conflict
continue
subreq = InstallRequirement(
str(subreq),
req_to_install,
isolated=self.isolated,
)
if not self.ignore_dependencies:
for req in req_to_install.requirements(
req_to_install.extras):
try:
name = pkg_resources.Requirement.parse(
req
).project_name
except ValueError as exc:
# FIXME: proper warning
logger.error(
'Invalid requirement: %r (%s) in '
'requirement %s',
req, exc, req_to_install,
)
continue
if self.has_requirement(name):
# FIXME: check for conflict
continue
subreq = InstallRequirement(
req,
req_to_install,
isolated=self.isolated,
)
reqs.append(subreq)
self.add_requirement(subreq)
if not self.has_requirement(req_to_install.name):
# 'unnamed' requirements will get added here
self.add_requirement(req_to_install)
reqs.append(subreq)
self.add_requirement(subreq)
if not self.has_requirement(req_to_install.name):
# 'unnamed' requirements will get added here
self.add_requirement(req_to_install)
# cleanup tmp src
if (self.is_download or

View File

@ -0,0 +1 @@
/LocalEnvironMarker.egg-info

View File

@ -0,0 +1,29 @@
import os
from setuptools import setup, find_packages
def path_to_url(path):
"""
Convert a path to URI. The path will be made absolute and
will not have quoted path parts.
"""
path = os.path.normpath(os.path.abspath(path))
drive, path = os.path.splitdrive(path)
filepath = path.split(os.path.sep)
url = '/'.join(filepath)
if drive:
return 'file:///' + drive + url
return 'file://' +url
HERE = os.path.dirname(__file__)
DEP_PATH = os.path.join(HERE, '..', '..', 'indexes', 'simple', 'simple')
DEP_URL = path_to_url(DEP_PATH)
setup(
name='LocalEnvironMarker',
version='0.0.1',
packages=find_packages(),
extras_require={":python_version == '2.7' or python_version == '3.4'": ['simple'] },
dependency_links=[DEP_URL]
)

View File

@ -55,6 +55,23 @@ class TestRequirementSet(object):
finder,
)
def test_environment_marker_extras(self, data):
"""
Test that the environment marker extras are used with
non-wheel installs.
"""
reqset = self.basic_reqset()
req = InstallRequirement.from_editable(
data.packages.join("LocalEnvironMarker"))
reqset.add_requirement(req)
finder = PackageFinder([data.find_links], [], session=PipSession())
reqset.prepare_files(finder)
# This is hacky but does test both case in py2 and py3
if sys.version_info[:2] in ((2, 7), (3, 4)):
assert reqset.has_requirement('simple')
else:
assert not reqset.has_requirement('simple')
@pytest.mark.parametrize(('file_contents', 'expected'), [
(b'\xf6\x80', b'\xc3\xb6\xe2\x82\xac'), # cp1252