Exemple #1
0
 def test_list_my_props(self):
     p1 = model.Person()
     p1.classified_as = model.Type()
     props = p1.list_my_props()
     self.assertEqual(set(props), set(['classified_as', 'id']))
     props = p1.list_my_props(filter=model.Type)
     self.assertEqual(props, ['classified_as'])
Exemple #2
0
    def _populate_object_visual_item(self, data: dict, subject_genre):
        hmo = get_crom_object(data)
        title = data.get('title')
        title = truncate_with_ellipsis(title, 100) or title

        # The visual item 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 visual items (of which there should only be one per object)
        vi_uri = hmo.id + '-VisItem'
        vi = model.VisualItem(ident=vi_uri)
        vidata = {'uri': vi_uri}
        if title:
            vidata['label'] = f'Visual work of “{title}”'
            sales_record = get_crom_object(data['_record'])
            vidata['names'] = [(title, {'referred_to_by': [sales_record]})]

        for key in ('genre', 'subject'):
            if key in data:
                values = [v.strip() for v in data[key].split(';')]
                for value in values:
                    for prop, mapping in subject_genre.items():
                        if value in mapping:
                            aat_url = mapping[value]
                            type = model.Type(ident=aat_url, label=value)
                            setattr(vi, prop, type)
        data['_visual_item'] = add_crom_data(data=vidata, what=vi)
        hmo.shows = vi
Exemple #3
0
	def test_aa_check(self):

		# Make sure that some other test hasn't set it
		try:
			del model.AttributeAssignment.set_assigned_property
		except:
			pass

		t = model.Type()
		aa = model.AttributeAssignment()
		# First check that aa accepts a type
		aa.assigned_property = t
		# And will not accept a string
		self.assertRaises(model.DataError, aa.__setattr__, "assigned_property", "classified_as")

		# Check we can set anything to assigned / assigned_to
		aa.assigned_property = None
		aa.assigned = aa
		aa.assigned_to = aa
		self.assertEqual(aa.assigned, aa)
		self.assertEqual(aa.assigned_to, aa)

		vocab.add_attribute_assignment_check()

		# This should fail right now as can't classify as an AA
		self.assertRaises(model.DataError, aa.__setattr__, "assigned_property", "classified_as")
		aa.assigned = None
		aa.assigned_to = None
		aa.assigned = t
		aa.assigned_to = t
		aa.assigned_property = "classified_as"
		self.assertEqual(aa.assigned_property, 'classified_as')
Exemple #4
0
    def set_properties(self, data, thing):
        super().set_properties(data, thing)
        title_type = model.Type(
            ident='http://vocab.getty.edu/aat/300417193',
            label='Title')  # TODO: is this the right aat URI?
        if 'label' in data:
            set_la_name(thing, data['label'], title_type, set_label=True)

        if 'title' in data:
            # TODO: This needs to be a PrimaryName, not a Name classified as a Title
            title = data['title']
            if isinstance(title, str):
                set_la_name(thing, title, title_type, set_label=True)
            elif isinstance(title, (list, tuple)):
                value, *properties = title
                n = set_la_name(thing, value, title_type, set_label=True)
                n.classified_as = title_type
                self.set_lo_properties(n, *properties)
                thing.identified_by = n

        parents = data.get('part_of', [])
        for parent_data in parents:
            parent = get_crom_object(parent_data)
            thing.part_of = parent

        for carried in data.get('carries', []):
            lo = get_crom_object(carried)
            thing.carries = lo

        for coll in data.get('member_of', []):
            thing.member_of = coll

        for annotation in data.get('annotations', []):
            a = model.Annotation(ident='', content=annotation)
            thing.carries = a
Exemple #5
0
	def role_type(self, role):
		author_roles = self.services['author_roles']
		code = author_roles.get(role)
		if code:
			t = model.Type(ident='http://vocab.getty.edu/aat/' + code, label=role)
			return t
		return None
Exemple #6
0
	def place_classification(self, name):
		place_types = self.services['place_types']
		if name in place_types:
			aat = place_types[name]
			return model.Type(ident=f'http://vocab.getty.edu/aat/{aat}', label=name)
		else:
			warnings.warn(f'*** No matching AAT code for place type: {name}')
		return None
