def _term(self, token): if token.startswith('='): kwstr = token[1:] try: kw = self.model.keyword(kwstr) except UnicodeEncodeError: raise ExprError('invalid keyword %r' % kwstr) except LookupError: raise ExprError('no such keyword %r' % kwstr) return keyed_with(kw) elif token.startswith('in:'): try: place = self.model.lookup_place(token[3:]) except LookupError as e: raise ExprError('no such place %r' % token[3:]) return in_place(place) elif (token.startswith('work:') or token.startswith('loc:') or token.startswith('with:') or token.startswith('ex:')): i = token.index(':') cond = token[:i] name = token[i+1:] try: org = self.model.find(Organisation, name) except LookupError: raise ExprError('no such organisation %r' % name) select = { 'work': outgoing & is_link(Works_at) & to_node(org), 'loc': outgoing & is_link(Located_at) & to_node(org), 'with': outgoing & is_link(With) & to_node(org), 'ex': outgoing & is_link(Ex) & to_node(org), }[cond] return node_predicate(lambda node: not iempty(node.links(select))) else: return name_imatches(token)
def keyed_with(keyword): r'''Return a predicate that returns true if the node at the other end of the link linked to the given keyword node. ''' def _pred(node): return bool(node.link(outgoing & is_link(Keyed_with) & to_node(keyword))) return node_predicate(_pred)
def report_dump(options, model, predicate, local): sort_mode = sort_modes.get(options.sort_mode, SortMode.FIRST_NAME) # If no predicate given, then select all people, organisations, and # families. if predicate is None: predicate = node_predicate(lambda node: True) # Populate the top level of the report with all the nodes that satisfy the # predicate. itemiser = Itemiser(sort_mode) itemiser.update(model.nodes(is_other(instance_p(NamedNode) & predicate))) # These sets control where entries are listed. seen = set(itemiser) see_in = defaultdict(set) alias = dict() # Form the sorted index of all the top-level entries in the report. toplevel = sorted(chain(list(itemiser.items()), itemiser.alias_items(iter(alias.items())))) # Remove unnecessary references. cull_references(toplevel) # Now format the report. from sixx.output import Treebuf tree = Treebuf(local=local, sort_mode=sort_mode) for item in toplevel: if item.node is None: pass elif item is not item.single: tree.nl() tree.add(item.key, ' -> ', item.single.key) tree.nl() elif isinstance(item.node, Person): tree.nl() dump_names(item.node, tree, name=item.key) dump_person(item.node, tree.sub(), seen - see_in.get(item.node, set())) elif isinstance(item.node, Family): tree.nl() dump_names(item.node, tree, name=item.key) dump_family(item.node, tree.sub(), seen - see_in.get(item.node, set())) elif isinstance(item.node, Department): tree.nl() dump_names(item.node, tree, name=item.key) dump_organisation(item.node, tree.sub(), seen - see_in.get(item.node, set())) elif isinstance(item.node, Organisation): tree.nl() dump_names(item.node, tree, name=item.key) dump_organisation(item.node, tree.sub(), seen - see_in.get(item.node, set())) if options.output_path: ofile = file(options.output_path, 'wb', encoding=options.encoding, errors='replace') else: ofile = sys.stdout ofile.write(str(tree))
def report_email(options, model, predicate, local): if predicate is None: predicate = node_predicate(lambda node: True) options.all = False itemiser = Itemiser() itemiser.update(model.nodes(is_other(instance_p(NamedNode) & predicate))) # Remove entries for families for which one or more of the heads was found. for person in [node for node in itemiser if isinstance(node, Person)]: for belongs_to in person.links(outgoing & is_link(Belongs_to)): if belongs_to.is_head: itemiser.discard(belongs_to.family) for item in sorted(itemiser.items()): if item is not item.single: continue node = item.node print_emails(node, options.encoding) stop = lambda node: False if isinstance(node, Organisation): pred = ((incoming & is_link(Works_at)) | (outgoing & is_link(Belongs_to)) | (outgoing & is_link(Resides_at))) if not options.all: stop = instance_p(Person) elif isinstance(node, Family): pred = ((outgoing & is_link(Works_at)) | (incoming & is_link(Belongs_to)) | (outgoing & is_link(Resides_at))) if not options.all: stop = instance_p(Organisation) elif isinstance(node, Person): pred = ((outgoing & is_link(Belongs_to)) | (outgoing & is_link(Resides_at)) | (outgoing & is_link(Works_at))) if not options.all: stop = instance_p(Organisation) for tup in sorted(node.find_nodes(pred, stop=stop), key=len): print_emails(tup[-1], options.encoding)
def report_book(options, model, predicate, local): if not options.output_path: raise InputError("missing --output option") # If no predicate given, then select all people, organisations, and # families. if predicate is None: predicate = node_predicate(lambda node: True) # Populate the top level of the report with all the nodes that satisfy the # predicate. itemiser = Itemiser() itemiser.update(model.nodes(is_other(instance_p(NamedNode) & predicate))) # Top level references. A dictionary that maps top level node to the node # in whose entry it appears. refs = dict() # Add top level nodes that are implied by the predicate: # - A selected department imples its parent company and all intermediate # departments. Departments are always listed within the entry of their # parent company, so they are never listed as top level entries. Any # Departments at the top level are there because they were selected by # the predicate, so these are converted into references to their # company's entry. for node in list(itemiser): if isinstance(node, Department): dept = node com = dept.company() itemiser.discard(dept) itemiser.add(com) assert dept not in refs refs[dept] = com # Add top level nodes that are implied by the predicate: # - A selected person implies the family(ies) they belong to. If a person # belongs to only one family, then that person's top level entry becomes # a reference to their family. for node in list(itemiser): if isinstance(node, Person): person = node # Omit top-level entries for people who belong to a single family # or who work for a single organisation, if the family/org has its # own top-level entry. Instead, their details will get listed # within that entry. Any top level entries for heads of families # get turned into aliases for the family. belongs_to = list(person.links(outgoing & is_link(Belongs_to))) if len(belongs_to) == 1 and belongs_to[0].family in itemiser: itemiser.discard(person) if belongs_to[0].is_head and person in refs: refs[person] = belongs_to[0].family # Form the sorted index of all the top-level entries in the report, and # the 'refs' dictionary. toplevel = sorted(chain(list(itemiser.items()), itemiser.alias_items(iter(refs.items())))) refs.update(list(zip(itemiser, itemiser))) # Remove unnecessary references. cull_references(toplevel) # Format the report. booklet = Booklet( predicate=predicate, refs=refs, local=local, page_size=page_sizes[options.pagesize], sections=sections[options.sections], ) for item in toplevel: if item.node is not None: booklet.add_entry(item) booklet.write_pdf_to(options.output_path)