Ejemplo n.º 1
0
 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
                 elif 'or' in plno.lower():
                     desc = f'Also sold in an uncertain lot: {pcno} {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
Ejemplo n.º 2
0
    def handle_places(self, data):
        base_uri = self.helper.make_proj_uri('PLACE', '')
        for loc in data.get('locations', []):
            l = loc.get('location')
            if l:
                current = parse_location_name(l,
                                              uri_base=self.helper.proj_prefix)
                place_data = self.helper.make_place(current, base_uri=base_uri)
                data['places'].append(place_data)
                note = loc.get('location_note')
                if note:
                    note = vocab.Note(ident='', content=note)
                    data['referred_to_by'].append(note)
                date = loc.get('location_date')
                if date:
                    note = vocab.BibliographyStatement(
                        ident='', content=f'Residence in {l} ({date})')
                    data['referred_to_by'].append(note)

            address = loc.get('address')
            if address:
                contact = model.Identifier(ident='', content=address)
                contact_data = add_crom_data(data={}, what=contact)
                data['contact_point'].append(contact_data)
                note = loc.get('address_note')
                if note:
                    note = vocab.Note(ident='', content=note)
                    data['referred_to_by'].append(note)
                date = loc.get('address_date')
                if date:
                    note = vocab.BibliographyStatement(
                        ident='', content=f'Address at {l} ({date})')
                    data['referred_to_by'].append(note)
Ejemplo n.º 3
0
    def model_record_desc_group(self, record, data):
        record.setdefault('referred_to_by', [])
        record.setdefault('identifiers', [])

        jid = data['record_id']
        inote = data.get('internal_note')
        snote = data.get('source_note')
        record['identifiers'].append(self.helper.gci_number_id(jid))

        if inote:
            record['referred_to_by'].append(vocab.Note(ident='',
                                                       content=inote))
        if snote:
            record['referred_to_by'].append(vocab.Note(ident='',
                                                       content=snote))
Ejemplo n.º 4
0
 def add_mod_notes(self, act, all_mods, label):
     if act and all_mods:
         # Preserve the seller modifier strings as notes on the acquisition/bidding activity
         for mod in all_mods:
             note = vocab.Note(ident='', label=label, content=mod)
             note.classified_as = vocab.instances['qualifier']
             act.referred_to_by = note
Ejemplo n.º 5
0
    def handle_statements(self, data):
        text_content = data.get('text')
        if text_content:
            cite = vocab.BiographyStatement(ident='', content=text_content)
            data['referred_to_by'].append(cite)

        source_content = data.get('source')
        if source_content:
            cite = vocab.BibliographyStatement(ident='',
                                               content=source_content)
            data['referred_to_by'].append(cite)

        project = data.get('project')
        if project:
            data['referred_to_by'].append(
                vocab.SourceStatement(ident='', content=project))

        awards = {
            l.strip()
            for l in data.get('medal_received', '').split(';')
        } - {''}
        for award in awards:
            cite = vocab.Note(
                ident='', content=award
            )  # TODO: add proper classification for an Awards Statement
            data['referred_to_by'].append(cite)
Ejemplo n.º 6
0
    def __call__(self, data):
        d = {k: v for k, v in data.items()}
        parent = data['parent_data']
        cno = str(parent['catalog_number'])
        sno = parent['star_record_no']
        entry_record = get_crom_object(data.get('_catalog'))
        catalog = get_crom_object(d)
        for lugt_no in parent.get('lugt', {}).values():
            if not lugt_no:
                warnings.warn(f'Setting empty identifier on {catalog.id}')
            catalog.identified_by = self.lugt_number_id(lugt_no)

        if not cno:
            warnings.warn(f'Setting empty identifier on {catalog.id}')

        catalog.identified_by = self.helper.gpi_number_id(
            cno, vocab.LocalNumber)

        if not sno:
            warnings.warn(f'Setting empty identifier on {catalog.id}')
        catalog.identified_by = self.helper.gpi_number_id(
            sno, vocab.StarNumber)
        notes = data.get('notes')
        if notes:
            note = vocab.Note(ident='', content=parent['notes'])
            catalog.referred_to_by = note
        return d
Ejemplo n.º 7
0
    def populate_destruction_events(self,
                                    data: dict,
                                    note,
                                    *,
                                    type_map,
                                    location=None):
        destruction_types_map = type_map
        hmo = get_crom_object(data)
        title = data.get('title')
        short_title = truncate_with_ellipsis(title, 100) or title

        r = re.compile(
            r'[Dd]estroyed(?: (?:by|during) (\w+))?(?: in (\d{4})[.]?)?')
        m = r.search(note)
        if m:
            method = m.group(1)
            year = m.group(2)
            # The destruction URI is just the object URI with a suffix. When URIs are
            # reconciled during prev/post sale rewriting, this will allow us to also reconcile
            # the URIs for the destructions (of which there should only be one per object)
            dest_uri = hmo.id + '-Destruction'

            d = model.Destruction(ident=dest_uri,
                                  label=f'Destruction of “{short_title}”')
            d.referred_to_by = vocab.Note(ident='', content=note)
            if year is not None:
                begin, end = date_cleaner(year)
                ts = timespan_from_outer_bounds(begin, end)
                ts.identified_by = model.Name(ident='', content=year)
                d.timespan = ts

            if method:
                with suppress(KeyError, AttributeError):
                    type_name = destruction_types_map[method.lower()]
                    otype = vocab.instances[type_name]
                    event = model.Event(
                        label=
                        f'{method.capitalize()} event causing the destruction of “{short_title}”'
                    )
                    event.classified_as = otype
                    d.caused_by = event
                    data['_events'].append(add_crom_data(data={}, what=event))

            if location:
                current = parse_location_name(
                    location, uri_base=self.helper.uid_tag_prefix)
                # The place URI used for destruction events is based on the object URI with
                # a suffix. When URIs are reconciled during prev/post sale rewriting, this
                # will allow us to also reconcile the URIs for the places of destruction
                # (of which there should only be one hierarchy per object)
                base_uri = hmo.id + '-Destruction-Place,'
                place_data = self.helper.make_place(current, base_uri=base_uri)
                place = get_crom_object(place_data)
                if place:
                    data['_locations'].append(place_data)
                    d.took_place_at = place

            hmo.destroyed_by = d
