mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-08 06:44:46 +08:00
Merge remote-tracking branch 'origin/namedtuple' into dev
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -11,3 +11,4 @@
|
||||
/dist/
|
||||
jedi.egg-info/
|
||||
record.json
|
||||
/.cache/
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
"""
|
||||
Implementations of standard library functions, because it's not possible to
|
||||
understand them with Jedi.
|
||||
|
||||
To add a new implementation, create a function and add it to the
|
||||
``_implemented`` dict at the bottom of this module.
|
||||
|
||||
"""
|
||||
import collections
|
||||
from jedi._compatibility import unicode
|
||||
from jedi.evaluate import compiled
|
||||
from jedi.evaluate import representation as er
|
||||
from jedi.evaluate import iterable
|
||||
from jedi.evaluate.helpers import FakeArray, FakeStatement
|
||||
from jedi.parser import Parser
|
||||
from jedi.parser import representation as pr
|
||||
from jedi import debug
|
||||
|
||||
@@ -107,6 +113,49 @@ def builtins_reversed(evaluator, obj, params):
|
||||
return [er.Instance(evaluator, obj, objects)]
|
||||
|
||||
|
||||
def collections_namedtuple(evaluator, obj, params):
|
||||
"""
|
||||
Implementation of the namedtuple function.
|
||||
|
||||
This has to be done by processing the namedtuple class template and
|
||||
evaluating the result.
|
||||
|
||||
.. note:: |jedi| only supports namedtuples on Python >2.6.
|
||||
|
||||
"""
|
||||
# Namedtuples are not supported on Python 2.6
|
||||
if not hasattr(collections, '_class_template'):
|
||||
return []
|
||||
|
||||
# Process arguments
|
||||
name = _follow_param(evaluator, params, 0)[0].obj
|
||||
_fields = _follow_param(evaluator, params, 1)[0]
|
||||
if isinstance(_fields, compiled.CompiledObject):
|
||||
fields = _fields.obj.replace(',', ' ').split()
|
||||
elif isinstance(_fields, iterable.Array):
|
||||
try:
|
||||
fields = [v.obj for v in _fields.values()]
|
||||
except AttributeError:
|
||||
return []
|
||||
else:
|
||||
return []
|
||||
|
||||
# Build source
|
||||
source = collections._class_template.format(
|
||||
typename=name,
|
||||
field_names=fields,
|
||||
num_fields=len(fields),
|
||||
arg_list=', '.join(fields),
|
||||
repr_fmt=', '.join(collections._repr_template.format(name=name) for name in fields),
|
||||
field_defs='\n'.join(collections._field_template.format(index=index, name=name)
|
||||
for index, name in enumerate(fields))
|
||||
)
|
||||
|
||||
# Parse source
|
||||
generated_class = Parser(unicode(source)).module.subscopes[0]
|
||||
return [er.Class(evaluator, generated_class)]
|
||||
|
||||
|
||||
def _return_first_param(evaluator, obj, params):
|
||||
if len(params) == 1:
|
||||
return _follow_param(evaluator, params, 0)
|
||||
@@ -128,4 +177,7 @@ _implemented = {
|
||||
'load': lambda *args: [],
|
||||
'loads': lambda *args: [],
|
||||
},
|
||||
'collections': {
|
||||
'namedtuple': collections_namedtuple,
|
||||
},
|
||||
}
|
||||
|
||||
37
test/test_integration_stdlib.py
Normal file
37
test/test_integration_stdlib.py
Normal file
@@ -0,0 +1,37 @@
|
||||
"""
|
||||
Tests of various stdlib related things that could not be tested
|
||||
with "Black Box Tests".
|
||||
"""
|
||||
import pytest
|
||||
from jedi import Script
|
||||
from jedi._compatibility import is_py26
|
||||
|
||||
|
||||
@pytest.mark.parametrize(['letter', 'expected'], [
|
||||
('n', ['name']),
|
||||
('s', ['smart']),
|
||||
])
|
||||
def test_namedtuple_str(letter, expected):
|
||||
source = "import collections\n" + \
|
||||
"Person = collections.namedtuple('Person', 'name smart')\n" + \
|
||||
"dave = Person('Dave', False)\n" + \
|
||||
"dave.%s" % letter
|
||||
result = Script(source).completions()
|
||||
completions = set(r.name for r in result)
|
||||
if is_py26:
|
||||
assert completions == set()
|
||||
else:
|
||||
assert completions == set(expected)
|
||||
|
||||
|
||||
def test_namedtuple_list():
|
||||
source = "import collections\n" + \
|
||||
"Cat = collections.namedtuple('Person', ['legs', u'length', 'large'])\n" + \
|
||||
"garfield = Cat(4, '85cm', True)\n" + \
|
||||
"garfield.l"
|
||||
result = Script(source).completions()
|
||||
completions = set(r.name for r in result)
|
||||
if is_py26:
|
||||
assert completions == set()
|
||||
else:
|
||||
assert completions == set(['legs', 'length', 'large'])
|
||||
Reference in New Issue
Block a user