[PATCH eac V3] Add support for <chronList> under <biogHist> tag

Guillaume Vandevelde guillaume.vandevelde at logilab.fr
Mon Jul 22 14:45:56 CEST 2019


# HG changeset patch
# User Guillaume Vandevelde <gvandevelde at logilab.fr>
# Date 1563546183 -7200
#      Fri Jul 19 16:23:03 2019 +0200
# Node ID 8d8cb026854adef808130ac78f1efa0e83d3e639
# Parent  c6719ba14ca67516c6f2bd932fe562c2a593e376
# Available At http://hg.logilab.org/review/cubes/eac
#              hg pull http://hg.logilab.org/review/cubes/eac -r 8d8cb026854a
Add support for <chronList> under <biogHist> tag

Build a new Event entities as child of the History entity.

Added as a new entity for handling the case of multiples events under a <biogHist> tag.
Modified the `add_citation_for` decorator so it can handle any child appending.
Modified the History child creation and concatenation so it can use this system.

diff -r c6719ba14ca6 -r 8d8cb026854a cubicweb_eac/dataimport.py
--- a/cubicweb_eac/dataimport.py	Thu Jul 04 15:10:27 2019 +0200
+++ b/cubicweb_eac/dataimport.py	Fri Jul 19 16:23:03 2019 +0200
@@ -19,7 +19,7 @@
 
 from collections import deque
 import datetime
-from functools import wraps
+from functools import wraps, partial
 import inspect
 import logging
 from uuid import uuid4
@@ -40,7 +40,7 @@
 TYPE_MAPPING['human'] = u'person'
 
 ETYPES_ORDER_HINT = ('AgentKind', 'PhoneNumber', 'PostalAddress', 'AuthorityRecord',
-                     'AgentPlace', 'Mandate', 'LegalStatus', 'History',
+                     'AgentPlace', 'Mandate', 'LegalStatus', 'History', 'HistoricalEvent',
                      'Structure', 'AgentFunction', 'Occupation', 'GeneralContext',
                      'AssociationRelation', 'ChronologicalRelation', 'HierarchicalRelation',
                      'EACResourceRelation', 'ExternalUri', 'EACSource',
@@ -153,24 +153,29 @@
     return decorator
 
 
-def add_citations_for(etype):
+def add_child_for(etype, relation, builder):
     """Handle import of citation tag for `etype` ExtEntity that is yielded by
     decorated method.
     """
     def decorator(func):
         @wraps(func)
         def wrapper(self, elem):
+            build_child = getattr(self, builder)
             for extentity in func(self, elem):
                 if extentity.etype == etype:
-                    for citation in self.build_citation(elem):
+                    for child in build_child(elem):
                         extentity.values.setdefault(
-                            'has_citation', set()).add(citation.extid)
-                        yield citation
+                            relation, set()).add(child.extid)
+                        yield child
                 yield extentity
         return wrapper
     return decorator
 
 
+add_citations_for = partial(add_child_for, relation='has_citation', builder='build_citation')
+add_events_for = partial(add_child_for, relation='has_event', builder='build_event')
+
+
 def require_tag(tagname):
     """Method decorator handling a mandatory tag within a XML element."""
     def warn(self, elem):
@@ -583,6 +588,7 @@
             yield ExtEntity('Citation', self._gen_extid(), values)
 
     @relate_to_record_through('History', 'history_agent')
+    @add_events_for('History')
     @add_citations_for('History')
     @elem_maybe_none
     def build_history(self, elem):
@@ -596,6 +602,28 @@
                 values['abstract'] = set([text_type(abstract.text)])
             yield ExtEntity('History', self._gen_extid(), values)
 
+    @filter_none
+    @filter_empty
+    @elem_maybe_none
+    def build_event(self, elem):
+        """Build a `HistoricalEvent` external entity."""
+        citems = self._elem_findall(elem, './/eac:chronItem')
+        if citems is not None:
+            for citem in citems:
+                values = {}
+                date = self._elem_find(citem, 'eac:date')
+                date_range = self._elem_find(citem, 'eac:dateRange')
+                event = self._elem_find(citem, 'eac:event')
+                if event is not None and event.text:
+                    values['event'] = set([text_type(event.text)])
+                    if date is None and date_range is not None:
+                        date_range = self.parse_daterange(date_range)
+                        values.update(date_range)
+                    elif date is not None:
+                        values.update({'start_date': set([self.parse_date(date)]),
+                                       'end_date': set([self.parse_date(date)])})
+                    yield ExtEntity('HistoricalEvent', self._gen_extid(), values)
+
     @elem_maybe_none
     @relate_to_record_through('Structure', 'structure_agent')
     def build_structure(self, elem):
