def extended_sources(ids, schemes): """Return a dict of Source instances, with extra attributes :param schemes: Either None or a set. If specified, it will contain the set of surety schemes necessary to represent the assertions. """ assert (isinstance(ids, list)) assert schemes is None or isinstance(schemes, set) sources = dict() # id -> Source for s in sql_in( models.Source.objects.select_related("repositories", "researcher"), "id", ids): sources[s.id] = s s.asserts = [] # Assertions deducted from this source p2e = models.P2E.objects.select_related() for c in sql_in(p2e, "source", ids): sources[c.source_id].asserts.append(c) if schemes is not None: schemes.add(c.surety.scheme_id) p2c = models.P2C.objects.select_related() for c in sql_in(p2c, "source", ids): sources[c.source_id].asserts.append(c) if schemes is not None: schemes.add(c.surety.scheme_id) return sources
def extended_events(ids): """Return a dict of Event instances, augmented with the following fields: - "p2e": a list of instances of P2E for this event """ assert (isinstance(ids, list)) events = dict() # id -> ExtendedEvent p2e = models.P2E.objects.select_related() for a in sql_in(p2e, "event", ids): assert isinstance(a, models.P2E) ev = events.get(a.event_id, {'p2e': []}) events[a.event_id] = ev p2e = { 'disproved': a.disproved, 'rationale': a.rationale, 'role_name': a.role.name, 'person': { 'name': a.person.name, 'id': a.person_id }, 'surety': a.surety_id, 'source': { 'id': a.source_id } } ev['p2e'].append(p2e) return events
def extended_events(ids): """Return a dict of Event instances, augmented with the following fields: - "p2e": a list of instances of P2E for this event """ assert(isinstance(ids, list)) events = dict() # id -> ExtendedEvent p2e = models.P2E.objects.select_related() for a in sql_in(p2e, "event", ids): assert isinstance(a, models.P2E) ev = events.get(a.event_id, {'p2e': []}) events[a.event_id] = ev p2e = { 'disproved': a.disproved, 'rationale': a.rationale, 'role_name': a.role.name, 'person': { 'name': a.person.name, 'id': a.person_id }, 'surety': a.surety_id, 'source': { 'id': a.source_id } } ev['p2e'].append(p2e) return events
def extended_events(ids): """Return a dict of Event instances, augmented with the following fields: - "p2e": a list of instances of P2E for this event """ assert(isinstance(ids, list)) events = dict() # id -> ExtendedEvent p2e = models.P2E.objects.select_related() for a in sql_in(p2e, "event", ids): events[a.event_id] = ev = events.get(a.event_id, a.event) p = ev.p2e = getattr(ev, "p2e", []) p.append(a) return events
def extended_personas( nodes, styles, graph, p2e=None, event_types=None, schemes=None, p2c=None, p2g=None, all_sources=None, as_css=False, query_groups=True): """ Compute the events for the various persons in `nodes` (all all persons in the database if None) Return a dict indexed on id containing extended instances of Persona, with additional fields for the birth, the death,... :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. :param dict all_sources: either a dictionary, or None. If specified, it will be filled with "sourceId -> models.Source" objects :param as_css: True to get the styles as a CSS string rather than a python dict :param event_types: restricts the types of events that are retrieved :param dict p2e: All person-to-event assertions :param dict p2c: All persona-to-characteristic assertions :param dict p2g: All persona-to-group assertions :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)) if styles: styles.start() # 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 event_types: events = events.filter(event__type__in=event_types) all_ids = None if nodes: all_ids = set() for p in nodes: all_ids.update(p.ids) # All query the 'principal' for each events, so that we can provide # that information graphically. for p in sql_in(events, "person", all_ids): e = p.event p_node = graph.node_from_id(p.person_id) person = persons[p_node.main_id] # ??? A person could be involved multiple times in the same # event, under multiple roles. Here we are only preserving the # last occurrence if p2e is not None: # ??? Should we reset p.p1, since this is always the same p2e[e.id] = p if all_sources is not None: all_sources.setdefault(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] if p2g is not None: p2g[gr.group_id] = gr if all_sources is not None: all_sources.setdefault(gr.source_id, {}) if schemes is not None: schemes.add(gr.surety.scheme_id) ######### # Get all characteristics of these personas ######### c2p = 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] c2p[c.id] = person if all_sources is not None: all_sources.setdefault(p.source_id, {}) c.date = c.date and DateRange(c.date) if schemes is not None: schemes.add(p.surety.scheme_id) if p2c is not None: # ??? Should we reset p.person, since this is always the same # ??? but can't set it to None in the model p2c[c.id] = p 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 c2p.keys()): person = c2p[part.characteristic_id] 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 ########## # Get the title for all sources that are mentioned ########## if all_sources is not None: for s in sql_in(models.Source.objects, "id", all_sources.keys()): all_sources[s.id] = s ########## # Compute the styles ########## if styles: for p in persons.itervalues(): styles.compute(p, as_css=as_css) return persons
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
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
def extended_personas( nodes, styles, graph, asserts=None, event_types=None, schemes=None, as_css=False, query_groups=True): """ Compute the events for the various persons in `nodes` (all all persons in the database if None) Return a dict indexed on id containing extended instances of Persona, with additional fields for the birth, the death,... :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. :param as_css: True to get the styles as a CSS string rather than a python dict :param event_types: restricts the types of events that are retrieved :param list asserts: All assertions :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 assert schemes is None or isinstance(schemes, set) if styles: styles.start() # Get the role names logger.debug('MANU getting 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) logger.debug('MANU retrieve personas') ################ # Check all events that the persons were involved in. ################ events = models.P2E.objects.select_related( 'event', 'event__type', *models.P2E.related_json_fields()) if event_types: events = events.filter(event__type__in=event_types) all_ids = None if nodes: all_ids = set() for p in nodes: all_ids.update(p.ids) logger.debug('MANU about to retrieve events') birth = None death = None # Also query the 'principal' for each events, so that we can provide # that information graphically. for p in sql_in(events, "person", all_ids): e = p.event p_node = graph.node_from_id(p.person_id) person = persons[p_node.main_id] # ??? A person could be involved multiple times in the same # event, under multiple roles. Here we are only preserving the # last occurrence if asserts is not None: asserts.append(p) # ??? Could we take advantage of the e.date_sort string, instead # of reparsing the DateRange ? e.Date = e.date and DateRange(e.date) if schemes is not None: schemes.add(p.surety.scheme_id) if styles: styles.process(person, p.role_id, e) if not p.disproved \ and p.role_id == models.Event_Type_Role.PK_principal: if not e.Date: pass elif e.type_id == models.Event_Type.PK_birth: if birth is None or more_recent(birth, e): person.birthISODate = e.date_sort elif e.type_id == models.Event_Type.PK_death: if death is None or more_recent(death, e): person.deathISODate = e.date_sort elif e.type_id == models.Event_Type.PK_marriage: person.marriageISODate = e.date_sort logger.debug('MANU done processing events') ######### # Get all groups to which the personas belong ######### # if query_groups: # groups = models.P2G.objects.select_related( # *models.P2G.related_json_fields()) # # for gr in sql_in(groups, "person", all_ids): # p_node = graph.node_from_id(gr.person_id) # person = persons[p_node.main_id] # # if asserts is not None: # asserts.append(gr) # # if schemes is not None: # schemes.add(gr.surety.scheme_id) ######### # Get all characteristics of these personas ######### if asserts: asserts.extend(sql_in( models.P2C.objects.select_related(*models.P2C.related_json_fields()), "person", all_ids)) # logger.debug('MANU processing p2c') # c2p = dict() # characteristic_id -> person # all_p2c = models.P2C.objects.select_related( # *models.P2C.related_json_fields()) # # 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] # c2p[c.id] = person # # c.date = c.date and DateRange(c.date) # # if schemes is not None: # schemes.add(p.surety.scheme_id) # # if asserts is not None: # asserts.append(p) # logger.debug('MANU processing characteristic parts') # # chars = models.Characteristic_Part.objects.select_related( # 'type', 'characteristic').filter( # type__in=(models.Characteristic_Part_Type.PK_sex, )).order_by() # # for part in sql_in(chars, "characteristic", nodes and c2p): # person = c2p[part.characteristic_id] # # if part.type_id == models.Characteristic_Part_Type.PK_sex: # person.sex = 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. ######## # logger.debug('MANU processing places') # # 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): # # # ??? 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 ########## # Compute the styles ########## if styles: logger.debug('MANU compute styles') for p in persons.values(): styles.compute(p, as_css=as_css) return persons