From 668be370893b36414954e36dfb006695330d234c Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Tue, 26 Feb 2013 10:25:16 +0100 Subject: [PATCH 1/6] Use nose to run doctests --- tox.ini | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tox.ini b/tox.ini index f61c3157..db9d67dc 100644 --- a/tox.ini +++ b/tox.ini @@ -3,11 +3,15 @@ envlist = py25, py26, py27, py32 [testenv] setenv = XDG_CACHE_HOME={envtmpdir}/cache +deps = + nose commands = python regression.py python run.py python refactor.py + nosetests --with-doctest --doctest-tests {toxinidir}/jedi changedir = test [testenv:py25] deps = simplejson + {[testenv]deps} From dad9cf05188dfae1526c48187dbc6d80fe6525d8 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Tue, 26 Feb 2013 10:28:25 +0100 Subject: [PATCH 2/6] Print str to avoid u prefix --- jedi/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/jedi/__init__.py b/jedi/__init__.py index 3e95de32..1e87dece 100644 --- a/jedi/__init__.py +++ b/jedi/__init__.py @@ -23,10 +23,10 @@ example for the autocompletion feature: >>> completions = script.complete() >>> completions [, ] ->>> completions[0].complete -'oad' ->>> completions[0].word -'load' +>>> print(completions[0].complete) +oad +>>> print(completions[0].word) +load As you see Jedi is pretty simple and allows you to concentrate on writing a good text editor, while still having very good IDE features for Python. From 95a98c90332fe22fbe6ac307edd85afdfa5c7bf4 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Tue, 26 Feb 2013 10:36:08 +0100 Subject: [PATCH 3/6] Do not use >>> for non-doctest code example Use literal block instead. --- jedi/api.py | 4 ++-- jedi/api_classes.py | 4 ++-- jedi/dynamic.py | 15 ++++++++------- jedi/evaluate.py | 17 +++++++++-------- jedi/imports.py | 5 +++-- jedi/parsing.py | 6 +++--- 6 files changed, 27 insertions(+), 24 deletions(-) diff --git a/jedi/api.py b/jedi/api.py index 394df66b..49ff0738 100644 --- a/jedi/api.py +++ b/jedi/api.py @@ -360,11 +360,11 @@ class Script(object): E.g. if the cursor is here:: - >>> abs(# <-- cursor is here + abs(# <-- cursor is here This would return the ``abs`` function. On the other hand:: - >>> abs()# <-- cursor is here + abs()# <-- cursor is here This would return ``None``. diff --git a/jedi/api_classes.py b/jedi/api_classes.py index edb5de20..3a966609 100644 --- a/jedi/api_classes.py +++ b/jedi/api_classes.py @@ -187,7 +187,7 @@ class Completion(BaseDefinition): """ Return the rest of the word, e.g. completing ``isinstance``:: - >>> isinstan# <-- Cursor is here + isinstan# <-- Cursor is here would return the string 'ce'. It also adds additional stuff, depending on your `settings.py`. @@ -211,7 +211,7 @@ class Completion(BaseDefinition): Similar to :meth:`Completion.complete`, but return the whole word, for example:: - >>> isinstan + isinstan would return 'isinstance'. """ diff --git a/jedi/dynamic.py b/jedi/dynamic.py index 6c2503d1..2d270a43 100644 --- a/jedi/dynamic.py +++ b/jedi/dynamic.py @@ -26,11 +26,11 @@ Parameter completion ******************** One of the really important features of |jedi| is to have an option to -understand code like this: +understand code like this:: ->>> def foo(bar): ->>> bar. # completion here ->>> foo(1) + def foo(bar): + bar. # completion here + foo(1) There's no doubt wheter bar is an ``int`` or not, but if there's also a call like ``foo('str')``, what would happen? Well, we'll just show both. Because @@ -496,9 +496,10 @@ def related_name_add_import_modules(definitions, search_name): def check_flow_information(flow, search_name, pos): """ Try to find out the type of a variable just with the information that - is given by the flows: e.g. It is also responsible for assert checks. - >>> if isinstance(k, str): - >>> k. # <- completion here + is given by the flows: e.g. It is also responsible for assert checks.:: + + if isinstance(k, str): + k. # <- completion here ensures that `k` is a string. """ diff --git a/jedi/evaluate.py b/jedi/evaluate.py index 47bc6ae8..4d6269b3 100644 --- a/jedi/evaluate.py +++ b/jedi/evaluate.py @@ -16,10 +16,10 @@ This is where autocompletion starts. Everything you want to complete is either a ``Statement`` or some special name like ``class``, which is easy to complete. Therefore you need to understand what follows after ``follow_statement``. Let's -make an example: +make an example:: ->>> import datetime ->>> datetime.date.toda# <-- cursor here + import datetime + datetime.date.toda# <-- cursor here First of all, this module doesn't care about completion. It really just cares about ``datetime.date``. At the end of the procedure ``follow_statement`` will @@ -45,10 +45,10 @@ the datetime import. So it continues Now what would happen if we wanted ``datetime.date.foo.bar``? Just two more calls to ``follow_paths`` (which calls itself with a recursion). What if the -import would contain another Statement like this: +import would contain another Statement like this:: ->>> from foo import bar ->>> Date = bar.baz + from foo import bar + Date = bar.baz Well... You get it. Just another ``follow_statement`` recursion. It's really easy. Just that Python is not that easy sometimes. To understand tuple @@ -681,8 +681,9 @@ def follow_paths(path, results, call_scope, position=None): def follow_path(path, scope, call_scope, position=None): """ - Uses a generator and tries to complete the path, e.g. - >>> foo.bar.baz + Uses a generator and tries to complete the path, e.g.:: + + foo.bar.baz `follow_path` is only responsible for completing `.bar.baz`, the rest is done in the `follow_call` function. diff --git a/jedi/imports.py b/jedi/imports.py index b0e9b3b4..5a6353cb 100644 --- a/jedi/imports.py +++ b/jedi/imports.py @@ -84,8 +84,9 @@ class ImportPath(pr.Base): def is_nested_import(self): """ This checks for the special case of nested imports, without aliases and - from statement: - >>> import foo.bar + from statement:: + + import foo.bar """ return not self.import_stmt.alias and not self.import_stmt.from_ns \ and len(self.import_stmt.namespace.names) > 1 \ diff --git a/jedi/parsing.py b/jedi/parsing.py index 95992b54..73b8a534 100644 --- a/jedi/parsing.py +++ b/jedi/parsing.py @@ -299,10 +299,10 @@ class Parser(object): def _parse_statement(self, pre_used_token=None, added_breaks=None, stmt_class=pr.Statement): """ - Parses statements like: + Parses statements like:: - >>> a = test(b) - >>> a += 3 - 2 or b + a = test(b) + a += 3 - 2 or b and so on. One line at a time. From b56c212a2c47c259a59ad698b8f364f96a2e3158 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Tue, 26 Feb 2013 10:36:29 +0100 Subject: [PATCH 4/6] Fix renamed functions in docstring --- jedi/docstrings.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/jedi/docstrings.py b/jedi/docstrings.py index d9aad406..e7d413b8 100644 --- a/jedi/docstrings.py +++ b/jedi/docstrings.py @@ -61,14 +61,14 @@ def _search_param_in_docstr(docstr, param_str): """ Search `docstr` for a type of `param_str`. - >>> search_param_in_docstr(':type param: int', 'param') + >>> _search_param_in_docstr(':type param: int', 'param') 'int' - >>> search_param_in_docstr('@type param: int', 'param') + >>> _search_param_in_docstr('@type param: int', 'param') 'int' - >>> search_param_in_docstr( + >>> _search_param_in_docstr( ... ':type param: :class:`threading.Thread`', 'param') 'threading.Thread' - >>> search_param_in_docstr('no document', 'param') is None + >>> _search_param_in_docstr('no document', 'param') is None True """ @@ -87,11 +87,11 @@ def _strip_rest_role(type_str): """ Strip off the part looks like a ReST role in `type_str`. - >>> strip_rest_role(':class:`ClassName`') # strip off :class: + >>> _strip_rest_role(':class:`ClassName`') # strip off :class: 'ClassName' - >>> strip_rest_role(':py:obj:`module.Object`') # works with domain + >>> _strip_rest_role(':py:obj:`module.Object`') # works with domain 'module.Object' - >>> strip_rest_role('ClassName') # do nothing when not ReST role + >>> _strip_rest_role('ClassName') # do nothing when not ReST role 'ClassName' See also: From 6d2f7558fb0edf00a086e60e719e0e52cfa5497d Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Tue, 26 Feb 2013 10:45:58 +0100 Subject: [PATCH 5/6] Run doctests on Travis CI --- .travis.yml | 1 + test/test.sh | 2 ++ 2 files changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index cdd88810..b049499b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ python: - 3.2 install: - if [[ $TRAVIS_PYTHON_VERSION == '2.5' ]]; then pip install --use-mirrors simplejson; fi + - pip install --use-mirrors nose script: - cd test - ./test.sh diff --git a/test/test.sh b/test/test.sh index 9e2077f9..4b41f743 100755 --- a/test/test.sh +++ b/test/test.sh @@ -4,3 +4,5 @@ python regression.py python run.py echo python refactor.py +echo +nosetests --with-doctest --doctest-tests ../jedi/ From 9ba9e2c3a665bdcf4893bdf5e9475797659aea9d Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Tue, 26 Feb 2013 10:58:24 +0100 Subject: [PATCH 6/6] Make doctest work on Python 2.5 --- jedi/__init__.py | 14 ++++++++------ jedi/api.py | 8 +++++--- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/jedi/__init__.py b/jedi/__init__.py index 1e87dece..397aa9f4 100644 --- a/jedi/__init__.py +++ b/jedi/__init__.py @@ -16,17 +16,19 @@ To give you a simple example how you can use the Jedi library, here is an example for the autocompletion feature: >>> import jedi ->>> source = '''import json; json.l''' ->>> script = jedi.Script(source, 1, 19, 'example.py') +>>> source = ''' +... import datetime +... datetime.da''' +>>> script = jedi.Script(source, 3, len('datetime.da'), 'example.py') >>> script >>> completions = script.complete() ->>> completions -[, ] +>>> completions #doctest: +ELLIPSIS +[, , ...] >>> print(completions[0].complete) -oad +te >>> print(completions[0].word) -load +date As you see Jedi is pretty simple and allows you to concentrate on writing a good text editor, while still having very good IDE features for Python. diff --git a/jedi/api.py b/jedi/api.py index 49ff0738..e2631507 100644 --- a/jedi/api.py +++ b/jedi/api.py @@ -485,10 +485,12 @@ def _quick_complete(source): """ Convenience function to complete a source string at the end. - Example:: + Example: - >>> _quick_complete('import json\\njson.l') - [, ] + >>> _quick_complete(''' + ... import datetime + ... datetime.da''') #doctest: +ELLIPSIS + [, , ...] :param source: The source code to be completed. :type source: string