Ejemplo n.º 8
0
    def model_authorship_group(self, record, data):
        if not data:
            return
        record.setdefault('_people', [])
        record.setdefault('created_by', [])
        authors = _as_list(data.get('primary_author'))

        mlap = MakeLinkedArtPerson()
        mlao = MakeLinkedArtOrganization()

        ordered_data = []
        article_label = record['label']
        creation_id = record['uri'] + '-Creation'
        creation = model.Creation(ident=creation_id,
                                  label=f'Creation of {article_label}')
        for a in authors:
            gaia_id = a['gaia_authority_id']
            gaia_type = a['gaia_authority_type']
            name = a['author_name']
            roles = _as_list(a['author_role'])
            order = a['author_order']

            ordered_data.append((order, name))

            p = {
                'label': name,
                'name': name,
            }

            if gaia_type == 'Person':
                uri = self.helper.person_uri(gaia_id)
                p['uri'] = uri
                mlap(p)
            elif gaia_type == 'Corp':
                uri = self.helper.corporate_body_uri(gaia_id)
                p['uri'] = uri
                mlao(p)
            else:
                raise Exception(
                    f'Unexpected type of authorship record: {gaia_type}')
# 				uri = self.helper.make_proj_uri(gaia_type, 'GAIA', gaia_id)

            record['_people'].append(p)

            for role in roles:
                part = model.Creation(ident='',
                                      label=f'{role} Creation sub-event')
                part.carried_out_by = get_crom_object(p)
                cl = self.helper.role_type(role)
                if cl:
                    part.classified_as = cl
                creation.part = part

        ordered_authors = [p[1] for p in sorted(ordered_data)]
        order_string = self.helper.ordered_author_string(ordered_authors)
        creation.referred_to_by = vocab.Note(ident='', content=order_string)
        record['created_by'].append(creation)
Ejemplo n.º 9
0
    def model_notes_group(self, record, data):
        if not data:
            return
        record.setdefault('_declared_languages', set())
        record.setdefault('language', [])
        record.setdefault('identifiers', [])
        record.setdefault('referred_to_by', [])

        lang_docs = _as_list(data.get('lang_doc'))
        lang_summaries = _as_list(data.get('lang_summary'))
        isbns = _as_list(data.get('isbn'))
        issns = _as_list(data.get('issn'))
        citation_note = data.get('citation_note')
        inotes = _as_list(data.get('internal_note'))

        for lang in lang_summaries:
            record['_declared_languages'].add(lang)

        for lang in lang_docs:
            record['_declared_languages'].add(lang)
            l = self.helper.language_object_from_code(lang)
            if l:
                record['language'].append(l)

        for isbn in isbns:
            num = isbn.get('isbn_number')
            q = isbn.get('isbn_qualifier')
            if num:
                i = vocab.IsbnIdentifier(ident='', content=num)
                if q:
                    i.referred_to_by = vocab.Note(ident='', content=q)
                record['identifiers'].append(i)

        for issn in issns:
            i = vocab.IssnIdentifier(ident='', content=issn)
            record['identifiers'].append(i)

        if citation_note:
            record['referred_to_by'].append(
                vocab.Citation(ident='', content=citation_note))

        for inote in inotes:
            record['referred_to_by'].append(
                vocab.Note(ident='', content=inote['note']))
Ejemplo n.º 10
0
 def set_referred_to_by(self, data, thing):
     for notedata in data.get('referred_to_by', []):
         if isinstance(notedata, tuple):
             content, itype = notedata
             if itype is not None:
                 if isinstance(itype, type):
                     note = itype(content=content)
                 elif isinstance(itype, object):
                     note = itype
                     note.content = content
                 else:
                     note = vocab.Note(content=content)
                     note.classified_as = itype
         elif isinstance(notedata, model.BaseResource):
             note = notedata
         elif isinstance(notedata, str):
             note = vocab.Note(content=notedata)
         else:
             note = notedata
         thing.referred_to_by = note
Ejemplo n.º 11
0
 def set_lot_notes(self, lot, auction_data, sale_type):
     '''Associate notes with the auction lot.'''
     cno, lno, _ = object_key(auction_data)
     notes = auction_data.get('lot_notes')
     if notes:
         note_id = lot.id + '-Notes'
         lot.referred_to_by = vocab.Note(ident=note_id, content=notes)
     if not lno:
         warnings.warn(f'Setting empty identifier on {lot.id}')
     lno = str(lno)
     lot.identified_by = vocab.LotNumber(ident='', content=lno)
Ejemplo n.º 12
0
    def populate_destruction_events(self,
                                    data: dict,
                                    note,
                                    *,
                                    type_map,
                                    location=None):
        destruction_types_map = type_map
        hmo = get_crom_object(data)
        title = data.get('title')
        short_title = truncate_with_ellipsis(title, 100) or title

        r = re.compile(
            r'[Dd]estroyed(?: (?:by|during) (\w+))?(?: in (\d{4})[.]?)?')
        m = r.search(note)
        if m:
            method = m.group(1)
            year = m.group(2)
            dest_id = hmo.id + '-Destr'
            d = model.Destruction(ident=dest_id,
                                  label=f'Destruction of “{short_title}”')
            d.referred_to_by = vocab.Note(ident='', content=note)
            if year is not None:
                begin, end = date_cleaner(year)
                ts = timespan_from_outer_bounds(begin, end)
                ts.identified_by = model.Name(ident='', content=year)
                d.timespan = ts

            if method:
                with suppress(KeyError, AttributeError):
                    type_name = destruction_types_map[method.lower()]
                    otype = vocab.instances[type_name]
                    event = model.Event(
                        label=
                        f'{method.capitalize()} event causing the destruction of “{short_title}”'
                    )
                    event.classified_as = otype
                    d.caused_by = event
                    data['_events'].append(add_crom_data(data={}, what=event))

            if location:
                current = parse_location_name(
                    location, uri_base=self.helper.uid_tag_prefix)
                base_uri = hmo.id + '-Place,'
                place_data = self.helper.make_place(current, base_uri=base_uri)
                place = get_crom_object(place_data)
                if place:
                    data['_locations'].append(place_data)
                    d.took_place_at = place

            hmo.destroyed_by = d
Ejemplo n.º 13
0
 def set_lot_notes(self, lot, auction_data, sale_type):
     '''Associate notes with the auction lot.'''
     cno, lno, _ = object_key(auction_data)
     notes = auction_data.get('lot_notes')
     if notes:
         # In case the lot is reconciled with another lot, notes should not be merged.
         # Therefore, the note URI must not share a prefix with the lot URI, otherwise
         # all notes are liable to be merged during URI reconciliation.
         note_uri = self.helper.prepend_uri_key(lot.id, 'NOTE')
         lot.referred_to_by = vocab.Note(ident=note_uri, content=notes)
     if not lno:
         warnings.warn(f'Setting empty identifier on {lot.id}')
     lno = str(lno)
     lot.identified_by = vocab.LotNumber(ident='', content=lno)
