Esempio n. 1
0
def alive(person):
    """Whether the person is alive"""

    # If we have no birth date, we could assume it is at least 15 years
    # before the first child's birth date (recursively). But that becomes
    # more expensive to compute

    return not person.death \
        and (not person.birth
             or DateRange.today().years_since(person.birth.Date) <= max_age)
Esempio n. 2
0
def alive(person):
    """Whether the person is alive"""

    # If we have no birth date, we could assume it is at least 15 years
    # before the first child's birth date (recursively). But that becomes
    # more expensive to compute

    return not person.death \
        and (not person.birth
             or DateRange.today().years_since(person.birth.Date) <= max_age)
Esempio n. 3
0
      def default (self, obj):
         """See inherited documentation"""

         if isinstance (obj, models.Persona):
            b = self._event (obj.birth)
            d = self._event (obj.death)

            if not year_only and obj.birth:
               if obj.death:
                  if obj.death.Date:
                     age = " (age " \
                        + str (obj.death.Date.years_since (obj.birth.Date)) \
                        + ")"
                     d[0] += age
               else:
                  age = " (age " \
                        + str (DateRange.today().years_since (obj.birth.Date)) \
                        + ")"
                  d = [age, None, None]

            return {"id":obj.id, "givn":obj.given_name,
                    'surn':obj.surname, 'sex':obj.sex,
                    'generation': obj.generation,
                    'y':obj.styles, 'b':b, 'd':d}

         elif isinstance (obj, DateRange):
            return obj.display(year_only=year_only)

         elif isinstance (obj, models.Event):
            return self._event (obj)

         elif isinstance(obj, set):
             return list(obj)

         elif hasattr(obj, 'to_json'):
            return obj.to_json()

         return super (ModelEncoder, self).default(obj)
Esempio n. 4
0
def alive(person):
    """Whether the person is alive"""

    # If we have no birth date, we could assume it is at least 15 years
    # before the first child's birth date (recursively). But that becomes
    # more expensive to compute

    logger.error('Did not compute birth or death for person')
    return False

    if person.death is not None:
        return False
    elif person.birth is None:
        # Might be alive. We could look at other events to guess at the
        # timeframe
        return True
    else:
        d = DateRange.today().years_since(person.birth.Date)
        if d is None:
            # Could not compute elapsed time (likely because birth has no know
            # year
            return True
        else:
            return d <= max_age
Esempio n. 5
0
    def __init__(self, rules, graph, decujus):
        """Rules specifies the rules to use for the highlighting.
        """
        super(Styles, self).__init__()

        # Preprocess the rules for faster computation

        self.graph = graph
        self.rules = []
        self.today = DateRange.today()
        self.counts = [None] * len(rules)  # the "count" rules: (test, value)
        self._need_place_parts = False

        self.styles_count = 0

        for index, r in enumerate(rules):
            rule_name, rule_type, rule_tests, rule_style = r

            if rule_type in (RULE_EVENT, RULE_ATTR):
                tests = []
                for t in rule_tests:
                    if t[0] == "count" and rule_type == RULE_EVENT:
                        # Handled separately at the end
                        self.counts[index] = (rules_func[t[1]], t[2])
                        continue
                    elif t[0] == "ancestor" and rule_type == RULE_ATTR:
                        ancestors = graph.people_in_tree(
                            id=t[2], maxdepthAncestors=-1, maxdepthDescendants=0)
                        tests.append((t[0], [a.main_id for a in ancestors]))
                        continue
                    elif t[0] == "descendant" and rule_type == RULE_ATTR:
                        descendants = graph.people_in_tree(
                            id=t[2], maxdepthAncestors=0, maxdepthDescendants=-1)
                        tests.append((t[0], [a.main_id for a in descendants]))
                        continue
                    elif t[0] == "IMPLEX" and rule_type == RULE_ATTR:
                        # ??? We used to preprocess the tree to know how many times
                        # an id occurred in the tree, but the graph no longer
                        # provides that info

                        def build_implex(counts, id):
                            counts[id] = counts.get(id, 0) + 1
                            fathers = graph.fathers(id)
                            if fathers:
                                build_implex(counts, fathers[0].main_id)
                            mothers = graph.mothers(id)
                            if mothers:
                                build_implex(counts, mothers[0].main_id)
                        counts = dict()
                        build_implex(
                            counts, graph.node_from_id(decujus).main_id)
                        tests.append((t[0], rules_func[t[1]], t[2], counts))
                        continue
                    elif t[0].startswith("place.") and t[0] != "place.name":
                        self._need_place_parts = True

                    if t[1] == RULE_CONTAINS_INSENSITIVE \
                       or t[1] == RULE_CONTAINS_NOT_INSENSITIVE \
                       or t[1] == RULE_IS_INSENSITIVE:
                        tests.append((t[0], rules_func[t[1]], t[2].lower()))
                    elif t[1] == RULE_BEFORE:
                        tests.append((t[0], rules_func[t[1]], DateRange(t[2])))
                    else:
                        tests.append((t[0], rules_func[t[1]], t[2]))

                self.rules.append((rule_type, tests, rule_style))
            else:
                print "Unknown rule tag in the style rules: %s" % r

        self.no_match = [0] * len(self.rules)
