class PipTestEnvironment(scripttest.TestFileEnvironment): """ A specialized TestFileEnvironment for testing pip """ # # Attribute naming convention # --------------------------- # # Instances of this class have many attributes representing paths # in the filesystem. To keep things straight, absolute paths have # a name of the form xxxx_path and relative paths have a name that # does not end in '_path'. exe = sys.platform == 'win32' and '.exe' or '' verbose = False def __init__(self, base_path, *args, **kwargs): # Make our base_path a test.lib.path.Path object base_path = Path(base_path) # Store paths related to the virtual environment _virtualenv = kwargs.pop("virtualenv") path_locations = virtualenv.path_locations(_virtualenv) # Make sure we have test.lib.path.Path objects venv, lib, include, bin = map(Path, path_locations) self.venv_path = venv self.lib_path = virtualenv_lib_path(venv, lib) self.include_path = include self.bin_path = bin if hasattr(sys, "pypy_version_info"): self.site_packages_path = self.venv_path.join("site-packages") else: self.site_packages_path = self.lib_path.join("site-packages") self.user_base_path = self.venv_path.join("user") self.user_site_path = self.venv_path.join( "user", site.USER_SITE[len(site.USER_BASE) + 1:], ) if sys.platform == 'win32': if sys.version_info >= (3, 5): scripts_base = self.user_site_path.join('..').normpath else: scripts_base = self.user_base_path self.user_bin_path = scripts_base.join('Scripts') else: self.user_bin_path = self.user_base_path.join( self.bin_path - self.venv_path ) # Create a Directory to use as a scratch pad self.scratch_path = base_path.join("scratch").mkdir() # Set our default working directory kwargs.setdefault("cwd", self.scratch_path) # Setup our environment environ = kwargs.get("environ") if environ is None: environ = os.environ.copy() environ["PATH"] = Path.pathsep.join( [self.bin_path] + [environ.get("PATH", [])], ) environ["PYTHONUSERBASE"] = self.user_base_path # Writing bytecode can mess up updated file detection environ["PYTHONDONTWRITEBYTECODE"] = "1" # Make sure we get UTF-8 on output, even on Windows... environ["PYTHONIOENCODING"] = "UTF-8" kwargs["environ"] = environ # Call the TestFileEnvironment __init__ super(PipTestEnvironment, self).__init__(base_path, *args, **kwargs) # Expand our absolute path directories into relative for name in ["base", "venv", "lib", "include", "bin", "site_packages", "user_base", "user_site", "user_bin", "scratch"]: real_name = "%s_path" % name setattr(self, name, getattr(self, real_name) - self.base_path) # Make sure temp_path is a Path object self.temp_path = Path(self.temp_path) # Ensure the tmp dir exists, things break horribly if it doesn't self.temp_path.mkdir() # create easy-install.pth in user_site, so we always have it updated # instead of created self.user_site_path.makedirs() self.user_site_path.join("easy-install.pth").touch() def _ignore_file(self, fn): if fn.endswith('__pycache__') or fn.endswith(".pyc"): result = True else: result = super(PipTestEnvironment, self)._ignore_file(fn) return result def run(self, *args, **kw): if self.verbose: print('>> running %s %s' % (args, kw)) cwd = kw.pop('cwd', None) run_from = kw.pop('run_from', None) assert not cwd or not run_from, "Don't use run_from; it's going away" cwd = cwd or run_from or self.cwd if sys.platform == 'win32': # Partial fix for ScriptTest.run using `shell=True` on Windows. args = [str(a).replace('^', '^^').replace('&', '^&') for a in args] return TestPipResult( super(PipTestEnvironment, self).run(cwd=cwd, *args, **kw), verbose=self.verbose, ) def pip(self, *args, **kwargs): # On old versions of Python, urllib3/requests will raise a warning # about the lack of an SSLContext. Expect it when running commands # that will touch the outside world. if (pyversion_tuple < (2, 7, 9) and args and args[0] in ('search', 'install', 'download')): kwargs['expect_stderr'] = True if kwargs.pop('use_module', False): exe = 'python' args = ('-m', 'pip') + args else: exe = 'pip' return self.run(exe, *args, **kwargs) def pip_install_local(self, *args, **kwargs): return self.pip( "install", "--no-index", "--find-links", path_to_url(os.path.join(DATA_DIR, "packages")), *args, **kwargs )
class PipTestEnvironment(TestFileEnvironment): """ A specialized TestFileEnvironment for testing pip """ # # Attribute naming convention # --------------------------- # # Instances of this class have many attributes representing paths # in the filesystem. To keep things straight, absolute paths have # a name of the form xxxx_path and relative paths have a name that # does not end in '_path'. exe = sys.platform == 'win32' and '.exe' or '' verbose = False def __init__(self, base_path, *args, **kwargs): # Make our base_path a test.lib.path.Path object base_path = Path(base_path) # Store paths related to the virtual environment venv = kwargs.pop("virtualenv") self.venv_path = venv.location self.lib_path = venv.lib self.site_packages_path = venv.site self.bin_path = venv.bin self.user_base_path = self.venv_path.join("user") self.user_site_path = self.venv_path.join( "user", site.USER_SITE[len(site.USER_BASE) + 1:], ) if sys.platform == 'win32': if sys.version_info >= (3, 5): scripts_base = self.user_site_path.join('..').normpath else: scripts_base = self.user_base_path self.user_bin_path = scripts_base.join('Scripts') else: self.user_bin_path = self.user_base_path.join( self.bin_path - self.venv_path ) # Create a Directory to use as a scratch pad self.scratch_path = base_path.join("scratch").mkdir() # Set our default working directory kwargs.setdefault("cwd", self.scratch_path) # Setup our environment environ = kwargs.get("environ") if environ is None: environ = os.environ.copy() environ["PATH"] = Path.pathsep.join( [self.bin_path] + [environ.get("PATH", [])], ) environ["PYTHONUSERBASE"] = self.user_base_path # Writing bytecode can mess up updated file detection environ["PYTHONDONTWRITEBYTECODE"] = "1" # Make sure we get UTF-8 on output, even on Windows... environ["PYTHONIOENCODING"] = "UTF-8" kwargs["environ"] = environ # Whether all pip invocations should expect stderr # (useful for Python version deprecation) self.pip_expect_warning = kwargs.pop('pip_expect_warning', None) # Call the TestFileEnvironment __init__ super(PipTestEnvironment, self).__init__(base_path, *args, **kwargs) # Expand our absolute path directories into relative for name in ["base", "venv", "bin", "lib", "site_packages", "user_base", "user_site", "user_bin", "scratch"]: real_name = "%s_path" % name setattr(self, name, getattr(self, real_name) - self.base_path) # Make sure temp_path is a Path object self.temp_path = Path(self.temp_path) # Ensure the tmp dir exists, things break horribly if it doesn't self.temp_path.mkdir() # create easy-install.pth in user_site, so we always have it updated # instead of created self.user_site_path.makedirs() self.user_site_path.join("easy-install.pth").touch() def _ignore_file(self, fn): if fn.endswith('__pycache__') or fn.endswith(".pyc"): result = True else: result = super(PipTestEnvironment, self)._ignore_file(fn) return result def _find_traverse(self, path, result): # Ignore symlinked directories to avoid duplicates in `run()` # results because of venv `lib64 -> lib/` symlink on Linux. full = os.path.join(self.base_path, path) if os.path.isdir(full) and os.path.islink(full): if not self.temp_path or path != 'tmp': result[path] = FoundDir(self.base_path, path) else: super(PipTestEnvironment, self)._find_traverse(path, result) def run(self, *args, **kw): """ :param allow_stderr_warning: whether a logged warning (or deprecation message) is allowed in stderr. :param allow_stderr_error: whether a logged error is allowed in stderr. Passing True for this argument implies `allow_stderr_warning` since warnings are weaker than errors. :param expect_stderr: whether to allow warnings in stderr (equivalent to `allow_stderr_warning`). This argument is an abbreviated version of `allow_stderr_warning` and is also kept for backwards compatibility. """ if self.verbose: print('>> running %s %s' % (args, kw)) cwd = kw.pop('cwd', None) run_from = kw.pop('run_from', None) assert not cwd or not run_from, "Don't use run_from; it's going away" cwd = cwd or run_from or self.cwd if sys.platform == 'win32': # Partial fix for ScriptTest.run using `shell=True` on Windows. args = [str(a).replace('^', '^^').replace('&', '^&') for a in args] # Remove `allow_stderr_error` and `allow_stderr_warning` before # calling run() because PipTestEnvironment doesn't support them. allow_stderr_error = kw.pop('allow_stderr_error', None) allow_stderr_warning = kw.pop('allow_stderr_warning', None) if kw.get('expect_error'): # Then default to allowing logged errors. if allow_stderr_error is not None and not allow_stderr_error: raise RuntimeError( 'cannot pass allow_stderr_error=False with ' 'expect_error=True' ) allow_stderr_error = True elif kw.get('expect_stderr'): # Then default to allowing logged warnings. if allow_stderr_warning is not None and not allow_stderr_warning: raise RuntimeError( 'cannot pass allow_stderr_warning=False with ' 'expect_stderr=True' ) allow_stderr_warning = True # Pass expect_stderr=True to allow any stderr. We do this because # we do our checking of stderr further on in check_stderr(). kw['expect_stderr'] = True result = super(PipTestEnvironment, self).run(cwd=cwd, *args, **kw) check_stderr( result.stderr, allow_stderr_error=allow_stderr_error, allow_stderr_warning=allow_stderr_warning, ) return TestPipResult(result, verbose=self.verbose) def pip(self, *args, **kwargs): if self.pip_expect_warning: kwargs['allow_stderr_warning'] = True if kwargs.pop('use_module', True): exe = 'python' args = ('-m', 'pip') + args else: exe = 'pip' return self.run(exe, *args, **kwargs) def pip_install_local(self, *args, **kwargs): return self.pip( "install", "--no-index", "--find-links", path_to_url(os.path.join(DATA_DIR, "packages")), *args, **kwargs ) def easy_install(self, *args, **kwargs): args = ('-m', 'easy_install') + args return self.run('python', *args, **kwargs)
class PipTestEnvironment(scripttest.TestFileEnvironment): """ A specialized TestFileEnvironment for testing pip """ # # Attribute naming convention # --------------------------- # # Instances of this class have many attributes representing paths # in the filesystem. To keep things straight, absolute paths have # a name of the form xxxx_path and relative paths have a name that # does not end in '_path'. exe = sys.platform == 'win32' and '.exe' or '' verbose = False def __init__(self, base_path, *args, **kwargs): # Make our base_path a test.lib.path.Path object base_path = Path(base_path) # Store paths related to the virtual environment _virtualenv = kwargs.pop("virtualenv") venv, lib, include, bin = virtualenv.path_locations(_virtualenv) # workaround for https://github.com/pypa/virtualenv/issues/306 if hasattr(sys, "pypy_version_info"): lib = os.path.join(venv, 'lib-python', pyversion) self.venv_path = venv self.lib_path = lib self.include_path = include self.bin_path = bin if hasattr(sys, "pypy_version_info"): self.site_packages_path = self.venv_path.join("site-packages") else: self.site_packages_path = self.lib_path.join("site-packages") self.user_base_path = self.venv_path.join("user") self.user_bin_path = self.user_base_path.join(self.bin_path - self.venv_path) self.user_site_path = self.venv_path.join( "user", site.USER_SITE[len(site.USER_BASE) + 1:], ) # Create a Directory to use as a scratch pad self.scratch_path = base_path.join("scratch").mkdir() # Set our default working directory kwargs.setdefault("cwd", self.scratch_path) # Setup our environment environ = kwargs.get("environ") if environ is None: environ = os.environ.copy() environ["PIP_LOG_FILE"] = base_path.join("pip-log.txt") environ["PATH"] = Path.pathsep.join([self.bin_path] + [environ.get("PATH", [])], ) environ["PYTHONUSERBASE"] = self.user_base_path # Writing bytecode can mess up updated file detection environ["PYTHONDONTWRITEBYTECODE"] = "1" kwargs["environ"] = environ # Call the TestFileEnvironment __init__ super(PipTestEnvironment, self).__init__(base_path, *args, **kwargs) # Expand our absolute path directories into relative for name in [ "base", "venv", "lib", "include", "bin", "site_packages", "user_base", "user_site", "user_bin", "scratch" ]: real_name = "%s_path" % name setattr(self, name, getattr(self, real_name) - self.base_path) # Make sure temp_path is a Path object self.temp_path = Path(self.temp_path) # Ensure the tmp dir exists, things break horribly if it doesn't self.temp_path.mkdir() # create easy-install.pth in user_site, so we always have it updated # instead of created self.user_site_path.makedirs() self.user_site_path.join("easy-install.pth").touch() def _ignore_file(self, fn): if fn.endswith('__pycache__') or fn.endswith(".pyc"): result = True else: result = super(PipTestEnvironment, self)._ignore_file(fn) return result def run(self, *args, **kw): if self.verbose: print('>> running %s %s' % (args, kw)) cwd = kw.pop('cwd', None) run_from = kw.pop('run_from', None) assert not cwd or not run_from, "Don't use run_from; it's going away" cwd = cwd or run_from or self.cwd return TestPipResult( super(PipTestEnvironment, self).run(cwd=cwd, *args, **kw), verbose=self.verbose, ) def pip(self, *args, **kwargs): return self.run("pip", *args, **kwargs) def pip_install_local(self, *args, **kwargs): return self.pip("install", "--no-index", "--find-links", path_to_url(os.path.join(DATA_DIR, "packages")), *args, **kwargs)
class PipTestEnvironment(TestFileEnvironment): """ A specialized TestFileEnvironment for testing pip """ # # Attribute naming convention # --------------------------- # # Instances of this class have many attributes representing paths # in the filesystem. To keep things straight, absolute paths have # a name of the form xxxx_path and relative paths have a name that # does not end in '_path'. exe = sys.platform == 'win32' and '.exe' or '' verbose = False def __init__(self, base_path, *args, **kwargs): # Make our base_path a test.lib.path.Path object base_path = Path(base_path) # Store paths related to the virtual environment venv = kwargs.pop("virtualenv") self.venv_path = venv.location self.lib_path = venv.lib self.site_packages_path = venv.site self.bin_path = venv.bin self.user_base_path = self.venv_path.joinpath("user") self.user_site_path = self.venv_path.joinpath( "user", site.USER_SITE[len(site.USER_BASE) + 1:], ) if sys.platform == 'win32': if sys.version_info >= (3, 5): scripts_base = Path( os.path.normpath(self.user_site_path.joinpath('..'))) else: scripts_base = self.user_base_path self.user_bin_path = scripts_base.joinpath('Scripts') else: self.user_bin_path = self.user_base_path.joinpath( os.path.relpath(self.bin_path, self.venv_path)) # Create a Directory to use as a scratch pad self.scratch_path = base_path.joinpath("scratch") self.scratch_path.mkdir() # Set our default working directory kwargs.setdefault("cwd", self.scratch_path) # Setup our environment environ = kwargs.setdefault("environ", os.environ.copy()) environ["PATH"] = Path.pathsep.join([self.bin_path] + [environ.get("PATH", [])], ) environ["PYTHONUSERBASE"] = self.user_base_path # Writing bytecode can mess up updated file detection environ["PYTHONDONTWRITEBYTECODE"] = "1" # Make sure we get UTF-8 on output, even on Windows... environ["PYTHONIOENCODING"] = "UTF-8" # Whether all pip invocations should expect stderr # (useful for Python version deprecation) self.pip_expect_warning = kwargs.pop('pip_expect_warning', None) # Call the TestFileEnvironment __init__ super(PipTestEnvironment, self).__init__(base_path, *args, **kwargs) # Expand our absolute path directories into relative for name in [ "base", "venv", "bin", "lib", "site_packages", "user_base", "user_site", "user_bin", "scratch" ]: real_name = "{name}_path".format(**locals()) relative_path = Path( os.path.relpath(getattr(self, real_name), self.base_path)) setattr(self, name, relative_path) # Make sure temp_path is a Path object self.temp_path = Path(self.temp_path) # Ensure the tmp dir exists, things break horribly if it doesn't self.temp_path.mkdir() # create easy-install.pth in user_site, so we always have it updated # instead of created self.user_site_path.mkdir(parents=True) self.user_site_path.joinpath("easy-install.pth").touch() def _ignore_file(self, fn): if fn.endswith('__pycache__') or fn.endswith(".pyc"): result = True else: result = super(PipTestEnvironment, self)._ignore_file(fn) return result def _find_traverse(self, path, result): # Ignore symlinked directories to avoid duplicates in `run()` # results because of venv `lib64 -> lib/` symlink on Linux. full = os.path.join(self.base_path, path) if os.path.isdir(full) and os.path.islink(full): if not self.temp_path or path != 'tmp': result[path] = FoundDir(self.base_path, path) else: super(PipTestEnvironment, self)._find_traverse(path, result) def run(self, *args, **kw): """ :param allow_stderr_error: whether a logged error is allowed in stderr. Passing True for this argument implies `allow_stderr_warning` since warnings are weaker than errors. :param allow_stderr_warning: whether a logged warning (or deprecation message) is allowed in stderr. :param allow_error: if True (default is False) does not raise exception when the command exit value is non-zero. Implies expect_error, but in contrast to expect_error will not assert that the exit value is zero. :param expect_error: if False (the default), asserts that the command exits with 0. Otherwise, asserts that the command exits with a non-zero exit code. Passing True also implies allow_stderr_error and allow_stderr_warning. :param expect_stderr: whether to allow warnings in stderr (equivalent to `allow_stderr_warning`). This argument is an abbreviated version of `allow_stderr_warning` and is also kept for backwards compatibility. """ if self.verbose: print('>> running {args} {kw}'.format(**locals())) cwd = kw.pop('cwd', None) run_from = kw.pop('run_from', None) assert not cwd or not run_from, "Don't use run_from; it's going away" cwd = cwd or run_from or self.cwd if sys.platform == 'win32': # Partial fix for ScriptTest.run using `shell=True` on Windows. args = [str(a).replace('^', '^^').replace('&', '^&') for a in args] # Remove `allow_stderr_error`, `allow_stderr_warning` and # `allow_error` before calling run() because PipTestEnvironment # doesn't support them. allow_stderr_error = kw.pop('allow_stderr_error', None) allow_stderr_warning = kw.pop('allow_stderr_warning', None) allow_error = kw.pop('allow_error', None) if allow_error: kw['expect_error'] = True # Propagate default values. expect_error = kw.get('expect_error') if expect_error: # Then default to allowing logged errors. if allow_stderr_error is not None and not allow_stderr_error: raise RuntimeError('cannot pass allow_stderr_error=False with ' 'expect_error=True') allow_stderr_error = True elif kw.get('expect_stderr'): # Then default to allowing logged warnings. if allow_stderr_warning is not None and not allow_stderr_warning: raise RuntimeError( 'cannot pass allow_stderr_warning=False with ' 'expect_stderr=True') allow_stderr_warning = True if allow_stderr_error: if allow_stderr_warning is not None and not allow_stderr_warning: raise RuntimeError( 'cannot pass allow_stderr_warning=False with ' 'allow_stderr_error=True') # Default values if not set. if allow_stderr_error is None: allow_stderr_error = False if allow_stderr_warning is None: allow_stderr_warning = allow_stderr_error # Pass expect_stderr=True to allow any stderr. We do this because # we do our checking of stderr further on in check_stderr(). kw['expect_stderr'] = True result = super(PipTestEnvironment, self).run(cwd=cwd, *args, **kw) if expect_error and not allow_error: if result.returncode == 0: __tracebackhide__ = True raise AssertionError("Script passed unexpectedly.") _check_stderr( result.stderr, allow_stderr_error=allow_stderr_error, allow_stderr_warning=allow_stderr_warning, ) return TestPipResult(result, verbose=self.verbose) def pip(self, *args, **kwargs): __tracebackhide__ = True if self.pip_expect_warning: kwargs['allow_stderr_warning'] = True if kwargs.pop('use_module', True): exe = 'python' args = ('-m', 'pip') + args else: exe = 'pip' return self.run(exe, *args, **kwargs) def pip_install_local(self, *args, **kwargs): return self.pip("install", "--no-index", "--find-links", path_to_url(os.path.join(DATA_DIR, "packages")), *args, **kwargs) def easy_install(self, *args, **kwargs): args = ('-m', 'easy_install') + args return self.run('python', *args, **kwargs)
class PipTestEnvironment(scripttest.TestFileEnvironment): """ A specialized TestFileEnvironment for testing pip """ # # Attribute naming convention # --------------------------- # # Instances of this class have many attributes representing paths # in the filesystem. To keep things straight, absolute paths have # a name of the form xxxx_path and relative paths have a name that # does not end in '_path'. exe = sys.platform == 'win32' and '.exe' or '' verbose = False def __init__(self, base_path, *args, **kwargs): # Make our base_path a test.lib.path.Path object base_path = Path(base_path) # Store paths related to the virtual environment _virtualenv = kwargs.pop("virtualenv") path_locations = virtualenv.path_locations(_virtualenv) # Make sure we have test.lib.path.Path objects venv, lib, include, bin = map(Path, path_locations) self.venv_path = venv self.lib_path = virtualenv_lib_path(venv, lib) self.include_path = include self.bin_path = bin if hasattr(sys, "pypy_version_info"): self.site_packages_path = self.venv_path.join("site-packages") else: self.site_packages_path = self.lib_path.join("site-packages") self.user_base_path = self.venv_path.join("user") self.user_site_path = self.venv_path.join( "user", site.USER_SITE[len(site.USER_BASE) + 1:], ) if sys.platform == 'win32': if sys.version_info >= (3, 5): scripts_base = self.user_site_path.join('..').normpath else: scripts_base = self.user_base_path self.user_bin_path = scripts_base.join('Scripts') else: self.user_bin_path = self.user_base_path.join(self.bin_path - self.venv_path) # Create a Directory to use as a scratch pad self.scratch_path = base_path.join("scratch").mkdir() # Set our default working directory kwargs.setdefault("cwd", self.scratch_path) # Setup our environment environ = kwargs.get("environ") if environ is None: environ = os.environ.copy() environ["PATH"] = Path.pathsep.join([self.bin_path] + [environ.get("PATH", [])], ) environ["PYTHONUSERBASE"] = self.user_base_path # Writing bytecode can mess up updated file detection environ["PYTHONDONTWRITEBYTECODE"] = "1" # Make sure we get UTF-8 on output, even on Windows... environ["PYTHONIOENCODING"] = "UTF-8" kwargs["environ"] = environ # Call the TestFileEnvironment __init__ super(PipTestEnvironment, self).__init__(base_path, *args, **kwargs) # Expand our absolute path directories into relative for name in [ "base", "venv", "lib", "include", "bin", "site_packages", "user_base", "user_site", "user_bin", "scratch" ]: real_name = "%s_path" % name setattr(self, name, getattr(self, real_name) - self.base_path) # Make sure temp_path is a Path object self.temp_path = Path(self.temp_path) # Ensure the tmp dir exists, things break horribly if it doesn't self.temp_path.mkdir() # create easy-install.pth in user_site, so we always have it updated # instead of created self.user_site_path.makedirs() self.user_site_path.join("easy-install.pth").touch() def _ignore_file(self, fn): if fn.endswith('__pycache__') or fn.endswith(".pyc"): result = True else: result = super(PipTestEnvironment, self)._ignore_file(fn) return result def run(self, *args, **kw): if self.verbose: print('>> running %s %s' % (args, kw)) cwd = kw.pop('cwd', None) run_from = kw.pop('run_from', None) assert not cwd or not run_from, "Don't use run_from; it's going away" cwd = cwd or run_from or self.cwd if sys.platform == 'win32': # Partial fix for ScriptTest.run using `shell=True` on Windows. args = [str(a).replace('^', '^^').replace('&', '^&') for a in args] return TestPipResult( super(PipTestEnvironment, self).run(cwd=cwd, *args, **kw), verbose=self.verbose, ) def pip(self, *args, **kwargs): # On old versions of Python, urllib3/requests will raise a warning # about the lack of an SSLContext. Expect it when running commands # that will touch the outside world. if (pyversion_tuple < (2, 7, 9) and args and args[0] in ('search', 'install', 'download')): kwargs['expect_stderr'] = True # Python 3.3 is deprecated and we emit a warning on it. if pyversion_tuple[:2] == (3, 3): kwargs['expect_stderr'] = True if kwargs.pop('use_module', False): exe = 'python' args = ('-m', 'pip') + args else: exe = 'pip' return self.run(exe, *args, **kwargs) def pip_install_local(self, *args, **kwargs): return self.pip("install", "--no-index", "--find-links", path_to_url(os.path.join(DATA_DIR, "packages")), *args, **kwargs)
class PipTestEnvironment(scripttest.TestFileEnvironment): """ A specialized TestFileEnvironment for testing pip """ # # Attribute naming convention # --------------------------- # # Instances of this class have many attributes representing paths # in the filesystem. To keep things straight, absolute paths have # a name of the form xxxx_path and relative paths have a name that # does not end in '_path'. exe = sys.platform == 'win32' and '.exe' or '' verbose = False def __init__(self, base_path, *args, **kwargs): # Make our base_path a test.lib.path.Path object base_path = Path(base_path) # Store paths related to the virtual environment _virtualenv = kwargs.pop("virtualenv") venv, lib, include, bin = virtualenv.path_locations(_virtualenv) # workaround for https://github.com/pypa/virtualenv/issues/306 if hasattr(sys, "pypy_version_info"): lib = os.path.join(venv, 'lib-python', pyversion) self.venv_path = venv self.lib_path = lib self.include_path = include self.bin_path = bin if hasattr(sys, "pypy_version_info"): self.site_packages_path = self.venv_path.join("site-packages") else: self.site_packages_path = self.lib_path.join("site-packages") self.user_base_path = self.venv_path.join("user") self.user_bin_path = self.user_base_path.join( self.bin_path - self.venv_path ) self.user_site_path = self.venv_path.join( "user", site.USER_SITE[len(site.USER_BASE) + 1:], ) # Create a Directory to use as a scratch pad self.scratch_path = base_path.join("scratch").mkdir() # Set our default working directory kwargs.setdefault("cwd", self.scratch_path) # Setup our environment environ = kwargs.get("environ") if environ is None: environ = os.environ.copy() environ["PIP_LOG_FILE"] = base_path.join("pip-log.txt") environ["PATH"] = Path.pathsep.join( [self.bin_path] + [environ.get("PATH", [])], ) environ["PYTHONUSERBASE"] = self.user_base_path # Writing bytecode can mess up updated file detection environ["PYTHONDONTWRITEBYTECODE"] = "1" kwargs["environ"] = environ # Call the TestFileEnvironment __init__ super(PipTestEnvironment, self).__init__(base_path, *args, **kwargs) # Expand our absolute path directories into relative for name in ["base", "venv", "lib", "include", "bin", "site_packages", "user_base", "user_site", "user_bin", "scratch"]: real_name = "%s_path" % name setattr(self, name, getattr(self, real_name) - self.base_path) # Make sure temp_path is a Path object self.temp_path = Path(self.temp_path) # Ensure the tmp dir exists, things break horribly if it doesn't self.temp_path.mkdir() # create easy-install.pth in user_site, so we always have it updated # instead of created self.user_site_path.makedirs() self.user_site_path.join("easy-install.pth").touch() def _ignore_file(self, fn): if fn.endswith('__pycache__') or fn.endswith(".pyc"): result = True else: result = super(PipTestEnvironment, self)._ignore_file(fn) return result def run(self, *args, **kw): if self.verbose: print('>> running %s %s' % (args, kw)) cwd = kw.pop('cwd', None) run_from = kw.pop('run_from', None) assert not cwd or not run_from, "Don't use run_from; it's going away" cwd = cwd or run_from or self.cwd return TestPipResult( super(PipTestEnvironment, self).run(cwd=cwd, *args, **kw), verbose=self.verbose, ) def pip(self, *args, **kwargs): return self.run("pip", *args, **kwargs) def pip_install_local(self, *args, **kwargs): return self.pip( "install", "--no-index", "--find-links", path_to_url(os.path.join(DATA_DIR, "packages")), *args, **kwargs )