Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/typing_syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ In addition, docstub extends this syntax with several "natural language" express

Docstrings should follow a form that is inspired by the [NumPyDoc style](https://numpydoc.readthedocs.io/en/latest/format.html):
```none
Section namew
Section name
------------
name : doctype, optional_info
Description.
Expand Down
4 changes: 2 additions & 2 deletions src/docstub-stubs/_concurrency.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ class LoggingProcessExecutor:

max_workers: int | None = ...
logging_handlers: tuple[logging.Handler, ...] = ...
initializer: Callable | None = ...
initializer: Callable[..., None] | None = ...
initargs: tuple | None = ...

@staticmethod
def _initialize_worker(
queue: multiprocessing.Queue,
worker_log_level: int,
initializer: Callable,
initializer: Callable[..., None],
initargs: tuple[Any],
) -> None: ...
def __enter__(self) -> ProcessPoolExecutor | MockPoolExecutor: ...
Expand Down
2 changes: 2 additions & 0 deletions src/docstub-stubs/_docstrings.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ class DoctypeTransformer(lark.visitors.Transformer):
def rst_role(self, tree: lark.Tree) -> lark.Token: ...
def union(self, tree: lark.Tree) -> str: ...
def subscription(self, tree: lark.Tree) -> str: ...
def param_spec(self, tree: lark.Tree) -> str: ...
def callable(self, tree: lark.Tree) -> str: ...
def natlang_literal(self, tree: lark.Tree) -> str: ...
def natlang_container(self, tree: lark.Tree) -> str: ...
def natlang_array(self, tree: lark.Tree) -> str: ...
Expand Down
4 changes: 3 additions & 1 deletion src/docstub-stubs/_utils.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ from zlib import crc32

def accumulate_qualname(qualname: str, *, start_right: bool = ...) -> None: ...
def escape_qualname(name: str) -> str: ...
def _resolve_path_before_caching(func: Callable) -> Callable: ...
def _resolve_path_before_caching(
func: Callable[[Path], str],
) -> Callable[[Path], str]: ...
def module_name_from_path(path: Path) -> str: ...
def pyfile_checksum(path: Path) -> str: ...
def update_with_add_values(
Expand Down
4 changes: 2 additions & 2 deletions src/docstub/_concurrency.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class LoggingProcessExecutor:

max_workers: int | None = None
logging_handlers: tuple[logging.Handler, ...] = ()
initializer: Callable | None = None
initializer: Callable[..., None] | None = None
initargs: tuple | None = ()

@staticmethod
Expand All @@ -67,7 +67,7 @@ def _initialize_worker(queue, worker_log_level, initializer, initargs):
----------
queue : multiprocessing.Queue
worker_log_level : int
initializer : Callable
initializer : Callable[..., None]
initargs : tuple of Any
"""
queue_handler = logging.handlers.QueueHandler(queue)
Expand Down
29 changes: 29 additions & 0 deletions src/docstub/_docstrings.py
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,35 @@ def subscription(self, tree):
out = f"{_container}[{_content}]"
return out

def param_spec(self, tree):
"""
Parameters
----------
tree : lark.Tree

Returns
-------
out : str
"""
_content = ", ".join(tree.children)
out = f"[{_content}]"
return out

def callable(self, tree):
"""
Parameters
----------
tree : lark.Tree

Returns
-------
out : str
"""
_callable, *_content = tree.children
_content = ", ".join(_content)
out = f"{_callable}[{_content}]"
return out

def natlang_literal(self, tree):
"""
Parameters
Expand Down
4 changes: 2 additions & 2 deletions src/docstub/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,11 @@ def _resolve_path_before_caching(func):

Parameters
----------
func : Callable
func : Callable[[Path], str]

Returns
-------
wrapped : Callable
wrapped : Callable[[Path], str]
"""

@wraps(func)
Expand Down
12 changes: 12 additions & 0 deletions src/docstub/doctype.lark
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
?type: qualname
| union
| subscription
| callable
| natlang_literal
| natlang_container
| natlang_array
Expand Down Expand Up @@ -47,6 +48,17 @@ _OR: "or" | "|"
subscription: qualname "[" type ("," type)* ("," ELLIPSES)? "]"


// An expression describing a callable like "Callable[[int], str]"
// [1] https://typing.python.org/en/latest/spec/callables.html#callable
//
callable: qualname "[" ELLIPSES ("," type)? "]"
| qualname "[" param_spec "," type "]"


// The parameter specification inside a callable expression.
param_spec: "[" type? ("," type)* ("," ELLIPSES)? "]"


// Allow Python's ellipses object
ELLIPSES: "..."

Expand Down
32 changes: 32 additions & 0 deletions tests/test_docstrings.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,38 @@ def test_subscription_error(self, doctype):
with pytest.raises(lark.exceptions.UnexpectedInput):
transformer.doctype_to_annotation(doctype)

@pytest.mark.parametrize(
"doctype",
[
"Callable[[int], str]",
"some_func[[int], str]",
"Callable[[int, float, byte], list[str]]",
"Callable[..., str]",
"Callable[[], str]",
"Callback[...]",
"Callable[Concatenate[int, float], str]",
"Callable[Concatenate[int, ...], str]",
"Callable[P, str]",
],
)
def test_callable(self, doctype):
transformer = DoctypeTransformer()
annotation, _ = transformer.doctype_to_annotation(doctype)
assert annotation.value == doctype

@pytest.mark.parametrize(
"doctype",
[
"Callable[[...], int]",
"Callable[[..., str], int]",
"Callable[[float, str], int, byte]",
],
)
def test_callable_error(self, doctype):
transformer = DoctypeTransformer()
with pytest.raises(lark.exceptions.UnexpectedInput):
transformer.doctype_to_annotation(doctype)

@pytest.mark.parametrize(
("doctype", "expected"),
[
Expand Down
Loading