Esempio n. 6
0
    def __init__(self, rules, graph, decujus):
        """Rules specifies the rules to use for the highlighting.
        """
        super(Styles, self).__init__()

        # Preprocess the rules for faster computation

        self.graph = graph
        self.rules = []
        self.today = DateRange.today()
        self.counts = [None] * len(rules)  # the "count" rules: (test, value)
        self._need_place_parts = False

        self.styles_count = 0

        for index, r in enumerate(rules):
            rule_name, rule_type, rule_tests, rule_style = r

            if rule_type in (RULE_EVENT, RULE_ATTR):
                tests = []
                for t in rule_tests:
                    if t[0] == "count" and rule_type == RULE_EVENT:
                        # Handled separately at the end
                        self.counts[index] = (rules_func[t[1]], t[2])
                        continue
                    elif t[0] == "ancestor" and rule_type == RULE_ATTR:
                        ancestors = graph.people_in_tree(id=t[2],
                                                         maxdepthAncestors=-1,
                                                         maxdepthDescendants=0)
                        tests.append((t[0], [a.main_id for a in ancestors]))
                        continue
                    elif t[0] == "descendant" and rule_type == RULE_ATTR:
                        descendants = graph.people_in_tree(
                            id=t[2],
                            maxdepthAncestors=0,
                            maxdepthDescendants=-1)
                        tests.append((t[0], [a.main_id for a in descendants]))
                        continue
                    elif t[0] == "IMPLEX" and rule_type == RULE_ATTR:
                        # ??? We used to preprocess the tree to know how many times
                        # an id occurred in the tree, but the graph no longer
                        # provides that info

                        def build_implex(counts, id):
                            counts[id] = counts.get(id, 0) + 1
                            fathers = graph.fathers(id)
                            if fathers:
                                build_implex(counts, fathers[0].main_id)
                            mothers = graph.mothers(id)
                            if mothers:
                                build_implex(counts, mothers[0].main_id)

                        counts = dict()
                        build_implex(counts,
                                     graph.node_from_id(decujus).main_id)
                        tests.append((t[0], rules_func[t[1]], t[2], counts))
                        continue
                    elif t[0].startswith("place.") and t[0] != "place.name":
                        self._need_place_parts = True

                    if t[1] == RULE_CONTAINS_INSENSITIVE \
                       or t[1] == RULE_CONTAINS_NOT_INSENSITIVE \
                       or t[1] == RULE_IS_INSENSITIVE:
                        tests.append((t[0], rules_func[t[1]], t[2].lower()))
                    elif t[1] == RULE_BEFORE:
                        tests.append((t[0], rules_func[t[1]], DateRange(t[2])))
                    else:
                        tests.append((t[0], rules_func[t[1]], t[2]))

                self.rules.append((rule_type, tests, rule_style))
            else:
                print "Unknown rule tag in the style rules: %s" % r

        self.no_match = [0] * len(self.rules)
