11#
22# Gramps Web API - A RESTful API for the Gramps genealogy program
33#
4- # Copyright (C) 2020 David Straub
4+ # Copyright (C) 2020-2023 David Straub
55#
66# This program is free software; you can redistribute it and/or modify
77# it under the terms of the GNU Affero General Public License as published by
2121
2222import json
2323from abc import abstractmethod
24- from typing import Dict , List , Sequence
24+ from typing import Dict , List
2525
26- from flask import Response , abort , current_app , request
26+ from flask import Response , abort , request
2727from gramps .gen .const import GRAMPS_LOCALE as glocale
2828from gramps .gen .db import DbTxn
2929from gramps .gen .db .base import DbReadBase
3333from gramps .gen .utils .grampslocale import GrampsLocale
3434from webargs import fields , validate
3535
36- from ...auth import get_tree_usage , set_tree_usage
3736from ...auth .const import PERM_ADD_OBJ , PERM_DEL_OBJ , PERM_EDIT_OBJ
37+ from ...const import GRAMPS_OBJECT_PLURAL
3838from ..auth import require_permissions
3939from ..search import SearchIndexer
4040from ..util import (
5555from .util import (
5656 abort_with_message ,
5757 add_object ,
58+ filter_missing_files ,
5859 fix_object_dict ,
5960 get_backlinks ,
6061 get_extended_attributes ,
61- get_missing_media_file_handles ,
6262 get_reference_profile_for_object ,
6363 get_soundex ,
6464 hash_object ,
@@ -109,18 +109,18 @@ def object_extend(
109109 return obj
110110
111111 def sort_objects (
112- self , objs : List [str ], args : Dict , locale : GrampsLocale = glocale
112+ self , objects : List [GrampsObject ], args : Dict , locale : GrampsLocale = glocale
113113 ) -> List :
114114 """Sort the list of objects as needed."""
115115 return sort_objects (
116- self .db_handle , self .gramps_class_name , objs , args , locale = locale
116+ self .db_handle , self .gramps_class_name , objects , args , locale = locale
117117 )
118118
119- def match_dates (self , handles : List [str ], date : str ):
119+ def match_dates (self , objects : List [GrampsObject ], date : str ) -> List [ GrampsObject ] :
120120 """If supported filter objects using date mask."""
121121 if self .gramps_class_name in ["Event" , "Media" , "Citation" ]:
122- return match_dates (self . db_handle , self . gramps_class_name , handles , date )
123- return handles
122+ return match_dates (objects , date )
123+ return objects
124124
125125 @property
126126 def db_handle (self ) -> DbReadBase :
@@ -387,41 +387,50 @@ def get(self, args: Dict) -> Response:
387387 200 , [self .full_object (obj , args , locale = locale )], args , total_items = 1
388388 )
389389
390+ # load all objects to memory
391+ objects_name = GRAMPS_OBJECT_PLURAL [self .gramps_class_name ]
392+ iter_objects_method = self .db_handle .method ("iter_%s" , objects_name )
393+ objects = list (iter_objects_method ())
394+
395+ # for all objects except events, repos, and notes, Gramps supports
396+ # a database-backed default sort order. Use that if no sort order
397+ # requested.
390398 query_method = self .db_handle .method ("get_%s_handles" , self .gramps_class_name )
391399 if self .gramps_class_name in ["Event" , "Repository" , "Note" ]:
392400 handles = query_method ()
393401 else :
394402 handles = query_method (sort_handles = True , locale = locale )
403+ handle_index = {handle : index for index , handle in enumerate (handles )}
404+ # sort objects by the sorted handle order
405+ objects = sorted (
406+ objects , key = lambda obj : handle_index .get (obj .handle , len (handles ) + 1 )
407+ )
395408
396409 if "filter" in args or "rules" in args :
410+ handles = [obj .handle for obj in objects ]
397411 handles = apply_filter (
398412 self .db_handle , args , self .gramps_class_name , handles
399413 )
414+ objects = [obj for obj in objects if obj .handle in set (handles )]
400415
401416 if self .gramps_class_name == "Media" and args .get ("filemissing" ):
402- handles = get_missing_media_file_handles ( self . db_handle , handles )
417+ objects = filter_missing_files ( objects )
403418
404419 if args ["dates" ]:
405- handles = self .match_dates (handles , args ["dates" ])
420+ objects = self .match_dates (objects , args ["dates" ])
406421
407422 if "sort" in args :
408- handles = self .sort_objects (handles , args ["sort" ], locale = locale )
423+ objects = self .sort_objects (objects , args ["sort" ], locale = locale )
409424
410- total_items = len (handles )
425+ total_items = len (objects )
411426
412427 if args ["page" ] > 0 :
413428 offset = (args ["page" ] - 1 ) * args ["pagesize" ]
414- handles = handles [offset : offset + args ["pagesize" ]]
429+ objects = objects [offset : offset + args ["pagesize" ]]
415430
416- query_method = self .db_handle .method (
417- "get_%s_from_handle" , self .gramps_class_name
418- )
419431 return self .response (
420432 200 ,
421- [
422- self .full_object (query_method (handle ), args , locale = locale )
423- for handle in handles
424- ],
433+ [self .full_object (obj , args , locale = locale ) for obj in objects ],
425434 args ,
426435 total_items = total_items ,
427436 )
@@ -439,7 +448,7 @@ def post(self) -> Response:
439448 with DbTxn ("Add objects" , db_handle ) as trans :
440449 try :
441450 add_object (db_handle , obj , trans , fail_if_exists = True )
442- except ValueError as exc :
451+ except ValueError :
443452 abort_with_message (400 , "Error while adding object" )
444453 trans_dict = transaction_to_json (trans )
445454 # update usage
0 commit comments