Skip to content

Commit 238766a

Browse files
committed
Add support of callable expressions
1 parent 80a7ce4 commit 238766a

3 files changed

Lines changed: 75 additions & 0 deletions

File tree

src/docstub/_docstrings.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,35 @@ def subscription(self, tree):
384384
out = f"{_container}[{_content}]"
385385
return out
386386

387+
def param_spec(self, tree):
388+
"""
389+
Parameters
390+
----------
391+
tree : lark.Tree
392+
393+
Returns
394+
-------
395+
out : str
396+
"""
397+
_content = ", ".join(tree.children)
398+
out = f"[{_content}]"
399+
return out
400+
401+
def callable(self, tree):
402+
"""
403+
Parameters
404+
----------
405+
tree : lark.Tree
406+
407+
Returns
408+
-------
409+
out : str
410+
"""
411+
_callable, *_content = tree.children
412+
_content = ", ".join(_content)
413+
out = f"{_callable}[{_content}]"
414+
return out
415+
387416
def natlang_literal(self, tree):
388417
"""
389418
Parameters

src/docstub/doctype.lark

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
?type: qualname
2121
| union
2222
| subscription
23+
| callable
2324
| natlang_literal
2425
| natlang_container
2526
| natlang_array
@@ -47,6 +48,17 @@ _OR: "or" | "|"
4748
subscription: qualname "[" type ("," type)* ("," ELLIPSES)? "]"
4849

4950

51+
// An expression describing a callable like "Callable[[int], str]"
52+
// [1] https://typing.python.org/en/latest/spec/callables.html#callable
53+
//
54+
callable: qualname "[" ELLIPSES ("," type)? "]"
55+
| qualname "[" param_spec "," type "]"
56+
57+
58+
// The parameter specification inside a callable expression.
59+
param_spec: "[" type? ("," type)* ("," ELLIPSES)? "]"
60+
61+
5062
// Allow Python's ellipses object
5163
ELLIPSES: "..."
5264

tests/test_docstrings.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,40 @@ def test_subscription_error(self, doctype):
154154
with pytest.raises(lark.exceptions.UnexpectedInput):
155155
transformer.doctype_to_annotation(doctype)
156156

157+
@pytest.mark.parametrize(
158+
"doctype",
159+
[
160+
"Callable[[int], str]",
161+
"some_func[[int], str]",
162+
"Callable[[int, float, byte], list[str]]",
163+
"Callable[..., str]",
164+
"Callable[[], str]",
165+
"Callback[...]",
166+
"Callable[Concatenate[int, float], str]",
167+
"Callable[Concatenate[int, ...], str]",
168+
"Callable[P, str]",
169+
],
170+
)
171+
def test_callable(self, doctype):
172+
transformer = DoctypeTransformer()
173+
annotation, _ = transformer.doctype_to_annotation(doctype)
174+
assert annotation.value == doctype
175+
176+
@pytest.mark.parametrize(
177+
"doctype",
178+
[
179+
"Callable[[...], int]",
180+
"Callable[[..., str], int]",
181+
"Callable[[float, str], int, byte]",
182+
"Callable[Ellipsis]",
183+
"Callable[Ellipsis, int]",
184+
],
185+
)
186+
def test_callable_error(self, doctype):
187+
transformer = DoctypeTransformer()
188+
with pytest.raises(lark.exceptions.UnexpectedInput):
189+
transformer.doctype_to_annotation(doctype)
190+
157191
@pytest.mark.parametrize(
158192
("doctype", "expected"),
159193
[

0 commit comments

Comments
 (0)