6999987 Need for a simple XML node base-class in the data cache Build154
authorDarren Kenny <Darren.Kenny@Oracle.COM>
Wed, 24 Nov 2010 19:37:52 +0000
changeset 950 382a165ad03b
parent 949 77a2901ff057
child 951 1ba12d3daefe
6999987 Need for a simple XML node base-class in the data cache
usr/src/lib/install_doc/data_object/Makefile
usr/src/lib/install_doc/data_object/__init__.py
usr/src/lib/install_doc/data_object/simple.py
usr/src/lib/install_doc/test/test_data_object_simple.py
usr/src/pkg/manifests/system-library-install.mf
--- a/usr/src/lib/install_doc/data_object/Makefile	Wed Nov 24 10:20:59 2010 -0800
+++ b/usr/src/lib/install_doc/data_object/Makefile	Wed Nov 24 19:37:52 2010 +0000
@@ -27,7 +27,8 @@
 
 PYMODS		= __init__.py \
 		cache.py \
-		data_dict.py
+		data_dict.py \
+		simple.py
 
 PYCMODS		= $(PYMODS:%.py=%.pyc)
 
--- a/usr/src/lib/install_doc/data_object/__init__.py	Wed Nov 24 10:20:59 2010 -0800
+++ b/usr/src/lib/install_doc/data_object/__init__.py	Wed Nov 24 19:37:52 2010 +0000
@@ -26,7 +26,7 @@
 '''Provides definition of base classes for storage in Data Object Cache.
 '''
 
