Skip to content

Commit 598d08a

Browse files
committed
fix: Fix handling of lambda expressions
1 parent ad68e65 commit 598d08a

File tree

2 files changed

+53
-9
lines changed

2 files changed

+53
-9
lines changed

src/griffe/expressions.py

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from itertools import zip_longest
1111
from typing import TYPE_CHECKING, Any, Callable, Iterable, Iterator, Sequence
1212

13+
from griffe.agents.nodes import get_parameters
1314
from griffe.enumerations import ParameterKind
1415
from griffe.exceptions import NameResolutionError
1516
from griffe.logger import LogLevel, get_logger
@@ -486,8 +487,34 @@ class ExprLambda(Expr):
486487
"""Lambda's body."""
487488

488489
def iterate(self, *, flat: bool = True) -> Iterator[str | Expr]: # noqa: D102
489-
yield "lambda "
490-
yield from _join(self.parameters, ", ", flat=flat)
490+
pos_only = False
491+
pos_or_kw = False
492+
kw_only = False
493+
length = len(self.parameters)
494+
yield "lambda"
495+
if length:
496+
yield " "
497+
for index, parameter in enumerate(self.parameters, 1):
498+
if parameter.kind is ParameterKind.positional_only:
499+
pos_only = True
500+
elif parameter.kind is ParameterKind.var_positional:
501+
yield "*"
502+
elif parameter.kind is ParameterKind.var_keyword:
503+
yield "**"
504+
elif parameter.kind is ParameterKind.positional_or_keyword and not pos_or_kw:
505+
pos_or_kw = True
506+
elif parameter.kind is ParameterKind.keyword_only and not kw_only:
507+
kw_only = True
508+
yield "*, "
509+
if parameter.kind is not ParameterKind.positional_only and pos_only:
510+
pos_only = False
511+
yield "/, "
512+
yield parameter.name
513+
if parameter.default and parameter.kind not in (ParameterKind.var_positional, ParameterKind.var_keyword):
514+
yield "="
515+
yield from _yield(parameter.default, flat=flat)
516+
if index < length:
517+
yield ", "
491518
yield ": "
492519
yield from _yield(self.body, flat=flat)
493520

@@ -587,13 +614,13 @@ def iterate(self, *, flat: bool = True) -> Iterator[str | Expr]: # noqa: D102
587614
class ExprParameter(Expr):
588615
"""Parameters in function signatures like `a: int = 0`."""
589616

590-
kind: str
591-
"""Parameter kind."""
592-
name: str | None = None
617+
name: str
593618
"""Parameter name."""
619+
kind: ParameterKind = ParameterKind.positional_or_keyword
620+
"""Parameter kind."""
594621
annotation: Expr | None = None
595622
"""Parameter type."""
596-
default: Expr | None = None
623+
default: str | Expr | None = None
597624
"""Parameter default."""
598625

599626

@@ -924,10 +951,19 @@ def _build_keyword(node: ast.keyword, parent: Module | Class, function: Expr | N
924951

925952

926953
def _build_lambda(node: ast.Lambda, parent: Module | Class, **kwargs: Any) -> Expr:
927-
# FIXME: This needs better handling (all parameter kinds).
928954
return ExprLambda(
929-
[ExprParameter(ParameterKind.positional_or_keyword.value, arg.arg) for arg in node.args.args],
930-
_build(node.body, parent, **kwargs),
955+
parameters=[
956+
ExprParameter(
957+
name=name,
958+
kind=kind,
959+
annotation=None,
960+
default=default
961+
if isinstance(default, str)
962+
else safe_get_expression(default, parent=parent, parse_strings=False),
963+
)
964+
for name, _, kind, default in get_parameters(node.args)
965+
],
966+
body=_build(node.body, parent, **kwargs),
931967
)
932968

933969

tests/test_nodes.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,14 @@
7272
"yield",
7373
"yield a",
7474
"yield from a",
75+
# lambdas
76+
"lambda a: a",
77+
"lambda a, b: a",
78+
"lambda *a, **b: a",
79+
"lambda a, b=0: a",
80+
"lambda a, /, b, c: a",
81+
"lambda a, *, b, c: a",
82+
"lambda a, /, b, *, c: a",
7583
]
7684

7785

0 commit comments

Comments
 (0)