mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-07 06:24:27 +08:00
Merge with master
The deprecation of Python2.6 and the insertion of environments made it quite difficult to merge.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,6 +5,7 @@
|
|||||||
.tox
|
.tox
|
||||||
.coveralls.yml
|
.coveralls.yml
|
||||||
.coverage
|
.coverage
|
||||||
|
.idea
|
||||||
/build/
|
/build/
|
||||||
/docs/_build/
|
/docs/_build/
|
||||||
/dist/
|
/dist/
|
||||||
|
|||||||
@@ -3,6 +3,12 @@
|
|||||||
Changelog
|
Changelog
|
||||||
---------
|
---------
|
||||||
|
|
||||||
|
0.12.0 (2018-01-01)
|
||||||
|
+++++++++++++++++++
|
||||||
|
|
||||||
|
- Remove Python 2.6
|
||||||
|
- VirtualEnvs
|
||||||
|
|
||||||
0.11.1 (2017-12-14)
|
0.11.1 (2017-12-14)
|
||||||
+++++++++++++++++++
|
+++++++++++++++++++
|
||||||
|
|
||||||
|
|||||||
31
README.rst
31
README.rst
@@ -2,16 +2,23 @@
|
|||||||
Jedi - an awesome autocompletion/static analysis library for Python
|
Jedi - an awesome autocompletion/static analysis library for Python
|
||||||
###################################################################
|
###################################################################
|
||||||
|
|
||||||
.. image:: https://secure.travis-ci.org/davidhalter/jedi.png?branch=master
|
.. image:: https://img.shields.io/pypi/v/jedi.svg?style=flat
|
||||||
:target: http://travis-ci.org/davidhalter/jedi
|
:target: https://pypi.python.org/pypi/jedi
|
||||||
:alt: Travis-CI build status
|
:alt: PyPI version
|
||||||
|
|
||||||
.. image:: https://coveralls.io/repos/davidhalter/jedi/badge.png?branch=master
|
.. image:: https://img.shields.io/pypi/pyversions/jedi.svg
|
||||||
|
:target: https://pypi.python.org/pypi/jedi
|
||||||
|
:alt: Supported Python versions
|
||||||
|
|
||||||
|
.. image:: https://travis-ci.org/davidhalter/jedi.svg?branch=master
|
||||||
|
:target: https://travis-ci.org/davidhalter/jedi
|
||||||
|
:alt: Travis CI build status
|
||||||
|
|
||||||
|
.. image:: https://coveralls.io/repos/davidhalter/jedi/badge.svg?branch=master
|
||||||
:target: https://coveralls.io/r/davidhalter/jedi
|
:target: https://coveralls.io/r/davidhalter/jedi
|
||||||
:alt: Coverage Status
|
:alt: Coverage status
|
||||||
|
|
||||||
|
*If you have specific questions, please add an issue or ask on* `Stack Overflow
|
||||||
*If you have specific questions, please add an issue or ask on* `stackoverflow
|
|
||||||
<https://stackoverflow.com/questions/tagged/python-jedi>`_ *with the label* ``python-jedi``.
|
<https://stackoverflow.com/questions/tagged/python-jedi>`_ *with the label* ``python-jedi``.
|
||||||
|
|
||||||
|
|
||||||
@@ -25,7 +32,7 @@ related names and to list all names in a Python file and infer them. Jedi
|
|||||||
understands docstrings and you can use Jedi autocompletion in your REPL as
|
understands docstrings and you can use Jedi autocompletion in your REPL as
|
||||||
well.
|
well.
|
||||||
|
|
||||||
Jedi uses a very simple API to connect with IDE's. There's a reference
|
Jedi uses a very simple API to connect with IDEs. There's a reference
|
||||||
implementation as a `VIM-Plugin <https://github.com/davidhalter/jedi-vim>`_,
|
implementation as a `VIM-Plugin <https://github.com/davidhalter/jedi-vim>`_,
|
||||||
which uses Jedi's autocompletion. We encourage you to use Jedi in your IDEs.
|
which uses Jedi's autocompletion. We encourage you to use Jedi in your IDEs.
|
||||||
It's really easy.
|
It's really easy.
|
||||||
@@ -45,7 +52,7 @@ Jedi can currently be used with the following editors/projects:
|
|||||||
- Gedit (gedi_)
|
- Gedit (gedi_)
|
||||||
- wdb_ - Web Debugger
|
- wdb_ - Web Debugger
|
||||||
- `Eric IDE`_ (Available as a plugin)
|
- `Eric IDE`_ (Available as a plugin)
|
||||||
- `Ipython 6.0.0+ <https://ipython.readthedocs.io/en/stable/whatsnew/version6.html>`_
|
- `IPython 6.0.0+ <https://ipython.readthedocs.io/en/stable/whatsnew/version6.html>`_
|
||||||
|
|
||||||
and many more!
|
and many more!
|
||||||
|
|
||||||
@@ -96,7 +103,7 @@ 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.6, 2.7, 3.3, 3.4 or 3.5 but it should also
|
You can run Jedi on CPython 2.7 or 3.3+ but it should also
|
||||||
understand/parse code older than those versions.
|
understand/parse code older than those versions.
|
||||||
|
|
||||||
Tips on how to use Jedi efficiently can be found `here
|
Tips on how to use Jedi efficiently can be found `here
|
||||||
@@ -123,7 +130,7 @@ The returned objects are very powerful and really all you might need.
|
|||||||
Autocompletion in your REPL (IPython, etc.)
|
Autocompletion in your REPL (IPython, etc.)
|
||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
|
|
||||||
Starting with Ipython `6.0.0` Jedi is a dependency of IPython. Autocompletion
|
Starting with IPython `6.0.0` Jedi is a dependency of IPython. Autocompletion
|
||||||
in IPython is therefore possible without additional configuration.
|
in IPython is therefore possible without additional configuration.
|
||||||
|
|
||||||
It's possible to have Jedi autocompletion in REPL modes - `example video <https://vimeo.com/122332037>`_.
|
It's possible to have Jedi autocompletion in REPL modes - `example video <https://vimeo.com/122332037>`_.
|
||||||
@@ -178,7 +185,7 @@ Tests are also run automatically on `Travis CI
|
|||||||
<https://travis-ci.org/davidhalter/jedi/>`_.
|
<https://travis-ci.org/davidhalter/jedi/>`_.
|
||||||
|
|
||||||
For more detailed information visit the `testing documentation
|
For more detailed information visit the `testing documentation
|
||||||
<https://jedi.readthedocs.org/en/latest/docs/testing.html>`_
|
<https://jedi.readthedocs.org/en/latest/docs/testing.html>`_.
|
||||||
|
|
||||||
|
|
||||||
Acknowledgements
|
Acknowledgements
|
||||||
|
|||||||
1
docs/_themes/flask/layout.html
vendored
1
docs/_themes/flask/layout.html
vendored
@@ -19,7 +19,6 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
{%- block footer %}
|
{%- block footer %}
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
© Copyright {{ copyright }}.
|
|
||||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a>.
|
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a>.
|
||||||
</div>
|
</div>
|
||||||
{% if pagename == 'index' %}
|
{% if pagename == 'index' %}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ master_doc = 'index'
|
|||||||
|
|
||||||
# General information about the project.
|
# General information about the project.
|
||||||
project = u'Jedi'
|
project = u'Jedi'
|
||||||
copyright = u'2012 - {today.year}, Jedi contributors'.format(today=datetime.date.today())
|
copyright = u'jedi contributors'
|
||||||
|
|
||||||
import jedi
|
import jedi
|
||||||
from jedi.utils import version_info
|
from jedi.utils import version_info
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ make it work.
|
|||||||
General Features
|
General Features
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
- python 2.6+ and 3.3+ support
|
- Python 2.7 and 3.3+ 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
|
||||||
- virtualenv support
|
- virtualenv support
|
||||||
@@ -64,7 +64,7 @@ Not yet implemented:
|
|||||||
|
|
||||||
- manipulations of instances outside the instance variables without using
|
- manipulations of instances outside the instance variables without using
|
||||||
methods
|
methods
|
||||||
- implicit namespace packages (Python 3.3+, `PEP 420 <https://www.python.org/dev/peps/pep-0420/>`_)
|
- implicit namespace packages (Python 3.4+, `PEP 420 <https://www.python.org/dev/peps/pep-0420/>`_)
|
||||||
|
|
||||||
Will probably never be implemented:
|
Will probably never be implemented:
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ etc.
|
|||||||
**Security**
|
**Security**
|
||||||
|
|
||||||
Security is an important issue for |jedi|. Therefore no Python code is
|
Security is an important issue for |jedi|. Therefore no Python code is
|
||||||
executed. As long as you write pure python, everything is evaluated
|
executed. As long as you write pure Python, everything is evaluated
|
||||||
statically. But: If you use builtin modules (``c_builtin``) there is no other
|
statically. But: If you use builtin modules (``c_builtin``) there is no other
|
||||||
option than to execute those modules. However: Execute isn't that critical (as
|
option than to execute those modules. However: Execute isn't that critical (as
|
||||||
e.g. in pythoncomplete, which used to execute *every* import!), because it
|
e.g. in pythoncomplete, which used to execute *every* import!), because it
|
||||||
@@ -117,7 +117,7 @@ one of the following docstring/annotation syntax styles:
|
|||||||
|
|
||||||
https://www.python.org/dev/peps/pep-0484/
|
https://www.python.org/dev/peps/pep-0484/
|
||||||
|
|
||||||
function annotations (python 3 only; python 2 function annotations with
|
function annotations (Python 3 only; Python 2 function annotations with
|
||||||
comments in planned but not yet implemented)
|
comments in planned but not yet implemented)
|
||||||
|
|
||||||
::
|
::
|
||||||
@@ -129,7 +129,7 @@ comments in planned but not yet implemented)
|
|||||||
node.| # complete here
|
node.| # complete here
|
||||||
|
|
||||||
|
|
||||||
assignment, for-loop and with-statement type hints (all python versions).
|
assignment, for-loop and with-statement type hints (all Python versions).
|
||||||
Note that the type hints must be on the same line as the statement
|
Note that the type hints must be on the same line as the statement
|
||||||
|
|
||||||
::
|
::
|
||||||
@@ -142,7 +142,7 @@ Note that the type hints must be on the same line as the statement
|
|||||||
print(f + 3)
|
print(f + 3)
|
||||||
|
|
||||||
Most of the features in PEP-0484 are supported including the typing module
|
Most of the features in PEP-0484 are supported including the typing module
|
||||||
(for python < 3.5 you have to do ``pip install typing`` to use these),
|
(for Python < 3.5 you have to do ``pip install typing`` to use these),
|
||||||
and forward references.
|
and forward references.
|
||||||
|
|
||||||
Things that are missing (and this is not an exhaustive list; some of these
|
Things that are missing (and this is not an exhaustive list; some of these
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
To ensure compatibility from Python ``2.6`` - ``3.3``, a module has been
|
To ensure compatibility from Python ``2.7`` - ``3.x``, a module has been
|
||||||
created. Clearly there is huge need to use conforming syntax.
|
created. Clearly there is huge need to use conforming syntax.
|
||||||
"""
|
"""
|
||||||
import sys
|
import sys
|
||||||
@@ -13,12 +13,10 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Cannot use sys.version.major and minor names, because in Python 2.6 it's not
|
|
||||||
# a namedtuple.
|
|
||||||
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_py33 = is_py3 and sys.version_info[1] >= 3
|
||||||
is_py34 = is_py3 and sys.version_info[1] >= 4
|
is_py34 = is_py3 and sys.version_info[1] >= 4
|
||||||
is_py26 = not is_py3 and sys.version_info[1] < 7
|
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]))
|
||||||
|
|
||||||
|
|
||||||
@@ -74,7 +72,7 @@ def find_module_py33(string, path=None, loader=None, full_name=None):
|
|||||||
raise ImportError("Originally " + repr(e))
|
raise ImportError("Originally " + repr(e))
|
||||||
|
|
||||||
if loader is None:
|
if loader is None:
|
||||||
raise ImportError("Couldn't find a loader for {0}".format(string))
|
raise ImportError("Couldn't find a loader for {}".format(string))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
is_package = loader.is_package(string)
|
is_package = loader.is_package(string)
|
||||||
@@ -127,14 +125,7 @@ def find_module_pre_py33(string, path=None, full_name=None):
|
|||||||
if loader:
|
if loader:
|
||||||
is_package = loader.is_package(string)
|
is_package = loader.is_package(string)
|
||||||
is_archive = hasattr(loader, 'archive')
|
is_archive = hasattr(loader, 'archive')
|
||||||
try:
|
|
||||||
module_path = loader.get_filename(string)
|
module_path = loader.get_filename(string)
|
||||||
except AttributeError:
|
|
||||||
# fallback for py26
|
|
||||||
try:
|
|
||||||
module_path = loader._get_filename(string)
|
|
||||||
except AttributeError:
|
|
||||||
continue
|
|
||||||
if is_package:
|
if is_package:
|
||||||
module_path = os.path.dirname(module_path)
|
module_path = os.path.dirname(module_path)
|
||||||
if is_archive:
|
if is_archive:
|
||||||
@@ -142,10 +133,10 @@ def find_module_pre_py33(string, path=None, full_name=None):
|
|||||||
file = None
|
file = None
|
||||||
if not is_package or is_archive:
|
if not is_package or is_archive:
|
||||||
file = DummyFile(loader, string)
|
file = DummyFile(loader, string)
|
||||||
return (file, module_path, is_package)
|
return file, module_path, is_package
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
raise ImportError("No module named {0}".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_py33 if is_py33 else find_module_pre_py33
|
||||||
@@ -260,11 +251,6 @@ import ast
|
|||||||
|
|
||||||
|
|
||||||
def literal_eval(string):
|
def literal_eval(string):
|
||||||
# py3.0, py3.1 and py32 don't support unicode literals. Support those, I
|
|
||||||
# don't want to write two versions of the tokenizer.
|
|
||||||
if is_py3 and sys.version_info.minor < 3:
|
|
||||||
if re.match('[uU][\'"]', string):
|
|
||||||
string = string[1:]
|
|
||||||
return ast.literal_eval(string)
|
return ast.literal_eval(string)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ arguments.
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
import parso
|
||||||
from parso.python import tree
|
from parso.python import tree
|
||||||
from parso import python_bytes_to_unicode, split_lines
|
|
||||||
|
|
||||||
from jedi._compatibility import force_unicode, is_py3
|
from jedi._compatibility import force_unicode, is_py3
|
||||||
from jedi.parser_utils import get_executable_nodes
|
from jedi.parser_utils import get_executable_nodes
|
||||||
@@ -94,9 +94,29 @@ class Script(object):
|
|||||||
with open(path, 'rb') as f:
|
with open(path, 'rb') as f:
|
||||||
source = f.read()
|
source = f.read()
|
||||||
|
|
||||||
# TODO do we really want that?
|
# Load the Python grammar of the current interpreter.
|
||||||
self._source = python_bytes_to_unicode(source, encoding, errors='replace')
|
self._grammar = parso.load_grammar()
|
||||||
self._code_lines = split_lines(self._source)
|
|
||||||
|
if sys_path is not None and not is_py3:
|
||||||
|
sys_path = list(map(force_unicode, sys_path))
|
||||||
|
|
||||||
|
# Load the Python grammar of the current interpreter.
|
||||||
|
project = get_default_project()
|
||||||
|
# TODO deprecate and remove sys_path from the Script API.
|
||||||
|
if sys_path is not None:
|
||||||
|
project._sys_path = sys_path
|
||||||
|
self._evaluator = Evaluator(project, environment=environment, script_path=path)
|
||||||
|
self._project = project
|
||||||
|
debug.speed('init')
|
||||||
|
self._module_node, source = self._evaluator.parse_and_get_code(
|
||||||
|
code=source,
|
||||||
|
path=self.path,
|
||||||
|
cache=False, # No disk cache, because the current script often changes.
|
||||||
|
diff_cache=True,
|
||||||
|
cache_path=settings.cache_directory
|
||||||
|
)
|
||||||
|
debug.speed('parsed')
|
||||||
|
self._code_lines = parso.split_lines(source)
|
||||||
line = max(len(self._code_lines), 1) if line is None else line
|
line = max(len(self._code_lines), 1) if line is None else line
|
||||||
if not (0 < line <= len(self._code_lines)):
|
if not (0 < line <= len(self._code_lines)):
|
||||||
raise ValueError('`line` parameter is not in a valid range.')
|
raise ValueError('`line` parameter is not in a valid range.')
|
||||||
@@ -111,35 +131,8 @@ class Script(object):
|
|||||||
cache.clear_time_caches()
|
cache.clear_time_caches()
|
||||||
debug.reset_time()
|
debug.reset_time()
|
||||||
|
|
||||||
if sys_path is not None and not is_py3:
|
|
||||||
sys_path = list(map(force_unicode, sys_path))
|
|
||||||
|
|
||||||
# Load the Python grammar of the current interpreter.
|
|
||||||
project = get_default_project()
|
|
||||||
# TODO deprecate and remove sys_path from the Script API.
|
|
||||||
if sys_path is not None:
|
|
||||||
project._sys_path = sys_path
|
|
||||||
self._evaluator = Evaluator(project, environment=environment, script_path=path)
|
|
||||||
self._project = project
|
|
||||||
debug.speed('init')
|
|
||||||
|
|
||||||
@cache.memoize_method
|
|
||||||
def _get_module_node(self):
|
|
||||||
return self._evaluator.grammar.parse(
|
|
||||||
code=self._source,
|
|
||||||
path=self.path,
|
|
||||||
cache=False, # No disk cache, because the current script often changes.
|
|
||||||
diff_cache=True,
|
|
||||||
cache_path=settings.cache_directory
|
|
||||||
)
|
|
||||||
|
|
||||||
@cache.memoize_method
|
|
||||||
def _get_module(self):
|
def _get_module(self):
|
||||||
module = ModuleContext(
|
module = ModuleContext(self._evaluator, self._module_node, self.path)
|
||||||
self._evaluator,
|
|
||||||
self._get_module_node(),
|
|
||||||
self.path
|
|
||||||
)
|
|
||||||
if self.path is not None:
|
if self.path is not None:
|
||||||
name = dotted_path_in_sys_path(self._evaluator.get_sys_path(), self.path)
|
name = dotted_path_in_sys_path(self._evaluator.get_sys_path(), self.path)
|
||||||
if name is not None:
|
if name is not None:
|
||||||
@@ -178,10 +171,9 @@ class Script(object):
|
|||||||
|
|
||||||
:rtype: list of :class:`classes.Definition`
|
:rtype: list of :class:`classes.Definition`
|
||||||
"""
|
"""
|
||||||
module_node = self._get_module_node()
|
leaf = self._module_node.get_name_of_position(self._pos)
|
||||||
leaf = module_node.get_name_of_position(self._pos)
|
|
||||||
if leaf is None:
|
if leaf is None:
|
||||||
leaf = module_node.get_leaf_for_position(self._pos)
|
leaf = self._module_node.get_leaf_for_position(self._pos)
|
||||||
if leaf is None:
|
if leaf is None:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@@ -212,7 +204,7 @@ class Script(object):
|
|||||||
else:
|
else:
|
||||||
yield name
|
yield name
|
||||||
|
|
||||||
tree_name = self._get_module_node().get_name_of_position(self._pos)
|
tree_name = self._module_node.get_name_of_position(self._pos)
|
||||||
if tree_name is None:
|
if tree_name is None:
|
||||||
return []
|
return []
|
||||||
context = self._evaluator.create_context(self._get_module(), tree_name)
|
context = self._evaluator.create_context(self._get_module(), tree_name)
|
||||||
@@ -243,7 +235,7 @@ class Script(object):
|
|||||||
|
|
||||||
:rtype: list of :class:`classes.Definition`
|
:rtype: list of :class:`classes.Definition`
|
||||||
"""
|
"""
|
||||||
tree_name = self._get_module_node().get_name_of_position(self._pos)
|
tree_name = self._module_node.get_name_of_position(self._pos)
|
||||||
if tree_name is None:
|
if tree_name is None:
|
||||||
# Must be syntax
|
# Must be syntax
|
||||||
return []
|
return []
|
||||||
@@ -270,7 +262,7 @@ class Script(object):
|
|||||||
:rtype: list of :class:`classes.CallSignature`
|
:rtype: list of :class:`classes.CallSignature`
|
||||||
"""
|
"""
|
||||||
call_signature_details = \
|
call_signature_details = \
|
||||||
helpers.get_call_signature_details(self._get_module_node(), self._pos)
|
helpers.get_call_signature_details(self._module_node, self._pos)
|
||||||
if call_signature_details is None:
|
if call_signature_details is None:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@@ -295,10 +287,9 @@ class Script(object):
|
|||||||
|
|
||||||
def _analysis(self):
|
def _analysis(self):
|
||||||
self._evaluator.is_analysis = True
|
self._evaluator.is_analysis = True
|
||||||
module_node = self._get_module_node()
|
self._evaluator.analysis_modules = [self._module_node]
|
||||||
self._evaluator.analysis_modules = [module_node]
|
|
||||||
try:
|
try:
|
||||||
for node in get_executable_nodes(module_node):
|
for node in get_executable_nodes(self._module_node):
|
||||||
context = self._get_module().create_context(node)
|
context = self._get_module().create_context(node)
|
||||||
if node.type in ('funcdef', 'classdef'):
|
if node.type in ('funcdef', 'classdef'):
|
||||||
# Resolve the decorators.
|
# Resolve the decorators.
|
||||||
@@ -374,10 +365,9 @@ class Interpreter(Script):
|
|||||||
self.namespaces = namespaces
|
self.namespaces = namespaces
|
||||||
|
|
||||||
def _get_module(self):
|
def _get_module(self):
|
||||||
parser_module = super(Interpreter, self)._get_module_node()
|
|
||||||
return interpreter.MixedModuleContext(
|
return interpreter.MixedModuleContext(
|
||||||
self._evaluator,
|
self._evaluator,
|
||||||
parser_module,
|
self._module_node,
|
||||||
self.namespaces,
|
self.namespaces,
|
||||||
path=self.path
|
path=self.path
|
||||||
)
|
)
|
||||||
@@ -413,7 +403,7 @@ def names(source=None, path=None, encoding='utf-8', all_scopes=False,
|
|||||||
module_context.create_context(name if name.parent.type == 'file_input' else name.parent),
|
module_context.create_context(name if name.parent.type == 'file_input' else name.parent),
|
||||||
name
|
name
|
||||||
)
|
)
|
||||||
) for name in get_module_names(script._get_module_node(), all_scopes)
|
) for name in get_module_names(script._module_node, all_scopes)
|
||||||
]
|
]
|
||||||
return sorted(filter(def_ref_filter, defs), key=lambda x: (x.line, x.column))
|
return sorted(filter(def_ref_filter, defs), key=lambda x: (x.line, x.column))
|
||||||
|
|
||||||
|
|||||||
@@ -555,7 +555,7 @@ class Definition(BaseDefinition):
|
|||||||
.. todo:: Add full path. This function is should return a
|
.. todo:: Add full path. This function is should return a
|
||||||
`module.class.function` path.
|
`module.class.function` path.
|
||||||
"""
|
"""
|
||||||
position = '' if self.in_builtin_module else '@%s' % (self.line)
|
position = '' if self.in_builtin_module else '@%s' % self.line
|
||||||
return "%s:%s%s" % (self.module_name, self.description, position)
|
return "%s:%s%s" % (self.module_name, self.description, position)
|
||||||
|
|
||||||
@memoize_method
|
@memoize_method
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ that are not used are just being ignored.
|
|||||||
|
|
||||||
from parso.python import tree
|
from parso.python import tree
|
||||||
import parso
|
import parso
|
||||||
|
from parso import python_bytes_to_unicode
|
||||||
|
|
||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi import parser_utils
|
from jedi import parser_utils
|
||||||
@@ -106,6 +107,7 @@ class Evaluator(object):
|
|||||||
self.access_cache = {}
|
self.access_cache = {}
|
||||||
|
|
||||||
self.reset_recursion_limitations()
|
self.reset_recursion_limitations()
|
||||||
|
self.allow_different_encoding = True
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@evaluator_function_cache()
|
@evaluator_function_cache()
|
||||||
@@ -366,3 +368,15 @@ class Evaluator(object):
|
|||||||
node = node.parent
|
node = node.parent
|
||||||
scope_node = parent_scope(node)
|
scope_node = parent_scope(node)
|
||||||
return from_scope_node(scope_node, is_nested=True, node_is_object=node_is_object)
|
return from_scope_node(scope_node, is_nested=True, node_is_object=node_is_object)
|
||||||
|
|
||||||
|
def parse_and_get_code(self, code, path, **kwargs):
|
||||||
|
if self.allow_different_encoding:
|
||||||
|
if code is None:
|
||||||
|
with open(path, 'rb') as f:
|
||||||
|
code = f.read()
|
||||||
|
code = python_bytes_to_unicode(code, errors='replace')
|
||||||
|
|
||||||
|
return self.grammar.parse(code=code, path=path, **kwargs), code
|
||||||
|
|
||||||
|
def parse(self, *args, **kwargs):
|
||||||
|
return self.parse_and_get_code(*args, **kwargs)[0]
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ from jedi.evaluate.base_context import NO_CONTEXTS
|
|||||||
from jedi.evaluate.context import iterable
|
from jedi.evaluate.context import iterable
|
||||||
from jedi.evaluate.param import get_params, ExecutedParam
|
from jedi.evaluate.param import get_params, ExecutedParam
|
||||||
|
|
||||||
|
|
||||||
def try_iter_content(types, depth=0):
|
def try_iter_content(types, depth=0):
|
||||||
"""Helper method for static analysis."""
|
"""Helper method for static analysis."""
|
||||||
if depth > 10:
|
if depth > 10:
|
||||||
@@ -29,6 +30,8 @@ def try_iter_content(types, depth=0):
|
|||||||
|
|
||||||
class AbstractArguments(object):
|
class AbstractArguments(object):
|
||||||
context = None
|
context = None
|
||||||
|
argument_node = None
|
||||||
|
trailer = None
|
||||||
|
|
||||||
def eval_argument_clinic(self, parameters):
|
def eval_argument_clinic(self, parameters):
|
||||||
"""Uses a list with argument clinic information (see PEP 436)."""
|
"""Uses a list with argument clinic information (see PEP 436)."""
|
||||||
@@ -95,10 +98,9 @@ class TreeArguments(AbstractArguments):
|
|||||||
self.trailer = trailer # Can be None, e.g. in a class definition.
|
self.trailer = trailer # Can be None, e.g. in a class definition.
|
||||||
|
|
||||||
def _split(self):
|
def _split(self):
|
||||||
if isinstance(self.argument_node, (tuple, list)):
|
if self.argument_node is None:
|
||||||
for el in self.argument_node:
|
return
|
||||||
yield 0, el
|
|
||||||
else:
|
|
||||||
if not (self.argument_node.type == 'arglist' or (
|
if not (self.argument_node.type == 'arglist' or (
|
||||||
# in python 3.5 **arg is an argument, not arglist
|
# in python 3.5 **arg is an argument, not arglist
|
||||||
(self.argument_node.type == 'argument') and
|
(self.argument_node.type == 'argument') and
|
||||||
@@ -197,7 +199,11 @@ class TreeArguments(AbstractArguments):
|
|||||||
arguments = param.var_args
|
arguments = param.var_args
|
||||||
break
|
break
|
||||||
|
|
||||||
return [arguments.argument_node or arguments.trailer]
|
if arguments.argument_node is not None:
|
||||||
|
return [arguments.argument_node]
|
||||||
|
if arguments.trailer is not None:
|
||||||
|
return [arguments.trailer]
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
class ValuesArguments(AbstractArguments):
|
class ValuesArguments(AbstractArguments):
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ else:
|
|||||||
return getattr(klass, '__dict__', _sentinel)
|
return getattr(klass, '__dict__', _sentinel)
|
||||||
return _shadowed_dict_newstyle(klass)
|
return _shadowed_dict_newstyle(klass)
|
||||||
|
|
||||||
class _OldStyleClass():
|
class _OldStyleClass:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
_oldstyle_instance_type = type(_OldStyleClass())
|
_oldstyle_instance_type = type(_OldStyleClass())
|
||||||
@@ -124,7 +124,7 @@ def _safe_hasattr(obj, name):
|
|||||||
|
|
||||||
|
|
||||||
def _safe_is_data_descriptor(obj):
|
def _safe_is_data_descriptor(obj):
|
||||||
return (_safe_hasattr(obj, '__set__') or _safe_hasattr(obj, '__delete__'))
|
return _safe_hasattr(obj, '__set__') or _safe_hasattr(obj, '__delete__')
|
||||||
|
|
||||||
|
|
||||||
def getattr_static(obj, attr, default=_sentinel):
|
def getattr_static(obj, attr, default=_sentinel):
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ class MixedName(compiled.CompiledName):
|
|||||||
contexts = list(self.infer())
|
contexts = list(self.infer())
|
||||||
if not contexts:
|
if not contexts:
|
||||||
# This means a start_pos that doesn't exist (compiled objects).
|
# This means a start_pos that doesn't exist (compiled objects).
|
||||||
return (0, 0)
|
return 0, 0
|
||||||
return contexts[0].name.start_pos
|
return contexts[0].name.start_pos
|
||||||
|
|
||||||
@start_pos.setter
|
@start_pos.setter
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ class ModuleContext(use_metaclass(CachedMetaClass, TreeContext)):
|
|||||||
|
|
||||||
def py__package__(self):
|
def py__package__(self):
|
||||||
if self._get_init_directory() is None:
|
if self._get_init_directory() is None:
|
||||||
return re.sub(r'\.?[^\.]+$', '', self.py__name__())
|
return re.sub(r'\.?[^.]+$', '', self.py__name__())
|
||||||
else:
|
else:
|
||||||
return self.py__name__()
|
return self.py__name__()
|
||||||
|
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ def _evaluate_for_statement_string(module_context, string):
|
|||||||
Need this docstring so that if the below part is not valid Python this
|
Need this docstring so that if the below part is not valid Python this
|
||||||
is still a function.
|
is still a function.
|
||||||
'''
|
'''
|
||||||
{0}
|
{}
|
||||||
"""))
|
"""))
|
||||||
if string is None:
|
if string is None:
|
||||||
return []
|
return []
|
||||||
@@ -252,7 +252,7 @@ def _execute_array_values(evaluator, array):
|
|||||||
for typ in lazy_context.infer()
|
for typ in lazy_context.infer()
|
||||||
)
|
)
|
||||||
values.append(LazyKnownContexts(objects))
|
values.append(LazyKnownContexts(objects))
|
||||||
return set([FakeSequence(evaluator, array.array_type, values)])
|
return {FakeSequence(evaluator, array.array_type, values)}
|
||||||
else:
|
else:
|
||||||
return array.execute_evaluated()
|
return array.execute_evaluated()
|
||||||
|
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ def _check_name_for_execution(evaluator, context, compare_node, name, trailer):
|
|||||||
def create_func_excs():
|
def create_func_excs():
|
||||||
arglist = trailer.children[1]
|
arglist = trailer.children[1]
|
||||||
if arglist == ')':
|
if arglist == ')':
|
||||||
arglist = ()
|
arglist = None
|
||||||
args = TreeArguments(evaluator, context, arglist, trailer)
|
args = TreeArguments(evaluator, context, arglist, trailer)
|
||||||
if value_node.type == 'funcdef':
|
if value_node.type == 'funcdef':
|
||||||
yield value.get_function_execution(args)
|
yield value.get_function_execution(args)
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class AbstractNameDefinition(object):
|
|||||||
def goto(self):
|
def goto(self):
|
||||||
# Typically names are already definitions and therefore a goto on that
|
# Typically names are already definitions and therefore a goto on that
|
||||||
# name will always result on itself.
|
# name will always result on itself.
|
||||||
return set([self])
|
return {self}
|
||||||
|
|
||||||
def get_root_context(self):
|
def get_root_context(self):
|
||||||
return self.parent_context.get_root_context()
|
return self.parent_context.get_root_context()
|
||||||
@@ -386,7 +386,7 @@ def get_global_filters(evaluator, context, until_position, origin_scope):
|
|||||||
... def func():
|
... def func():
|
||||||
... y = None
|
... y = None
|
||||||
... '''))
|
... '''))
|
||||||
>>> module_node = script._get_module_node()
|
>>> module_node = script._module_node
|
||||||
>>> scope = next(module_node.iter_funcdefs())
|
>>> scope = next(module_node.iter_funcdefs())
|
||||||
>>> scope
|
>>> scope
|
||||||
<Function: func@3-5>
|
<Function: func@3-5>
|
||||||
|
|||||||
@@ -465,7 +465,7 @@ def _load_module(evaluator, path=None, code=None, sys_path=None, parent_module=N
|
|||||||
if path is not None and path.endswith(('.py', '.zip', '.egg')) \
|
if path is not None and path.endswith(('.py', '.zip', '.egg')) \
|
||||||
and dotted_path not in settings.auto_import_modules:
|
and dotted_path not in settings.auto_import_modules:
|
||||||
|
|
||||||
module_node = evaluator.grammar.parse(
|
module_node = evaluator.parse(
|
||||||
code=code, path=path, cache=True, diff_cache=True,
|
code=code, path=path, cache=True, diff_cache=True,
|
||||||
cache_path=settings.cache_directory)
|
cache_path=settings.cache_directory)
|
||||||
|
|
||||||
|
|||||||
@@ -263,8 +263,6 @@ def collections_namedtuple(evaluator, obj, arguments):
|
|||||||
This has to be done by processing the namedtuple class template and
|
This has to be done by processing the namedtuple class template and
|
||||||
evaluating the result.
|
evaluating the result.
|
||||||
|
|
||||||
.. note:: |jedi| only supports namedtuples on Python >2.6.
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
collections_context = obj.parent_context
|
collections_context = obj.parent_context
|
||||||
_class_template_set = collections_context.py__getattribute__(u'_class_template')
|
_class_template_set = collections_context.py__getattribute__(u'_class_template')
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ def eval_node(context, element):
|
|||||||
def eval_trailer(context, base_contexts, trailer):
|
def eval_trailer(context, base_contexts, trailer):
|
||||||
trailer_op, node = trailer.children[:2]
|
trailer_op, node = trailer.children[:2]
|
||||||
if node == ')': # `arglist` is optional.
|
if node == ')': # `arglist` is optional.
|
||||||
node = ()
|
node = None
|
||||||
|
|
||||||
if trailer_op == '[':
|
if trailer_op == '[':
|
||||||
trailer_op, node, _ = trailer.children
|
trailer_op, node, _ = trailer.children
|
||||||
@@ -149,7 +149,7 @@ def eval_trailer(context, base_contexts, trailer):
|
|||||||
name_or_str=node
|
name_or_str=node
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
assert trailer_op == '('
|
assert trailer_op == '(', 'trailer_op is actually %s' % trailer_op
|
||||||
args = arguments.TreeArguments(context.evaluator, context, node, trailer)
|
args = arguments.TreeArguments(context.evaluator, context, node, trailer)
|
||||||
return base_contexts.execute(args)
|
return base_contexts.execute(args)
|
||||||
|
|
||||||
@@ -287,10 +287,10 @@ def eval_or_test(context, or_test):
|
|||||||
# handle lazy evaluation of and/or here.
|
# handle lazy evaluation of and/or here.
|
||||||
if operator in ('and', 'or'):
|
if operator in ('and', 'or'):
|
||||||
left_bools = set(left.py__bool__() for left in types)
|
left_bools = set(left.py__bool__() for left in types)
|
||||||
if left_bools == set([True]):
|
if left_bools == {True}:
|
||||||
if operator == 'and':
|
if operator == 'and':
|
||||||
types = context.eval_node(right)
|
types = context.eval_node(right)
|
||||||
elif left_bools == set([False]):
|
elif left_bools == {False}:
|
||||||
if operator != 'and':
|
if operator != 'and':
|
||||||
types = context.eval_node(right)
|
types = context.eval_node(right)
|
||||||
# Otherwise continue, because of uncertainty.
|
# Otherwise continue, because of uncertainty.
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ def detect_additional_paths(evaluator, script_path):
|
|||||||
|
|
||||||
def _get_paths_from_buildout_script(evaluator, buildout_script_path):
|
def _get_paths_from_buildout_script(evaluator, buildout_script_path):
|
||||||
try:
|
try:
|
||||||
module_node = evaluator.grammar.parse(
|
module_node = evaluator.parse(
|
||||||
path=buildout_script_path,
|
path=buildout_script_path,
|
||||||
cache=True,
|
cache=True,
|
||||||
cache_path=settings.cache_directory
|
cache_path=settings.cache_directory
|
||||||
|
|||||||
@@ -4,11 +4,10 @@ from inspect import cleandoc
|
|||||||
from jedi._compatibility import literal_eval, force_unicode
|
from jedi._compatibility import literal_eval, force_unicode
|
||||||
from parso.python import tree
|
from parso.python import tree
|
||||||
|
|
||||||
_EXECUTE_NODES = set([
|
_EXECUTE_NODES = {'funcdef', 'classdef', 'import_from', 'import_name', 'test',
|
||||||
'funcdef', 'classdef', 'import_from', 'import_name', 'test', 'or_test',
|
'or_test', 'and_test', 'not_test', 'comparison', 'expr',
|
||||||
'and_test', 'not_test', 'comparison', 'expr', 'xor_expr', 'and_expr',
|
'xor_expr', 'and_expr', 'shift_expr', 'arith_expr',
|
||||||
'shift_expr', 'arith_expr', 'atom_expr', 'term', 'factor', 'power', 'atom'
|
'atom_expr', 'term', 'factor', 'power', 'atom'}
|
||||||
])
|
|
||||||
|
|
||||||
_FLOW_KEYWORDS = (
|
_FLOW_KEYWORDS = (
|
||||||
'try', 'except', 'finally', 'else', 'if', 'elif', 'with', 'for', 'while'
|
'try', 'except', 'finally', 'else', 'if', 'elif', 'with', 'for', 'while'
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ def setup_readline(namespace_module=__main__):
|
|||||||
lines = split_lines(text)
|
lines = split_lines(text)
|
||||||
position = (len(lines), len(lines[-1]))
|
position = (len(lines), len(lines[-1]))
|
||||||
name = get_on_completion_name(
|
name = get_on_completion_name(
|
||||||
interpreter._get_module_node(),
|
interpreter._module_node,
|
||||||
lines,
|
lines,
|
||||||
position
|
position
|
||||||
)
|
)
|
||||||
|
|||||||
4
setup.py
4
setup.py
@@ -32,7 +32,8 @@ setup(name='jedi',
|
|||||||
license='MIT',
|
license='MIT',
|
||||||
keywords='python completion refactoring vim',
|
keywords='python completion refactoring vim',
|
||||||
long_description=readme,
|
long_description=readme,
|
||||||
packages=find_packages(exclude=['test']),
|
packages=find_packages(exclude=['test', 'test.*']),
|
||||||
|
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*',
|
||||||
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']},
|
||||||
@@ -44,7 +45,6 @@ setup(name='jedi',
|
|||||||
'License :: OSI Approved :: MIT License',
|
'License :: OSI Approved :: MIT License',
|
||||||
'Operating System :: OS Independent',
|
'Operating System :: OS Independent',
|
||||||
'Programming Language :: Python :: 2',
|
'Programming Language :: Python :: 2',
|
||||||
'Programming Language :: Python :: 2.6',
|
|
||||||
'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.3',
|
||||||
|
|||||||
@@ -403,8 +403,6 @@ def test_func():
|
|||||||
x
|
x
|
||||||
|
|
||||||
|
|
||||||
# python >= 2.7
|
|
||||||
# Set literals are not valid in 2.6.
|
|
||||||
#? int()
|
#? int()
|
||||||
tuple({1})[0]
|
tuple({1})[0]
|
||||||
|
|
||||||
|
|||||||
@@ -286,8 +286,6 @@ with open('') as f:
|
|||||||
#? str()
|
#? str()
|
||||||
line
|
line
|
||||||
|
|
||||||
# Nested with statements don't exist in Python 2.6.
|
|
||||||
# python >= 2.7
|
|
||||||
with open('') as f1, open('') as f2:
|
with open('') as f1, open('') as f2:
|
||||||
#? ['closed']
|
#? ['closed']
|
||||||
f1.closed
|
f1.closed
|
||||||
|
|||||||
@@ -210,6 +210,5 @@ d[2]
|
|||||||
next(iter({a for a in range(10)}))
|
next(iter({a for a in range(10)}))
|
||||||
|
|
||||||
|
|
||||||
# with a set literal (also doesn't work in 2.6).
|
|
||||||
#? int()
|
#? int()
|
||||||
[a for a in {1, 2, 3}][0]
|
[a for a in {1, 2, 3}][0]
|
||||||
|
|||||||
@@ -211,6 +211,17 @@ class X():
|
|||||||
#?
|
#?
|
||||||
self.x()
|
self.x()
|
||||||
|
|
||||||
|
|
||||||
|
def decorator_var_args(function, *args):
|
||||||
|
return function(*args)
|
||||||
|
|
||||||
|
@decorator_var_args
|
||||||
|
def function_var_args(param):
|
||||||
|
return param
|
||||||
|
|
||||||
|
#? int()
|
||||||
|
function_var_args(1)
|
||||||
|
|
||||||
# -----------------
|
# -----------------
|
||||||
# method decorators
|
# method decorators
|
||||||
# -----------------
|
# -----------------
|
||||||
|
|||||||
@@ -288,8 +288,6 @@ third()[0]
|
|||||||
# -----------------
|
# -----------------
|
||||||
# set.add
|
# set.add
|
||||||
# -----------------
|
# -----------------
|
||||||
# Set literals are not valid in 2.6.
|
|
||||||
# python >= 2.7
|
|
||||||
st = {1.0}
|
st = {1.0}
|
||||||
for a in [1,2]:
|
for a in [1,2]:
|
||||||
st.add(a)
|
st.add(a)
|
||||||
|
|||||||
@@ -47,10 +47,6 @@ b
|
|||||||
class Employee:
|
class Employee:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# The typing library is not installable for Python 2.6, therefore ignore the
|
|
||||||
# following tests.
|
|
||||||
# python >= 2.7
|
|
||||||
|
|
||||||
from typing import List
|
from typing import List
|
||||||
x = [] # type: List[Employee]
|
x = [] # type: List[Employee]
|
||||||
#? Employee()
|
#? Employee()
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ Test the typing library, with docstrings. This is needed since annotations
|
|||||||
are not supported in python 2.7 else then annotating by comment (and this is
|
are not supported in python 2.7 else then annotating by comment (and this is
|
||||||
still TODO at 2016-01-23)
|
still TODO at 2016-01-23)
|
||||||
"""
|
"""
|
||||||
# There's no Python 2.6 typing module.
|
|
||||||
# python >= 2.7
|
|
||||||
import typing
|
import typing
|
||||||
class B:
|
class B:
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -116,8 +116,6 @@ tup4.index
|
|||||||
# -----------------
|
# -----------------
|
||||||
# set
|
# set
|
||||||
# -----------------
|
# -----------------
|
||||||
# Set literals are not valid in 2.6.
|
|
||||||
# python >= 2.7
|
|
||||||
set_t = {1,2}
|
set_t = {1,2}
|
||||||
|
|
||||||
#? ['clear', 'copy']
|
#? ['clear', 'copy']
|
||||||
|
|||||||
@@ -296,8 +296,6 @@ x = 32
|
|||||||
[x for x in something]
|
[x for x in something]
|
||||||
|
|
||||||
x = 3
|
x = 3
|
||||||
# Not supported syntax in Python 2.6.
|
|
||||||
# python >= 2.7
|
|
||||||
#< 1 (0,1), (0,10)
|
#< 1 (0,1), (0,10)
|
||||||
{x:1 for x in something}
|
{x:1 for x in something}
|
||||||
#< 10 (0,1), (0,10)
|
#< 10 (0,1), (0,10)
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ def parse_test_files_option(opt):
|
|||||||
opt = str(opt)
|
opt = str(opt)
|
||||||
if ':' in opt:
|
if ':' in opt:
|
||||||
(f_name, rest) = opt.split(':', 1)
|
(f_name, rest) = opt.split(':', 1)
|
||||||
return (f_name, list(map(int, rest.split(','))))
|
return f_name, list(map(int, rest.split(',')))
|
||||||
else:
|
else:
|
||||||
return (opt, [])
|
return opt, []
|
||||||
|
|
||||||
|
|
||||||
def pytest_generate_tests(metafunc):
|
def pytest_generate_tests(metafunc):
|
||||||
@@ -127,7 +127,7 @@ class StaticAnalysisCase(object):
|
|||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def cwd_tmpdir(monkeypatch, tmpdir):
|
def cwd_tmpdir(monkeypatch, tmpdir):
|
||||||
with helpers.set_cwd(tmpdir.dirpath):
|
with helpers.set_cwd(tmpdir.strpath):
|
||||||
yield tmpdir
|
yield tmpdir
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ class IntegrationTestCase(object):
|
|||||||
completions = self.script(environment).completions()
|
completions = self.script(environment).completions()
|
||||||
#import cProfile; cProfile.run('script.completions()')
|
#import cProfile; cProfile.run('script.completions()')
|
||||||
|
|
||||||
comp_str = set([c.name for c in completions])
|
comp_str = {c.name for c in completions}
|
||||||
return compare_cb(self, comp_str, set(literal_eval(self.correct)))
|
return compare_cb(self, comp_str, set(literal_eval(self.correct)))
|
||||||
|
|
||||||
def run_goto_definitions(self, compare_cb, environment):
|
def run_goto_definitions(self, compare_cb, environment):
|
||||||
|
|||||||
@@ -103,8 +103,8 @@ def test_completion_on_complex_literals(Script):
|
|||||||
_check_number(Script, '4.0j.', 'complex')
|
_check_number(Script, '4.0j.', 'complex')
|
||||||
# No dot no completion - I thought, but 4j is actually a literall after
|
# No dot no completion - I thought, but 4j is actually a literall after
|
||||||
# which a keyword like or is allowed. Good times, haha!
|
# which a keyword like or is allowed. Good times, haha!
|
||||||
assert (set([c.name for c in Script('4j').completions()]) ==
|
assert ({c.name for c in Script('4j').completions()} ==
|
||||||
set(['if', 'and', 'in', 'is', 'not', 'or']))
|
{'if', 'and', 'in', 'is', 'not', 'or'})
|
||||||
|
|
||||||
|
|
||||||
def test_goto_assignments_on_non_name(Script, environment):
|
def test_goto_assignments_on_non_name(Script, environment):
|
||||||
@@ -152,7 +152,7 @@ def test_goto_definition_not_multiple(Script):
|
|||||||
|
|
||||||
def test_usage_description(Script):
|
def test_usage_description(Script):
|
||||||
descs = [u.description for u in Script("foo = ''; foo").usages()]
|
descs = [u.description for u in Script("foo = ''; foo").usages()]
|
||||||
assert set(descs) == set(["foo = ''", 'foo'])
|
assert set(descs) == {"foo = ''", 'foo'}
|
||||||
|
|
||||||
|
|
||||||
def test_get_line_code(Script):
|
def test_get_line_code(Script):
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ def test_follow_import_incomplete(Script):
|
|||||||
|
|
||||||
# incomplete `from * import` part
|
# incomplete `from * import` part
|
||||||
datetime = check_follow_definition_types(Script, "from datetime import datetim")
|
datetime = check_follow_definition_types(Script, "from datetime import datetim")
|
||||||
assert set(datetime) == set(['class', 'instance']) # py33: builtin and pure py version
|
assert set(datetime) == {'class', 'instance'} # py33: builtin and pure py version
|
||||||
|
|
||||||
# os.path check
|
# os.path check
|
||||||
ospath = check_follow_definition_types(Script, "from os.path import abspat")
|
ospath = check_follow_definition_types(Script, "from os.path import abspat")
|
||||||
|
|||||||
@@ -68,25 +68,25 @@ def test_basedefinition_type(Script, environment):
|
|||||||
|
|
||||||
def test_basedefinition_type_import(Script):
|
def test_basedefinition_type_import(Script):
|
||||||
def get_types(source, **kwargs):
|
def get_types(source, **kwargs):
|
||||||
return set([t.type for t in Script(source, **kwargs).completions()])
|
return {t.type for t in Script(source, **kwargs).completions()}
|
||||||
|
|
||||||
# import one level
|
# import one level
|
||||||
assert get_types('import t') == set(['module'])
|
assert get_types('import t') == {'module'}
|
||||||
assert get_types('import ') == set(['module'])
|
assert get_types('import ') == {'module'}
|
||||||
assert get_types('import datetime; datetime') == set(['module'])
|
assert get_types('import datetime; datetime') == {'module'}
|
||||||
|
|
||||||
# from
|
# from
|
||||||
assert get_types('from datetime import timedelta') == set(['class'])
|
assert get_types('from datetime import timedelta') == {'class'}
|
||||||
assert get_types('from datetime import timedelta; timedelta') == set(['class'])
|
assert get_types('from datetime import timedelta; timedelta') == {'class'}
|
||||||
assert get_types('from json import tool') == set(['module'])
|
assert get_types('from json import tool') == {'module'}
|
||||||
assert get_types('from json import tool; tool') == set(['module'])
|
assert get_types('from json import tool; tool') == {'module'}
|
||||||
|
|
||||||
# import two levels
|
# import two levels
|
||||||
assert get_types('import json.tool; json') == set(['module'])
|
assert get_types('import json.tool; json') == {'module'}
|
||||||
assert get_types('import json.tool; json.tool') == set(['module'])
|
assert get_types('import json.tool; json.tool') == {'module'}
|
||||||
assert get_types('import json.tool; json.tool.main') == set(['function'])
|
assert get_types('import json.tool; json.tool.main') == {'function'}
|
||||||
assert get_types('import json.tool') == set(['module'])
|
assert get_types('import json.tool') == {'module'}
|
||||||
assert get_types('import json.tool', column=9) == set(['module'])
|
assert get_types('import json.tool', column=9) == {'module'}
|
||||||
|
|
||||||
|
|
||||||
def test_function_call_signature_in_doc(Script):
|
def test_function_call_signature_in_doc(Script):
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ else:
|
|||||||
exec source in global_map """, 'blub', 'exec'))
|
exec source in global_map """, 'blub', 'exec'))
|
||||||
|
|
||||||
|
|
||||||
class _GlobalNameSpace():
|
class _GlobalNameSpace:
|
||||||
class SideEffectContainer():
|
class SideEffectContainer:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ def test_numpy_like_non_zero():
|
|||||||
|
|
||||||
|
|
||||||
def test_nested_resolve():
|
def test_nested_resolve():
|
||||||
class XX():
|
class XX:
|
||||||
def x():
|
def x():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -168,7 +168,7 @@ def test_list():
|
|||||||
|
|
||||||
|
|
||||||
def test_slice():
|
def test_slice():
|
||||||
class Foo1():
|
class Foo1:
|
||||||
bar = []
|
bar = []
|
||||||
baz = 'xbarx'
|
baz = 'xbarx'
|
||||||
_assert_interpreter_complete('getattr(Foo1, baz[1:-1]).append',
|
_assert_interpreter_complete('getattr(Foo1, baz[1:-1]).append',
|
||||||
@@ -177,7 +177,7 @@ def test_slice():
|
|||||||
|
|
||||||
|
|
||||||
def test_getitem_side_effects():
|
def test_getitem_side_effects():
|
||||||
class Foo2():
|
class Foo2:
|
||||||
def __getitem__(self, index):
|
def __getitem__(self, index):
|
||||||
# Possible side effects here, should therefore not call this.
|
# Possible side effects here, should therefore not call this.
|
||||||
if True:
|
if True:
|
||||||
@@ -190,7 +190,7 @@ def test_getitem_side_effects():
|
|||||||
|
|
||||||
def test_property_error_oldstyle():
|
def test_property_error_oldstyle():
|
||||||
lst = []
|
lst = []
|
||||||
class Foo3():
|
class Foo3:
|
||||||
@property
|
@property
|
||||||
def bar(self):
|
def bar(self):
|
||||||
lst.append(1)
|
lst.append(1)
|
||||||
@@ -261,7 +261,7 @@ def test_completion_param_annotations():
|
|||||||
a, b, c = c.params
|
a, b, c = c.params
|
||||||
assert a._goto_definitions() == []
|
assert a._goto_definitions() == []
|
||||||
assert [d.name for d in b._goto_definitions()] == ['str']
|
assert [d.name for d in b._goto_definitions()] == ['str']
|
||||||
assert set([d.name for d in c._goto_definitions()]) == set(['int', 'float'])
|
assert {d.name for d in c._goto_definitions()} == {'int', 'float'}
|
||||||
|
|
||||||
|
|
||||||
def test_more_complex_instances():
|
def test_more_complex_instances():
|
||||||
@@ -269,7 +269,7 @@ def test_more_complex_instances():
|
|||||||
def foo(self, other):
|
def foo(self, other):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
class Base():
|
class Base:
|
||||||
def wow(self):
|
def wow(self):
|
||||||
return Something()
|
return Something()
|
||||||
|
|
||||||
|
|||||||
@@ -63,3 +63,12 @@ def test_complete_at_zero(Script):
|
|||||||
|
|
||||||
s = Script("", 1, 0).completions()
|
s = Script("", 1, 0).completions()
|
||||||
assert len(s) > 0
|
assert len(s) > 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_wrong_encoding(Script, cwd_tmpdir):
|
||||||
|
x = cwd_tmpdir.join('x.py')
|
||||||
|
# Use both latin-1 and utf-8 (a really broken file).
|
||||||
|
x.write_binary(u'foobar = 1\nä'.encode('latin-1') + 'ä'.encode())
|
||||||
|
|
||||||
|
c, = Script('import x; x.foo', sys_path=['.']).completions()
|
||||||
|
assert c.name == 'foobar'
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
def test_module_attributes(Script):
|
def test_module_attributes(Script):
|
||||||
def_, = Script('__name__').completions()
|
def_, = Script('__name__').completions()
|
||||||
assert def_.name == '__name__'
|
assert def_.name == '__name__'
|
||||||
assert def_.line == None
|
assert def_.line is None
|
||||||
assert def_.column == None
|
assert def_.column is None
|
||||||
str_, = def_._goto_definitions()
|
str_, = def_._goto_definitions()
|
||||||
assert str_.name == 'str'
|
assert str_.name == 'str'
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ import pytest
|
|||||||
from jedi._compatibility import find_module_py33, find_module
|
from jedi._compatibility import find_module_py33, find_module
|
||||||
from ..helpers import cwd_at
|
from ..helpers import cwd_at
|
||||||
|
|
||||||
from jedi._compatibility import is_py26
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif('sys.version_info < (3,3)')
|
@pytest.mark.skipif('sys.version_info < (3,3)')
|
||||||
def test_find_module_py33():
|
def test_find_module_py33():
|
||||||
@@ -163,9 +161,8 @@ def test_complete_on_empty_import(Script):
|
|||||||
# relative import
|
# relative import
|
||||||
assert 10 < len(Script("from . import classes", 1, 6, 'whatever.py').completions()) < 30
|
assert 10 < len(Script("from . import classes", 1, 6, 'whatever.py').completions()) < 30
|
||||||
|
|
||||||
wanted = set(['ImportError', 'import', 'ImportWarning'])
|
wanted = {'ImportError', 'import', 'ImportWarning'}
|
||||||
assert set([c.name for c in Script("import").completions()]) == wanted
|
assert {c.name for c in Script("import").completions()} == wanted
|
||||||
if not is_py26: # python 2.6 doesn't always come with a library `import*`.
|
|
||||||
assert len(Script("import import", path='').completions()) > 0
|
assert len(Script("import import", path='').completions()) > 0
|
||||||
|
|
||||||
# 111
|
# 111
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ with "Black Box Tests".
|
|||||||
from textwrap import dedent
|
from textwrap import dedent
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from jedi._compatibility import is_py26
|
|
||||||
|
|
||||||
|
|
||||||
# The namedtuple is different for different Python2.7 versions. Some versions
|
# The namedtuple is different for different Python2.7 versions. Some versions
|
||||||
@@ -28,9 +27,6 @@ def test_namedtuple_str(letter, expected, Script):
|
|||||||
dave.%s""") % letter
|
dave.%s""") % letter
|
||||||
result = Script(source).completions()
|
result = Script(source).completions()
|
||||||
completions = set(r.name for r in result)
|
completions = set(r.name for r in result)
|
||||||
if is_py26:
|
|
||||||
assert completions == set()
|
|
||||||
else:
|
|
||||||
assert completions == set(expected)
|
assert completions == set(expected)
|
||||||
|
|
||||||
|
|
||||||
@@ -42,10 +38,7 @@ def test_namedtuple_list(Script):
|
|||||||
garfield.l""")
|
garfield.l""")
|
||||||
result = Script(source).completions()
|
result = Script(source).completions()
|
||||||
completions = set(r.name for r in result)
|
completions = set(r.name for r in result)
|
||||||
if is_py26:
|
assert completions == {'legs', 'length', 'large'}
|
||||||
assert completions == set()
|
|
||||||
else:
|
|
||||||
assert completions == set(['legs', 'length', 'large'])
|
|
||||||
|
|
||||||
|
|
||||||
def test_namedtuple_content(Script):
|
def test_namedtuple_content(Script):
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ def test_paths_from_assignment(Script):
|
|||||||
expr_stmt = script._get_module_node().children[0]
|
expr_stmt = script._get_module_node().children[0]
|
||||||
return set(sys_path._paths_from_assignment(script._get_module(), expr_stmt))
|
return set(sys_path._paths_from_assignment(script._get_module(), expr_stmt))
|
||||||
|
|
||||||
assert paths('sys.path[0:0] = ["a"]') == set(['/foo/a'])
|
assert paths('sys.path[0:0] = ["a"]') == {'/foo/a'}
|
||||||
assert paths('sys.path = ["b", 1, x + 3, y, "c"]') == set(['/foo/b', '/foo/c'])
|
assert paths('sys.path = ["b", 1, x + 3, y, "c"]') == {'/foo/b', '/foo/c'}
|
||||||
assert paths('sys.path = a = ["a"]') == set(['/foo/a'])
|
assert paths('sys.path = a = ["a"]') == {'/foo/a'}
|
||||||
|
|
||||||
# Fail for complicated examples.
|
# Fail for complicated examples.
|
||||||
assert paths('sys.path, other = ["a"], 2') == set()
|
assert paths('sys.path, other = ["a"], 2') == set()
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from parso.python import tree
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
class TestCallAndName():
|
class TestCallAndName:
|
||||||
def get_call(self, source):
|
def get_call(self, source):
|
||||||
# Get the simple_stmt and then the first one.
|
# Get the simple_stmt and then the first one.
|
||||||
node = parse(source).children[0]
|
node = parse(source).children[0]
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ def test_scipy_speed(Script):
|
|||||||
s = 'import scipy.weave; scipy.weave.inline('
|
s = 'import scipy.weave; scipy.weave.inline('
|
||||||
script = Script(s, 1, len(s), '')
|
script = Script(s, 1, len(s), '')
|
||||||
script.call_signatures()
|
script.call_signatures()
|
||||||
#print(jedi.imports.imports_processed)
|
|
||||||
|
|
||||||
|
|
||||||
@_check_speed(0.8)
|
@_check_speed(0.8)
|
||||||
@@ -63,10 +62,11 @@ def test_no_repr_computation(Script):
|
|||||||
unwanted computation of repr(). Exemple : big pandas data.
|
unwanted computation of repr(). Exemple : big pandas data.
|
||||||
See issue #919.
|
See issue #919.
|
||||||
"""
|
"""
|
||||||
class SlowRepr():
|
class SlowRepr:
|
||||||
"class to test what happens if __repr__ is very slow."
|
"class to test what happens if __repr__ is very slow."
|
||||||
def some_method(self):
|
def some_method(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
time.sleep(0.2)
|
time.sleep(0.2)
|
||||||
test = SlowRepr()
|
test = SlowRepr()
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ class TestSetupReadline(unittest.TestCase):
|
|||||||
string = 'os.path.join("a").upper'
|
string = 'os.path.join("a").upper'
|
||||||
assert self.completions(string) == [string]
|
assert self.completions(string) == [string]
|
||||||
|
|
||||||
c = set(['os.' + d for d in dir(os) if d.startswith('ch')])
|
c = {'os.' + d for d in dir(os) if d.startswith('ch')}
|
||||||
assert set(self.completions('os.ch')) == set(c)
|
assert set(self.completions('os.ch')) == set(c)
|
||||||
finally:
|
finally:
|
||||||
del self.namespace.sys
|
del self.namespace.sys
|
||||||
@@ -68,12 +68,12 @@ class TestSetupReadline(unittest.TestCase):
|
|||||||
|
|
||||||
def test_import(self):
|
def test_import(self):
|
||||||
s = 'from os.path import a'
|
s = 'from os.path import a'
|
||||||
assert set(self.completions(s)) == set([s + 'ltsep', s + 'bspath'])
|
assert set(self.completions(s)) == {s + 'ltsep', s + 'bspath'}
|
||||||
assert self.completions('import keyword') == ['import keyword']
|
assert self.completions('import keyword') == ['import keyword']
|
||||||
|
|
||||||
import os
|
import os
|
||||||
s = 'from os import '
|
s = 'from os import '
|
||||||
goal = set([s + el for el in dir(os)])
|
goal = {s + el for el in dir(os)}
|
||||||
# There are minor differences, e.g. the dir doesn't include deleted
|
# There are minor differences, e.g. the dir doesn't include deleted
|
||||||
# items as well as items that are not only available on linux.
|
# items as well as items that are not only available on linux.
|
||||||
assert len(set(self.completions(s)).symmetric_difference(goal)) < 20
|
assert len(set(self.completions(s)).symmetric_difference(goal)) < 20
|
||||||
@@ -85,7 +85,7 @@ class TestSetupReadline(unittest.TestCase):
|
|||||||
|
|
||||||
def test_preexisting_values(self):
|
def test_preexisting_values(self):
|
||||||
self.namespace.a = range(10)
|
self.namespace.a = range(10)
|
||||||
assert set(self.completions('a.')) == set(['a.' + n for n in dir(range(1))])
|
assert set(self.completions('a.')) == {'a.' + n for n in dir(range(1))}
|
||||||
del self.namespace.a
|
del self.namespace.a
|
||||||
|
|
||||||
def test_colorama(self):
|
def test_colorama(self):
|
||||||
|
|||||||
4
tox.ini
4
tox.ini
@@ -24,10 +24,6 @@ setenv =
|
|||||||
env37: JEDI_TEST_ENVIRONMENT=37
|
env37: JEDI_TEST_ENVIRONMENT=37
|
||||||
commands =
|
commands =
|
||||||
py.test {posargs:jedi test}
|
py.test {posargs:jedi test}
|
||||||
[testenv:py26]
|
|
||||||
deps =
|
|
||||||
unittest2
|
|
||||||
{[testenv]deps}
|
|
||||||
[testenv:py27]
|
[testenv:py27]
|
||||||
deps =
|
deps =
|
||||||
# for testing the typing module
|
# for testing the typing module
|
||||||
|
|||||||
Reference in New Issue
Block a user