fix(core): prefer a registered class over a generated one - #166
fix(core): prefer a registered class over a generated one#166LukasGold wants to merge 2 commits into
Conversation
- load_entity looked up classes by name in osw.model.entity only - a packaged class registered for the category IRI was invisible - the generated class then took over the oold type registry slot - warn instead of silently replacing a foreign registration - closes #138
Release previewMerging this PR would release v2.3.2 (current: Changelog preview (truncated)## v2.3.2 (2026-09-04)
### Bug Fixes
- **core**: Ignore registered subclasses of the canonical model class
([`07e7e99`](https://github.com/OpenSemanticLab/osw-python/commit/07e7e998bdb6265b6ed3734ad0c8869a892355dc))
- **core**: Prefer a registered class over a generated one
([`f4c7e01`](https://github.com/OpenSemanticLab/osw-python/commit/f4c7e01bee60c708de865a39ce0bd540cc5adb11))
Preview via python-semantic-release and conventional commits. |
- controllers and result wrappers inherit the category IRI they extend - oold's registry keeps whichever of them was defined last - UploadFileResult thus replaced WikiFile and broke file up/download - prefer osw.model.entity's class when the registered one specializes it
|
Integration tests caught a regression in this PR: Cause. Preferring the registered class unconditionally is not safe, because osw's own classes reuse a category IRI.
Fix (07e7e99): ignore a registered class that is a strict subclass of the class New offline regression test asserts a registered specialization requiring an extra field is skipped. Without the fix it fails with the same shape as CI: Local: 195 passed, 1 skipped. Integration needs a re-run here. |
Closes #138
Problem
load_entitydecided whether to compile a class by askinghasattr(model, cls_name), wherecls_nameisschema["title"]. That is keyed by class name and only ever looks inosw.model.entity, so a packaged class already registered for the category IRI (e.g.opensemantic.base.v1.Database) was invisible. A new class got compiled, took over the oold type registry slot for that category, and the packaged typed fields and helpers were lost. For ooldrangefields the reference then resolves toNonewith no error.Confirmed while writing the tests: importing
osw.corealone already registersDatabaseunderCategory:OSW51ad0d17...inoold.model.v1._types, even thoughosw.model.entitynever exposesDatabaseby name. That mismatch is the bug.Changes
load_entitynow looks the category IRI up in the oold type registry first and reuses a registered class instead of compiling a replacement.category_to_clsmap for both the single-schema and the multiple-inheritance base list, instead ofgetattr(model, schema["title"])._loggerrather than passing silently. It warns rather than raising, so existing setups keep working.param.model_to_usestill takes precedence and its branch is unchanged.Registry API
The issue proposed
oold.model._typesandoold.model.v1._types. Against the installed oold 0.16.2 only the v1 registry is relevant: osw model classes descend frompydantic.v1.BaseModel/oold.model.v1.LinkedBaseModel, and entries are written byLinkedBaseModelMetaClass.__new__when a subclass is defined.oold.static.resolve_typeis not a usable accessor here, since it still requires the caller to pass the private dict and adds controller-preference logic osw never uses.Out of scope, deliberately
The issue notes that the
jsonschemaslot no longer needs fetching when a class is already registered, and asks to keep that separate sinceschemasstill feeds the multiple-inheritance base list. This PR keeps the fetch unconditional and does not take that optimization.Tests
tests/test_load_entity_registered_class.py, fully offline:type(entity) is Database, and no newDatabaseis compiled intoosw.model.entityThe first and third fail on unpatched code; the second passes there, since it guards behaviour that is genuinely unchanged. Full unit suite: 194 passed, 1 skipped.