From a95f7811ce09041ef6f46ea4e11521442fb4d6d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= Date: Fri, 25 Apr 2014 12:57:16 +0200 Subject: [PATCH] formdefs: add more attributes to the XML export, and tests --- tests/test_formdef_import.py | 96 ++++++++++++++++++++++++++++++++++++++++ wcs/formdef.py | 101 ++++++++++++++++++++++++++++++++----------- 2 files changed, 172 insertions(+), 25 deletions(-) create mode 100644 tests/test_formdef_import.py diff --git a/tests/test_formdef_import.py b/tests/test_formdef_import.py new file mode 100644 index 0000000..e476901 --- /dev/null +++ b/tests/test_formdef_import.py @@ -0,0 +1,96 @@ +import sys +import shutil +import StringIO +import tempfile + +from quixote import cleanup +from wcs import publisher + +from wcs.formdef import FormDef, fields +from wcs.admin.forms import ET, indent + + +def setup_module(module): + cleanup() + + global pub, req + + publisher.WcsPublisher.APP_DIR = tempfile.mkdtemp() + pub = publisher.WcsPublisher.create_publisher() + + +def teardown_module(module): + shutil.rmtree(pub.APP_DIR) + +def assert_import_export_works(formdef, include_id=False): + formdef2 = FormDef.import_from_xml_tree( + formdef.export_to_xml(include_id=include_id), include_id=include_id) + assert ET.tostring(indent(formdef.export_to_xml(include_id=include_id)) + ) == ET.tostring(indent(formdef2.export_to_xml(include_id=include_id))) + return formdef2 + +def test_empty(): + formdef = FormDef() + formdef.name = 'empty' + assert_import_export_works(formdef) + +def test_text_attributes(): + formdef = FormDef() + formdef.name = 'Foo' + formdef.url_name = 'foo' + f2 = assert_import_export_works(formdef) + assert f2.url_name == formdef.url_name + +def test_boolean_attributes(): + formdef = FormDef() + formdef.name = 'Foo' + formdef.url_name = 'foo' + formdef.confirmation = True + formdef.allow_drafts = True + f2 = assert_import_export_works(formdef) + assert f2.allow_drafts == formdef.allow_drafts + assert f2.confirmation == formdef.confirmation + +def test_a_field(): + formdef = FormDef() + formdef.name = 'Foo' + formdef.fields = [ + fields.StringField(type='string', id=1, label='Bar', size=40) + ] + f2 = assert_import_export_works(formdef) + assert len(f2.fields) == len(formdef.fields) + +def test_more_fields(): + formdef = FormDef() + formdef.name = 'Blah' + formdef.fields = [ + fields.TextField(type='text', label='Bar', pre=True), + fields.EmailField(type='email', label='Bar'), + fields.BoolField(type='bool', label='Bar'), + fields.DateField(type='date', label='Bar', minimum_date='2014-01-01'), + fields.ItemField(type='item', label='Bar', items=['foo', 'bar', 'baz']), + ] + f2 = assert_import_export_works(formdef) + assert len(f2.fields) == len(formdef.fields) + assert f2.fields[2].type == formdef.fields[2].type + assert f2.fields[3].minimum_date == formdef.fields[3].minimum_date + assert f2.fields[4].items == formdef.fields[4].items + +def test_include_id(): + formdef = FormDef() + formdef.name = 'Blah' + formdef.fields = [ + fields.TextField(type='text', label='Bar', pre=True), + fields.EmailField(type='email', label='Bar'), + fields.BoolField(type='bool', label='Bar'), + fields.DateField(type='date', label='Bar', minimum_date='2014-01-01'), + fields.ItemField(type='item', label='Bar', items=['foo', 'bar', 'baz']), + ] + for field in formdef.fields: + field.id = formdef.get_new_field_id() + formdef.fields[4].id = '10' + f2 = assert_import_export_works(formdef, include_id=True) + assert len(f2.fields) == len(formdef.fields) + assert f2.fields[0].id == formdef.fields[0].id + assert f2.fields[4].id == formdef.fields[4].id + diff --git a/wcs/formdef.py b/wcs/formdef.py index cfb7c8d..fca542f 100644 --- a/wcs/formdef.py +++ b/wcs/formdef.py @@ -93,6 +93,14 @@ class FormDef(StorableObject): max_field_id = None + + # declarations for serialization + TEXT_ATTRIBUTES = ('name', 'url_name', 'signing', + 'publication_date', 'expiration_date') + BOOLEAN_ATTRIBUTES = ('discussion', 'detailed_emails', 'disabled', + 'only_allow_one', 'allow_drafts', 'disabled_redirection', + 'always_advertise', 'private_status_and_history') + def migrate(self): changed = False @@ -398,8 +406,7 @@ class FormDef(StorableObject): root['name'] = unicode(self.name, charset) if self.category: root['category'] = unicode(self.category.name, charset) - for boolean_attribute in ('only_allow_one', 'allow_drafts', 'discussion', - 'confirmation', 'signing'): + for boolean_attribute in self.BOOLEAN_ATTRIBUTES: value = getattr(self, boolean_attribute) if value: value = 'true' @@ -415,25 +422,44 @@ class FormDef(StorableObject): def export_to_xml(self, include_id=False): charset = get_publisher().site_charset root = ET.Element('formdef') - ET.SubElement(root, 'name').text = unicode(self.name, charset) - if self.url_name: - ET.SubElement(root, 'url_name').text = unicode(self.url_name, charset) - if self.category: - ET.SubElement(root, 'category').text = unicode(self.category.name, charset) - for boolean_attribute in ('only_allow_one', 'allow_drafts', 'discussion', - 'confirmation', 'signing'): + for text_attribute in self.TEXT_ATTRIBUTES: + if not hasattr(self, text_attribute) or not getattr(self, text_attribute): + continue + ET.SubElement(root, text_attribute).text = unicode( + getattr(self, text_attribute), charset) + for boolean_attribute in self.BOOLEAN_ATTRIBUTES: + if not hasattr(self, boolean_attribute): + continue value = getattr(self, boolean_attribute) if value: value = 'true' else: value = 'false' ET.SubElement(root, boolean_attribute).text = value + + if self.category: + elem = ET.SubElement(root, 'category') + elem.text = unicode(self.category.name, charset) + if include_id: + elem.attrib['category_id'] = str(self.category.id) + + if self.workflow: + elem = ET.SubElement(root, 'workflow') + elem.text = unicode(self.workflow.name, charset) + if include_id: + elem.attrib['workflow_id'] = str(self.workflow.id) + if self.max_field_id: ET.SubElement(root, 'max_field_id').text = str(self.max_field_id) - only_allow_one = False - allow_drafts = False + + if self.last_modification_time: + elem = ET.SubElement(root, 'last_modification') + elem.text = time.strftime('%Y-%m-%d %H:%M:%S', self.last_modification_time) + if include_id: + elem.attrib['user_id'] = str(self.last_modification_user_id) + fields = ET.SubElement(root, 'fields') - for field in self.fields: + for field in self.fields or []: fields.append(field.export_to_xml(charset=charset, include_id=include_id)) return root @@ -453,7 +479,18 @@ class FormDef(StorableObject): if tree.find('name') is None or not tree.find('name').text: raise ValueError() - formdef.name = tree.find('name').text.encode(charset) + for text_attribute in cls.TEXT_ATTRIBUTES: + value = tree.find(text_attribute) + if value is None: + continue + setattr(formdef, text_attribute, value.text.encode(charset)) + + for boolean_attribute in cls.BOOLEAN_ATTRIBUTES: + value = tree.find(boolean_attribute) + if value is None: + continue + setattr(formdef, boolean_attribute, value.text == 'true') + formdef.fields = [] for i, field in enumerate(tree.find('fields')): try: @@ -473,20 +510,34 @@ class FormDef(StorableObject): else: formdef.max_field_id = max([lax_int(x.id) for x in formdef.fields])+1 + if tree.find('last_modification') is not None: + node = tree.find('last_modification') + self.last_modification_time = time.strptime(node.text, '%Y-%m-%d %H:%M:%S') + if include_id and elem.attrib.get('user_id'): + self.last_modification_user_id = elem.attrib.get('user_id') + if tree.find('category') is not None: - category = tree.find('category').text.encode(charset) - cats = Category.select() - for c in cats: - if c.name == category: - formdef.category_id = c.id - break + category_node = tree.find('category') + if include_id and category_node.attrib.get('category_id'): + formdef.category_id = int(category_node.attrib.get('category_id')) + else: + category = category_node.text.encode(charset) + cats = Category.select() + for c in Category.select(): + if c.name == category: + formdef.category_id = c.id + break - for boolean_attribute in ('only_allow_one', 'allow_drafts', 'discussion', - 'confirmation', 'signing'): - value = tree.find(boolean_attribute) - if value is None: - continue - setattr(formdef, boolean_attribute, value.text == 'true') + if tree.find('workflow') is not None: + workflow_node = tree.find('workflow') + if include_id and workflow_node.attrib.get('workflow_id'): + formdef.workflow_id = workflow_node.attrib.get('workflow_id') + else: + workflow = workflow_node.text.encode(charset) + for w in Workflow.select(): + if c.name == workflow: + formdef.workflow_id = c.id + break return formdef import_from_xml_tree = classmethod(import_from_xml_tree) -- 2.0.0.rc0