Exemple #7
0
    def model_classification_group(self, record, data):
        record.setdefault('classified_as', [])

        code = data['class_code']
        name = data['class_name']
        uri = self.helper.make_proj_uri('Classification', code)
        t = model.Type(ident=uri, label=name)
        record['classified_as'].append(t)
Exemple #8
0
 def test_collapse_json(self):
     p = model.Person()
     p.classified_as = model.Type(ident="http://example.org/Type",
                                  label="Test")
     res1 = model.factory.toString(p, compact=False,
                                   collapse=60)  # all new lines
     res2 = model.factory.toString(p, compact=False,
                                   collapse=120)  # compact list of type
     self.assertEqual(len(res1.splitlines()), 12)
     self.assertEqual(len(res2.splitlines()), 6)
Exemple #9
0
    def set_properties(self, data, thing):
        super().set_properties(data, thing)
        with suppress(ValueError, TypeError):
            ulan = int(data.get('ulan'))
            if ulan:
                thing.exact_match = model.BaseResource(
                    ident=f'http://vocab.getty.edu/ulan/{ulan}')

        if 'name' in data:
            title_type = model.Type(
                ident='http://vocab.getty.edu/aat/300417193', label='Title')
            name = data['name']
            if name:
                if isinstance(name, str):
                    set_la_name(thing, name, title_type, set_label=True)
                elif isinstance(name, (list, tuple)):
                    value, *properties = name
                    n = model.Name(ident='', content=value)
                    n.classified_as = title_type
                    self.set_lo_properties(n, *properties)
                    thing.identified_by = n

        for uri in data.get('exact_match', []):
            thing.exact_match = uri

        for sdata in data.get('sojourns', []):
            label = sdata.get('label', 'Sojourn activity')
            stype = sdata.get('type', model.Activity)
            act = stype(ident='', label=label)
            ts = get_crom_object(sdata.get('timespan'))
            place = get_crom_object(sdata.get('place'))
            act.timespan = ts
            act.took_place_at = place
            thing.carried_out = act
            self.set_referred_to_by(sdata, act)

        # Locations are names of residence places (P74 -> E53)
        # XXX FIXME: Places are their own model
        if 'places' in data:
            for p in data['places']:
                if isinstance(p, model.Place):
                    pl = p
                elif isinstance(p, dict):
                    pl = get_crom_object(p)
                else:
                    pl = model.Place(ident='', label=p)
                #pl._label = p['label']
                #nm = model.Name()
                #nm.content = p['label']
                #pl.identified_by = nm
                #for s in p['sources']:
                #		l = model.LinguisticObject(ident="urn:uuid:%s" % s[1])
                # l._label = _row_label(s[2], s[3], s[4])
                #	pl.referred_to_by = l
                thing.residence = pl
Exemple #10
0
 def test_collapse_json(self):
     model.factory.auto_id_type = "uuid"
     model.factory.base_url = "http://lod.example.org/museum/"
     model.factory.context_uri = "https://linked.art/ns/v1/linked-art.json"
     p = model.Person()
     p.classified_as = model.Type(ident="http://example.org/Type",
                                  label="Test")
     res1 = model.factory.toString(p, compact=False,
                                   collapse=60)  # all new lines
     res2 = model.factory.toString(p, compact=False,
                                   collapse=120)  # compact list of type
     self.assertEqual(len(res1.splitlines()), 12)
     self.assertEqual(len(res2.splitlines()), 6)
Exemple #11
0
 def model_index_group(record, data):
     record.setdefault('indexing', [])
     term = data['index_term']
     auth_type = data.get('gaia_auth_type')
     opids = _as_list(data.get('other_persistent_id'))
     for opid in opids:
         eid = opid['external_id']
         ename = opid['external_name']
         if ename in ('AAT', 'ULAN', 'TGN'):
             v = ename.lower()
             uri = f'http://vocab.getty.edu/{v}/{eid}'
             t = model.Type(ident=uri, label=term)
             record['indexing'].append(t)
