def _populate_object_prev_post_sales(self, data: dict, this_key, post_sale_map): hmo = get_crom_object(data) post_sales = data.get('post_sale', []) prev_sales = data.get('prev_sale', []) prev_post_sales_records = [(post_sales, False), (prev_sales, True)] for sales_data, rev in prev_post_sales_records: for sale_record in sales_data: pcno = sale_record.get('cat') plno = sale_record.get('lot') # plot = self.helper.shared_lot_number_from_lno(plno) pdate = implode_date(sale_record, '') if pcno and plno and pdate: if pcno == 'NA': desc = f'Also sold in an unidentified sale: {plno} ({pdate})' note = vocab.Note(ident='', content=desc) hmo.referred_to_by = note else: that_key = (pcno, plno, pdate) if rev: # `that_key` is for a previous sale for this object post_sale_map[this_key] = that_key else: # `that_key` is for a later sale for this object post_sale_map[that_key] = this_key
def object_key(data): ''' Returns a 3-tuple of (catalog number, lot number, sale date) that identify an object from a sales record, extracted from properties of the supplied `data` dict. ''' cno = data['catalog_number'] lno = data['lot_number'] date = implode_date(data, 'lot_sale_') return (cno, lno, date)
def set_lot_date(lot, auction_data, event_dates): '''Associate a timespan with the auction lot.''' date = implode_date(auction_data, 'lot_sale_') if date: begin = implode_date(auction_data, 'lot_sale_', clamp='begin') end = implode_date(auction_data, 'lot_sale_', clamp='eoe') bounds = [begin, end] else: bounds = [] if bounds: if auction_data.get('lot_sale_mod'): # if the lot sale date is marked as uncertain: # - use the event end date as the lot sale's end_of_the_end # - if the event doesn't have a known end date, assert no end_of_the_end for the lot sale if event_dates and event_dates[1]: bounds[1] = event_dates[1] else: bounds[1] = None ts = timespan_from_outer_bounds(*bounds) ts.identified_by = model.Name(ident='', content=date) lot.timespan = ts
def object_key(data): ''' Returns a 3-tuple of (catalog number, lot number, sale date) that identify an object from a sales record, extracted from properties of the supplied `data` dict. ''' try: cno = data['catalog_number'] lno = data['lot_number'] date = implode_date(data, 'lot_sale_') return (cno, lno, date) except KeyError as e: import pprint warnings.warn(f'Error in object_key call: {e}') pprint.pprint(data) raise
def __call__(self, data: dict, post_sale_map, unique_catalogs, subject_genre, destruction_types_map): '''Add modeling for an object described by a sales record''' hmo = get_crom_object(data) parent = data['parent_data'] auction_data = parent.get('auction_of_lot') if auction_data: lno = str(auction_data['lot_number']) data.setdefault('identifiers', []) if not lno: warnings.warn(f'Setting empty identifier on {hmo.id}') data['identifiers'].append(vocab.LotNumber(ident='', content=lno)) else: warnings.warn(f'***** NO AUCTION DATA FOUND IN populate_object') cno = auction_data['catalog_number'] lno = auction_data['lot_number'] date = implode_date(auction_data, 'lot_sale_') lot = self.helper.shared_lot_number_from_lno( lno ) # the current key for this object; may be associated later with prev and post object keys now_key = (cno, lno, date) data['_locations'] = [] data['_events'] = [] record = self._populate_object_catalog_record(data, parent, lot, cno, parent['pi_record_no']) self._populate_object_visual_item(data, subject_genre) self._populate_object_destruction(data, parent, destruction_types_map) self.populate_object_statements(data) self._populate_object_present_location(data, now_key, destruction_types_map) self._populate_object_notes(data, parent, unique_catalogs) self._populate_object_prev_post_sales(data, now_key, post_sale_map) for p in data.get('portal', []): url = p['portal_url'] hmo.referred_to_by = vocab.WebPage(ident=url, label=url) if 'title' in data: title = data['title'] if not hasattr(hmo, '_label'): typestring = data.get('object_type', 'Object') hmo._label = f'{typestring}: “{title}”' del data['title'] shorter = truncate_with_ellipsis(title, 100) if shorter: description = vocab.Description(ident='', content=title) description.referred_to_by = record hmo.referred_to_by = description title = shorter t = vocab.PrimaryName(ident='', content=title) t.classified_as = model.Type( ident='http://vocab.getty.edu/aat/300417193', label='Title') t.referred_to_by = record data['identifiers'].append(t) for d in data.get('other_titles', []): title = d['title'] t = vocab.Name(ident='', content=title) data['identifiers'].append(t) return data
def test_implode_date(self): full_data = {'year': '2019', 'month': '04', 'day': '08'} self.assertEqual('2019-04-08', implode_date(full_data)) self.assertEqual('2019-04-08', implode_date(full_data, clamp='begin')) self.assertEqual('2019-04-08', implode_date(full_data, clamp='end')) self.assertEqual('2019-04-09', implode_date(full_data, clamp='eoe')) prefixed_data = {'xxyear': '2019', 'xxmonth': '02'} self.assertEqual('2019-02', implode_date(prefixed_data, prefix='xx')) self.assertEqual('2019-02-01', implode_date(prefixed_data, prefix='xx', clamp='begin')) self.assertEqual('2019-02-28', implode_date(prefixed_data, prefix='xx', clamp='end')) self.assertEqual('2019-03-01', implode_date(prefixed_data, prefix='xx', clamp='eoe')) month_end_data = {'year': '2019', 'month': '02', 'day': '28'} self.assertEqual('2019-02-28', implode_date(month_end_data)) self.assertEqual('2019-02-28', implode_date(month_end_data, clamp='begin')) self.assertEqual('2019-02-28', implode_date(month_end_data, clamp='end')) self.assertEqual('2019-03-01', implode_date(month_end_data, clamp='eoe')) year_end_data = {'year': '2019', 'month': '12', 'day': '31'} self.assertEqual('2019-12-31', implode_date(year_end_data)) self.assertEqual('2019-12-31', implode_date(year_end_data, clamp='begin')) self.assertEqual('2019-12-31', implode_date(year_end_data, clamp='end')) self.assertEqual('2020-01-01', implode_date(year_end_data, clamp='eoe')) bad_month_data = {'day': '00', 'mo': '00', 'year': '1781'} self.assertEqual('1781', implode_date(bad_month_data, prefix='')) self.assertEqual('1781-01-01', implode_date(bad_month_data, prefix='', clamp='begin')) self.assertEqual('1781-12-31', implode_date(bad_month_data, prefix='', clamp='end')) self.assertEqual('1782-01-01', implode_date(bad_month_data, prefix='', clamp='eoe')) bad_day_data = {'day': '00', 'mo': '09', 'year': '1781'} self.assertEqual('1781-09', implode_date(bad_day_data, prefix='')) self.assertEqual('1781-09-01', implode_date(bad_day_data, prefix='', clamp='begin')) self.assertEqual('1781-09-30', implode_date(bad_day_data, prefix='', clamp='end')) self.assertEqual('1781-10-01', implode_date(bad_day_data, prefix='', clamp='eoe'))
def __call__(self, data: dict, event_properties): '''Add modeling data for an auction event''' cno = data['catalog_number'] auction_locations = event_properties['auction_locations'] event_experts = event_properties['experts'] event_commissaires = event_properties['commissaire'] auction = get_crom_object(data) catalog = data['_catalog']['_LOD_OBJECT'] location_data = data['location'] current = self.auction_event_location(location_data) # helper.make_place is called here instead of using make_la_place as a separate graph node because the Place object # gets stored in the `auction_locations` object to be used in the second graph component # which uses the data to associate the place with auction lots. base_uri = self.helper.make_proj_uri('AUCTION-EVENT', cno, 'PLACE', '') place_data = self.helper.make_place(current, base_uri=base_uri) place = get_crom_object(place_data) if place: data['_locations'] = [place_data] auction.took_place_at = place auction_locations[cno] = place.clone(minimal=True) begin = implode_date(data, 'sale_begin_', clamp='begin') end = implode_date(data, 'sale_end_', clamp='eoe') ts = timespan_from_outer_bounds(begin=begin, end=end, inclusive=True) event_properties['auction_dates'][cno] = (begin, end) event_record = get_crom_object(data['_record']) for seq_no, expert in enumerate(data.get('expert', [])): self.helper.copy_source_information(expert, data), person = self.helper.add_person(expert, record=event_record, relative_id=f'expert-{seq_no+1}', role='expert') event_experts[cno].append(person.clone(minimal=True)) data['_organizers'].append(add_crom_data(data={}, what=person)) role_id = '' # self.helper.make_proj_uri('AUCTION-EVENT', cno, 'Expert', seq_no) role = vocab.Expert(ident=role_id, label=f'Role of Expert in the event {cno}') role.carried_out_by = person auction.part = role for seq_no, commissaire in enumerate(data.get('commissaire', [])): self.helper.copy_source_information(commissaire, data), person = self.helper.add_person( commissaire, record=event_record, relative_id=f'commissaire-{seq_no+1}', role='commissaire') event_commissaires[cno].append(person.clone(minimal=True)) data['_organizers'].append(add_crom_data(data={}, what=person)) role_id = '' # self.helper.make_proj_uri('AUCTION-EVENT', cno, 'Commissaire', seq_no) role = vocab.CommissairePriseur( ident=role_id, label=f'Role of Commissaire-priseur in the event {cno}') role.carried_out_by = person auction.part = role notes = data.get('notes') if notes: auction.referred_to_by = vocab.Note(ident='', content=notes) if begin and end: ts.identified_by = model.Name(ident='', content=f'{begin} to {end}') elif begin: ts.identified_by = model.Name(ident='', content=f'{begin} onwards') elif end: ts.identified_by = model.Name(ident='', content=f'up to {end}') for p in data.get('portal', []): url = p['portal_url'] if url.startswith('http'): auction.referred_to_by = vocab.WebPage(ident=url, label=url) else: warnings.warn( f'*** Portal URL value does not appear to be a valid URL: {url}' ) if ts: auction.timespan = ts auction.referred_to_by = catalog return data