9744: Tidy up iterators

Remove order_by parameter.
Add unit tests.
This commit is contained in:
Nick Hall 2016-10-28 21:41:05 +01:00
parent 1905d417be
commit 9fc316abdf
9 changed files with 215 additions and 315 deletions

View File

@ -50,35 +50,6 @@ from .exceptions import DbTransactionCancel
_LOG = logging.getLogger(DBLOGNAME) _LOG = logging.getLogger(DBLOGNAME)
def eval_order_by(order_by, obj, db):
"""
Given a list of [[field, DIRECTION], ...]
return the list of values of the fields
"""
values = []
for (field, direction) in order_by:
values.append(obj.get_field(field, db, ignore_errors=True))
return values
def sort_objects(objects, order_by, db):
"""
Python-based sorting.
"""
# first build sort order:
sorted_items = []
map_items = {}
for obj in objects:
# just use values and handle to keep small:
sorted_items.append((eval_order_by(order_by, obj, db), obj.handle))
map_items[obj.handle] = obj
# next we sort by fields and direction
pos = len(order_by) - 1
for (field, order) in reversed(order_by): # sort the lasts parts first
sorted_items.sort(key=itemgetter(pos), reverse=(order=="DESC"))
pos -= 1
for (order_by_values, handle) in sorted_items:
yield map_items[handle]
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
# Gramps libraries # Gramps libraries
@ -953,7 +924,7 @@ class DbReadBase:
""" """
raise NotImplementedError raise NotImplementedError
def iter_citations(self, order_by=None): def iter_citations(self):
""" """
Return an iterator over objects for Citations in the database Return an iterator over objects for Citations in the database
""" """
@ -965,13 +936,13 @@ class DbReadBase:
""" """
raise NotImplementedError raise NotImplementedError
def iter_events(self, order_by=None): def iter_events(self):
""" """
Return an iterator over objects for Events in the database Return an iterator over objects for Events in the database
""" """
raise NotImplementedError raise NotImplementedError
def iter_families(self, order_by=None): def iter_families(self):
""" """
Return an iterator over objects for Families in the database Return an iterator over objects for Families in the database
""" """
@ -989,7 +960,7 @@ class DbReadBase:
""" """
raise NotImplementedError raise NotImplementedError
def iter_media(self, order_by=None): def iter_media(self):
""" """
Return an iterator over objects for Medias in the database Return an iterator over objects for Medias in the database
""" """
@ -1001,13 +972,13 @@ class DbReadBase:
""" """
raise NotImplementedError raise NotImplementedError
def iter_notes(self, order_by=None): def iter_notes(self):
""" """
Return an iterator over objects for Notes in the database Return an iterator over objects for Notes in the database
""" """
raise NotImplementedError raise NotImplementedError
def iter_people(self, order_by=None): def iter_people(self):
""" """
Return an iterator over objects for Persons in the database Return an iterator over objects for Persons in the database
""" """
@ -1025,13 +996,13 @@ class DbReadBase:
""" """
raise NotImplementedError raise NotImplementedError
def iter_places(self, order_by=None): def iter_places(self):
""" """
Return an iterator over objects for Places in the database Return an iterator over objects for Places in the database
""" """
raise NotImplementedError raise NotImplementedError
def iter_repositories(self, order_by=None): def iter_repositories(self):
""" """
Return an iterator over objects for Repositories in the database Return an iterator over objects for Repositories in the database
""" """
@ -1049,7 +1020,7 @@ class DbReadBase:
""" """
raise NotImplementedError raise NotImplementedError
def iter_sources(self, order_by=None): def iter_sources(self):
""" """
Return an iterator over objects for Sources in the database Return an iterator over objects for Sources in the database
""" """
@ -1061,7 +1032,7 @@ class DbReadBase:
""" """
raise NotImplementedError raise NotImplementedError
def iter_tags(self, order_by=None): def iter_tags(self):
""" """
Return an iterator over objects for Tags in the database Return an iterator over objects for Tags in the database
""" """

View File