diff -r c6719ba14ca6 -r 8d8cb026854a cubicweb_eac/i18n/en.po
--- a/cubicweb_eac/i18n/en.po	Thu Jul 04 15:10:27 2019 +0200
+++ b/cubicweb_eac/i18n/en.po	Fri Jul 19 16:23:03 2019 +0200
@@ -126,6 +126,9 @@
 msgid "EACSource_plural"
 msgstr "Sources"
 
+msgid "Events linked to an History object"
+msgstr ""
+
 msgid "GeneralContext"
 msgstr "General context"
 
@@ -141,6 +144,15 @@
 msgid "HierarchicalRelation_plural"
 msgstr "Hierarchical relations"
 
+msgid "HistoricalEvent"
+msgstr "Historical event"
+
+msgid "HistoricalEvent with date for describing an historical event"
+msgstr ""
+
+msgid "HistoricalEvent_plural"
+msgstr "Historical events"
+
 msgid "History"
 msgstr "Piece of historical information"
 
@@ -237,6 +249,9 @@
 msgid "New HierarchicalRelation"
 msgstr "New hierarchical relation"
 
+msgid "New HistoricalEvent"
+msgstr "New historical event"
+
 msgid "New History"
 msgstr "New piece of historical information"
 
@@ -364,6 +379,12 @@
 msgid "This HierarchicalRelation:"
 msgstr "This hierarchical relation:"
 
+msgid "This HistoricalEvent"
+msgstr "This historical event"
+
+msgid "This HistoricalEvent:"
+msgstr "This historical event:"
+
 msgid "This History"
 msgstr "This piece of historical information"
 
@@ -419,6 +440,9 @@
 msgid "abstract_format"
 msgstr ""
 
+msgid "add History has_event HistoricalEvent subject"
+msgstr ""
+
 msgid "add a AgentFunction"
 msgstr ""
 
@@ -483,6 +507,9 @@
 msgid "add a HierarchicalRelation"
 msgstr "add a hierarchical relation"
 
+msgid "add a HistoricalEvent"
+msgstr "add a historical event"
+
 msgid "add a History"
 msgstr ""
 
@@ -655,6 +682,9 @@
 msgid "could not parse date from %s"
 msgstr ""
 
+msgid "creating HistoricalEvent (History %(linkto)s has_event HistoricalEvent)"
+msgstr ""
+
 msgid "ctxcomponents_eac.xml_wrap"
 msgstr ""
 
@@ -796,6 +826,10 @@
 msgid "end_date"
 msgstr ""
 
+msgctxt "HistoricalEvent"
+msgid "end_date"
+msgstr ""
+
 msgctxt "LegalStatus"
 msgid "end_date"
 msgstr ""
@@ -857,12 +891,26 @@
 msgid "equivalent_concept_object"
 msgstr ""
 
+msgid "event"
+msgstr ""
+
+msgctxt "HistoricalEvent"
+msgid "event"
+msgstr ""
+
 #, python-format
 msgid ""
 "eventType %s does not match the PROV-O vocabulary, respective Activity will "
 "not have a `type` attribute set."
 msgstr ""
 
+msgid "event_format"
+msgstr ""
+
+msgctxt "HistoricalEvent"
+msgid "event_format"
+msgstr ""
+
 #, python-format
 msgid "expecting a %s tag in element %s, found none"
 msgstr ""
@@ -977,6 +1025,20 @@
 msgid "has_citation_object"
 msgstr ""
 
+msgid "has_event"
+msgstr ""
+
+msgctxt "History"
+msgid "has_event"
+msgstr ""
+
+msgid "has_event_object"
+msgstr ""
+
+msgctxt "HistoricalEvent"
+msgid "has_event_object"
+msgstr ""
+
 msgid "hierarchical_child"
 msgstr "child"
 
@@ -1188,6 +1250,13 @@
 msgid "place_agent_object"
 msgstr ""
 
+msgid "place_entry"
+msgstr ""
+
+msgctxt "HistoricalEvent"
+msgid "place_entry"
+msgstr ""
+
 msgid "postal_address"
 msgstr "postal address"
 
@@ -1294,6 +1363,10 @@
 msgid "start_date"
 msgstr ""
 
+msgctxt "HistoricalEvent"
+msgid "start_date"
+msgstr ""
+
 msgctxt "LegalStatus"
 msgid "start_date"
 msgstr ""
