Better tests for venvs

This commit is contained in:
Dave Halter
2018-04-09 01:28:43 +02:00
parent 81d8c49119
commit f4c14864a5
2 changed files with 37 additions and 19 deletions

View File

@@ -31,8 +31,8 @@ class _BaseEnvironment(object):
class Environment(_BaseEnvironment):
def __init__(self, path, executable):
self._base_path = path
self._executable = executable
self._base_path = os.path.abspath(path)
self._executable = os.path.abspath(executable)
self.version_info = self._get_version()
def _get_version(self):
@@ -50,7 +50,7 @@ class Environment(_BaseEnvironment):
output = stdout + stderr
match = re.match(br'Python (\d+)\.(\d+)\.(\d+)', output)
if match is None:
raise InvalidPythonEnvironment()
raise InvalidPythonEnvironment("--version not working")
return _VersionInfo(*[int(m) for m in match.groups()])
@@ -107,7 +107,7 @@ def _get_virtual_env_from_var():
def get_default_environment():
"""
Tries to return an active VirtualEnv. If there is no VIRTUAL_ENV variable
Tries to return an active Virtualenv. If there is no VIRTUAL_ENV variable
set it will return the latest Python version installed on the system. This
makes it possible to use as many new Python features as possible when using
autocompletion and other functionality.
@@ -122,9 +122,10 @@ def get_default_environment():
def find_virtualenvs(paths=None, **kwargs):
"""
:param paths: A list of paths in your file system that this function will
use to search virtual env's. It will exclusively search in these paths
and potentially execute the Python binaries on these paths.
:param paths: A list of paths in your file system to be scanned for
Virtualenvs. It will search in these paths and potentially execute the
Python binaries. Also the VIRTUAL_ENV variable will be checked if it
contains a valid Virtualenv.
:param safe: Default True. In case this is False, it will allow this
function to execute potential `python` environments. An attacker might
be able to drop an executable in a path this function is searching by
@@ -137,12 +138,20 @@ def find_virtualenvs(paths=None, **kwargs):
_used_paths = set()
# Using this variable should be safe, because attackers might be able
# to drop files (via git) but not environment variables.
virtual_env = _get_virtual_env_from_var()
if virtual_env is not None:
yield virtual_env
_used_paths.add(virtual_env._base_path)
for path in paths:
for directory in paths:
if not os.path.isdir(directory):
continue
directory = os.path.abspath(directory)
for path in os.listdir(directory):
path = os.path.join(directory, path)
if path in _used_paths:
# A path shouldn't be evaluated twice.
continue

View File

@@ -1,12 +1,13 @@
import os
from contextlib import contextmanager
from distutils.spawn import find_executable
import pytest
import jedi
from jedi._compatibility import py_version
from jedi.api.environment import Environment, get_default_environment, \
InvalidPythonEnvironment, find_python_environments
InvalidPythonEnvironment, find_python_environments, find_virtualenvs
def test_sys_path():
@@ -30,7 +31,10 @@ def test_find_python_environments():
['2.7', '3.3', '3.4', '3.5', '3.6', '3.7']
)
def test_versions(version):
executable = 'python' + version
executable_name = 'python' + version
executable = find_executable(executable_name)
if executable is None:
executable = executable_name
try:
env = Environment('some path', executable)
except InvalidPythonEnvironment:
@@ -40,7 +44,7 @@ def test_versions(version):
return
sys_path = env.get_sys_path()
assert any(executable in p for p in sys_path)
assert any(executable_name in p for p in sys_path)
def test_load_module(evaluator):
@@ -109,3 +113,8 @@ def test_not_existing_virtualenv():
def test_working_venv(venv_path):
with set_environment_variable('VIRTUAL_ENV', venv_path):
assert get_default_environment()._base_path == venv_path
def test_scanning_venvs(venv_path):
parent_dir = os.path.dirname(venv_path)
assert any(venv._base_path == venv_path for venv in find_virtualenvs([parent_dir]))