def test_pipe_scoped(self): x = model.Activity() y = model.Activity() x.part = y model.factory.pipe_scoped_contexts = True js = model.factory.toJSON(x) self.assertTrue('part|crm:P9_consists_of' in js) model.factory.pipe_scoped_contexts = False js = model.factory.toJSON(x) self.assertTrue('part|crm:P9_consists_of' not in js) self.assertTrue('part' in js)
def test_int_per_type(self): model.factory.auto_id_type = "int-per-type" p = model.Person() p2 = model.Person() self.assertEqual(int(p.id[-1]), int(p2.id[-1]) - 1) p3 = model.Activity() self.assertEqual(int(p.id[-1]), int(p3.id[-1]))
def test_procurement_boundary(self): vocab.add_linked_art_boundary_check() a = model.Activity() p = vocab.ProvenanceEntry() a.caused = p js = factory.toJSON(a) self.assertTrue(not 'classified_as' in js['caused'][0])
def add_imprint_orgs(data): ''' Given a `dict` representing an "article," extract the "imprint organization" records and their role (e.g. publisher, distributor), and add add a new 'organizations' key to the dictionary containing an array of `dict`s representing the organizations. Also construct an Activity for each organization's role, and associate it with the article and organization (article --role--> organization). The resulting organization `dict` will contain these keys: * `_aata_record_id`: The identifier of the corresponding article * `_aata_record_organization_seq`: A integer identifying this organization (unique within the scope of the article) * `label`: The name of the organization * `role`: The role the organization played in the article's creation (e.g. `'Publishing'`) * `properties`: A `dict` of additional properties associated with this organization's role in the article creation (e.g. `DatesOfPublication`) * `names`: A `list` of names this organization may be identified by * `identifiers`: A `list` of (identifier, identifier type) pairs * `uid`: A unique ID for this organization * `uuid`: A unique UUID for this organization used in assigning it a URN ''' lod_object = get_crom_object(data) organizations = [] for o in data.get('_organizations', []): org = {k: v for k, v in o.items()} org_obj = vocab.Group(ident=org['uri']) add_crom_data(data=org, what=org_obj) event = model.Activity() # TODO: change to vocab.Publishing for publishing activities lod_object.used_for = event event.carried_out_by = org_obj properties = o.get('properties') role = o.get('role') if role is not None: activity_names = { 'distributor': 'Distributing', 'publisher': 'Publishing', # TODO: Need to also handle roles: Organization, Sponsor, University } if role.lower() in activity_names: event_label = activity_names[role.lower()] event._label = event_label else: print('*** No/unknown organization role (%r) found for imprint_group in %s:' % ( role, lod_object,)) # pprint.pprint(o) if role == 'Publisher' and 'DatesOfPublication' in properties: pubdate = properties['DatesOfPublication'] span = CleanDateToSpan.string_to_span(pubdate) if span is not None: event.timespan = span organizations.append(org) data['organizations'] = organizations return data
def test_int_per_segment(self): model.factory._auto_id_segments = {} model.factory.auto_id_type = "int-per-segment" model.Activity._uri_segment = model.Person._uri_segment p = model.Person() p2 = model.Activity() self.assertEqual(int(p.id[-1]), int(p2.id[-1]) - 1) p3 = model.TimeSpan() self.assertEqual(int(p.id[-1]), int(p3.id[-1]))
def make_aata_org_event(o: dict): ''' Given a `dict` representing an organization, create an `model.Activity` object to represent the organization's part in the "article" creation (associating any applicable publication timespan to the activity), associate the activity with the organization and the corresponding "article", and return a new `dict` that combines the input data with an `'events'` key having a `list` value containing the new activity object. For example, ``` make_aata_org_event({ 'event_label': 'Publishing', 'publication_date_span': model.TimeSpan(...), ... }) ``` will return: ``` { 'event_label': 'Publishing', 'publication_date_span': model.TimeSpan(...), 'events': [model.Activity(_label: 'Publishing', 'timespan': ts.TimeSpan(...))], ... } ``` and also set the article object's `used_for` property to the new activity. ''' event = model.Activity() lod_object = get_crom_object(o['parent_data']) lod_object.used_for = event event._label = o.get('event_label') if 'publication_date_span' in o: ts = o['publication_date_span'] event.timespan = ts org = {k: v for k, v in o.items()} org.update({ 'events': [event], }) yield org
def test_breadth(self): x = model.TransferOfCustody() e = model.Activity() fr = model.Group() to = model.Group() w = model.ManMadeObject() fr.label = "From" to.label = "To" x.transferred_custody_of = w x.transferred_custody_from = fr x.transferred_custody_to = to e.used_specific_object = w e.carried_out_by = to w.current_owner = fr x.specific_purpose = e js = model.factory.toJSON(x) # Okay ... if we're breadth first, then custody_from is a resource # And now it's the first in the list self.assertTrue(isinstance(js['transferred_custody_from'][0], OrderedDict))
def test_int(self): model.factory.auto_id_type = "int" p = model.Person() p2 = model.Activity() self.assertEqual(int(p.id[-1]), int(p2.id[-1]) - 1)
def test_string_list(self): x = model.Activity() x.label = ["Label 1", "Label 2"] js = model.factory.toJSON(x) self.assertTrue(js['label'] == x.label)
def test_recursion(self): x = model.Activity() x.part = x js = model.factory.toJSON(x) # If our recursion checks have regressed, this will barf right here self.assertTrue(1)
def add_bidding(self, data: dict, buyers, sellers, buy_sell_modifiers, sale_type, transaction, transaction_types, auction_houses_data): '''Add modeling of bids that did not lead to an acquisition''' hmo = get_crom_object(data) parent = data['parent_data'] data['seller'] = sellers auction_data = parent['auction_of_lot'] lot_object_key = object_key(auction_data) cno, lno, date = lot_object_key lot_data = parent.get('_event_causing_prov_entry') if not lot_data: return lot = get_crom_object(lot_data) if not lot: return ts = getattr(lot, 'timespan', None) UNSOLD = transaction_types['unsold'] model_custody_return = transaction in UNSOLD prev_procurements = self.add_non_sale_sellers(data, sellers, sale_type, transaction, transaction_types) prices = parent.get('price', []) if not prices: yield data # amnts = [get_crom_object(p) for p in prices] tx_data = parent.get('_prov_entry_data') tx = get_crom_object(tx_data) houses = auction_houses_data self.add_transfer_of_custody(data, tx, xfer_to=houses, xfer_from=sellers, buy_sell_modifiers=buy_sell_modifiers, sequence=1, purpose='selling') if model_custody_return: self.add_transfer_of_custody(data, tx, xfer_to=sellers, xfer_from=houses, buy_sell_modifiers=buy_sell_modifiers, sequence=2, purpose='returning') data.setdefault('_prov_entries', []) data['_prov_entries'].append(tx_data) self.add_prev_post_owners(data, hmo, tx_data, sale_type, lot_object_key, ts) if prices: # The bidding for an object is specific to a single transaction. Therefore, # the bidding URI must not share a prefix with the object URI, otherwise all # such bidding entries are liable to be merged during URI reconciliation as # part of the prev/post sale rewriting. bidding_id = self.helper.prepend_uri_key(hmo.id, 'BID') all_bids_label = f'Bidding on {cno} {lno} ({date})' all_bids = model.Activity(ident=bidding_id, label=all_bids_label) all_bids.identified_by = model.Name(ident='', content=all_bids_label) for tx_data in prev_procurements: tx = get_crom_object(tx_data) all_bids.starts_after_the_end_of = tx all_bids.part_of = lot THROUGH = CaseFoldingSet(buy_sell_modifiers['through']) FOR = CaseFoldingSet(buy_sell_modifiers['for']) for seq_no, amnt_data in enumerate(prices): amnt = get_crom_object(amnt_data) # The individual bid and promise URIs are just the bidding URI with a suffix. # In any case where the bidding is merged, the bids and promises should be # merged as well. bid_id = bidding_id + f'-Bid-{seq_no}' bid = vocab.Bidding(ident=bid_id) prop_id = bidding_id + f'-Bid-{seq_no}-Promise' try: amnt_label = amnt._label bid_label = f'Bid of {amnt_label} on {cno} {lno} ({date})' prop = model.PropositionalObject( ident=prop_id, label=f'Promise to pay {amnt_label}') except AttributeError: bid_label = f'Bid on {cno} {lno} ({date})' prop = model.PropositionalObject(ident=prop_id, label=f'Promise to pay') bid._label = bid_label bid.identified_by = model.Name(ident='', content=bid_label) self.set_possible_attribute(prop, 'refers_to', amnt_data) prop.refers_to = amnt bid.created = prop # TODO: there are often no buyers listed for non-sold records. # should we construct an anonymous person to carry out the bid? for buyer_data in buyers: buyer = get_crom_object(buyer_data) mod = self.modifiers(buyer_data, 'auth_mod_a') if THROUGH.intersects(mod): bid.carried_out_by = buyer elif FOR.intersects(mod): warnings.warn( f'buyer modifier {mod} for non-sale bidding: {cno} {lno} {date}' ) else: bid.carried_out_by = buyer all_bids.part = bid final_owner_data = data.get('_final_org') if final_owner_data: data['_organizations'].append(final_owner_data) final_owner = get_crom_object(final_owner_data) hmo = get_crom_object(data) tx_label_args = tuple([ self.helper, sale_type, 'Sold', 'leading to the currently known location of' ] + list(lot_object_key)) tx, acq = self.final_owner_prov_entry(tx_label_args, final_owner, None, hmo, ts) note = final_owner_data.get('note') if note: acq.referred_to_by = vocab.Note(ident='', content=note) data['_prov_entries'].append(add_crom_data(data={}, what=tx)) data['_bidding'] = {'uri': bidding_id} add_crom_data(data=data['_bidding'], what=all_bids) yield data else: warnings.warn( f'*** No price data found for {parent["transaction"]!r} transaction' ) yield data
def add_bidding(self, data: dict, buyers, sellers, buy_sell_modifiers, sale_type, transaction, transaction_types, auction_houses_data): '''Add modeling of bids that did not lead to an acquisition''' hmo = get_crom_object(data) parent = data['parent_data'] data['seller'] = sellers auction_data = parent['auction_of_lot'] lot_object_key = object_key(auction_data) cno, lno, date = lot_object_key lot_data = parent.get('_event_causing_prov_entry') if not lot_data: return lot = get_crom_object(lot_data) if not lot: return ts = lot.timespan UNSOLD = transaction_types['unsold'] model_custody_return = transaction in UNSOLD prev_procurements = self.add_non_sale_sellers(data, sellers, sale_type, transaction, transaction_types) prices = parent.get('price', []) if not prices: yield data amnts = [get_crom_object(p) for p in prices] tx_data = parent.get('_prov_entry_data') tx = get_crom_object(tx_data) houses = auction_houses_data self.add_transfer_of_custody(data, tx, xfer_to=houses, xfer_from=sellers, sequence=1, purpose='selling') if model_custody_return: self.add_transfer_of_custody(data, tx, xfer_to=sellers, xfer_from=houses, sequence=2, purpose='returning') data.setdefault('_prov_entries', []) data['_prov_entries'].append(tx_data) if amnts: bidding_id = hmo.id + '-Bidding' all_bids_label = f'Bidding on {cno} {lno} ({date})' all_bids = model.Activity(ident=bidding_id, label=all_bids_label) all_bids.identified_by = model.Name(ident='', content=all_bids_label) for tx_data in prev_procurements: tx = get_crom_object(tx_data) all_bids.starts_after_the_end_of = tx all_bids.part_of = lot THROUGH = set(buy_sell_modifiers['through']) FOR = set(buy_sell_modifiers['for']) for seq_no, amnt in enumerate(amnts): bid_id = hmo.id + f'-Bid-{seq_no}' bid = vocab.Bidding(ident=bid_id) prop_id = hmo.id + f'-Bid-{seq_no}-Promise' try: amnt_label = amnt._label bid_label = f'Bid of {amnt_label} on {cno} {lno} ({date})' prop = model.PropositionalObject( ident=prop_id, label=f'Promise to pay {amnt_label}') except AttributeError: bid_label = f'Bid on {cno} {lno} ({date})' prop = model.PropositionalObject(ident=prop_id, label=f'Promise to pay') bid._label = bid_label bid.identified_by = model.Name(ident='', content=bid_label) prop.refers_to = amnt bid.created = prop # TODO: there are often no buyers listed for non-sold records. # should we construct an anonymous person to carry out the bid? for buyer_data in buyers: buyer = get_crom_object(buyer_data) mod = buyer_data.get('auth_mod_a', '') if mod in THROUGH: bid.carried_out_by = buyer elif mod in FOR: warnings.warn( f'buyer modifier {mod} for non-sale bidding: {cno} {lno} {date}' ) else: bid.carried_out_by = buyer all_bids.part = bid final_owner_data = data.get('_final_org') if final_owner_data: data['_organizations'].append(final_owner_data) final_owner = get_crom_object(final_owner_data) hmo = get_crom_object(data) tx_label_args = tuple([ self.helper, sale_type, 'Sold', 'leading to the currently known location of' ] + list(lot_object_key)) tx, acq = self.final_owner_procurement(tx_label_args, final_owner, None, hmo, ts) note = final_owner_data.get('note') if note: acq.referred_to_by = vocab.Note(ident='', content=note) data['_prov_entries'].append(add_crom_data(data={}, what=tx)) data['_bidding'] = {'uri': bidding_id} add_crom_data(data=data['_bidding'], what=all_bids) yield data else: warnings.warn( f'*** No price data found for {parent["transaction"]!r} transaction' ) yield data