effect_base#
Base types for the data_effects
system.
Penzai’s effect system is based on representing effects as dataclass PyTree nodes, and handling them by substituting abstract effect nodes with concrete handler nodes. This module contains the base types for the system.
To use an existing effect, you should:
Add an attribute to the layer that will use the effect, and annotate its type as
{EffectName}Effect
.In the builder for your layer (e.g. inside the
from_config
method or other class method), set that attribute to an instance of the corresponding effect request, e.g.{EffectName}Request(*args, **kwargs)
. Alternatively you can set this as the default value for the dataclass attribute.In the
__call__
method of your layer, assume that the effect request has been replaced with some concrete instance that implements all of the methods of{EffectName}Effect
, and call them as normal.To use your layer, wrap it in an effect handler for that effect. The effect handler will replace the effect request with an effect reference (usually of type
HandledEffectRef
), and then when it is called it will further replace that reference with a temporary implementation node implementing the effect.
To define a new effect, you should:
Create a new
Protocol
(e.g. a new class withProtocol
as the base class), by convention called{EffectName}Effect
, whose methods define the interface for that effect. For instance, a state effect would define methods for getting and setting values.Create a subclass of
EffectRequest
, by convention called{EffectName}Request
and overrideeffect_protocol
to return the protocol you defined in step 1. Optionally, add attributes that provide information to the handler that is needed to handle the effect.Create a subclass of
HandledEffectRef
, by convention calledHandled{EffectName}Ref
and overrideeffect_protocol
to return the protocol you defined in step 1. Optionally, add attributes that store information needed by the handler to handle the effect.Create a subclass of
EffectRuntimeImpl
that implements the protocol you defined in step 1, by convention called{EffectName}EffectImpl
. This does not have to be a PyTree dataclass node (although it can be). It is allowed to store a reference to some external state that it can modify. Note that you are also allowed to define multiple different implementations if needed.Create one or more subclasses of
EffectHandler
, by convention called something likeWith{EffectDescription}
, and configure them to replace the effect requests with refs when the handler is created, and then replaces the refs with a temporary implementation node when it is called.
Classes
A handler for a particular effect. |
|
Base class for "effect requests", which represent unhandled effects. |
|
Base class for runtime effect implementations. |
|
Base class for references to a handler that handles this effect. |
Functions
|
Collects the set of all handler IDs inside a model or submodel. |
|
Collects the effect types of each broken |
|
Collects the effect types of all |
|
Gets the default color for a given effect (for treescope rendering). |
|
Tries to generate a unique handler ID from the structure of a subtree. |
|
Decorator to register a treescope-rendering color for a given effect. |
Exceptions
Exception raised when a method is called on an unhandled effect. |