Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Python metaclasses: validate a class before registering its wire format

Last updated: 30 Sept 20264 min read
tutorial
IntermediateBy AITrove Editorial

A metaclass constructs class objects and can enforce a class-level contract before publishing a class into a registry.

Download Python source kit

Operation contract

The codec registry requires a unique nonempty wire name and a decode function on each concrete class. Validation and type construction finish before the registry is updated. A duplicate declaration raises without replacing the previously accepted codec. The base class deliberately has no wire name and is not registered.

Failure and ownership boundary

This is a local class registry, not automatic loading of received plugin paths. Metaclass conflicts can arise with multiple bases, and another hook can have its own side effects. Preserve the class namespace when passing it to type.__new__, including compiler-provided cells. For many simple subclass checks, __init_subclass__ is sufficient; Python ABC: prevent construction of an incomplete implementation and Python super and method resolution: cooperate across mixins cover other mechanisms.

Working program

python
CODECS = {}
class CodecMeta(type):
    def __new__(metaclass, name, bases, namespace, **options):
        wire_name = namespace.get("wire_name")
        if wire_name is not None:
            if not isinstance(wire_name, str) or not wire_name or wire_name in CODECS:
                raise ValueError("wire name rejected")
            if not callable(namespace.get("decode")):
                raise ValueError("decode function required")
        created = super().__new__(metaclass, name, bases, namespace, **options)
        if wire_name is not None:
            CODECS[wire_name] = created
        return created

class ReceiptCodec(metaclass=CodecMeta):
    wire_name = None

class ReceiptJson(ReceiptCodec):
    wire_name = "receipt-json"
    def decode(payload):
        return payload["receipt_id"]

print(CODECS["receipt-json"].decode({"receipt_id": "R-0041"}))
try:
    class DuplicateReceipt(ReceiptCodec):
        wire_name = "receipt-json"
        def decode(payload):
            return payload
except ValueError:
    print("duplicate class rejected")
print(CODECS["receipt-json"] is ReceiptJson)

Output

Output
R-0041
duplicate class rejected
True

Costs and limits

Class construction performs validation once per declaration and retains the accepted class in the registry. The registry therefore owns its classes until removed. This fixture has no weak retention or plugin unload policy.

Common Mistakes

  • Do not publish a registry entry before class construction succeeds.
  • A metaclass does not make received plugin code safe to execute.

Connected lessons

Python ABC: prevent construction of an incomplete implementation, Python super and method resolution: cooperate across mixins, Python weak references: a cache does not own its values.

Check the next state boundary

Python __init_subclass__: validate declarations without a custom metaclass, Python plugin project: load owned code and publish only an accepted interface.

python
metaclass-registry
Storage details