diff -r c6719ba14ca6 -r 8d8cb026854a cubicweb_eac/i18n/fr.po
--- a/cubicweb_eac/i18n/fr.po	Thu Jul 04 15:10:27 2019 +0200
+++ b/cubicweb_eac/i18n/fr.po	Fri Jul 19 16:23:03 2019 +0200
@@ -129,6 +129,9 @@
 msgid "EACSource_plural"
 msgstr "Sources"
 
+msgid "Events linked to an History object"
+msgstr "Événements liées à un segment d'histoire"
+
 msgid "GeneralContext"
 msgstr "Contexte général"
 
@@ -144,6 +147,15 @@
 msgid "HierarchicalRelation_plural"
 msgstr "Relations hiérarchiques"
 
+msgid "HistoricalEvent"
+msgstr "Événement historique"
+
+msgid "HistoricalEvent with date for describing an historical event"
+msgstr "Événement historique avec une date"
+
+msgid "HistoricalEvent_plural"
+msgstr "ÉvénementS historiqueS"
+
 msgid "History"
 msgstr "Élément d'information historique"
 
@@ -240,6 +252,9 @@
 msgid "New HierarchicalRelation"
 msgstr "Nouvelle relation hiérarchique"
 
+msgid "New HistoricalEvent"
+msgstr "Nouvel événement historique"
+
 msgid "New History"
 msgstr "Nouvel élément d'information historique"
 
@@ -369,6 +384,12 @@
 msgid "This HierarchicalRelation:"
 msgstr "Cette relation hiérarchique :"
 
+msgid "This HistoricalEvent"
+msgstr "Cet événement historique"
+
+msgid "This HistoricalEvent:"
+msgstr "Cet événement historique :"
+
 msgid "This History"
 msgstr "Cet élément d'information historique"
 
@@ -424,6 +445,9 @@
 msgid "abstract_format"
 msgstr ""
 
+msgid "add History has_event HistoricalEvent subject"
+msgstr "ajouter un événement historique"
+
 msgid "add a AgentFunction"
 msgstr ""
 
@@ -488,6 +512,9 @@
 msgid "add a HierarchicalRelation"
 msgstr "ajouter une relation hiérarchique"
 
+msgid "add a HistoricalEvent"
+msgstr "ajouter un Événement historique"
+
 msgid "add a History"
 msgstr ""
 
@@ -661,6 +688,9 @@
 msgid "could not parse date from %s"
 msgstr "impossible de décoder une date à partir de %s"
 
+msgid "creating HistoricalEvent (History %(linkto)s has_event HistoricalEvent)"
+msgstr ""
+
 msgid "ctxcomponents_eac.xml_wrap"
 msgstr "Données XML supplémentaires"
 
@@ -802,6 +832,10 @@
 msgid "end_date"
 msgstr ""
 
+msgctxt "HistoricalEvent"
+msgid "end_date"
+msgstr ""
+
 msgctxt "LegalStatus"
 msgid "end_date"
 msgstr ""
@@ -863,6 +897,13 @@
 msgid "equivalent_concept_object"
 msgstr ""
 
+msgid "event"
+msgstr ""
+
+msgctxt "HistoricalEvent"
+msgid "event"
+msgstr ""
+
 #, python-format
 msgid ""
 "eventType %s does not match the PROV-O vocabulary, respective Activity will "
@@ -871,6 +912,13 @@
 "le type d'événement %s ne correspond pas au vocabulaire PROV-O, l'attribut "
 "type de l'activité associée ne sera pas défini"
 
+msgid "event_format"
+msgstr ""
+
+msgctxt "HistoricalEvent"
+msgid "event_format"
+msgstr ""
+
 #, python-format
 msgid "expecting a %s tag in element %s, found none"
 msgstr "une balise %s était attendue dans l'élément %s, aucune n'a été trouvée"
@@ -995,6 +1043,20 @@
 msgid "has_citation_object"
 msgstr ""
 
+msgid "has_event"
+msgstr "événément historique"
+
+msgctxt "History"
+msgid "has_event"
+msgstr ""
+
+msgid "has_event_object"
+msgstr "élément d'information historique"
+
+msgctxt "HistoricalEvent"
+msgid "has_event_object"
+msgstr ""
+
 msgid "hierarchical_child"
 msgstr "enfant"
 
@@ -1208,6 +1270,13 @@
 msgid "place_agent_object"
 msgstr ""
 
