示例#1
0
    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
示例#2
0
    def __call__(self, data, non_auctions, event_properties,
                 problematic_records, transaction_types):
        '''Add modeling data for the auction of a lot of objects.'''
        self.helper.copy_source_information(data['_object'], data)

        auction_houses_data = event_properties['auction_houses']

        auction_locations = event_properties['auction_locations']
        auction_data = data['auction_of_lot']
        try:
            lot_object_key = object_key(auction_data)
        except Exception as e:
            warnings.warn(
                f'Failed to compute lot object key from data {auction_data} ({e})'
            )
            pprint.pprint({k: v
                           for k, v in data.items() if v != ''},
                          stream=sys.stderr)
            raise
        cno, lno, date = lot_object_key
        sale_type = non_auctions.get(cno, 'Auction')

        ask_price = data.get('ask_price', {}).get('ask_price')
        if ask_price:
            # if there is an asking price/currency, it's a direct sale, not an auction;
            # filter these out from subsequent modeling of auction lots.
            warnings.warn(
                f'Skipping {cno} {lno} because it asserts an asking price')
            return

        if sale_type != 'Auction':
            # the records in this sales catalog do not represent auction sales, so the
            # price data should not be asserted as a sale price, but instead as an
            # asking price.
            with suppress(KeyError):
                prices = data['price']
                del data['price']
                if prices:
                    price_data = prices[0]
                    price = get_crom_object(price_data)
                    if price:
                        ma = vocab.add_classification(price, vocab.AskingPrice)
                        data['ask_price'] = add_crom_data(price_data, ma)

        shared_lot_number = self.helper.shared_lot_number_from_lno(lno)
        uid, uri = self.helper.shared_lot_number_ids(cno, lno, date)
        sale_data = {'uid': uid, 'uri': uri}

        lot = self.helper.sale_for_sale_type(sale_type, lot_object_key)
        data['lot_object_id'] = f'{cno} {lno} ({date})'

        if 'link_to_pdf' in auction_data:
            url = auction_data['link_to_pdf']
            page = vocab.WebPage(ident=url, label=url)
            lot.referred_to_by = page

        for problem_key, problem in problematic_records.get('lots', []):
            # TODO: this is inefficient, but will probably be OK so long as the number
            #       of problematic records is small. We do it this way because we can't
            #       represent a tuple directly as a JSON dict key, and we don't want to
            #       have to do post-processing on the services JSON files after loading.
            if tuple(problem_key) == lot_object_key:
                note = model.LinguisticObject(ident='', content=problem)
                problem_classification = model.Type(
                    ident=self.helper.problematic_record_uri,
                    label='Problematic Record')
                problem_classification.classified_as = vocab.instances[
                    "brief text"]
                note.classified_as = problem_classification
                lot.referred_to_by = note

        cite_content = []
        if data.get('transaction_so'):
            cite_content.append(data['transaction_so'])
        if data.get('transaction_cite'):
            cite_content.append(data['transaction_cite'])
        if cite_content:
            content = ', '.join(cite_content)
            cite = vocab.BibliographyStatement(
                ident='', content=content, label='Source of transaction type')
            cite.identified_by = model.Name(
                ident='', content='Source of transaction type')
            lot.referred_to_by = cite

        transaction = data.get('transaction')
        SOLD = transaction_types['sold']
        WITHDRAWN = transaction_types['withdrawn']
        self.set_lot_objects(lot, cno, lno, sale_data['uri'], data, sale_type)
        auction, _, _ = self.helper.sale_event_for_catalog_number(
            cno, sale_type)
        if transaction not in WITHDRAWN:
            lot.part_of = auction
            event_dates = event_properties['auction_dates'].get(cno)

            auction_houses = [
                get_crom_object(self.helper.add_auction_house_data(h.copy()))
                for h in auction_houses_data.get(cno, [])
            ]

            self.set_lot_auction_houses(lot, cno, auction_houses)
            self.set_lot_location(lot, cno, auction_locations)
            self.set_lot_date(lot, auction_data, event_dates)
            self.set_lot_notes(lot, auction_data, sale_type)

            tx_uri = self.helper.transaction_uri_for_lot(auction_data, data)
            lots = self.helper.lots_in_transaction(auction_data, data)
            tx = vocab.ProvenanceEntry(ident=tx_uri)
            tx_label = prov_entry_label(self.helper, sale_type, transaction,
                                        'of', cno, lots, date)
            tx._label = tx_label
            tx.identified_by = model.Name(ident='', content=tx_label)
            tx.caused_by = lot
            tx_data = {'uri': tx_uri}

            if transaction in SOLD:
                if sale_type == 'Auction':
                    # the records in this sales catalog represent auction sales, so the
                    # price data for a sale should be asserted as a hammer price.
                    with suppress(KeyError):
                        prices = data['price']
                        if prices:
                            price_data = prices[0]
                            price = get_crom_object(price_data)
                            if price:
                                vocab.add_classification(
                                    price, vocab.HammerPrice)

                multi = self.helper.transaction_contains_multiple_lots(
                    auction_data, data)
                if multi:
                    tx_data['multi_lot_tx'] = lots

            with suppress(AttributeError):
                tx_data['_date'] = lot.timespan
            data['_prov_entry_data'] = add_crom_data(data=tx_data, what=tx)

            data['_event_causing_prov_entry'] = add_crom_data(data=sale_data,
                                                              what=lot)
        yield data
示例#3
0
	def __call__(self, data:dict, event_properties, date_modifiers):
		'''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)
		if not current:
			print(f'*** Empty location data: {pprint.pformat(location_data)}')
			pprint.pprint(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', '')
		record = get_crom_object(data.get('_record'))
		
		current_p = current
		locs = []
		while current_p:
			l = current_p.get('name')
			if l:
				locs.append(l)
			current_p = current_p.get('part_of')
		loc = ', '.join(locs) if len(locs) else None
		canonical_place = self.helper.get_canonical_place(loc)
		if canonical_place:
			place = canonical_place
			place_data = add_crom_data(data={'uri': place.id}, what=place)
		else:
			place_data = self.helper.make_place(current, base_uri=base_uri, record=record)
			place = get_crom_object(place_data)

		if place:
			data['_locations'] = [place_data]
			auction.took_place_at = place
			auction_locations[cno] = place.clone(minimal=True)

		ts, begin, end = timespan_from_bound_components(
			data,
			date_modifiers,
			'sale_begin_', 'begin',
			'sale_end_', 'eoe'
		)

		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 'links' in data:
			event_record = get_crom_object(data['_record'])
			links = data['links']
			link_keys = set(links.keys()) - {'portal'}
			for p in links.get('portal', []):
				url = p['portal_url']
				if url.startswith('http'):
					event_record.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}')
			for k in link_keys:
				url = links[k]
				if isinstance(url, str):
					event_record.referred_to_by = vocab.WebPage(ident=url, label=url)
				else:
					print(f'*** not a URL string: {k}: {url}')

		if ts:
			auction.timespan = ts

		auction.referred_to_by = catalog
		return data
示例#4
0
文件: events.py 项目: kasei/pipeline
    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