mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-07 14:34:31 +08:00
Merge branch 'master' into typeshed
This commit is contained in:
@@ -8,7 +8,6 @@ python:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
- JEDI_TEST_ENVIRONMENT=27
|
- JEDI_TEST_ENVIRONMENT=27
|
||||||
- JEDI_TEST_ENVIRONMENT=33
|
|
||||||
- JEDI_TEST_ENVIRONMENT=34
|
- JEDI_TEST_ENVIRONMENT=34
|
||||||
- JEDI_TEST_ENVIRONMENT=35
|
- JEDI_TEST_ENVIRONMENT=35
|
||||||
- JEDI_TEST_ENVIRONMENT=36
|
- JEDI_TEST_ENVIRONMENT=36
|
||||||
@@ -39,7 +38,6 @@ before_install:
|
|||||||
- ./travis_install.sh
|
- ./travis_install.sh
|
||||||
# Need to add the path to the Python versions in the end. This might add
|
# 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.
|
# 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
|
- export PATH=$PATH:/opt/python/3.5/bin
|
||||||
# 3.6 was not installed manually, but already is on the system. However
|
# 3.6 was not installed manually, but already is on the system. However
|
||||||
# it's not on path (unless 3.6 is selected).
|
# it's not on path (unless 3.6 is selected).
|
||||||
|
|||||||
@@ -3,9 +3,11 @@
|
|||||||
Changelog
|
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.
|
- Added ``include_builtins`` as a parameter to usages.
|
||||||
- ``goto_assignments`` has a new ``follow_builtin_imports`` parameter that
|
- ``goto_assignments`` has a new ``follow_builtin_imports`` parameter that
|
||||||
changes the previous behavior slightly.
|
changes the previous behavior slightly.
|
||||||
|
|||||||
@@ -111,8 +111,8 @@ understands, see: `Features
|
|||||||
<https://jedi.readthedocs.org/en/latest/docs/features.html>`_. A list of
|
<https://jedi.readthedocs.org/en/latest/docs/features.html>`_. A list of
|
||||||
caveats can be found on the same page.
|
caveats can be found on the same page.
|
||||||
|
|
||||||
You can run Jedi on CPython 2.7 or 3.3+ but it should also
|
You can run Jedi on CPython 2.7 or 3.4+ but it should also
|
||||||
understand/parse code older than those versions. Additonally you should be able
|
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>`_
|
to use `Virtualenvs <https://jedi.readthedocs.org/en/latest/docs/api.html#environments>`_
|
||||||
very well.
|
very well.
|
||||||
|
|
||||||
|
|||||||
12
appveyor.yml
12
appveyor.yml
@@ -3,9 +3,6 @@ environment:
|
|||||||
- TOXENV: py27
|
- TOXENV: py27
|
||||||
PYTHON_PATH: C:\Python27
|
PYTHON_PATH: C:\Python27
|
||||||
JEDI_TEST_ENVIRONMENT: 27
|
JEDI_TEST_ENVIRONMENT: 27
|
||||||
- TOXENV: py27
|
|
||||||
PYTHON_PATH: C:\Python27
|
|
||||||
JEDI_TEST_ENVIRONMENT: 33
|
|
||||||
- TOXENV: py27
|
- TOXENV: py27
|
||||||
PYTHON_PATH: C:\Python27
|
PYTHON_PATH: C:\Python27
|
||||||
JEDI_TEST_ENVIRONMENT: 34
|
JEDI_TEST_ENVIRONMENT: 34
|
||||||
@@ -19,9 +16,6 @@ environment:
|
|||||||
- TOXENV: py34
|
- TOXENV: py34
|
||||||
PYTHON_PATH: C:\Python34
|
PYTHON_PATH: C:\Python34
|
||||||
JEDI_TEST_ENVIRONMENT: 27
|
JEDI_TEST_ENVIRONMENT: 27
|
||||||
- TOXENV: py34
|
|
||||||
PYTHON_PATH: C:\Python34
|
|
||||||
JEDI_TEST_ENVIRONMENT: 33
|
|
||||||
- TOXENV: py34
|
- TOXENV: py34
|
||||||
PYTHON_PATH: C:\Python34
|
PYTHON_PATH: C:\Python34
|
||||||
JEDI_TEST_ENVIRONMENT: 34
|
JEDI_TEST_ENVIRONMENT: 34
|
||||||
@@ -35,9 +29,6 @@ environment:
|
|||||||
- TOXENV: py35
|
- TOXENV: py35
|
||||||
PYTHON_PATH: C:\Python35
|
PYTHON_PATH: C:\Python35
|
||||||
JEDI_TEST_ENVIRONMENT: 27
|
JEDI_TEST_ENVIRONMENT: 27
|
||||||
- TOXENV: py35
|
|
||||||
PYTHON_PATH: C:\Python35
|
|
||||||
JEDI_TEST_ENVIRONMENT: 33
|
|
||||||
- TOXENV: py35
|
- TOXENV: py35
|
||||||
PYTHON_PATH: C:\Python35
|
PYTHON_PATH: C:\Python35
|
||||||
JEDI_TEST_ENVIRONMENT: 34
|
JEDI_TEST_ENVIRONMENT: 34
|
||||||
@@ -51,9 +42,6 @@ environment:
|
|||||||
- TOXENV: py36
|
- TOXENV: py36
|
||||||
PYTHON_PATH: C:\Python36
|
PYTHON_PATH: C:\Python36
|
||||||
JEDI_TEST_ENVIRONMENT: 27
|
JEDI_TEST_ENVIRONMENT: 27
|
||||||
- TOXENV: py36
|
|
||||||
PYTHON_PATH: C:\Python36
|
|
||||||
JEDI_TEST_ENVIRONMENT: 33
|
|
||||||
- TOXENV: py36
|
- TOXENV: py36
|
||||||
PYTHON_PATH: C:\Python36
|
PYTHON_PATH: C:\Python36
|
||||||
JEDI_TEST_ENVIRONMENT: 34
|
JEDI_TEST_ENVIRONMENT: 34
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ from functools import partial
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import jedi
|
import jedi
|
||||||
from jedi.api.environment import get_default_environment, \
|
from jedi.api.environment import get_system_environment, InterpreterEnvironment
|
||||||
get_system_environment, InterpreterEnvironment
|
|
||||||
from jedi._compatibility import py_version
|
from jedi._compatibility import py_version
|
||||||
|
|
||||||
collect_ignore = [
|
collect_ignore = [
|
||||||
@@ -98,9 +97,6 @@ def environment(request):
|
|||||||
if version is None:
|
if version is None:
|
||||||
version = os.environ.get('JEDI_TEST_ENVIRONMENT', str(py_version))
|
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:])
|
return get_system_environment(version[0] + '.' + version[1:])
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ make it work.
|
|||||||
General Features
|
General Features
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
- Python 2.7 and 3.3+ support
|
- Python 2.7 and 3.4+ support
|
||||||
- Ignores syntax errors and wrong indentation
|
- Ignores syntax errors and wrong indentation
|
||||||
- Can deal with complex module / function / class structures
|
- Can deal with complex module / function / class structures
|
||||||
- Great Virtualenv support
|
- Great Virtualenv support
|
||||||
|
|||||||
@@ -16,8 +16,6 @@ except ImportError:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
is_py3 = sys.version_info[0] >= 3
|
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
|
is_py35 = is_py3 and sys.version_info[1] >= 5
|
||||||
py_version = int(str(sys.version_info[0]) + str(sys.version_info[1]))
|
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
|
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
|
# This import is here, because in other places it will raise a
|
||||||
# DeprecationWarning.
|
# DeprecationWarning.
|
||||||
import imp
|
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))
|
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_py3 else find_module_pre_py34
|
||||||
find_module = find_module_py34 if is_py34 else find_module
|
|
||||||
find_module.__doc__ = """
|
find_module.__doc__ = """
|
||||||
Provides information about a module.
|
Provides information about a module.
|
||||||
|
|
||||||
@@ -369,6 +366,7 @@ def print_to_stderr(*args):
|
|||||||
eval("print(*args, file=sys.stderr)")
|
eval("print(*args, file=sys.stderr)")
|
||||||
else:
|
else:
|
||||||
print >> sys.stderr, args
|
print >> sys.stderr, args
|
||||||
|
sys.stderr.flush()
|
||||||
|
|
||||||
|
|
||||||
def utf8_repr(func):
|
def utf8_repr(func):
|
||||||
@@ -521,6 +519,9 @@ class GeneralizedPopen(subprocess.Popen):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
CREATE_NO_WINDOW = 0x08000000
|
CREATE_NO_WINDOW = 0x08000000
|
||||||
kwargs['creationflags'] = CREATE_NO_WINDOW
|
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)
|
super(GeneralizedPopen, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from textwrap import dedent
|
|||||||
import operator as op
|
import operator as op
|
||||||
from collections import namedtuple
|
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
|
py_version, force_unicode, print_to_stderr
|
||||||
from jedi.evaluate.compiled.getattr_static import getattr_static
|
from jedi.evaluate.compiled.getattr_static import getattr_static
|
||||||
|
|
||||||
@@ -31,10 +31,9 @@ NOT_CLASS_TYPES = (
|
|||||||
if is_py3:
|
if is_py3:
|
||||||
NOT_CLASS_TYPES += (
|
NOT_CLASS_TYPES += (
|
||||||
types.MappingProxyType,
|
types.MappingProxyType,
|
||||||
types.SimpleNamespace
|
types.SimpleNamespace,
|
||||||
|
types.DynamicClassAttribute,
|
||||||
)
|
)
|
||||||
if is_py34:
|
|
||||||
NOT_CLASS_TYPES += (types.DynamicClassAttribute,)
|
|
||||||
|
|
||||||
|
|
||||||
# Those types don't exist in typing.
|
# Those types don't exist in typing.
|
||||||
@@ -141,7 +140,7 @@ def load_module(evaluator, dotted_name, sys_path):
|
|||||||
__import__(dotted_name)
|
__import__(dotted_name)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
# If a module is "corrupt" or not really a Python module or whatever.
|
# 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
|
return None
|
||||||
except Exception:
|
except Exception:
|
||||||
# Since __import__ pretty much makes code execution possible, just
|
# Since __import__ pretty much makes code execution possible, just
|
||||||
|
|||||||
@@ -447,8 +447,11 @@ def create_from_name(evaluator, compiled_object, name):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
access = compiled_object.access_handle.getattr(name, default=None)
|
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(
|
return create_cached_compiled_object(
|
||||||
evaluator, access, parent_context=compiled_object, faked=faked
|
evaluator, access, parent_context=parent_context, faked=faked
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -15,9 +15,15 @@ import errno
|
|||||||
import weakref
|
import weakref
|
||||||
import traceback
|
import traceback
|
||||||
from functools import partial
|
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, \
|
from jedi._compatibility import queue, is_py3, force_unicode, \
|
||||||
pickle_dump, pickle_load, GeneralizedPopen
|
pickle_dump, pickle_load, GeneralizedPopen
|
||||||
|
from jedi import debug
|
||||||
from jedi.cache import memoize_method
|
from jedi.cache import memoize_method
|
||||||
from jedi.evaluate.compiled.subprocess import functions
|
from jedi.evaluate.compiled.subprocess import functions
|
||||||
from jedi.evaluate.compiled.access import DirectObjectAccess, AccessPath, \
|
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')
|
_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):
|
def _get_function(name):
|
||||||
return getattr(functions, name)
|
return getattr(functions, name)
|
||||||
|
|
||||||
@@ -135,6 +147,7 @@ class CompiledSubprocess(object):
|
|||||||
@property
|
@property
|
||||||
@memoize_method
|
@memoize_method
|
||||||
def _process(self):
|
def _process(self):
|
||||||
|
debug.dbg('Start environment subprocess %s', self._executable)
|
||||||
parso_path = sys.modules['parso'].__file__
|
parso_path = sys.modules['parso'].__file__
|
||||||
args = (
|
args = (
|
||||||
self._executable,
|
self._executable,
|
||||||
@@ -142,7 +155,7 @@ class CompiledSubprocess(object):
|
|||||||
os.path.dirname(os.path.dirname(parso_path)),
|
os.path.dirname(os.path.dirname(parso_path)),
|
||||||
'.'.join(str(x) for x in sys.version_info[:3]),
|
'.'.join(str(x) for x in sys.version_info[:3]),
|
||||||
)
|
)
|
||||||
return GeneralizedPopen(
|
process = GeneralizedPopen(
|
||||||
args,
|
args,
|
||||||
stdin=subprocess.PIPE,
|
stdin=subprocess.PIPE,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
@@ -151,6 +164,14 @@ class CompiledSubprocess(object):
|
|||||||
# (this is already the case on Python 3).
|
# (this is already the case on Python 3).
|
||||||
bufsize=-1
|
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={}):
|
def run(self, evaluator, function, args=(), kwargs={}):
|
||||||
# Delete old evaluators.
|
# Delete old evaluators.
|
||||||
@@ -219,6 +240,16 @@ class CompiledSubprocess(object):
|
|||||||
stderr,
|
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:
|
if is_exception:
|
||||||
# Replace the attribute error message with a the traceback. It's
|
# Replace the attribute error message with a the traceback. It's
|
||||||
# way more informative.
|
# way more informative.
|
||||||
@@ -282,11 +313,9 @@ class Listener(object):
|
|||||||
|
|
||||||
def listen(self):
|
def listen(self):
|
||||||
stdout = sys.stdout
|
stdout = sys.stdout
|
||||||
# Mute stdout/stderr. Nobody should actually be able to write to those,
|
# Mute stdout. Nobody should actually be able to write to it,
|
||||||
# because stdout is used for IPC and stderr will just be annoying if it
|
# because stdout is used for IPC.
|
||||||
# leaks (on module imports).
|
|
||||||
sys.stdout = open(os.devnull, 'w')
|
sys.stdout = open(os.devnull, 'w')
|
||||||
sys.stderr = open(os.devnull, 'w')
|
|
||||||
stdin = sys.stdin
|
stdin = sys.stdin
|
||||||
if sys.version_info[0] > 2:
|
if sys.version_info[0] > 2:
|
||||||
stdout = stdout.buffer
|
stdout = stdout.buffer
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from jedi.evaluate.arguments import AbstractArguments, AnonymousArguments
|
|||||||
from jedi.cache import memoize_method
|
from jedi.cache import memoize_method
|
||||||
from jedi.evaluate.context.function import FunctionExecutionContext, \
|
from jedi.evaluate.context.function import FunctionExecutionContext, \
|
||||||
FunctionContext, AbstractFunction
|
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.evaluate.context import iterable
|
||||||
from jedi.parser_utils import get_parent_scope
|
from jedi.parser_utils import get_parent_scope
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ class AbstractInstanceContext(Context):
|
|||||||
|
|
||||||
def execute_function_slots(self, names, *evaluated_args):
|
def execute_function_slots(self, names, *evaluated_args):
|
||||||
return ContextSet.from_sets(
|
return ContextSet.from_sets(
|
||||||
name.execute_evaluated(*evaluated_args)
|
name.infer().execute_evaluated(*evaluated_args)
|
||||||
for name in names
|
for name in names
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -169,7 +169,7 @@ class AbstractInstanceContext(Context):
|
|||||||
|
|
||||||
def create_init_executions(self):
|
def create_init_executions(self):
|
||||||
for name in self.get_function_slot_names(u'__init__'):
|
for name in self.get_function_slot_names(u'__init__'):
|
||||||
if isinstance(name, SelfName):
|
if isinstance(name, LazyInstanceClassName):
|
||||||
function = FunctionContext.from_context(
|
function = FunctionContext.from_context(
|
||||||
self.parent_context,
|
self.parent_context,
|
||||||
name.tree_name.parent
|
name.tree_name.parent
|
||||||
@@ -265,17 +265,23 @@ class AnonymousInstance(TreeInstance):
|
|||||||
|
|
||||||
|
|
||||||
class CompiledInstanceName(compiled.CompiledName):
|
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._instance = instance
|
||||||
|
self._class = klass
|
||||||
|
self._class_member_name = name
|
||||||
|
|
||||||
@iterator_to_context_set
|
@iterator_to_context_set
|
||||||
def infer(self):
|
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'
|
is_function = result_context.api_type == 'function'
|
||||||
if result_context.tree_node is not None and is_function:
|
if result_context.tree_node is not None and is_function:
|
||||||
|
yield BoundMethod(self._instance, self._class, result_context)
|
||||||
yield BoundMethod(self._instance, self.parent_context, result_context)
|
|
||||||
else:
|
else:
|
||||||
if is_function:
|
if is_function:
|
||||||
yield CompiledBoundMethod(result_context)
|
yield CompiledBoundMethod(result_context)
|
||||||
@@ -283,20 +289,26 @@ class CompiledInstanceName(compiled.CompiledName):
|
|||||||
yield result_context
|
yield result_context
|
||||||
|
|
||||||
|
|
||||||
class CompiledInstanceClassFilter(compiled.CompiledObjectFilter):
|
class CompiledInstanceClassFilter(filters.AbstractFilter):
|
||||||
name_class = CompiledInstanceName
|
name_class = CompiledInstanceName
|
||||||
|
|
||||||
def __init__(self, evaluator, instance, compiled_object):
|
def __init__(self, evaluator, instance, klass):
|
||||||
super(CompiledInstanceClassFilter, self).__init__(
|
self._evaluator = evaluator
|
||||||
evaluator,
|
|
||||||
compiled_object,
|
|
||||||
is_instance=True,
|
|
||||||
)
|
|
||||||
self._instance = instance
|
self._instance = instance
|
||||||
|
self._class = klass
|
||||||
|
self._class_filter = next(klass.get_filters(is_instance=True))
|
||||||
|
|
||||||
def _create_name(self, name):
|
def get(self, name):
|
||||||
return self.name_class(
|
return self._convert(self._class_filter.get(name))
|
||||||
self._evaluator, self._instance, self._compiled_object, 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):
|
class BoundMethod(AbstractFunction):
|
||||||
@@ -332,11 +344,6 @@ class CompiledBoundMethod(compiled.CompiledObject):
|
|||||||
return list(super(CompiledBoundMethod, self).get_param_names())[1:]
|
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):
|
class SelfName(filters.TreeNameDefinition):
|
||||||
"""
|
"""
|
||||||
This name calculates the parent_context lazily.
|
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)
|
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
|
@iterator_to_context_set
|
||||||
def infer(self):
|
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):
|
if isinstance(result_context, FunctionContext):
|
||||||
# Classes are never used to resolve anything within the
|
# Classes are never used to resolve anything within the
|
||||||
# functions. Only other functions and modules will resolve
|
# 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):
|
for c in apply_py__get__(result_context, self._instance):
|
||||||
yield c
|
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):
|
def __init__(self, evaluator, context, class_context, origin_scope):
|
||||||
super(InstanceClassFilter, self).__init__(
|
self._instance = context
|
||||||
evaluator=evaluator,
|
|
||||||
context=context,
|
|
||||||
node_context=class_context,
|
|
||||||
origin_scope=origin_scope
|
|
||||||
)
|
|
||||||
self._class_context = class_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):
|
def get(self, name):
|
||||||
node = self._origin_scope
|
return self._convert(self._class_filter.get(name))
|
||||||
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):
|
def values(self):
|
||||||
return not name.value.startswith('__') or name.value.endswith('__') \
|
return self._convert(self._class_filter.values())
|
||||||
or self._equals_origin_scope()
|
|
||||||
|
|
||||||
def _filter(self, names):
|
def _convert(self, names):
|
||||||
names = super(InstanceClassFilter, self)._filter(names)
|
return [LazyInstanceClassName(self._instance, self._class_context, n) for n in 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]
|
|
||||||
|
|
||||||
|
|
||||||
class SelfAttributeFilter(InstanceClassFilter):
|
class SelfAttributeFilter(ClassFilter):
|
||||||
"""
|
"""
|
||||||
This class basically filters all the use cases where `self.*` was assigned.
|
This class basically filters all the use cases where `self.*` was assigned.
|
||||||
"""
|
"""
|
||||||
name_class = SelfName
|
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):
|
def _filter(self, names):
|
||||||
names = self._filter_self_names(names)
|
names = self._filter_self_names(names)
|
||||||
if isinstance(self._parser_scope, compiled.CompiledObject) and False:
|
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):
|
if name.is_definition() and self._access_possible(name):
|
||||||
yield 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):
|
def _check_flows(self, names):
|
||||||
return names
|
return names
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ py__doc__(include_call_signature: Returns the docstring for a context.
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
from jedi._compatibility import use_metaclass
|
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.cache import evaluator_method_cache, CachedMetaClass
|
||||||
from jedi.evaluate import compiled
|
from jedi.evaluate import compiled
|
||||||
from jedi.evaluate.lazy_context import LazyKnownContext
|
from jedi.evaluate.lazy_context import LazyKnownContext
|
||||||
@@ -58,9 +59,10 @@ def apply_py__get__(context, base_context):
|
|||||||
|
|
||||||
|
|
||||||
class ClassName(TreeNameDefinition):
|
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)
|
super(ClassName, self).__init__(parent_context, tree_name)
|
||||||
self._name_context = name_context
|
self._name_context = name_context
|
||||||
|
self._apply_decorators = apply_decorators
|
||||||
|
|
||||||
@iterator_to_context_set
|
@iterator_to_context_set
|
||||||
def infer(self):
|
def infer(self):
|
||||||
@@ -70,16 +72,45 @@ class ClassName(TreeNameDefinition):
|
|||||||
self.parent_context.evaluator, self._name_context, self.tree_name)
|
self.parent_context.evaluator, self._name_context, self.tree_name)
|
||||||
|
|
||||||
for result_context in inferred:
|
for result_context in inferred:
|
||||||
for c in apply_py__get__(result_context, self.parent_context):
|
if self._apply_decorators:
|
||||||
yield c
|
for c in apply_py__get__(result_context, self.parent_context):
|
||||||
|
yield c
|
||||||
|
else:
|
||||||
|
yield result_context
|
||||||
|
|
||||||
|
|
||||||
class ClassFilter(ParserTreeFilter):
|
class ClassFilter(ParserTreeFilter):
|
||||||
name_class = ClassName
|
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):
|
def _convert_names(self, names):
|
||||||
return [self.name_class(self.context, name, self._node_context)
|
return [
|
||||||
for name in names]
|
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)):
|
class ClassContext(use_metaclass(CachedMetaClass, TreeContext)):
|
||||||
@@ -163,7 +194,9 @@ class ClassContext(use_metaclass(CachedMetaClass, TreeContext)):
|
|||||||
else:
|
else:
|
||||||
yield ClassFilter(
|
yield ClassFilter(
|
||||||
self.evaluator, self, node_context=cls,
|
self.evaluator, self, node_context=cls,
|
||||||
origin_scope=origin_scope)
|
origin_scope=origin_scope,
|
||||||
|
is_instance=is_instance
|
||||||
|
)
|
||||||
|
|
||||||
def is_class(self):
|
def is_class(self):
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -38,12 +38,6 @@ class AbstractNameDefinition(object):
|
|||||||
return '<%s: %s>' % (self.__class__.__name__, self.string_name)
|
return '<%s: %s>' % (self.__class__.__name__, self.string_name)
|
||||||
return '<%s: %s@%s>' % (self.__class__.__name__, self.string_name, self.start_pos)
|
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):
|
def is_import(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
3
setup.py
3
setup.py
@@ -29,7 +29,7 @@ setup(name='jedi',
|
|||||||
keywords='python completion refactoring vim',
|
keywords='python completion refactoring vim',
|
||||||
long_description=readme,
|
long_description=readme,
|
||||||
packages=find_packages(exclude=['test', 'test.*']),
|
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,
|
install_requires=install_requires,
|
||||||
extras_require={'dev': ['docopt']},
|
extras_require={'dev': ['docopt']},
|
||||||
package_data={'jedi': ['evaluate/compiled/fake/*.pym']},
|
package_data={'jedi': ['evaluate/compiled/fake/*.pym']},
|
||||||
@@ -43,7 +43,6 @@ setup(name='jedi',
|
|||||||
'Programming Language :: Python :: 2',
|
'Programming Language :: Python :: 2',
|
||||||
'Programming Language :: Python :: 2.7',
|
'Programming Language :: Python :: 2.7',
|
||||||
'Programming Language :: Python :: 3',
|
'Programming Language :: Python :: 3',
|
||||||
'Programming Language :: Python :: 3.3',
|
|
||||||
'Programming Language :: Python :: 3.4',
|
'Programming Language :: Python :: 3.4',
|
||||||
'Programming Language :: Python :: 3.5',
|
'Programming Language :: Python :: 3.5',
|
||||||
'Programming Language :: Python :: 3.6',
|
'Programming Language :: Python :: 3.6',
|
||||||
|
|||||||
@@ -437,7 +437,7 @@ def test_func():
|
|||||||
#? int()
|
#? int()
|
||||||
tuple({1})[0]
|
tuple({1})[0]
|
||||||
|
|
||||||
# python >= 3.3
|
# python >= 3.4
|
||||||
# -----------------
|
# -----------------
|
||||||
# PEP 3132 Extended Iterable Unpacking (star unpacking)
|
# PEP 3132 Extended Iterable Unpacking (star unpacking)
|
||||||
# -----------------
|
# -----------------
|
||||||
|
|||||||
@@ -417,6 +417,9 @@ class PrivateVar():
|
|||||||
def __private_func(self):
|
def __private_func(self):
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
#? int()
|
||||||
|
__private_func()
|
||||||
|
|
||||||
def wrap_private(self):
|
def wrap_private(self):
|
||||||
return self.__private_func()
|
return self.__private_func()
|
||||||
#? []
|
#? []
|
||||||
@@ -425,6 +428,8 @@ PrivateVar().__var
|
|||||||
PrivateVar().__var
|
PrivateVar().__var
|
||||||
#? []
|
#? []
|
||||||
PrivateVar().__private_func
|
PrivateVar().__private_func
|
||||||
|
#? []
|
||||||
|
PrivateVar.__private_func
|
||||||
#? int()
|
#? int()
|
||||||
PrivateVar().wrap_private()
|
PrivateVar().wrap_private()
|
||||||
|
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ def x():
|
|||||||
# yield from
|
# yield from
|
||||||
# -----------------
|
# -----------------
|
||||||
|
|
||||||
# python >= 3.3
|
# python >= 3.4
|
||||||
|
|
||||||
def yield_from():
|
def yield_from():
|
||||||
yield from iter([1])
|
yield from iter([1])
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
""" Pep-0484 type hinting """
|
""" Pep-0484 type hinting """
|
||||||
|
|
||||||
# python >= 3.2
|
# python >= 3.4
|
||||||
|
|
||||||
|
|
||||||
class A():
|
class A():
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ for key in x.keys():
|
|||||||
for value in x.values():
|
for value in x.values():
|
||||||
#? int()
|
#? int()
|
||||||
value
|
value
|
||||||
# python >= 3.2
|
# python >= 3.4
|
||||||
|
|
||||||
class TestDefaultDict(typing.DefaultDict[str, int]):
|
class TestDefaultDict(typing.DefaultDict[str, int]):
|
||||||
def setdud(self):
|
def setdud(self):
|
||||||
@@ -271,7 +271,7 @@ for key in x.keys():
|
|||||||
for value in x.values():
|
for value in x.values():
|
||||||
#? int()
|
#? int()
|
||||||
value
|
value
|
||||||
# python >= 3.2
|
# python >= 3.4
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import pytest
|
|||||||
|
|
||||||
from ..helpers import TestCase
|
from ..helpers import TestCase
|
||||||
from jedi import cache
|
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):
|
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):
|
def test_param_name(Script):
|
||||||
if not is_py33:
|
if not is_py3:
|
||||||
p = _params(Script, '''int(''')
|
p = _params(Script, '''int(''')
|
||||||
# int is defined as: `int(x[, base])`
|
# int is defined as: `int(x[, base])`
|
||||||
assert p[0].name == 'x'
|
assert p[0].name == 'x'
|
||||||
|
|||||||
@@ -10,8 +10,10 @@ import os
|
|||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
import jedi
|
import jedi
|
||||||
from ..helpers import cwd_at
|
from jedi.api.environment import SameEnvironment
|
||||||
|
|
||||||
|
|
||||||
SRC = """class Foo:
|
SRC = """class Foo:
|
||||||
@@ -22,35 +24,44 @@ class Bar:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def generate_pyc():
|
@pytest.fixture
|
||||||
os.mkdir("dummy_package")
|
def pyc_project_path(tmpdir):
|
||||||
with open("dummy_package/__init__.py", 'w'):
|
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
|
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)
|
f.write(SRC)
|
||||||
import compileall
|
import compileall
|
||||||
compileall.compile_file("dummy_package/dummy.py")
|
compileall.compile_file(dummy_path)
|
||||||
os.remove("dummy_package/dummy.py")
|
os.remove(dummy_path)
|
||||||
|
|
||||||
if sys.version_info[0] == 3:
|
if sys.version_info.major == 3:
|
||||||
# Python3 specific:
|
# Python3 specific:
|
||||||
# To import pyc modules, we must move them out of the __pycache__
|
# To import pyc modules, we must move them out of the __pycache__
|
||||||
# directory and rename them to remove ".cpython-%s%d"
|
# directory and rename them to remove ".cpython-%s%d"
|
||||||
# see: http://stackoverflow.com/questions/11648440/python-does-not-detect-pyc-files
|
# 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 = f.replace('.cpython-%s%s' % sys.version_info[:2], "")
|
||||||
dst = os.path.join("dummy_package", dst)
|
dst = os.path.join(dummy_package_path, dst)
|
||||||
shutil.copy(os.path.join("dummy_package/__pycache__", f), dst)
|
shutil.copy(os.path.join(pycache, f), dst)
|
||||||
|
try:
|
||||||
|
yield path
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(path)
|
||||||
|
|
||||||
|
|
||||||
@cwd_at('test/test_evaluate')
|
def test_pyc(pyc_project_path):
|
||||||
def test_pyc(Script):
|
|
||||||
"""
|
"""
|
||||||
The list of completion must be greater than 2.
|
The list of completion must be greater than 2.
|
||||||
"""
|
"""
|
||||||
try:
|
path = os.path.join(pyc_project_path, 'blub.py')
|
||||||
generate_pyc()
|
s = jedi.Script(
|
||||||
s = jedi.Script("from dummy_package import dummy; dummy.", path='blub.py')
|
"from dummy_package import dummy; dummy.",
|
||||||
assert len(s.completions()) >= 2
|
path=path,
|
||||||
finally:
|
environment=SameEnvironment())
|
||||||
shutil.rmtree("dummy_package")
|
assert len(s.completions()) >= 2
|
||||||
|
|||||||
9
tox.ini
9
tox.ini
@@ -1,8 +1,8 @@
|
|||||||
[tox]
|
[tox]
|
||||||
envlist = py27, py33, py34, py35, py36
|
envlist = py27, py34, py35, py36
|
||||||
[testenv]
|
[testenv]
|
||||||
deps =
|
deps =
|
||||||
pytest>=2.3.5, < 3.3
|
pytest>=2.3.5
|
||||||
pytest-cache
|
pytest-cache
|
||||||
# docopt for sith doctests
|
# docopt for sith doctests
|
||||||
docopt
|
docopt
|
||||||
@@ -19,7 +19,6 @@ setenv =
|
|||||||
# To test Jedi in different versions than the same Python version, set a
|
# To test Jedi in different versions than the same Python version, set a
|
||||||
# different test environment.
|
# different test environment.
|
||||||
env27: JEDI_TEST_ENVIRONMENT=27
|
env27: JEDI_TEST_ENVIRONMENT=27
|
||||||
env33: JEDI_TEST_ENVIRONMENT=33
|
|
||||||
env34: JEDI_TEST_ENVIRONMENT=34
|
env34: JEDI_TEST_ENVIRONMENT=34
|
||||||
env35: JEDI_TEST_ENVIRONMENT=35
|
env35: JEDI_TEST_ENVIRONMENT=35
|
||||||
env36: JEDI_TEST_ENVIRONMENT=36
|
env36: JEDI_TEST_ENVIRONMENT=36
|
||||||
@@ -33,10 +32,6 @@ deps =
|
|||||||
# numpydoc for typing scipy stack
|
# numpydoc for typing scipy stack
|
||||||
numpydoc
|
numpydoc
|
||||||
{[testenv]deps}
|
{[testenv]deps}
|
||||||
[testenv:py33]
|
|
||||||
deps =
|
|
||||||
typing
|
|
||||||
{[testenv]deps}
|
|
||||||
[testenv:py34]
|
[testenv:py34]
|
||||||
deps =
|
deps =
|
||||||
typing
|
typing
|
||||||
|
|||||||
@@ -8,10 +8,6 @@ set -e
|
|||||||
sudo chown root: /opt/python/3.6/bin/python
|
sudo chown root: /opt/python/3.6/bin/python
|
||||||
sudo chown root: /opt/python/3.6.3/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
|
if [[ $JEDI_TEST_ENVIRONMENT == "35" ]]; then
|
||||||
VERSION=3.5
|
VERSION=3.5
|
||||||
DOWNLOAD=1
|
DOWNLOAD=1
|
||||||
|
|||||||
Reference in New Issue
Block a user