@ -51,8 +51,7 @@ from gramps.gen.db import (DbReadBase, DbWriteBase, DbTxn, DbUndo,
CLASS_TO_KEY_MAP, TXNADD, TXNUPD, TXNDEL, CLASS_TO_KEY_MAP, TXNADD, TXNUPD, TXNDEL,
PERSON_KEY, FAMILY_KEY, CITATION_KEY, PERSON_KEY, FAMILY_KEY, CITATION_KEY,
SOURCE_KEY, EVENT_KEY, MEDIA_KEY, SOURCE_KEY, EVENT_KEY, MEDIA_KEY,
PLACE_KEY, REPOSITORY_KEY, NOTE_KEY, PLACE_KEY, REPOSITORY_KEY, NOTE_KEY, TAG_KEY)
TAG_KEY, eval_order_by)
from gramps.gen.errors import HandleError from gramps.gen.errors import HandleError
from gramps.gen.utils.callback import Callback from gramps.gen.utils.callback import Callback
from gramps.gen.updatecallback import UpdateCallback from gramps.gen.updatecallback import UpdateCallback
@ -1217,47 +1216,43 @@ class DbGeneric(DbWriteBase, DbReadBase, UpdateCallback, Callback):
else: else:
return None return None
def iter_items(self, order_by, class_): def _iter_objects(self, class_):
""" """
Iterate over items in a class, possibly ordered by Iterate over items in a class.
a list of field names and direction ("ASC" or "DESC").
""" """
cursor = self.get_table_func(class_.__name__,"cursor_func") cursor = self.get_table_func(class_.__name__,"cursor_func")
if order_by is None: for data in cursor():
for data in cursor(): yield class_.create(data[1])
yield class_.create(data[1])
else:
# first build sort order:
sorted_items = []
for data in cursor():
obj = class_.create(data[1])
# just use values and handle to keep small:
sorted_items.append((eval_order_by(order_by, obj, self), obj.handle))
# next we sort by fields and direction
def getitem(item, pos):
sort_items = item[0]
if isinstance(sort_items[pos], str):
return sort_items[pos]
elif sort_items[pos] is None:
return ""
else:
# FIXME: should do something clever/recurive to
# sort these meaningfully, and return a string:
return str(sort_items[pos])
pos = len(order_by) - 1
for (field, order) in reversed(order_by): # sort the lasts parts first
sorted_items.sort(key=lambda item: getitem(item, pos),
reverse=(order=="DESC"))
pos -= 1
# now we will look them up again:
for (order_by_values, handle) in sorted_items:
yield self.get_table_func(class_.__name__,"handle_func")(handle)
def iter_people(self, order_by=None): def iter_people(self):
return self.iter_items(order_by, Person) return self._iter_objects(Person)
def iter_families(self, order_by=None): def iter_families(self):
return self.iter_items(order_by, Family) return self._iter_objects(Family)
def iter_citations(self):
return self._iter_objects(Citation)
def iter_events(self):
return self._iter_objects(Event)
def iter_media(self):
return self._iter_objects(Media)
def iter_notes(self):
return self._iter_objects(Note)
def iter_places(self):
return self._iter_objects(Place)
def iter_repositories(self):
return self._iter_objects(Repository)
def iter_sources(self):
return self._iter_objects(Source)
def iter_tags(self):
return self._iter_objects(Tag)
def get_person_from_gramps_id(self, gramps_id): def get_person_from_gramps_id(self, gramps_id):
data = self._get_raw_person_from_id_data(gramps_id) data = self._get_raw_person_from_id_data(gramps_id)
@ -1838,30 +1833,6 @@ class DbGeneric(DbWriteBase, DbReadBase, UpdateCallback, Callback):
def is_open(self): def is_open(self):
return self.db_is_open return self.db_is_open
def iter_citations(self, order_by=None):
return self.iter_items(order_by, Citation)
def iter_events(self, order_by=None):
return self.iter_items(order_by, Event)
def iter_media(self, order_by=None):
return self.iter_items(order_by, Media)
def iter_notes(self, order_by=None):
return self.iter_items(order_by, Note)
def iter_places(self, order_by=None):
return self.iter_items(order_by, Place)
def iter_repositories(self, order_by=None):
return self.iter_items(order_by, Repository)
def iter_sources(self, order_by=None):
return self.iter_items(order_by, Source)
def iter_tags(self, order_by=None):
return self.iter_items(order_by, Tag)
def set_prefixes(self, person, media, family, source, citation, def set_prefixes(self, person, media, family, source, citation,
place, event, repository, note): place, event, repository, note):
self.set_person_id_prefix(person) self.set_person_id_prefix(person)

