Ejemplo n.º 1
0
def run_mother(database, document, person):
    """ Function writing the mother lineage quick report
    """
    sa = SimpleAccess(database)
    sd = SimpleDoc(document)

    # display the results

    # feature request 2356: avoid genitive form
    sd.title(_("Mother lineage for %s") % sa.name(person))
    sd.paragraph("")
    sd.paragraph(_(""
        "This report shows the mother lineage, also called matronymic lineage "
        "mtDNA lineage."
        " People in this lineage all share the same Mitochondrial DNA (mtDNA)."
        ))
    sd.paragraph("")

    stab = QuickTable(sa)
    stab.columns(_("Name Mother"), _("Birth"), _("Death Date"), _("Remark"))
    make_details(Person.FEMALE, person, sa, sd, database, stab)
    stab.write(sd)
    sd.paragraph("")

    if person.gender == Person.MALE :
        return

    sd.header2((_("Direct line female descendants")))
    sd.paragraph("")

    make_details_child(Person.FEMALE, person, sa, sd, database)
Ejemplo n.º 2
0
def run(database, document, object, item, trans):
    """
    Display back-references for this object.
    """

    # setup the simple access functions
    sdb = SimpleAccess(database)
    sdoc = SimpleDoc(document)
    stab = QuickTable(sdb)

    # display the title
    sdoc.title(_("References for this %s") % trans)
    sdoc.paragraph("\n")
    stab.columns(_("Type"), _("Reference"))
    for (objclass, handle) in database.find_backlink_handles(object.handle):
        ref = get_ref(database, objclass, handle)
        stab.row(_(objclass), ref)  # translation are explicit (above)

    if stab.get_row_count() > 0:
        document.has_data = True
        stab.write(sdoc)
    else:
        document.has_data = False
        sdoc.paragraph(_("No references for this %s") % trans)
        sdoc.paragraph("")
    sdoc.paragraph("")
Ejemplo n.º 3
0
def run(database, document, person):
    """
    Loops through the person events and the family events of any family
    in which the person is a parent (to catch Marriage events), displaying
    the basic details of the event
    """

    sdb = SimpleAccess(database)
    sdoc = SimpleDoc(document)
    stab = QuickTable(sdb)

    # get the personal events
    event_list = sdb.events(person)

    # get the events of each family in which the person is
    # a parent
    for family in sdb.parent_in(person):
        event_list += sdb.events(family)

    # Sort the events by their date
    event_list.sort(key=lambda x: x.get_date_object())

    # display the results

    # feature request 2356: avoid genitive form
    sdoc.title(_("Sorted events of %s") % sdb.name(person))
    sdoc.paragraph("")

    stab.columns(_("Event Type"), _("Event Date"), _("Event Place"))
    document.has_data = False
    for event in event_list:
        stab.row(event, sdb.event_date_obj(event), sdb.event_place(event))
        document.has_data = True
    stab.write(sdoc)
Ejemplo n.º 4
0
def run(database, document, *args, **kwargs):
    """
    Loops through the families that the person is a child in, and display
    the information about the other children.
    """
    # setup the simple access functions
    sdb = SimpleAccess(database)
    sdoc = SimpleDoc(document)
    stab = QuickTable(sdb)
    # display the title
    sdoc.title(_("All Names of All People"))
    sdoc.paragraph("")
    matches = 0
    stab.columns(_("Name"), _("Primary Name"), _("Name Type"))
    names = []  # name, person
    for person in database.iter_people():
        primary_name = person.get_primary_name()
        if primary_name:
            names += [(nd.display_name(primary_name), person,
                       str(primary_name.get_type()))]
        names += [(nd.display_name(name), person, str(name.get_type()))
                  for name in person.get_alternate_names()]

    matches = 0
    for (name, person, name_type) in sorted(names, key=lambda x: x[0]):
        stab.row(name, person, name_type)
        matches += 1
    sdoc.paragraph(_("Total names %d") % matches)
    sdoc.paragraph("")
    stab.write(sdoc)
Ejemplo n.º 5
0
def run(database, document, person):
    """
    Loops through the families that the person is a child in, and display
    the information about the other children.
    """
    global cache
    cache = {}
    # setup the simple access functions
    sdb = SimpleAccess(database)
    sdoc = SimpleDoc(document)
    stab = QuickTable(sdb)
    # display the title
    sdoc.title(_("Descendant Count"))
    sdoc.paragraph("")
    stab.columns(_("Person"), _("Number of Descendants"))
    people = database.get_person_handles(sort_handles=True)
    for person_handle in people:
        result = countem(database, handle2internal(person_handle))
        cache[person_handle] = len(result)
    matches = 0
    for person_handle in cache:
        person = database.get_person_from_handle(person_handle)
        stab.row(person, cache[person_handle])
        matches += 1
    sdoc.paragraph(_("There are %d people.\n") % matches)
    stab.write(sdoc)
Ejemplo n.º 6
0
def run(database, document, person):
    """
    Loops through the families that the person is a child in, and display
    the information about the other children.
    """
    # setup the simple access functions
    sdb = SimpleAccess(database)
    sdoc = SimpleDoc(document)
    stab = QuickTable(sdb)
    rel_class = get_relationship_calculator(glocale)

    # display the title
    # feature request 2356: avoid genitive form
    sdoc.title(_("Siblings of %s") % sdb.name(person))
    sdoc.paragraph("")
    stab.columns(_("Sibling"), _("Gender"), _("Birth Date"), _("Type"))
    # grab our current id (self):
    gid = sdb.gid(person)
    # loop through each family in which the person is a child
    document.has_data = False
    for family in sdb.child_in(person):
        # loop through each child in the family
        for child in sdb.children(family):
            # only display if this child is not the active person
            if sdb.gid(child) != gid:
                rel_str = rel_class.get_sibling_relationship_string(
                    rel_class.get_sibling_type(database, person, child),
                    person.get_gender(), child.get_gender())
            else:
                rel_str = _('self')
            # pass row the child object to make link:
            stab.row(child, sdb.gender(child), sdb.birth_or_fallback(child),
                     rel_str)
            document.has_data = True
    stab.write(sdoc)
Ejemplo n.º 7
0
def run(database, document, object, item, trans):
    """
    Display back-references for this object.
    """

    # setup the simple access functions
    sdb = SimpleAccess(database)
    sdoc = SimpleDoc(document)
    stab = QuickTable(sdb)

    # display the title
    sdoc.title(_("References for this %s") % trans)
    sdoc.paragraph("\n")
    stab.columns(_("Type"), _("Reference"))
    for (objclass, handle) in database.find_backlink_handles(object.handle):
        ref = get_ref(database, objclass, handle)
        stab.row(_(objclass), ref) # translation are explicit (above)

    if stab.get_row_count() > 0:
        document.has_data = True
        stab.write(sdoc)
    else:
        document.has_data = False
        sdoc.paragraph(_("No references for this %s") % trans)
        sdoc.paragraph("")
    sdoc.paragraph("")
Ejemplo n.º 8
0
def run(database, document, *args, **kwargs):
    """
    Loops through the families that the person is a child in, and display
    the information about the other children.
    """
    # setup the simple access functions
    sdb = SimpleAccess(database)
    sdoc = SimpleDoc(document)
    stab = QuickTable(sdb)
    # display the title
    sdoc.title(_("All Names of All People"))
    sdoc.paragraph("")
    matches = 0
    stab.columns(_("Name"), _("Primary Name"), _("Name Type"))
    names = [] # name, person
    for person in database.iter_people():
        primary_name = person.get_primary_name()
        if primary_name:
            names += [(nd.display_name(primary_name),
                       person,
                       str(primary_name.get_type()))]
        names += [(nd.display_name(name),
                   person,
                   str(name.get_type())) for name in
                  person.get_alternate_names()]

    matches = 0
    for (name, person, name_type) in sorted(names, key=lambda x: x[0]):
        stab.row(name, person, name_type)
        matches += 1
    sdoc.paragraph(_("Total names %d") % matches)
    sdoc.paragraph("")
    stab.write(sdoc)
Ejemplo n.º 9
0
def run(database, document, person):
    """
    Loops through the families that the person is a child in, and display
    the information about the other children.
    """
    global cache
    cache = {}
    # setup the simple access functions
    sdb = SimpleAccess(database)
    sdoc = SimpleDoc(document)
    stab = QuickTable(sdb)
    # display the title
    sdoc.title(_("Descendant Count"))
    sdoc.paragraph("")
    stab.columns(_("Person"), _("Number of Descendants"))
    people = database.get_person_handles(sort_handles=True)
    for person_handle in people:
        result = countem(database, handle2internal(person_handle))
        cache[person_handle] = len(result)
    matches = 0
    for person_handle in cache:
        person = database.get_person_from_handle(person_handle)
        stab.row(person, cache[person_handle])
        matches += 1
    sdoc.paragraph(_("There are %d people.\n") % matches)
    stab.write(sdoc)
Ejemplo n.º 10
0
 def eval(self):
     """
     Execute the query.
     """
     self.sdb = SimpleAccess(self.database)
     self.stab = QuickTable(self.sdb)
     self.select = 0
     start_time = time.time()
     self.process_table(self.stab) # a class that has .row(1, 2, 3, ...)
     if self.select > 0:
         self.stab.columns(*self.clean_titles(self.columns))
         self.sdoc = SimpleDoc(self.document)
         self.sdoc.title(self.query_text)
         self.sdoc.paragraph("\n")
         self.sdoc.paragraph("%d rows processed in %s seconds.\n" % (self.select, time.time() - start_time))
         self.stab.write(self.sdoc)
         self.sdoc.paragraph("")
     return _("%d rows processed in %s seconds.\n") % (self.select, time.time() - start_time)
Ejemplo n.º 11
0
def run_mother(database, document, person):
    """ Function writing the mother lineage quick report
    """
    sa = SimpleAccess(database)
    sd = SimpleDoc(document)

    # display the results

    # feature request 2356: avoid genitive form
    sd.title(_("Mother lineage for %s") % sa.name(person))
    sd.paragraph("")
    sd.paragraph(
        _(""
          "This report shows the mother lineage, also called matronymic lineage "
          "mtDNA lineage."
          " People in this lineage all share the same Mitochondrial DNA (mtDNA)."
          ))
    sd.paragraph("")

    stab = QuickTable(sa)
    stab.columns(_("Name Mother"), _("Birth"), _("Death Date"), _("Remark"))
    make_details(Person.FEMALE, person, sa, sd, database, stab)
    stab.write(sd)
    sd.paragraph("")

    if person.gender == Person.MALE:
        return

    sd.header2((_("Direct line female descendants")))
    sd.paragraph("")

    make_details_child(Person.FEMALE, person, sa, sd, database)
Ejemplo n.º 12
0
def run(database, document, repo):
    """
    Display back-references (sources) for this repository.
    """

    # setup the simple access functions

    sdb = SimpleAccess(database)
    sdoc = SimpleDoc(document)
    stab = QuickTable(sdb)

    # First we find repository and add its text

    sdoc.title('%s\n' % repo.get_name())

    # Go over all the sources that refer to this repository

    repo_handle = repo.handle
    source_list = [item[1] for item in
                   database.find_backlink_handles(repo_handle, ['Source'
                   ])]

    stab.columns(_("Source"), _("Type of media"), _("Call number"))
    document.has_data = False
    for source_handle in source_list:
        src = database.get_source_from_handle(source_handle)

        # Get the list of references from this source to our repo
        # (can be more than one, technically)

        for reporef in src.get_reporef_list():
            if reporef.ref == repo_handle:

                # Determine the text for this source

                media = str(reporef.get_media_type())
                call = reporef.get_call_number()

                stab.row(src.get_title(), media, call)
                document.has_data = True
    if document.has_data:
        stab.write(sdoc)
    else:
        sdoc.header1(_("Not found"))
Ejemplo n.º 13
0
def run(database, document, obj):
    """
    Display link references for this note.
    """

    # setup the simple access functions
    sdb = SimpleAccess(database)
    sdoc = SimpleDoc(document)
    stab = QuickTable(sdb)

    # display the title
    sdoc.title(_("Link References for this note"))
    sdoc.paragraph("\n")
    stab.columns(_("Type"), _("Reference"), _("Link check"))

    for (ldomain, ltype, lprop, lvalue) in obj.get_links():
        if ldomain == "gramps":
            tagtype = _(ltype)
            ref_obj = sdb.get_link(ltype, lprop, lvalue)
            if ref_obj:
                tagvalue = ref_obj
                tagcheck = _("Ok")
            else:
                tagvalue = styledtext_tag.value
                tagcheck = _("Failed: missing object")
        else:
            tagtype = _("Internet")
            tagvalue = lvalue
            tagcheck = ""
        stab.row(tagtype, tagvalue, tagcheck)

    if stab.get_row_count() > 0:
        stab.write(sdoc)
        document.has_data = True
    else:
        sdoc.paragraph(_("No link references for this note"))
        sdoc.paragraph("")
        document.has_data = False
    sdoc.paragraph("")
