def _load_event(loader: _Loader, element: ElementTree.Element): handle = element.get('handle') event_id = element.get('id') gramps_type = _xpath1(element, './ns:type') try: event_type = _EVENT_TYPE_MAP[gramps_type.text] except KeyError: event_type = UnknownEventType() logging.getLogger().warning( 'Betty is unfamiliar with Gramps event "%s"\'s type of "%s". The event was imported, but its type was set to "%s".' % (event_id, gramps_type.text, event_type.label)) event = IdentifiableEvent(event_id, event_type) event.date = _load_date(element) # Load the event place. place_handle_element = _xpath1(element, './ns:place') if place_handle_element is not None: event.place = loader._places[place_handle_element.get('hlink')] # Load the description. description_element = _xpath1(element, './ns:description') if description_element is not None: event.description = description_element.text _load_objref(loader, event, element) _load_citationref(loader, event, element) _load_attribute_privacy(event, element, 'attribute') loader._events[handle] = event
def _parse_event(ancestry: _IntermediateAncestry, element: Element): handle = str(_xpath1(element, './@handle')) event_id = _xpath1(element, './@id') gramps_type = _xpath1(element, './ns:type') try: event_type = _EVENT_TYPE_MAP[gramps_type.text] except KeyError: event_type = UnknownEventType() logging.getLogger().warning( 'Betty is unfamiliar with Gramps event "%s"\'s type of "%s". The event was imported, but its type was set to "%s".' % (event_id, gramps_type.text, event_type.label)) event = IdentifiableEvent(event_id, event_type) event.date = _parse_date(element) # Parse the event place. place_handle = _xpath1(element, './ns:place/@hlink') if place_handle: event.place = ancestry.places[place_handle] # Parse the description. description_element = _xpath1(element, './ns:description') if description_element is not None: event.description = description_element.text _parse_objref(ancestry, event, element) _parse_citationref(ancestry, event, element) _parse_attribute_privacy(event, element, 'attribute') ancestry.events[handle] = event
def test_clean_should_not_clean_event_with_presences_with_people( self) -> None: ancestry = Ancestry() source = IdentifiableSource('S1', 'The Source') ancestry.sources[source.id] = source citation = IdentifiableCitation('C1', source) ancestry.citations[citation.id] = citation file = File('F1', __file__) ancestry.files[file.id] = file place = Place('P0', [PlaceName('The Place')]) ancestry.places[place.id] = place person = Person('P0') event = IdentifiableEvent('E0', Birth()) event.citations.append(citation) event.files.append(file) event.place = place ancestry.events[event.id] = event Presence(person, Subject(), event) clean(ancestry) self.assertEqual(event, ancestry.events[event.id]) self.assertIn(event, place.events) self.assertEqual(place, ancestry.places[place.id]) self.assertIn(event, citation.facts) self.assertEqual(citation, ancestry.citations[citation.id]) self.assertIn(event, file.resources) self.assertEqual(file, ancestry.files[file.id])
def test_clean_should_clean_event(self) -> None: ancestry = Ancestry() source = IdentifiableSource('S1', 'The Source') ancestry.sources[source.id] = source citation = IdentifiableCitation('C1', source) ancestry.citations[citation.id] = citation file = File('F1', __file__) ancestry.files[file.id] = file place = Place('P0', [PlaceName('The Place')]) ancestry.places[place.id] = place event = IdentifiableEvent('E0', Birth()) event.citations.append(citation) event.files.append(file) event.place = place ancestry.events[event.id] = event clean(ancestry) self.assertNotIn(event.id, ancestry.events) self.assertIsNone(event.place) self.assertNotIn(event, place.events) self.assertNotIn(place.id, ancestry.places) self.assertNotIn(event, citation.facts) self.assertNotIn(citation.id, ancestry.citations) self.assertNotIn(event, file.resources) self.assertNotIn(file.id, ancestry.files)
def test_event_should_encode_full(self): event = IdentifiableEvent('the_event', Birth()) event.date = DateRange(Date(2000, 1, 1), Date(2019, 12, 31)) event.place = Place('the_place', [PlaceName('The Place')]) Presence(Person('the_person'), Subject(), event) event.citations.append( IdentifiableCitation('the_citation', Source('The Source'))) expected = { '$schema': '/schema.json#/definitions/event', '@context': { 'place': 'https://schema.org/location', }, '@type': 'https://schema.org/Event', 'id': 'the_event', 'type': 'birth', 'presences': [ { '@context': { 'person': 'https://schema.org/actor', }, 'role': 'subject', 'person': '/en/person/the_person/index.json', }, ], 'citations': [ '/en/citation/the_citation/index.json', ], 'date': { 'start': { 'year': 2000, 'month': 1, 'day': 1, }, 'end': { 'year': 2019, 'month': 12, 'day': 31, }, }, 'place': '/en/place/the_place/index.json', 'links': [ { 'url': '/en/event/the_event/index.json', 'relationship': 'canonical', 'mediaType': 'application/json', }, { 'url': '/nl/event/the_event/index.json', 'relationship': 'alternate', 'locale': 'nl-NL', }, { 'url': '/en/event/the_event/index.html', 'relationship': 'alternate', 'mediaType': 'text/html', }, ], } self.assert_encodes(expected, event, 'event')
def test_with_private_event_should_anonymize(self, m_anonymize_event) -> None: event = IdentifiableEvent('E0', Event.Type.BIRTH) event.private = True ancestry = Ancestry() ancestry.events[event.id] = event anonymize(ancestry) m_anonymize_event.assert_called_once_with(event)
def test_with_public_event_should_not_anonymize(self, m_anonymize_event) -> None: event = IdentifiableEvent('E0', Event.Type.BIRTH) event.private = False ancestry = Ancestry() ancestry.events[event.id] = event anonymize(ancestry) m_anonymize_event.assert_not_called()
def test_place_should_sync_references(self): place = Place('1', [LocalizedName('one')]) sut = IdentifiableEvent('1', Event.Type.BIRTH) sut.place = place self.assertEquals(place, sut.place) self.assertIn(sut, place.events) sut.place = None self.assertEquals(None, sut.place) self.assertNotIn(sut, place.events)
def test_place_should_sync_references(self): place = Place('1', [PlaceName('one')]) sut = IdentifiableEvent('1', Birth()) sut.place = place self.assertEquals(place, sut.place) self.assertIn(sut, place.events) sut.place = None self.assertEquals(None, sut.place) self.assertNotIn(sut, place.events)
def test_derive_birth_with_existing_event(self, other_date: Datey): with TemporaryDirectory() as output_directory_path: configuration = Configuration( output_directory_path, 'https://example.com') configuration.plugins[Deriver] = {} site = Site(configuration) person = Person('P0') other_presence = Presence(person, Presence.Role.SUBJECT, IdentifiableEvent('E0', Event.Type.MARRIAGE)) other_presence.event.date = other_date irrelevant_presence = Presence(person, Presence.Role.SUBJECT, IdentifiableEvent('E1', Event.Type.DIVORCE)) irrelevant_presence.event.date = Date(1972, 1, 1) site.ancestry.people[person.id] = person parse(site) self.assertEquals(4, len(person.presences)) self.assertEquals(DateRange(None, Date(1971, 1, 1)), person.start.date)
def test_derive_birth_with_existing_birth_with_date(self): with TemporaryDirectory() as output_directory_path: configuration = Configuration( output_directory_path, 'https://example.com') configuration.plugins[Deriver] = {} site = Site(configuration) person = Person('P0') birth_presence = Presence(person, Presence.Role.SUBJECT, IdentifiableEvent('E0', Event.Type.BIRTH)) birth_presence.event.date = Date(1970, 2, 1) other_presence = Presence(person, Presence.Role.SUBJECT, IdentifiableEvent('E0', Event.Type.MARRIAGE)) other_presence.event.date = Date(1970, 1, 1) site.ancestry.people[person.id] = person parse(site) self.assertEquals(3, len(person.presences)) self.assertIsNotNone(birth_presence.event.date) self.assertEquals(Date(1970, 2, 1), birth_presence.event.date)
async def test_with_identifiable(self): event = IdentifiableEvent('E0', Birth()) expected = '<a href="/event/E0/index.html">Birth</a>' async with self._render(data={ 'event': event, }) as (actual, _): self.assertEqual(expected, actual)
def test_citation_should_encode_full(self): citation = IdentifiableCitation( 'the_citation', IdentifiableSource('the_source', 'The Source')) citation.description = 'The Source Description' citation.facts.append(IdentifiableEvent('the_event', Birth())) expected = { '$schema': '/schema.json#/definitions/citation', '@type': 'https://schema.org/Thing', 'id': 'the_citation', 'source': '/en/source/the_source/index.json', 'facts': ['/en/event/the_event/index.json'], 'links': [ { 'url': '/en/citation/the_citation/index.json', 'relationship': 'canonical', 'mediaType': 'application/json', }, { 'url': '/nl/citation/the_citation/index.json', 'relationship': 'alternate', 'locale': 'nl-NL', }, { 'url': '/en/citation/the_citation/index.html', 'relationship': 'alternate', 'mediaType': 'text/html', }, ], } self.assert_encodes(expected, citation, 'citation')
def test_event_should_encode_minimal(self): event = IdentifiableEvent('the_event', Birth()) expected = { '$schema': '/schema.json#/definitions/event', '@type': 'https://schema.org/Event', 'id': 'the_event', 'type': 'birth', 'presences': [], 'citations': [], 'links': [ { 'url': '/en/event/the_event/index.json', 'relationship': 'canonical', 'mediaType': 'application/json', }, { 'url': '/nl/event/the_event/index.json', 'relationship': 'alternate', 'locale': 'nl-NL', }, { 'url': '/en/event/the_event/index.html', 'relationship': 'alternate', 'mediaType': 'text/html', }, ], } self.assert_encodes(expected, event, 'event')
def test_event_should_encode_full(self): event = IdentifiableEvent('the_event', Event.Type.BIRTH) event.date = DateRange(Date(2000, 1, 1), Date(2019, 12, 31)) event.place = Place('the_place', [LocalizedName('The Place')]) Presence(Person('the_person'), Presence.Role.SUBJECT, event) event.citations.append( Citation('the_citation', Source('the_source', 'The Source'))) expected = { '$schema': '/schema.json#/definitions/event', '@context': { 'place': 'https://schema.org/location', }, '@type': 'https://schema.org/Event', 'id': 'the_event', 'type': Event.Type.BIRTH.value, 'presences': [ { '@context': { 'person': 'https://schema.org/actor', }, 'role': Presence.Role.SUBJECT.value, 'person': '/person/the_person/index.json', }, ], 'citations': [ '/citation/the_citation/index.json', ], 'date': { 'start': { 'year': 2000, 'month': 1, 'day': 1, }, 'end': { 'year': 2019, 'month': 12, 'day': 31, }, }, 'place': '/place/the_place/index.json', } self.assert_encodes(expected, event, 'event')
def test_place_should_encode_full(self): place_id = 'the_place' name = 'The Place' locale = 'nl-NL' latitude = 12.345 longitude = -54.321 coordinates = Point(latitude, longitude) place = Place(place_id, [LocalizedName(name, locale)]) place.coordinates = coordinates place.enclosed_by = Place('the_enclosing_place', []) place.encloses.append(Place('the_enclosed_place', [])) place.links.add( Link('https://example.com/the-place', 'The Place Online')) place.events.append(IdentifiableEvent('E1', Event.Type.BIRTH)) expected = { '$schema': '/schema.json#/definitions/place', '@context': { 'encloses': 'https://schema.org/containsPlace', 'events': 'https://schema.org/event', 'enclosedBy': 'https://schema.org/containedInPlace', 'coordinates': 'https://schema.org/geo', }, '@type': 'https://schema.org/Place', 'id': place_id, 'names': [ { 'name': name, 'locale': 'nl-NL', }, ], 'events': [ '/event/E1/index.json', ], 'links': [ { 'url': 'https://example.com/the-place', 'label': 'The Place Online', }, ], 'coordinates': { '@context': { 'latitude': 'https://schema.org/latitude', 'longitude': 'https://schema.org/longitude', }, '@type': 'https://schema.org/GeoCoordinates', 'latitude': latitude, 'longitude': longitude, }, 'encloses': [ '/place/the_enclosed_place/index.json', ], 'enclosedBy': '/place/the_enclosing_place/index.json', } self.assert_encodes(expected, place, 'place')
async def test_embedded_with_identifiable(self): event = IdentifiableEvent('E0', Birth()) Presence(Person('P0'), Subject(), event) expected = 'Birth of <span class="nn" title="This person\'s name is unknown.">n.n.</span>' async with self._render(data={ 'event': event, 'embedded': True, }) as (actual, _): self.assertEqual(expected, actual)
def test_events_should_sync_references(self): sut = Place('1', [PlaceName('one')]) event = IdentifiableEvent('1', Birth()) sut.events.append(event) self.assertIn(event, sut.events) self.assertEquals(sut, event.place) sut.events.remove(event) self.assertCountEqual([], sut.events) self.assertEquals(None, event.place)
def test_events(self) -> None: sut = Place('P1', [PlaceName('The Place')]) event = IdentifiableEvent('1', Birth()) sut.events.append(event) self.assertIn(event, sut.events) self.assertEquals(sut, event.place) sut.events.remove(event) self.assertCountEqual([], sut.events) self.assertEquals(None, event.place)
async def test_post_parse(self) -> None: event = IdentifiableEvent('E0', Birth()) with TemporaryDirectory() as output_directory_path: configuration = Configuration(output_directory_path, 'https://example.com') configuration.extensions[Cleaner] = None async with App(configuration) as app: app.ancestry.events[event.id] = event await load(app) self.assertEquals({}, app.ancestry.events)
def test_presence_should_sync_references(self): person = Person('P1') sut = IdentifiableEvent('1', Birth()) presence = Presence(person, Subject(), sut) sut.presences.append(presence) self.assertCountEqual([presence], sut.presences) self.assertEquals(sut, presence.event) sut.presences.remove(presence) self.assertCountEqual([], sut.presences) self.assertIsNone(presence.event)
async def test_post_parse(self) -> None: event = IdentifiableEvent('E0', Birth()) with TemporaryDirectory() as output_directory_path: configuration = Configuration(output_directory_path, 'https://example.com') configuration.plugins[Cleaner] = None async with Site(configuration) as site: site.ancestry.events[event.id] = event await parse(site) self.assertEquals({}, site.ancestry.events)
def test_presence_should_sync_references(self): person = Person('P1') sut = IdentifiableEvent('1', Event.Type.BIRTH) presence = Presence(person, Presence.Role.SUBJECT, sut) sut.presences.append(presence) self.assertCountEqual([presence], sut.presences) self.assertEquals(sut, presence.event) sut.presences.remove(presence) self.assertCountEqual([], sut.presences) self.assertIsNone(presence.event)
def test_post_parse(self) -> None: with TemporaryDirectory() as output_directory_path: configuration = Configuration(output_directory_path, 'https://example.com') configuration.plugins[Cleaner] = {} site = Site(configuration) event = IdentifiableEvent('E0', Event.Type.BIRTH) site.ancestry.events[event.id] = event parse(site) self.assertEquals({}, site.ancestry.events)
def test_clean(self) -> None: ancestry = Ancestry() onymous_event = IdentifiableEvent('E0', Event.Type.BIRTH) Presence(Person('P0'), Presence.Role.SUBJECT, onymous_event) ancestry.events[onymous_event.id] = onymous_event anonymous_event = IdentifiableEvent('E1', Event.Type.BIRTH) ancestry.events[anonymous_event.id] = anonymous_event onymous_place = Place('P0', [LocalizedName('Amsterdam')]) onymous_place.events.append(onymous_event) ancestry.places[onymous_place.id] = onymous_place anonymous_place = Place('P1', [LocalizedName('Almelo')]) ancestry.places[anonymous_place.id] = anonymous_place onmyous_place_because_encloses_onmyous_places = Place( 'P3', [LocalizedName('Netherlands')]) onmyous_place_because_encloses_onmyous_places.encloses.append( onymous_place) onmyous_place_because_encloses_onmyous_places.encloses.append( anonymous_place) ancestry.places[onmyous_place_because_encloses_onmyous_places. id] = onmyous_place_because_encloses_onmyous_places clean(ancestry) self.assertDictEqual({ onymous_event.id: onymous_event, }, ancestry.events) self.assertDictEqual( { onymous_place.id: onymous_place, onmyous_place_because_encloses_onmyous_places.id: onmyous_place_because_encloses_onmyous_places, }, ancestry.places) self.assertNotIn( anonymous_place, onmyous_place_because_encloses_onmyous_places.encloses)
def test_post_parse(self): with TemporaryDirectory() as output_directory_path: configuration = Configuration( output_directory_path, 'https://example.com') configuration.plugins[Privatizer] = {} site = Site(configuration) person = Person('P0') Presence(person, Presence.Role.SUBJECT, IdentifiableEvent('E0', Event.Type.BIRTH)) site.ancestry.people[person.id] = person parse(site) self.assertTrue(person.private)
def test_derive_with_events_without_dates(self): with TemporaryDirectory() as output_directory_path: configuration = Configuration( output_directory_path, 'https://example.com') configuration.plugins[Deriver] = {} site = Site(configuration) person = Person('P0') Presence(person, Presence.Role.SUBJECT, IdentifiableEvent('E0', Event.Type.MARRIAGE)) site.ancestry.people[person.id] = person parse(site) self.assertEquals(1, len(person.presences))
def test_event_should_encode_minimal(self): event = IdentifiableEvent('the_event', Event.Type.BIRTH) expected = { '$schema': '/schema.json#/definitions/event', '@type': 'https://schema.org/Event', 'id': 'the_event', 'type': Event.Type.BIRTH.value, 'presences': [], 'citations': [], } self.assert_encodes(expected, event, 'event')
def test_clean(self) -> None: ancestry = Ancestry() onymous_event = IdentifiableEvent('E0', Birth()) Presence(Person('P0'), Subject(), onymous_event) ancestry.events[onymous_event.id] = onymous_event anonymous_event = IdentifiableEvent('E1', Birth()) ancestry.events[anonymous_event.id] = anonymous_event onymous_place = Place('P0', [PlaceName('Amsterdam')]) onymous_place.events.append(onymous_event) ancestry.places[onymous_place.id] = onymous_place anonymous_place = Place('P1', [PlaceName('Almelo')]) ancestry.places[anonymous_place.id] = anonymous_place onmyous_place_because_encloses_onmyous_places = Place( 'P3', [PlaceName('Netherlands')]) Enclosure(onymous_place, onmyous_place_because_encloses_onmyous_places) Enclosure(anonymous_place, onmyous_place_because_encloses_onmyous_places) ancestry.places[onmyous_place_because_encloses_onmyous_places. id] = onmyous_place_because_encloses_onmyous_places clean(ancestry) self.assertDictEqual({ onymous_event.id: onymous_event, }, ancestry.events) self.assertDictEqual( { onymous_place.id: onymous_place, onmyous_place_because_encloses_onmyous_places.id: onmyous_place_because_encloses_onmyous_places, }, ancestry.places) self.assertNotIn( anonymous_place, onmyous_place_because_encloses_onmyous_places.encloses)
def test_citation_should_encode_full(self): citation = Citation('the_citation', Source('the_source', 'The Source')) citation.description = 'The Source Description' citation.facts.append(IdentifiableEvent('the_event', Event.Type.BIRTH)) expected = { '$schema': '/schema.json#/definitions/citation', '@type': 'https://schema.org/Thing', 'id': 'the_citation', 'source': '/source/the_source/index.json', 'facts': ['/event/the_event/index.json'], } self.assert_encodes(expected, citation, 'citation')