View File

@ -30,7 +30,6 @@ Proxy class for the Gramps databases. Apply filter
# Gramps libraries # Gramps libraries
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
from gramps.gen.db.base import sort_objects
from .proxybase import ProxyDbBase from .proxybase import ProxyDbBase
from ..lib import (Date, Person, Name, Surname, NameOriginType, Family, Source, from ..lib import (Date, Person, Name, Surname, NameOriginType, Family, Source,
Citation, Event, Media, Place, Repository, Note, Tag) Citation, Event, Media, Place, Repository, Note, Tag)
@ -516,14 +515,11 @@ class FilterProxyDb(ProxyDbBase):
""" """
return self.plist return self.plist
def iter_people(self, order_by=None): def iter_people(self):
""" """
Return an iterator over objects for Persons in the database Return an iterator over objects for Persons in the database
""" """
if order_by: return map(self.get_person_from_handle, self.plist)
return sort_objects(map(self.get_person_from_handle, self.plist), order_by, self)
else:
return map(self.get_person_from_handle, self.plist)
def get_event_handles(self): def get_event_handles(self):
""" """
@ -539,14 +535,11 @@ class FilterProxyDb(ProxyDbBase):
""" """
return self.elist return self.elist
def iter_events(self, order_by=None): def iter_events(self):
""" """
Return an iterator over objects for Events in the database Return an iterator over objects for Events in the database
""" """
if order_by: return map(self.get_event_from_handle, self.elist)
return sort_objects(map(self.get_event_from_handle, self.elist), order_by, self)
else:
return map(self.get_event_from_handle, self.elist)
def get_family_handles(self, sort_handles=False): def get_family_handles(self, sort_handles=False):
""" """
@ -563,14 +556,11 @@ class FilterProxyDb(ProxyDbBase):
""" """
return self.flist return self.flist
def iter_families(self, order_by=None): def iter_families(self):
""" """
Return an iterator over objects for Families in the database Return an iterator over objects for Families in the database
""" """
if order_by: return map(self.get_family_from_handle, self.flist)
return sort_objects(map(self.get_family_from_handle, self.flist), order_by, self)
else:
return map(self.get_family_from_handle, self.flist)
def get_note_handles(self): def get_note_handles(self):
""" """
@ -586,14 +576,11 @@ class FilterProxyDb(ProxyDbBase):
""" """
return self.nlist return self.nlist
def iter_notes(self, order_by=None): def iter_notes(self):
""" """
Return an iterator over objects for Notes in the database Return an iterator over objects for Notes in the database
""" """
if order_by: return map(self.get_note_from_handle, self.nlist)
return sort_objects(map(self.get_note_from_handle, self.nlist), order_by, self)
else:
return map(self.get_note_from_handle, self.nlist)
def get_default_person(self): def get_default_person(self):
"""returns the default Person of the database""" """returns the default Person of the database"""

View File

