Skip to content

Python: declarative codegen config with a targets registry (parity with metaobjects.config.ts) #267

Description

@dmealing

Summary

The TypeScript port has a declarative config (metaobjects.config.tsdefineConfig with a targets registry), so a project's codegen surface is described once and both meta gen and meta verify --codegen read it. A platform gate is then just:

npx meta verify --templates --codegen

The Python port is flags-only. There is no config file and no targets registry, so everything a target needs — output directory, generator selection, entity allowlist, provider module — has to be passed on the command line. In practice that means it lives in CI shell scripts, which is exactly where configuration goes stale.

server/python/src/metaobjects/codegen/KNOWN_GAPS.md already anticipates this ("once the Python codegen grows per-target output directories (mirroring the TS targets registry)"), so this is a request to schedule what is already acknowledged.

What it looks like downstream

An adopter generating two separate Python model directories from one metadata tree ends up with, per gate:

PYTHONPATH=<dir-containing-provider> metaobjects gen <metadata-dir> \
  --out "$tmp" --generators entity \
  --entities Aaa,Bbb,Ccc,Ddd,Eee,Fff,Ggg,Hhh,Iii,Jjj,Kkk,Lll,Mmm,Nnn \
  --provider my_provider:provider \
  && diff -ru --exclude='__pycache__' <committed-dir> "$tmp"

Three problems follow from that:

  1. The entity list is duplicated into every place the gate runs — a local gate script plus one or more CI workflows. Add a model, update two of the three, and the new one is silently ungated. (An adopter hit exactly this: a committed generated directory sat several emitter minor-versions stale because nothing re-derived it, and the fix — consolidating the list into one shared script — is itself only a workaround for the missing config.)
  2. PYTHONPATH= is required to make a consumer provider importable as a top-level module, because the provider is named by module:symbol with no config-relative resolution.
  3. The gate is a hand-written gen-to-temp-and-diff, rather than verify --codegen (see the companion issue about verify --generators).

Proposed API

A metaobjects.config.py (or .yaml) beside the metadata:

config = {
  "providers": ["my_provider:provider"],
  "targets": [
    {"out": "pkg/models/generated", "generators": ["entity"], "entities": [...]},
    {"out": "pkg/other/generated",  "generators": ["entity"], "entities": [...]},
  ],
}
  • metaobjects gen with no arguments runs every target.
  • metaobjects verify --codegen with no arguments checks every target.
  • Provider module resolution relative to the config file, removing the PYTHONPATH requirement.

That is the same ergonomics the TS side already has, and it makes the duplicated-list failure mode structurally impossible rather than merely documented.

Scope

Python port only. No metamodel or vocabulary change, so no coordinated multi-port release.

Relationship to the other issue

Independent but complementary. verify --codegen --generators alone is enough to delete the hand-written diff scripts; the config file is what stops the entity lists living in CI at all. Either helps; together they reduce a multi-file shell gate to one command.

Filed against 0.20.11.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions