Dataclass progress

This commit is contained in:
Dave Halter
2019-07-19 01:27:37 +02:00
parent fd4eca5e03
commit 1cccc832b6
4 changed files with 69 additions and 8 deletions

View File

@@ -140,3 +140,11 @@ def skip_pre_python38(environment):
# This if is just needed to avoid that tests ever skip way more than
# they should for all Python versions.
pytest.skip()
@pytest.fixture()
def skip_pre_python37(environment):
if environment.version_info < (3, 7):
# This if is just needed to avoid that tests ever skip way more than
# they should for all Python versions.
pytest.skip()

View File

@@ -198,12 +198,7 @@ class ClassMixin(object):
yield f
if search_global:
yield ParserTreeFilter(
self.evaluator,
context=self,
until_position=until_position,
origin_scope=origin_scope
)
yield self.get_global_filter(until_position, origin_scope)
else:
for cls in self.py__mro__():
if isinstance(cls, compiled.CompiledObject):
@@ -227,6 +222,14 @@ class ClassMixin(object):
next(instance_filters)
yield next(instance_filters)
def get_global_filter(self, until_position=None, origin_scope=None):
return ParserTreeFilter(
self.evaluator,
context=self,
until_position=until_position,
origin_scope=origin_scope
)
class ClassContext(use_metaclass(CachedMetaClass, ClassMixin, FunctionAndClassBase)):
"""

View File

@@ -520,6 +520,37 @@ def _random_choice(sequences):
)
def _dataclass(obj, arguments):
for c in _follow_param(obj.evaluator, arguments, 0):
if c.is_class():
return ContextSet([DataclassWrapper(c)])
else:
return ContextSet([obj])
return NO_CONTEXTS
class DataclassWrapper(ContextWrapper):
def get_signatures(self):
params = []
for cls in reversed(self._wrapped_context.py__mro__()):
if isinstance(cls, ClassContext) and not cls.is_stub():
filter_ = cls.get_global_filter()
print(filter_)
for name in filter_.values():
d = name.tree_name.get_definition()
if d.type == 'expr_stmt' and d.children[1].type == 'annassign':
params.append()
return [DataclassSignature(cls, params)]
class DataclassSignature(AbstractSignature):
def __init__(self, context, params):
super(DataclassSignature, self).__init__(context)
self._params = params
def get_param_names(self):
class ItemGetterCallable(ContextWrapper):
def __init__(self, instance, args_context_set):
super(ItemGetterCallable, self).__init__(instance)
@@ -602,7 +633,7 @@ _implemented = {
},
'dataclasses': {
# For now this works at least better than Jedi trying to understand it.
'dataclass': lambda obj, arguments: NO_CONTEXTS,
'dataclass': _dataclass
},
}

View File

@@ -1,6 +1,8 @@
import pytest
from textwrap import dedent
from operator import ge, lt
import pytest
from jedi.evaluate.gradual.conversion import _stub_to_python_context_set
@@ -60,3 +62,20 @@ def test_pow_signature(Script):
'pow(x: float, y: float, /) -> float',
'pow(x: int, y: int, z: int, /) -> Any',
'pow(x: int, y: int, /) -> Any'}
@pytest.mark.parametrize('decorator', ['@dataclass', '@dataclass(eq=True)'])
def test_dataclass_signature(Script, skip_pre_python37, decorator):
code = dedent('''
class InventoryItem:
name: str
foo = 3
unit_price: float
quantity_on_hand: int = 0
InventoryItem(''')
code = 'from dataclasses import dataclass\n' + decorator + code
sig, = Script(code).call_signatures()
assert [p.name for p in sig.params] == ['name', 'unit_price', 'quantity_on_hand']