1. Enhance cursor.py to support updating records after reading them
2. Implement enhancement in write.py, get_cursor method 3. Exploit new capability in ChangeNames.py svn: r13237
This commit is contained in:
parent
dd10d9bfdb
commit
9b586eaf4f
@ -23,7 +23,8 @@
|
|||||||
# Standard python modules
|
# Standard python modules
|
||||||
#
|
#
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
import cPickle as pickle
|
from cPickle import dumps, loads
|
||||||
|
from bsddb import db
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
@ -44,12 +45,15 @@ class GrampsCursor(object):
|
|||||||
should be used.
|
should be used.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, txn=None, update=False, commit=False):
|
||||||
"""
|
"""
|
||||||
Instantiate the object. Note, this method should be overridden in
|
Instantiate the object. Note, this method should be overridden in
|
||||||
derived classes that properly set self.cursor and self.source
|
derived classes that properly set self.cursor and self.source
|
||||||
"""
|
"""
|
||||||
self.cursor = self.source = None
|
self.cursor = self.source = None
|
||||||
|
self.txn = txn
|
||||||
|
self._update = update
|
||||||
|
self.commit = commit
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
"""
|
"""
|
||||||
@ -68,6 +72,8 @@ class GrampsCursor(object):
|
|||||||
Context manager exit method
|
Context manager exit method
|
||||||
"""
|
"""
|
||||||
self.close()
|
self.close()
|
||||||
|
if self.txn and self.commit:
|
||||||
|
self.txn.commit()
|
||||||
return exc_type is None
|
return exc_type is None
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
@ -76,74 +82,38 @@ class GrampsCursor(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
data = self.first()
|
data = self.first()
|
||||||
|
_n = self.next # Saved attribute lookup in the loop
|
||||||
while data:
|
while data:
|
||||||
yield data
|
yield data
|
||||||
data = self.next()
|
data = _n()
|
||||||
|
|
||||||
def first(self, *args, **kwargs):
|
def _get(_flags=0):
|
||||||
|
""" Closure that returns a cursor get function """
|
||||||
|
|
||||||
|
def get(self, flags=0, **kwargs):
|
||||||
|
"""
|
||||||
|
Issue DBCursor get call (with DB_RMW flag if update requested)
|
||||||
|
Return results to caller
|
||||||
|
"""
|
||||||
|
data = self.cursor.get(
|
||||||
|
_flags | flags | (db.DB_RMW if self._update else 0),
|
||||||
|
**kwargs)
|
||||||
|
|
||||||
|
return (data[0], loads(data[1])) if data else None
|
||||||
|
|
||||||
|
return get
|
||||||
|
|
||||||
|
# Use closure to define access methods
|
||||||
|
|
||||||
|
current = _get(db.DB_CURRENT)
|
||||||
|
first = _get(db.DB_FIRST)
|
||||||
|
next = _get(db.DB_NEXT)
|
||||||
|
last = _get(db.DB_LAST)
|
||||||
|
prev = _get(db.DB_PREV)
|
||||||
|
|
||||||
|
def update(self, key, data, flags=0, **kwargs):
|
||||||
"""
|
"""
|
||||||
Return the first (index, data) pair in the database.
|
Write the current key, data pair to the database.
|
||||||
|
|
||||||
This should be called before the first call to next(). Note that the
|
|
||||||
data return is in the format of the serialized format stored in the
|
|
||||||
database, not in the more usable class object. The data should be
|
|
||||||
converted to a class using the class's unserialize method.
|
|
||||||
|
|
||||||
If no data is available, None is returned.
|
|
||||||
"""
|
"""
|
||||||
|
self.cursor.put(key, dumps(data), flags=flags | db.DB_CURRENT,
|
||||||
data = self.cursor.first(*args, **kwargs)
|
**kwargs)
|
||||||
if data:
|
|
||||||
return (data[0], pickle.loads(data[1]))
|
|
||||||
return None
|
|
||||||
|
|
||||||
def next(self, *args, **kwargs):
|
|
||||||
"""
|
|
||||||
Return the next (index, data) pair in the database.
|
|
||||||
|
|
||||||
Like the first() method, the data return is in the format of the
|
|
||||||
serialized format stored in the database, not in the more usable class
|
|
||||||
object. The data should be converted to a class using the class's
|
|
||||||
unserialize method.
|
|
||||||
|
|
||||||
None is returned when no more data is available.
|
|
||||||
"""
|
|
||||||
|
|
||||||
data = self.cursor.next(*args, **kwargs)
|
|
||||||
if data:
|
|
||||||
return (data[0], pickle.loads(data[1]))
|
|
||||||
return None
|
|
||||||
|
|
||||||
def prev(self, *args, **kwargs):
|
|
||||||
"""
|
|
||||||
Return the previous (index, data) pair in the database.
|
|
||||||
|
|
||||||
Like the first() method, the data return is in the format of the
|
|
||||||
serialized format stored in the database, not in the more usable class
|
|
||||||
object. The data should be converted to a class using the class's
|
|
||||||
unserialize method.
|
|
||||||
|
|
||||||
If no data is available, None is returned.
|
|
||||||
"""
|
|
||||||
|
|
||||||
data = self.cursor.prev(*args, **kwargs)
|
|
||||||
if data:
|
|
||||||
return (data[0], pickle.loads(data[1]))
|
|
||||||
return None
|
|
||||||
|
|
||||||
def last(self, *args, **kwargs):
|
|
||||||
"""
|
|
||||||
Return the last (index, data) pair in the database.
|
|
||||||
|
|
||||||
Like the first() method, the data return is in the format of the
|
|
||||||
serialized format stored in the database, not in the more usable class
|
|
||||||
object. The data should be converted to a class using the class's
|
|
||||||
unserialize method.
|
|
||||||
|
|
||||||
None is returned when no more data is available.
|
|
||||||
"""
|
|
||||||
|
|
||||||
data = self.cursor.last(*args, **kwargs)
|
|
||||||
if data:
|
|
||||||
return (data[0], pickle.loads(data[1]))
|
|
||||||
return None
|
|
||||||
|
@ -99,7 +99,8 @@ class GrampsDbBookmarks(object):
|
|||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
class GrampsDbReadCursor(GrampsCursor):
|
class GrampsDbReadCursor(GrampsCursor):
|
||||||
|
|
||||||
def __init__(self, source, txn=None):
|
def __init__(self, source, txn=None, **kwargs):
|
||||||
|
GrampsCursor.__init__(self, txn=txn, **kwargs)
|
||||||
self.cursor = source.db.cursor(txn)
|
self.cursor = source.db.cursor(txn)
|
||||||
self.source = source
|
self.source = source
|
||||||
|
|
||||||
@ -280,36 +281,36 @@ class GrampsDbRead(GrampsDbBase, Callback):
|
|||||||
"""Return True when the file has a supported version."""
|
"""Return True when the file has a supported version."""
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def __get_cursor(self, table):
|
def get_cursor(self, table, *args, **kwargs):
|
||||||
try:
|
try:
|
||||||
return GrampsDbReadCursor(table, self.txn)
|
return GrampsDbReadCursor(table, self.txn)
|
||||||
except DBERRS, msg:
|
except DBERRS, msg:
|
||||||
self.__log_error()
|
self.__log_error()
|
||||||
raise Errors.DbError(msg)
|
raise Errors.DbError(msg)
|
||||||
|
|
||||||
def get_person_cursor(self):
|
def get_person_cursor(self, *args, **kwargs):
|
||||||
return self.__get_cursor(self.person_map)
|
return self.get_cursor(self.person_map, *args, **kwargs)
|
||||||
|
|
||||||
def get_family_cursor(self):
|
def get_family_cursor(self, *args, **kwargs):
|
||||||
return self.__get_cursor(self.family_map)
|
return self.get_cursor(self.family_map, *args, **kwargs)
|
||||||
|
|
||||||
def get_event_cursor(self):
|
def get_event_cursor(self, *args, **kwargs):
|
||||||
return self.__get_cursor(self.event_map)
|
return self.get_cursor(self.event_map, *args, **kwargs)
|
||||||
|
|
||||||
def get_place_cursor(self):
|
def get_place_cursor(self, *args, **kwargs):
|
||||||
return self.__get_cursor(self.place_map)
|
return self.get_cursor(self.place_map, *args, **kwargs)
|
||||||
|
|
||||||
def get_source_cursor(self):
|
def get_source_cursor(self, *args, **kwargs):
|
||||||
return self.__get_cursor(self.source_map)
|
return self.get_cursor(self.source_map, *args, **kwargs)
|
||||||
|
|
||||||
def get_media_cursor(self):
|
def get_media_cursor(self, *args, **kwargs):
|
||||||
return self.__get_cursor(self.media_map)
|
return self.get_cursor(self.media_map, *args, **kwargs)
|
||||||
|
|
||||||
def get_repository_cursor(self):
|
def get_repository_cursor(self, *args, **kwargs):
|
||||||
return self.__get_cursor(self.repository_map)
|
return self.get_cursor(self.repository_map, *args, **kwargs)
|
||||||
|
|
||||||
def get_note_cursor(self):
|
def get_note_cursor(self, *args, **kwargs):
|
||||||
return self.__get_cursor(self.note_map)
|
return self.get_cursor(self.note_map, *args, **kwargs)
|
||||||
|
|
||||||
def load(self, name, callback, mode=DBMODE_R):
|
def load(self, name, callback, mode=DBMODE_R):
|
||||||
"""
|
"""
|
||||||
|
@ -142,12 +142,13 @@ def find_referenced_handle(key, data):
|
|||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# GrampsDBDirCursor
|
# GrampsWriteCursor
|
||||||
#
|
#
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
class GrampsDBDirCursor(GrampsCursor):
|
class GrampsWriteCursor(GrampsCursor):
|
||||||
|
|
||||||
def __init__(self, source, txn=None):
|
def __init__(self, source, txn=None, **kwargs):
|
||||||
|
GrampsCursor.__init__(self, txn=txn, **kwargs)
|
||||||
self.cursor = source.db.cursor(txn)
|
self.cursor = source.db.cursor(txn)
|
||||||
self.source = source
|
self.source = source
|
||||||
|
|
||||||
@ -158,7 +159,8 @@ class GrampsDBDirCursor(GrampsCursor):
|
|||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
class GrampsDBDirAssocCursor(GrampsCursor):
|
class GrampsDBDirAssocCursor(GrampsCursor):
|
||||||
|
|
||||||
def __init__(self, source, txn=None):
|
def __init__(self, source, txn=None, **kwargs):
|
||||||
|
GrampsCursor.__init__(self, txn=txn, **kwargs)
|
||||||
self.cursor = source.cursor(txn)
|
self.cursor = source.cursor(txn)
|
||||||
self.source = source
|
self.source = source
|
||||||
|
|
||||||
@ -257,6 +259,17 @@ class GrampsDBDir(GrampsDbRead, Callback, UpdateCallback):
|
|||||||
|
|
||||||
_log_error = __log_error
|
_log_error = __log_error
|
||||||
|
|
||||||
|
# Override get_cursor method from the superclass to add udpate
|
||||||
|
# capability
|
||||||
|
|
||||||
|
@catch_db_error
|
||||||
|
def get_cursor(self, table, txn=None, update=False, commit=False):
|
||||||
|
""" Helper function to return a cursor over a table """
|
||||||
|
if update and not txn:
|
||||||
|
txn = self.env.txn_begin(self.txn)
|
||||||
|
return GrampsWriteCursor(table, txn=txn or self.txn,
|
||||||
|
update=update, commit=commit)
|
||||||
|
|
||||||
# cursors for lookups in the reference_map for back reference
|
# cursors for lookups in the reference_map for back reference
|
||||||
# lookups. The reference_map has three indexes:
|
# lookups. The reference_map has three indexes:
|
||||||
# the main index: a tuple of (primary_handle, referenced_handle)
|
# the main index: a tuple of (primary_handle, referenced_handle)
|
||||||
@ -1802,11 +1815,9 @@ if __name__ == "__main__":
|
|||||||
d.load(db_path, lambda x: x)
|
d.load(db_path, lambda x: x)
|
||||||
|
|
||||||
print d.get_default_person()
|
print d.get_default_person()
|
||||||
|
|
||||||
with d.get_person_cursor() as c:
|
with d.get_person_cursor() as c:
|
||||||
for key, data in c:
|
for key, data in c:
|
||||||
person = Person(data)
|
person = Person(data)
|
||||||
print key, person.get_primary_name().get_name(),
|
print key, person.get_primary_name().get_name(),
|
||||||
|
|
||||||
print d.surnames.keys()
|
print d.surnames.keys()
|
||||||
print d.remove_from_surname_list.__doc__
|
|
||||||
|
@ -30,6 +30,8 @@
|
|||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
import gobject
|
import gobject
|
||||||
import gtk
|
import gtk
|
||||||
|
import cPickle
|
||||||
|
from bsddb.db import DB_CURRENT
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
@ -40,6 +42,7 @@ import const
|
|||||||
from gui.utils import ProgressMeter
|
from gui.utils import ProgressMeter
|
||||||
import GrampsDisplay
|
import GrampsDisplay
|
||||||
import ManagedWindow
|
import ManagedWindow
|
||||||
|
from gen.lib import Person
|
||||||
|
|
||||||
from QuestionDialog import OkDialog
|
from QuestionDialog import OkDialog
|
||||||
from PluginUtils import Tool
|
from PluginUtils import Tool
|
||||||
@ -234,10 +237,10 @@ class ChangeNames(Tool.BatchTool, ManagedWindow.ManagedWindow):
|
|||||||
for node in self.iter_list
|
for node in self.iter_list
|
||||||
if self.model.get_value(node,0)]
|
if self.model.get_value(node,0)]
|
||||||
|
|
||||||
#for handle in self.db.get_person_handles(sort_handles=False):
|
with self.db.get_person_cursor(update=True, commit=True) as cursor:
|
||||||
for handle in self.db.get_person_handles(False):
|
for handle, data in cursor:
|
||||||
|
person = Person(data)
|
||||||
change = False
|
change = False
|
||||||
person = self.db.get_person_from_handle(handle)
|
|
||||||
for name in [person.get_primary_name()] + person.get_alternate_names():
|
for name in [person.get_primary_name()] + person.get_alternate_names():
|
||||||
sname = name.get_surname()
|
sname = name.get_surname()
|
||||||
if sname in changelist:
|
if sname in changelist:
|
||||||
@ -245,7 +248,7 @@ class ChangeNames(Tool.BatchTool, ManagedWindow.ManagedWindow):
|
|||||||
sname = self.name_cap(sname)
|
sname = self.name_cap(sname)
|
||||||
name.set_surname(sname)
|
name.set_surname(sname)
|
||||||
if change:
|
if change:
|
||||||
self.db.commit_person(person,self.trans)
|
cursor.update(handle, person.serialize())
|
||||||
|
|
||||||
self.db.transaction_commit(self.trans,_("Capitalization changes"))
|
self.db.transaction_commit(self.trans,_("Capitalization changes"))
|
||||||
self.db.enable_signals()
|
self.db.enable_signals()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user