Ejemplo n.º 14
0
    def model_sojourn(self, data, loc):
        base_uri = self.helper.make_proj_uri('PLACE', '')
        cb = data.get('corporate_body', False)
        sojourn_type = vocab.Establishment if cb else vocab.Residing
        sdata = {
            'type': sojourn_type,
            'referred_to_by': [],
        }

        verbatim_date = loc.get('address_date')
        if verbatim_date:
            date_range = date_cleaner(verbatim_date)
            if date_range:
                begin, end = date_range
                ts = timespan_from_outer_bounds(*date_range)
                ts.identified_by = model.Name(ident='', content=verbatim_date)
                sdata['timespan'] = add_crom_data(
                    {
                        'address_date': verbatim_date,
                        'begin': begin,
                        'end': end
                    }, ts)

        current = None
        l = loc.get('location')
        if l:
            current = parse_location_name(l, uri_base=self.helper.proj_prefix)
        address = loc.get('address')
        if address:
            current = {
                'name': address,
                'part_of': current,
                'type': 'address',
            }

        for k in ('address_note', 'location_note'):
            note = loc.get(k)
            if note:
                sdata['referred_to_by'].append(
                    vocab.Note(ident='', content=note))

        if current:
            place_data = self.helper.make_place(current, base_uri=base_uri)
            data['_places'].append(place_data)
            sdata['place'] = place_data
        return sdata
Ejemplo n.º 15
0
    def __call__(self, data: dict, non_auctions):
        '''Add modeling for physical copies of an auction catalog'''
        catalog = get_crom_object(data['_catalog'])
        cno = data['catalog_number']
        owner = data['owner_code']
        copy = data['copy_number']
        sale_type = non_auctions.get(cno, 'Auction')
        catalogObject = self.helper.physical_catalog(cno, sale_type, owner,
                                                     copy)
        data['uri'] = catalogObject.id
        info = data.get('annotation_info')
        if info:
            catalogObject.referred_to_by = vocab.Note(ident='', content=info)
        catalogObject.carries = catalog

        add_crom_data(data=data, what=catalogObject)
        return data
Ejemplo n.º 16
0
    def model_series_group(self, record, data):
        if not data:
            return
        record.setdefault('identifiers', [])
        record.setdefault('referred_to_by', [])
        record.setdefault('language', [])

        title = data.get('title')
        title_translated = data.get('title_translated')
        variant_titles = _as_list(data.get('variant_title'))
        related_titles = _as_list(data.get('related_title'))
        lang_docs = _as_list(data['lang_doc'])
        frequency = data.get('frequency')
        start_year = data.get('start_year')
        cease_year = data.get('cease_year')
        issn = data.get('issn')
        coden = data.get('coden')
        if title:
            record['label'] = title
            record['identifiers'].append(
                vocab.PrimaryName(ident='', content=title))
        if title_translated:
            record['identifiers'].append(
                vocab.TranslatedTitle(ident='', content=title))
        for vtitle in variant_titles:
            record['identifiers'].append(vocab.Title(ident='', content=vtitle))
        for lang in lang_docs:
            l = self.helper.language_object_from_code(lang)
            if l:
                record['language'].append(l)
        if frequency:
            record['referred_to_by'].append(
                vocab.Note(ident='', content=frequency))

        if start_year:
            record['_publishing_start_year'] = start_year
        if cease_year:
            record['_publishing_cease_year'] = cease_year

        if issn:
            record['identifiers'].append(
                vocab.IssnIdentifier(ident='', content=issn))

        if coden:
            record['identifiers'].append(
                vocab.CodenIdentifier(ident='', content=coden))
Ejemplo n.º 17
0
    def _populate_object_notes(self, data: dict, parent, unique_catalogs):
        hmo = get_crom_object(data)
        notes = data.get('hand_note', [])
        for note in notes:
            hand_note_content = note['hand_note']
            owner = note.get('hand_note_so')
            cno = parent['auction_of_lot']['catalog_number']
            catalog_uri = self.helper.make_proj_uri('CATALOG', cno, owner,
                                                    None)
            catalogs = unique_catalogs.get(catalog_uri)
            note = vocab.Note(ident='', content=hand_note_content)
            hmo.referred_to_by = note
            if catalogs and len(catalogs) == 1:
                note.carried_by = vocab.AuctionCatalog(
                    ident=catalog_uri,
                    label=f'Sale Catalog {cno}, owned by “{owner}”')

        inscription = data.get('inscription')
        if inscription:
            hmo.referred_to_by = vocab.InscriptionStatement(
                ident='', content=inscription)
Ejemplo n.º 18
0
	def model_concept_group(self, record, data):
		record.setdefault('referred_to_by', [])
		record.setdefault('identifiers', [])
		record.setdefault('_places', []) # for extraction/serialization by the pipeline
		record.setdefault('places', []) # for pipeline.linkedart modeling code

		gaia_id = data['gaia_auth_id']
		snote = data.get('scope_note')
		inote = data.get('internal_note')
		snfnote = data.get('source_not_found_note')
		locations = _as_list(data.get('location', []))

		record['uri'] = self.helper.corporate_body_uri(gaia_id)
		record['identifiers'].append(self.helper.gci_number_id(gaia_id, id_class=vocab.SystemNumber))

		if snote:
			record['referred_to_by'].append(vocab.Note(ident='', content=snote))
		if inote:
			record['referred_to_by'].append(vocab.InternalNote(ident='', content=inote))
		if snfnote:
			record['referred_to_by'].append(vocab.InternalNote(ident='', content=snfnote))

		mlap = MakeLinkedArtPlace()
		for loc in locations:
			geog_id = loc.get('gaia_geog_id')
			if geog_id:
				geog_uri = self.helper.place_uri(geog_id)
				geog_data = {
					'uri': geog_uri,
					'identifiers': [],
				}
				geog_name = loc.get('location_string')
				if geog_name:
					geog_data['label'] = geog_name
					geog_data['name'] = geog_name
				mlap(geog_data)
				record['places'].append(geog_data)
				record['_places'].append(geog_data)
