Source code for mafw.processor.meta
# Copyright 2025–2026 European Union
# Author: Bulgheroni Antonio (antonio.bulgheroni@ec.europa.eu)
# SPDX-License-Identifier: EUPL-1.2
"""
Metaclass for the Processor framework.
This module defines :class:`~mafw.processor.ProcessorMeta`, the metaclass responsible for
finalising every :class:`~mafw.processor.Processor` subclass at creation time.
Its duties include:
- Ensuring parameter definitions are properly inherited and registered.
- Validating any declared filter schema against the allowed model constraints.
- Installing the super-call wrappers that guard method execution at runtime.
- Invoking :meth:`~mafw.processor.Processor.__post_init__` after each instance
is constructed.
.. versionadded:: 2.3
Extracted from the monolithic ``processor.py`` module for improved
maintainability and focused testing.
"""
from __future__ import annotations
from typing import TYPE_CHECKING, Any, cast
from mafw.processor.parameters import _ensure_parameter_definitions, _validate_filter_schema
if TYPE_CHECKING:
from mafw.processor.base import Processor
[docs]
class ProcessorMeta(type):
"""Metaclass that finalizes Processor subclasses before instantiation."""
def __init__(cls, name: str, bases: tuple[type, ...], namespace: dict[str, Any]) -> None:
"""
Set up new Processor subclasses.
This method first checks the class for well-formed parameter definitions
and filter metadata, then runs the super-call wrapping machinery described
below. The wrappers are installed at class-creation time so that any later
instance will be guarded before it even starts executing.
"""
super().__init__(name, bases, namespace)
# Validate and register parameter descriptors declared on the new class.
_ensure_parameter_definitions(cast(type['Processor'], cls))
_validate_filter_schema(cast(type['Processor'], cls))
# If the metaclass detected a deferred error during descriptor registration
# (e.g. duplicate parameter names), raise it now.
error = getattr(cls, '_parameter_definition_error', None)
if error is not None:
delattr(cls, '_parameter_definition_error')
raise error
# For concrete Processor subclasses (not Processor itself), install wrappers
# that verify super() was called in overridden lifecycle methods.
if any(base.__name__ == 'Processor' for base in cls.__mro__[1:]):
apply_wrappers = getattr(cls, '_apply_super_call_wrappers', None)
if apply_wrappers is not None:
apply_wrappers()
def __call__(cls, *args: Any, **kwargs: Any) -> ProcessorMeta:
"""
Create a new Processor instance and run post-initialisation.
After the standard ``type.__call__`` produces the instance, this override
invokes ``__post_init__`` — giving subclasses a hook that runs after
``__init__`` completes but before the caller receives the object.
"""
obj = type.__call__(cls, *args, **kwargs)
obj.__post_init__()
return cast(ProcessorMeta, obj)