From af0d270c8a0c6bde7979ae59cb71108fa987c324 Mon Sep 17 00:00:00 2001 From: bcolsen Date: Wed, 8 Feb 2017 00:53:21 -0700 Subject: [PATCH 1/8] Numpydoc monkey patch for jedi 0.10.0 --- spyder/utils/introspection/jedi_patch.py | 178 ++++++++++++--------- spyder/utils/introspection/jedi_plugin.py | 4 +- spyder/utils/introspection/manager.py | 2 +- spyder/utils/introspection/numpy_docstr.py | 22 ++- 4 files changed, 117 insertions(+), 89 deletions(-) diff --git a/spyder/utils/introspection/jedi_patch.py b/spyder/utils/introspection/jedi_patch.py index 1790be10d7c..93a12de3185 100644 --- a/spyder/utils/introspection/jedi_patch.py +++ b/spyder/utils/introspection/jedi_patch.py @@ -22,10 +22,11 @@ def apply(): See [1] and [2] module docstring.""" from spyder.utils.programs import is_module_installed - if is_module_installed('jedi', '=0.9.0'): + if (is_module_installed('jedi', '=0.9.0') or + is_module_installed('jedi', '=0.10.0')): import jedi else: - raise ImportError("jedi %s can't be patched" % jedi.__version__) + raise ImportError("jedi not =0.9.0 or 0.10.0, can't be patched") # [1] Adding numpydoc type returns to docstrings from spyder.utils.introspection import numpy_docstr @@ -36,11 +37,9 @@ def apply(): # [2] Adding type returns for compiled objects in jedi # Patching jedi.evaluate.compiled.CompiledObject... - from jedi.evaluate.compiled import ( - CompiledObject, builtin, _create_from_name, debug) + if is_module_installed('jedi', '=0.9.0'): + from jedi.evaluate.compiled import builtin, _create_from_name, debug - class CompiledObject(CompiledObject): - # ...adding docstrings int _execute_function... def _execute_function(self, evaluator, params): if self.type != 'funcdef': return @@ -64,81 +63,100 @@ def _execute_function(self, evaluator, params): for result in evaluator.execute(bltn_obj, params): yield result - # ...docstrings needs a raw_doc property - @property - def raw_doc(self): - try: - doc = unicode(self.doc) - except NameError: # python 3 - doc = self.doc - return doc + else: + from jedi.evaluate.compiled import debug + from jedi._compatibility import builtins as _builtins - jedi.evaluate.compiled.CompiledObject = CompiledObject - - # [3] Fixing introspection for matplotlib Axes objects - # Patching jedi.evaluate.precedence... - from jedi.evaluate.precedence import tree, calculate - - def calculate_children(evaluator, children): - """ - Calculate a list of children with operators. - """ - iterator = iter(children) - types = evaluator.eval_element(next(iterator)) - for operator in iterator: - try:# PATCH: Catches StopIteration error - right = next(iterator) - if tree.is_node(operator, 'comp_op'): # not in / is not - operator = ' '.join(str(c.value) for c in operator.children) - - # handle lazy evaluation of and/or here. - if operator in ('and', 'or'): - left_bools = set([left.py__bool__() for left in types]) - if left_bools == set([True]): - if operator == 'and': - types = evaluator.eval_element(right) - elif left_bools == set([False]): - if operator != 'and': - types = evaluator.eval_element(right) - # Otherwise continue, because of uncertainty. + def _execute_function(self, params): + from spyder.utils.introspection import numpy_docstr + if self.type != 'funcdef': + return + types = set([]) + types |= set(numpy_docstr.find_return_types(self.parent_context, self)) + debug.dbg('docstrings type return: %s in %s', types, self) + for name in self._parse_function_doc()[1].split(): + try: + bltn_obj = getattr(_builtins, name) + except AttributeError: + continue else: - types = calculate(evaluator, types, operator, - evaluator.eval_element(right)) - except StopIteration: - debug.warning('calculate_children StopIteration %s', types) - debug.dbg('calculate_children types %s', types) - return types - - jedi.evaluate.precedence.calculate_children = calculate_children - - # [4] Fixing introspection for matplotlib Axes objects - # Patching jedi.evaluate.precedence... - from jedi.evaluate.representation import ( - InstanceName, Instance, compiled, FunctionExecution, InstanceElement) - - def get_instance_el(evaluator, instance, var, is_class_var=False): - """ - Returns an InstanceElement if it makes sense, otherwise leaves the object - untouched. - - Basically having an InstanceElement is context information. That is needed - in quite a lot of cases, which includes Nodes like ``power``, that need to - know where a self name comes from for example. - """ - if isinstance(var, tree.Name): - parent = get_instance_el(evaluator, instance, var.parent, is_class_var) - return InstanceName(var, parent) - # PATCH: compiled objects can be None - elif var is None: - return var - elif var.type != 'funcdef' \ - and isinstance(var, (Instance, compiled.CompiledObject, tree.Leaf, - tree.Module, FunctionExecution)): - return var - - var = evaluator.wrap(var) - return InstanceElement(evaluator, instance, var, is_class_var) - - jedi.evaluate.representation.get_instance_el = get_instance_el + if bltn_obj is None: + # We want to evaluate everything except None. + # TODO do we? + continue + bltn_obj = create(self.evaluator, bltn_obj) + types |= set(self.evaluator.execute(bltn_obj, params)) + for result in types: + yield result + + jedi.evaluate.compiled.CompiledObject._execute_function = _execute_function + + + if is_module_installed('jedi', '=0.9.0'): + # [3] Fixing introspection for matplotlib Axes objects + # Patching jedi.evaluate.precedence... + from jedi.evaluate.precedence import tree, calculate + + def calculate_children(evaluator, children): + """ + Calculate a list of children with operators. + """ + iterator = iter(children) + types = evaluator.eval_element(next(iterator)) + for operator in iterator: + try:# PATCH: Catches StopIteration error + right = next(iterator) + if tree.is_node(operator, 'comp_op'): # not in / is not + operator = ' '.join(str(c.value) for c in operator.children) + + # handle lazy evaluation of and/or here. + if operator in ('and', 'or'): + left_bools = set([left.py__bool__() for left in types]) + if left_bools == set([True]): + if operator == 'and': + types = evaluator.eval_element(right) + elif left_bools == set([False]): + if operator != 'and': + types = evaluator.eval_element(right) + # Otherwise continue, because of uncertainty. + else: + types = calculate(evaluator, types, operator, + evaluator.eval_element(right)) + except StopIteration: + debug.warning('calculate_children StopIteration %s', types) + debug.dbg('calculate_children types %s', types) + return types + + jedi.evaluate.precedence.calculate_children = calculate_children + + # [4] Fixing introspection for matplotlib Axes objects + # Patching jedi.evaluate.precedence... + from jedi.evaluate.representation import ( + InstanceName, Instance, compiled, FunctionExecution, InstanceElement) + + def get_instance_el(evaluator, instance, var, is_class_var=False): + """ + Returns an InstanceElement if it makes sense, otherwise leaves the object + untouched. + + Basically having an InstanceElement is context information. That is needed + in quite a lot of cases, which includes Nodes like ``power``, that need to + know where a self name comes from for example. + """ + if isinstance(var, tree.Name): + parent = get_instance_el(evaluator, instance, var.parent, is_class_var) + return InstanceName(var, parent) + # PATCH: compiled objects can be None + elif var is None: + return var + elif var.type != 'funcdef' \ + and isinstance(var, (Instance, compiled.CompiledObject, tree.Leaf, + tree.Module, FunctionExecution)): + return var + + var = evaluator.wrap(var) + return InstanceElement(evaluator, instance, var, is_class_var) + + jedi.evaluate.representation.get_instance_el = get_instance_el return jedi diff --git a/spyder/utils/introspection/jedi_plugin.py b/spyder/utils/introspection/jedi_plugin.py index c66d5e8afbb..d46c5739dcc 100644 --- a/spyder/utils/introspection/jedi_plugin.py +++ b/spyder/utils/introspection/jedi_plugin.py @@ -25,11 +25,13 @@ try: from spyder.utils.introspection import jedi_patch jedi = jedi_patch.apply() - except ImportError: + except ImportError as err: import jedi + debug_print(jedi.__version__ +' '+ str(err)) except ImportError: jedi = None +#jedi.set_debug_function() class JediPlugin(IntrospectionPlugin): """ diff --git a/spyder/utils/introspection/manager.py b/spyder/utils/introspection/manager.py index eb5df245754..6eb0e1a9c79 100644 --- a/spyder/utils/introspection/manager.py +++ b/spyder/utils/introspection/manager.py @@ -33,7 +33,7 @@ _("Editor's code completion, go-to-definition and help"), required_version=ROPE_REQVER) -JEDI_REQVER = '=0.9.0' +JEDI_REQVER = '>=0.9.0' dependencies.add('jedi', _("Editor's code completion, go-to-definition and help"), required_version=JEDI_REQVER) diff --git a/spyder/utils/introspection/numpy_docstr.py b/spyder/utils/introspection/numpy_docstr.py index c3ff0e83c1d..6141abf00f2 100644 --- a/spyder/utils/introspection/numpy_docstr.py +++ b/spyder/utils/introspection/numpy_docstr.py @@ -15,7 +15,9 @@ from ast import literal_eval import re -from jedi._compatibility import is_py3 +from spyder.utils.programs import is_module_installed + +from jedi._compatibility import u, is_py3 from jedi.evaluate.cache import memoize_default from jedi.evaluate.docstrings import (_evaluate_for_statement_string, _strip_rst_role, @@ -106,8 +108,8 @@ def _search_return_in_numpydocstr(docstr): return found -@memoize_default(None, evaluator_is_first_arg=True) -def find_return_types(evaluator, func): +#@memoize_default() +def find_return_types(module_context, func): """ Determines a set of potential return types for `func` using docstring hints :type evaluator: jedi.evaluate.Evaluator @@ -140,11 +142,17 @@ def search_return_in_docstr(docstr): # Check for numpy style return hint found = _search_return_in_numpydocstr(docstr) return found - - docstr = func.raw_doc - module = func.get_parent_until() + try: + docstr = func.raw_doc + except AttributeError: + docstr = func.doc types = [] for type_str in search_return_in_docstr(docstr): - type_ = _evaluate_for_statement_string(evaluator, type_str, module) + if is_module_installed('jedi', '=0.10.0'): + type_ = _evaluate_for_statement_string(module_context, type_str) + else: + module = func.get_parent_until() + type_ = _evaluate_for_statement_string(module_context, type_str, module) types.extend(type_) return types + From d233969433ac489508def5e0cbd98234a93bb5c4 Mon Sep 17 00:00:00 2001 From: bcolsen Date: Wed, 8 Feb 2017 21:18:17 -0700 Subject: [PATCH 2/8] Code clean up and PEP8 --- spyder/utils/introspection/jedi_patch.py | 47 ++++++++++++---------- spyder/utils/introspection/jedi_plugin.py | 4 +- spyder/utils/introspection/numpy_docstr.py | 8 ++-- 3 files changed, 31 insertions(+), 28 deletions(-) diff --git a/spyder/utils/introspection/jedi_patch.py b/spyder/utils/introspection/jedi_patch.py index 93a12de3185..d6cf23cfdb6 100644 --- a/spyder/utils/introspection/jedi_patch.py +++ b/spyder/utils/introspection/jedi_patch.py @@ -22,7 +22,7 @@ def apply(): See [1] and [2] module docstring.""" from spyder.utils.programs import is_module_installed - if (is_module_installed('jedi', '=0.9.0') or + if (is_module_installed('jedi', '=0.9.0') or is_module_installed('jedi', '=0.10.0')): import jedi else: @@ -38,7 +38,8 @@ def apply(): # [2] Adding type returns for compiled objects in jedi # Patching jedi.evaluate.compiled.CompiledObject... if is_module_installed('jedi', '=0.9.0'): - from jedi.evaluate.compiled import builtin, _create_from_name, debug + from jedi.evaluate.compiled import (builtin, _create_from_name, + debug, CompiledObject) def _execute_function(self, evaluator, params): if self.type != 'funcdef': @@ -57,14 +58,15 @@ def _execute_function(self, evaluator, params): except AttributeError: continue else: - if isinstance(bltn_obj, CompiledObject) and bltn_obj.obj is None: + if (isinstance(bltn_obj, CompiledObject) and + bltn_obj.obj is None): # We want everything except None. continue for result in evaluator.execute(bltn_obj, params): yield result - else: - from jedi.evaluate.compiled import debug + else: # Code for Jedi 0.10.0 + from jedi.evaluate.compiled import debug, create from jedi._compatibility import builtins as _builtins def _execute_function(self, params): @@ -72,7 +74,8 @@ def _execute_function(self, params): if self.type != 'funcdef': return types = set([]) - types |= set(numpy_docstr.find_return_types(self.parent_context, self)) + types |= set(numpy_docstr.find_return_types(self.parent_context, + self)) debug.dbg('docstrings type return: %s in %s', types, self) for name in self._parse_function_doc()[1].split(): try: @@ -82,7 +85,6 @@ def _execute_function(self, params): else: if bltn_obj is None: # We want to evaluate everything except None. - # TODO do we? continue bltn_obj = create(self.evaluator, bltn_obj) types |= set(self.evaluator.execute(bltn_obj, params)) @@ -90,8 +92,7 @@ def _execute_function(self, params): yield result jedi.evaluate.compiled.CompiledObject._execute_function = _execute_function - - + if is_module_installed('jedi', '=0.9.0'): # [3] Fixing introspection for matplotlib Axes objects # Patching jedi.evaluate.precedence... @@ -104,10 +105,11 @@ def calculate_children(evaluator, children): iterator = iter(children) types = evaluator.eval_element(next(iterator)) for operator in iterator: - try:# PATCH: Catches StopIteration error + try: # PATCH: Catches StopIteration error right = next(iterator) if tree.is_node(operator, 'comp_op'): # not in / is not - operator = ' '.join(str(c.value) for c in operator.children) + operator = ' '.join(str(c.value) for c in + operator.children) # handle lazy evaluation of and/or here. if operator in ('and', 'or'): @@ -131,27 +133,30 @@ def calculate_children(evaluator, children): # [4] Fixing introspection for matplotlib Axes objects # Patching jedi.evaluate.precedence... - from jedi.evaluate.representation import ( - InstanceName, Instance, compiled, FunctionExecution, InstanceElement) + from jedi.evaluate.representation import (InstanceName, Instance, + compiled, FunctionExecution, + InstanceElement) def get_instance_el(evaluator, instance, var, is_class_var=False): """ - Returns an InstanceElement if it makes sense, otherwise leaves the object - untouched. + Returns an InstanceElement if it makes sense, otherwise leaves the + object untouched. - Basically having an InstanceElement is context information. That is needed - in quite a lot of cases, which includes Nodes like ``power``, that need to - know where a self name comes from for example. + Basically having an InstanceElement is context information. That is + needed in quite a lot of cases, which includes Nodes like + ``power``, that need to know where a self name comes from for + example. """ if isinstance(var, tree.Name): - parent = get_instance_el(evaluator, instance, var.parent, is_class_var) + parent = get_instance_el(evaluator, instance, var.parent, + is_class_var) return InstanceName(var, parent) # PATCH: compiled objects can be None elif var is None: return var elif var.type != 'funcdef' \ - and isinstance(var, (Instance, compiled.CompiledObject, tree.Leaf, - tree.Module, FunctionExecution)): + and isinstance(var, (Instance, compiled.CompiledObject, + tree.Leaf, tree.Module, FunctionExecution)): return var var = evaluator.wrap(var) diff --git a/spyder/utils/introspection/jedi_plugin.py b/spyder/utils/introspection/jedi_plugin.py index d46c5739dcc..c66d5e8afbb 100644 --- a/spyder/utils/introspection/jedi_plugin.py +++ b/spyder/utils/introspection/jedi_plugin.py @@ -25,13 +25,11 @@ try: from spyder.utils.introspection import jedi_patch jedi = jedi_patch.apply() - except ImportError as err: + except ImportError: import jedi - debug_print(jedi.__version__ +' '+ str(err)) except ImportError: jedi = None -#jedi.set_debug_function() class JediPlugin(IntrospectionPlugin): """ diff --git a/spyder/utils/introspection/numpy_docstr.py b/spyder/utils/introspection/numpy_docstr.py index 6141abf00f2..d53eb268f1c 100644 --- a/spyder/utils/introspection/numpy_docstr.py +++ b/spyder/utils/introspection/numpy_docstr.py @@ -143,16 +143,16 @@ def search_return_in_docstr(docstr): found = _search_return_in_numpydocstr(docstr) return found try: - docstr = func.raw_doc + docstr = u(func.raw_doc) except AttributeError: - docstr = func.doc + docstr = u(func.doc) types = [] for type_str in search_return_in_docstr(docstr): if is_module_installed('jedi', '=0.10.0'): type_ = _evaluate_for_statement_string(module_context, type_str) else: module = func.get_parent_until() - type_ = _evaluate_for_statement_string(module_context, type_str, module) + type_ = _evaluate_for_statement_string(module_context, + type_str, module) types.extend(type_) return types - From a252d1c7e8033419726138fffa9841d030c6a3fb Mon Sep 17 00:00:00 2001 From: bcolsen Date: Thu, 9 Feb 2017 21:17:08 -0700 Subject: [PATCH 3/8] Remove jedi 0.9.0 pinning --- README.md | 2 +- continuous_integration/conda-recipes/spyder/meta.yaml | 2 +- doc/installation.rst | 2 +- setup.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4011720acdc..2e110bdde86 100644 --- a/README.md +++ b/README.md @@ -143,7 +143,7 @@ a Python version greater than 2.7 (Python 3.2 is not supported anymore). * **Python** 2.7 or 3.3+ * **PyQt5** 5.2+ or **PyQt4** 4.6+: PyQt5 is recommended. * **qtconsole** 4.2.0+: Enhanced Python interpreter. -* **Rope** and **Jedi** 0.9.0: Editor code completion, calltips +* **Rope** and **Jedi**: Editor code completion, calltips and go-to-definition. * **Pyflakes**: Real-time code analysis. * **Sphinx**: Rich text mode for the Help pane. diff --git a/continuous_integration/conda-recipes/spyder/meta.yaml b/continuous_integration/conda-recipes/spyder/meta.yaml index 41f90cbaa8e..e0e971dbab8 100644 --- a/continuous_integration/conda-recipes/spyder/meta.yaml +++ b/continuous_integration/conda-recipes/spyder/meta.yaml @@ -23,7 +23,7 @@ requirements: - rope 0.9.* # [py34 or py35] - rope # [py27] - pyflakes - - jedi 0.9.* + - jedi - qtconsole - nbconvert - pygments diff --git a/doc/installation.rst b/doc/installation.rst index 678ba8f381a..9795e3e5aa2 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -161,7 +161,7 @@ The requirements to run Spyder are: enhanced Python interpreter. * `Rope `_ >=0.9.4 and - `Jedi ` 0.9.0 -- for code completion, + `Jedi ` >=0.9.0 -- for code completion, go-to-definition and calltips on the Editor. * `Pyflakes `_ -- for real-time diff --git a/setup.py b/setup.py index ecb20ddcbfc..9de1cf79e45 100644 --- a/setup.py +++ b/setup.py @@ -272,7 +272,7 @@ def run(self): install_requires = [ 'rope_py3k' if PY3 else 'rope>=0.9.4', - 'jedi==0.9.0', + 'jedi>=0.9.0', 'pyflakes', 'pygments>=2.0', 'qtconsole>=4.2.0', From 113f5ef0f3f780bf9efc5c46369ec5f186eeaed1 Mon Sep 17 00:00:00 2001 From: bcolsen Date: Wed, 22 Feb 2017 21:52:31 -0700 Subject: [PATCH 4/8] cache fix --- spyder/utils/introspection/numpy_docstr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spyder/utils/introspection/numpy_docstr.py b/spyder/utils/introspection/numpy_docstr.py index d53eb268f1c..a17a3720757 100644 --- a/spyder/utils/introspection/numpy_docstr.py +++ b/spyder/utils/introspection/numpy_docstr.py @@ -108,7 +108,7 @@ def _search_return_in_numpydocstr(docstr): return found -#@memoize_default() +@memoize_default(None, evaluator_is_first_arg=True) def find_return_types(module_context, func): """ Determines a set of potential return types for `func` using docstring hints From 5879b89b79a566e2d140fe137496e2ac1d2a6e8e Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Thu, 23 Feb 2017 10:04:48 -0500 Subject: [PATCH 5/8] Testing: Install Jedi with pip in CircleCI to use 0.10.0 Conda packages are still at 0.9.0 --- circle.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/circle.yml b/circle.yml index cf1ac512888..3ee0e7df44e 100644 --- a/circle.yml +++ b/circle.yml @@ -10,9 +10,9 @@ machine: TRAVIS_OS_NAME: "linux" CONDA_DEPENDENCIES_FLAGS: "--quiet" CONDA_DEPENDENCIES: > - rope jedi pyflakes sphinx pygments pylint pep8 psutil nbconvert qtawesome pickleshare + rope pyflakes sphinx pygments pylint pep8 psutil nbconvert qtawesome pickleshare qtpy pyzmq chardet mock nomkl pandas pytest pytest-cov numpydoc scipy - PIP_DEPENDENCIES: "coveralls pytest-qt flaky" + PIP_DEPENDENCIES: "coveralls flaky jedi pytest-qt" dependencies: pre: From f9fe24d67ee7691857f04e0175f8ade3e1979b6f Mon Sep 17 00:00:00 2001 From: bcolsen Date: Thu, 23 Feb 2017 23:06:43 -0700 Subject: [PATCH 6/8] disable cache --- spyder/utils/introspection/numpy_docstr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spyder/utils/introspection/numpy_docstr.py b/spyder/utils/introspection/numpy_docstr.py index a17a3720757..6e679ca82bf 100644 --- a/spyder/utils/introspection/numpy_docstr.py +++ b/spyder/utils/introspection/numpy_docstr.py @@ -108,7 +108,7 @@ def _search_return_in_numpydocstr(docstr): return found -@memoize_default(None, evaluator_is_first_arg=True) +# @memoize_default(None, evaluator_is_first_arg=True) def find_return_types(module_context, func): """ Determines a set of potential return types for `func` using docstring hints From 4e6a7f67246c0679085adf26f07d976390dfec41 Mon Sep 17 00:00:00 2001 From: bcolsen Date: Fri, 24 Feb 2017 22:33:32 -0700 Subject: [PATCH 7/8] Change the tests? --- spyder/utils/introspection/jedi_plugin.py | 1 - spyder/utils/introspection/numpy_docstr.py | 2 +- spyder/utils/introspection/test/test_jedi_plugin.py | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/spyder/utils/introspection/jedi_plugin.py b/spyder/utils/introspection/jedi_plugin.py index c66d5e8afbb..1ff5a7da66e 100644 --- a/spyder/utils/introspection/jedi_plugin.py +++ b/spyder/utils/introspection/jedi_plugin.py @@ -54,7 +54,6 @@ def get_completions(self, info): completions = self.get_jedi_object('completions', info) if DEBUG_EDITOR: log_last_error(LOG_FILENAME, str("comp: " + str(completions)[:100])) - debug_print("comp: " + str(completions)[:100]) completions = [(c.name, c.type) for c in completions] debug_print(str(completions)[:100]) return completions diff --git a/spyder/utils/introspection/numpy_docstr.py b/spyder/utils/introspection/numpy_docstr.py index 6e679ca82bf..08432459c00 100644 --- a/spyder/utils/introspection/numpy_docstr.py +++ b/spyder/utils/introspection/numpy_docstr.py @@ -107,7 +107,7 @@ def _search_return_in_numpydocstr(docstr): found.extend(_expand_typestr(p_type)) return found - +# Caching disabled because jedi_patch breaks it # @memoize_default(None, evaluator_is_first_arg=True) def find_return_types(module_context, func): """ diff --git a/spyder/utils/introspection/test/test_jedi_plugin.py b/spyder/utils/introspection/test/test_jedi_plugin.py index eb8e870939d..5c5395961d8 100644 --- a/spyder/utils/introspection/test/test_jedi_plugin.py +++ b/spyder/utils/introspection/test/test_jedi_plugin.py @@ -32,7 +32,7 @@ def test_get_info(): - source_code = "import os; os.walk(" + source_code = "import os; os.walk" docs = p.get_info(CodeInfo('info', source_code, len(source_code))) assert docs['calltip'].startswith('walk(') and docs['name'] == 'walk' @@ -63,7 +63,7 @@ def test_get_docstring(): def test(a, b): """Test docstring""" pass - test(1,''') + test''') path, line = p.get_definition(CodeInfo('definition', source_code, len(source_code), 'dummy.txt', is_python_like=True)) From c34b99d3dfe03e780523f8ea6380e0e32afd6d78 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Mon, 13 Mar 2017 10:12:43 -0500 Subject: [PATCH 8/8] Docs: Fix link to Jedi webpage --- doc/installation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/installation.rst b/doc/installation.rst index 9795e3e5aa2..9b31fd78659 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -161,7 +161,7 @@ The requirements to run Spyder are: enhanced Python interpreter. * `Rope `_ >=0.9.4 and - `Jedi ` >=0.9.0 -- for code completion, + `Jedi `_ >=0.9.0 -- for code completion, go-to-definition and calltips on the Editor. * `Pyflakes `_ -- for real-time