Writing code to find out something about your family tree in Gramps isn’t particularly hard, but it is tedious. And I find the more tedious code is to write, the more errors I make.
Let’s take a look at some random example of what it takes to do something in Gramps. Consider the problem of finding out how many people were born in March. Basically, we need to go through the database, get the reference (if one) to the birth event, look up the birth event, if found, get the date from it, get the month and compare it. That might look like this:
count = 0 for p in db.iter_people(): birth_ref = p.get_birth_ref() if birth_ref: event = db.get_event_from_handle(birth_ref.ref) if event: date = event.get_date_object() if date.get_month() == 3: count += 1
This example is not unusual; you’d have to do something like this whatever it is that you are doing. And this is a simple example. It can get much more complicated. But even in this “simple” example, you have to know a lot about the gen.lib objects that make up Gramps (things like Person, Event, and Date) but you also need to know the interface to the database (things like iter_people, get_event_from_handle) and how things are linked together (handles and refs).
I’ve been working on Gramps-Connect, a web version of Gramps, and it starts from a completely different premise. As it is based on a query language (and built from Django), the above question can be done in one line:
This form takes a bit of getting used to, as it has some different syntax from regular Python. You need to read the double-underscore as a dot. You still have to know the names of the tables and fields, but everything else is just standard Django. There are some nice things here: there is no reference to the database, and there is no explicit mention of handles to manually lookup related data.
I wondered if we can take some of the ideas from Django and apply them to Gramps to end up with a better interface. I’m not that interested in writing a query engine for Gramps (Gramps is implemented in a schema-less graph-like datastore, not anything like a relational database), but I would like to simplify the manner in which developers interact with Gramps.
Here is how you would solve the above using this experimental Gramps addon:
from libaccess import * init(dbstate.db) len([p for p in Person.all() if p.birth.date.month == 3])
That’s it. Now there’s quite a bit going on here, but I think the most interesting is that this works even if a person doesn’t have a birth event, or if the birth event happens to be missing (eg, the database is in an inconsistent state). By allowing this, it makes chained accessors (item.item.item) possible to use to get to the endpoint to make the comparison (month == 3). Also, one doesn’t need to know anything about the database or gen.lib objects other than the field names we’re interested in.
The Gramps development team will be looking at alternative interfaces for Gramps 3.3 for a variety of reasons. Perhaps you have some ideas.
You can play (and make changes to) this experimental interface by running Gramps trunk, and using libaccess from gramps-addons. Or wait a couple of months for Gramps 3.2!