I have about 2000 sources that I would like to update the title and abbreviation for. There is a source table in the Gramps database with those columns, so I tried to update the values. It was probably not a great idea because in Gramps I still see the old data instead, I guess the values might also be stored in some blobs.
Is there some (not too complicated) way to get “raw access” to objects so I can modify them programatically and save them? There seems to be a Python shell plugin, could that be useful? (This is a one-time-thing so I don’t want to dive into plugin development.)
(I have a file with the source ids, titles and abbreviations. The ids are the same as the gramps_id, but the titles and abbreviations needs to be updated in Gramps.)
I know I can export the entire tree, edit the XML and import to a new tree, but I would prefer another way.
The low tech option:
Create a tiny tree with samples of the data you want to update. Then export the whole tree as CSV file. You can use that as a template for doing import tests with the Import Text gramplet addon.
If you want to get your fingers in doing thing programmatically, you cannot beat the Isotammi SuperTool addon tool.
Since this is to be a one time thing, another approach that doesn’t require any programming is to export your tree to an xml file, use a text editor to make the changes you want, and import the resulting xml file into a new tree. I’ve used this approach for making other types of changes and it worked well as long as I was careful.
Kari’s ( @kku ) most recent tweaks to SuperTool have been quite versatile.
You can now embed Scripts as Notes and customize the SuperTool Help JSON file to exampand and link examples. It makes organizing and trading scripts easier. (You can attach them to a dummy person and export a whole personal library of scripts as a 1-person tree.)
There’s an experimental version that has a comment section in the script parser. So you can keep design notes about the script evolution.
Primary objects are treated as tables within the database. Individual components that compose the primary object are stored as individual items in the database.
object components are not stored as individual COLUMNs (in SQL sense) in TABLEs. The Python object is not “unfolded” into human-perceptible bits. It is stored as an opaque block in i BLOB (Binary Large OBject).
Therefore, accessing the DB directly is not possible if you don’t reuse a large part of the GRAMPS code.
For such tasks as modifying GRAMPS objects or transforming objects from one category to another one (like turning a Note into a Url), I work on the XML with a macro-generator.
I have so far only use the API for read access (creating simple reports) but my understading is that the objects can be modified and will be serialised back into python blobs in the DB.
Access to Gramps objects using the database API is easy. The Python Shell or Python Evaluation plugins can run code for you.
To get a list of sources, with their ID, title and author type:
for src in self.dbstate.db.iter_sources():
print (src.gramps_id, src.title, src.author)
To change the Gramps ID of a source object use:
from gramps.gen.db import DbTxn
with DbTxn("Transaction description", self.dbstate.db) as trans:
src.set_gramps_id("New ID")
self.dbstate.db.commit_source(src, trans)
Obviously only try this last example on a test database. You can retrieve a source object using code in the first example.
This is the first step to writing your own addon such as a report, tool or gramplet.
SuperTool is probably the best solution for a one-off task as described in this topic though. I just added a couple of code examples for completeness.
I did it like this. I had to add the line with db.commit_source to save each entry, before that only ~50% of the entries was actually updated. I think I red somewhere that there might be some issue when handling more than 1000 objects and I have about 2000 sources, so perhaps that’s why.
[Gramps SuperTool script file]
version=1
[title]
SuperTool-Sources_ModifySourceDataFromFile
[category]
Sources
[initial_statements]
file = open("C:\\somepath\\modified.csv")
content = file.readlines()
file.close()
dict = {}
for row in content:
rowItems = row.split(";")
dict[rowItems[0]] = [rowItems[1], rowItems[2].strip()]
[statements]
currentId = source.gramps_id
if currentId in dict:
match = dict[currentId]
title = match[0]
abbrev = match[1]
source.set_title(title)
source.set_abbreviation(abbrev)
db.commit_source(source, trans)
[filter]
[expressions]
gramps_id, title, abbrev
[scope]
all
[unwind_lists]
False
[commit_changes]
True
[summary_only]
False