Ejemplo n.º 14
0
def run_given(database, document, person):
    """
    Loops through the families that the person is a child in, and displays
    the information about the other children.
    """
    # setup the simple access functions
    sdb = SimpleAccess(database)
    sdoc = SimpleDoc(document)
    stab = QuickTable(sdb)
    if isinstance(person, Person):
        rgivenname = person.get_primary_name().get_first_name()
    else:
        rgivenname = person
    if " " in rgivenname.strip():
        rgivenname, second = rgivenname.strip().split(" ", 1)
    # display the title
    sdoc.title(_("People with the given name '%s'") % rgivenname)
    sdoc.paragraph("")
    stab.columns(_("Person"), _("Birth Date"), _("Name type"))
    filter = GenericFilterFactory('Person')()
    if rgivenname != '':
        rule = SameGiven([rgivenname])
    else:
        rule = IncompleteGiven([])
    filter.add_rule(rule)
    people = filter.apply(database, database.iter_person_handles())

    matches = 0
    for person_handle in people:
        person = database.get_person_from_handle(person_handle)
        stab.row(person, sdb.birth_or_fallback(person),
                 str(person.get_primary_name().get_type()))
        matches += 1

    document.has_data = matches > 0
    sdoc.paragraph(
        # Translators: leave all/any {...} untranslated
        ngettext(
            "There is {number_of} person "
            "with a matching name, or alternate name.\n",
            "There are {number_of} people "
            "with a matching name, or alternate name.\n",
            matches).format(number_of=matches))
    stab.write(sdoc)
Ejemplo n.º 15
0
 def eval(self):
     """
     Execute the query.
     """
     self.sdb = SimpleAccess(self.database)
     self.stab = QuickTable(self.sdb)
     self.select = 0
     start_time = time.time()
     self.process_table(self.stab) # a class that has .row(1, 2, 3, ...)
     if self.select > 0:
         self.stab.columns(*self.clean_titles(self.columns))
         self.sdoc = SimpleDoc(self.document)
         self.sdoc.title(self.query_text)
         self.sdoc.paragraph("\n")
         self.sdoc.paragraph("%d rows processed in %s seconds.\n" % (self.select, time.time() - start_time))
         self.stab.write(self.sdoc)
         self.sdoc.paragraph("")
     return _("%d rows processed in %s seconds.\n") % (self.select, time.time() - start_time)
def run(database, document, person):
    """Handle quick view report generation."""
    sdoc = SimpleDoc(document)
    name = gramps.gen.display.name.displayer.display(person)

    sdoc.title(_("Number of %s's ancestors") % name)
    sdoc.paragraph("")

    stab = QuickTable(document)
    stab.columns(_("Generation"), _("Found"), _("Theoretical"), _("Percent"))

    num_lst = count_ancestors(database, person)
    for entry in num_lst[1:-1]:
        stab.row(*entry)

    stab.write(sdoc)
    vals = num_lst[-1][1:]
    sdoc.paragraph(
        _("There were {} of {} ancestors ({}) found.\n"
          "Only individual ancestors were counted. Duplicates "
          "caused by pedigree collapse were ignored.").format(*vals))
Ejemplo n.º 17
0
def run(database, document, attribute, value=None):
    sdb = SimpleAccess(database)
    sdoc = SimpleDoc(document)
    stab = QuickTable(sdb)
    sdoc.title(_("People who have the '%s' Attribute") % attribute)
    sdoc.paragraph("")
    stab.columns(_("Person"), str(attribute))
    matches = 0
    for person_handle in database.iter_person_handles():
        person = database.get_person_from_handle(person_handle)
        matched = False
        for attr in person.attribute_list:
            if str(attr.type) == attribute:
                stab.row(person, str(attr.get_value()))
                matched = True
        if matched:
            matches += 1
    document.has_data = matches > 0
    sdoc.paragraph(
        _("There are %d people with a matching attribute name.\n") % matches)
    stab.write(sdoc)
Ejemplo n.º 18
0
def run(database, document, person):
    """
    Loops through the families that the person is a child in, and displays
    the information about the other children.
    """
    # setup the simple access functions
    sdb = SimpleAccess(database)
    sdoc = SimpleDoc(document)
    stab = QuickTable(sdb)
    if isinstance(person, Person):
        surname = sdb.surname(person)
        rsurname = person.get_primary_name().get_group_name()
    else:
        surname = person
        rsurname = person
    # display the title
    sdoc.title(_("People sharing the surname '%s'") % surname)
    sdoc.paragraph("")
    stab.columns(_("Person"), _("Birth Date"), _("Name type"))
    filter = GenericFilterFactory('Person')()
    if rsurname != '':
        rule = SameSurname([rsurname])
    else:
        rule = IncompleteSurname([])
    filter.add_rule(rule)
    people = filter.apply(database,
                          database.iter_person_handles())

    matches = 0
    for person_handle in people:
        person = database.get_person_from_handle(person_handle)
        stab.row(person, sdb.birth_or_fallback(person),
                 str(person.get_primary_name().get_type()))
        matches += 1

    document.has_data = matches > 0
    sdoc.paragraph(
        # translators: leave all/any {...} untranslated
        ngettext("There is {number_of} person "
                     "with a matching name, or alternate name.\n",
                 "There are {number_of} people "
                     "with a matching name, or alternate name.\n", matches
                ).format(number_of=matches) )
    stab.write(sdoc)
Ejemplo n.º 19
0
def run(database, document, obj):
    """
    Display link references for this note.
    """

    # setup the simple access functions
    sdb = SimpleAccess(database)
    sdoc = SimpleDoc(document)
    stab = QuickTable(sdb)

    # display the title
    sdoc.title(_("Link References for this note"))
    sdoc.paragraph("\n")
    stab.columns(_("Type"), _("Reference"), _("Link check"))

    for (ldomain, ltype, lprop, lvalue) in obj.get_links():
            if ldomain == "gramps":
                tagtype = _(ltype)
                ref_obj = sdb.get_link(ltype, lprop, lvalue)
                if ref_obj:
                    tagvalue = ref_obj
                    tagcheck = _("Ok")
                else:
                    tagvalue = lvalue
                    tagcheck = _("Failed: missing object")
            else:
                tagtype = _("Internet")
                tagvalue = lvalue
                tagcheck = ""
            stab.row(tagtype, tagvalue, tagcheck)

    if stab.get_row_count() > 0:
        stab.write(sdoc)
        document.has_data = True
    else:
        sdoc.paragraph(_("No link references for this note"))
        sdoc.paragraph("")
        document.has_data = False
    sdoc.paragraph("")
Ejemplo n.º 20
0
def run(database, document, attribute, value=None):
    sdb = SimpleAccess(database)
    sdoc = SimpleDoc(document)
    stab = QuickTable(sdb)
    sdoc.title(_("People who have the '%s' Attribute") % attribute)
    sdoc.paragraph("")
    stab.columns(_("Person"), str(attribute))
    matches = 0
    for person_handle in database.iter_person_handles():
        person = database.get_person_from_handle(person_handle)
        matched = False
        for attr in person.attribute_list:
            if str(attr.type) == attribute:
                stab.row(person, str(attr.get_value()))
                matched = True
        if matched:
            matches += 1
    document.has_data = matches > 0
    sdoc.paragraph(_("There are %d people with a matching attribute name.\n") % matches)
    stab.write(sdoc)
Ejemplo n.º 21
0
def run(database, document, person):
    """
    Loops through the families that the person is a child in, and display
    the information about the other children.
    """
    # setup the simple access functions
    sdb = SimpleAccess(database)
    sdoc = SimpleDoc(document)
    stab = QuickTable(sdb)
    rel_class = get_relationship_calculator(glocale)

    # display the title
    # feature request 2356: avoid genitive form
    sdoc.title(_("Siblings of %s") % sdb.name(person))
    sdoc.paragraph("")
    stab.columns(_("Sibling"), _("Gender"), _("Birth Date"), _("Type"))
    # grab our current id (self):
    gid = sdb.gid(person)
    # loop through each family in which the person is a child
    document.has_data = False
    for family in sdb.child_in(person):
        # loop through each child in the family
        for child in sdb.children(family):
            # only display if this child is not the active person
            if sdb.gid(child) != gid:
                rel_str = rel_class.get_sibling_relationship_string(
                    rel_class.get_sibling_type(database, person, child),
                    person.get_gender(), child.get_gender())
            else:
                rel_str = _('self')
            # pass row the child object to make link:
            stab.row(child,
                     sdb.gender(child),
                     sdb.birth_or_fallback(child),
                     rel_str)
            document.has_data = True
    if document.has_data:
        stab.write(sdoc)
    else:
        sdoc.header1(_("Not found") + "\n")
Ejemplo n.º 22
0
def run(database, document, person):
    """
    Loops through the person events and the family events of any family
    in which the person is a parent (to catch Marriage events), displaying
    the basic details of the event
    """

    sdb = SimpleAccess(database)
    sdoc = SimpleDoc(document)
    stab = QuickTable(sdb)

    # get the personal events
    event_list = sdb.events(person)

    # get the events of each family in which the person is
    # a parent
    for family in sdb.parent_in(person):
        event_list += sdb.events(family)

    # Sort the events by their date
    event_list.sort(key=lambda x: x.get_date_object())

    # display the results

    # feature request 2356: avoid genitive form
    sdoc.title(_("Sorted events of %s") % sdb.name(person))
    sdoc.paragraph("")

    stab.columns(_("Event Type"), _("Event Date"), _("Event Place"))
    document.has_data = False
    for event in event_list:
        stab.row(event,
                 sdb.event_date_obj(event),
                 sdb.event_place(event))
        document.has_data = True
    if document.has_data:
        stab.write(sdoc)
    else:
        sdoc.header1(_("Not found"))
Ejemplo n.º 23
0
def run(database, document, date):
    """
    Display people probably alive and their ages on a particular date.
    """
    # setup the simple access functions
    sdb = SimpleAccess(database)
    sdoc = SimpleDoc(document)
    stab = QuickTable(sdb)
    if not date.get_valid():
        sdoc.paragraph("Date is not a valid date.")
        return
    # display the title
    if date.get_day_valid():
        sdoc.title(_("People and their ages the %s") %
               displayer.display(date))
    else:
        sdoc.title(_("People and their ages on %s") %
               displayer.display(date))
    stab.columns(_("Person"), _("Age"), _("Status")) # Actual Date makes column unicode
    alive_matches = 0
    dead_matches = 0
    for person in sdb.all_people():
        alive, birth, death, explain, relative = \
            probably_alive(person, database, date, return_range=True)
        # Doesn't show people probably alive but no way of figuring an age:
        if alive:
            if birth:
                diff_span = (date - birth)
                stab.row(person, str(diff_span), _("Alive: %s") % explain)
                stab.row_sort_val(1, int(diff_span))
            else:
                stab.row(person, "", _("Alive: %s") % explain)
                stab.row_sort_val(1, 0)
            alive_matches += 1
        else: # not alive
            if birth:
                diff_span = (date - birth)
                stab.row(person, str(diff_span), _("Deceased: %s") % explain)
                stab.row_sort_val(1, int(diff_span))
            else:
                stab.row(person, "", _("Deceased: %s") % explain)
                stab.row_sort_val(1, 1)
            dead_matches += 1

    document.has_data = (alive_matches + dead_matches) > 0
    sdoc.paragraph(_("\nLiving matches: %(alive)d, "
                     "Deceased matches: %(dead)d\n") %
                         {'alive' : alive_matches, 'dead' : dead_matches})
    if document.has_data:
        stab.write(sdoc)
    sdoc.paragraph("")