Ejemplo n.º 19
0
    def add_acquisition(self, data, buyers, sellers, houses, non_auctions,
                        buy_sell_modifiers, transaction, transaction_types):
        '''Add modeling of an acquisition as a transfer of title from the seller to the buyer'''
        hmo = get_crom_object(data)
        parent = data['parent_data']
        # 	transaction = parent['transaction']
        prices = parent.get('price')
        ask_price = parent.get('ask_price')
        auction_data = parent['auction_of_lot']
        lot_object_key = object_key(auction_data)
        cno, lno, date = lot_object_key
        sale_type = non_auctions.get(cno, 'Auction')
        data['buyer'] = buyers
        data['seller'] = sellers

        acq_label = None
        try:
            object_label = f'“{hmo._label}”'
            acq_label = f'Acquisition of {cno} {lno} ({date}): {object_label}'
        except AttributeError:
            object_label = '(object)'
            acq_label = f'Acquisition of {cno} {lno} ({date})'

    # 	if not prices:
    # 		print(f'*** No price data found for {transaction} transaction')

        tx_data = parent.get('_prov_entry_data')
        current_tx = get_crom_object(tx_data)

        # The payment URIs are just the provenance entry URI with a suffix. In any case
        # where the provenance entry is merged, the payment should be merged as well.
        sell_payment_id = current_tx.id + '-Pay-to-Seller'
        buy_payment_id = current_tx.id + '-Pay-from-Buyer'

        # The acquisition URI is just the provenance entry URI with a suffix. In any case
        # where the provenance entry is merged, the acquisition should be merged as well.
        acq_id = hmo.id + '-Acq'
        acq = model.Acquisition(ident=acq_id, label=acq_label)
        acq.transferred_title_of = hmo

        self.attach_source_catalog(data, acq, buyers + sellers)

        multi = tx_data.get('multi_lot_tx')
        paym_label = f'multiple lots {multi}' if multi else object_label
        # 		paym = model.Payment(ident=payment_id, label=f'Payment for {paym_label}')
        payments = {
            'buy':
            model.Payment(ident=buy_payment_id,
                          label=f'Payment from buyer for {paym_label}'),
            'sell':
            model.Payment(ident=sell_payment_id,
                          label=f'Payment to seller for {paym_label}'),
        }
        for house_data in houses:
            house = get_crom_object(house_data)
            payments['buy'].paid_to = house
            payments['sell'].paid_from = house
        payments_used = set()

        THROUGH = CaseFoldingSet(buy_sell_modifiers['through'])
        FOR = CaseFoldingSet(buy_sell_modifiers['for'])

        single_seller = (len(sellers) == 1)
        single_buyer = (len(buyers) == 1)

        pi = self.helper.person_identity

        def is_or_anon(data: dict):
            mods = self.modifiers(data, 'auth_mod_a')
            return 'or anonymous' in mods

        or_anon_records = [is_or_anon(a) for a in sellers]
        uncertain_attribution = any(or_anon_records)

        for seq_no, seller_data in enumerate(sellers):
            seller = get_crom_object(seller_data)
            mod = self.modifiers(seller_data, 'auth_mod_a')
            attrib_assignment_classes = [model.AttributeAssignment]
            if uncertain_attribution:
                attrib_assignment_classes.append(vocab.PossibleAssignment)

            if THROUGH.intersects(mod):
                acq.carried_out_by = seller
                payments['sell'].carried_out_by = seller
                payments_used.add('sell')
            elif FOR.intersects(mod):
                acq.transferred_title_from = seller
                payments['sell'].paid_to = seller
                payments_used.add('sell')
            elif uncertain_attribution:  # this is true if ANY of the sellers have an 'or anonymous' modifier
                # The assignment URIs are just the acquisition URI with a suffix.
                # In any case where the acquisition is merged, the assignments should be
                # merged as well.
                acq_assignment_uri = acq.id + f'-seller-assignment-{seq_no}'
                paym_assignment_uri = payments[
                    'sell'].id + f'-seller-assignment-{seq_no}'

                acq_assignment_label = f'Uncertain seller as previous title holder in acquisition'
                acq_assignment = vocab.PossibleAssignment(
                    ident=acq_assignment_uri, label=acq_assignment_label)
                acq_assignment.referred_to_by = vocab.Note(
                    ident='', content=acq_assignment_label)
                acq_assignment.assigned_property = 'transferred_title_from'
                acq_assignment.assigned = seller
                acq.attributed_by = acq_assignment

                paym_assignment_label = f'Uncertain seller as recipient of payment'
                paym_assignment = vocab.PossibleAssignment(
                    ident=paym_assignment_uri, label=paym_assignment_label)
                paym_assignment.referred_to_by = vocab.Note(
                    ident='', content=paym_assignment_label)
                paym_assignment.assigned_property = 'paid_to'
                paym_assignment.assigned = seller
                payments['sell'].attributed_by = paym_assignment
                payments_used.add('sell')
            else:
                # covers non-modified
                # 				acq.carried_out_by = seller
                acq.transferred_title_from = seller
                # 				payments['sell'].carried_out_by = seller
                payments['sell'].paid_to = seller
                payments_used.add('sell')

        for buyer_data in buyers:
            buyer = get_crom_object(buyer_data)
            mod = self.modifiers(buyer_data, 'auth_mod_a')

            if 'or' in mod:
                # or/or others/or another
                mod_non_auth = buyer_data.get('auth_mod')
                if mod_non_auth:
                    acq.referred_to_by = vocab.Note(ident='',
                                                    label=f'Buyer modifier',
                                                    content=mod_non_auth)
                warnings.warn(f'Handle buyer modifier: {mod}'
                              )  # TODO: some way to model this uncertainty?

            if THROUGH.intersects(mod):
                acq.carried_out_by = buyer
                payments['buy'].carried_out_by = buyer
                payments_used.add('buy')
            elif FOR.intersects(mod):
                acq.transferred_title_to = buyer
                payments['buy'].paid_from = buyer
                payments_used.add('buy')
            else:
                # covers FOR modifiers and non-modified
                # 				acq.carried_out_by = buyer
                acq.transferred_title_to = buyer
                payments['buy'].paid_from = buyer
                # 				payments['buy'].carried_out_by = buyer
                payments_used.add('buy')

        if prices:
            amnt = get_crom_object(prices[0])
            for paym in payments.values():
                self.set_possible_attribute(paym, 'paid_amount', prices[0])
                for price in prices[1:]:
                    amnt = get_crom_object(price)
                    content = self._price_note(price)
                    if content:
                        paym.referred_to_by = vocab.PriceStatement(
                            ident='', content=content)
        elif ask_price:
            # for non-auction sales, the ask price is the amount paid for the acquisition
            for paym in payments.values():
                self.set_possible_attribute(paym, 'paid_amount', ask_price)

        ts = tx_data.get('_date')
        if ts:
            acq.timespan = ts

        current_tx.part = acq
        for pay_key in payments_used:
            paym = payments[pay_key]
            current_tx.part = paym
# 		current_tx.part = paym
        data['_prov_entries'] += [add_crom_data(data={}, what=current_tx)]
        # 	lot_uid, lot_uri = helper.shared_lot_number_ids(cno, lno)
        # TODO: `annotation` here is from add_physical_catalog_objects
        # 	paym.referred_to_by = annotation

        data['_acquisition'] = add_crom_data(data={'uri': acq_id}, what=acq)

        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)
            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,
                                                  current_tx, 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))

        self.add_prev_post_owners(data, hmo, tx_data, sale_type,
                                  lot_object_key, ts)
        yield data, current_tx
Ejemplo n.º 20
0
 def person(self, label):
     p = model.Person(ident='http://example.org/person', label=label)
     p.referred_to_by = vocab.Note(ident='', content='This is Eve')
     return p
