DbDjango database works read-only in Gtk Gramps

These changes add most of what is necessary to use DbDjango as
a full database to Gtk Gramps.
This commit is contained in:
Doug Blank 2015-05-10 22:43:51 -04:00
parent ccbab78fbc
commit 03b78a0884
3 changed files with 393 additions and 48 deletions

View File

@ -89,13 +89,10 @@ class MetaCursor(object):
def __iter__(self): def __iter__(self):
return self.__next__() return self.__next__()
def __next__(self): def __next__(self):
for item in []: yield None
yield ("", None)
def __exit__(self, *args, **kwargs): def __exit__(self, *args, **kwargs):
pass pass
def iter(self): def iter(self):
for item in []:
yield ("", "")
yield None yield None
def first(self): def first(self):
self._iter = self.__iter__() self._iter = self.__iter__()
@ -118,12 +115,12 @@ class Cursor(object):
return self.__next__() return self.__next__()
def __next__(self): def __next__(self):
for item in self.model.all(): for item in self.model.all():
yield (item.handle, self.func(item.handle)) yield (bytes(item.handle, "utf-8"), self.func(item.handle))
def __exit__(self, *args, **kwargs): def __exit__(self, *args, **kwargs):
pass pass
def iter(self): def iter(self):
for item in self.model.all(): for item in self.model.all():
yield (item.handle, self.func(item.handle)) yield (bytes(item.handle, "utf-8"), self.func(item.handle))
yield None yield None
def first(self): def first(self):
self._iter = self.__iter__() self._iter = self.__iter__()
@ -136,11 +133,13 @@ class Cursor(object):
def close(self): def close(self):
pass pass
class Bookmarks: class Bookmarks(object):
def __init__(self):
self.handles = []
def get(self): def get(self):
return [] # handles return self.handles
def append(self, handle): def append(self, handle):
pass self.handles.append(handle)
class DjangoTxn(DbTxn): class DjangoTxn(DbTxn):
def __init__(self, message, db, table=None): def __init__(self, message, db, table=None):
@ -334,6 +333,23 @@ class DbDjango(DbWriteBase, DbReadBase):
self.import_cache = {} self.import_cache = {}
self.use_import_cache = False self.use_import_cache = False
self.use_db_cache = True self.use_db_cache = True
self._signals_enabled = False
self._signals = {}
self.event_names = set()
self.individual_attributes = set()
self.family_attributes = set()
self.source_attributes = set()
self.child_ref_types = set()
self.family_rel_types = set()
self.event_role_names = set()
self.name_types = set()
self.origin_types = set()
self.repository_types = set()
self.note_types = set()
self.source_media_types = set()
self.url_types = set()
self.media_attributes = set()
self.place_types = set()
def prepare_import(self): def prepare_import(self):
""" """
@ -403,7 +419,7 @@ class DbDjango(DbWriteBase, DbReadBase):
pass pass
def enable_signals(self): def enable_signals(self):
pass self._signals_enabled = True
def request_rebuild(self): def request_rebuild(self):
# caches are ok, but let's compute public's # caches are ok, but let's compute public's
@ -752,17 +768,6 @@ class DbDjango(DbWriteBase, DbReadBase):
return None return None
return self.make_family(family) return self.make_family(family)
def get_family_from_gramps_id(self, gramps_id):
if self.import_cache:
for handle in self.import_cache:
if self.import_cache[handle].gramps_id == gramps_id:
return self.import_cache[handle]
try:
family = self.dji.Family.get(gramps_id=gramps_id)
except:
return None
return self.make_family(family)
def get_repository_from_handle(self, handle): def get_repository_from_handle(self, handle):
if handle in self.import_cache: if handle in self.import_cache:
return self.import_cache[handle] return self.import_cache[handle]
@ -990,6 +995,94 @@ class DbDjango(DbWriteBase, DbReadBase):
else: else:
return None return None
def get_family_from_gramps_id(self, gramps_id):
if self.import_cache:
for handle in self.import_cache:
if self.import_cache[handle].gramps_id == gramps_id:
return self.import_cache[handle]
try:
family = self.dji.Family.get(gramps_id=gramps_id)
except:
return None
return self.make_family(family)
def get_source_from_gramps_id(self, gramps_id):
if self.import_cache:
for handle in self.import_cache:
if self.import_cache[handle].gramps_id == gramps_id:
return self.import_cache[handle]
match_list = self.dji.Source.filter(gramps_id=gramps_id)
if match_list.count() > 0:
return self.make_source(match_list[0])
else:
return None
def get_citation_from_gramps_id(self, gramps_id):
if self.import_cache:
for handle in self.import_cache:
if self.import_cache[handle].gramps_id == gramps_id:
return self.import_cache[handle]
match_list = self.dji.Citation.filter(gramps_id=gramps_id)
if match_list.count() > 0:
return self.make_citation(match_list[0])
else:
return None
def get_event_from_gramps_id(self, gramps_id):
if self.import_cache:
for handle in self.import_cache:
if self.import_cache[handle].gramps_id == gramps_id:
return self.import_cache[handle]
match_list = self.dji.Event.filter(gramps_id=gramps_id)
if match_list.count() > 0:
return self.make_event(match_list[0])
else:
return None
def get_object_from_gramps_id(self, gramps_id):
if self.import_cache:
for handle in self.import_cache:
if self.import_cache[handle].gramps_id == gramps_id:
return self.import_cache[handle]
match_list = self.dji.Media.filter(gramps_id=gramps_id)
if match_list.count() > 0:
return self.make_media(match_list[0])
else:
return None
def get_place_from_gramps_id(self, gramps_id):
if self.import_cache:
for handle in self.import_cache:
if self.import_cache[handle].gramps_id == gramps_id:
return self.import_cache[handle]
match_list = self.dji.Place.filter(gramps_id=gramps_id)
if match_list.count() > 0:
return self.make_place(match_list[0])
else:
return None
def get_repsoitory_from_gramps_id(self, gramps_id):
if self.import_cache:
for handle in self.import_cache:
if self.import_cache[handle].gramps_id == gramps_id:
return self.import_cache[handle]
match_list = self.dji.Repsoitory.filter(gramps_id=gramps_id)
if match_list.count() > 0:
return self.make_repository(match_list[0])
else:
return None
def get_note_from_gramps_id(self, gramps_id):
if self.import_cache:
for handle in self.import_cache:
if self.import_cache[handle].gramps_id == gramps_id:
return self.import_cache[handle]
match_list = self.dji.Note.filter(gramps_id=gramps_id)
if match_list.count() > 0:
return self.make_note(match_list[0])
else:
return None
def get_number_of_people(self): def get_number_of_people(self):
return self.dji.Person.count() return self.dji.Person.count()
@ -1225,6 +1318,7 @@ class DbDjango(DbWriteBase, DbReadBase):
if not person.gramps_id and set_gid: if not person.gramps_id and set_gid:
person.gramps_id = self.find_next_person_gramps_id() person.gramps_id = self.find_next_person_gramps_id()
self.commit_person(person, trans) self.commit_person(person, trans)
self.signal("person-add", [person.handle])
return person.handle return person.handle
def add_family(self, family, trans, set_gid=True): def add_family(self, family, trans, set_gid=True):
@ -1233,6 +1327,7 @@ class DbDjango(DbWriteBase, DbReadBase):
if not family.gramps_id and set_gid: if not family.gramps_id and set_gid:
family.gramps_id = self.find_next_family_gramps_id() family.gramps_id = self.find_next_family_gramps_id()
self.commit_family(family, trans) self.commit_family(family, trans)
self.signal("family-add", [family.handle])
return family.handle return family.handle
def add_citation(self, citation, trans, set_gid=True): def add_citation(self, citation, trans, set_gid=True):
@ -1241,6 +1336,7 @@ class DbDjango(DbWriteBase, DbReadBase):
if not citation.gramps_id and set_gid: if not citation.gramps_id and set_gid:
citation.gramps_id = self.find_next_citation_gramps_id() citation.gramps_id = self.find_next_citation_gramps_id()
self.commit_citation(citation, trans) self.commit_citation(citation, trans)
self.signal("citation-add", [citation.handle])
return citation.handle return citation.handle
def add_source(self, source, trans, set_gid=True): def add_source(self, source, trans, set_gid=True):
@ -1249,6 +1345,7 @@ class DbDjango(DbWriteBase, DbReadBase):
if not source.gramps_id and set_gid: if not source.gramps_id and set_gid:
source.gramps_id = self.find_next_source_gramps_id() source.gramps_id = self.find_next_source_gramps_id()
self.commit_source(source, trans) self.commit_source(source, trans)
self.signal("source-add", [source.handle])
return source.handle return source.handle
def add_repository(self, repository, trans, set_gid=True): def add_repository(self, repository, trans, set_gid=True):
@ -1257,6 +1354,7 @@ class DbDjango(DbWriteBase, DbReadBase):
if not repository.gramps_id and set_gid: if not repository.gramps_id and set_gid:
repository.gramps_id = self.find_next_repository_gramps_id() repository.gramps_id = self.find_next_repository_gramps_id()
self.commit_repository(repository, trans) self.commit_repository(repository, trans)
self.signal("repository-add", [repository.handle])
return repository.handle return repository.handle
def add_note(self, note, trans, set_gid=True): def add_note(self, note, trans, set_gid=True):
@ -1265,6 +1363,7 @@ class DbDjango(DbWriteBase, DbReadBase):
if not note.gramps_id and set_gid: if not note.gramps_id and set_gid:
note.gramps_id = self.find_next_note_gramps_id() note.gramps_id = self.find_next_note_gramps_id()
self.commit_note(note, trans) self.commit_note(note, trans)
self.signal("note-add", [note.handle])
return note.handle return note.handle
def add_place(self, place, trans, set_gid=True): def add_place(self, place, trans, set_gid=True):
@ -1304,38 +1403,78 @@ class DbDjango(DbWriteBase, DbReadBase):
return obj.handle return obj.handle
def commit_person(self, person, trans, change_time=None): def commit_person(self, person, trans, change_time=None):
self.import_cache[person.handle] = person if self.use_import_cache:
self.import_cache[person.handle] = person
else:
print("WARNING: haven't written logic to update")
self.signal("person-update", [person.handle])
def commit_family(self, family, trans, change_time=None): def commit_family(self, family, trans, change_time=None):
self.import_cache[family.handle] = family if self.use_import_cache:
self.import_cache[family.handle] = family
else:
print("WARNING: haven't written logic to update")
self.signal("family-update", [family.handle])
def commit_citation(self, citation, trans, change_time=None): def commit_citation(self, citation, trans, change_time=None):
self.import_cache[citation.handle] = citation if self.use_import_cache:
self.import_cache[citation.handle] = citation
else:
print("WARNING: haven't written logic to update")
self.signal("citation-update", [citation.handle])
def commit_source(self, source, trans, change_time=None): def commit_source(self, source, trans, change_time=None):
self.import_cache[source.handle] = source if self.use_import_cache:
self.import_cache[source.handle] = source
else:
print("WARNING: haven't written logic to update")
self.signal("source-update", [source.handle])
def commit_repository(self, repository, trans, change_time=None): def commit_repository(self, repository, trans, change_time=None):
self.import_cache[repository.handle] = repository if self.use_import_cache:
self.import_cache[repository.handle] = repository
else:
print("WARNING: haven't written logic to update")
self.signal("repository-update", [repository.handle])
def commit_note(self, note, trans, change_time=None): def commit_note(self, note, trans, change_time=None):
self.import_cache[note.handle] = note if self.use_import_cache:
self.import_cache[note.handle] = note
else:
print("WARNING: haven't written logic to update")
self.signal("note-update", [note.handle])
def commit_place(self, place, trans, change_time=None): def commit_place(self, place, trans, change_time=None):
self.import_cache[place.handle] = place if self.use_import_cache:
self.import_cache[place.handle] = place
else:
print("WARNING: haven't written logic to update")
self.signal("place-update", [place.handle])
def commit_event(self, event, trans, change_time=None): def commit_event(self, event, trans, change_time=None):
self.import_cache[event.handle] = event if self.use_import_cache:
self.import_cache[event.handle] = event
else:
print("WARNING: haven't written logic to update")
self.signal("event-update", [event.handle])
def commit_tag(self, tag, trans, change_time=None): def commit_tag(self, tag, trans, change_time=None):
self.import_cache[tag.handle] = tag if self.use_import_cache:
self.import_cache[tag.handle] = tag
else:
print("WARNING: haven't written logic to update")
self.signal("tag-update", [tag.handle])
def commit_media_object(self, obj, transaction, change_time=None): def commit_media_object(self, obj, transaction, change_time=None):
""" """
Commit the specified MediaObject to the database, storing the changes Commit the specified MediaObject to the database, storing the changes
as part of the transaction. as part of the transaction.
""" """
self.import_cache[obj.handle] = obj if self.use_import_cache:
self.import_cache[obj.handle] = obj
else:
print("WARNING: haven't written logic to update")
self.signal("media-update", [obj.handle])
def get_gramps_ids(self, obj_key): def get_gramps_ids(self, obj_key):
key2table = { key2table = {
@ -1357,7 +1496,7 @@ class DbDjango(DbWriteBase, DbReadBase):
return return
def disable_signals(self): def disable_signals(self):
pass self._signals_enabled = False
def set_researcher(self, owner): def set_researcher(self, owner):
pass pass
@ -1464,46 +1603,250 @@ class DbDjango(DbWriteBase, DbReadBase):
return False return False
def connect(self, signal, callback): def connect(self, signal, callback):
pass ## citation-add
## citation-delete
## citation-rebuild
## citation-update
#print("Adding signal: ", signal)
if signal in self._signals:
self._signals[signal].append(callback)
else:
self._signals[signal] = [callback]
def find_backlink_handles(self, active_handle): def disconnect(self, signal):
#print("Disconnecting signal: ", signal)
if signal in self._signals:
del self._signals[signal]
def signal(self, sig, items):
#print("Firing signal: ", sig, items)
if self._signals_enabled:
if sig in self._signals:
for callback in self._signals[sig]:
callback(items)
else:
print("WARNING: no such signal: ", sig)
def find_backlink_handles(self, handle, include_classes=None):
## FIXME: figure out how to get objects that refer
## to this handle
return [] return []
def get_note_bookmarks(self): def get_note_bookmarks(self):
return [] return self.note_bookmarks
def get_media_bookmarks(self): def get_media_bookmarks(self):
return [] return self.media_bookmarks
def get_repo_bookmarks(self): def get_repo_bookmarks(self):
return [] return self.repo_bookmarks
def get_citation_bookmarks(self): def get_citation_bookmarks(self):
return [] return self.citation_bookmarks
def get_source_bookmarks(self): def get_source_bookmarks(self):
return [] return self.source_bookmarks
def get_place_bookmarks(self): def get_place_bookmarks(self):
return [] return self.place_bookmarks
def get_event_bookmarks(self): def get_event_bookmarks(self):
return [] return self.event_bookmarks
def get_bookmarks(self): def get_bookmarks(self):
return [] return self.bookmarks
def get_family_bookmarks(self): def get_family_bookmarks(self):
return [] return self.family_bookmarks
def get_save_path(self): def get_save_path(self):
return "/tmp/" return "/tmp/"
## Get types:
def get_event_attribute_types(self):
"""
Return a list of all Attribute types assocated with Event instances
in the database.
"""
return list(self.event_attributes)
def get_event_types(self):
"""
Return a list of all event types in the database.
"""
return list(self.event_names)
def get_person_event_types(self):
"""
Deprecated: Use get_event_types
"""
return list(self.event_names)
def get_person_attribute_types(self):
"""
Return a list of all Attribute types assocated with Person instances
in the database.
"""
return list(self.individual_attributes)
def get_family_attribute_types(self):
"""
Return a list of all Attribute types assocated with Family instances
in the database.
"""
return list(self.family_attributes)
def get_family_event_types(self):
"""
Deprecated: Use get_event_types
"""
return list(self.event_names)
def get_media_attribute_types(self):
"""
Return a list of all Attribute types assocated with Media and MediaRef
instances in the database.
"""
return list(self.media_attributes)
def get_family_relation_types(self):
"""
Return a list of all relationship types assocated with Family
instances in the database.
"""
return list(self.family_rel_types)
def get_child_reference_types(self):
"""
Return a list of all child reference types assocated with Family
instances in the database.
"""
return list(self.child_ref_types)
def get_event_roles(self):
"""
Return a list of all custom event role names assocated with Event
instances in the database.
"""
return list(self.event_role_names)
def get_name_types(self):
"""
Return a list of all custom names types assocated with Person
instances in the database.
"""
return list(self.name_types)
def get_origin_types(self): def get_origin_types(self):
return [] """
Return a list of all custom origin types assocated with Person/Surname
instances in the database.
"""
return list(self.origin_types)
def get_repository_types(self):
"""
Return a list of all custom repository types assocated with Repository
instances in the database.
"""
return list(self.repository_types)
def get_note_types(self):
"""
Return a list of all custom note types assocated with Note instances
in the database.
"""
return list(self.note_types)
def get_source_attribute_types(self):
"""
Return a list of all Attribute types assocated with Source/Citation
instances in the database.
"""
return list(self.source_attributes)
def get_source_media_types(self):
"""
Return a list of all custom source media types assocated with Source
instances in the database.
"""
return list(self.source_media_types)
def get_url_types(self):
"""
Return a list of all custom names types assocated with Url instances
in the database.
"""
return list(self.url_types)
def get_place_types(self):
"""
Return a list of all custom place types assocated with Place instances
in the database.
"""
return list(self.place_types)
def get_default_handle(self): def get_default_handle(self):
return None return None
def close(self): def close(self):
pass pass
def get_surname_list(self):
return []
def is_open(self):
return True
def get_table_names(self):
"""Return a list of valid table names."""
return list(self._tables.keys())
def find_initial_person(self):
return None
# Removals:
def remove_person(self, handle, txn):
self.dji.Person.filter(handle=handle)[0].delete()
self.signal("person-delete", [handle])
def remove_source(self, handle, transaction):
self.dji.Source.filter(handle=handle)[0].delete()
self.signal("source-delete", [handle])
def remove_citation(self, handle, transaction):
self.dji.Citation.filter(handle=handle)[0].delete()
self.signal("citation-delete", [handle])
def remove_event(self, handle, transaction):
self.dji.Event.filter(handle=handle)[0].delete()
self.signal("event-delete", [handle])
def remove_object(self, handle, transaction):
self.dji.Media.filter(handle=handle)[0].delete()
self.signal("media-delete", [handle])
def remove_place(self, handle, transaction):
self.dji.Place.filter(handle=handle)[0].delete()
self.signal("place-delete", [handle])
def remove_family(self, handle, transaction):
self.dji.Family.filter(handle=handle)[0].delete()
self.signal("family-delete", [handle])
def remove_repository(self, handle, transaction):
self.dji.Repository.filter(handle=handle)[0].delete()
self.signal("repository-delete", [handle])
def remove_note(self, handle, transaction):
self.dji.Note.filter(handle=handle)[0].delete()
self.signal("note-delete", [handle])
def remove_tag(self, handle, transaction):
self.dji.Tag.filter(handle=handle)[0].delete()
self.signal("tag-delete", [handle])
def remove_from_surname_list(self, person):
## FIXME
pass

View File

@ -439,7 +439,7 @@ class Tag(models.Model):
if self.dji is None: if self.dji is None:
self.dji = DjangoInterface() self.dji = DjangoInterface()
raw = self.dji.get_tag(self) raw = self.dji.get_tag(self)
return base64.encodebytes(pickle.dumps(raw)) return str(base64.encodebytes(pickle.dumps(raw)), "utf-8")
def from_cache(self): def from_cache(self):
return pickle.loads(base64.decodebytes(bytes(self.cache, "utf-8"))) return pickle.loads(base64.decodebytes(bytes(self.cache, "utf-8")))
@ -529,7 +529,7 @@ class PrimaryObject(models.Model):
raw = self.dji.get_tag(self) raw = self.dji.get_tag(self)
else: else:
raise Exception("Don't know how to get raw '%s'" % type(item)) raise Exception("Don't know how to get raw '%s'" % type(item))
return base64.encodebytes(pickle.dumps(raw)) return str(base64.encodebytes(pickle.dumps(raw)), "utf-8")
def from_cache(self): def from_cache(self):
return pickle.loads(base64.decodebytes(bytes(self.cache, "utf-8"))) return pickle.loads(base64.decodebytes(bytes(self.cache, "utf-8")))

View File

@ -58,11 +58,13 @@ from gramps.gen.constfunc import conv_to_unicode
# gperson = dbdjango.DbDjango().get_person_from_handle(handle) # gperson = dbdjango.DbDjango().get_person_from_handle(handle)
def check_diff(item, raw): def check_diff(item, raw):
encoded = base64.encodestring(pickle.dumps(raw)) encoded = str(base64.encodebytes(pickle.dumps(raw)), "utf-8")
if item.cache != encoded: if item.cache != encoded:
print("Different:", item.__class__.__name__, item.gramps_id) print("Different:", item.__class__.__name__, item.gramps_id)
print("raw :", raw) print("raw :", raw)
print("cache:", item.from_cache()) print("cache:", item.from_cache())
# FIXING, TOO:
item.save_cache()
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -536,6 +538,7 @@ class DjangoInterface(object):
place.lat, place.lat,
place_ref_list, place_ref_list,
place.name, place.name,
[], ## FIXME: get_alt_names
tuple(place.place_type), tuple(place.place_type),
place.code, place.code,
alt_location_list, alt_location_list,
@ -1840,7 +1843,6 @@ class DjangoInterface(object):
for item in self.Media.all(): for item in self.Media.all():
raw = self.get_media(item) raw = self.get_media(item)
check_diff(item, raw) check_diff(item, raw)
encoded = base64.encodestring(pickle.dumps(raw))
count += 1 count += 1
callback(100 * (count/total if total else 0)) callback(100 * (count/total if total else 0))