Ejemplo n.º 24
0
def run(database, document, main_event):
    """
    Displays events on a specific date of an event (or date)

    Takes an Event or Date object
    """
    if isinstance(main_event, Date):
        main_date = main_event
    else:
        main_date = main_event.get_date_object()

    cal = main_date.get_calendar();

    # setup the simple access functions
    sdb = SimpleAccess(database)
    sdoc = SimpleDoc(document)
    stab = QuickTable(sdb)
    stab.set_link_col(3)
    yeartab = QuickTable(sdb)
    yeartab.set_link_col(3)
    histab = QuickTable(sdb)
    histab.set_link_col(3)

    # display the title
    sdoc.title(_("Events of %(date)s") %
               {"date": sdb.date_string(main_date)})
    sdoc.paragraph("")
    stab.columns(_("Date"), _("Type"), _("Place"), _("Reference"))
    yeartab.columns(_("Date"), _("Type"), _("Place"), _("Reference"))
    histab.columns(_("Date"), _("Type"), _("Place"), _("Reference"))

    for event in database.iter_events():
        date = event.get_date_object()
        date.convert_calendar(cal)
        if date.get_year() == 0:
            continue
        if (date.get_year() == main_date.get_year() and
            date.get_month() == main_date.get_month() and
            date.get_day() == main_date.get_day()):
            for (objclass, handle) in database.find_backlink_handles(event.handle):
                ref = get_ref(database, objclass, handle)
                stab.row(date,
                         sdb.event_type(event),
                         sdb.event_place(event), ref)
        elif (date.get_month() == main_date.get_month() and
              date.get_day() == main_date.get_day() and
              date.get_month() != 0):
            for (objclass, handle) in database.find_backlink_handles(event.handle):
                ref = get_ref(database, objclass, handle)
                histab.row(date,
                           sdb.event_type(event),
                           sdb.event_place(event), ref)
        elif (date.get_year() == main_date.get_year()):
            for (objclass, handle) in database.find_backlink_handles(event.handle):
                ref = get_ref(database, objclass, handle)
                yeartab.row(date,
                            sdb.event_type(event),
                            sdb.event_place(event), ref)

    document.has_data = False
    if stab.get_row_count() > 0:
        document.has_data = True
        sdoc.paragraph(_("Events on this exact date"))
        stab.write(sdoc)
    else:
        sdoc.paragraph(_("No events on this exact date"))
        sdoc.paragraph("")
    sdoc.paragraph("")

    if histab.get_row_count() > 0:
        document.has_data = True
        sdoc.paragraph(_("Other events on this month/day in history"))
        histab.write(sdoc)
    else:
        sdoc.paragraph(_("No other events on this month/day in history"))
        sdoc.paragraph("")
    sdoc.paragraph("")

    if yeartab.get_row_count() > 0:
        document.has_data = True
        sdoc.paragraph(_("Other events in %(year)d") %
                       {"year":main_date.get_year()})
        yeartab.write(sdoc)
    else:
        sdoc.paragraph(_("No other events in %(year)d") %
                       {"year":main_date.get_year()})
        sdoc.paragraph("")
    sdoc.paragraph("")
Ejemplo n.º 25
0
def run(database, document, object, item='place', trans=_("Place")):
    """
    Display back-references for this object.
    """

    # setup the simple access functions
    sdb = SimpleAccess(database)
    sdoc = SimpleDoc(document)
    stab = QuickTable(sdb)

    # hold a person-event dictionary
    pedic = defaultdict(list)
    for pe in database.get_person_handles():
        for eventref in database.get_person_from_handle(pe).event_ref_list:
            pedic[eventref.ref].append((eventref.get_role(), pe))
    #for ev in pedic.keys():
    #    print(ev,pedic[ev])

    # display the title
    sdoc.title(_("References for this %s") % trans)
    sdoc.paragraph("\n")
    stab.columns(_("Type"), _("Reference"), _("Date"), _("Persons"))
    


    # get the events
    event_handle_list = [handle for (objclass, handle) in database.find_backlink_handles(object.handle)]
    
    #    ref = get_ref(database, objclass, handle)
    #    #print(ref,pedic[handle])
    #    line=''
    #    for i, (role, personhandle) in enumerate(pedic[handle]):
    #        line = line + ' ' + (
    #                f'{i} {role} {_nd.display(database.get_person_from_handle(personhandle))} '
    #                f'[{database.get_person_from_handle(personhandle).get_gramps_id()}]'
    #                )
    #    e_date = ref.get_date_object()
    #    s_date = ref.get_date_object().get_sort_value()
    #    event_list += [s_date, _(objclass), ref, e_date, line]


    # Sort the events by their date
    event_handle_list.sort(key=lambda x: database.get_event_from_handle(x).get_date_object().get_sort_value())
    print(len(event_handle_list))
    for handle in event_handle_list:
        print(database.get_event_from_handle(handle), pedic[handle], database.get_event_from_handle(handle).get_date_object())

        line=''
        for i, (role, personhandle) in enumerate(pedic[handle]):
            line = line + ' ' + (
                    f'{i} {role} {_nd.display(database.get_person_from_handle(personhandle))} '
                    f'[{database.get_person_from_handle(personhandle).get_gramps_id()}]'
                    )
        stab.row(database.get_event_from_handle(handle).get_description(), database.get_event_from_handle(handle), database.get_event_from_handle(handle).get_date_object(), line)  # translation are explicit (above)

    if stab.get_row_count() > 0:
        document.has_data = True
#        stab.sort(_("Date"))
        stab.write(sdoc)
    else:
        document.has_data = False
        sdoc.paragraph(_("No references for this %s") % trans)
        sdoc.paragraph("")
    sdoc.paragraph("")
    def run(self):
        BUTTONS = ((_("Select All"), self.select_all),
                   (_("Select None"), self.select_none),
                   (_("Toggle Selection"), self.toggle_select),
                   (_("Add Selected Events"), self.apply_selection),
                   )

        if hasattr(self, "table") and self.table:
            self.reselect = False
            if self.options.handler.options_dict['remove']:
                QuestionDialog(_("Remove Events, Notes, and Source and Reselect Data"),
                               _("Are you sure you want to remove previous events, notes, and source and reselect data?"),
                               _("Remove and Run Select Again"),
                               self.set_reselect,
                               self.window)
            else:
                QuestionDialog(_("Reselect Data"),
                               _("Are you sure you want to reselect data?"),
                               _("Run Select Again"),
                               self.set_reselect,
                               self.window)
            if not self.reselect:
                return

        current_date = Date()
        current_date.set_yr_mon_day(*time.localtime(time.time())[0:3])
        self.action = {}
        widget = self.add_results_frame(_("Select"))
        document = TextBufDoc(make_basic_stylesheet(), None)
        document.dbstate = self.dbstate
        document.uistate = self.uistate
        document.open("", container=widget)
        self.sdb = SimpleAccess(self.db)
        sdoc = SimpleDoc(document)
        stab = QuickTable(self.sdb)
        self.table = stab
        stab.columns(_("Select"), _("Person"), _("Action"),
                     _("Birth Date"), _("Death Date"),
                     _("Evidence"), _("Relative"))
        self.results_write(_("Processing...\n"))
        self.filter_option =  self.options.menu.get_option_by_name('filter')
        self.filter = self.filter_option.get_filter() # the actual filter
        people = self.filter.apply(self.db,
                                   self.db.iter_person_handles())
        num_people = self.db.get_number_of_people()
        source_text = self.options.handler.options_dict['source_text']
        source = None
        add_birth = self.options.handler.options_dict['add_birth']
        add_death = self.options.handler.options_dict['add_death']
        remove_old = self.options.handler.options_dict['remove']

        self.MAX_SIB_AGE_DIFF = self.options.handler.options_dict['MAX_SIB_AGE_DIFF']
        self.MAX_AGE_PROB_ALIVE = self.options.handler.options_dict['MAX_AGE_PROB_ALIVE']
        self.AVG_GENERATION_GAP = self.options.handler.options_dict['AVG_GENERATION_GAP']
        if remove_old:
            with DbTxn("", self.db, batch=True) as self.trans:
                self.db.disable_signals()
                self.results_write(_("Removing old estimations... "))
                self.progress.set_pass((_("Removing '%s'...") % source_text),
                                       num_people)
                supdate = None
                for person_handle in people:
                    self.progress.step()
                    pupdate = 0
                    person = self.db.get_person_from_handle(person_handle)
                    birth_ref = person.get_birth_ref()
                    if birth_ref:
                        birth = self.db.get_event_from_handle(birth_ref.ref)
                        for citation_handle in birth.get_citation_list():
                            citation = self.db.get_citation_from_handle(citation_handle)
                            source_handle = citation.get_reference_handle()
                            #print "birth handle:", source_handle
                            source = self.db.get_source_from_handle(source_handle)
                            if source:
                                if source.get_title() == source_text:
                                    #print("birth event removed from:",
                                    #      person.gramps_id)
                                    person.set_birth_ref(None)
                                    person.remove_handle_references('Event',[birth_ref.ref])
                                    # remove note
                                    note_list = birth.get_referenced_note_handles()
                                    birth.remove_handle_references('Note',
                                      [note_handle for (obj_type, note_handle) in note_list])
                                    for (obj_type, note_handle) in note_list:
                                        self.db.remove_note(note_handle, self.trans)
                                    self.db.remove_event(birth_ref.ref, self.trans)
                                    self.db.remove_citation(citation_handle,
                                                            self.trans)
                                    pupdate = 1
                                    supdate = source  # found the source.
                                    break
                    death_ref = person.get_death_ref()
                    if death_ref:
                        death = self.db.get_event_from_handle(death_ref.ref)
                        for citation_handle in death.get_citation_list():
                            citation = self.db.get_citation_from_handle(citation_handle)
                            source_handle = citation.get_reference_handle()
                            #print "death handle:", source_handle
                            source = self.db.get_source_from_handle(source_handle)
                            if source:
                                if source.get_title() == source_text:
                                    #print("death event removed from:",
                                    #      person.gramps_id)
                                    person.set_death_ref(None)
                                    person.remove_handle_references('Event',[death_ref.ref])
                                    # remove note
                                    note_list = death.get_referenced_note_handles()
                                    death.remove_handle_references('Note',
                                      [note_handle for (obj_type, note_handle) in note_list])
                                    for (obj_type, note_handle) in note_list:
                                        self.db.remove_note(note_handle, self.trans)
                                    self.db.remove_event(death_ref.ref, self.trans)
                                    self.db.remove_citation(citation_handle,
                                                            self.trans)
                                    pupdate = 1
                                    supdate = source  # found the source.
                                    break
                    if pupdate == 1:
                        self.db.commit_person(person, self.trans)
                if supdate:
                    self.db.remove_source(supdate.handle, self.trans)
            self.results_write(_("done!\n"))
            self.db.enable_signals()
            self.db.request_rebuild()
        if add_birth or add_death:
            self.results_write(_("Selecting... \n\n"))
            self.progress.set_pass(_('Selecting...'),
                                   num_people)
            row = 0
            for person_handle in people:
                self.progress.step()
                person = self.db.get_person_from_handle(person_handle)
                birth_ref = person.get_birth_ref()
                death_ref = person.get_death_ref()
                add_birth_event, add_death_event = False, False
                if not birth_ref or not death_ref:
                    date1, date2, explain, other = self.calc_estimates(person)
                    if birth_ref:
                        ev = self.db.get_event_from_handle(birth_ref.ref)
                        date1 = ev.get_date_object()
                    elif not birth_ref and add_birth and date1:
                        if date1.match( current_date, "<"):
                            add_birth_event = True
                            date1.make_vague()
                        else:
                            date1 = Date()
                    else:
                        date1 = Date()
                    if death_ref:
                        ev = self.db.get_event_from_handle(death_ref.ref)
                        date2 = ev.get_date_object()
                    elif not death_ref and add_death and date2:
                        if date2.match( current_date, "<"):
                            add_death_event = True
                            date2.make_vague()
                        else:
                            date2 = Date()
                    else:
                        date2 = Date()
                    # Describe
                    if add_birth_event and add_death_event:
                        action = _("Add birth and death events")
                    elif add_birth_event:
                        action = _("Add birth event")
                    elif add_death_event:
                        action = _("Add death event")
                    else:
                        continue
                    #stab.columns(_("Select"), _("Person"), _("Action"),
                    # _("Birth Date"), _("Death Date"), _("Evidence"), _("Relative"))
                    if add_birth == 1 and not birth_ref: # no date
                        date1 = Date()
                    if add_death == 1 and not death_ref: # no date
                        date2 = Date()
                    if person == other:
                        other = None
                    stab.row("checkbox",
                             person,
                             action,
                             date1,
                             date2,
                             explain or "",
                             other or "")
                    if add_birth_event:
                        stab.set_cell_markup(3, row, "<b>%s</b>" % date_displayer.display(date1))
                    if add_death_event:
                        stab.set_cell_markup(4, row, "<b>%s</b>" % date_displayer.display(date2))
                    self.action[person.handle] = (add_birth_event, add_death_event)
                    row += 1
            if row > 0:
                self.results_write("  ")
                for text, function in BUTTONS:
                    self.make_button(text, function, widget)
                self.results_write("\n")
                stab.write(sdoc)
                self.results_write("  ")
                for text, function in BUTTONS:
                    self.make_button(text, function, widget)
                self.results_write("\n")
            else:
                self.results_write(_("No events to be added."))
                self.results_write("\n")
        self.results_write("\n")
        self.set_current_frame(_("Select"))
