Commit 5e4eea7d authored by Jason R. Coombs's avatar Jason R. Coombs

In test command, add installed eggs to PYTHONPATH when invoking tests so that...

In test command, add installed eggs to PYTHONPATH when invoking tests so that subprocesses will also have the dependencies available. Fixes #794.
parent 22aa7670
......@@ -2,6 +2,13 @@
CHANGES
=======
v27.3.0
-------
* #794: In test command, add installed eggs to PYTHONPATH
when invoking tests so that subprocesses will also have the
dependencies available.
v27.2.0
-------
......
import os
import operator
import sys
import contextlib
from distutils.errors import DistutilsOptionError
from unittest import TestLoader
from setuptools.extern import six
from setuptools.extern.six.moves import map
from setuptools.extern.six.moves import map, filter
from pkg_resources import (resource_listdir, resource_exists, normalize_path,
working_set, _namespace_packages,
......@@ -112,7 +114,7 @@ class test(Command):
func()
@contextlib.contextmanager
def project_on_sys_path(self):
def project_on_sys_path(self, include_dists=[]):
with_2to3 = six.PY3 and getattr(self.distribution, 'use_2to3', False)
if with_2to3:
......@@ -144,23 +146,57 @@ class test(Command):
old_modules = sys.modules.copy()
try:
sys.path.insert(0, normalize_path(ei_cmd.egg_base))
project_path = normalize_path(ei_cmd.egg_base)
sys.path.insert(0, project_path)
working_set.__init__()
add_activation_listener(lambda dist: dist.activate())
require('%s==%s' % (ei_cmd.egg_name, ei_cmd.egg_version))
yield
with self.paths_on_pythonpath([project_path]):
yield
finally:
sys.path[:] = old_path
sys.modules.clear()
sys.modules.update(old_modules)
working_set.__init__()
@staticmethod
@contextlib.contextmanager
def paths_on_pythonpath(paths):
"""
Add the indicated paths to the head of the PYTHONPATH environment
variable so that subprocesses will also see the packages at
these paths.
Do this in a context that restores the value on exit.
"""
nothing = object()
orig_pythonpath = os.environ.get('PYTHONPATH', nothing)
current_pythonpath = os.environ.get('PYTHONPATH', '')
try:
prefix = os.pathsep.join(paths)
to_join = filter(None, [prefix, current_pythonpath])
new_path = os.pathsep.join(to_join)
if new_path:
os.environ['PYTHONPATH'] = new_path
yield
finally:
if orig_pythonpath is nothing:
os.environ.pop('PYTHONPATH', None)
else:
os.environ['PYTHONPATH'] = orig_pythonpath
def run(self):
installed_dists = []
if self.distribution.install_requires:
self.distribution.fetch_build_eggs(
self.distribution.install_requires)
installed_dists.extend(
self.distribution.fetch_build_eggs(
self.distribution.install_requires,
))
if self.distribution.tests_require:
self.distribution.fetch_build_eggs(self.distribution.tests_require)
installed_dists.extend(
self.distribution.fetch_build_eggs(
self.distribution.tests_require,
))
cmd = ' '.join(self._argv)
if self.dry_run:
......@@ -168,8 +204,11 @@ class test(Command):
return
self.announce('running "%s"' % cmd)
with self.project_on_sys_path():
self.run_tests()
paths = map(operator.attrgetter('location'), installed_dists)
with self.paths_on_pythonpath(paths):
with self.project_on_sys_path():
self.run_tests()
def run_tests(self):
# Purge modules under test from sys.modules. The test loader will
......
......@@ -362,6 +362,7 @@ class Distribution(_Distribution):
)
for dist in resolved_dists:
pkg_resources.working_set.add(dist, replace=True)
return resolved_dists
def finalize_options(self):
_Distribution.finalize_options(self)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment