[PATCH 2 of 2 eac V2] Add support for <functionRelation> in <cpfRelation>

Guillaume Vandevelde guillaume.vandevelde at logilab.fr
Fri Aug 9 12:41:48 CEST 2019


# HG changeset patch
# User Guillaume Vandevelde <gvandevelde at logilab.fr>
# Date 1564500697 -7200
#      Tue Jul 30 17:31:37 2019 +0200
# Node ID c37835aca3abb4b6cb422bd9bc584123c8495b19
# Parent  506b5b445292e3f8c8206ecd4516b78da59e953a
# Available At http://hg.logilab.org/review/cubes/eac
#              hg pull http://hg.logilab.org/review/cubes/eac -r c37835aca3ab
Add support for <functionRelation> in <cpfRelation>

Create a new entity EACFunctionRelation similar to EACRessourceRelation.

diff -r 506b5b445292 -r c37835aca3ab cubicweb_eac/dataimport.py
--- a/cubicweb_eac/dataimport.py	Tue Jul 30 17:31:36 2019 +0200
+++ b/cubicweb_eac/dataimport.py	Tue Jul 30 17:31:37 2019 +0200
@@ -40,11 +40,11 @@
 TYPE_MAPPING['human'] = u'person'
 
 ETYPES_ORDER_HINT = ('AgentKind', 'PhoneNumber', 'PostalAddress', 'AuthorityRecord',
-                     'Convention', 'AgentPlace', 'Mandate', 'LegalStatus',
-                     'History', 'HistoricalEvent', 'Structure', 'AgentFunction', 'Occupation',
-                     'GeneralContext', 'AssociationRelation', 'ChronologicalRelation',
-                     'HierarchicalRelation', 'EACResourceRelation', 'ExternalUri',
-                     'EACSource', 'Activity')
+                     'Convention', 'AgentPlace', 'Mandate',
+                     'LegalStatus', 'History', 'HistoricalEvent', 'Structure', 'AgentFunction',
+                     'Occupation', 'GeneralContext', 'AssociationRelation', 'ChronologicalRelation',
+                     'HierarchicalRelation', 'EACResourceRelation', 'EACFunctionRelation',
+                     'ExternalUri', 'EACSource', 'Activity')
 
 
 class InvalidEAC(RuntimeError):
@@ -773,7 +773,8 @@
         if relations is None:
             return
         builders = (('eac:cpfRelation', self.build_relation),
-                    ('eac:resourceRelation', self.build_resource_relation),)
+                    ('eac:resourceRelation', self.build_resource_relation),
+                    ('eac:functionRelation', self.build_function_relation),)
         for xpath, builder in builders:
             for elem in self._elem_findall(relations, xpath):
                 for extentity in builder(elem):
@@ -836,6 +837,50 @@
         values.update(self.parse_tag_description(elem))
         yield ExtEntity(etype, self._gen_extid(), values)
 
+    @add_xml_wrap_for('EACFunctionRelation')
+    def build_function_relation(self, elem):
+        """Build a relation between function entities
+
+        yield an ExternalUri object, and an EACFunctionRelation
+        object that make the link between the ExternalUri and
+        the AuthorityRecord object"""
+        relationship = elem.attrib.get('functionRelationType')
+        if relationship is None:
+            self.import_log.record_warning(self._(
+                'found no functionRelationType attribute in element %s, defaulting '
+                'to performs') % etree.tostring(elem),
+                line=elem.sourceline)
+            relationship = 'performs'
+        obj_uri = elem.attrib.get('{%(xlink)s}href' % self.namespaces)
+        if obj_uri is None:
+            self.import_log.record_warning(self._(
+                'found a functionRelation without any object (no xlink:href '
+                'attribute), skipping'), line=elem.sourceline)
+            return
+        # Yield the ExternalUri object
+        yield external_uri(obj_uri)
+        values = self.parse_tag_description(elem)
+        dates = self.parse_daterange(
+            self._elem_find(elem, 'eac:dateRange'))
+        if dates:
+            values.update(dates)
+        values.update({
+            'r_type': set([text_type(relationship)]),
+            'function_relation_function': set([text_type(obj_uri)]),
+            'function_relation_agent': set([text_type(self.record.extid)]),
+        })
+        values.update(self.values_from_xpaths(
+            elem,
+            (('place_entry', 'eac:placeEntry'),
+             ('relation_entry', 'eac:relationEntry'))))
+        attrib = {k: v for (k, v) in dict(elem.attrib).items() if k not in {
+            'functionRelationType',
+            '{%(xlink)s}href' % self.namespaces
+        }}
+        if attrib:
+            values.update({'attributes': set([text_type(attrib)])})
+        yield ExtEntity('EACFunctionRelation', self._gen_extid(), values)
+
     @add_xml_wrap_for('EACResourceRelation')
     def build_resource_relation(self, elem):
         """Build a `EACResourceRelation` external entity (along with
diff -r 506b5b445292 -r c37835aca3ab cubicweb_eac/entities.py
--- a/cubicweb_eac/entities.py	Tue Jul 30 17:31:36 2019 +0200
+++ b/cubicweb_eac/entities.py	Tue Jul 30 17:31:37 2019 +0200
@@ -134,6 +134,23 @@
                  'to': resource_title})
 
 
+class EACFunctionRelation(AnyEntity):
+    __regid__ = 'EACFunctionRelation'
+    fetch_attrs, cw_fetch_order = fetch_config(('r_type',
+                                                'description',
+                                                'relation_entry',
+                                                'place_entry',
+                                                'attributes',))
+
+    @property
+    def record(self):
+        return self.function_relation_agent[0]
+
+    @property
+    def resource(self):
+        return self.function_relation_function[0]
+
+
 class SameAsMixIn(object):
     """Mix-in class for entity types supporting vocabulary_source and
     equivalent_concept relations.