Exemple #12
0
    def test_ordering(self):
        p = model.Person(label="Person")
        p.classified_as = model.Type(ident="type-uri")
        p.referred_to_by = model.LinguisticObject(content="text")
        p.dimension = model.Dimension(value=1)

        outstr = model.factory.toString(p)
        lbl = outstr.index("_label")
        clsf = outstr.index("classified_as")
        r2b = outstr.index("referred_to_by")
        dim = outstr.index("dimension")
        self.assertTrue(lbl < clsf)
        self.assertTrue(clsf < r2b)
        self.assertTrue(r2b < dim)
Exemple #13
0
    def _populate_object_visual_item(self, data: dict, subject_genre):
        hmo = get_crom_object(data)
        title = data.get('title')
        title = truncate_with_ellipsis(title, 100) or title

        vi_id = hmo.id + '-VisItem'
        vi = model.VisualItem(ident=vi_id)
        vidata = {'uri': vi_id}
        if title:
            vidata['label'] = f'Visual work of “{title}”'
            sales_record = get_crom_object(data['_record'])
            vidata['names'] = [(title, {'referred_to_by': [sales_record]})]

        for key in ('genre', 'subject'):
            if key in data:
                values = [v.strip() for v in data[key].split(';')]
                for value in values:
                    for prop, mapping in subject_genre.items():
                        if value in mapping:
                            aat_url = mapping[value]
                            type = model.Type(ident=aat_url, label=value)
                            setattr(vi, prop, type)
        data['_visual_item'] = add_crom_data(data=vidata, what=vi)
        hmo.shows = vi
Exemple #14
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
Exemple #15
0
    def set_properties(self, data, thing):
        super().set_properties(data, thing)

        # TODO: this whole title_type thing isn't right. most of the identifiers below aren't titles
        title_type = model.Type(ident='http://vocab.getty.edu/aat/300417193',
                                label='Title')
        name = None
        if 'label' in data:
            name = set_la_name(thing,
                               data['label'],
                               title_type,
                               set_label=True)

        for author in data.get('created_by', []):
            thing.created_by = author

        for a in data.get('used_for', []):
            thing.used_for = a

        for a in data.get('about', []):
            thing.about = a

        for c in data.get('classified_as', []):
            thing.classified_as = c

        for t in data.get('translations', []):
            n = set_la_name(thing, t, title_type)
            if name is not None:
                n.translation_of = name

        for content, itype, notes in data.get('qualified_identifiers', []):
            ident = itype(content=content)
            if not content:
                warnings.warn(f'Setting empty identifier on {thing.id}')
            thing.identified_by = ident
            for n in notes:
                ident.referred_to_by = n

        code_type = None  # TODO: is there a model.Type value for this sort of code?
        for c in data.get('classifications', []):
            if isinstance(c, model.Type):
                classification = c
            else:
                cid, label = c
                name = model.Name()
                name.classified_as = title_type
                name.content = label

                classification = model.Type(label=label)
                if not label:
                    warnings.warn(f'Setting empty name on {classification.id}')
                classification.identified_by = name

                code = model.Identifier()
                code.classified_as = code_type
                if not cid:
                    warnings.warn(f'Setting empty identifier on {code.id}')
                code.content = cid
                classification.identified_by = code
            thing.about = classification

        for c in data.get('indexing', []):
            if isinstance(c, tuple):
                cid, label = c
                name = model.Name()
                name.classified_as = title_type
                name.content = label

                indexing = model.Type(label=label)
                if not label:
                    warnings.warn(f'Setting empty name on {indexing.id}')
                indexing.identified_by = name

                code = model.Identifier()
                code.classified_as = code_type
                code.content = cid
                if not cid:
                    warnings.warn(f'Setting empty identifier on {code.id}')
                indexing.identified_by = code
            else:
                indexing = c
            thing.about = indexing

        parents = data.get('part_of', [])
        for parent_data in parents:
            parent = get_crom_object(parent_data)
            thing.part_of = parent

        children = data.get('part', [])
        for child_data in children:
            child = get_crom_object(child_data)
            thing.part = child

        for carrier in data.get('carried_by', []):
            hmo = get_crom_object(carrier)
            thing.carried_by = hmo

        for dimension in data.get('dimensions', []):
            thing.dimension = dimension
Exemple #16
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
	def test_type_patch(self):
		t = model.Type("http://vocab.getty.edu/aat/5")
		nt = t._toJSON()
		self.assertEqual(nt, "aat:5")