Working on select/update from Struct
This commit is contained in:
parent
f80e6422a3
commit
2c1ba1496b
@ -36,6 +36,53 @@ from ..const import GRAMPS_LOCALE as glocale
|
|||||||
from ..constfunc import handle2internal
|
from ..constfunc import handle2internal
|
||||||
_ = glocale.translation.gettext
|
_ = glocale.translation.gettext
|
||||||
|
|
||||||
|
def parse(string):
|
||||||
|
"""
|
||||||
|
Break a string up into a struct-path:
|
||||||
|
|
||||||
|
>>> parse("primary.first_name.startswith('Sarah')")
|
||||||
|
["primary_name", "first_name", "startswith", "('Sarah')"]
|
||||||
|
"""
|
||||||
|
retval = []
|
||||||
|
stack = []
|
||||||
|
current = ""
|
||||||
|
for p in range(len(string)):
|
||||||
|
c = string[p]
|
||||||
|
if c == ")":
|
||||||
|
if stack and stack[-1] == "(": # end
|
||||||
|
stack.pop(-1)
|
||||||
|
current += c
|
||||||
|
retval.append(current)
|
||||||
|
current = ""
|
||||||
|
elif c == "(":
|
||||||
|
stack.append(c)
|
||||||
|
retval.append(current)
|
||||||
|
current = ""
|
||||||
|
current += c
|
||||||
|
elif c in ["'", '"']:
|
||||||
|
if stack and stack[-1] == c: # end
|
||||||
|
stack.pop(-1)
|
||||||
|
current += c
|
||||||
|
if stack and stack[-1] in ["'", '"', '(']: # in quote or args
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
current += c
|
||||||
|
retval.append(current)
|
||||||
|
current = ""
|
||||||
|
else: # start
|
||||||
|
stack.append(c)
|
||||||
|
current += c
|
||||||
|
elif stack and stack[-1] in ["'", '"', '(']: # in quote or args
|
||||||
|
current += c
|
||||||
|
elif c == ".":
|
||||||
|
retval.append(current)
|
||||||
|
current = ""
|
||||||
|
else:
|
||||||
|
current += c
|
||||||
|
if current:
|
||||||
|
retval.append(current)
|
||||||
|
return retval
|
||||||
|
|
||||||
def import_as_dict(filename, user=None):
|
def import_as_dict(filename, user=None):
|
||||||
"""
|
"""
|
||||||
Import the filename into a DictionaryDb and return it.
|
Import the filename into a DictionaryDb and return it.
|
||||||
@ -245,7 +292,10 @@ class Struct(object):
|
|||||||
def __init__(self, struct, db=None):
|
def __init__(self, struct, db=None):
|
||||||
self.struct = struct
|
self.struct = struct
|
||||||
self.db = db
|
self.db = db
|
||||||
self.transaction = db.get_transaction_class()
|
if self.db:
|
||||||
|
self.transaction = db.get_transaction_class()
|
||||||
|
else:
|
||||||
|
self.transaction = None
|
||||||
|
|
||||||
def __getitem__(self, path):
|
def __getitem__(self, path):
|
||||||
"""
|
"""
|
||||||
@ -253,14 +303,30 @@ class Struct(object):
|
|||||||
|
|
||||||
>>> Struct(struct)["primary_name.surname_list.0.surname"]
|
>>> Struct(struct)["primary_name.surname_list.0.surname"]
|
||||||
"""
|
"""
|
||||||
# First, work way down to last part:
|
# Work way down to last part:
|
||||||
|
return self.getitem_from_path(parse(path))
|
||||||
|
|
||||||
|
def getitem_from_path(self, path):
|
||||||
|
"""
|
||||||
|
Given a path that is already parsed, return item.
|
||||||
|
"""
|
||||||
struct = self.struct
|
struct = self.struct
|
||||||
for part in path.split("."):
|
for part in path:
|
||||||
struct = self.getitem(part, struct)
|
struct = self.getitem(part, struct)
|
||||||
if struct is None:
|
if struct is None:
|
||||||
return None
|
return None
|
||||||
return struct
|
return struct
|
||||||
|
|
||||||
|
def get_ref_struct(self, item):
|
||||||
|
"""
|
||||||
|
If the item is a handle, look up reference object.
|
||||||
|
"""
|
||||||
|
if hasattr(item, "classname") and self.db:
|
||||||
|
obj = self.db.get_from_name_and_handle(item.classname, str(item))
|
||||||
|
return Struct(obj.to_struct(), self.db)
|
||||||
|
else:
|
||||||
|
return item
|
||||||
|
|
||||||
def getitem(self, item, struct=None):
|
def getitem(self, item, struct=None):
|
||||||
"""
|
"""
|
||||||
>>> Struct(struct).getitem("primary_name")
|
>>> Struct(struct).getitem("primary_name")
|
||||||
@ -272,14 +338,21 @@ class Struct(object):
|
|||||||
if isinstance(struct, (list, tuple)):
|
if isinstance(struct, (list, tuple)):
|
||||||
pos = int(item)
|
pos = int(item)
|
||||||
if pos < len(struct):
|
if pos < len(struct):
|
||||||
return struct[int(item)]
|
return self.get_ref_struct(struct[int(item)])
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
elif isinstance(struct, dict):
|
elif isinstance(struct, dict):
|
||||||
if item in struct:
|
if item in struct.keys():
|
||||||
return struct[item]
|
return self.get_ref_struct(struct[item])
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
elif isinstance(struct, Struct):
|
||||||
|
return self.get_ref_struct(struct[item])
|
||||||
|
elif hasattr(struct, item):
|
||||||
|
return getattr(struct, item)
|
||||||
|
elif item.startswith("("):
|
||||||
|
args = eval(item[1:-1] + ",")
|
||||||
|
return struct(*args)
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -289,33 +362,40 @@ class Struct(object):
|
|||||||
|
|
||||||
>>> Struct(struct).getitem(["primary_name", "surname_list", "0", "surname"])
|
>>> Struct(struct).getitem(["primary_name", "surname_list", "0", "surname"])
|
||||||
"""
|
"""
|
||||||
path = path.split(".")
|
return self.setitem_from_path(parse(path), value)
|
||||||
|
|
||||||
|
def setitem_from_path(self, path, value):
|
||||||
path, item = path[:-1], path[-1]
|
path, item = path[:-1], path[-1]
|
||||||
struct = self[".".join(path)]
|
struct = self.getitem_from_path(path)
|
||||||
if isinstance(struct, (list, tuple)):
|
if isinstance(struct, (list, tuple)):
|
||||||
pos = int(item)
|
pos = int(item)
|
||||||
if pos < len(struct):
|
if pos < len(struct):
|
||||||
struct[int(item)] = value
|
struct[int(item)] = value
|
||||||
elif isinstance(struct, dict):
|
elif isinstance(struct, dict):
|
||||||
struct[item] = value
|
if item in struct.keys():
|
||||||
|
struct[item] = value
|
||||||
|
else:
|
||||||
|
raise AttributeError("no such property: '%s'" % item)
|
||||||
|
elif isinstance(struct, Struct):
|
||||||
|
struct.setitem_from_path(path, value)
|
||||||
|
elif hasattr(struct, item):
|
||||||
|
setattr(struct, item, value)
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
# update the database
|
self.update_db()
|
||||||
if self.db:
|
|
||||||
self.update_db()
|
|
||||||
|
|
||||||
def update_db(self):
|
def update_db(self):
|
||||||
name = self.struct["_class"]
|
if self.db:
|
||||||
handle = self.struct["handle"]
|
with self.transaction("Struct Update", self.db) as trans:
|
||||||
obj = self.db.get_from_name_and_handle(name, handle)
|
new_obj = from_struct(self.struct)
|
||||||
new_obj = from_struct(self.struct)
|
name, handle = self.struct["_class"], self.struct["handle"]
|
||||||
with self.transaction("Struct Update", self.db) as trans:
|
old_obj = self.db.get_from_name_and_handle(name, handle)
|
||||||
if obj:
|
if old_obj:
|
||||||
commit_func = self.db._tables[name]["commit_func"]
|
commit_func = self.db._tables[name]["commit_func"]
|
||||||
commit_func(new_obj, trans)
|
commit_func(new_obj, trans)
|
||||||
else:
|
else:
|
||||||
add_func = self.db._tables[name]["add_func"]
|
add_func = self.db._tables[name]["add_func"]
|
||||||
add_func(new_obj, trans)
|
add_func(new_obj, trans)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.struct)
|
return str(self.struct)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user