diff -r 506b5b445292 -r c37835aca3ab cubicweb_eac/migration/0.9.0_Any.py
--- a/cubicweb_eac/migration/0.9.0_Any.py	Tue Jul 30 17:31:36 2019 +0200
+++ b/cubicweb_eac/migration/0.9.0_Any.py	Tue Jul 30 17:31:37 2019 +0200
@@ -1,3 +1,4 @@
 add_attribute('History', 'abstract')
 add_entity_type('HistoricalEvent')
 add_entity_type('Convention')
+add_entity_type('EACFunctionRelation')
diff -r 506b5b445292 -r c37835aca3ab cubicweb_eac/schema.py
--- a/cubicweb_eac/schema.py	Tue Jul 30 17:31:36 2019 +0200
+++ b/cubicweb_eac/schema.py	Tue Jul 30 17:31:37 2019 +0200
@@ -371,6 +371,35 @@
 
 @xml_wrap
 @dated_entity_type
+class EACFunctionRelation(EntityType):
+    """Represent a relation between an AuthorityRecord and a function"""
+    r_type = String(internationalizable=True,
+                    description=_('type of relation the function has '
+                                  'with the Authority'))
+    description = RichString(fulltextindexed=True)
+    relation_entry = String(fulltextindexed=True)
+    place_entry = String(fulltextindexed=True)
+    attributes = String(fulltextindexed=True)
+
+
+class function_relation_agent(RelationDefinition):
+    subject = 'EACFunctionRelation'
+    object = 'AuthorityRecord'
+    cardinality = '1*'
+    inlined = True
+    composite = 'object'
+    fulltext_container = 'object'
+
+
+class function_relation_function(RelationDefinition):
+    subject = 'EACFunctionRelation'
+    object = 'ExternalUri'
+    cardinality = '1*'
+    inlined = True
+
+
+ at xml_wrap
+ at dated_entity_type
 class EACResourceRelation(EntityType):
     """Represent a relation between an AuthorityRecord and a remote resource in the
     EAC-CPF model.
diff -r 506b5b445292 -r c37835aca3ab test/data/FRAD033_EAC_00001_simplified.xml
--- a/test/data/FRAD033_EAC_00001_simplified.xml	Tue Jul 30 17:31:36 2019 +0200
+++ b/test/data/FRAD033_EAC_00001_simplified.xml	Tue Jul 30 17:31:37 2019 +0200
@@ -261,7 +261,6 @@
       </cpfRelation>
 
       <cpfRelation cpfRelationType="associative" xlink:href="agent-x" xlink:type="simple"></cpfRelation>
-
       <resourceRelation resourceRelationType="creatorOf"
         xmlns:xlink="http://www.w3.org/1999/xlink" 
         xlink:href="http://gael.gironde.fr/ead.html?id=FRAD033_IR_N" xlink:type="simple" xlink:role="Fonds d'archives" xlink:show="new" xlink:actuate="onRequest">
@@ -271,7 +270,63 @@
           <toDate>1963</toDate>
         </dateRange>
       </resourceRelation>
-      
+      <functionRelation
+	  functionRelationType="performs"
+	  xlink:href="http://gael.gironde.fr/ead.html?id=FRAD033_IR_N"
+	  xlink:actuate="onLoad"
+	  xlink:arcrole="http://test_arcrole.lol.com"
+	  xlink:role="http://test_role.lmao.com">
+	<relationEntry>Alumni communication
+	management, University of
+	Glasgow
+	</relationEntry>
+	<descriptiveNote>
+	  <p>The management of the University's
+	  communication with its alumni.
+	  </p>
+	</descriptiveNote>
+	<objectXMLWrap>
+	  <mods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xsi:schemaLocation="http://www.loc.gov/mods/v3 http:
+				    //www.loc.gov/mods/v3/mods-3-3.xsd">
+	    <titleInfo>
+	      <title>Artisti trentini tra le due
+	      guerre
+	      </title>
+	    </titleInfo>
+	    <name>
+	      <namePart
+		  type="given">Nicoletta
+	      </namePart>
+	      <namePart
+		  type="family">Boschiero
+	      </namePart>
+	      <role>
+		<roleTerm
+		    type="text">autore
+		</roleTerm>
+	      </role>
+	    </name>
+	  </mods>
+	</objectXMLWrap>
+      </functionRelation>
+      <functionRelation
+	  functionRelationType="controls"
+	  xlink:href="FRAD033_IR_N">
+	<dateRange>
+          <fromDate standardDate="1922">1922</fromDate>
+          <toDate standardDate="2001">2001</toDate>
+          </dateRange>
+	<relationEntry>Establishment and abolishment
+	of schools
+	</relationEntry>
+	<descriptiveNote>
+	  <p>The second responsibility of the
+	  Department is to control the establishment
+	  and abolishment of schools.
+	  </p>
+	</descriptiveNote>
+      </functionRelation>
       
     </relations>
 
diff -r 506b5b445292 -r c37835aca3ab test/test_dataimport.py
--- a/test/test_dataimport.py	Tue Jul 30 17:31:36 2019 +0200
+++ b/test/test_dataimport.py	Tue Jul 30 17:31:37 2019 +0200
@@ -390,6 +390,42 @@
               'xml_wrap': set(['<he xmlns="urn:isbn:1-931666-33-4" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">joe</he>']),  # noqa
              },
             ),
+            ('EACFunctionRelation', _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">The management of the University'
+                                  '\'s\n\t  communication with its alumni.\n\t  </p>']),
+              'r_type': [u'performs'],
+              'description_format': set([u'text/html']),
+              'function_relation_agent': set([u'FRAD033_EAC_00001']),
+              'function_relation_function': set([u'http://gael.gironde.fr/ead.html?'
+                                                 'id=FRAD033_IR_N']),
+              'relation_entry': set([u'Alumni communication\n\tmanagement, '
+                                     'University of\n\tGlasgow\n\t']),
+              'xml_wrap': set(['<mods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:isbn:1-931666-33-4" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://www.loc.gov/mods/v3 http:         //www.loc.gov/mods/v3/mods-3-3.xsd">\n\t    <titleInfo>\n\t      <title>Artisti trentini tra le due\n\t      guerre\n\t      </title>\n\t    </titleInfo>\n\t    <name>\n\t      <namePart type="given">Nicoletta\n\t      </namePart>\n\t      <namePart type="family">Boschiero\n\t      </namePart>\n\t      <role>\n\t\t<roleTerm type="text">autore\n\t\t</roleTerm>\n\t      </role>\n\t    </name>\n\t  </mods>\n\t']), # noqa
+              'attributes': set([u"{'{http://www.w3.org/1999/xlink}actuate': 'onLoad', '{http://www.w3.org/1999/xlink}arcrole': 'http://test_arcrole.lol.com', '{http://www.w3.org/1999/xlink}role': 'http://test_role.lmao.com'}"]) # noqa
+             },
+            ),
+            ('EACFunctionRelation', _gen_extid(),
+             {'function_relation_function': set([u'FRAD033_IR_N']),
+              'function_relation_agent': set([u'FRAD033_EAC_00001']),
+              '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">'
+                                  'The second responsibility of the\n\t  '
+                                  'Department is to control the establishment\n\t  '
+                                  'and abolishment of schools.\n\t  </p>']),
+              'end_date': set([datetime.date(2001, 1, 1)]),
+              'r_type': set([u'controls']),
+              'description_format': set([u'text/html']),
+              'relation_entry': set([u'Establishment and abolishment\n\tof schools\n\t']),
+              'start_date': set([datetime.date(1922, 1, 1)])
+             },
+            ),
+            ('ExternalUri', 'FRAD033_IR_N',
+             {'uri': set([u'FRAD033_IR_N']),
+              'cwuri': set([u'FRAD033_IR_N'])},
+            ),
             ('ExternalUri', 'http://gael.gironde.fr/ead.html?id=FRAD033_IR_N',
              {'uri': set([u'http://gael.gironde.fr/ead.html?id=FRAD033_IR_N']),
               'cwuri': set([u'http://gael.gironde.fr/ead.html?id=FRAD033_IR_N'])},
@@ -561,7 +597,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), 45)
+            self.assertEqual(len(created), 48)
             self.assertEqual(updated, set())
             rset = cnx.find('AuthorityRecord', isni=u'22330001300016')
             self.assertEqual(len(rset), 1)
@@ -669,6 +705,27 @@
                          u'http://gael.gironde.fr/ead.html?id=FRAD033_IR_N')
         self.assertEqual(rrelation.xml_wrap.getvalue(),
                          '<he xmlns="urn:isbn:1-931666-33-4" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">joe</he>')  # noqa
+        rset = cnx.find('EACFunctionRelation', r_type=u'performs')
+        func_relation = rset.one()
+        self.assertEqual(func_relation.attributes,
+                         u"{'{http://www.w3.org/1999/xlink}actuate': 'onLoad', '{http://www.w3.org/1999/xlink}arcrole': 'http://test_arcrole.lol.com', '{http://www.w3.org/1999/xlink}role': 'http://test_role.lmao.com'}") # noqa
+        self.assertEqual(func_relation.relation_entry,
+                         u'Alumni communication\n\tmanagement, '
+                         'University of\n\tGlasgow\n\t')
+        self.assertEqual(func_relation.xml_wrap.getvalue(),
+                         u'<mods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:isbn:1-931666-33-4" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://www.loc.gov/mods/v3 http:         //www.loc.gov/mods/v3/mods-3-3.xsd">\n\t    <titleInfo>\n\t      <title>Artisti trentini tra le due\n\t      guerre\n\t      </title>\n\t    </titleInfo>\n\t    <name>\n\t      <namePart type="given">Nicoletta\n\t      </namePart>\n\t      <namePart type="family">Boschiero\n\t      </namePart>\n\t      <role>\n\t\t<roleTerm type="text">autore\n\t\t</roleTerm>\n\t      </role>\n\t    </name>\n\t  </mods>\n\t') # noqa
+        self.assertEqual(func_relation.function_relation_agent[0], record)
+        self.assertEqual(func_relation.function_relation_function[0].uri,
+                         u'http://gael.gironde.fr/ead.html?id=FRAD033_IR_N')
+        rset = cnx.find('EACFunctionRelation', r_type=u'controls')
+        func_relation = rset.one()
+        self.assertEqual(func_relation.function_relation_agent[0], record)
+        self.assertEqual(func_relation.function_relation_function[0].uri,
+                         u'FRAD033_IR_N')
+        self.assertEqual(func_relation.start_date,
+                         datetime.date(1922, 1, 1))
+        self.assertEqual(func_relation.end_date,
+                         datetime.date(2001, 1, 1))
 
     def _check_equivalent_concept(self, cnx, record):
         functions = dict((f.name, f) for f in record.reverse_function_agent)
diff -r 506b5b445292 -r c37835aca3ab test/test_schema.py
--- a/test/test_schema.py	Tue Jul 30 17:31:36 2019 +0200
+++ b/test/test_schema.py	Tue Jul 30 17:31:37 2019 +0200
@@ -103,6 +103,8 @@
                 'GeneralContext', 'Mandate', 'Occupation', 'AgentFunction',
                 'AgentPlace', 'History', 'LegalStatus', 'Convention',
             ])},
+            'EACFunctionRelation': {('function_relation_agent', 'subject'):
+                                    set(['AuthorityRecord'])},
             'EACOtherRecordId': {('eac_other_record_id_of', 'subject'):
                                  set(['AuthorityRecord'])},
             'EACResourceRelation': {('resource_relation_agent', 'subject'):



More information about the saem-devel mailing list