Esempio n. 7
0
def __get_events(nodes,
                 styles,
                 graph,
                 types=None,
                 schemes=None,
                 query_groups=True):
    """Compute the events for the various persons in IDS (all all persons in
       the database if None)

       :param nodes:
           A set of graph.Persona_node, or None to get all persons from the
           database.
       :param graph: an instance of Graph, which is used to compute whether
          two ids represent the same person.
       :return: a list of persons:
          * persons is a dictionary of Persona instances, indexed on persona_id

       SCHEMES is the list of ids of Surety_Scheme that are used. You
          should pass a set() if you are interested in this. Otherwise, it is
          just discarded.

       This sets persons[*].chars to a list of the characteristics.
       Only the events of type in TYPES are returned
    """
    if nodes:
        ids = [a.main_id for a in nodes]
    else:
        ids = None

    compute_parts = styles and styles.need_place_parts()

    roles = dict()  # role_id  -> name
    places = dict()  # place_id -> place

    assert (schemes is None or isinstance(schemes, set))

    # Get the role names

    for role in models.Event_Type_Role.objects.all():
        roles[role.id] = role.name

    ##############
    # Create the personas that will be returned.
    ##############

    persons = dict()  # id -> person
    if ids:
        for p in sql_in(models.Persona.objects, "id", ids):
            # p.id is always the main_id, since that's how ids was built
            persons[p.id] = p
            __add_default_person_attributes(p)
    else:
        for p in models.Persona.objects.all():
            mid = graph.node_from_id(p.id).main_id
            if mid not in persons:
                persons[mid] = p
                __add_default_person_attributes(p)

    ################
    # Check all events that the persons were involved in.
    ################

    events = models.P2E.objects.select_related('event', 'event__place',
                                               'event__type', 'surety')
    if types:
        events = events.filter(event__type__in=types)

    all_ids = None
    if nodes:
        all_ids = set()
        for p in nodes:
            all_ids.update(p.ids)

    all_events = dict()

    # All query the 'principal' for each events, so that we can provide
    # that information graphically.
    for p in sql_in(events, "person", all_ids):
        # or_q=Q(role=models.Event_Type_Role.principal)):
        e = p.event

        p_node = graph.node_from_id(p.person_id)
        person = persons[p_node.main_id]
        person.all_events[e.id] = EventInfo(event=e,
                                            role=roles[p.role_id],
                                            assertion=p)

        e.sources = getattr(e, "sources", set())
        e.sources.add(p.source_id)
        e.Date = e.date and DateRange(e.date)

        if schemes is not None:
            schemes.add(p.surety.scheme_id)

        if compute_parts and e.place:
            places[e.place_id] = e.place

        if styles:
            styles.process(person, p.role_id, e)

        if not p.disproved \
           and p.role_id == models.Event_Type_Role.principal:
            if not e.Date:
                pass
            elif e.type_id == models.Event_Type.birth:
                if person.birth is None \
                   or person.birth.date_sort > e.date_sort:
                    person.birth = e
            elif e.type_id == models.Event_Type.death:
                if person.death is None \
                   or person.death.date_sort < e.date_sort:
                    person.death = e
            elif e.type_id == models.Event_Type.marriage:
                person.marriage = e

    #########
    # Get all groups to which the personas belong
    #########

    if query_groups:
        groups = models.P2G.objects.select_related('group')
        for gr in sql_in(groups, "person", all_ids):
            p_node = graph.node_from_id(gr.person_id)
            person = persons[p_node.main_id]
            person.all_groups[gr.group_id] = GroupInfo(group=gr.group,
                                                       assertion=gr)
            if gr.source_id:
                src = getattr(gr.group, "sources", [])
                src.append(gr.source_id)
                gr.group.sources = src
            gr.group.role = gr.role

            if schemes is not None:
                schemes.add(gr.surety.scheme_id)

    #########
    # Get all characteristics of these personas
    #########

    p2c = dict()  # characteristic_id -> person
    all_p2c = models.P2C.objects.select_related('characteristic',
                                                'characteristic__place')

    for p in sql_in(all_p2c, "person", all_ids):
        c = p.characteristic
        p_node = graph.node_from_id(p.person_id)
        person = persons[p_node.main_id]
        p2c[c.id] = person

        c.sources = getattr(c, "sources", set())
        c.sources.add(p.source_id)
        c.date = c.date and DateRange(c.date)

        if schemes is not None:
            schemes.add(p.surety.scheme_id)

        person.all_chars[c.id] = CharInfo(char=c, assertion=p, parts=[])

        if compute_parts and c.place:
            places[c.place_id] = c.place

    chars = models.Characteristic_Part.objects.select_related(
        'type', 'characteristic', 'characteristic__place')

    for part in sql_in(chars, "characteristic", nodes and p2c.keys()):
        person = p2c[part.characteristic_id]
        ch = person.all_chars[part.characteristic_id]
        ch.parts.append(CharPartInfo(name=part.type.name, value=part.name))

        if part.type_id == models.Characteristic_Part_Type.sex:
            person.sex = part.name
        elif part.type_id == models.Characteristic_Part_Type.given_name:
            person.given_name = part.name
        elif part.type_id == models.Characteristic_Part_Type.surname:
            person.surname = part.name

    ########
    # Compute place parts once, to limit the number of queries
    # These are only used for styles, not for actual display, although we
    # could benefit from them.
    ########

    if compute_parts:
        prev_place = None
        d = None

        for p in sql_in(
                models.Place_Part.objects.order_by('place').select_related(
                    'type'), "place", places.keys()):

            # ??? We should also check the parent place to gets its own parts
            if p.place_id != prev_place:
                prev_place = p.place_id
                d = dict()
                setattr(places[prev_place], "parts", d)

            d[p.type.name] = p.name

    return persons