+msgid "place_entry"
+msgstr ""
+
+msgctxt "HistoricalEvent"
+msgid "place_entry"
+msgstr ""
+
 msgid "postal_address"
 msgstr "adresse postale"
 
@@ -1314,6 +1383,10 @@
 msgid "start_date"
 msgstr ""
 
+msgctxt "HistoricalEvent"
+msgid "start_date"
+msgstr ""
+
 msgctxt "LegalStatus"
 msgid "start_date"
 msgstr ""
diff -r c6719ba14ca6 -r 8d8cb026854a cubicweb_eac/migration/0.9.0_Any.py
--- a/cubicweb_eac/migration/0.9.0_Any.py	Thu Jul 04 15:10:27 2019 +0200
+++ b/cubicweb_eac/migration/0.9.0_Any.py	Fri Jul 19 16:23:03 2019 +0200
@@ -1,1 +1,2 @@
 add_attribute('History', 'abstract')
+add_entity_type('HistoricalEvent')
diff -r c6719ba14ca6 -r 8d8cb026854a cubicweb_eac/schema.py
--- a/cubicweb_eac/schema.py	Thu Jul 04 15:10:27 2019 +0200
+++ b/cubicweb_eac/schema.py	Fri Jul 19 16:23:03 2019 +0200
@@ -265,6 +265,22 @@
     text = RichString(fulltextindexed=True)
 
 
+ at dated_entity_type
+class HistoricalEvent(EntityType):
+    """Events linked to an History object"""
+    event = RichString(fulltextindexed=True)
+    place_entry = String(fulltextindexed=True)
+
+
+class has_event(RelationDefinition):
+    subject = 'History'
+    object = 'HistoricalEvent'
+    cardinality = '*1'
+    composite = 'subject'
+    fulltext_container = 'subject'
+    description = _('HistoricalEvent with date for describing an historical event')
+
+
 class Structure(EntityType):
     """Information about the structure of an authority"""
     description = RichString(fulltextindexed=True)
diff -r c6719ba14ca6 -r 8d8cb026854a test/data/FRAD033_EAC_00001_simplified.xml
--- a/test/data/FRAD033_EAC_00001_simplified.xml	Thu Jul 04 15:10:27 2019 +0200
+++ b/test/data/FRAD033_EAC_00001_simplified.xml	Fri Jul 19 16:23:03 2019 +0200
@@ -199,6 +199,30 @@
           <p>L'inspecteur Canardo</p>
           <citation xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.assemblee-nationale.fr/histoire/images-decentralisation/decentralisation/loi-du-22-decembre-1789-.pdf" xlink:type="simple"></citation>
           <citation xlink:href="http://pifgadget">Voir aussi pifgadget</citation>
+	  <chronList>
+	    <chronItem>
+	      <date standardDate="1957">1957
+	      </date>
+	      <event>Left Mer and moved to the mainland.
+	      Worked at various jobs including canecutter
+	      and railway labourer.
+	      </event>
+	    </chronItem>
+	    <chronItem>
+	      <dateRange>
+		<fromDate
+		    standardDate="1960">1960
+		</fromDate>
+		<toDate standardDate="1961">1961
+		</toDate>
+	      </dateRange>
+	      <event>Union representative, Townsville-
+	      Mount Isa rail construction project.
+	      </event>
+	    </chronItem>
+	  </chronList>
+	  <chronList></chronList>
+	  <chronList><chronItem></chronItem></chronList>
       </biogHist>
 
       <!--empty biogHist-->