Ejemplo n.º 27
0
def run(database, document, person):
    """
    Display a person's timeline.
    """
    sa = SimpleAccess(database)
    sd = SimpleDoc(document)
    sd.title(_("Timeline for %s") % sa.name(person))
    sd.paragraph("")
    stab = QuickTable(sa)
    stab.columns(_("Date"), 
                 _("Event"), 
                 _("Age"), 
                 _("Place"), 
                 _("People involved"))
    stab.set_link_col(4)

    handled = {}
    birth_ref = gramps.gen.lib.Person.get_birth_ref(person)
    birth_date = get_event_date_from_ref(database, birth_ref)
    event_list = []

    process(database, sa, event_list, handled, person, False, person)

    for (event, obj, desc) in sorted(event_list, key=by_date):
        edate = sa.event_date_obj(event)
        span_str, span_int = format_date(birth_date, edate, obj == person)
        if desc == None:
            desc = event
        stab.row(edate,
                 desc,
                 span_str,
                 sa.event_place(event),
                 obj)
        stab.row_sort_val(2, span_int)
    today = Today()
    span_str, span_int = format_date(birth_date, today, False)
    stab.row(today, _("Today"), span_str, "", person)
    stab.row_sort_val(2, span_int)
    stab.write(sd)
    sd.paragraph("")
Ejemplo n.º 28
0
def run(database, document, person):

    sdoc = SimpleDoc(document)

    name = gramps.gen.display.name.displayer.display(person)
    death_date = _get_date(database, person.get_death_ref())

    sdoc.title(_("Number of %s's descendants") % name)
    sdoc.paragraph("")

    total    = []
    seen     = []
    outlived = []
    alive    = []
    handles  = []

    _count_descendants(database, person, death_date, 0,
            total, seen, outlived, alive, handles)

    # Bring all lists to the same length. No list can be longer than "total".
    while len(seen) < len(total):
        seen.append(0)
    while len(outlived) < len(total):
        outlived.append(0)
    while len(alive) < len(total):
        alive.append(0)

    rel_calc = get_relationship_calculator()

    stab = QuickTable(document)
    if death_date:
        stab.columns(
                _("Generation"),
                _("Total"),
                _("Seen"),
                _("Outlived"),
                _("Now alive"))
    else:
        stab.columns(
                _("Generation"),
                _("Total"),
                _("Now alive"))
    n = 0
    for (a, b, c, d, h) in zip(total, seen, outlived, alive, handles):
        n += 1
        generation = rel_calc.get_plural_relationship_string(0, n)
        if death_date:
            # stab.row([generation, "PersonList"] + h, a, b, c, d) # Needs 3.2
            stab.row(generation, a, b, c, d)
        else:
            # stab.row([generation, "PersonList"] + h, a, d) # Needs 3.2
            stab.row(generation, a, d)
        stab.row_sort_val(0, n)

    if death_date:
        # stab.row([_("Total"), "PersonList"] + sum(handles, []), # Needs 3.2
        stab.row(_("Total"),
                 sum(total), sum(seen), sum(outlived), sum(alive))
    else:
        # stab.row([_("Total"), "PersonList"] + sum(handles, []), # Needs 3.2
        stab.row(_("Total"),
                 sum(total), sum(alive))
    stab.row_sort_val(0, n + 1)

    stab.write(sdoc)

    if death_date:
        sdoc.paragraph(_("Seen = number of descendants whose birth %s has "
            "lived to see") % name)
        sdoc.paragraph(_("Outlived = number of descendants who died while %s "
            "was still alive") % name)
    def run(self):
        BUTTONS = ((_("Select All"), self.select_all),
                   (_("Select None"), self.select_none),
                   (_("Toggle Selection"), self.toggle_select),
                   (_("Add Selected Events"), self.apply_selection),
                   )

        if hasattr(self, "table") and self.table:
            self.reselect = False
            if self.options.handler.options_dict['remove']:
                QuestionDialog(_("Remove Events, Notes, and Source and Reselect Data"),
                               _("Are you sure you want to remove previous events, notes, and source and reselect data?"),
                               _("Remove and Run Select Again"),
                               self.set_reselect,
                               self.window)
            else:
                QuestionDialog(_("Reselect Data"),
                               _("Are you sure you want to reselect data?"),
                               _("Run Select Again"),
                               self.set_reselect,
                               self.window)
            if not self.reselect:
                return

        current_date = Date()
        current_date.set_yr_mon_day(*time.localtime(time.time())[0:3])
        self.action = {}
        widget = self.add_results_frame(_("Select"))
        document = TextBufDoc(make_basic_stylesheet(), None)
        document.dbstate = self.dbstate
        document.uistate = self.uistate
        document.open("", container=widget)
        self.sdb = SimpleAccess(self.db)
        sdoc = SimpleDoc(document)
        stab = QuickTable(self.sdb)
        self.table = stab
        stab.columns(_("Select"), _("Person"), _("Action"),
                     _("Birth Date"), _("Death Date"),
                     _("Evidence"), _("Relative"))
        self.results_write(_("Processing...\n"))
        self.filter_option =  self.options.menu.get_option_by_name('filter')
        self.filter = self.filter_option.get_filter() # the actual filter
        people = self.filter.apply(self.db,
                                   self.db.iter_person_handles())
        num_people = self.db.get_number_of_people()
        source_text = self.options.handler.options_dict['source_text']
        source = None
        add_birth = self.options.handler.options_dict['add_birth']
        add_death = self.options.handler.options_dict['add_death']
        remove_old = self.options.handler.options_dict['remove']

        self.MAX_SIB_AGE_DIFF = self.options.handler.options_dict['MAX_SIB_AGE_DIFF']
        self.MAX_AGE_PROB_ALIVE = self.options.handler.options_dict['MAX_AGE_PROB_ALIVE']
        self.AVG_GENERATION_GAP = self.options.handler.options_dict['AVG_GENERATION_GAP']
        if remove_old:
            with DbTxn("", self.db, batch=True) as self.trans:
                self.db.disable_signals()
                self.results_write(_("Removing old estimations... "))
                self.progress.set_pass((_("Removing '%s'...") % source_text),
                                       num_people)
                for person_handle in people:
                    self.progress.step()
                    pupdate = 0
                    person = self.db.get_person_from_handle(person_handle)
                    birth_ref = person.get_birth_ref()
                    if birth_ref:
                        birth = self.db.get_event_from_handle(birth_ref.ref)
                        for citation_handle in birth.get_citation_list():
                            citation = self.db.get_citation_from_handle(citation_handle)
                            source_handle = citation.get_reference_handle()
                            #print "birth handle:", source_handle
                            source = self.db.get_source_from_handle(source_handle)
                            if source:
                                #print "birth source:", source, source.get_title()
                                if source.get_title() == source_text:
                                    person.set_birth_ref(None)
                                    person.remove_handle_references('Event',[birth_ref.ref])
                                    # remove note
                                    note_list = birth.get_referenced_note_handles()
                                    birth.remove_handle_references('Note',
                                      [note_handle for (obj_type, note_handle) in note_list])
                                    for (obj_type, note_handle) in note_list:
                                        self.db.remove_note(note_handle, self.trans)
                                    self.db.remove_event(birth_ref.ref, self.trans)
                                    self.db.commit_source(source, self.trans)
                                    pupdate = 1
                                    break
                    death_ref = person.get_death_ref()
                    if death_ref:
                        death = self.db.get_event_from_handle(death_ref.ref)
                        for citation_handle in death.get_citation_list():
                            citation = self.db.get_citation_from_handle(citation_handle)
                            source_handle = citation.get_reference_handle()
                            #print "death handle:", source_handle
                            source = self.db.get_source_from_handle(source_handle)
                            if source:
                                #print "death source:", source, source.get_title()
                                if source.get_title() == source_text:
                                    person.set_death_ref(None)
                                    person.remove_handle_references('Event',[death_ref.ref])
                                    # remove note
                                    note_list = death.get_referenced_note_handles()
                                    birth.remove_handle_references('Note',
                                      [note_handle for (obj_type, note_handle) in note_list])
                                    for (obj_type, note_handle) in note_list:
                                        self.db.remove_note(note_handle, self.trans)
                                    self.db.remove_event(death_ref.ref, self.trans)
                                    self.db.commit_source(source, self.trans)
                                    pupdate = 1
                                    break
                    if pupdate == 1:
                        self.db.commit_person(person, self.trans)
                if source:
                    self.db.remove_source(source.handle, self.trans)
                self.results_write(_("done!\n"))
                self.db.enable_signals()
                self.db.request_rebuild()
        if add_birth or add_death:
            self.results_write(_("Selecting... \n\n"))
            self.progress.set_pass(_('Selecting...'),
                                   num_people)
            row = 0
            for person_handle in people:
                self.progress.step()
                person = self.db.get_person_from_handle(person_handle)
                birth_ref = person.get_birth_ref()
                death_ref = person.get_death_ref()
                add_birth_event, add_death_event = False, False
                if not birth_ref or not death_ref:
                    date1, date2, explain, other = self.calc_estimates(person)
                    if birth_ref:
                        ev = self.db.get_event_from_handle(birth_ref.ref)
                        date1 = ev.get_date_object()
                    elif not birth_ref and add_birth and date1:
                        if date1.match( current_date, "<"):
                            add_birth_event = True
                            date1.make_vague()
                        else:
                            date1 = Date()
                    else:
                        date1 = Date()
                    if death_ref:
                        ev = self.db.get_event_from_handle(death_ref.ref)
                        date2 = ev.get_date_object()
                    elif not death_ref and add_death and date2:
                        if date2.match( current_date, "<"):
                            add_death_event = True
                            date2.make_vague()
                        else:
                            date2 = Date()
                    else:
                        date2 = Date()
                    # Describe
                    if add_birth_event and add_death_event:
                        action = _("Add birth and death events")
                    elif add_birth_event:
                        action = _("Add birth event")
                    elif add_death_event:
                        action = _("Add death event")
                    else:
                        continue
                    #stab.columns(_("Select"), _("Person"), _("Action"),
                    # _("Birth Date"), _("Death Date"), _("Evidence"), _("Relative"))
                    if add_birth == 1 and not birth_ref: # no date
                        date1 = Date()
                    if add_death == 1 and not death_ref: # no date
                        date2 = Date()
                    if person == other:
                        other = None
                    stab.row("checkbox",
                             person,
                             action,
                             date1,
                             date2,
                             explain or "",
                             other or "")
                    if add_birth_event:
                        stab.set_cell_markup(3, row, "<b>%s</b>" % date_displayer.display(date1))
                    if add_death_event:
                        stab.set_cell_markup(4, row, "<b>%s</b>" % date_displayer.display(date2))
                    self.action[person.handle] = (add_birth_event, add_death_event)
                    row += 1
            if row > 0:
                self.results_write("  ")
                for text, function in BUTTONS:
                    self.make_button(text, function, widget)
                self.results_write("\n")
                stab.write(sdoc)
                self.results_write("  ")
                for text, function in BUTTONS:
                    self.make_button(text, function, widget)
                self.results_write("\n")
            else:
                self.results_write(_("No events to be added."))
                self.results_write("\n")
        self.results_write("\n")
        self.progress.close()
        self.set_current_frame(_("Select"))
Ejemplo n.º 30
0
def run(database, document, date):
    """
    Display people probably alive and their ages on a particular date.
    """
    # setup the simple access functions
    sdb = SimpleAccess(database)
    sdoc = SimpleDoc(document)
    stab = QuickTable(sdb)
    if not date.get_valid():
        sdoc.paragraph("Date is not a valid date.")
        return
    # display the title
    if date.get_day_valid():
        sdoc.title(_("People and their ages the %s") % displayer.display(date))
    else:
        sdoc.title(_("People and their ages on %s") % displayer.display(date))
    stab.columns(_("Person"), _("Age"),
                 _("Status"))  # Actual Date makes column unicode
    alive_matches = 0
    dead_matches = 0
    for person in sdb.all_people():
        alive, birth, death, explain, relative = \
            probably_alive(person, database, date, return_range=True)
        # Doesn't show people probably alive but no way of figuring an age:
        if alive:
            if birth:
                diff_span = (date - birth)
                stab.row(person, str(diff_span), _("Alive: %s") % explain)
                stab.row_sort_val(1, int(diff_span))
            else:
                stab.row(person, "", _("Alive: %s") % explain)
                stab.row_sort_val(1, 0)
            alive_matches += 1
        else:  # not alive
            if birth:
                diff_span = (date - birth)
                stab.row(person, str(diff_span), _("Deceased: %s") % explain)
                stab.row_sort_val(1, int(diff_span))
            else:
                stab.row(person, "", _("Deceased: %s") % explain)
                stab.row_sort_val(1, 1)
            dead_matches += 1

    document.has_data = (alive_matches + dead_matches) > 0
    sdoc.paragraph(
        _("\nLiving matches: %(alive)d, "
          "Deceased matches: %(dead)d\n") % {
              'alive': alive_matches,
              'dead': dead_matches
          })
    stab.write(sdoc)
    sdoc.paragraph("")
