Merge pull request #146 from tkf/doctest

Add doctest
This commit is contained in:
David Halter
2013-02-26 03:46:08 -08:00
11 changed files with 56 additions and 42 deletions
+1
View File
@@ -6,6 +6,7 @@ python:
- 3.2 - 3.2
install: install:
- if [[ $TRAVIS_PYTHON_VERSION == '2.5' ]]; then pip install --use-mirrors simplejson; fi - if [[ $TRAVIS_PYTHON_VERSION == '2.5' ]]; then pip install --use-mirrors simplejson; fi
- pip install --use-mirrors nose
script: script:
- cd test - cd test
- ./test.sh - ./test.sh
+10 -8
View File
@@ -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: example for the autocompletion feature:
>>> import jedi >>> import jedi
>>> source = '''import json; json.l''' >>> source = '''
>>> script = jedi.Script(source, 1, 19, 'example.py') ... import datetime
... datetime.da'''
>>> script = jedi.Script(source, 3, len('datetime.da'), 'example.py')
>>> script >>> script
<Script: 'example.py'> <Script: 'example.py'>
>>> completions = script.complete() >>> completions = script.complete()
>>> completions >>> completions #doctest: +ELLIPSIS
[<Completion: load>, <Completion: loads>] [<Completion: date>, <Completion: datetime>, ...]
>>> completions[0].complete >>> print(completions[0].complete)
'oad' te
>>> completions[0].word >>> print(completions[0].word)
'load' date
As you see Jedi is pretty simple and allows you to concentrate on writing a 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. good text editor, while still having very good IDE features for Python.
+7 -5
View File
@@ -360,11 +360,11 @@ class Script(object):
E.g. if the cursor is here:: 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:: This would return the ``abs`` function. On the other hand::
>>> abs()# <-- cursor is here abs()# <-- cursor is here
This would return ``None``. This would return ``None``.
@@ -485,10 +485,12 @@ def _quick_complete(source):
""" """
Convenience function to complete a source string at the end. Convenience function to complete a source string at the end.
Example:: Example:
>>> _quick_complete('import json\\njson.l') >>> _quick_complete('''
[<Completion: load>, <Completion: loads>] ... import datetime
... datetime.da''') #doctest: +ELLIPSIS
[<Completion: date>, <Completion: datetime>, ...]
:param source: The source code to be completed. :param source: The source code to be completed.
:type source: string :type source: string
+2 -2
View File
@@ -187,7 +187,7 @@ class Completion(BaseDefinition):
""" """
Return the rest of the word, e.g. completing ``isinstance``:: 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 would return the string 'ce'. It also adds additional stuff, depending
on your `settings.py`. on your `settings.py`.
@@ -211,7 +211,7 @@ class Completion(BaseDefinition):
Similar to :meth:`Completion.complete`, but return the whole word, for Similar to :meth:`Completion.complete`, but return the whole word, for
example:: example::
>>> isinstan isinstan
would return 'isinstance'. would return 'isinstance'.
""" """
+7 -7
View File
@@ -61,14 +61,14 @@ def _search_param_in_docstr(docstr, param_str):
""" """
Search `docstr` for a type of `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' 'int'
>>> search_param_in_docstr('@type param: int', 'param') >>> _search_param_in_docstr('@type param: int', 'param')
'int' 'int'
>>> search_param_in_docstr( >>> _search_param_in_docstr(
... ':type param: :class:`threading.Thread`', 'param') ... ':type param: :class:`threading.Thread`', 'param')
'threading.Thread' 'threading.Thread'
>>> search_param_in_docstr('no document', 'param') is None >>> _search_param_in_docstr('no document', 'param') is None
True True
""" """
@@ -87,11 +87,11 @@ def _strip_rest_role(type_str):
""" """
Strip off the part looks like a ReST role in `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' 'ClassName'
>>> strip_rest_role(':py:obj:`module.Object`') # works with domain >>> _strip_rest_role(':py:obj:`module.Object`') # works with domain
'module.Object' 'module.Object'
>>> strip_rest_role('ClassName') # do nothing when not ReST role >>> _strip_rest_role('ClassName') # do nothing when not ReST role
'ClassName' 'ClassName'
See also: See also:
+8 -7
View File
@@ -26,11 +26,11 @@ Parameter completion
******************** ********************
One of the really important features of |jedi| is to have an option to 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): def foo(bar):
>>> bar. # completion here bar. # completion here
>>> foo(1) foo(1)
There's no doubt wheter bar is an ``int`` or not, but if there's also a call 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 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): def check_flow_information(flow, search_name, pos):
""" Try to find out the type of a variable just with the information that """ 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. is given by the flows: e.g. It is also responsible for assert checks.::
>>> if isinstance(k, str):
>>> k. # <- completion here if isinstance(k, str):
k. # <- completion here
ensures that `k` is a string. ensures that `k` is a string.
""" """
+9 -8
View File
@@ -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. 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 Therefore you need to understand what follows after ``follow_statement``. Let's
make an example: make an example::
>>> import datetime import datetime
>>> datetime.date.toda# <-- cursor here datetime.date.toda# <-- cursor here
First of all, this module doesn't care about completion. It really just cares 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 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 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 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 from foo import bar
>>> Date = bar.baz Date = bar.baz
Well... You get it. Just another ``follow_statement`` recursion. It's really Well... You get it. Just another ``follow_statement`` recursion. It's really
easy. Just that Python is not that easy sometimes. To understand tuple 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): def follow_path(path, scope, call_scope, position=None):
""" """
Uses a generator and tries to complete the path, e.g. Uses a generator and tries to complete the path, e.g.::
>>> foo.bar.baz
foo.bar.baz
`follow_path` is only responsible for completing `.bar.baz`, the rest is `follow_path` is only responsible for completing `.bar.baz`, the rest is
done in the `follow_call` function. done in the `follow_call` function.
+3 -2
View File
@@ -84,8 +84,9 @@ class ImportPath(pr.Base):
def is_nested_import(self): def is_nested_import(self):
""" """
This checks for the special case of nested imports, without aliases and This checks for the special case of nested imports, without aliases and
from statement: from statement::
>>> import foo.bar
import foo.bar
""" """
return not self.import_stmt.alias and not self.import_stmt.from_ns \ return not self.import_stmt.alias and not self.import_stmt.from_ns \
and len(self.import_stmt.namespace.names) > 1 \ and len(self.import_stmt.namespace.names) > 1 \
+3 -3
View File
@@ -299,10 +299,10 @@ class Parser(object):
def _parse_statement(self, pre_used_token=None, added_breaks=None, def _parse_statement(self, pre_used_token=None, added_breaks=None,
stmt_class=pr.Statement): stmt_class=pr.Statement):
""" """
Parses statements like: Parses statements like::
>>> a = test(b) a = test(b)
>>> a += 3 - 2 or b a += 3 - 2 or b
and so on. One line at a time. and so on. One line at a time.
+2
View File
@@ -4,3 +4,5 @@ python regression.py
python run.py python run.py
echo echo
python refactor.py python refactor.py
echo
nosetests --with-doctest --doctest-tests ../jedi/
+4
View File
@@ -3,11 +3,15 @@ envlist = py25, py26, py27, py32
[testenv] [testenv]
setenv = setenv =
XDG_CACHE_HOME={envtmpdir}/cache XDG_CACHE_HOME={envtmpdir}/cache
deps =
nose
commands = commands =
python regression.py python regression.py
python run.py python run.py
python refactor.py python refactor.py
nosetests --with-doctest --doctest-tests {toxinidir}/jedi
changedir = test changedir = test
[testenv:py25] [testenv:py25]
deps = deps =
simplejson simplejson
{[testenv]deps}