1
0
forked from VimPlug/jedi

Extend dataclass constructor hinting to attrs next-gen apis.

Trivially extends dataclass constructor hinting to attrs next-gen APIs.

This will stumble in cases where attrs extends beyond the standard
dataclasses API, such as complex use of defaults, converters, et al.
However, it likely covers the vast majority of cases which fall solidly
in the intersection of the two APIs.

Extension beyond these cases could use [PEP0681 dataclass_transforms],
however this is definitely a problem for another day.

[PEP0681 dataclass_transforms]: https://peps.python.org/pep-0681/

https://github.com/davidhalter/jedi/issues/1835
This commit is contained in:
Alex Ford
2022-10-10 11:15:27 -07:00
parent 8b0d391ac1
commit 40e1e3f560
2 changed files with 48 additions and 0 deletions

View File

@@ -803,6 +803,15 @@ _implemented = {
# For now this works at least better than Jedi trying to understand it.
'dataclass': _dataclass
},
# attrs exposes declaration interface roughly compatible with dataclasses
# via attrs.define, attrs.frozen and attrs.mutable
# https://www.attrs.org/en/stable/names.html
'attr': {
'define': _dataclass,
},
'attrs': {
'define': _dataclass,
},
'os.path': {
'dirname': _create_string_input_function(os.path.dirname),
'abspath': _create_string_input_function(os.path.abspath),

View File

@@ -355,6 +355,45 @@ def test_dataclass_signature(Script, skip_pre_python37, start, start_params):
price, = sig.params[-2].infer()
assert price.name == 'float'
@pytest.mark.parametrize(
'start, start_params', [
['@define\nclass X:', []],
['@frozen\nclass X:', []],
['@mutable\nclass X:', []],
['@define(eq=True)\nclass X:', []],
[dedent('''
class Y():
y: int
@define
class X(Y):'''), []],
[dedent('''
@define
class Y():
y: int
z = 5
@define
class X(Y):'''), ['y']],
]
)
def test_attrs_signature(Script, skip_pre_python37, start, start_params):
code = dedent('''
name: str
foo = 3
price: float
quantity: int = 0.0
X(''')
# attrs exposes two namespaces
code = 'from attrs import define, frozen\n' + start + code
sig, = Script(code).get_signatures()
assert [p.name for p in sig.params] == start_params + ['name', 'price', 'quantity']
quantity, = sig.params[-1].infer()
assert quantity.name == 'int'
price, = sig.params[-2].infer()
assert price.name == 'float'
@pytest.mark.parametrize(
'stmt, expected', [