Ejemplo n.º 31
0
class DBI(object):
    """
    The SQL-like interface to the database and document instances.
    """
    def __init__(self, database, document=None):
        self.database = database
        self.document = document
        self.data = {}
        self.select = 0
        self.flat = False
        self.raw = False
        if self.database:
            for name in self.database.get_table_names():
                d = self.database._tables[name]["class_func"]().to_struct()
                self.data[name.lower()] = d.keys()
        # The macros:
        self.shortcuts = {
            "SURNAME": "primary_name.surname_list[0].surname",
            "GIVEN": "primary_name.first_name",
        }

    def parse(self, query):
        """
        Parse the query.
        """
        self.query_text = query.replace("\n", " ").strip()
        lexed = self.lexer(self.query_text)
        #print(lexed)
        self.parser(lexed)
        for col_name in self.columns[:]: # copy
            if col_name == "*":
                self.columns.remove('*')
                # this is useful to see what _class it is:
                self.columns.extend(self.get_columns(self.table))
                # otherwise remove metadata:
                #self.columns.extend([col for col in self.get_columns(self.table) if not col.startswith("_"))

    def lexer(self, string):
        """
        Given a string, break into a list of chunks.
        """
        retval = []
        state = None
        current = ""
        stack = []
        i = 0
        # Handle macros:
        for key in self.shortcuts.keys():
            string = string.replace(key, self.shortcuts[key])
        # (some "expression" in ok)
        # func(some "expression" in (ok))
        # list[1][0]
        # [x for x in list]
        while i < len(string):
            ch = string[i]
            #print("lex:", i, ch, state, retval, current)
            if state == "in-double-quote":
                if ch == '"':
                    state = stack.pop()
                current += ch
            elif state == "in-single-quote":
                if ch == "'":
                    state = stack.pop()
                current += ch
            elif state == "in-expr":
                if ch == ")":
                    state = stack.pop()
                elif ch == "(":
                    stack.append("in-expr")
                current += ch
            elif state == "in-square-bracket":
                if ch == "]":
                    state = stack.pop()
                elif ch == "[":
                    stack.append("in-square-bracket")
                current += ch
            elif ch == '"':
                stack.append(state)
                state = "in-double-quote"
                current += ch
            elif ch == "'":
                stack.append(state)
                state = "in-single-quote"
                current += ch
            elif ch == "(":
                stack.append(state)
                state = "in-expr"
                current += "("
            elif ch == "[":
                stack.append(state)
                state = "in-square-bracket"
                current += "["
            elif ch == ",":
                if current:
                    retval.append(current)
                retval.append(",")
                current = ""
            elif ch == "=":
                if current:
                    retval.append(current)
                retval.append("=")
                current = ""
            elif ch in [' ', '\t', '\n', ";"]: # break
                if current:
                    retval.append(current)
                    if current.upper() == "WHERE":
                        # HACK: get rest of string:
                        if string[-1] == ";":
                            retval.append(string[i + 1:-1])
                            i = len(string) - 2
                        else:
                            retval.append(string[i + 1:])
                            i = len(string) - 1
                    current = ""
                else:
                    pass # ignore whitespace
            else:
                current += ch
            i += 1
        if current:
            retval.append(current)
        #print("lexed:", retval)
        return retval

    def parser(self, lex):
        """
        Takes output of lexer, and sets the values.
        After parser, the DBI will be ready to process query.
        """
        self.action = None
        self.table = None
        self.columns = []
        self.setcolumns = []
        self.values = []
        self.aliases = {}
        self.limit = None
        self.where = None
        self.index = 0
        while self.index < len(lex):
            symbol = lex[self.index]
            if symbol.upper() == "FROM":
                # from table select *;
                self.index += 1
                if self.index < len(lex):
                    self.table = lex[self.index]
            elif symbol.upper() == "SELECT":
                # select a, b from table;
                self.action = "SELECT"
                self.index += 1
                self.columns.append(lex[self.index])
                self.index += 1
                while self.index < len(lex) and lex[self.index].upper() in [",", "AS"]:
                    sep = lex[self.index]
                    if sep == ",":
                        self.index += 1
                        self.columns.append(lex[self.index])
                        self.index += 1
                    elif sep.upper() == "AS":
                        self.index += 1 # alias
                        self.aliases[self.columns[-1]] = lex[self.index]
                        self.index += 1
                self.index -= 1
            elif symbol.upper() == "DELETE":
                # delete from table where item == 1;
                self.action = "DELETE"
                self.columns = ["gramps_id"]
            elif symbol.upper() == "SET":
                # SET x=1, y=2
                self.index += 1
                self.setcolumns.append(lex[self.index]) # first column
                self.index += 1 # equal sign
                # =
                self.index += 1 # value
                self.values.append(lex[self.index])
                self.index += 1 # comma
                while self.index < len(lex) and lex[self.index] == ",":
                    self.index += 1 # next column
                    self.setcolumns.append(lex[self.index])
                    self.index += 1 # equal
                    # =
                    self.index += 1 # value
                    self.values.append(lex[self.index])
                    self.index += 1 # comma?
                self.index -= 1
            elif symbol.upper() == "LIMIT":
                self.index += 1 # after LIMIT
                number = lex[self.index]
                self.index += 1 # maybe a comma
                if self.index < len(lex) and lex[self.index] == ",":
                    self.index += 1 # after ","
                    stop = lex[self.index]
                    self.limit = (int(number), int(stop))
                else:
                    self.limit = (0, int(number))
                    self.index -= 1
            elif symbol.upper() == "WHERE":
                # how can we get all of Python expressions?
                # this assumes all by ;
                self.index += 1
                self.where = lex[self.index]
            elif symbol.upper() == "UPDATE":
                # update table set x=1, y=2 where condition;
                # UPDATE gramps_id set tag_list = Tag("Betty") from person where  "Betty" in primary_name.first_name
                self.columns = ["gramps_id"]
                self.action = "UPDATE"
                if self.index < len(lex):
                    self.index += 1
                    self.table = lex[self.index]
            elif symbol.upper() == "FLAT":
                self.flat = True
            elif symbol.upper() == "EXPAND":
                self.flat = False
            elif symbol.upper() == "RAW":
                self.raw = True
            elif symbol.upper() == "NORAW":
                self.raw = False
            else:
                raise AttributeError("invalid SQL expression: '... %s ...'" % symbol)
            self.index += 1

    def close(self):
        """
        Close up any progress widgets or dialogs.
        """
        #try:
        #    self.progress.close()
        #except:
        pass

    def clean_titles(self, columns):
        """
        Take the columns and turn them into strings for the table.
        """
        retval = []
        for column in columns:
            if column in self.aliases:
                column = self.aliases[column]
            retval.append(column.replace("_", "__"))
        return retval

    def query(self, query):
        self.parse(query)
        self.select = 0
        start_time = time.time()
        class Table():
            results = []
            def row(self, *args, **kwargs):
                self.results.append([args, kwargs])
            def get_rows(self):
                return [list(item[0]) for item in self.results]
        table = Table()
        self.sdb = SimpleAccess(self.database)
        self.process_table(table) # a class that has .row(1, 2, 3, ...)
        print(_("%d rows processed in %s seconds.\n") % (self.select, time.time() - start_time))
        return table

    def eval(self):
        """
        Execute the query.
        """
        self.sdb = SimpleAccess(self.database)
        self.stab = QuickTable(self.sdb)
        self.select = 0
        start_time = time.time()
        self.process_table(self.stab) # a class that has .row(1, 2, 3, ...)
        if self.select > 0:
            self.stab.columns(*self.clean_titles(self.columns))
            self.sdoc = SimpleDoc(self.document)
            self.sdoc.title(self.query_text)
            self.sdoc.paragraph("\n")
            self.sdoc.paragraph("%d rows processed in %s seconds.\n" % (self.select, time.time() - start_time))
            self.stab.write(self.sdoc)
            self.sdoc.paragraph("")
        return _("%d rows processed in %s seconds.\n") % (self.select, time.time() - start_time)

    def get_columns(self, table):
        """
        Get the columns for the given table.
        """
        if self.database:
            retval = self.data[table.lower()]
            return retval # [self.name] + retval
        else:
            return ["*"]

    def process_table(self, table):
        """
        Given a table name, process the query on the elements of the
        table.
        """
        # 'Person', 'Family', 'Source', 'Citation', 'Event', 'Media',
        # 'Place', 'Repository', 'Note', 'Tag'
        # table: a class that has .row(1, 2, 3, ...)
        if self.table == "person":
            self.do_query(self.sdb.all_people(), table)
        elif self.table == "family":
            self.do_query(self.sdb.all_families(), table)
        elif self.table == "event":
            self.do_query(self.sdb.all_events(), table)
        elif self.table == "source":
            self.do_query(self.sdb.all_sources(), table)
        elif self.table == "tag":
            self.do_query(self.sdb.all_tags(), table)
        elif self.table == "citation":
            self.do_query(self.sdb.all_citations(), table)
        elif self.table == "media":
            self.do_query(self.sdb.all_media(), table)
        elif self.table == "place":
            self.do_query(self.sdb.all_places(), table)
        elif self.table == "repository":
            self.do_query(self.sdb.all_repositories(), table)
        elif self.table == "note":
            self.do_query(self.sdb.all_notes(), table)
        else:
            raise AttributeError("no such table: '%s'" % self.table)

    def get_tag(self, name):
        tag = self.database.get_tag_from_name(name)
        if tag is None:
            tag = gramps.gen.lib.Tag()
            tag.set_name(name)
            trans_class = self.database.get_transaction_class()
            with trans_class("QueryQuickview new Tag", self.database, batch=False) as trans:
                self.database.add_tag(tag, trans)
        return Handle("Tag", tag.handle)

    def make_env(self, **kwargs):
        """
        An environment with which to eval elements.
        """
        retval= Environment({
            _("Date"): gramps.gen.lib.date.Date,
            _("Today"): gramps.gen.lib.date.Today(),
            "random": random,
            "re": re,
            "db": self.database,
            "sdb": self.sdb,
            "lib": gramps.gen.lib,
            "_": _,
            "Tag": self.get_tag,
            })
        retval.update(__builtins__)
        retval.update(kwargs)
        return retval

    def stringify(self, value):
        """
        Turn the value into an appropriate string representation.
        """
        if self.raw:
            return value
        if isinstance(value, Struct):
            return self.stringify(value.struct)
        elif isinstance(value, (list, tuple)):
            if len(value) == 0 and not self.flat:
                return ""
            elif len(value) == 1 and not self.flat:
                return self.stringify(value[0])
            else:
                return "[%s]" % (", ".join(map(self.stringify, value)))
        elif isinstance(value, PrimaryObject):
            return value
        else:
            return str(value)

    def clean(self, values, names):
        """
        Given the values and names of columns, change the values
        into string versions for the display table.
        """
        if self.raw:
            return values
        retval = []
        for i in range(len(values)):
            if names[i].endswith("handle"):
                retval.append(repr(values[i].struct["handle"]))
            else:
                retval.append(self.stringify(values[i]))
        return retval

    def do_query(self, items, table):
        """
        Perform the query on the items in the named table.
        """
        # table: a class that has .row(1, 2, 3, ...)
        with self.database.get_transaction_class()("QueryQuickview", self.database, batch=True) as trans:
            ROWNUM = 0
            env = self.make_env()
            for item in items:
                if item is None:
                    continue
                row = []
                row_env = []
                # "col[0]" in WHERE clause will return first column of selection:
                env["col"] = row_env
                env["ROWNUM"] = ROWNUM
                env["object"] = item
                struct = Struct(item.to_struct(), self.database)
                env.set_struct(struct)
                for col in self.columns:
                    try:
                        value = eval(col, env)
                    except:
                        value = None
                    row.append(value)
                    # allow col[#] reference:
                    row_env.append(value)
                    # an alias?
                    if col in self.aliases:
                        env[self.aliases[col]] = value
                # Should we include this row?
                if self.where:
                    try:
                        result = eval(self.where, env)
                    except:
                        continue
                else:
                    if self.action in ["DELETE", "UPDATE"]:
                        result = True
                    else:
                        result = any([col != None for col in row]) # are they all None?
                # If result, then append the row
                if result:
                    if (self.limit is None) or (self.limit[0] <= ROWNUM < self.limit[1]):
                        if self.action == "SELECT":
                            if not self.flat:
                                # Join by rows:
                                products = []
                                columns = []
                                count = 0
                                for col in row:
                                    if ((isinstance(col, Struct) and isinstance(col.struct, list) and len(col.struct) > 0) or
                                        (isinstance(col, list) and len(col) > 0)):
                                        products.append(col)
                                        columns.append(count)
                                    count += 1
                                if len(products) > 0:
                                    current = self.clean(row, self.columns)
                                    for items in itertools.product(*products):
                                        for i in range(len(items)):
                                            current[columns[i]] = self.stringify(items[i])
                                        table.row(*current, link=(item.__class__.__name__, item.handle))
                                        self.select += 1
                                else:
                                    table.row(*self.clean(row, self.columns), link=(item.__class__.__name__, item.handle))
                                    self.select += 1
                            else:
                                table.row(*self.clean(row, self.columns), link=(item.__class__.__name__, item.handle))
                                self.select += 1
                        elif self.action == "UPDATE":
                            # update table set col=val, col=val where expr;
                            table.row(*self.clean(row, self.columns), link=(item.__class__.__name__, item.handle))
                            self.select += 1
                            for i in range(len(self.setcolumns)):
                                struct.setitem(self.setcolumns[i], eval(self.values[i], env), trans=trans)
                        elif self.action == "DELETE":
                            table.row(*self.clean(row, self.columns))
                            self.select += 1
                            self.database.remove_instance(item, trans)
                        else:
                            raise AttributeError("unknown command: '%s'", self.action)
                    ROWNUM += 1
                    if (self.limit is not None) and (ROWNUM >= self.limit[1]):
                        break
