Merge branch 'master' into typeshed

This commit is contained in:
Dave Halter
2018-08-04 23:42:17 +02:00
23 changed files with 210 additions and 140 deletions

View File

@@ -8,7 +8,6 @@ python:
env:
- JEDI_TEST_ENVIRONMENT=27
- JEDI_TEST_ENVIRONMENT=33
- JEDI_TEST_ENVIRONMENT=34
- JEDI_TEST_ENVIRONMENT=35
- JEDI_TEST_ENVIRONMENT=36
@@ -39,7 +38,6 @@ before_install:
- ./travis_install.sh
# Need to add the path to the Python versions in the end. This might add
# something twice, but it doesn't really matter, because they are appended.
- export PATH=$PATH:/opt/python/3.3/bin
- export PATH=$PATH:/opt/python/3.5/bin
# 3.6 was not installed manually, but already is on the system. However
# it's not on path (unless 3.6 is selected).

View File

@@ -3,9 +3,11 @@
Changelog
---------
0.12.2 ()
0.13.0 ()
+++++++++++++++++++
- Remove Python 3.3 support. Python 3.3 support has been dropped by the Python
foundation.
- Added ``include_builtins`` as a parameter to usages.
- ``goto_assignments`` has a new ``follow_builtin_imports`` parameter that
changes the previous behavior slightly.

View File

@@ -111,8 +111,8 @@ understands, see: `Features
<https://jedi.readthedocs.org/en/latest/docs/features.html>`_. A list of
caveats can be found on the same page.
You can run Jedi on CPython 2.7 or 3.3+ but it should also
understand/parse code older than those versions. Additonally you should be able
You can run Jedi on CPython 2.7 or 3.4+ but it should also
understand/parse code older than those versions. Additionally you should be able
to use `Virtualenvs <https://jedi.readthedocs.org/en/latest/docs/api.html#environments>`_
very well.

View File

@@ -3,9 +3,6 @@ environment:
- TOXENV: py27
PYTHON_PATH: C:\Python27
JEDI_TEST_ENVIRONMENT: 27
- TOXENV: py27
PYTHON_PATH: C:\Python27
JEDI_TEST_ENVIRONMENT: 33
- TOXENV: py27
PYTHON_PATH: C:\Python27
JEDI_TEST_ENVIRONMENT: 34
@@ -19,9 +16,6 @@ environment:
- TOXENV: py34
PYTHON_PATH: C:\Python34
JEDI_TEST_ENVIRONMENT: 27
- TOXENV: py34
PYTHON_PATH: C:\Python34
JEDI_TEST_ENVIRONMENT: 33
- TOXENV: py34
PYTHON_PATH: C:\Python34
JEDI_TEST_ENVIRONMENT: 34
@@ -35,9 +29,6 @@ environment:
- TOXENV: py35
PYTHON_PATH: C:\Python35
JEDI_TEST_ENVIRONMENT: 27
- TOXENV: py35
PYTHON_PATH: C:\Python35
JEDI_TEST_ENVIRONMENT: 33
- TOXENV: py35
PYTHON_PATH: C:\Python35
JEDI_TEST_ENVIRONMENT: 34
@@ -51,9 +42,6 @@ environment:
- TOXENV: py36
PYTHON_PATH: C:\Python36
JEDI_TEST_ENVIRONMENT: 27
- TOXENV: py36
PYTHON_PATH: C:\Python36
JEDI_TEST_ENVIRONMENT: 33
- TOXENV: py36
PYTHON_PATH: C:\Python36
JEDI_TEST_ENVIRONMENT: 34

View File

