From a760a8c684cae0da6b6cc83e37d1d374bfeed662 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Sat, 17 Aug 2024 17:50:28 +0200 Subject: [PATCH] feat: Add `on_alias` event Issue-282: https://github.com/mkdocstrings/griffe/issues/282 --- docs/guide/users/extending.md | 12 ++++++------ src/_griffe/agents/inspector.py | 4 +++- src/_griffe/agents/visitor.py | 30 ++++++++++++++---------------- src/_griffe/extensions/base.py | 19 ++++++++++++++++++- 4 files changed, 41 insertions(+), 24 deletions(-) diff --git a/docs/guide/users/extending.md b/docs/guide/users/extending.md index a5796a29..509247d6 100644 --- a/docs/guide/users/extending.md +++ b/docs/guide/users/extending.md @@ -200,9 +200,9 @@ This event is triggered when the loader has finished loading a package entirely, There are 3 generic **analysis events**: -- [`on_node`][griffe.Extension.on_node] -- [`on_instance`][griffe.Extension.on_instance] -- [`on_members`][griffe.Extension.on_members] +- [`on_node`][griffe.Extension.on_node]: The "on node" events are triggered when the agent (visitor or inspector) starts handling a node in the tree (AST or object tree). +- [`on_instance`][griffe.Extension.on_instance]: The "on instance" events are triggered when the agent just created an instance of [Module][griffe.Module], [Class][griffe.Class], [Function][griffe.Function], or [Attribute][griffe.Attribute], and added it as a member of its parent. The "on instance" event is **not** triggered when an [Alias][griffe.Alias] is created. +- [`on_members`][griffe.Extension.on_members]: The "on members" events are triggered when the agent just finished handling all the members of an object. Functions and attributes do not have members, so there are no "on members" event for these two kinds. There are also specific **analysis events** for each object kind: @@ -217,11 +217,11 @@ There are also specific **analysis events** for each object kind: - [`on_attribute_node`][griffe.Extension.on_attribute_node] - [`on_attribute_instance`][griffe.Extension.on_attribute_instance] -The "on node" events are triggered when the agent (visitor or inspector) starts handling a node in the tree (AST or object tree). +And a special event for aliases: -The "on instance" events are triggered when the agent just created an instance of [Module][griffe.Module], [Class][griffe.Class], [Function][griffe.Function], or [Attribute][griffe.Attribute], and added it as a member of its parent. +- [`on_alias`][griffe.Extension.on_alias]: The "on alias" event is triggered when an [Alias][griffe.Alias] was just created and added as a member of its parent object. -The "on members" events are triggered when the agent just finished handling all the members of an object. Functions and attributes do not have members, so there are no "on members" event for these two kinds. +--- **Hooks** are methods that are called when a particular event is triggered. To target a specific event, the hook must be named after it. diff --git a/src/_griffe/agents/inspector.py b/src/_griffe/agents/inspector.py index afd3c30f..34cdbab8 100644 --- a/src/_griffe/agents/inspector.py +++ b/src/_griffe/agents/inspector.py @@ -267,7 +267,9 @@ def generic_inspect(self, node: ObjectNode) -> None: self.current.set_member(child.name, inspector.current.module) # Otherwise, alias the object. else: - self.current.set_member(child.name, Alias(child.name, target_path)) + alias = Alias(child.name, target_path) + self.current.set_member(child.name, alias) + self.extensions.call("on_alias", alias=alias, node=node, agent=self) else: self.inspect(child) diff --git a/src/_griffe/agents/visitor.py b/src/_griffe/agents/visitor.py index 9e3cc500..44ad3684 100644 --- a/src/_griffe/agents/visitor.py +++ b/src/_griffe/agents/visitor.py @@ -463,16 +463,15 @@ def visit_import(self, node: ast.Import) -> None: alias_path = name.name if name.asname else name.name.split(".", 1)[0] alias_name = name.asname or alias_path.split(".", 1)[0] self.current.imports[alias_name] = alias_path - self.current.set_member( + alias = Alias( alias_name, - Alias( - alias_name, - alias_path, - lineno=node.lineno, - endlineno=node.end_lineno, - runtime=not self.type_guarded, - ), + alias_path, + lineno=node.lineno, + endlineno=node.end_lineno, + runtime=not self.type_guarded, ) + self.current.set_member(alias_name, alias) + self.extensions.call("on_alias", alias=alias, node=node, agent=self) def visit_importfrom(self, node: ast.ImportFrom) -> None: """Visit an "import from" node. @@ -499,16 +498,15 @@ def visit_importfrom(self, node: ast.ImportFrom) -> None: # `from package.current_module import Thing as Thing` or # `from . import thing as thing`). if alias_path != f"{self.current.path}.{alias_name}": - self.current.set_member( + alias = Alias( alias_name, - Alias( - alias_name, - alias_path, - lineno=node.lineno, - endlineno=node.end_lineno, - runtime=not self.type_guarded, - ), + alias_path, + lineno=node.lineno, + endlineno=node.end_lineno, + runtime=not self.type_guarded, ) + self.current.set_member(alias_name, alias) + self.extensions.call("on_alias", alias=alias, node=node, agent=self) def handle_attribute( self, diff --git a/src/_griffe/extensions/base.py b/src/_griffe/extensions/base.py index ebdcdb56..31b52dc1 100644 --- a/src/_griffe/extensions/base.py +++ b/src/_griffe/extensions/base.py @@ -22,7 +22,7 @@ from _griffe.agents.nodes.runtime import ObjectNode from _griffe.agents.visitor import Visitor from _griffe.loader import GriffeLoader - from _griffe.models import Attribute, Class, Function, Module, Object + from _griffe.models import Alias, Attribute, Class, Function, Module, Object class Extension: @@ -235,6 +235,23 @@ def on_attribute_instance( **kwargs: For forward-compatibility. """ + def on_alias( + self, + *, + node: ast.AST | ObjectNode, + alias: Alias, + agent: Visitor | Inspector, + **kwargs: Any, + ) -> None: + """Run when an Alias has been created. + + Parameters: + node: The currently visited node. + alias: The alias instance. + agent: The analysis agent currently running. + **kwargs: For forward-compatibility. + """ + def on_package_loaded(self, *, pkg: Module, loader: GriffeLoader, **kwargs: Any) -> None: """Run when a package has been completely loaded.