Ejemplo n.º 32
0
def run(database, document, filter_name, *args, **kwargs):
    """
    Loops through the families that the person is a child in, and display
    the information about the other children.
    """
    # setup the simple access functions
    sdb = SimpleAccess(database)
    sdoc = SimpleDoc(document)
    stab = QuickTable(sdb)
    if (filter_name == 'all'):
        sdoc.title(_("Summary counts of current selection"))
        sdoc.paragraph("")
        sdoc.paragraph(_("Right-click row (or press ENTER) to see selected items."))
        sdoc.paragraph("")
        stab.columns(_("Object"), _("Count/Total"))
        if hasattr(database, "db"):
            stab.row([_("People"), "Filter", "Person"], 
                     "%d/%d" % (len(database.get_person_handles()),
                                len(database.db.get_person_handles())))
            stab.row([_("Families"), "Filter", "Family"], 
                     "%d/%d" % (len(database.get_family_handles()),
                                len(database.db.get_family_handles())))
            stab.row([_("Events"), "Filter", "Event"], 
                     "%d/%d" % (len(database.get_event_handles()),
                                len(database.db.get_event_handles())))
            stab.row([_("Places"), "Filter", "Place"], 
                     "%d/%d" % (len(database.get_place_handles()),
                                len(database.db.get_place_handles())))
            stab.row([_("Sources"), "Filter", "Source"], 
                     "%d/%d" % (len(database.get_source_handles()),
                                len(database.db.get_source_handles())))
            stab.row([_("Repositories"), "Filter", "Repository"], 
                     "%d/%d" % (len(database.get_repository_handles()),
                     len(database.db.get_repository_handles())))
            stab.row([_("Media"), "Filter", "MediaObject"], 
                     "%d/%d" % (len(database.get_media_object_handles()),
                                len(database.db.get_media_object_handles())))
            stab.row([_("Notes"), "Filter", "Note"], 
                     "%d/%d" % (len(database.get_note_handles()),
                                len(database.db.get_note_handles())))
        else:
            stab.row([_("People"), "Filter", "Person"], 
                     "%d/%d" % (len(database.get_person_handles()),
                                len(database.basedb.get_person_handles())))
            stab.row([_("Families"), "Filter", "Family"], 
                     "%d/%d" % (len(database.get_family_handles()),
                                len(database.basedb.get_family_handles())))
            stab.row([_("Events"), "Filter", "Event"], 
                     "%d/%d" % (len(database.get_event_handles()),
                                len(database.basedb.get_event_handles())))
            stab.row([_("Places"), "Filter", "Place"], 
                     "%d/%d" % (len(database.get_place_handles()),
                                len(database.basedb.get_place_handles())))
            stab.row([_("Sources"), "Filter", "Source"], 
                     "%d/%d" % (len(database.get_source_handles()),
                                len(database.basedb.get_source_handles())))
            stab.row([_("Repositories"), "Filter", "Repository"], 
                     "%d/%d" % (len(database.get_repository_handles()),
                     len(database.basedb.get_repository_handles())))
            stab.row([_("Media"), "Filter", "MediaObject"], 
                     "%d/%d" % (len(database.get_media_object_handles()),
                                len(database.basedb.get_media_object_handles())))
            stab.row([_("Notes"), "Filter", "Note"], 
                     "%d/%d" % (len(database.get_note_handles()),
                                len(database.basedb.get_note_handles())))
        sdoc.paragraph("")
        stab.write(sdoc)
        return

    # display the title
    if filter_name in fname_map:
        sdoc.title(_("Filtering on %s") % fname_map[filter_name]) # listed above
    else:
        sdoc.title(_("Filtering on %s") % _(filter_name))
    sdoc.paragraph("")
    matches = 0

    if (filter_name == 'Inverse Person'):
        sdb.dbase = database.db
        stab.columns(_("Person"), _("Gramps ID"), _("Birth Date"))
        proxy_handles = set(database.iter_person_handles())

        for person in database.db.iter_people():
            if person.handle not in proxy_handles:
                stab.row(person, person.gramps_id, 
                         sdb.birth_or_fallback(person))
                matches += 1

    elif (filter_name == 'Inverse Family'):
        sdb.dbase = database.db
        stab.columns(_("Family"), _("Gramps ID"))
        proxy_handles = set(database.iter_family_handles())

        for family in database.db.iter_families():
            if family.handle not in proxy_handles:
                stab.row(family, family.gramps_id)
                matches += 1

    elif (filter_name == 'Inverse Event'):
        sdb.dbase = database.db
        stab.columns(_("Event"), _("Gramps ID"))
        proxy_handles = set(database.iter_event_handles())

        for event in database.db.iter_events():
            if event.handle not in proxy_handles:
                stab.row(event, event.gramps_id)
                matches += 1

    elif (filter_name == 'Inverse Place'):
        sdb.dbase = database.db
        stab.columns(_("Place"), _("Gramps ID"))
        proxy_handles = set(database.iter_place_handles())                              

        for place in database.db.iter_places():
            if place.handle not in proxy_handles:
                stab.row(place, place.gramps_id)
                matches += 1

    elif (filter_name == 'Inverse Source'):
        sdb.dbase = database.db
        stab.columns(_("Source"), _("Gramps ID"))
        proxy_handles = set(database.iter_source_handles())                              

        for source in database.db.iter_sources():
            if source.handle not in proxy_handles:
                stab.row(source, source.gramps_id)
                matches += 1

    elif (filter_name == 'Inverse Repository'):
        sdb.dbase = database.db
        stab.columns(_("Repository"), _("Gramps ID"))
        proxy_handles = set(database.iter_repository_handles())

        for repository in database.db.iter_repositories():
            if repository.handle not in proxy_handles:
                stab.row(repository, repository.gramps_id)
                matches += 1

    elif (filter_name == 'Inverse MediaObject'):
        sdb.dbase = database.db
        stab.columns(_("Media"), _("Gramps ID"))
        proxy_handles = set(database.iter_media_object_handles())                              

        for media in database.db.iter_media_objects():
            if media.handle not in proxy_handles:
                stab.row(media, media.gramps_id)
                matches += 1

    elif (filter_name == 'Inverse Note'):
        sdb.dbase = database.db
        stab.columns(_("Note"), _("Gramps ID"))
        proxy_handles = set(database.iter_note_handles())                              

        for note in database.db.iter_notes():
            if note.handle not in proxy_handles:
                stab.row(note, note.gramps_id)
                matches += 1

    elif (filter_name in ['all people', 'Person']):
        stab.columns(_("Person"), _("Gramps ID"), _("Birth Date"))
        for person in database.iter_people():
            stab.row(person, person.gramps_id, sdb.birth_or_fallback(person))
            matches += 1

    elif (filter_name in ['all families', 'Family']):
        stab.columns(_("Family"), _("Gramps ID"))
        for family in database.iter_families():
            stab.row(family, family.gramps_id)
            matches += 1

    elif (filter_name in ['all events', 'Event']):
        stab.columns(_("Event"), _("Gramps ID"))
        for obj in database.iter_events():
            stab.row(obj, obj.gramps_id)
            matches += 1

    elif (filter_name in ['all places', 'Place']):
        stab.columns(_("Place"), _("Gramps ID"))
        for obj in database.iter_places():
            stab.row(obj, obj.gramps_id)
            matches += 1

    elif (filter_name in ['all sources', 'Source']):
        stab.columns(_("Source"), _("Gramps ID"))
        for obj in database.iter_sources():
            stab.row(obj, obj.gramps_id)
            matches += 1

    elif (filter_name in ['all repositories', 'Repository']):
        stab.columns(_("Repository"), _("Gramps ID"))
        for obj in database.iter_repositories():
            stab.row(obj, obj.gramps_id)
            matches += 1

    elif (filter_name in ['all media', 'MediaObject']):
        stab.columns(_("Media"), _("Gramps ID"))
        for obj in database.iter_media_objects():
            stab.row(obj, obj.gramps_id)
            matches += 1

    elif (filter_name in ['all notes', 'Note']):
        stab.columns(_("Note"), _("Gramps ID"))
        for obj in database.iter_notes():
            stab.row(obj, obj.gramps_id)
            matches += 1

    elif (filter_name == 'males'):
        stab.columns(_("Person"), _("Birth Date"), _("Name type"))
        for person in database.iter_people():
            if person.gender == Person.MALE:
                stab.row(person, sdb.birth_or_fallback(person),
                         str(person.get_primary_name().get_type()))
                matches += 1

    elif (filter_name == 'females'):
        stab.columns(_("Person"), _("Birth Date"), _("Name type"))
        for person in database.iter_people():
            if person.gender == Person.FEMALE:
                stab.row(person, sdb.birth_or_fallback(person),
                         str(person.get_primary_name().get_type()))
                matches += 1

    elif (filter_name == 'people with unknown gender'):
        stab.columns(_("Person"), _("Birth Date"), _("Name type"))
        for person in database.iter_people():
            if person.gender not in [Person.FEMALE, Person.MALE]:
                stab.row(person, sdb.birth_or_fallback(person),
                         str(person.get_primary_name().get_type()))
                matches += 1

    elif (filter_name == 'incomplete names'):
        stab.columns(_("Name"), _("Birth Date"), _("Name type"))
        for person in database.iter_people():
            for name in [person.get_primary_name()] + person.get_alternate_names():
                if name.get_first_name().strip() == "":
                    stab.row([name.get_name(), "Person", person.handle], sdb.birth_or_fallback(person),
                             str(name.get_type()))
                    matches += 1
                else:
                    if name.get_surname_list():
                        for surname in name.get_surname_list():
                            if surname.get_surname().strip() == "":
                                stab.row([name.get_first_name(), "Person", person.handle], sdb.birth_or_fallback(person),
                                         str(name.get_type()))
                                matches += 1
                    else:
                        stab.row([name.get_first_name(), "Person", person.handle], sdb.birth_or_fallback(person),
                                 str(name.get_type()))
                        matches += 1

    elif (filter_name == 'people with missing birth dates'):
        stab.columns(_("Person"), _("Type"))
        for person in database.iter_people():
            birth_ref = person.get_birth_ref()
            if birth_ref:
                birth = database.get_event_from_handle(birth_ref.ref)
                if not get_date(birth):
                    stab.row(person, _("birth event but no date"))
                    matches += 1
            else:
                stab.row(person, _("missing birth event"))
                matches += 1

    elif (filter_name == 'disconnected people'):
        stab.columns(_("Person"), _("Birth Date"), _("Name type"))
        for person in database.iter_people():
            if ((not person.get_main_parents_family_handle()) and 
                (not len(person.get_family_handle_list()))):
                stab.row(person, sdb.birth_or_fallback(person),
                         str(person.get_primary_name().get_type()))
                matches += 1

    elif (filter_name == 'unique surnames'):
        namelist = defaultdict(int)
        for person in database.iter_people():
            names = [person.get_primary_name()] + person.get_alternate_names()
            surnames = list(set([name.get_group_name() for name in names]))
            for surname in surnames:
                namelist[surname] += 1
        stab.columns(_("Surname"), _("Count"))
        for name in sorted(namelist):
            stab.row(name, namelist[name])
            matches += 1
        stab.set_callback("leftdouble", 
            lambda name: run_quick_report_by_name_direct("samesurnames",
                                                         database,
                                                         document,
                                                         name))

    elif (filter_name == 'people with media'):
        stab.columns(_("Person"), _("Media count"))
        for person in database.iter_people():
            length = len(person.get_media_list())
            if length > 0:
                stab.row(person, str(length))
                matches += 1

    elif (filter_name == 'media references'):
        stab.columns(_("Person"), _("Reference"))
        for person in database.iter_people():
            medialist = person.get_media_list()
            for item in medialist:
                stab.row(person, _("media"))
                matches += 1

    elif (filter_name == 'unique media'):
        stab.columns(_("Unique Media"))
        for photo in database.iter_media_objects():
            fullname = media_path_full(database, photo.get_path())
            stab.row(fullname)
            matches += 1

    elif (filter_name == 'missing media'):
        stab.columns(_("Missing Media"))
        for photo in database.iter_media_objects():
            fullname = media_path_full(database, photo.get_path())
            try:
                posixpath.getsize(fullname)
            except:
                stab.row(fullname)
                matches += 1

    elif (filter_name == 'media by size'):
        stab.columns(_("Media"), _("Size in bytes"))
        for photo in database.iter_media_objects():
            fullname = media_path_full(database, photo.get_path())
            try:
                bytes = posixpath.getsize(fullname)
                stab.row(fullname, str(bytes))
                matches += 1
            except:
                pass

    elif (filter_name == 'list of people'):
        stab.columns(_("Person"), _("Birth Date"), _("Name type"))
        handles = kwargs["handles"]
        for person_handle in handles:
            person = database.get_person_from_handle(person_handle)
            stab.row(person, sdb.birth_or_fallback(person),
                     str(person.get_primary_name().get_type()))
            matches += 1

    else:
        raise AttributeError("invalid filter name: '%s'" % filter_name)
    # translators: leave all/any {...} untranslated
    sdoc.paragraph(ngettext("Filter matched {number_of} record.",
                            "Filter matched {number_of} records.", matches
                           ).format(number_of=matches) )
    sdoc.paragraph("")
    document.has_data = matches > 0
    if matches > 0:
        stab.write(sdoc)
