Keep getting errors about orientation when creating a new gramplet

I am trying to create a death clean up gramplet. however, I keep getting different orientation errors.

Here is the code to the main file:

from gramps.gen.const import GRAMPS_LOCALE as glocale
from gramps.gen.const import GRAMPS_LOCALE_DIR as glocaledir
from gramps.gen.lib import Date

class DeathDateModifierGramplet:
def init(self, db, person, view):
self.db = db
self.view = view

def update_death_dates(self):
    # Replace 'unknown', 'Deceased', 'Dead' with an empty value
    for person_handle in self.db.get_family_handles():
        person = self.db.get_person_from_handle(person_handle)
        death_ref = person.get_death_ref()
        if death_ref:
            death_value = death_ref.get_value().lower()
            if death_value in ['unknown', 'deceased', 'dead']:
                death_ref.set_value('')

    # Commit changes to the database
    self.db.commit()

def main(self):
    self.update_death_dates()

Entry point to execute the Gramplet

def run(db, view):
glocale.init()
locale_dir = glocaledir()
locale_dir.install()
gramplet = DeathDateModifierGramplet(db, None, view)
gramplet.main()

Can someone help me with this?

an error dump with stack trace would be very helpful in debugging this…

Here is one of the errors that come up, they keep saying the same thing except the number of the error changes:

2123: ERROR: grampsapp.py: line 188: Unhandled exception
Traceback (most recent call last):
  File "C:\Program Files\GrampsAIO64-5.2.0\gramps\gui\widgets\grampletbar.py", line 478, in __page_added
    gramplet.set_orientation(self.orientation)
  File "C:\Program Files\GrampsAIO64-5.2.0\gramps\gui\widgets\grampletbar.py", line 693, in set_orientation
    self.pui.set_orientation(orientation)
    ^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'set_orientation'

Your gramplet needs to sub-class the Gramplet base class.

from gramps.gen.plug import Gramplet

class DeathDateModifierGramplet(Gramplet):

The get_family_handles method returns family handles not person handles.

Event reference objects don’t have a get_value method.

You shouldn’t instantiate a gramplet yourself, or call the main method directly.

Nick, I will try this out after my import. I am waiting to see how long it takes to import over 3 million records. However, once the import is complete I will try what you have suggested. I really appreciate it.

I have changed the code to this:

from gramps.gen.plug import Gramplet
from gramps.gen.const import GRAMPS_LOCALE as glocale
from gramps.gen.const import GRAMPS_LOCALE_DIR as glocaledir

class DeathDateModifierGramplet(Gramplet):
    def __init__(self, db, view):
        Gramplet.__init__(self, db)
        self.view = view

    def update_death_dates(self):
        # Retrieve person handles
        person_handles = self.db.get_person_handles()
        for person_handle in person_handles:
            person = self.db.get_person_from_handle(person_handle)
            # Access death event
            death_event_ref = person.get_death_ref()
            if death_event_ref:
                # Set death event value to empty if it matches criteria
                death_event = death_event_ref.get_event()
                if death_event and death_event.get_value().lower() in ['unknown', 'deceased', 'dead']:
                    death_event_ref.set_value('')

        # Commit changes to the database
        self.db.commit()

    def main(self):
        self.update_death_dates()

# Entry point to execute the Gramplet
def run(db, view):
    glocale.init()
    locale_dir = glocaledir()
    locale_dir.install()
    gramplet = DeathDateModifierGramplet(db, view)
    gramplet.main()

I will be trying to see if this does the job once my import is complete.

This isn’t going to work. Try:

death_event = self.db.get_event_from_handle(death_event_ref.ref)

Events don’t have a get_value method.

What are you trying to do? I think that a Tool would probably be better than a Gramplet for this.

the goal was to create a death date clean-up function. mainly to get rid of words like “unknown, dead, and deceased” these tend to come from familysearch data pulls. I have about 5 ideas that I believe can help clean up data received into gramps and thought that gramplets would have been the way. This is just one of the five I am interested in creating.

Try something like the following to check if the death date is text only and in the list of values you are interested in:

from gramps.gen.lib import Date

date = death_event.get_date_object()
if (date.get_modifier() == Date.MOD_TEXTONLY and
        date.get_text().lower() in ['unknown', 'deceased', 'dead']):
    death_event.set_date_object(Date())

Then you probably want to commit the updated event using a transaction. Use something like:

from gramps.gen.db import DbTxn

with DbTxn(_("Transaction description"), self.db) as trans:
    self.db.commit_event(death_event, trans)

Here is the updated version I will try:

from gramps.gen.plug import Gramplet
from gramps.gen.const import GRAMPS_LOCALE as glocale
from gramps.gen.const import GRAMPS_LOCALE_DIR as glocaledir
from gramps.gen.lib import Date
from gramps.gen.db import DbTxn

class DeathDateModifierGramplet(Gramplet):
    def __init__(self, db, view):
        Gramplet.__init__(self, db)
        self.view = view

    def update_death_dates(self):
        # Retrieve person handles
        person_handles = self.db.get_person_handles()
        for person_handle in person_handles:
            person = self.db.get_person_from_handle(person_handle)
            # Access death event
            death_event_ref = person.get_death_ref()
            if death_event_ref:
                death_event_handle = death_event_ref.ref
                death_event = self.db.get_event_from_handle(death_event_handle)
                # Check if death date is text only and in the list of values of interest
                date = death_event.get_date_object()
                if (date.get_modifier() == Date.MOD_TEXTONLY and
                    date.get_text().lower() in ['unknown', 'deceased', 'dead']):
                    # Update death date to empty
                    death_event.set_date_object(Date())

                    # Commit updated event within a transaction
                    with DbTxn(_("Update Death Date"), self.db) as trans:
                        self.db.commit_event(death_event, trans)

    def main(self):
        self.update_death_dates()

# Entry point to execute the Gramplet
def run(db, view):
    glocale.init()
    locale_dir = glocaledir()
    locale_dir.install()
    gramplet = DeathDateModifierGramplet(db, view)
    gramplet.main()

Nick, I am still waiting on the import I started on 2/29/2024. I will not be able to test until the import is complete. I didn’t think it would take this long. However, once it is complete I will test it and let you know. Thanks again for the help.

the import just finished, 4,655,218 individuals have been successfully imported into their database. It took over 1 week to get these imported. I tried the code you suggested and still getting the orientation error. How can I convert into a tool and utilize the code that way?

When I import from FamilySearch, via Ancestral Quest or RootsMagic, I see those dates too, and in most cases, the associated events have no useful other data, like a location, so I just try to get rid of them, and the easiest way for me is to sort the event list by date. When I do that, the empty dates are shown at the top, followed by the invalid ones, making it very easy to inspect them, do a multi select, and delete all in one go.

This sorting may not work so nice when you have more than 4 Million persons, but you can also create a custom filter for invalid dates, so that you only see those in the event view.

If you really want to write code, because you don’t like the bulk delete that I do, there is no need to read all persons, because the events live in their own table, so you can just retrieve those, filter by type, and do your thing.

You can use gramps/plugins/tool/changetypes.py for inspiration.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.