Skip to content

Commit 07e7e99

Browse files
committed
fix(core): ignore registered subclasses of the canonical model class
- 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
1 parent f4c7e01 commit 07e7e99

2 files changed

Lines changed: 73 additions & 0 deletions

File tree

‎src/osw/core.py‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,6 +1266,26 @@ def load_entity(
12661266
# registry entry for this category and hide the packaged
12671267
# class' typed fields/helpers.
12681268
registered_cls = oold_type_registry.get(category)
1269+
# Controllers and result wrappers (e.g.
1270+
# WikiFileController, UploadFileResult) inherit their
1271+
# category IRI from the model class they extend, and
1272+
# the registry keeps whichever class was defined last.
1273+
# Such a specialization asks for fields a plain page's
1274+
# jsondata does not carry, so prefer the canonical
1275+
# class from osw.model.entity over a subclass of it.
1276+
canonical_cls = getattr(model, cls_name, None)
1277+
if (
1278+
registered_cls is not None
1279+
and canonical_cls is not None
1280+
and registered_cls is not canonical_cls
1281+
and issubclass(registered_cls, canonical_cls)
1282+
):
1283+
_logger.debug(
1284+
f"Ignoring '{registered_cls}' registered for "
1285+
f"category '{category}': it specializes "
1286+
f"'{canonical_cls}', which is used instead."
1287+
)
1288+
registered_cls = None
12691289
if registered_cls is not None:
12701290
category_to_cls[category] = registered_cls
12711291
else:

‎tests/test_load_entity_registered_class.py‎

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,59 @@ def test_load_entity_falls_back_to_generated_class_when_nothing_registered():
171171
delattr(model, cls_name)
172172

173173

174+
def test_load_entity_ignores_a_registered_subclass_of_the_model_class():
175+
"""osw's own controllers and result wrappers (WikiFileController,
176+
UploadFileResult, ...) inherit the category IRI of the model class they
177+
extend, and oold's registry keeps whichever class was defined last. Such a
178+
specialization needs fields a plain page does not carry, so load_entity()
179+
must fall back to the canonical class in osw.model.entity.
180+
"""
181+
category = "Category:OSWSubclassTest000000000000000000000000"
182+
cls_name = "SubclassTestBase"
183+
184+
base_cls = make_isolated_cls(cls_name)
185+
# a controller-like specialization that additionally requires a field the
186+
# page's jsondata does not provide, mirroring UploadFileResult.source
187+
specialized_cls = type(base_cls)(
188+
"SubclassTestController",
189+
(base_cls,),
190+
{"__annotations__": {"source": str}, "__qualname__": "SubclassTestController"},
191+
)
192+
setattr(model, cls_name, base_cls)
193+
oold_type_registry[category] = specialized_cls
194+
try:
195+
entity_page = OfflineWtPage(
196+
title="Item:OSWSubclassEntity0000000000000000000000000"
197+
)
198+
jsondata = {
199+
"type": [category],
200+
"uuid": "22222222-2222-2222-2222-222222222222",
201+
"name": "x",
202+
"label": [{"text": "x"}],
203+
}
204+
remove_empty(jsondata)
205+
entity_page.set_slot_content("jsondata", jsondata)
206+
schema_page = make_schema_page(category, cls_name)
207+
208+
osw_obj = OSW(site=make_offline_wtsite())
209+
210+
result = osw_obj.load_entity(
211+
OSW.LoadEntityParam(
212+
titles=[entity_page.title],
213+
autofetch_schema=True,
214+
offline_pages={
215+
entity_page.title: entity_page,
216+
category: schema_page,
217+
},
218+
)
219+
)
220+
221+
assert type(result.entities[0]) is base_cls
222+
finally:
223+
delattr(model, cls_name)
224+
oold_type_registry.pop(category, None)
225+
226+
174227
def test_load_entity_warns_on_registry_conflict(monkeypatch, caplog):
175228
"""If the class about to be used for a category differs from whatever is
176229
now registered for that IRI, load_entity() logs a warning instead of

0 commit comments

Comments
 (0)