@@ -6,8 +6,7 @@ from functools import partial
import pytest
import jedi
from jedi.api.environment import get_default_environment, \
get_system_environment, InterpreterEnvironment
from jedi.api.environment import get_system_environment, InterpreterEnvironment
from jedi._compatibility import py_version
collect_ignore = [
@@ -98,9 +97,6 @@ def environment(request):
if version is None:
version = os.environ.get('JEDI_TEST_ENVIRONMENT', str(py_version))
if int(version) == py_version:
return get_default_environment()
return get_system_environment(version[0] + '.' + version[1:])

View File

@@ -20,7 +20,7 @@ make it work.
General Features
----------------
- Python 2.7 and 3.3+ support
- Python 2.7 and 3.4+ support
- Ignores syntax errors and wrong indentation
- Can deal with complex module / function / class structures
- Great Virtualenv support

View File

@@ -16,8 +16,6 @@ except ImportError:
pass
is_py3 = sys.version_info[0] >= 3
is_py33 = is_py3 and sys.version_info[1] >= 3
is_py34 = is_py3 and sys.version_info[1] >= 4
is_py35 = is_py3 and sys.version_info[1] >= 5
py_version = int(str(sys.version_info[0]) + str(sys.version_info[1]))
@@ -116,7 +114,7 @@ def find_module_py33(string, path=None, loader=None, full_name=None, is_global_s
return module_file, module_path, is_package
def find_module_pre_py33(string, path=None, full_name=None, is_global_search=True):
def find_module_pre_py34(string, path=None, full_name=None, is_global_search=True):
# This import is here, because in other places it will raise a
# DeprecationWarning.
import imp
@@ -151,8 +149,7 @@ def find_module_pre_py33(string, path=None, full_name=None, is_global_search=Tru
raise ImportError("No module named {}".format(string))
find_module = find_module_py33 if is_py33 else find_module_pre_py33
find_module = find_module_py34 if is_py34 else find_module
find_module = find_module_py34 if is_py3 else find_module_pre_py34
find_module.__doc__ = """
Provides information about a module.
@@ -369,6 +366,7 @@ def print_to_stderr(*args):
eval("print(*args, file=sys.stderr)")
else:
print >> sys.stderr, args
sys.stderr.flush()
def utf8_repr(func):
@@ -521,6 +519,9 @@ class GeneralizedPopen(subprocess.Popen):
except AttributeError:
CREATE_NO_WINDOW = 0x08000000
kwargs['creationflags'] = CREATE_NO_WINDOW
# The child process doesn't need file descriptors except 0, 1, 2.
# This is unix only.
kwargs['close_fds'] = 'posix' in sys.builtin_module_names
super(GeneralizedPopen, self).__init__(*args, **kwargs)

View File

@@ -5,7 +5,7 @@ from textwrap import dedent
import operator as op
from collections import namedtuple
from jedi._compatibility import unicode, is_py3, is_py34, builtins, \
from jedi._compatibility import unicode, is_py3, builtins, \
py_version, force_unicode, print_to_stderr
from jedi.evaluate.compiled.getattr_static import getattr_static
@@ -31,10 +31,9 @@ NOT_CLASS_TYPES = (
if is_py3:
NOT_CLASS_TYPES += (
types.MappingProxyType,
types.SimpleNamespace
types.SimpleNamespace,
types.DynamicClassAttribute,
)
if is_py34:
NOT_CLASS_TYPES += (types.DynamicClassAttribute,)
# Those types don't exist in typing.
@@ -141,7 +140,7 @@ def load_module(evaluator, dotted_name, sys_path):
__import__(dotted_name)
except ImportError:
# If a module is "corrupt" or not really a Python module or whatever.
print_to_stderr('Module %s not importable.' % dotted_name)
print_to_stderr('Module %s not importable in path %s.' % (dotted_name, sys_path))
return None
except Exception:
# Since __import__ pretty much makes code execution possible, just

View File

@@ -447,8 +447,11 @@ def create_from_name(evaluator, compiled_object, name):
pass
access = compiled_object.access_handle.getattr(name, default=None)
parent_context = compiled_object
if parent_context.is_class():
parent_context = parent_context.parent_context
return create_cached_compiled_object(
evaluator, access, parent_context=compiled_object, faked=faked
evaluator, access, parent_context=parent_context, faked=faked
)

View File

@@ -15,9 +15,15 @@ import errno
import weakref
import traceback
from functools import partial
from threading import Thread
try:
from queue import Queue, Empty
except ImportError:
from Queue import Queue, Empty # python 2.7
from jedi._compatibility import queue, is_py3, force_unicode, \
pickle_dump, pickle_load, GeneralizedPopen
from jedi import debug
from jedi.cache import memoize_method
from jedi.evaluate.compiled.subprocess import functions
from jedi.evaluate.compiled.access import DirectObjectAccess, AccessPath, \
@@ -28,6 +34,12 @@ from jedi.api.exceptions import InternalError
_MAIN_PATH = os.path.join(os.path.dirname(__file__), '__main__.py')
def _enqueue_output(out, queue):
for line in iter(out.readline, b''):
queue.put(line)
out.close()
def _get_function(name):
return getattr(functions, name)
@@ -135,6 +147,7 @@ class CompiledSubprocess(object):
@property
@memoize_method
def _process(self):
debug.dbg('Start environment subprocess %s', self._executable)
parso_path = sys.modules['parso'].__file__
args = (
self._executable,
@@ -142,7 +155,7 @@ class CompiledSubprocess(object):
os.path.dirname(os.path.dirname(parso_path)),
'.'.join(str(x) for x in sys.version_info[:3]),
)
return GeneralizedPopen(
process = GeneralizedPopen(
args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
@@ -151,6 +164,14 @@ class CompiledSubprocess(object):
# (this is already the case on Python 3).
bufsize=-1
)
self._stderr_queue = Queue()
self._stderr_thread = t = Thread(
target=_enqueue_output,
args=(process.stderr, self._stderr_queue)
)
t.daemon = True
t.start()
return process
def run(self, evaluator, function, args=(), kwargs={}):
# Delete old evaluators.
@@ -219,6 +240,16 @@ class CompiledSubprocess(object):
stderr,
))
while True:
# Try to do some error reporting from the subprocess and print its
# stderr contents.
try:
line = self._stderr_queue.get_nowait()
line = line.decode('utf-8', 'replace')
debug.warning('stderr output: %s' % line.rstrip('\n'))
except Empty:
break
if is_exception:
# Replace the attribute error message with a the traceback. It's
# way more informative.
@@ -282,11 +313,9 @@ class Listener(object):
def listen(self):
stdout = sys.stdout
# Mute stdout/stderr. Nobody should actually be able to write to those,
# because stdout is used for IPC and stderr will just be annoying if it
# leaks (on module imports).
# Mute stdout. Nobody should actually be able to write to it,
# because stdout is used for IPC.
sys.stdout = open(os.devnull, 'w')
sys.stderr = open(os.devnull, 'w')
stdin = sys.stdin
if sys.version_info[0] > 2:
stdout = stdout.buffer

View File

@@ -11,7 +11,7 @@ from jedi.evaluate.arguments import AbstractArguments, AnonymousArguments
from jedi.cache import memoize_method
from jedi.evaluate.context.function import FunctionExecutionContext, \
FunctionContext, AbstractFunction
from jedi.evaluate.context.klass import ClassContext, apply_py__get__
from jedi.evaluate.context.klass import ClassContext, apply_py__get__, ClassFilter
from jedi.evaluate.context import iterable
from jedi.parser_utils import get_parent_scope
@@ -87,7 +87,7 @@ class AbstractInstanceContext(Context):
def execute_function_slots(self, names, *evaluated_args):
return ContextSet.from_sets(
name.execute_evaluated(*evaluated_args)
name.infer().execute_evaluated(*evaluated_args)
for name in names
)
@@ -169,7 +169,7 @@ class AbstractInstanceContext(Context):
def create_init_executions(self):
for name in self.get_function_slot_names(u'__init__'):
if isinstance(name, SelfName):
if isinstance(name, LazyInstanceClassName):
function = FunctionContext.from_context(
self.parent_context,
name.tree_name.parent
@@ -265,17 +265,23 @@ class AnonymousInstance(TreeInstance):
class CompiledInstanceName(compiled.CompiledName):
def __init__(self, evaluator, instance, parent_context, name):
super(CompiledInstanceName, self).__init__(evaluator, parent_context, name)
def __init__(self, evaluator, instance, klass, name):
super(CompiledInstanceName, self).__init__(
evaluator,
klass.parent_context,
name.string_name
)
self._instance = instance
self._class = klass
self._class_member_name = name
@iterator_to_context_set
def infer(self):
for result_context in super(CompiledInstanceName, self).infer():
for result_context in self._class_member_name.infer():
is_function = result_context.api_type == 'function'
if result_context.tree_node is not None and is_function:
yield BoundMethod(self._instance, self.parent_context, result_context)
yield BoundMethod(self._instance, self._class, result_context)
else:
if is_function:
yield CompiledBoundMethod(result_context)
@@ -283,20 +289,26 @@ class CompiledInstanceName(compiled.CompiledName):
yield result_context
class CompiledInstanceClassFilter(compiled.CompiledObjectFilter):
class CompiledInstanceClassFilter(filters.AbstractFilter):
name_class = CompiledInstanceName
def __init__(self, evaluator, instance, compiled_object):
super(CompiledInstanceClassFilter, self).__init__(
evaluator,
compiled_object,
is_instance=True,
)
def __init__(self, evaluator, instance, klass):
self._evaluator = evaluator
self._instance = instance
self._class = klass
self._class_filter = next(klass.get_filters(is_instance=True))
def _create_name(self, name):
return self.name_class(
self._evaluator, self._instance, self._compiled_object, name)
def get(self, name):
return self._convert(self._class_filter.get(name))
def values(self):
return self._convert(self._class_filter.values())
def _convert(self, names):
return [
CompiledInstanceName(self._evaluator, self._instance, self._class, n)
for n in names
]
class BoundMethod(AbstractFunction):
@@ -332,11 +344,6 @@ class CompiledBoundMethod(compiled.CompiledObject):
return list(super(CompiledBoundMethod, self).get_param_names())[1:]
class InstanceNameDefinition(filters.TreeNameDefinition):
def infer(self):
return super(InstanceNameDefinition, self).infer()
class SelfName(filters.TreeNameDefinition):
"""
This name calculates the parent_context lazily.
@@ -351,10 +358,15 @@ class SelfName(filters.TreeNameDefinition):
return self._instance.create_instance_context(self.class_context, self.tree_name)
class LazyInstanceClassName(SelfName):
class LazyInstanceClassName(object):
def __init__(self, instance, class_context, class_member_name):
self._instance = instance
self.class_context = class_context
self._class_member_name = class_member_name
@iterator_to_context_set
def infer(self):
for result_context in super(LazyInstanceClassName, self).infer():
for result_context in self._class_member_name.infer():
if isinstance(result_context, FunctionContext):
# Classes are never used to resolve anything within the
# functions. Only other functions and modules will resolve
@@ -364,45 +376,51 @@ class LazyInstanceClassName(SelfName):
for c in apply_py__get__(result_context, self._instance):
yield c
def __getattr__(self, name):
return getattr(self._class_member_name, name)
class InstanceClassFilter(filters.ParserTreeFilter):
name_class = LazyInstanceClassName
class InstanceClassFilter(filters.AbstractFilter):
"""
This filter is special in that it uses the class filter and wraps the
resulting names in LazyINstanceClassName. The idea is that the class name
filtering can be very flexible and always be reflected in instances.
"""
def __init__(self, evaluator, context, class_context, origin_scope):
super(InstanceClassFilter, self).__init__(
evaluator=evaluator,
context=context,
node_context=class_context,
origin_scope=origin_scope
)
self._instance = context
self._class_context = class_context
self._class_filter = next(class_context.get_filters(
search_global=False,
origin_scope=origin_scope,
is_instance=True,
))
def _equals_origin_scope(self):
node = self._origin_scope
while node is not None:
if node == self._parser_scope or node == self.context:
return True
node = get_parent_scope(node)
return False
def get(self, name):
return self._convert(self._class_filter.get(name))
def _access_possible(self, name):
return not name.value.startswith('__') or name.value.endswith('__') \
or self._equals_origin_scope()
def values(self):
return self._convert(self._class_filter.values())
def _filter(self, names):
names = super(InstanceClassFilter, self)._filter(names)
return [name for name in names if self._access_possible(name)]
def _convert_names(self, names):
return [self.name_class(self.context, self._class_context, name) for name in names]
def _convert(self, names):
return [LazyInstanceClassName(self._instance, self._class_context, n) for n in names]
class SelfAttributeFilter(InstanceClassFilter):
class SelfAttributeFilter(ClassFilter):
"""
This class basically filters all the use cases where `self.*` was assigned.
"""
name_class = SelfName
def __init__(self, evaluator, context, class_context, origin_scope):
super(SelfAttributeFilter, self).__init__(
evaluator=evaluator,
context=context,
node_context=class_context,
origin_scope=origin_scope,
is_instance=True,
)
self._class_context = class_context
def _filter(self, names):
names = self._filter_self_names(names)
if isinstance(self._parser_scope, compiled.CompiledObject) and False:
@@ -421,6 +439,9 @@ class SelfAttributeFilter(InstanceClassFilter):
if name.is_definition() and self._access_possible(name):
yield name
def _convert_names(self, names):
return [self.name_class(self.context, self._class_context, name) for name in names]
def _check_flows(self, names):
return names

View File

@@ -38,6 +38,7 @@ py__doc__(include_call_signature: Returns the docstring for a context.
"""
from jedi._compatibility import use_metaclass
from jedi.parser_utils import get_parent_scope
from jedi.evaluate.cache import evaluator_method_cache, CachedMetaClass
from jedi.evaluate import compiled
from jedi.evaluate.lazy_context import LazyKnownContext
@@ -58,9 +59,10 @@ def apply_py__get__(context, base_context):
class ClassName(TreeNameDefinition):
def __init__(self, parent_context, tree_name, name_context):
def __init__(self, parent_context, tree_name, name_context, apply_decorators):
super(ClassName, self).__init__(parent_context, tree_name)
self._name_context = name_context
self._apply_decorators = apply_decorators
@iterator_to_context_set
def infer(self):
@@ -70,16 +72,45 @@ class ClassName(TreeNameDefinition):
self.parent_context.evaluator, self._name_context, self.tree_name)
for result_context in inferred:
for c in apply_py__get__(result_context, self.parent_context):
yield c
if self._apply_decorators:
for c in apply_py__get__(result_context, self.parent_context):
yield c
else:
yield result_context
class ClassFilter(ParserTreeFilter):
name_class = ClassName
def __init__(self, *args, **kwargs):
self._is_instance = kwargs.pop('is_instance') # Python 2 :/
super(ClassFilter, self).__init__(*args, **kwargs)
def _convert_names(self, names):
return [self.name_class(self.context, name, self._node_context)
for name in names]
return [
self.name_class(
parent_context=self.context,
tree_name=name,
name_context=self._node_context,
apply_decorators=not self._is_instance,
) for name in names
]
def _equals_origin_scope(self):
node = self._origin_scope
while node is not None:
if node == self._parser_scope or node == self.context:
return True
node = get_parent_scope(node)
return False
def _access_possible(self, name):
return not name.value.startswith('__') or name.value.endswith('__') \
or self._equals_origin_scope()
def _filter(self, names):
names = super(ClassFilter, self)._filter(names)
return [name for name in names if self._access_possible(name)]
class ClassContext(use_metaclass(CachedMetaClass, TreeContext)):
@@ -163,7 +194,9 @@ class ClassContext(use_metaclass(CachedMetaClass, TreeContext)):
else:
yield ClassFilter(
self.evaluator, self, node_context=cls,
origin_scope=origin_scope)
origin_scope=origin_scope,
is_instance=is_instance
)
def is_class(self):
return True

View File

@@ -38,12 +38,6 @@ class AbstractNameDefinition(object):
return '<%s: %s>' % (self.__class__.__name__, self.string_name)
return '<%s: %s@%s>' % (self.__class__.__name__, self.string_name, self.start_pos)
def execute(self, arguments):
return self.infer().execute(arguments)
def execute_evaluated(self, *args, **kwargs):
return self.infer().execute_evaluated(*args, **kwargs)
def is_import(self):
return False

View File

@@ -29,7 +29,7 @@ setup(name='jedi',
keywords='python completion refactoring vim',
long_description=readme,
packages=find_packages(exclude=['test', 'test.*']),
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*',
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
install_requires=install_requires,
extras_require={'dev': ['docopt']},
package_data={'jedi': ['evaluate/compiled/fake/*.pym']},
@@ -43,7 +43,6 @@ setup(name='jedi',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',

View File

@@ -437,7 +437,7 @@ def test_func():
#? int()
tuple({1})[0]
# python >= 3.3
# python >= 3.4
# -----------------
# PEP 3132 Extended Iterable Unpacking (star unpacking)
# -----------------

View File

@@ -417,6 +417,9 @@ class PrivateVar():
def __private_func(self):
return 1
#? int()
__private_func()
def wrap_private(self):
return self.__private_func()
#? []
@@ -425,6 +428,8 @@ PrivateVar().__var
PrivateVar().__var
#? []
PrivateVar().__private_func
#? []
PrivateVar.__private_func
#? int()
PrivateVar().wrap_private()

View File

@@ -220,7 +220,7 @@ def x():
# yield from
# -----------------
# python >= 3.3
# python >= 3.4
def yield_from():
yield from iter([1])

View File

@@ -1,6 +1,6 @@
""" Pep-0484 type hinting """
# python >= 3.2
# python >= 3.4
class A():

View File

@@ -243,7 +243,7 @@ for key in x.keys():
for value in x.values():
#? int()
value
# python >= 3.2
# python >= 3.4
class TestDefaultDict(typing.DefaultDict[str, int]):
def setdud(self):
@@ -271,7 +271,7 @@ for key in x.keys():
for value in x.values():
#? int()
value
# python >= 3.2
# python >= 3.4
"""

View File

@@ -6,7 +6,7 @@ import pytest
from ..helpers import TestCase
from jedi import cache
from jedi._compatibility import is_py33
from jedi._compatibility import is_py3
def assert_signature(Script, source, expected_name, expected_index=0, line=None, column=None):
@@ -247,7 +247,7 @@ def _params(Script, source, line=None, column=None):
def test_param_name(Script):
if not is_py33:
if not is_py3:
p = _params(Script, '''int(''')
# int is defined as: `int(x[, base])`
assert p[0].name == 'x'

View File

@@ -10,8 +10,10 @@ import os
import shutil
import sys
import pytest
import jedi
from ..helpers import cwd_at
from jedi.api.environment import SameEnvironment
SRC = """class Foo:
@@ -22,35 +24,44 @@ class Bar:
"""
def generate_pyc():
os.mkdir("dummy_package")
with open("dummy_package/__init__.py", 'w'):
@pytest.fixture
def pyc_project_path(tmpdir):
path = tmpdir.strpath
dummy_package_path = os.path.join(path, "dummy_package")
os.mkdir(dummy_package_path)
with open(os.path.join(dummy_package_path, "__init__.py"), 'w'):
pass
with open("dummy_package/dummy.py", 'w') as f:
dummy_path = os.path.join(dummy_package_path, 'dummy.py')
with open(dummy_path, 'w') as f:
f.write(SRC)
import compileall
compileall.compile_file("dummy_package/dummy.py")
os.remove("dummy_package/dummy.py")
compileall.compile_file(dummy_path)
os.remove(dummy_path)
if sys.version_info[0] == 3:
if sys.version_info.major == 3:
# Python3 specific:
# To import pyc modules, we must move them out of the __pycache__
# directory and rename them to remove ".cpython-%s%d"
# see: http://stackoverflow.com/questions/11648440/python-does-not-detect-pyc-files
for f in os.listdir("dummy_package/__pycache__"):
pycache = os.path.join(dummy_package_path, "__pycache__")
for f in os.listdir(pycache):
dst = f.replace('.cpython-%s%s' % sys.version_info[:2], "")
dst = os.path.join("dummy_package", dst)
shutil.copy(os.path.join("dummy_package/__pycache__", f), dst)
dst = os.path.join(dummy_package_path, dst)
shutil.copy(os.path.join(pycache, f), dst)
try:
yield path
finally:
shutil.rmtree(path)
@cwd_at('test/test_evaluate')
def test_pyc(Script):
def test_pyc(pyc_project_path):
"""
The list of completion must be greater than 2.
"""
try:
generate_pyc()
s = jedi.Script("from dummy_package import dummy; dummy.", path='blub.py')
assert len(s.completions()) >= 2
finally:
shutil.rmtree("dummy_package")
path = os.path.join(pyc_project_path, 'blub.py')
s = jedi.Script(
"from dummy_package import dummy; dummy.",
path=path,
environment=SameEnvironment())
assert len(s.completions()) >= 2

View File

@@ -1,8 +1,8 @@
[tox]
envlist = py27, py33, py34, py35, py36
envlist = py27, py34, py35, py36
[testenv]
deps =
pytest>=2.3.5, < 3.3
pytest>=2.3.5
pytest-cache
# docopt for sith doctests
docopt
@@ -19,7 +19,6 @@ setenv =
# To test Jedi in different versions than the same Python version, set a
# different test environment.
env27: JEDI_TEST_ENVIRONMENT=27
env33: JEDI_TEST_ENVIRONMENT=33
env34: JEDI_TEST_ENVIRONMENT=34
env35: JEDI_TEST_ENVIRONMENT=35
env36: JEDI_TEST_ENVIRONMENT=36
@@ -33,10 +32,6 @@ deps =
# numpydoc for typing scipy stack
numpydoc
{[testenv]deps}
[testenv:py33]
deps =
typing
{[testenv]deps}
[testenv:py34]
deps =
typing

View File

@@ -8,10 +8,6 @@ set -e
sudo chown root: /opt/python/3.6/bin/python
sudo chown root: /opt/python/3.6.3/bin/python
if [[ $JEDI_TEST_ENVIRONMENT == "33" ]]; then
VERSION=3.3
DOWNLOAD=1
fi
if [[ $JEDI_TEST_ENVIRONMENT == "35" ]]; then
VERSION=3.5
DOWNLOAD=1