@ -33,7 +33,6 @@ from ..lib import (Date, Person, Name, Surname, NameOriginType, Family, Source,
Citation, Event, Media, Place, Repository, Note, Tag) Citation, Event, Media, Place, Repository, Note, Tag)
from ..utils.alive import probably_alive from ..utils.alive import probably_alive
from ..config import config from ..config import config
from gramps.gen.db.base import sort_objects
from gramps.gen.const import GRAMPS_LOCALE as glocale from gramps.gen.const import GRAMPS_LOCALE as glocale
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
@ -234,32 +233,18 @@ class LivingProxyDb(ProxyDbBase):
family = self.__remove_living_from_family(family) family = self.__remove_living_from_family(family)
return family return family
def iter_people(self, order_by=None): def iter_people(self):
""" """
Protected version of iter_people Protected version of iter_people
""" """
if order_by: for person in filter(None, self.db.iter_people()):
retval = [] if self.__is_living(person):
for person in filter(None, self.db.iter_people()): if self.mode == self.MODE_EXCLUDE_ALL:
if self.__is_living(person): continue
if self.mode == self.MODE_EXCLUDE_ALL:
continue
else:
retval.append(self.__restrict_person(person))
else: else:
retval.append(person) yield self.__restrict_person(person)
retval = sort_objects(retval, order_by, self) else:
for item in retval: yield person
yield item
else:
for person in filter(None, self.db.iter_people()):
if self.__is_living(person):
if self.mode == self.MODE_EXCLUDE_ALL:
continue
else:
yield self.__restrict_person(person)
else:
yield person
def get_person_from_gramps_id(self, val): def get_person_from_gramps_id(self, val):
""" """

View File

@ -35,7 +35,7 @@ import types
# Gramps libraries # Gramps libraries
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
from ..db.base import DbReadBase, DbWriteBase, sort_objects from ..db.base import DbReadBase, DbWriteBase
from ..lib import (Citation, Event, Family, Media, Note, Person, Place, from ..lib import (Citation, Event, Family, Media, Note, Person, Place,
Repository, Source, Tag) Repository, Source, Tag)
@ -498,85 +498,82 @@ class ProxyDbBase(DbReadBase):
""" """
return filter(self.include_tag, self.db.iter_tag_handles()) return filter(self.include_tag, self.db.iter_tag_handles())
def __iter_object(self, selector, method, order_by=None): def __iter_object(self, selector, method):
""" Helper function to return an iterator over an object class """ """ Helper function to return an iterator over an object class """
retval = filter(lambda obj: retval = filter(lambda obj:
((selector is None) or selector(obj.handle)), ((selector is None) or selector(obj.handle)),
method()) method())
if order_by: return retval
return sort_objects([item for item in retval], order_by, self)
else:
return retval
def iter_people(self, order_by=None): def iter_people(self):
""" """
Return an iterator over Person objects in the database Return an iterator over Person objects in the database
""" """
return self.__iter_object(self.include_person, return self.__iter_object(self.include_person,
self.db.iter_people, order_by) self.db.iter_people)
def iter_families(self, order_by=None): def iter_families(self):
""" """
Return an iterator over Family objects in the database Return an iterator over Family objects in the database
""" """
return self.__iter_object(self.include_family, return self.__iter_object(self.include_family,
self.db.iter_families, order_by) self.db.iter_families)
def iter_events(self, order_by=None): def iter_events(self):
""" """
Return an iterator over Event objects in the database Return an iterator over Event objects in the database
""" """
return self.__iter_object(self.include_event, return self.__iter_object(self.include_event,
self.db.iter_events, order_by) self.db.iter_events)
def iter_places(self, order_by=None): def iter_places(self):
""" """
Return an iterator over Place objects in the database Return an iterator over Place objects in the database
""" """
return self.__iter_object(self.include_place, return self.__iter_object(self.include_place,
self.db.iter_places, order_by) self.db.iter_places)
def iter_sources(self, order_by=None): def iter_sources(self):
""" """
Return an iterator over Source objects in the database Return an iterator over Source objects in the database
""" """
return self.__iter_object(self.include_source, return self.__iter_object(self.include_source,
self.db.iter_sources, order_by) self.db.iter_sources)
def iter_citations(self, order_by=None): def iter_citations(self):
""" """
Return an iterator over Citation objects in the database Return an iterator over Citation objects in the database
""" """
return self.__iter_object(self.include_citation, return self.__iter_object(self.include_citation,
self.db.iter_citations, order_by) self.db.iter_citations)
def iter_media(self, order_by=None): def iter_media(self):
""" """
Return an iterator over Media objects in the database Return an iterator over Media objects in the database
""" """
return self.__iter_object(self.include_media, return self.__iter_object(self.include_media,
self.db.iter_media, order_by) self.db.iter_media)
def iter_repositories(self, order_by=None): def iter_repositories(self):
""" """
Return an iterator over Repositories objects in the database Return an iterator over Repositories objects in the database
""" """
return self.__iter_object(self.include_repository, return self.__iter_object(self.include_repository,
self.db.iter_repositories, order_by) self.db.iter_repositories)
def iter_notes(self, order_by=None): def iter_notes(self):
""" """
Return an iterator over Note objects in the database Return an iterator over Note objects in the database
""" """
return self.__iter_object(self.include_note, return self.__iter_object(self.include_note,
self.db.iter_notes, order_by) self.db.iter_notes)
def iter_tags(self, order_by=None): def iter_tags(self):
""" """
Return an iterator over Tag objects in the database Return an iterator over Tag objects in the database
""" """
return self.__iter_object(self.include_tag, return self.__iter_object(self.include_tag,
self.db.iter_tags, order_by) self.db.iter_tags)
@staticmethod @staticmethod
def gfilter(predicate, obj): def gfilter(predicate, obj):