Ejemplo n.º 21
0
    def handle_prev_post_owner(self,
                               data,
                               hmo,
                               tx_data,
                               sale_type,
                               lot_object_key,
                               owner_record,
                               record_id,
                               rev,
                               ts=None,
                               make_label=None):
        current_tx = get_crom_object(tx_data)
        sales_record = get_crom_object(data['_record'])
        if rev:
            rel = f'leading to the previous ownership of'
            source_label = 'Source of information on history of the object prior to the current sale.'
        else:
            rel = f'leading to the subsequent ownership of'
            source_label = 'Source of information on history of the object after the current sale.'
        owner_record.update({
            'pi_record_no':
            data['pi_record_no'],
            'ulan':
            owner_record.get('ulan', owner_record.get('own_ulan')),
        })
        self.add_person(owner_record,
                        record=sales_record,
                        relative_id=record_id,
                        role='artist')
        owner = get_crom_object(owner_record)

        # TODO: handle other fields of owner_record: own_auth_d, own_auth_q, own_ques, own_so

        if owner_record.get('own_auth_l'):
            loc = owner_record['own_auth_l']
            current = parse_location_name(loc,
                                          uri_base=self.helper.uid_tag_prefix)
            place_data = self.helper.make_place(current)
            place = get_crom_object(place_data)
            owner.residence = place
            data['_owner_locations'].append(place_data)

        if owner_record.get('own_auth_p'):
            content = owner_record['own_auth_p']
            owner.referred_to_by = vocab.Note(ident='', content=content)

        data.setdefault('_other_owners', [])
        data['_other_owners'].append(owner_record)

        # The Provenance Entry URI must not share a prefix with the object URI, otherwise
        # we run the rist of provenance entries being accidentally merged during URI
        # reconciliation as part of the prev/post sale rewriting.
        tx_uri = self.helper.prepend_uri_key(hmo.id, f'PROV-{record_id}')
        tx_label_args = tuple([self.helper, sale_type, 'Sold', rel] +
                              list(lot_object_key))
        tx, _ = self.related_procurement(hmo,
                                         tx_label_args,
                                         current_tx,
                                         ts,
                                         buyer=owner,
                                         previous=rev,
                                         ident=tx_uri,
                                         make_label=make_label)
        if owner_record.get('own_auth_e'):
            content = owner_record['own_auth_e']
            tx.referred_to_by = vocab.Note(ident='', content=content)

        own_info_source = owner_record.get('own_so')
        if own_info_source:
            note = vocab.SourceStatement(ident='',
                                         content=own_info_source,
                                         label=source_label)
            tx.referred_to_by = note

        ptx_data = tx_data.copy()
        data['_prov_entries'].append(add_crom_data(data=ptx_data, what=tx))
Ejemplo n.º 22
0
    def add_props(self, data: dict, role=None, **kwargs):
        role = role if role else 'person'
        auth_name = data.get('auth_name', '')
        period_match = self.anon_period_re.match(auth_name)
        nationalities = []
        if 'nationality' in data:
            nationality = data['nationality']
            if isinstance(nationality, str):
                nationalities.append(nationality.lower())
            elif isinstance(nationality, list):
                nationalities += [n.lower() for n in nationality]

        data['nationality'] = []
        data.setdefault('referred_to_by', [])

        name = data['label']
        active = self.clamped_timespan_args(data, name)
        if active:
            pact_uri = data['uri'] + '-ProfAct-active'
            a = self.professional_activity(name, ident=pact_uri, **active)
            data['events'].append(a)

        for key in ('notes', 'brief_notes', 'working_notes'):
            if key in data:
                for content in [n.strip() for n in data[key].split(';')]:
                    if content:
                        note = vocab.Note(ident='', content=content)
                        data['referred_to_by'].append(note)

        for key in ('name_cite', 'bibliography'):
            if data.get(key):
                cite = vocab.BibliographyStatement(ident='', content=data[key])
                data['referred_to_by'].append(cite)

        if data.get('name_cite'):
            cite = vocab.BibliographyStatement(ident='',
                                               content=data['name_cite'])
            data['referred_to_by'].append(cite)

        if self.is_anonymous_group(auth_name):
            nationality_match = self.anon_nationality_re.match(auth_name)
            dated_nationality_match = self.anon_dated_nationality_re.match(
                auth_name)
            dated_match = self.anon_dated_re.match(auth_name)
            data.setdefault('events', [])
            if nationality_match:
                with suppress(ValueError):
                    nationality = nationality_match.group(1).lower()
                    nationalities.append(nationality)
                    group_label = self.anonymous_group_label(
                        role, nationality=nationality)
                    data['label'] = group_label
            elif dated_nationality_match:
                with suppress(ValueError):
                    nationality = dated_nationality_match.group(1).lower()
                    nationalities.append(nationality)
                    century = int(dated_nationality_match.group(2))
                    group_label = self.anonymous_group_label(
                        role, century=century, nationality=nationality)
                    data['label'] = group_label
                    pact_uri = data['uri'] + '-ProfAct-dated-natl'
                    a = self.professional_activity(group_label,
                                                   ident=pact_uri,
                                                   century=century,
                                                   narrow=True)
                    data['events'].append(a)
            elif dated_match:
                with suppress(ValueError):
                    century = int(dated_match.group(1))
                    group_label = self.anonymous_group_label(role,
                                                             century=century)
                    data['label'] = group_label
                    pact_uri = data['uri'] + '-ProfAct-dated'
                    a = self.professional_activity(group_label,
                                                   ident=pact_uri,
                                                   century=century,
                                                   narrow=True)
                    data['events'].append(a)
            elif period_match:
                period = period_match.group(1).lower()
                data['label'] = f'anonymous {period} {role}s'
        for nationality in nationalities:
            key = f'{nationality.lower()} nationality'
            n = vocab.instances.get(key)
            if n:
                data['nationality'].append(n)
            else:
                warnings.warn(
                    f'No nationality instance found in crom for: {key!r}')