def run(database, document, person):
    """
    Display a person's timeline.
    """
    sa = SimpleAccess(database)
    sd = SimpleDoc(document)
    sd.title(_("Timeline for %s") % sa.name(person))
    sd.paragraph("")
    stab = QuickTable(sa)
    stab.columns(_("Date"), _("Event"), _("Age"), _("Place"),
                 _("People involved"))
    stab.set_link_col(4)

    handled = {}
    birth_ref = gramps.gen.lib.Person.get_birth_ref(person)
    birth_date = get_event_date_from_ref(database, birth_ref)
    event_list = []

    process(database, sa, event_list, handled, person, False, person)

    for (event, obj, desc) in sorted(event_list, key=by_date):
        edate = sa.event_date_obj(event)
        span_str, span_int = format_date(birth_date, edate, obj == person)
        if desc == None:
            desc = event
        stab.row(edate, desc, span_str, sa.event_place(event), obj)
        stab.row_sort_val(2, span_int)
    today = Today()
    span_str, span_int = format_date(birth_date, today, False)
    stab.row(today, _("Today"), span_str, "", person)
    stab.row_sort_val(2, span_int)
    stab.write(sd)
    sd.paragraph("")
Ejemplo n.º 34
0
def run_fam(database, document, family):
    """
    Loops through the family events and the events of all parents, displaying
    the basic details of the event
    """

    sdb = SimpleAccess(database)
    sdoc = SimpleDoc(document)
    stab = QuickTable(sdb)

    # get the family events
    event_list = [(_('Family'), x) for x in sdb.events(family)]

    # get the events of father and mother
    #fathername = sdb.first_name(sdb.father(family))
    event_list += [(sdb.father(family), x) for x in sdb.events(sdb.father(family))]
    #mothername = sdb.first_name(sdb.mother(family))
    event_list += [(sdb.mother(family), x) for x in sdb.events(sdb.mother(family))]

    # children events
    event_list_children = []
    for child in sdb.children(family) :
        #name = sdb.first_name(child)
        event_list_children += [(child, x) for x in sdb.events(child)]

    # Sort the events by their date
    event_list.sort(key=lambda x: x[1].get_date_object())
    event_list_children.sort(key=lambda x: x[1].get_date_object())

    # display the results

    sdoc.title(_("Sorted events of family\n %(father)s - %(mother)s") % {
        'father' : sdb.name(sdb.father(family)), 'mother' : sdb.name(sdb.mother(family)) })
    sdoc.paragraph("")

    document.has_data = False
    stab.columns(_("Family Member"), _("Event Type"),
                 _("Event Date"), _("Event Place"))

    for (person, event) in event_list:
        stab.row(person, sdb.event_type(event),
                 sdb.event_date_obj(event),
                 sdb.event_place(event))
        document.has_data = True
    stab.write(sdoc)

    stab = QuickTable(sdb)
    sdoc.header1(_("Personal events of the children"))
    stab.columns(_("Family Member"), _("Event Type"),
                 _("Event Date"), _("Event Place"))
    for (person, event) in event_list_children:
        stab.row(person, sdb.event_type(event),
                 sdb.event_date_obj(event),
                 sdb.event_place(event))
        document.has_data = True
    stab.write(sdoc)
Ejemplo n.º 35
0
def run(database, document, main_event):
    """
    Displays events on a specific date of an event (or date)

    Takes an Event or Date object
    """
    if isinstance(main_event, Date):
        main_date = main_event
    else:
        main_date = main_event.get_date_object()

    cal = main_date.get_calendar()

    # setup the simple access functions
    sdb = SimpleAccess(database)
    sdoc = SimpleDoc(document)
    stab = QuickTable(sdb)
    stab.set_link_col(3)
    yeartab = QuickTable(sdb)
    yeartab.set_link_col(3)
    histab = QuickTable(sdb)
    histab.set_link_col(3)

    # display the title
    sdoc.title(_("Events of %(date)s") % {"date": sdb.date_string(main_date)})
    sdoc.paragraph("")
    stab.columns(_("Date"), _("Type"), _("Place"), _("Reference"))
    yeartab.columns(_("Date"), _("Type"), _("Place"), _("Reference"))
    histab.columns(_("Date"), _("Type"), _("Place"), _("Reference"))

    for event in database.iter_events():
        date = event.get_date_object()
        date.convert_calendar(cal)
        if date.get_year() == 0:
            continue
        if (date.get_year() == main_date.get_year()
                and date.get_month() == main_date.get_month()
                and date.get_day() == main_date.get_day()):
            for (objclass,
                 handle) in database.find_backlink_handles(event.handle):
                ref = get_ref(database, objclass, handle)
                stab.row(date, sdb.event_type(event), sdb.event_place(event),
                         ref)
        elif (date.get_month() == main_date.get_month()
              and date.get_day() == main_date.get_day()
              and date.get_month() != 0):
            for (objclass,
                 handle) in database.find_backlink_handles(event.handle):
                ref = get_ref(database, objclass, handle)
                histab.row(date, sdb.event_type(event), sdb.event_place(event),
                           ref)
        elif (date.get_year() == main_date.get_year()):
            for (objclass,
                 handle) in database.find_backlink_handles(event.handle):
                ref = get_ref(database, objclass, handle)
                yeartab.row(date, sdb.event_type(event),
                            sdb.event_place(event), ref)

    document.has_data = False
    if stab.get_row_count() > 0:
        document.has_data = True
        sdoc.paragraph(_("Events on this exact date"))
        stab.write(sdoc)
    else:
        sdoc.paragraph(_("No events on this exact date"))
        sdoc.paragraph("")
    sdoc.paragraph("")

    if histab.get_row_count() > 0:
        document.has_data = True
        sdoc.paragraph(_("Other events on this month/day in history"))
        histab.write(sdoc)
    else:
        sdoc.paragraph(_("No other events on this month/day in history"))
        sdoc.paragraph("")
    sdoc.paragraph("")

    if yeartab.get_row_count() > 0:
        document.has_data = True
        sdoc.paragraph(
            _("Other events in %(year)d") % {"year": main_date.get_year()})
        yeartab.write(sdoc)
    else:
        sdoc.paragraph(
            _("No other events in %(year)d") % {"year": main_date.get_year()})
        sdoc.paragraph("")
    sdoc.paragraph("")
Ejemplo n.º 36
0
def run_fam(database, document, family):
    """
    Loops through the family events and the events of all parents, displaying
    the basic details of the event
    """

    sdb = SimpleAccess(database)
    sdoc = SimpleDoc(document)
    stab = QuickTable(sdb)

    # get the family events
    event_list = [(_('Family'), x) for x in sdb.events(family)]

    # get the events of father and mother
    #fathername = sdb.first_name(sdb.father(family))
    event_list += [(sdb.father(family), x)
                   for x in sdb.events(sdb.father(family))]
    #mothername = sdb.first_name(sdb.mother(family))
    event_list += [(sdb.mother(family), x)
                   for x in sdb.events(sdb.mother(family))]

    # children events
    event_list_children = []
    for child in sdb.children(family):
        #name = sdb.first_name(child)
        event_list_children += [(child, x) for x in sdb.events(child)]

    # Sort the events by their date
    event_list.sort(key=lambda x: x[1].get_date_object())
    event_list_children.sort(key=lambda x: x[1].get_date_object())

    # display the results

    sdoc.title(
        _("Sorted events of family\n %(father)s - %(mother)s") % {
            'father': sdb.name(sdb.father(family)),
            'mother': sdb.name(sdb.mother(family))
        })
    sdoc.paragraph("")

    document.has_data = False
    stab.columns(_("Family Member"), _("Event Type"), _("Event Date"),
                 _("Event Place"))

    for (person, event) in event_list:
        stab.row(person, sdb.event_type(event), sdb.event_date_obj(event),
                 sdb.event_place(event))
        document.has_data = True
    stab.write(sdoc)

    stab = QuickTable(sdb)
    sdoc.header1(_("Personal events of the children"))
    stab.columns(_("Family Member"), _("Event Type"), _("Event Date"),
                 _("Event Place"))
    for (person, event) in event_list_children:
        stab.row(person, sdb.event_type(event), sdb.event_date_obj(event),
                 sdb.event_place(event))
        document.has_data = True
    stab.write(sdoc)