View File

@ -71,7 +71,7 @@ from gramps.gen.lib.nameorigintype import NameOriginType
from gramps.gen.utils.callback import Callback from gramps.gen.utils.callback import Callback
from . import BsddbBaseCursor from . import BsddbBaseCursor
from gramps.gen.db.base import DbReadBase, eval_order_by from gramps.gen.db.base import DbReadBase
from gramps.gen.utils.id import create_id from gramps.gen.utils.id import create_id
from gramps.gen.errors import DbError, HandleError from gramps.gen.errors import DbError, HandleError
from gramps.gen.constfunc import get_env_var from gramps.gen.constfunc import get_env_var
@ -1260,34 +1260,12 @@ class DbBsddbRead(DbReadBase, Callback):
""" """
Closure that returns an iterator over objects in the database. Closure that returns an iterator over objects in the database.
""" """
def g(self, order_by=None): def g(self):
""" with curs_(self) as cursor:
order_by - [[field, DIRECTION], ...] for key, data in cursor:
DIRECTION is "ASC" or "DESC" obj = obj_()
""" obj.unserialize(data)
if order_by is None: yield obj
with curs_(self) as cursor:
for key, data in cursor:
obj = obj_()
obj.unserialize(data)
yield obj
else:
# first build sort order:
sorted_items = []
with curs_(self) as cursor:
for key, data in cursor:
obj = obj_()
obj.unserialize(data)
# just use values and handle to keep small:
sorted_items.append((eval_order_by(order_by, obj, self), obj.handle))
# next we sort by fields and direction
pos = len(order_by) - 1
for (field, order) in reversed(order_by): # sort the lasts parts first
sorted_items.sort(key=itemgetter(pos), reverse=(order=="DESC"))
pos -= 1
# now we will look them up again:
for (order_by_values, handle) in sorted_items:
yield self.get_table_func(obj_.__name__,"handle_func")(handle)
return g return g
# Use closure to define iterators for each primary object type # Use closure to define iterators for each primary object type

View File