Esempio n. 8
0
    def default(self, obj):
        """See inherited documentation"""

        if self.custom:
            p = self.custom(obj)
            if p:
                return p

        if isinstance(obj, DateRange):
            return obj.display(year_only=self.year_only)

        elif isinstance(obj, datetime.datetime):
            return obj.isoformat()

        elif isinstance(obj, django.db.models.query.QuerySet):
            return list(obj)

        elif isinstance(obj, GroupInfo):
            return dict(group=obj.group, assertion=obj.assertion)

        elif isinstance(obj, CharInfo):
            return dict(char=obj.char,
                        parts=obj.parts,
                        assertion=obj.assertion)

        elif isinstance(obj, CharPartInfo):
            return dict(name=obj.name, value=obj.value)

        elif isinstance(obj, models.Characteristic):
            return dict(
                name=obj.name,
                sources=list(obj.sources if hasattr(obj, 'sources') else []),
                date=obj.date,
                date_sort=obj.date_sort,
                place=obj.place)

        elif isinstance(obj, models.Assertion):
            result = dict(disproved=obj.disproved,
                          rationale=obj.rationale,
                          surety=obj.surety_id)

            if isinstance(obj, models.P2P):
                result['person1'] = obj.person1
                result['person2'] = obj.person2

            elif isinstance(obj, models.P2E):
                result['date'] = obj.event.date and DateRange(obj.event.date)
                result['place'] = obj.event.place and obj.event.place.name
                result['person1'] = obj.person
                result['event2'] = (obj.event, obj.role.name)

            elif isinstance(obj, models.P2C):
                parts = []
                for p in models.Characteristic_Part.objects.filter(
                        characteristic=obj.characteristic).select_related():
                    parts.append((p.type.name, p.name))
                result['date'] = \
                     obj.characteristic.date and DateRange(obj.characteristic.date)
                result['place'] = \
                     obj.characteristic.place and obj.characteristic.place.name
                result['person1'] = obj.person
                result['char2'] = (obj.characteristic, parts)

            return result

        elif isinstance(obj, models.Source):
            return dict(higher_source_id=obj.higher_source_id,
                        subject_place=obj.subject_place,
                        jurisdiction_place=obj.jurisdiction_place,
                        researcher=obj.researcher,
                        subject_date=obj.subject_date,
                        medium=obj.medium,
                        title=obj.title,
                        abbrev=obj.abbrev,
                        biblio=obj.biblio,
                        last_change=obj.last_change,
                        comments=obj.comments)

        elif isinstance(obj, EventInfo):
            return dict(event=obj.event,
                        role=obj.role,
                        assertion=obj.assertion)

        elif isinstance(obj, models.Event):
            return dict(
                id=obj.id,
                name=obj.name,
                type=obj.type,
                place=obj.place,
                sources=list(obj.sources if hasattr(obj, 'sources') else []),
                date=obj.date,
                date_sort=obj.date_sort)

        elif isinstance(obj, set):
            return list(obj)

        elif hasattr(obj, 'to_json'):
            return obj.to_json()

        else:
            return super(ModelEncoder, self).default(obj)