mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-07 06:24:27 +08:00
Dataclass progress
This commit is contained in:
@@ -140,3 +140,11 @@ def skip_pre_python38(environment):
|
|||||||
# This if is just needed to avoid that tests ever skip way more than
|
# This if is just needed to avoid that tests ever skip way more than
|
||||||
# they should for all Python versions.
|
# they should for all Python versions.
|
||||||
pytest.skip()
|
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()
|
||||||
|
|||||||
@@ -198,12 +198,7 @@ class ClassMixin(object):
|
|||||||
yield f
|
yield f
|
||||||
|
|
||||||
if search_global:
|
if search_global:
|
||||||
yield ParserTreeFilter(
|
yield self.get_global_filter(until_position, origin_scope)
|
||||||
self.evaluator,
|
|
||||||
context=self,
|
|
||||||
until_position=until_position,
|
|
||||||
origin_scope=origin_scope
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
for cls in self.py__mro__():
|
for cls in self.py__mro__():
|
||||||
if isinstance(cls, compiled.CompiledObject):
|
if isinstance(cls, compiled.CompiledObject):
|
||||||
@@ -227,6 +222,14 @@ class ClassMixin(object):
|
|||||||
next(instance_filters)
|
next(instance_filters)
|
||||||
yield 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)):
|
class ClassContext(use_metaclass(CachedMetaClass, ClassMixin, FunctionAndClassBase)):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -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):
|
class ItemGetterCallable(ContextWrapper):
|
||||||
def __init__(self, instance, args_context_set):
|
def __init__(self, instance, args_context_set):
|
||||||
super(ItemGetterCallable, self).__init__(instance)
|
super(ItemGetterCallable, self).__init__(instance)
|
||||||
@@ -602,7 +633,7 @@ _implemented = {
|
|||||||
},
|
},
|
||||||
'dataclasses': {
|
'dataclasses': {
|
||||||
# For now this works at least better than Jedi trying to understand it.
|
# For now this works at least better than Jedi trying to understand it.
|
||||||
'dataclass': lambda obj, arguments: NO_CONTEXTS,
|
'dataclass': _dataclass
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import pytest
|
from textwrap import dedent
|
||||||
from operator import ge, lt
|
from operator import ge, lt
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
from jedi.evaluate.gradual.conversion import _stub_to_python_context_set
|
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: float, y: float, /) -> float',
|
||||||
'pow(x: int, y: int, z: int, /) -> Any',
|
'pow(x: int, y: int, z: int, /) -> Any',
|
||||||
'pow(x: int, y: 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']
|
||||||
|
|||||||
Reference in New Issue
Block a user