Skip to content

Commit 65b4706

Browse files
authored
Merge pull request #119 from machow/fix-star-in-sig
fix: better support for rendering /, and * in signatures
2 parents 91692ec + c169d6d commit 65b4706

File tree

3 files changed

+55
-3
lines changed

3 files changed

+55
-3
lines changed

quartodoc/renderers/md_renderer.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,16 +325,36 @@ def render(self, el: Union[dc.Object, dc.Alias]):
325325

326326
@dispatch
327327
def render(self, el: dc.Parameters):
328+
# index for switch from positional to kw args (via an unnamed *)
328329
try:
329330
kw_only = [par.kind for par in el].index(dc.ParameterKind.keyword_only)
330331
except ValueError:
331332
kw_only = None
333+
334+
# index for final positionly only args (via /)
335+
try:
336+
pos_only = max([ii for ii, el in enumerate(el) if el.kind == dc.ParameterKind.positional_only])
337+
except ValueError:
338+
pos_only = None
339+
332340

333341
pars = list(map(self.render, el))
334342

335-
if kw_only is not None:
343+
# insert a single `*,` argument to represent the shift to kw only arguments,
344+
# only if the shift to kw_only was not triggered by *args (var_positional)
345+
if (
346+
kw_only is not None
347+
and kw_only > 0
348+
and el[kw_only-1].kind != dc.ParameterKind.var_positional
349+
):
336350
pars.insert(kw_only, sanitize("*"))
337351

352+
# insert a single `/, ` argument to represent shift from positional only arguments
353+
# note that this must come before a single *, so it's okay that both this
354+
# and block above insert into pars
355+
if pos_only is not None:
356+
pars.insert(pos_only + 1, sanitize("/"))
357+
338358
return ", ".join(pars)
339359

340360
@dispatch

quartodoc/tests/example_signature.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,19 @@ def yes_annotations(
66
a: int, b: int = 1, *args: list[str], c: int, d: int, **kwargs: dict[str, str]
77
):
88
"""A function with a signature"""
9+
10+
11+
def pos_only(x, /, a, b=2):
12+
...
13+
14+
15+
def kw_only(x, *, a, b=2):
16+
...
17+
18+
19+
def early_args(x, *args, a, b=2, **kwargs):
20+
...
21+
22+
23+
def late_args(x, a, b=2, *args, **kwargs):
24+
...

quartodoc/tests/test_renderers.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def test_render_param_kwargs(renderer):
1515
f = get_object("quartodoc.tests.example_signature.no_annotations")
1616
res = renderer.render(f.parameters)
1717

18-
assert res == "a, b=1, *args, *, c, d=2, **kwargs"
18+
assert res == "a, b=1, *args, c, d=2, **kwargs"
1919

2020

2121
def test_render_param_kwargs_annotated():
@@ -26,5 +26,21 @@ def test_render_param_kwargs_annotated():
2626

2727
assert (
2828
res
29-
== "a: int, b: int = 1, *args: list\\[str\\], *, c: int, d: int, **kwargs: dict\\[str, str\\]"
29+
== "a: int, b: int = 1, *args: list\\[str\\], c: int, d: int, **kwargs: dict\\[str, str\\]"
3030
)
31+
32+
33+
@pytest.mark.parametrize(
34+
"src, dst",
35+
[
36+
("example_signature.pos_only", "x, /, a, b=2"),
37+
("example_signature.kw_only", "x, *, a, b=2"),
38+
("example_signature.early_args", "x, *args, a, b=2, **kwargs"),
39+
("example_signature.late_args", "x, a, b=2, *args, **kwargs"),
40+
],
41+
)
42+
def test_render_param_kwonly(src, dst, renderer):
43+
f = get_object("quartodoc.tests", src)
44+
45+
res = renderer.render(f.parameters)
46+
assert res == dst

0 commit comments

Comments
 (0)