-__all__ = ["cache", "data_dict"]
+__all__ = ["cache", "data_dict", "simple"]
 
 import copy
 import logging
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/install_doc/data_object/simple.py	Wed Nov 24 19:37:52 2010 +0000
@@ -0,0 +1,110 @@
+#!/usr/bin/python
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+'''Defines the SimpleXmlHandlerBase class to convert simple XML to DataObject
+'''
+
+from lxml import etree
+
+from solaris_install.data_object import DataObject, ParsingError
+
+
+class SimpleXmlHandlerBase(DataObject):
+    '''Simple XML handling DataObject base-class.
+
+       Not to be instantiated directly, should be sub-classed.
+
+       Converts a simple xml tag (e.g. <tag>) to a DataObject, if there is a
+       name attribute in the tag, then it will be used as the name of the
+       DataObject.
+
+       To make it work, you need to sub-class it and redefine the value of
+       TAG_NAME to match the XML tag, e.g.:
+
+            from solaris_install.data_object.simple import SimpleXmlHandlerBase
+
+            # Define the class
+            class MyTag(SimpleXmlHandlerBase):
+                TAG_NAME="mytag"
+
+            # Register with DOC so that it will be used.
+            DataObjectCache.register_class(MyTag)
+
+       and that's it, this will take an XML tag like the following:
+
+           <mytag>
+              ...
+           </mytag>
+
+       and generate a DataObject for storage in the Data Object Cache.
+
+       The main reason you might do this is to place a set of sub-tags into a
+       specific location in the DOC.
+
+    '''
+
+    TAG_NAME = None
+
+    def __init__(self, name=None):
+        if self.TAG_NAME is None:
+            raise ValueError("TAG_NAME should not be None.")
+
+        super(DataObject, self).__init__(name)
+
+    def to_xml(self):
+        '''Generate XML'''
+        elem = etree.Element(self.TAG_NAME)
+        if self.name and self.name != self.TAG_NAME:
+            # We got a name on import, so set it on export
+            elem.set("name", self.name)
+
+        return(elem)
+
+    @classmethod
+    def can_handle(cls, element):
+        '''Check if XML tag matches TAG_NAME'''
+        if element.tag != cls.TAG_NAME:
+            return False
+        return True
+
+    @classmethod
+    def from_xml(cls, element):
+        '''Convert XML tag to a DataObject.
+
+           If there is a name attribute in the XML tag, then we will use that
+           as the name of the object for insertion in the the Data Object
+           Cache.
+        '''
+
+        if element.tag != cls.TAG_NAME:
+            raise ParsingError("Tag name %s != %s" %
+                (element.tag, cls.TAG_NAME))
+
+        # See if there is a name attribute, if so use it.
+        name = element.get("name")
+        if not name:
+            name = cls.TAG_NAME
+
+        return cls(name)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/install_doc/test/test_data_object_simple.py	Wed Nov 24 19:37:52 2010 +0000
@@ -0,0 +1,153 @@
+#!/usr/bin/python
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+'''Tests to validate SimpleXmlHandlerBase functionality'''
+
+import unittest
+
+from lxml import etree
+
+from solaris_install.data_object import \
+    ParsingError
+from solaris_install.data_object.simple import \
+    SimpleXmlHandlerBase
+
+from simple_data_object import SimpleDataObject
+
+
+class SimpleXmlHandlerTag(SimpleXmlHandlerBase):
+    '''Define class where we override TAG_NAME'''
+    TAG_NAME = "simple_tag"
+
+
+class SimpleXmlHandlerBadTag(SimpleXmlHandlerBase):
+    '''Define class where we override TAG_NAME with a bad tag value'''
+    TAG_NAME = "bad tag"
+
+
+class  TestSimpleXmlHandlerBase(unittest.TestCase):
+    '''Tests to validate SimpleXmlHandlerBase functionality'''
+
+    def setUp(self):
+        self.simple_tag_no_name = SimpleXmlHandlerTag()
+        self.simple_tag_with_name = SimpleXmlHandlerTag('My Name')
+
+    def tearDown(self):
+        self.simple_tag_no_name = None
+        self.simple_tag_with_name = None
+
+    def test_data_object_simple_fail_not_subclass(self):
+        '''Validate that direct instantaion of SimpleXmlHandlerBase will fail.
+        '''
+        self.assertRaises(ValueError, SimpleXmlHandlerBase)
+
+    def test_data_object_simple_xml_valid_tag_no_name(self):
+        '''Validate that XML is generated using a valid TAG_NAME and no name'''
+        # Set expected xml, and compensate for indent
+        expected_xml = '<simple_tag/>\n'
+
+        xml_str = self.simple_tag_no_name.get_xml_tree_str()
+        self.assertEqual(xml_str, expected_xml, "EXPECTED:\n%s\nGOT:\n%s" %\
+            (expected_xml, xml_str))
+
+    def test_data_object_simple_xml_valid_tag_with_name(self):
+        '''Validate that XML is generated using a valid TAG_NAME and name'''
+        # Set expected xml, and compensate for indent
+        expected_xml = '<simple_tag name="My Name"/>\n'
+
+        xml_str = self.simple_tag_with_name.get_xml_tree_str()
+        self.assertEqual(xml_str, expected_xml, "EXPECTED:\n%s\nGOT:\n%s" %\
+            (expected_xml, xml_str))
+
+    def test_data_object_simple_fail_invalid_tag(self):
+        '''Validate that XML generation fails using an invalid TAG_NAME'''
+        try:
+            data_obj = SimpleXmlHandlerBadTag()
+            data_obj.to_xml()
+            self.fail("Unexpected success creating obj with a bad tag name")
+        except ValueError:
+            pass
+
+    def test_data_object_simple_fail_can_handle_invalid_tag(self):
+        '''Validate that can_handle fails using an invalid tag name'''
+        TEST_XML = '<bad_tag/>'
+
+        # Parse the XML into an XML tree.
+        xml_tree = etree.fromstring(TEST_XML)
+
+        self.assertFalse(SimpleXmlHandlerBase.can_handle(xml_tree),
+            "can_handle returned True when given a bad tag: %s" % (TEST_XML))
+
+    def test_data_object_simple_fail_from_xml_invalid_tag(self):
+        '''Validate that from_xml() fails using an invalid XML tag'''
+        TEST_XML = '<bad_tag/>'
+
+        # Parse the XML into an XML tree.
+        xml_tree = etree.fromstring(TEST_XML)
+
+        # can_handle tested seperately, just ensure from_xml will fail too.
+        self.assertRaises(ParsingError,
+            SimpleXmlHandlerTag.from_xml, xml_tree)
+
+    def test_data_object_simple_import_xml_default(self):
+        '''Validate that from_xml() correctly imports XML'''
+        TEST_XML = '<simple_tag/>'
+
+        # Parse the XML into an XML tree.
+        xml_tree = etree.fromstring(TEST_XML)
+
+        if SimpleXmlHandlerTag.can_handle(xml_tree):
+            new_obj = SimpleXmlHandlerTag.from_xml(xml_tree)
+            self.assertTrue(new_obj is not None,
+                "Failed to create SimpleXmlHandlerTag from XML")
+            self.assertEquals(new_obj.name, SimpleXmlHandlerTag.TAG_NAME,
+                "Created SimpleXmlHandlerTag has wrong name.")
+        else:
+            self.fail("can_handle returned False, expected True!")
+
+    def test_data_object_simple_import_xml_with_name(self):
+        '''Validate that from_xml() correctly imports XML'''
+        TEST_XML = '<simple_tag name="My Name"/>'
+
+        # Parse the XML into an XML tree.
+        xml_tree = etree.fromstring(TEST_XML)
+
+        if SimpleXmlHandlerTag.can_handle(xml_tree):
+            new_obj = SimpleXmlHandlerTag.from_xml(xml_tree)
+            self.assertTrue(new_obj is not None,
+                "Failed to create SimpleXmlHandlerTag from XML")
+            self.assertEquals(new_obj.name, "My Name",
+                "Created SimpleXmlHandlerTag has wrong name.")
+        else:
+            self.fail("can_handle returned False, expected True!")
+
+    def test_data_object_simple_can_insert_to_doc(self):
+        '''Validate SimpleXmlHandlerBase can be inserted as child of DataObject
+        '''
+        data_obj = SimpleDataObject("test_obj")
+        data_obj.insert_children(SimpleXmlHandlerTag("test"))
+
+if __name__ == '__main__':
+    unittest.main()
--- a/usr/src/pkg/manifests/system-library-install.mf	Wed Nov 24 10:20:59 2010 -0800
+++ b/usr/src/pkg/manifests/system-library-install.mf	Wed Nov 24 19:37:52 2010 +0000
@@ -60,6 +60,8 @@
 file path=usr/lib/python2.6/vendor-packages/solaris_install/data_object/cache.pyc
 file path=usr/lib/python2.6/vendor-packages/solaris_install/data_object/data_dict.py
 file path=usr/lib/python2.6/vendor-packages/solaris_install/data_object/data_dict.pyc
+file path=usr/lib/python2.6/vendor-packages/solaris_install/data_object/simple.py
+file path=usr/lib/python2.6/vendor-packages/solaris_install/data_object/simple.pyc
 file path=usr/lib/python2.6/vendor-packages/solaris_install/engine/__init__.py
 file path=usr/lib/python2.6/vendor-packages/solaris_install/engine/__init__.pyc
 file path=usr/lib/python2.6/vendor-packages/solaris_install/engine/checkpoint.py