Ejemplo n.º 37
0
class DBI(object):
    """
    The SQL-like interface to the database and document instances.
    """
    def __init__(self, database, document=None):
        self.database = database
        self.document = document
        self.data = {}
        self.select = 0
        self.flat = False
        self.raw = False
        if self.database:
            for name in ('Person', 'Family', 'Event', 'Place', 'Repository',
                         'Source', 'Citation', 'Media', 'Note', 'Tag'):
                d = self.database._tables[name]["class_func"]().to_struct()
                self.data[name.lower()] = d.keys()
        # The macros:
        self.shortcuts = {
            "SURNAME": "primary_name.surname_list[0].surname",
            "GIVEN": "primary_name.first_name",
        }

    def parse(self, query):
        """
        Parse the query.
        """
        self.query_text = query.replace("\n", " ").strip()
        lexed = self.lexer(self.query_text)
        #print(lexed)
        self.parser(lexed)
        for col_name in self.columns[:]:  # copy
            if col_name == "*":
                self.columns.remove('*')
                # this is useful to see what _class it is:
                self.columns.extend(self.get_columns(self.table))
                # otherwise remove metadata:
                #self.columns.extend([col for col in self.get_columns(self.table) if not col.startswith("_"))

    def lexer(self, string):
        """
        Given a string, break into a list of chunks.
        """
        retval = []
        state = None
        current = ""
        stack = []
        i = 0
        # Handle macros:
        for key in self.shortcuts.keys():
            string = string.replace(key, self.shortcuts[key])
        # (some "expression" in ok)
        # func(some "expression" in (ok))
        # list[1][0]
        # [x for x in list]
        while i < len(string):
            ch = string[i]
            #print("lex:", i, ch, state, retval, current)
            if state == "in-double-quote":
                if ch == '"':
                    state = stack.pop()
                current += ch
            elif state == "in-single-quote":
                if ch == "'":
                    state = stack.pop()
                current += ch
            elif state == "in-expr":
                if ch == ")":
                    state = stack.pop()
                elif ch == "(":
                    stack.append("in-expr")
                current += ch
            elif state == "in-square-bracket":
                if ch == "]":
                    state = stack.pop()
                elif ch == "[":
                    stack.append("in-square-bracket")
                current += ch
            elif ch == '"':
                stack.append(state)
                state = "in-double-quote"
                current += ch
            elif ch == "'":
                stack.append(state)
                state = "in-single-quote"
                current += ch
            elif ch == "(":
                stack.append(state)
                state = "in-expr"
                current += "("
            elif ch == "[":
                stack.append(state)
                state = "in-square-bracket"
                current += "["
            elif ch == ",":
                if current:
                    retval.append(current)
                retval.append(",")
                current = ""
            elif ch == "=":
                if current:
                    retval.append(current)
                retval.append("=")
                current = ""
            elif ch in [' ', '\t', '\n', ";"]:  # break
                if current:
                    retval.append(current)
                    if current.upper() == "WHERE":
                        # HACK: get rest of string:
                        if string[-1] == ";":
                            retval.append(string[i + 1:-1])
                            i = len(string) - 2
                        else:
                            retval.append(string[i + 1:])
                            i = len(string) - 1
                    current = ""
                else:
                    pass  # ignore whitespace
            else:
                current += ch
            i += 1
        if current:
            retval.append(current)
        #print("lexed:", retval)
        return retval

    def parser(self, lex):
        """
        Takes output of lexer, and sets the values.
        After parser, the DBI will be ready to process query.
        """
        self.action = None
        self.table = None
        self.columns = []
        self.setcolumns = []
        self.values = []
        self.aliases = {}
        self.limit = None
        self.where = None
        self.index = 0
        while self.index < len(lex):
            symbol = lex[self.index]
            if symbol.upper() == "FROM":
                # from table select *;
                self.index += 1
                if self.index < len(lex):
                    self.table = lex[self.index]
            elif symbol.upper() == "SELECT":
                # select a, b from table;
                self.action = "SELECT"
                self.index += 1
                self.columns.append(lex[self.index])
                self.index += 1
                while self.index < len(lex) and lex[self.index].upper() in [
                        ",", "AS"
                ]:
                    sep = lex[self.index]
                    if sep == ",":
                        self.index += 1
                        self.columns.append(lex[self.index])
                        self.index += 1
                    elif sep.upper() == "AS":
                        self.index += 1  # alias
                        self.aliases[self.columns[-1]] = lex[self.index]
                        self.index += 1
                self.index -= 1
            elif symbol.upper() == "DELETE":
                # delete from table where item == 1;
                self.action = "DELETE"
                self.columns = ["gramps_id"]
            elif symbol.upper() == "SET":
                # SET x=1, y=2
                self.index += 1
                self.setcolumns.append(lex[self.index])  # first column
                self.index += 1  # equal sign
                # =
                self.index += 1  # value
                self.values.append(lex[self.index])
                self.index += 1  # comma
                while self.index < len(lex) and lex[self.index] == ",":
                    self.index += 1  # next column
                    self.setcolumns.append(lex[self.index])
                    self.index += 1  # equal
                    # =
                    self.index += 1  # value
                    self.values.append(lex[self.index])
                    self.index += 1  # comma?
                self.index -= 1
            elif symbol.upper() == "LIMIT":
                self.index += 1  # after LIMIT
                number = lex[self.index]
                self.index += 1  # maybe a comma
                if self.index < len(lex) and lex[self.index] == ",":
                    self.index += 1  # after ","
                    stop = lex[self.index]
                    self.limit = (int(number), int(stop))
                else:
                    self.limit = (0, int(number))
                    self.index -= 1
            elif symbol.upper() == "WHERE":
                # how can we get all of Python expressions?
                # this assumes all by ;
                self.index += 1
                self.where = lex[self.index]
            elif symbol.upper() == "UPDATE":
                # update table set x=1, y=2 where condition;
                # UPDATE gramps_id set tag_list = Tag("Betty") from person where  "Betty" in primary_name.first_name
                self.columns = ["gramps_id"]
                self.action = "UPDATE"
                if self.index < len(lex):
                    self.index += 1
                    self.table = lex[self.index]
            elif symbol.upper() == "FLAT":
                self.flat = True
            elif symbol.upper() == "EXPAND":
                self.flat = False
            elif symbol.upper() == "RAW":
                self.raw = True
            elif symbol.upper() == "NORAW":
                self.raw = False
            else:
                raise AttributeError("invalid SQL expression: '... %s ...'" %
                                     symbol)
            self.index += 1

    def close(self):
        """
        Close up any progress widgets or dialogs.
        """
        #try:
        #    self.progress.close()
        #except:
        pass

    def clean_titles(self, columns):
        """
        Take the columns and turn them into strings for the table.
        """
        retval = []
        for column in columns:
            if column in self.aliases:
                column = self.aliases[column]
            retval.append(column.replace("_", "__"))
        return retval

    def query(self, query):
        self.parse(query)
        self.select = 0
        start_time = time.time()

        class Table():
            results = []

            def row(self, *args, **kwargs):
                self.results.append([args, kwargs])

            def get_rows(self):
                return [list(item[0]) for item in self.results]

        table = Table()
        self.sdb = SimpleAccess(self.database)
        self.process_table(table)  # a class that has .row(1, 2, 3, ...)
        print(
            _("%d rows processed in %s seconds.\n") %
            (self.select, time.time() - start_time))
        return table

    def eval(self):
        """
        Execute the query.
        """
        self.sdb = SimpleAccess(self.database)
        self.stab = QuickTable(self.sdb)
        self.select = 0
        start_time = time.time()
        self.process_table(self.stab)  # a class that has .row(1, 2, 3, ...)
        if self.select > 0:
            self.stab.columns(*self.clean_titles(self.columns))
            self.sdoc = SimpleDoc(self.document)
            self.sdoc.title(self.query_text)
            self.sdoc.paragraph("\n")
            self.sdoc.paragraph("%d rows processed in %s seconds.\n" %
                                (self.select, time.time() - start_time))
            self.stab.write(self.sdoc)
            self.sdoc.paragraph("")
        return _("%d rows processed in %s seconds.\n") % (
            self.select, time.time() - start_time)

    def get_columns(self, table):
        """
        Get the columns for the given table.
        """
        if self.database:
            retval = self.data[table.lower()]
            return retval  # [self.name] + retval
        else:
            return ["*"]

    def process_table(self, table):
        """
        Given a table name, process the query on the elements of the
        table.
        """
        # 'Person', 'Family', 'Source', 'Citation', 'Event', 'Media',
        # 'Place', 'Repository', 'Note', 'Tag'
        # table: a class that has .row(1, 2, 3, ...)
        if self.table == "person":
            self.do_query(self.sdb.all_people(), table)
        elif self.table == "family":
            self.do_query(self.sdb.all_families(), table)
        elif self.table == "event":
            self.do_query(self.sdb.all_events(), table)
        elif self.table == "source":
            self.do_query(self.sdb.all_sources(), table)
        elif self.table == "tag":
            self.do_query(self.sdb.all_tags(), table)
        elif self.table == "citation":
            self.do_query(self.sdb.all_citations(), table)
        elif self.table == "media":
            self.do_query(self.sdb.all_media(), table)
        elif self.table == "place":
            self.do_query(self.sdb.all_places(), table)
        elif self.table == "repository":
            self.do_query(self.sdb.all_repositories(), table)
        elif self.table == "note":
            self.do_query(self.sdb.all_notes(), table)
        else:
            raise AttributeError("no such table: '%s'" % self.table)

    def get_tag(self, name):
        tag = self.database.get_tag_from_name(name)
        if tag is None:
            tag = gramps.gen.lib.Tag()
            tag.set_name(name)
            trans_class = self.database.get_transaction_class()
            with trans_class("QueryQuickview new Tag",
                             self.database,
                             batch=False) as trans:
                self.database.add_tag(tag, trans)
        return Handle("Tag", tag.handle)

    def make_env(self, **kwargs):
        """
        An environment with which to eval elements.
        """
        retval = Environment({
            _("Date"): gramps.gen.lib.date.Date,
            _("Today"): gramps.gen.lib.date.Today(),
            "random": random,
            "re": re,
            "db": self.database,
            "sdb": self.sdb,
            "lib": gramps.gen.lib,
            "_": _,
            "Tag": self.get_tag,
        })
        retval.update(__builtins__)
        retval.update(kwargs)
        return retval

    def stringify(self, value):
        """
        Turn the value into an appropriate string representation.
        """
        if self.raw:
            return value
        if isinstance(value, Struct):
            return self.stringify(value.struct)
        elif isinstance(value, (list, tuple)):
            if len(value) == 0 and not self.flat:
                return ""
            elif len(value) == 1 and not self.flat:
                return self.stringify(value[0])
            else:
                return "[%s]" % (", ".join(map(self.stringify, value)))
        elif isinstance(value, PrimaryObject):
            return value
        else:
            return str(value)

    def clean(self, values, names):
        """
        Given the values and names of columns, change the values
        into string versions for the display table.
        """
        if self.raw:
            return values
        retval = []
        for i in range(len(values)):
            if names[i].endswith("handle"):
                retval.append(repr(values[i].struct["handle"]))
            else:
                retval.append(self.stringify(values[i]))
        return retval

    def do_query(self, items, table):
        """
        Perform the query on the items in the named table.
        """
        # table: a class that has .row(1, 2, 3, ...)
        with self.database.get_transaction_class()("QueryQuickview",
                                                   self.database,
                                                   batch=True) as trans:
            ROWNUM = 0
            env = self.make_env()
            for item in items:
                if item is None:
                    continue
                row = []
                row_env = []
                # "col[0]" in WHERE clause will return first column of selection:
                env["col"] = row_env
                env["ROWNUM"] = ROWNUM
                env["object"] = item
                struct = Struct(item.to_struct(), self.database)
                env.set_struct(struct)
                for col in self.columns:
                    try:
                        value = eval(col, env)
                    except:
                        value = None
                    row.append(value)
                    # allow col[#] reference:
                    row_env.append(value)
                    # an alias?
                    if col in self.aliases:
                        env[self.aliases[col]] = value
                # Should we include this row?
                if self.where:
                    try:
                        result = eval(self.where, env)
                    except:
                        continue
                else:
                    if self.action in ["DELETE", "UPDATE"]:
                        result = True
                    else:
                        result = any([col != None
                                      for col in row])  # are they all None?
                # If result, then append the row
                if result:
                    if (self.limit is None) or (self.limit[0] <= ROWNUM <
                                                self.limit[1]):
                        if self.action == "SELECT":
                            if not self.flat:
                                # Join by rows:
                                products = []
                                columns = []
                                count = 0
                                for col in row:
                                    if ((isinstance(col, Struct)
                                         and isinstance(col.struct, list)
                                         and len(col.struct) > 0)
                                            or (isinstance(col, list)
                                                and len(col) > 0)):
                                        products.append(col)
                                        columns.append(count)
                                    count += 1
                                if len(products) > 0:
                                    current = self.clean(row, self.columns)
                                    for items in itertools.product(*products):
                                        for i in range(len(items)):
                                            current[
                                                columns[i]] = self.stringify(
                                                    items[i])
                                        table.row(
                                            *current,
                                            link=(item.__class__.__name__,
                                                  item.handle))
                                        self.select += 1
                                else:
                                    table.row(*self.clean(row, self.columns),
                                              link=(item.__class__.__name__,
                                                    item.handle))
                                    self.select += 1
                            else:
                                table.row(*self.clean(row, self.columns),
                                          link=(item.__class__.__name__,
                                                item.handle))
                                self.select += 1
                        elif self.action == "UPDATE":
                            # update table set col=val, col=val where expr;
                            table.row(*self.clean(row, self.columns),
                                      link=(item.__class__.__name__,
                                            item.handle))
                            self.select += 1
                            for i in range(len(self.setcolumns)):
                                struct.setitem(self.setcolumns[i],
                                               eval(self.values[i], env),
                                               trans=trans)
                        elif self.action == "DELETE":
                            table.row(*self.clean(row, self.columns))
                            self.select += 1
                            self.database.remove_instance(item, trans)
                        else:
                            raise AttributeError("unknown command: '%s'",
                                                 self.action)
                    ROWNUM += 1
                    if (self.limit is not None) and (ROWNUM >= self.limit[1]):
                        break