mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-06 14:04:26 +08:00
Merge branch 'master' into typeshed
This commit is contained in:
@@ -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).
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
12
appveyor.yml
12
appveyor.yml
@@ -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
|
||||
|
||||
@@ -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:])
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
3
setup.py
3
setup.py
@@ -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',
|
||||
|
||||
@@ -437,7 +437,7 @@ def test_func():
|
||||
#? int()
|
||||
tuple({1})[0]
|
||||
|
||||
# python >= 3.3
|
||||
# python >= 3.4
|
||||
# -----------------
|
||||
# PEP 3132 Extended Iterable Unpacking (star unpacking)
|
||||
# -----------------
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -220,7 +220,7 @@ def x():
|
||||
# yield from
|
||||
# -----------------
|
||||
|
||||
# python >= 3.3
|
||||
# python >= 3.4
|
||||
|
||||
def yield_from():
|
||||
yield from iter([1])
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
""" Pep-0484 type hinting """
|
||||
|
||||
# python >= 3.2
|
||||
# python >= 3.4
|
||||
|
||||
|
||||
class A():
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
"""
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
9
tox.ini
9
tox.ini
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user