@@ -1227,93 +1227,101 @@ def load_entity(
12271227 # enable cache to speed up loading
12281228 self .site .enable_cache ()
12291229
1230- entities = []
1231- pages = self .site .get_page (
1232- WtSite .GetPageParam (titles = param .titles , offline_pages = param .offline_pages )
1233- ).pages
1234- for page in pages :
1235- entity = None
1236- schemas = []
1237- schemas_fetched = True
1238- jsondata = page .get_slot_content ("jsondata" )
1239- if param .remove_empty :
1240- remove_empty (jsondata )
1241- if jsondata :
1242- for category in jsondata ["type" ]:
1243- schema = (
1244- self .site
1245- .get_page (
1246- WtSite .GetPageParam (
1247- titles = [category ], offline_pages = param .offline_pages
1230+ # the restore runs in a finally block so that an exception from any of the
1231+ # calls below cannot leave the cache enabled for the rest of the process
1232+ try :
1233+ entities = []
1234+ pages = self .site .get_page (
1235+ WtSite .GetPageParam (
1236+ titles = param .titles , offline_pages = param .offline_pages
1237+ )
1238+ ).pages
1239+ for page in pages :
1240+ entity = None
1241+ schemas = []
1242+ schemas_fetched = True
1243+ jsondata = page .get_slot_content ("jsondata" )
1244+ if param .remove_empty :
1245+ remove_empty (jsondata )
1246+ if jsondata :
1247+ for category in jsondata ["type" ]:
1248+ schema = (
1249+ self .site
1250+ .get_page (
1251+ WtSite .GetPageParam (
1252+ titles = [category ], offline_pages = param .offline_pages
1253+ )
12481254 )
1255+ .pages [0 ]
1256+ .get_slot_content ("jsonschema" )
12491257 )
1250- .pages [0 ]
1251- .get_slot_content ("jsonschema" )
1252- )
1253- schemas .append (schema )
1254- # generate model if not already exists
1255- cls_name : str = schema ["title" ]
1256- # If a schema_to_use is provided, we do not need to check if the
1257- # model exists
1258- if not param .model_to_use :
1259- if not hasattr (model , cls_name ):
1260- if param .autofetch_schema :
1261- self .fetch_schema (
1262- OSW .FetchSchemaParam (
1263- schema_title = category ,
1264- mode = "append" ,
1265- offline_pages = param .offline_pages ,
1258+ schemas .append (schema )
1259+ # generate model if not already exists
1260+ cls_name : str = schema ["title" ]
1261+ # If a schema_to_use is provided, we do not need to check if
1262+ # the model exists
1263+ if not param .model_to_use :
1264+ if not hasattr (model , cls_name ):
1265+ if param .autofetch_schema :
1266+ self .fetch_schema (
1267+ OSW .FetchSchemaParam (
1268+ schema_title = category ,
1269+ mode = "append" ,
1270+ offline_pages = param .offline_pages ,
1271+ )
12661272 )
1273+ if not hasattr (model , cls_name ):
1274+ schemas_fetched = False
1275+ print (
1276+ f"Error: Model { cls_name } not found. Schema { category } "
1277+ f"needs to be fetched first."
12671278 )
1268- if not hasattr (model , cls_name ):
1269- schemas_fetched = False
1270- print (
1271- f"Error: Model { cls_name } not found. Schema { category } "
1272- f"needs to be fetched first."
1273- )
1274- if not schemas_fetched :
1275- continue
1276-
1277- try :
1278- if param .model_to_use :
1279- entity : model .OswBaseModel = param .model_to_use (** jsondata )
1279+ if not schemas_fetched :
1280+ continue
12801281
1281- elif len (schemas ) == 0 :
1282- _logger .error ("Error: no schema defined" )
1282+ try :
1283+ if param .model_to_use :
1284+ entity : model .OswBaseModel = param .model_to_use (** jsondata )
12831285
1284- elif len (schemas ) == 1 :
1285- cls : Type [model .Entity ] = getattr (model , schemas [0 ]["title" ])
1286- entity : model .Entity = cls (** jsondata )
1286+ elif len (schemas ) == 0 :
1287+ _logger .error ("Error: no schema defined" )
12871288
1288- else :
1289- bases = []
1290- for schema in schemas :
1291- bases .append (getattr (model , schema ["title" ]))
1292- cls = create_model ("Test" , __base__ = tuple (bases ))
1293- entity : model .Entity = cls (** jsondata )
1294- except Exception as e :
1295- _logger .error (f"Error creating entity from page { page .title } : { e } " )
1296- # legacy: `entity` is annotated as OswBaseModel and Entity above
1297- entity = None # ty: ignore[conflicting-declarations]
1289+ elif len (schemas ) == 1 :
1290+ cls : Type [model .Entity ] = getattr (model , schemas [0 ]["title" ])
1291+ entity : model .Entity = cls (** jsondata )
12981292
1299- if entity is not None :
1300- # make sure we do not override existing metadata
1301- if not hasattr (entity , "meta" ) or entity .meta is None :
1302- entity .meta = model .Meta ()
1303- if (
1304- not hasattr (entity .meta , "wiki_page" )
1305- or entity .meta .wiki_page is None
1306- ):
1307- entity .meta .wiki_page = model .WikiPage ()
1308- entity .meta .wiki_page .namespace = namespace_from_full_title (page .title )
1309- entity .meta .wiki_page .title = title_from_full_title (page .title )
1293+ else :
1294+ bases = []
1295+ for schema in schemas :
1296+ bases .append (getattr (model , schema ["title" ]))
1297+ cls = create_model ("Test" , __base__ = tuple (bases ))
1298+ entity : model .Entity = cls (** jsondata )
1299+ except Exception as e :
1300+ _logger .error (f"Error creating entity from page { page .title } : { e } " )
1301+ # legacy: `entity` is annotated as OswBaseModel and Entity above
1302+ entity = None # ty: ignore[conflicting-declarations]
1303+
1304+ if entity is not None :
1305+ # make sure we do not override existing metadata
1306+ if not hasattr (entity , "meta" ) or entity .meta is None :
1307+ entity .meta = model .Meta ()
1308+ if (
1309+ not hasattr (entity .meta , "wiki_page" )
1310+ or entity .meta .wiki_page is None
1311+ ):
1312+ entity .meta .wiki_page = model .WikiPage ()
1313+ entity .meta .wiki_page .namespace = namespace_from_full_title (
1314+ page .title
1315+ )
1316+ entity .meta .wiki_page .title = title_from_full_title (page .title )
13101317
1311- entities .append (entity )
1312- # restore original cache state
1313- if cache_state :
1314- self .site .enable_cache ()
1315- else :
1316- self .site .disable_cache ()
1318+ entities .append (entity )
1319+ finally :
1320+ # restore original cache state
1321+ if cache_state :
1322+ self .site .enable_cache ()
1323+ else :
1324+ self .site .disable_cache ()
13171325
13181326 if isinstance (entity_title , str ): # single title
13191327 if len (entities ) >= 1 :
@@ -1701,8 +1709,11 @@ class StoreEntityResult(OswBaseModel):
17011709 """The pages that have been successfully stored, keyed by full page title.
17021710 On partial failure this contains only the successfully-stored pages."""
17031711 failed : Dict [str , Exception ] = {}
1704- """Entities that could not be stored, keyed by full page title and mapped to
1705- the exception that caused the failure. Empty on full success."""
1712+ """Entities that could not be stored, mapped to the exception that caused the
1713+ failure. Empty on full success. The key is the full page title where one could
1714+ be determined. For an entity whose title or namespace could not be resolved it
1715+ falls back to the entity name, then to its uuid, then to 'unknown', so do not
1716+ parse this key as 'namespace:title'."""
17061717
17071718 class Config :
17081719 arbitrary_types_allowed = True
@@ -1859,20 +1870,23 @@ def store_entity_(
18591870 entity_name = getattr (entity_ , "name" , None ) or getattr (
18601871 entity_ , "uuid" , "unknown"
18611872 )
1862- _logger .error (f"Error getting title for entity '{ entity_name } ': { e } " )
1863- return
1873+ # raise instead of returning: a plain return is not an exception,
1874+ # so the collector loop below would record the entity in neither
1875+ # created_pages nor failed and store_entity would report success
1876+ raise ValueError (
1877+ f"Error getting title for entity '{ entity_name } ': { e } "
1878+ ) from e
18641879 if namespace_ is None :
18651880 namespace_ = get_namespace (entity_ )
18661881 if namespace_ is None or title_ is None :
18671882 entity_name = getattr (entity_ , "name" , None ) or getattr (
18681883 entity_ , "uuid" , "unknown"
18691884 )
1870- _logger . error (
1885+ raise TypeError (
18711886 f"Unsupported entity type: namespace={ namespace_ } , "
18721887 f"title={ title_ } , entity name='{ entity_name } ', "
18731888 f"type={ type (entity_ ).__name__ } "
18741889 )
1875- return
18761890 if overwrite_class_param is None :
18771891 raise TypeError ("'overwrite_class_param' must not be None!" )
18781892 entity_title = namespace_ + ":" + title_
0 commit comments