Skip to content

Commit 6d019cf

Browse files
authored
Merge pull request #269 from metaobjectsdev/fix/267-python-declarative-config
feat(python): declarative codegen config with a targets registry
2 parents 0d05bee + 606437b commit 6d019cf

12 files changed

Lines changed: 2412 additions & 8 deletions

‎docs/features/cli.md‎

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,57 @@ at `-Dmeta.verify.templateRoot`). The one goal covers BOTH Java (`codegen-spring
8484
migrate engine, ADR-0015"); an unknown mode fails listing the valid ones. (Schema `--db` remains
8585
Node-only by the ADR-0015 design — see below.)
8686

87+
## Declarative config (`metaobjects.config.yaml`) — Python codegen
88+
89+
Alongside its flag-only mode (`metaobjects gen <metadata_dir> --out <dir>`), the
90+
Python `metaobjects` CLI supports a declarative project config,
91+
`metaobjects.config.yaml` (#267). The **schema keys are identical to the TS
92+
`metaobjects.config.ts` vocabulary** — a polyglot adopter learns one
93+
targets-registry shape regardless of port. A JSON Schema ships at
94+
[`server/python/src/metaobjects/codegen/metaobjects-config.schema.json`](../../server/python/src/metaobjects/codegen/metaobjects-config.schema.json)
95+
for editor autocomplete and non-Python validation.
96+
97+
```yaml
98+
metadata: metaobjects # optional, default "metaobjects" — relative to this file
99+
providers: # optional; "module:symbol" refs, resolved config-relative (no PYTHONPATH=)
100+
- my_project.providers:register_custom_types
101+
targets:
102+
api:
103+
outDir: src/generated/api
104+
generators: [entity, routes] # optional; stable names from `metaobjects gen --list`; omit = default suite
105+
admin:
106+
outDir: src/generated/admin
107+
entities: [Author, Book] # optional allowlist; omit = every entity
108+
```
109+
110+
- **`metaobjects gen`** with no positional `<metadata_dir>` runs config mode:
111+
it loads the config and metadata once and runs every target into its own
112+
`outDir`, with a cross-target guard against two targets writing the same
113+
output path. `--target <name>` scopes the run to a single target.
114+
- **`metaobjects verify --codegen`** — including bare `verify`, since
115+
`--codegen` is the Python default (see above) — runs the matching config
116+
mode with no positional `<metadata_dir>`: it regenerates the whole selection
117+
into a temp tree (the exact `gen` pipeline, including the cross-target
118+
duplicate-output-path guard) and diffs each **unique `outDir`** against the
119+
union of the co-resident targets' regen, aggregating the exit code (non-zero
120+
if *any* outDir has drifted). Targets sharing an `outDir` are verified
121+
together, so a shared `outDir` is never a false-positive `extra`. `--target`
122+
widens to the `outDir`-sharing closure (an `outDir` is verified as a unit).
123+
Strict-attr loading (ADR-0023) still applies unless `--lax` is passed.
124+
- **`--config <path>`** picks the config file explicitly on either command;
125+
with no positional metadata dir and no `--config`, both commands default to
126+
looking for `./metaobjects.config.yaml` in the current directory.
127+
- **Providers resolve config-relative.** A `providers:` entry is imported
128+
with the config file's own directory prepended to `sys.path`, so a
129+
consumer provider module living beside the config resolves with no
130+
`PYTHONPATH=` needed (unlike the flag-only `--provider module:symbol`
131+
path, which relies on the ambient environment).
132+
- **Back-compat is load-bearing.** Passing an explicit positional
133+
`<metadata_dir>` (with `--out` on `gen`, or `--out` on `verify --codegen`)
134+
keeps the original flag-only path byte-identical — the config file is never
135+
consulted. Config mode activates only when no positional `<metadata_dir>`
136+
is given.
137+
87138
## `meta gen` / `meta verify` run an advisory anti-pattern pass (Node `meta`)
88139

89140
Both `meta verify` and a real `meta gen` write run (not `--dry-run`) end with a

‎docs/features/own-your-codegen.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ provider class** in each language: a JSON file could express the declarative sur
6262
| Port | How the CLI / build tool loads your provider |
6363
|---|---|
6464
| **TypeScript** | `metaobjects.config.ts` → `providers: [myProvider]`. Threaded into `meta gen`, `meta verify`, `meta docs`, **and** the offline `meta migrate` paths (baseline + generate). |
65-
| **Python** | `metaobjects gen \| verify \| docs --provider module:symbol` (repeatable). The symbol resolves to a `Provider` (or a list, or a zero-arg factory returning one) and is composed **on top of** the core providers — parity with TS `config.providers`. E.g. `metaobjects gen ./metaobjects --out ./gen --provider myapp.providers:view_provider`. |
65+
| **Python** | `metaobjects gen \| verify \| docs --provider module:symbol` (repeatable). The symbol resolves to a `Provider` (or a list, or a zero-arg factory returning one) and is composed **on top of** the core providers — parity with TS `config.providers`. E.g. `metaobjects gen ./metaobjects --out ./gen --provider myapp.providers:view_provider`. A declarative `metaobjects.config.yaml` `providers:` list is also supported (resolved config-relative, no `PYTHONPATH=` — mirroring TS's config-file providers); see [`cli.md`](cli.md). |
6666
| **Java / Kotlin** | Put your compiled `MetaDataTypeProvider` on the **project classpath** with a `META-INF/services/com.metaobjects.registry.MetaDataTypeProvider` entry. `metaobjects-maven-plugin` builds the loader with the project classloader, so **Java ServiceLoader auto-discovers it** — no plugin config needed. |
6767
| **C#** | The loader accepts providers like every port; a first-class `dotnet meta` consumer-provider hook is tracked for a future release ([#158](https://github.com/metaobjectsdev/metaobjects/issues/158)). Today, extend the metamodel from an app that constructs the loader directly. |
6868

‎docs/ports/python.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,12 @@ metaobjects gen ./metadata --out ./generated # codegen → write
9595
metaobjects verify ./metadata --out ./generated # drift gate; bare verify defaults to --codegen
9696
```
9797

98+
For multi-target projects (several `outDir`s, per-target generator/entity
99+
selection, config-relative provider resolution), `metaobjects gen`/`verify` also
100+
read a declarative [`metaobjects.config.yaml`](../features/cli.md) (#267) — run
101+
either with no positional `<metadata_dir>` to use it; the flag path above stays
102+
byte-identical.
103+
98104
**Both `pydantic` and `fastapi` are consumer-installed, not transitive deps of
99105
`metaobjects` itself** — the entity/router files this emits `import pydantic`
100106
and `import fastapi`, so add them before importing the generated code:

0 commit comments

Comments
 (0)