Interface for getting/setting struct parts by dotted path

This commit is contained in:
Doug Blank 2013-11-10 09:11:49 -05:00
parent c24e037a64
commit 94dbcc5ac7

View File

@ -185,6 +185,9 @@ def diff_db_to_file(old_db, filename, user=None):
return diffs, m_old, m_new return diffs, m_old, m_new
def from_struct(struct): def from_struct(struct):
"""
Given a struct with metadata, create a Gramps object.
"""
from gramps.gen.lib import (Person, Family, Event, Source, Place, Citation, from gramps.gen.lib import (Person, Family, Event, Source, Place, Citation,
Repository, MediaObject, Note, Tag) Repository, MediaObject, Note, Tag)
if isinstance(struct, dict): if isinstance(struct, dict):
@ -210,3 +213,76 @@ def from_struct(struct):
elif struct["_class"] == "Tag": elif struct["_class"] == "Tag":
return Tag.create(Tag.from_struct(struct)) return Tag.create(Tag.from_struct(struct))
raise AttributeError("invalid struct") raise AttributeError("invalid struct")
class Struct(object):
"""
Class for getting and setting parts of a struct by dotted path.
>>> s = Struct({"gramps_id": "I0001", ...})
>>> s["primary_name.surname_list.0.surname"]
Jones
>>> s["primary_name.surname_list.0.surname"] = "Smith"
>>> s["primary_name.surname_list.0.surname"]
Smith
"""
def __init__(self, struct, db=None):
self.struct = struct
self.db = db
def __getitem__(self, path):
"""
Given a path to a struct part, return the part, or None.
>>> Struct(struct)["primary_name.surname_list.0.surname"]
"""
# First, work way down to last part:
struct = self.struct
for part in path.split("."):
struct = self.getitem(part, struct)
if struct is None:
return None
return struct
def getitem(self, item, struct=None):
"""
>>> Struct(struct).getitem("primary_name")
{...}
"""
if struct is None:
struct = self.struct
# Get part
if isinstance(struct, (list, tuple)):
pos = int(item)
if pos < len(struct):
return struct[int(item)]
else:
return None
elif isinstance(struct, dict):
if item in struct:
return struct[item]
else:
return None
else:
return None
def __setitem__(self, path, value):
"""
Given a path to a struct part, set the last part to value.
>>> Struct(struct).getitem(["primary_name", "surname_list", "0", "surname"])
"""
path = path.split(".")
path, item = path[:-1], path[-1]
struct = self[".".join(path)]
if isinstance(struct, (list, tuple)):
pos = int(item)
if pos < len(struct):
struct[int(item)] = value
elif isinstance(struct, dict):
struct[item] = value
else:
return
# update the database
def __str__(self):
return str(self.struct)