From 66c947c86ec83b26858e93d3298deb131359a457 Mon Sep 17 00:00:00 2001 From: Cole Maclean Date: Mon, 25 Feb 2019 14:36:15 -0800 Subject: [PATCH 1/4] Removed classmethod duplication. --- metsrw/mets.py | 46 ++++++++++++++++------------------------------ 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/metsrw/mets.py b/metsrw/mets.py index a927396..3b355f5 100755 --- a/metsrw/mets.py +++ b/metsrw/mets.py @@ -470,56 +470,42 @@ def _parse_tree(self, tree=None): def _validate(self): raise NotImplementedError() - def _fromfile(self, path): + @classmethod + def fromfile(cls, path): """ - Accept a filepath pointing to a valid METS document and parses it. + Creates a METS by parsing a file. :param str path: Path to a METS document. """ parser = etree.XMLParser(remove_blank_text=True) - self.tree = etree.parse(path, parser=parser) - self._parse_tree(self.tree) - @classmethod - def fromfile(cls, path): - """ Creates a METS by parsing a file. """ - i = cls() - i._fromfile(path) - return i + return cls.fromtree(etree.parse(path, parser=parser)) - def _fromstring(self, string): + @classmethod + def fromstring(cls, string): """ - Accept a string containing valid METS xml and parses it. + Create a METS by parsing a string. :param str string: String containing a METS document. """ parser = etree.XMLParser(remove_blank_text=True) root = etree.fromstring(string, parser) - self.tree = root.getroottree() - self._parse_tree(self.tree) + tree = root.getroottree() - @classmethod - def fromstring(cls, string): - """ Create a METS by parsing a string. """ - i = cls() - i._fromstring(string) - return i + return cls.fromtree(tree) - def _fromtree(self, tree): + @classmethod + def fromtree(cls, tree): """ - Accept an ElementTree or Element and parses it. + Create a METS from an ElementTree or Element. :param ElementTree tree: ElementTree to build a METS document from. """ - self.tree = tree - self._parse_tree(self.tree) + mets = cls() + mets.tree = tree + mets._parse_tree(tree) - @classmethod - def fromtree(cls, tree): - """ Create a METS from an ElementTree or Element. """ - i = cls() - i._fromtree(tree) - return i + return mets if __name__ == '__main__': From 0d7fdc5fafa80a992df3b9ebe17a3bcab9b4ec9d Mon Sep 17 00:00:00 2001 From: Cole Maclean Date: Wed, 13 Mar 2019 14:16:47 -0700 Subject: [PATCH 2/4] Added embedded XML support. Required for objectCharacteristicsExtension --- metsrw/plugins/premisrw/premis.py | 5 ++++- tests/plugins/premisrw/test_premis.py | 27 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/metsrw/plugins/premisrw/premis.py b/metsrw/plugins/premisrw/premis.py index ee25dda..605c6a8 100644 --- a/metsrw/plugins/premisrw/premis.py +++ b/metsrw/plugins/premisrw/premis.py @@ -298,7 +298,8 @@ def schema(self): 'inhibitors', ('inhibitor_type',), ('inhibitor_target',), - ) + ), + ('object_characteristics_extension',) ), ( 'relationship', @@ -490,6 +491,8 @@ def _data_to_lxml_el(data, ns, nsmap, element_maker=None, snake=True): element, ns, nsmap, element_maker=element_maker, snake=snake)) elif isinstance(element, six.text_type): args.append(element) + elif isinstance(element, etree._Element): + args.append(element) else: args.append(six.binary_type(element)) ret = func(*args) diff --git a/tests/plugins/premisrw/test_premis.py b/tests/plugins/premisrw/test_premis.py index 6951f7d..67645d4 100644 --- a/tests/plugins/premisrw/test_premis.py +++ b/tests/plugins/premisrw/test_premis.py @@ -2,6 +2,7 @@ from unittest import TestCase import pytest +from lxml import etree import metsrw import metsrw.plugins.premisrw as premisrw @@ -364,3 +365,29 @@ def test_dynamic_class_generation(self): assert pres_deriv_uuid pres_deriv_fsentry = mets.get_file(file_uuid=pres_deriv_uuid) assert pres_deriv_fsentry.path == orig_to_pres_deriv[fsentry.path] + + def test_object_characteristics_extension(self): + """ + Test the object characteristics extension container element with embedded XML. + """ + embedded_xml = etree.Element('arbitrary-xml') + child_element = etree.Element('a-child-element') + child_element.text = "Hello world" + embedded_xml.append(child_element) + + premis_element = premisrw.data_to_premis(( + 'object', + premisrw.PREMIS_META, + ( + 'object_identifier', + ('object_identifier_type', 'UUID'), + ('object_identifier_value', '8bce611a-fabc-4161-8108-ba041fb8e7b4'), + ), + ( + 'object_characteristics', + ('object_characteristics_extension', embedded_xml) + ) + )) + + xpath_lookup = './/premis:objectCharacteristicsExtension/arbitrary-xml' + assert premis_element.xpath(xpath_lookup, namespaces=premis_element.nsmap)[0] == embedded_xml From 71be00ce034b2c85f592c79721e716b5bd830a8a Mon Sep 17 00:00:00 2001 From: Cole Maclean Date: Wed, 13 Mar 2019 14:27:41 -0700 Subject: [PATCH 3/4] Python 3.7 is a thing now. --- .travis.yml | 3 +++ tox.ini | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d21bd85..c5aa534 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ sudo: false +dist: xenial language: python install: @@ -14,6 +15,8 @@ matrix: env: TOXENV=py34 - python: 3.6 env: TOXENV=py36 + - python: 3.7 + env: TOXENV=py37 script: - tox -e $TOXENV diff --git a/tox.ini b/tox.ini index 98a77fd..dcdd997 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py{27,34,36}, flake8 +envlist = py{27,34,36,37}, flake8 skip_missing_interpreters = True skipsdist = True From b6a9c3fe2a99973b66c1fb8c23c00966108ac0da Mon Sep 17 00:00:00 2001 From: Cole Maclean Date: Wed, 13 Mar 2019 14:36:14 -0700 Subject: [PATCH 4/4] flake8 --- tests/test_metadata.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_metadata.py b/tests/test_metadata.py index 2daaa5d..18c5717 100644 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -52,8 +52,8 @@ def test_replacement_techmd(self): techmd_old = metsrw.SubSection('techMD', self.STUB_MDWRAP) techmd_new = metsrw.SubSection('techMD', self.STUB_MDWRAP) techmd_old.replace_with(techmd_new) - assert techmd_old.get_status() is 'superseded' - assert techmd_new.get_status() is 'current' + assert techmd_old.get_status() == 'superseded' + assert techmd_new.get_status() == 'current' def test_replacement_sourcemd(self): """ It should have no special behaviour replacing sourceMDs. """