categories: add xml import/export (#4739)
This commit is contained in:
parent
3be51c00d2
commit
9cbdb2da56
|
@ -0,0 +1,89 @@
|
|||
import shutil
|
||||
import tempfile
|
||||
from cStringIO import StringIO
|
||||
|
||||
from quixote import cleanup
|
||||
from wcs import publisher
|
||||
|
||||
from wcs.categories import Category
|
||||
|
||||
def setup_module(module):
|
||||
cleanup()
|
||||
|
||||
global pub
|
||||
|
||||
publisher.WcsPublisher.APP_DIR = tempfile.mkdtemp()
|
||||
pub = publisher.WcsPublisher.create_publisher()
|
||||
|
||||
|
||||
def teardown_module(module):
|
||||
shutil.rmtree(pub.APP_DIR)
|
||||
|
||||
|
||||
def test_store():
|
||||
Category.wipe()
|
||||
test = Category()
|
||||
test.id = 1
|
||||
test.name = 'Test'
|
||||
test.description = 'Hello world'
|
||||
test.store()
|
||||
test2 = Category.get(1)
|
||||
assert test.id == test2.id
|
||||
assert test.name == test2.name
|
||||
assert test.description == test2.description
|
||||
|
||||
|
||||
def test_urlname():
|
||||
Category.wipe()
|
||||
test = Category()
|
||||
test.id = 1
|
||||
test.name = 'Test'
|
||||
test.description = 'Hello world'
|
||||
test.store()
|
||||
test = Category.get(1)
|
||||
assert test.url_name == 'test'
|
||||
|
||||
|
||||
def test_sort_positions():
|
||||
Category.wipe()
|
||||
|
||||
categories = []
|
||||
for i in range(10):
|
||||
test = Category()
|
||||
test.id = i+1
|
||||
test.name = 'Test %s' % i
|
||||
test.position = 10-i
|
||||
categories.append(test)
|
||||
|
||||
Category.sort_by_position(categories)
|
||||
assert categories[0].name == 'Test 9'
|
||||
|
||||
|
||||
def test_xml_export():
|
||||
Category.wipe()
|
||||
test = Category()
|
||||
test.id = 1
|
||||
test.name = 'Test'
|
||||
test.description = 'Hello world'
|
||||
test.store()
|
||||
test = Category.get(1)
|
||||
|
||||
assert '<name>Test</name>' in test.export_to_xml_string(include_id=True)
|
||||
assert ' id="1"' in test.export_to_xml_string(include_id=True)
|
||||
assert ' id="1"' not in test.export_to_xml_string(include_id=False)
|
||||
|
||||
|
||||
def test_xml_import():
|
||||
Category.wipe()
|
||||
test = Category()
|
||||
test.id = 1
|
||||
test.name = 'Test'
|
||||
test.description = 'Hello world'
|
||||
test.store()
|
||||
test = Category.get(1)
|
||||
|
||||
fd = StringIO(test.export_to_xml_string(include_id=True))
|
||||
test2 = Category.import_from_xml(fd, include_id=True)
|
||||
assert test.id == test2.id
|
||||
assert test.name == test2.name
|
||||
assert test.description == test2.description
|
|
@ -14,11 +14,13 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from quixote import get_publisher, get_response
|
||||
from quixote.html import TemplateIO, htmltext
|
||||
|
||||
from qommon.storage import StorableObject
|
||||
from qommon.misc import simplify, is_user_admin
|
||||
from qommon.misc import simplify, is_user_admin, indent_xml
|
||||
from qommon.substitution import Substitutions
|
||||
|
||||
class Category(StorableObject):
|
||||
|
@ -28,6 +30,10 @@ class Category(StorableObject):
|
|||
description = None
|
||||
position = None
|
||||
|
||||
# declarations for serialization
|
||||
TEXT_ATTRIBUTES = ['name', 'url_name', 'description']
|
||||
INT_ATTRIBUTES = ['position']
|
||||
|
||||
def __init__(self, name = None):
|
||||
StorableObject.__init__(self)
|
||||
self.name = name
|
||||
|
@ -75,6 +81,61 @@ class Category(StorableObject):
|
|||
form.store()
|
||||
StorableObject.remove_self(self)
|
||||
|
||||
def export_to_xml(self, include_id=False):
|
||||
charset = get_publisher().site_charset
|
||||
root = ET.Element('category')
|
||||
if include_id and self.id:
|
||||
root.attrib['id'] = str(self.id)
|
||||
for text_attribute in list(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 int_attribute in list(self.INT_ATTRIBUTES):
|
||||
if not hasattr(self, int_attribute) or not getattr(self, int_attribute):
|
||||
continue
|
||||
ET.SubElement(root, int_attribute).text = str(getattr(self, int_attribute))
|
||||
return root
|
||||
|
||||
def export_to_xml_string(self, include_id=False):
|
||||
x = self.export_to_xml(include_id=include_id)
|
||||
indent_xml(x)
|
||||
return ET.tostring(x)
|
||||
|
||||
def import_from_xml(cls, fd, charset=None, include_id=False):
|
||||
try:
|
||||
tree = ET.parse(fd)
|
||||
except:
|
||||
raise ValueError()
|
||||
return cls.import_from_xml_tree(tree, charset=charset,
|
||||
include_id=include_id)
|
||||
import_from_xml = classmethod(import_from_xml)
|
||||
|
||||
def import_from_xml_tree(cls, tree, include_id=False, charset=None):
|
||||
if charset is None:
|
||||
charset = get_publisher().site_charset
|
||||
category = cls()
|
||||
|
||||
# if the tree we get is actually a ElementTree for real, we get its
|
||||
# root element and go on happily.
|
||||
if not ET.iselement(tree):
|
||||
tree = tree.getroot()
|
||||
|
||||
if include_id and tree.attrib.get('id'):
|
||||
category.id = int(tree.attrib.get('id'))
|
||||
for text_attribute in list(cls.TEXT_ATTRIBUTES):
|
||||
value = tree.find(text_attribute)
|
||||
if value is None:
|
||||
continue
|
||||
setattr(category, text_attribute, value.text.encode(charset))
|
||||
for int_attribute in list(cls.INT_ATTRIBUTES):
|
||||
value = tree.find(int_attribute)
|
||||
if value is None:
|
||||
continue
|
||||
setattr(category, int_attribute, int(value.text))
|
||||
return category
|
||||
import_from_xml_tree = classmethod(import_from_xml_tree)
|
||||
|
||||
def get_substitution_variables(self, minimal=False):
|
||||
d = {
|
||||
'category_name': self.name,
|
||||
|
|
Loading…
Reference in New Issue