[Feature]: Enforce Abstract↔Concrete type-hint coherence via a metaclass
- Dominant language
- Python
- Stars
- 42
- Forks
- 18
- Avg merge
- 1m
- Merged PRs (30d)
- 1
Description
### 🤔 Problem Description
After merging PR #143, we will have **Beartype** on every method, but nothing automatically verifies that each **concrete** class still honors the **abstract** class’s type hints.
A small drift—e.g. changing an `add(...)` signature—can silently break downstream code or introduce subtle variance bugs that only fail at runtime.
### 💡 Proposed Solution
1. **Add a new metaclass** (e.g. `InterfaceMeta`) in a util module (say `mesa_frames.utils.interface_meta`) that, in its `__init__`, walks every `ABC` base and uses Beartype’s `is_subhint` to compare each abstract method’s type hints against the override in the subclass—raising a `TypeError` at class‐definition time on mismatch.
2. **Switch our ABCs** (like `AgentContainer`) to use `metaclass=InterfaceMeta` instead of plain `ABCMeta`. Any drop-in mismatch in `AgentSetPolars` (or any other subclass) will now fail immediately when Python imports the module, giving a clear error message.
### Example in mesa-frames
```python
# mesa_frames/abstract/agents.py
from abc import abstractmethod
from typing import get_type_hints
from typing_extensions import Self
from mesa_frames.types_ import DataFrameInput
from collections.abc import Collection
…
class AgentSetDF(AgentContainer, DataFrameMixin):
@abstractmethod
def add(
self,
agents: DataFrameInput,
inplace: bool = True,
) -> Self:
"""Add agents to the container."""
…
```
```python
# mesa_frames/concrete/agentset.py
import polars as pl
from typing import Sequence, Any
from mesa_frames.abstract.agents import AgentSetDF
from mesa_frames.utils.interface_meta import InterfaceMeta
class AgentSetPolars(AgentSetDF, PolarsMixin, metaclass=InterfaceMeta):
def add(
self,
agents: pl.DataFrame | Sequence[Any] | dict[str, Any],
inplace: bool = True,
) -> Self:
"""Polars-backed add implementation."""
…
```
Here, the metaclass check would ensure that the concrete `add`’s `agents:` hint (`pl.DataFrame | Sequence[Any] | dict[str,Any]`) is a valid **superhint** of the abstract `DataFrameInput` alias (`dict[str, Any] | Sequence[Sequence] | pl.DataFrame`), and would error out at class‐definition time if someone ever drifted one side out of alignment.
### 🔄 Alternatives Considered
- **Decorator** (opt-in per class), but easy to forget.
- **CI test** to compare signatures, but that only catches errors later in testing.
### ➕ Additional Context
- **Abstract**: [`mesa_frames/abstract/agents.py`](https://github.com/projectmesa/mesa-frames/blob/main/mesa_frames/abstract/agents.py)
- **Concrete**: [`mesa_frames/concrete/agentset.py`](https://github.com/projectmesa/mesa-frames/blob/main/mesa_frames/concrete/agentset.py)
Contributor guide
Research direction
Start by reading mesa_frames/abstract/agents.py and mesa_frames/concrete/agentset.py, then review the proposed mesa_frames.utils.interface_meta entry point and Beartype's is_subhint behavior. The work is done when ABCs use the new metaclass and incompatible concrete type hints raise TypeError at class-definition time with a clear error message.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100