Ejemplo n.º 23
0
    def set_properties(self, data, thing):
        '''
		The following keys in `data` are handled to set properties on `thing`:

		`referred_to_by`
		`identifiers`
		`names` -	An array of arrays of one or two elements. The first element of each
					array is a name string, and is set as the value of a `model.Name` for
					`thing`. If there is a `dict` second element, its contents are used to
					assert properties of the name:
					
					- An array associated with the key `'referred_to_by'` will be used to
					  assert that the `LinguisticObject`s (or `dict`s representing a
					  `LinguisticObject`) refer to the name.
					- A value associated with the key `'classified_as'` (either a
					  `model.Type` or a cromulent vocab class) will be asserted as the
					  classification of the `model.Name`.

		Example data:

		{
			'names': [
				['J. Paul Getty'],
				[
					'Getty',
					{
						'classified_as': model.Type(ident='http://vocab.getty.edu/aat/300404670', label='Primary Name'),
		# or:			'classified_as': vocab.PrimaryName,
						'referred_to_by': [
							{'uri': 'tag:getty.edu,2019:digital:pipeline:REPLACE-WITH-UUID:knoedler#K-ROW-1-2-3'},
							model.LinguisticObject(ident='tag:getty.edu,2019:digital:pipeline:REPLACE-WITH-UUID:knoedler#K-ROW-1-7-10'),
						]
					}
				]
			]
		}
		'''
        for notedata in data.get('referred_to_by', []):
            if isinstance(notedata, tuple):
                content, itype = notedata
                if itype is not None:
                    if isinstance(itype, type):
                        note = itype(content=content)
                    elif isinstance(itype, object):
                        note = itype
                        note.content = content
                    else:
                        note = vocab.Note(content=content)
                        note.classified_as = itype
            elif isinstance(notedata, model.BaseResource):
                note = notedata
            elif isinstance(notedata, str):
                note = vocab.Note(content=notedata)
            else:
                note = notedata
            thing.referred_to_by = note

        for identifier in data.get('identifiers', []):
            if isinstance(identifier, tuple):
                content, itype = identifier
                if itype is not None:
                    if isinstance(itype, type):
                        ident = itype(ident='', content=content)
                        if not content:
                            warnings.warn(
                                f'Setting empty identifier on {thing.id}')
                    elif isinstance(itype, object):
                        ident = itype
                        ident.content = content
                        if not content:
                            warnings.warn(
                                f'Setting empty identifier on {thing.id}')
                    else:
                        ident = model.Identifier(ident='')
                        if not content:
                            warnings.warn(
                                f'Setting empty identifier on {thing.id}')
                        ident.content = content
                        ident.classified_as = itype
            else:
                ident = identifier


# 				c = ident.content
            thing.identified_by = ident

        if not hasattr(thing, '_label') and 'label' in data:
            setattr(thing, '_label', data['label'])

        for namedata in data.get('names', []):
            # namedata should take the form of:
            # ["A. Name"]
            # ["A. Name", {'referred_to_by': [{'uri': 'URI-OF-LINGUISTIC_OBJECT'}, model.LinguisticObject()]}]
            if isinstance(namedata, tuple):
                name, *properties = namedata
            else:
                name = namedata
                properties = []
            name_kwargs = {}
            for props in properties:
                if 'classified_as' in props:
                    cl = props['classified_as']
                    del props['classified_as']
                    name_kwargs['title_type'] = cl

            n = set_la_name(thing, name, **name_kwargs)
            self.set_lo_properties(n, *properties)
Ejemplo n.º 24
0
    def model_artists_with_modifers(self, data: dict, hmo,
                                    attribution_modifiers,
                                    attribution_group_types,
                                    attribution_group_names):
        '''Add modeling for artists as people involved in the production of an object'''
        sales_record = get_crom_object(data['_record'])

        data.setdefault('_organizations', [])
        data.setdefault('_original_objects', [])

        try:
            hmo_label = f'{hmo._label}'
        except AttributeError:
            hmo_label = 'object'

        STYLE_OF = attribution_modifiers['style of']
        ATTRIBUTED_TO = attribution_modifiers['attributed to']
        COPY_AFTER = attribution_modifiers['copy after']
        COPY_BY = attribution_modifiers['copy by']
        POSSIBLY = attribution_modifiers['possibly by']
        UNCERTAIN = attribution_modifiers['uncertain']
        FORMERLY_MODS = attribution_modifiers['formerly attributed to']
        COPY_BY = attribution_modifiers['copy by']

        # The production event URI is just the object URI with a suffix. When URIs are
        # reconciled during prev/post sale rewriting, this will allow us to also reconcile
        # the URIs for the production events (of which there should only be one per object)
        event_uri = hmo.id + '-Production'
        prod_event = model.Production(
            ident=event_uri, label=f'Production event for {hmo_label}')
        hmo.produced_by = prod_event

        artists = data.get('_artists', [])
        for a in artists:
            self.add_properties(data, a)

        # 1. Remove "copy by/after" modifiers when in the presence of "manner of; style of". This combination is not meaningful, and the intended semantics are preserved by keeping only the style assertion (with the understanding that every "copy by" modifier has a paired "copy after" in another artist record, and vice-versa)
        for a in artists:
            mods = a['modifiers']
            if STYLE_OF.intersects(mods):
                for COPY in (COPY_BY, COPY_AFTER):
                    if COPY.intersects(mods):
                        a['modifiers'] -= COPY.intersection(mods)

        NON_ARTIST_MODS = COPY_AFTER | STYLE_OF
        ARTIST_NON_GROUP_MODS = FORMERLY_MODS | COPY_BY | {'attributed to'}
        artist_assertions = []
        non_artist_assertions = []
        for a in artists:
            mods = a['modifiers']
            if NON_ARTIST_MODS.intersects(mods):
                non_artist_assertions.append(a)
                if ARTIST_NON_GROUP_MODS.intersects(mods):
                    # these have both artist and non-artist assertions
                    artist_assertions.append(a)
            else:
                artist_assertions.append(a)

        # 4. Check for the special case of "A or style of A"
        uncertain = False
        if self.uncertain_artist_or_style(artists):
            artist = artists[0]['label']
            uncertain = True
            note = f'Record indicates certainty that this object was either created by {artist} or was created in the style of {artist}'
            hmo.referred_to_by = vocab.Note(ident='', content=note)

        # 2--3
        self.model_object_influence(data,
                                    non_artist_assertions,
                                    hmo,
                                    prod_event,
                                    attribution_modifiers,
                                    attribution_group_types,
                                    attribution_group_names,
                                    all_uncertain=uncertain)

        # 5
        self.model_object_artists(data,
                                  artist_assertions,
                                  hmo,
                                  prod_event,
                                  attribution_modifiers,
                                  attribution_group_types,
                                  attribution_group_names,
                                  all_uncertain=uncertain)

        # data['_artists'] is what's pulled out by the serializers
        data['_artists'] = [a for a in artists if not self.is_or_anon(a)]
        return data
