Skip to content

Commit 0709f0d

Browse files
committed
feat: Parse keywords in class declarations
1 parent 1f5b4a4 commit 0709f0d

File tree

5 files changed

+32
-1
lines changed

5 files changed

+32
-1
lines changed

docs/reference/api/expressions.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
::: griffe.get_base_class
1616

17+
::: griffe.get_class_keyword
18+
1719
::: griffe.get_condition
1820

1921
::: griffe.get_expression
@@ -22,6 +24,8 @@
2224

2325
::: griffe.safe_get_base_class
2426

27+
::: griffe.safe_get_class_keyword
28+
2529
::: griffe.safe_get_condition
2630

2731
::: griffe.safe_get_expression

src/griffe/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,12 @@
127127
128128
- [`griffe.get_annotation`][]: Get a type annotation as expression.
129129
- [`griffe.get_base_class`][]: Get a base class as expression.
130+
- [`griffe.get_class_keyword`][]: Get a class keyword as expression.
130131
- [`griffe.get_condition`][]: Get a condition as expression.
131132
- [`griffe.get_expression`][]: Get an expression from an AST node.
132133
- [`griffe.safe_get_annotation`][]: Get a type annotation as expression, safely (returns `None` on error).
133134
- [`griffe.safe_get_base_class`][]: Get a base class as expression, safely (returns `None` on error).
135+
- [`griffe.safe_get_class_keyword`][]: Get a class keyword as expression, safely (returns `None` on error).
134136
- [`griffe.safe_get_condition`][]: Get a condition as expression, safely (returns `None` on error).
135137
- [`griffe.safe_get_expression`][]: Get an expression from an AST node, safely (returns `None` on error).
136138
@@ -321,10 +323,12 @@
321323
ExprYieldFrom,
322324
get_annotation,
323325
get_base_class,
326+
get_class_keyword,
324327
get_condition,
325328
get_expression,
326329
safe_get_annotation,
327330
safe_get_base_class,
331+
safe_get_class_keyword,
328332
safe_get_condition,
329333
safe_get_expression,
330334
)
@@ -582,6 +586,7 @@ def __getattr__(name: str) -> Any:
582586
"get__all__",
583587
"get_annotation",
584588
"get_base_class",
589+
"get_class_keyword",
585590
"get_condition",
586591
"get_docstring",
587592
"get_expression",
@@ -618,6 +623,7 @@ def __getattr__(name: str) -> Any:
618623
"safe_get__all__",
619624
"safe_get_annotation",
620625
"safe_get_base_class",
626+
"safe_get_class_keyword",
621627
"safe_get_condition",
622628
"safe_get_expression",
623629
"safe_get_value",

src/griffe/_internal/agents/visitor.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
ExprName,
2727
safe_get_annotation,
2828
safe_get_base_class,
29+
safe_get_class_keyword,
2930
safe_get_condition,
3031
safe_get_expression,
3132
)
@@ -320,8 +321,11 @@ def visit_classdef(self, node: ast.ClassDef) -> None:
320321
else:
321322
lineno = node.lineno
322323

323-
# Handle base classes.
324+
# Handle base classes and keywords.
324325
bases = [safe_get_base_class(base, parent=self.current, member=node.name) for base in node.bases]
326+
keywords = {
327+
kw.arg: safe_get_class_keyword(kw.value, parent=self.current) for kw in node.keywords if kw.arg is not None
328+
}
325329

326330
class_ = Class(
327331
name=node.name,
@@ -331,6 +335,7 @@ def visit_classdef(self, node: ast.ClassDef) -> None:
331335
decorators=decorators,
332336
type_parameters=TypeParameters(*self._get_type_parameters(node, scope=node.name)),
333337
bases=bases, # type: ignore[arg-type]
338+
keywords=keywords,
334339
runtime=not self.type_guarded,
335340
analysis="static",
336341
)

src/griffe/_internal/expressions.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1492,6 +1492,12 @@ def safe_get_expression(
14921492
parse_strings=False,
14931493
msg_format=_msg_format % "base class",
14941494
)
1495+
get_class_keyword = partial(get_expression, parse_strings=False)
1496+
safe_get_class_keyword = partial(
1497+
safe_get_expression,
1498+
parse_strings=False,
1499+
msg_format=_msg_format % "class keyword",
1500+
)
14951501
get_condition = partial(get_expression, parse_strings=False)
14961502
safe_get_condition = partial(
14971503
safe_get_expression,

src/griffe/_internal/models.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1910,6 +1910,11 @@ def bases(self) -> list[Expr | str]:
19101910
"""
19111911
return cast("Class", self.final_target).bases
19121912

1913+
@property
1914+
def keywords(self) -> dict[str, Expr | str]:
1915+
"""The class keywords."""
1916+
return cast("Class", self.final_target).keywords
1917+
19131918
@property
19141919
def decorators(self) -> list[Decorator]:
19151920
"""The class/function decorators.
@@ -2354,6 +2359,7 @@ def __init__(
23542359
*args: Any,
23552360
bases: Sequence[Expr | str] | None = None,
23562361
decorators: list[Decorator] | None = None,
2362+
keywords: dict[str, Any] | None = None,
23572363
**kwargs: Any,
23582364
) -> None:
23592365
"""Initialize the class.
@@ -2362,6 +2368,7 @@ def __init__(
23622368
*args: See [`griffe.Object`][].
23632369
bases: The list of base classes, if any.
23642370
decorators: The class decorators, if any.
2371+
keywords: The class keywords arguments, if any.
23652372
**kwargs: See [`griffe.Object`][].
23662373
"""
23672374
super().__init__(*args, **kwargs)
@@ -2376,6 +2383,9 @@ def __init__(
23762383
self.decorators: list[Decorator] = decorators or []
23772384
"""The class decorators."""
23782385

2386+
self.keywords: dict[str, Any] = keywords or {}
2387+
"""The class keywords arguments."""
2388+
23792389
self.overloads: dict[str, list[Function]] = defaultdict(list)
23802390
"""The overloaded signatures declared in this class."""
23812391

0 commit comments

Comments
 (0)