feat(ogar-from-ruff): Python/Odoo lift consuming ruff_python_spo#131
Conversation
…odel_graph_python) The ruff_python_spo frontend (ruff #34, merged to main at 80d7f2cb) emits the Odoo/Python SPO corpus under the `odoo` namespace. OGAR's lift previously hard-coded `Language::Ruby`, so an Odoo ModelGraph lifted with the wrong producer-language discriminant. Refactor `lift_model` / `lift_model_graph` to delegate to private `lift_model_with_language` / `lift_model_graph_with_language` and add public `lift_model_python` / `lift_model_graph_python` that stamp `Language::Python`. The projection is otherwise identical: the `odoo` namespace already routes to the `erp` source domain and `odoo` curator via the existing `classify_domain` path, so the Python wrapper changes only the language discriminant, nothing else. Language is set explicitly (per producer) rather than guessed from `ModelGraph::namespace`, because the namespace (openproject, odoo, …) does not bind one-to-one to the producer language. Two regression tests: - lift_model_python_stamps_python_language - lift_model_graph_python_stamps_python_and_keeps_erp_domain Verified via an isolated probe workspace (path-dep real ogar-vocab + git-dep ruff main @ 80d7f2cb): 28 tests pass, clippy -D warnings clean. The OGAR workspace itself cannot resolve offline (surrealdb git dep 403 via ogar-adapter-surrealql), so the probe is the verification path. Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a7495afba1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| /// projection to [`lift_model`]; only the language discriminant differs. | ||
| #[must_use] | ||
| pub fn lift_model_python(model: &Model) -> Class { | ||
| lift_model_with_language(model, Language::Python) |
There was a problem hiding this comment.
Map Python fields before exposing Odoo path
For ruff_python_spo/Odoo graphs with fields.X declarations, the ruff IR records those as Model::fields (the core SPO shape), while lift_model_with_language only reads the Rails-side model.attributes/model.associations vectors and never populates Class.attributes, Class.associations, or Class.computed_fields from fields. Delegating the new Python API directly to that projection means a normal Odoo model can be stamped Python/erp but lose its schema, so downstream consumers receive empty classes.
Useful? React with 👍 / 👎.
|
Codex's P1 is correct: stamping Fix in progress — a Python-only
That last mapping needs a disambiguator: Generated by Claude Code |
…odex P1 #131) The Python lift previously only set the language discriminant; it read the Rails-side AR-DSL vectors (model.attributes / model.associations / …), which are empty for an Odoo model. An Odoo model carries its schema in the core-7 `Model::fields` vector, so the lifted class came out with empty attributes / associations / computed_fields — downstream consumers got a schema-less class (Codex P1 on #131). Add a Python-only `project_odoo_fields` pass mapping `Model::fields` onto the existing Class columns: - relational field (target set) -> Association; kind from `relation_kind` (many2one->BelongsTo, one2many->HasMany, many2many->HasAndBelongsToMany), class_name = raw comodel, inverse_of = One2many inverse. - non-relational field -> Attribute. - compute field (emitted_by set) -> ComputedField (method + @api.depends), in addition to its Attribute/Association. Gated on Language::Python: Rails ALSO populates Model::fields (DB columns), so projecting them for Rails would double-count its AR-DSL surface. Adds `ComputedField::new(field, compute_method)` to ogar-vocab (it lacked a constructor; #[non_exhaustive] makes a struct literal non-constructible cross-crate — parallels Association::new / Attribute::new). Consumes ruff's `relation_kind` predicate (AdaWorldAPI/ruff#35): target + inverse_name alone can't separate a Many2one from a Many2many (both comodel-only, no inverse), so the kind is required to pick the right AssociationKind. Tests: lift_model_python_projects_odoo_fields (scalar/relational/compute, incl. the M2O-vs-M2M case) + lift_model_ruby_does_not_project_fields (Ruby gating). Verified via probe (local ruff w/ relation_kind + real ogar-vocab): 30 tests pass, clippy -D warnings clean. NOTE: not yet pushed — gated on ruff#35 landing on ruff main + an OGAR Cargo.lock ruff-commit bump. Co-Authored-By: Claude <noreply@anthropic.com>
|
The Codex P1 from this PR (the Python lift dropping Odoo schema because it never projected Generated by Claude Code |
…sembler
Adds the keystone gap named in E-KEEP-AR-REMOVE-ORM / the OP convergence
assessment: a Rails-correct sibling of compile_graph_python. Identical
shape (mint_graph::<P> + per-class facet resolution) but routes through
the existing lift_model_graph (Language::Ruby) instead of
lift_model_graph_python — pure operator-reuse, no new lift, and
project_odoo_fields is correctly never invoked for Rails (it would
double-count; lift_model_graph_python's own doc-comment says so).
Proves the convergence claim in code: compile_graph_ruby::<OpenProjectPort>
on a WorkPackage graph and compile_graph_ruby::<RedminePort> on an Issue
graph mint to the SAME low-u16 concept (0x0102 project_work_item) and
DIFFERENT high-u16 render prefixes (0x0001 vs 0x0007) — one canonical
concept, two render skins, machine-checked rather than asserted.
Drive-by fix: 3 pre-existing Function{...} literal constructions
(emit.rs, mint.rs's account_move fixture, lib.rs) broke against the
already-merged ruff#38 (writes/calls fields) because this crate's
ruff_spo_triplet dep floats on branch=main. Added ..Default::default()
to each — no behavior change, restores compilation.
Verification: standalone probe workspace (path-dep ogar-vocab +
ogar-from-ruff, git-dep ruff branch=main) — the OGAR workspace itself
can't resolve in-sandbox (ogar-adapter-surrealql's surrealdb-ast git dep
403s), the same pattern prior PRs (#131/#132/#136/#138/#141) used.
44/44 tests pass (3 new + 41 pre-existing unbroken); clippy --no-deps
-D warnings clean at the pinned 1.95.0 toolchain (ogar-vocab itself has
pre-existing unrelated clippy debt from never being --workspace-gated,
out of scope here); doc-links resolve.
Summary
Adds the Python-aware lift path to
ogar-from-ruff, consuming the now-mergedruff_python_spofrontend (ruff #34, merged tomainat80d7f2cb). This is the OGAR half of the odoo-rs transcode track: ruff produces the Odoo/Python SPO corpus, OGAR lifts it intoogar_vocab::Classwith the correct producer-language discriminant.Before this change, the lift hard-coded
Language::Ruby, so an OdooModelGraph(namespaceodoo) lifted as if produced byruff_ruby_spo(Rails). The projection was otherwise correct — only the language stamp was wrong.What changed
lift_model/lift_model_graphto delegate to privatelift_model_with_language/lift_model_graph_with_language.lift_model_python/lift_model_graph_pythonthat stampLanguage::Python.odoonamespace already routes to theerpsource domain andodoocurator via the existingclassify_domainpath — the Python wrapper changes only the language discriminant, nothing else in the projection.ModelGraph::namespace, because the namespace (openproject,odoo, …) does not bind one-to-one to the producer language.Tests
Two regression tests added:
lift_model_python_stamps_python_languagelift_model_graph_python_stamps_python_and_keeps_erp_domain(asserts Python language anderpdomain /odoocurator preserved)Verification
Verified via an isolated probe workspace (path-dep real
ogar-vocab+ git-depruffmain@80d7f2cb): 28 tests pass,clippy -D warningsclean.Notes
lib.rs(the crate is not fmt-gated, norustfmt.toml) was left untouched; the added code matches the file's existing style.🤖 Generated with Claude Code
Generated by Claude Code