Ejemplo n.º 25
0
    def model_issue_group(self, record, data, seq):
        record.setdefault('^part', [])

        issue_id = data['issue_id']
        title = data.get('title')
        title_translated = data.get('title_translated')
        date = data.get('date')
        # issue_group/date/display_date
        # issue_group/date/sort_year
        volume = data.get('volume')
        number = data.get('number')
        note = data.get('note')

        journal_label = record['label']
        issue_label = f'Issue of {journal_label}'
        if title:
            issue_label = f'{journal_label}: “{title}”'
            if volume and number:
                issue_label = f'{issue_label} (v. {volume}, n. {number})'
        elif volume and number:
            issue_label = f'{journal_label} (v. {volume}, n. {number})'

        jid = record['record_desc_group']['record_id']
        issue = {
            'uri': self.helper.issue_uri(jid, issue_id),
            'label': issue_label,
            'object_type': vocab.IssueText,
            'identifiers': [self.helper.gci_number_id(issue_id)],
            'referred_to_by': [],
            'used_for': [],
        }
        if title:
            issue['identifiers'].append(
                vocab.PrimaryName(ident='', content=title))
        if title_translated:
            issue['identifiers'].append(
                vocab.TranslatedTitle(ident='', content=title_translated))

        if date:
            display_date = date.get('display_date')
            sort_year = date.get('sort_year')
            if display_date or sort_year:
                a_uri = issue['uri'] + f'-pub'
                a = vocab.Publishing(ident=a_uri,
                                     label=f'Publishing of {issue_label}')
                ts = model.TimeSpan(ident='')
                if display_date:
                    ts._label = display_date
                    ts.identified_by = vocab.DisplayName(ident='',
                                                         content=display_date)
                if sort_year:
                    try:
                        year = int(sort_year)
                        ts.begin_of_the_begin = '%04d-01-01:00:00:00Z' % (
                            year, )
                        ts.end_of_the_end = '%04d-01-01:00:00:00Z' % (year +
                                                                      1, )
                    except:
                        pass
                a.timespan = ts
                issue['used_for'].append(a)

        # TODO:
        # volume
        # number

        if note:
            issue['referred_to_by'].append(vocab.Note(ident='', content=note))

        mlalo = MakeLinkedArtLinguisticObject()
        mlalo(issue)

        i = get_crom_object(issue)
        for a in issue.get('used_for', []):
            i.used_for = a

        record['^part'].append(issue)
Ejemplo n.º 26
0
def extract_monetary_amount(data):
	'''
	Returns a `MonetaryAmount`, `StartingPrice`, or `EstimatedPrice` object
	based on properties of the supplied `data` dict. If no amount or currency
	data is found in found, returns `None`.

	For `EstimatedPrice`, values will be accessed from these keys:
		- amount: `est_price_amount` or `est_price`
		- currency: `est_price_currency` or `est_price_curr`
		- note: `est_price_note` or `est_price_desc`
		- bibliographic statement: `est_price_citation`

	For `StartingPrice`, values will be accessed from these keys:
		- amount: `start_price_amount` or `start_price`
		- currency: `start_price_currency` or `start_price_curr`
		- note: `start_price_note` or `start_price_desc`
		- bibliographic statement: `start_price_citation`

	For `MonetaryAmount` prices, values will be accessed from these keys:
		- amount: `price_amount` or `price`
		- currency: `price_currency` or `price_curr`
		- note: `price_note` or `price_desc`
		- bibliographic statement: `price_citation`
	'''
	amount_type = 'Price'
	if 'est_price' in data:
		amnt = vocab.EstimatedPrice()
		price_amount = data.get('est_price_amount', data.get('est_price'))
		price_currency = data.get('est_price_currency', data.get('est_price_curr'))
		amount_type = 'Estimated Price'
		note = data.get('est_price_note', data.get('est_price_desc'))
		cite = data.get('est_price_citation')
	elif 'start_price' in data:
		amnt = vocab.StartingPrice()
		price_amount = data.get('start_price_amount', data.get('start_price'))
		price_currency = data.get('start_price_currency', data.get('start_price_curr'))
		amount_type = 'Starting Price'
		note = data.get('start_price_note', data.get('start_price_desc'))
		cite = data.get('start_price_citation')
	else:
		amnt = model.MonetaryAmount()
		price_amount = data.get('price_amount', data.get('price'))
		price_currency = data.get('price_currency', data.get('price_curr'))
		note = data.get('price_note', data.get('price_desc'))
		cite = data.get('price_citation')

	if price_amount or price_currency:
		if cite:
			amnt.referred_to_by = vocab.BibliographyStatement(content=cite)
		if note:
			amnt.referred_to_by = vocab.Note(content=note)

		if price_amount:
			try:
				value = price_amount
				value = value.replace('[?]', '')
				value = value.replace('?', '')
				value = value.strip()
				price_amount = float(value)
				amnt.value = price_amount
			except ValueError:
				amnt._label = price_amount
				amnt.identified_by = model.Name(content=price_amount)
	# 			warnings.warn(f'*** Not a numeric price amount: {value}')
		if price_currency:
			if price_currency in CURRENCY_MAPPING:
				try:
					price_currency = CURRENCY_MAPPING[price_currency.lower()]
				except KeyError:
					pass
			if price_currency in vocab.instances:
				amnt.currency = vocab.instances[price_currency]
			else:
				warnings.warn('*** No currency instance defined for %s' % (price_currency,))
		if price_amount and price_currency:
			amnt._label = '%s %s' % (price_amount, price_currency)
		elif price_amount:
			amnt._label = '%s' % (price_amount,)
		return amnt
	return None
Ejemplo n.º 27
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
Ejemplo n.º 28
0
    def model_imprint_group(self, record, data):
        if not data:
            return
        record.setdefault('referred_to_by', [])
        record.setdefault('used_for', [])
        record.setdefault('part_of', [])
        record.setdefault('_activities', [])
        record.setdefault('_groups', [])
        record.setdefault('_places', [])
        record.setdefault('identifiers', [])

        edition = data.get('edition')
        series_number = data.get('series_number')
        doi = data.get('doi')
        coden = data.get('coden')
        website = data.get('website_address')
        publishers = _as_list(data.get('publisher'))
        distributors = _as_list(data.get('distributor'))
        journal = data.get('journal_info')
        # imprint_group/journal_info/aata_journal_id
        # imprint_group/journal_info/aata_issue_id
        degree = data.get('thesis_degree')
        tr = data.get('technical_report_number')

        if edition:
            record['referred_to_by'].append(
                vocab.EditionStatement(ident='', content=edition))

        if series_number:
            record['referred_to_by'].append(
                vocab.Note(ident='',
                           content=series_number))  # TODO: classify this Note

        if doi:
            record['identifiers'].append(
                vocab.DoiIdentifier(ident='', content=doi))

        if coden:
            record['identifiers'].append(
                vocab.CodenIdentifier(ident='', content=coden))

        if website:
            record['referred_to_by'].append(
                vocab.Note(ident='', content=website))

        article_label = record['label']
        for i, publisher in enumerate(publishers):
            corp_id = publisher.get('gaia_corp_id')
            geog_id = publisher.get('publisher_location',
                                    {}).get('gaia_geog_id')
            a_uri = record['uri'] + f'-pub-{i}'
            a = vocab.Publishing(ident=a_uri,
                                 label=f'Publishing of {article_label}')
            if corp_id:
                uri = self.helper.corporate_body_uri(corp_id)
                g = model.Group(ident=uri)
                a.carried_out_by = g
                record['_groups'].append(add_crom_data({}, g))
            if geog_id:
                uri = self.helper.place_uri(geog_id)
                p = model.Place(ident=uri)
                a.took_place_at = p
                record['_places'].append(add_crom_data({}, p))
            record['used_for'].append(a)