diff -r c6719ba14ca6 -r 8d8cb026854a test/test_dataimport.py
--- a/test/test_dataimport.py	Thu Jul 04 15:10:27 2019 +0200
+++ b/test/test_dataimport.py	Fri Jul 19 16:23:03 2019 +0200
@@ -182,7 +182,8 @@
              },
             ),
             ('History', _gen_extid(),
-             {'text': set(["\n".join((
+             {'abstract': set([u'Test of an abstract element']),
+              'text': set(["\n".join((
                      u'<p xmlns="urn:isbn:1-931666-33-4" '
                      u'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" '
                      u'xmlns:xlink="http://www.w3.org/1999/xlink">{0}</p>'
@@ -192,7 +193,7 @@
               'text_format': set([u'text/html']),
               'history_agent': set(['FRAD033_EAC_00001']),
               'has_citation': set(['16', '17']),
-              'abstract': set([u'Test of an abstract element']),
+              'has_event': set(['18', '19']),
              },
             ),
             ('Citation', _gen_extid(),
@@ -201,6 +202,16 @@
             ('Citation', _gen_extid(),
              {'uri': set(['http://pifgadget']), 'note': set(['Voir aussi pifgadget'])},
             ),
+            ('HistoricalEvent', _gen_extid(),
+             {'event': [u'Left Mer and moved to the mainland.\n\t      Worked at various jobs including canecutter\n\t      and railway labourer.\n\t      '], # noqa
+              'end_date': set([datetime.date(1957, 1, 1)]),
+              'start_date': set([datetime.date(1957, 1, 1)])}
+            ),
+            ('HistoricalEvent', _gen_extid(),
+             {'event': set([u'Union representative, Townsville-\n\t      Mount Isa rail construction project.\n\t      ']), # noqa
+              'end_date': set([datetime.date(1961, 1, 1)]),
+              'start_date': set([datetime.date(1960, 1, 1)])}
+            ),
             ('Structure', _gen_extid(),
              {'description': set([u'<p xmlns="urn:isbn:1-931666-33-4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink">Pour accomplir ses missions ...</p>']),  # noqa
               'description_format': set([u'text/html']),
@@ -238,7 +249,7 @@
               'description': set([u'Organisation des réunions ...']),
               'description_format': set([u'text/plain']),
               'occupation_agent': set(['FRAD033_EAC_00001']),
-              'has_citation': set(['23']),
+              'has_citation': set(['25']),
               'equivalent_concept': set(['http://pifgadget.com']),
              },
             ),
@@ -251,7 +262,7 @@
                               u'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" '
                               u'xmlns:xlink="http://www.w3.org/1999/xlink">very famous</p>']),
               'content_format': set([u'text/html']),
-              'has_citation': set(['25']),
+              'has_citation': set(['27']),
               'general_context_of': set(['FRAD033_EAC_00001']),
               }
             ),
@@ -335,7 +346,7 @@
             ('ExternalUri', 'http://catalogue.bnf.fr/ark:/12148/cb152418385',
              {'uri': set([u'http://catalogue.bnf.fr/ark:/12148/cb152418385']),
               'cwuri': set([u'http://catalogue.bnf.fr/ark:/12148/cb152418385'])},
-            ),
+           ),
             ('ExternalUri', 'http://pifgadget.com',
              {'uri': set([u'http://pifgadget.com']),
               'cwuri': set([u'http://pifgadget.com'])},
@@ -367,7 +378,7 @@
                           'localControl': set([54]),
                           'source': set([76]),  # empty.
                           'structureOrGenealogy': set([189]),  # empty.
-                          'biogHist': set([205, 208]),  # empty.
+                          'biogHist': set([229, 232]),  # empty.
                           })
 
     def test_mandate_under_mandates(self):
@@ -465,7 +476,7 @@
                                cwuri=u'http://data.culture.fr/thesaurus/page/ark:/67717/T1-1074')
             cnx.commit()
             created, updated = testutils.eac_import(cnx, fpath)
-            self.assertEqual(len(created), 39)
+            self.assertEqual(len(created), 41)
             self.assertEqual(updated, set())
             rset = cnx.find('AuthorityRecord', isni=u'22330001300016')
             self.assertEqual(len(rset), 1)
@@ -509,6 +520,8 @@
         self.assertEqual(entity.printable_value('text',
                                                 format=u'text/plain').strip(),
                          u"La loi du 22 décembre 1789, en divisant ...\n\nL'inspecteur Canardo")
+        events = rset.one().has_event
+        self.assertEqual(len(events), 2)
 
     def _check_mandate(self, cnx, record):
         rset = cnx.find('Mandate', mandate_agent=record)
diff -r c6719ba14ca6 -r 8d8cb026854a test/test_schema.py
--- a/test/test_schema.py	Thu Jul 04 15:10:27 2019 +0200
+++ b/test/test_schema.py	Fri Jul 19 16:23:03 2019 +0200
@@ -108,6 +108,7 @@
             'EACResourceRelation': {('resource_relation_agent', 'subject'):
                                     set(['AuthorityRecord'])},
             'EACSource': {('source_agent', 'subject'): set(['AuthorityRecord'])},
+            'HistoricalEvent': {('has_event', 'object'): set(['History'])},
             'GeneralContext': {('general_context_of', 'subject'): set(['AuthorityRecord'])},
             'History': {('history_agent', 'subject'): set(['AuthorityRecord'])},
             'LegalStatus': {('legal_status_agent', 'subject'): set(['AuthorityRecord'])},


More information about the saem-devel mailing list