@ -37,7 +37,6 @@ import logging
# Gramps Modules # Gramps Modules
# #
#------------------------------------------------------------------------ #------------------------------------------------------------------------
from gramps.gen.db.base import eval_order_by
from gramps.gen.db.dbconst import (DBLOGNAME, DBBACKEND, KEY_TO_NAME_MAP, from gramps.gen.db.dbconst import (DBLOGNAME, DBBACKEND, KEY_TO_NAME_MAP,
TXNADD, TXNUPD, TXNDEL, TXNADD, TXNUPD, TXNDEL,
PERSON_KEY, FAMILY_KEY, SOURCE_KEY, PERSON_KEY, FAMILY_KEY, SOURCE_KEY,
@ -1014,152 +1013,77 @@ class DBAPI(DbGeneric):
if row: if row:
return self.get_person_from_handle(row[0]) return self.get_person_from_handle(row[0])
def iter_items_order_by_python(self, order_by, class_): def _iter_handles(self, obj_key):
""" """
This method is for those iter_items with a order_by, but Return an iterator over handles in the database
can't be done with secondary fields.
""" """
# first build sort order: table = KEY_TO_NAME_MAP[obj_key]
sorted_items = [] sql = "SELECT handle FROM %s" % table
query = "SELECT blob_data FROM %s;" % class_.__name__.lower() self.dbapi.execute(sql)
self.dbapi.execute(query)
rows = self.dbapi.fetchall() rows = self.dbapi.fetchall()
for row in rows: for row in rows:
obj = self.get_table_func(class_.__name__, yield row[0]
"class_func").create(pickle.loads(row[0]))
# just use values and handle to keep small:
sorted_items.append((eval_order_by(order_by, obj, self),
obj.handle))
# next we sort by fields and direction
pos = len(order_by) - 1
for (field, order) in reversed(order_by): # sort the lasts parts first
sorted_items.sort(key=itemgetter(pos), reverse=(order == "DESC"))
pos -= 1
# now we will look them up again:
for (order_by_values, handle) in sorted_items:
yield self.get_table_func(class_.__name__, "handle_func")(handle)
def iter_items(self, order_by, class_):
"""
Iterate over items in a class, possibly ordered by
a list of field names and direction ("ASC" or "DESC").
"""
# check if order_by fields are secondary
# if so, fine
# else, use Python sorts
if order_by:
secondary_fields = class_.get_secondary_fields()
if not self._check_order_by_fields(class_.__name__,
order_by, secondary_fields):
for item in self.iter_items_order_by_python(order_by, class_):
yield item
return
## Continue with dbapi select
if order_by is None:
query = "SELECT blob_data FROM %s;" % class_.__name__.lower()
else:
order_phrases = [
"%s %s" % (self._hash_name(class_.__name__,
class_.get_field_alias(field)),
direction)
for (field, direction) in order_by]
query = "SELECT blob_data FROM %s ORDER BY %s;" % (
class_.__name__.lower(), ", ".join(order_phrases))
self.dbapi.execute(query)
rows = self.dbapi.fetchall()
for row in rows:
yield class_.create(pickle.loads(row[0]))
def iter_person_handles(self): def iter_person_handles(self):
""" """
Return an iterator over handles for Persons in the database Return an iterator over handles for Persons in the database
""" """
self.dbapi.execute("SELECT handle FROM person;") return self._iter_handles(PERSON_KEY)
rows = self.dbapi.fetchall()
for row in rows:
yield row[0]
def iter_family_handles(self): def iter_family_handles(self):
""" """
Return an iterator over handles for Families in the database Return an iterator over handles for Families in the database
""" """
self.dbapi.execute("SELECT handle FROM family;") return self._iter_handles(FAMILY_KEY)
rows = self.dbapi.fetchall()
for row in rows:
yield row[0]
def iter_citation_handles(self): def iter_citation_handles(self):
""" """
Return an iterator over database handles, one handle for each Citation Return an iterator over database handles, one handle for each Citation
in the database. in the database.
""" """
self.dbapi.execute("SELECT handle FROM citation;") return self._iter_handles(CITATION_KEY)
rows = self.dbapi.fetchall()
for row in rows:
yield row[0]
def iter_event_handles(self): def iter_event_handles(self):
""" """
Return an iterator over handles for Events in the database Return an iterator over handles for Events in the database
""" """
self.dbapi.execute("SELECT handle FROM event;") return self._iter_handles(EVENT_KEY)
rows = self.dbapi.fetchall()
for row in rows:
yield row[0]
def iter_media_handles(self): def iter_media_handles(self):
""" """
Return an iterator over handles for Media in the database Return an iterator over handles for Media in the database
""" """
self.dbapi.execute("SELECT handle FROM media;") return self._iter_handles(MEDIA_KEY)
rows = self.dbapi.fetchall()
for row in rows:
yield row[0]
def iter_note_handles(self): def iter_note_handles(self):
""" """
Return an iterator over handles for Notes in the database Return an iterator over handles for Notes in the database
""" """
self.dbapi.execute("SELECT handle FROM note;") return self._iter_handles(NOTE_KEY)
rows = self.dbapi.fetchall()
for row in rows:
yield row[0]
def iter_place_handles(self): def iter_place_handles(self):
""" """
Return an iterator over handles for Places in the database Return an iterator over handles for Places in the database
""" """
self.dbapi.execute("SELECT handle FROM place;") return self._iter_handles(PLACE_KEY)
rows = self.dbapi.fetchall()
for row in rows:
yield row[0]
def iter_repository_handles(self): def iter_repository_handles(self):
""" """
Return an iterator over handles for Repositories in the database Return an iterator over handles for Repositories in the database
""" """
self.dbapi.execute("SELECT handle FROM repository;") return self._iter_handles(REPOSITORY_KEY)
rows = self.dbapi.fetchall()
for row in rows:
yield row[0]
def iter_source_handles(self): def iter_source_handles(self):
""" """
Return an iterator over handles for Sources in the database Return an iterator over handles for Sources in the database
""" """
self.dbapi.execute("SELECT handle FROM source;") return self._iter_handles(SOURCE_KEY)
rows = self.dbapi.fetchall()
for row in rows:
yield row[0]
def iter_tag_handles(self): def iter_tag_handles(self):
""" """
Return an iterator over handles for Tags in the database Return an iterator over handles for Tags in the database
""" """
self.dbapi.execute("SELECT handle FROM tag;") return self._iter_handles(TAG_KEY)
rows = self.dbapi.fetchall()
for row in rows:
yield row[0]
def _iter_raw_data(self, obj_key): def _iter_raw_data(self, obj_key):
""" """
@ -1725,19 +1649,6 @@ class DBAPI(DbGeneric):
else: else:
return repr(value) return repr(value)
def _check_order_by_fields(self, table, order_by, secondary_fields):
"""
Check to make sure all order_by fields are defined. If not, then
we need to do the Python-based order.
secondary_fields are hashed.
"""
if order_by:
for (field, directory) in order_by:
if self._hash_name(table, field) not in secondary_fields:
return False
return True
def get_summary(self): def get_summary(self):
""" """
Returns dictionary of summary item. Returns dictionary of summary item.

View File

@ -506,6 +506,106 @@ class DbTest(unittest.TestCase):
self.__get_cursor_test(self.db.get_tag_cursor, self.__get_cursor_test(self.db.get_tag_cursor,
self.db.get_raw_tag_data) self.db.get_raw_tag_data)
################################################################
#
# Test iter_*_handles methods
#
################################################################
def __iter_handles_test(self, obj_type, iter_func):
for handle in iter_func():
self.assertIn(handle, self.handles[obj_type])
def test_iter_person_handles(self):
self.__iter_handles_test('Person',
self.db.iter_person_handles)
def test_iter_family_handles(self):
self.__iter_handles_test('Family',
self.db.iter_family_handles)
def test_iter_event_handles(self):
self.__iter_handles_test('Event',
self.db.iter_event_handles)
def test_iter_place_handles(self):
self.__iter_handles_test('Place',
self.db.iter_place_handles)
def test_iter_repository_handles(self):
self.__iter_handles_test('Repository',
self.db.iter_repository_handles)
def test_iter_source_handles(self):
self.__iter_handles_test('Source',
self.db.iter_source_handles)
def test_iter_citation_handles(self):
self.__iter_handles_test('Citation',
self.db.iter_citation_handles)
def test_iter_media_handles(self):
self.__iter_handles_test('Media',
self.db.iter_media_handles)
def test_iter_note_handles(self):
self.__iter_handles_test('Note',
self.db.iter_note_handles)
def test_iter_tag_handles(self):
self.__iter_handles_test('Tag',
self.db.iter_tag_handles)
################################################################
#
# Test iter_* methods
#
################################################################
def __iter_objects_test(self, obj_class, iter_func):
for obj in iter_func():
self.assertIsInstance(obj, obj_class)
def test_iter_people(self):
self.__iter_objects_test(Person,
self.db.iter_people)
def test_iter_families(self):
self.__iter_objects_test(Family,
self.db.iter_families)
def test_iter_events(self):
self.__iter_objects_test(Event,
self.db.iter_events)
def test_iter_places(self):
self.__iter_objects_test(Place,
self.db.iter_places)
def test_iter_repositories(self):
self.__iter_objects_test(Repository,
self.db.iter_repositories)
def test_iter_sources(self):
self.__iter_objects_test(Source,
self.db.iter_sources)
def test_iter_citations(self):
self.__iter_objects_test(Citation,
self.db.iter_citations)
def test_iter_media(self):
self.__iter_objects_test(Media,
self.db.iter_media)
def test_iter_notes(self):
self.__iter_objects_test(Note,
self.db.iter_notes)
def test_iter_tags(self):
self.__iter_objects_test(Tag,
self.db.iter_tags)
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()

View File

@ -1341,7 +1341,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
""" """
return self.db_is_open return self.db_is_open
def iter_citations(self, order_by=None): def iter_citations(self):
""" """
Return an iterator over objects for Citations in the database Return an iterator over objects for Citations in the database
""" """
@ -1357,7 +1357,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
LOG.warning("database is closed") LOG.warning("database is closed")
return [] return []
def iter_events(self, order_by=None): def iter_events(self):
""" """
Return an iterator over objects for Events in the database Return an iterator over objects for Events in the database
""" """
@ -1365,7 +1365,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
LOG.warning("database is closed") LOG.warning("database is closed")
return [] return []
def iter_families(self, order_by=None): def iter_families(self):
""" """
Return an iterator over objects for Families in the database Return an iterator over objects for Families in the database
""" """
@ -1389,7 +1389,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
LOG.warning("database is closed") LOG.warning("database is closed")
return [] return []
def iter_media(self, order_by=None): def iter_media(self):
""" """
Return an iterator over objects for Medias in the database Return an iterator over objects for Medias in the database
""" """
@ -1405,7 +1405,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
LOG.warning("database is closed") LOG.warning("database is closed")
return [] return []
def iter_notes(self, order_by=None): def iter_notes(self):
""" """
Return an iterator over objects for Notes in the database Return an iterator over objects for Notes in the database
""" """
@ -1413,7 +1413,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
LOG.warning("database is closed") LOG.warning("database is closed")
return [] return []
def iter_people(self, order_by=None): def iter_people(self):
""" """
Return an iterator over objects for Persons in the database Return an iterator over objects for Persons in the database
""" """
@ -1437,7 +1437,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
LOG.warning("database is closed") LOG.warning("database is closed")
return [] return []
def iter_places(self, order_by=None): def iter_places(self):
""" """
Return an iterator over objects for Places in the database Return an iterator over objects for Places in the database
""" """
@ -1445,7 +1445,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
LOG.warning("database is closed") LOG.warning("database is closed")
return [] return []
def iter_repositories(self, order_by=None): def iter_repositories(self):
""" """
Return an iterator over objects for Repositories in the database Return an iterator over objects for Repositories in the database
""" """
@ -1469,7 +1469,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
LOG.warning("database is closed") LOG.warning("database is closed")
return [] return []
def iter_sources(self, order_by=None): def iter_sources(self):
""" """
Return an iterator over objects for Sources in the database Return an iterator over objects for Sources in the database
""" """
@ -1485,7 +1485,7 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
LOG.warning("database is closed") LOG.warning("database is closed")
return [] return []
def iter_tags(self, order_by=None): def iter_tags(self):
""" """
Return an iterator over objects for Tags in the database Return an iterator over objects for Tags in the database
""" """