# 			record['_activities'].append(add_crom_data({}, a))

        for i, distributor in enumerate(distributors):
            corp_id = distributor.get('gaia_corp_id')
            geog_id = distributor.get('distributor_location',
                                      {}).get('gaia_geog_id')
            a_uri = record['uri'] + f'-dist-{i}'
            a = vocab.Distributing(ident=a_uri,
                                   label=f'Distribution of {article_label}')
            if corp_id:
                uri = self.helper.corporate_body_uri(corp_id)
                g = model.Group(ident=uri)
                a.carried_out_by = g
                record['_groups'].append(add_crom_data({}, g))
            if geog_id:
                uri = self.helper.place_uri(geog_id)
                p = model.Place(ident=uri)
                a.took_place_at = p
                record['_places'].append(add_crom_data({}, p))
            record['used_for'].append(a)
# 			record['_activities'].append(add_crom_data({}, a))

        if journal:
            journal_id = journal.get('aata_journal_id')
            issue_id = journal.get('aata_issue_id')
            issue_uri = self.helper.issue_uri(journal_id, issue_id)
            issue = vocab.IssueText(ident=issue_uri)
            record['part_of'].append(add_crom_data({'uri': issue_uri}, issue))

        if degree:
            record['referred_to_by'].append(
                vocab.Note(ident='', content=degree))

        if tr:
            record['identifiers'].append(model.Identifier(
                ident='', content=tr))  # TODO: classify this Identifier
Ejemplo n.º 29
0
def extract_monetary_amount(data,
                            add_citations=False,
                            currency_mapping=CURRENCY_MAPPING,
                            source_mapping=None,
                            truncate_label_digits=2):
    '''
	Returns a `MonetaryAmount`, `StartingPrice`, or `EstimatedPrice` object
	based on properties of the supplied `data` dict. If no amount or currency
	data is found in found, returns `None`.

	For `EstimatedPrice`, values will be accessed from these keys:
		- amount: `est_price_amount` or `est_price`
		- currency: `est_price_currency` or `est_price_curr`
		- note: `est_price_note` or `est_price_desc`
		- bibliographic statement: `est_price_citation`

	For `StartingPrice`, values will be accessed from these keys:
		- amount: `start_price_amount` or `start_price`
		- currency: `start_price_currency` or `start_price_curr`
		- note: `start_price_note` or `start_price_desc`
		- bibliographic statement: `start_price_citation`

	For `MonetaryAmount` prices, values will be accessed from these keys:
		- amount: `price_amount` or `price`
		- currency: `price_currency` or `price_curr`
		- note: `price_note` or `price_desc`
		- bibliographic statement: `price_citation`
	'''
    amount_type = 'Price'
    if 'price' in data or 'price_amount' in data or 'amount' in data:
        amnt = model.MonetaryAmount(ident='')
        price_amount = data.get('price_amount',
                                data.get('price', data.get('amount')))
        price_currency = data.get(
            'currency', data.get('price_currency', data.get('price_curr')))
        note = data.get('price_note', data.get('price_desc', data.get('note')))
        cite = data.get('price_citation', data.get('citation'))
        source = data.get('price_source', '')
    elif 'est_price' in data or 'est_price_amount' in data:
        amnt = vocab.EstimatedPrice(ident='')
        price_amount = data.get('est_price_amount', data.get('est_price'))
        price_currency = data.get(
            'est_price_currency',
            data.get('est_price_curr', data.get('currency')))
        amount_type = 'Estimated Price'
        note = data.get('est_price_note',
                        data.get('est_price_desc', data.get('note')))
        cite = data.get('est_price_citation', data.get('citation'))
        source = data.get('est_price_source', data.get('est_price_so', ''))
    elif 'start_price' in data or 'start_price_amount' in data:
        amnt = vocab.StartingPrice(ident='')
        price_amount = data.get('start_price_amount', data.get('start_price'))
        price_currency = data.get(
            'start_price_currency',
            data.get('start_price_curr', data.get('currency')))
        amount_type = 'Starting Price'
        note = data.get('start_price_note',
                        data.get('start_price_desc', data.get('note')))
        cite = data.get('start_price_citation', data.get('citation'))
        source = data.get('start_price_source', data.get('start_price_so', ''))
    elif 'ask_price' in data or 'ask_price_amount' in data:
        amnt = vocab.AskingPrice(ident='')
        price_amount = data.get('ask_price_amount', data.get('ask_price'))
        price_currency = data.get(
            'ask_price_currency',
            data.get('ask_price_curr', data.get('currency')))
        amount_type = 'Asking Price'
        note = data.get('ask_price_note',
                        data.get('ask_price_desc', data.get('note')))
        cite = data.get('ask_price_citation', data.get('citation'))
        source = data.get('ask_price_source', data.get('ask_price_so', ''))
    else:
        return None

    price_amount_label = price_amount
    if price_amount or price_currency:
        if cite and add_citations:
            amnt.referred_to_by = vocab.BibliographyStatement(ident='',
                                                              content=cite)
        if note:
            amnt.referred_to_by = vocab.Note(ident='', content=note)

        if price_amount:
            try:
                value = price_amount
                value = value.replace('[?]', '')
                value = value.replace('?', '')
                value = value.strip()
                if re.search(re.compile(r',\d\d\d'), value):
                    value = value.replace(',', '')
                value = float(value)

                label_fmt = '{:,.%df}' % truncate_label_digits
                price_amount_label = label_fmt.format(value)

                amnt.value = value
            except ValueError:
                amnt._label = price_amount
                amnt.identified_by = model.Name(ident='', content=price_amount)
    # 			warnings.warn(f'*** Not a numeric price amount: {value}')
        if price_currency:
            price_currency_key = price_currency
            try:
                price_currency_key = currency_mapping[
                    price_currency_key.lower()]
            except KeyError:
                pass
            if isinstance(price_currency_key, model.BaseResource):
                amnt.currency = price_currency_key
            elif price_currency_key in vocab.instances:
                amnt.currency = vocab.instances[price_currency_key]
            else:
                warnings.warn('*** No currency instance defined for %s' %
                              (price_currency_key, ))
        if price_amount_label and price_currency:
            amnt._label = '%s %s' % (price_amount_label, price_currency)
        elif price_amount:
            amnt._label = '%s' % (price_amount, )
        return amnt
    return None
Ejemplo n.º 30
0
    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