Projet

Général

Profil

0002-categories-add-xml-import-export-4739.patch

Frédéric Péters, 25 novembre 2014 12:18

Télécharger (6,21 ko)

Voir les différences:

Subject: [PATCH 2/3] categories: add xml import/export (#4739)

 tests/test_categories.py | 89 ++++++++++++++++++++++++++++++++++++++++++++++++
 wcs/categories.py        | 63 +++++++++++++++++++++++++++++++++-
 2 files changed, 151 insertions(+), 1 deletion(-)
 create mode 100644 tests/test_categories.py
tests/test_categories.py
1
import shutil
2
import tempfile
3
from cStringIO import StringIO
4

  
5
from quixote import cleanup
6
from wcs import publisher
7

  
8
from wcs.categories import Category
9

  
10
def setup_module(module):
11
    cleanup()
12

  
13
    global pub
14

  
15
    publisher.WcsPublisher.APP_DIR = tempfile.mkdtemp()
16
    pub = publisher.WcsPublisher.create_publisher()
17

  
18

  
19
def teardown_module(module):
20
    shutil.rmtree(pub.APP_DIR)
21

  
22

  
23
def test_store():
24
    Category.wipe()
25
    test = Category()
26
    test.id = 1
27
    test.name = 'Test'
28
    test.description = 'Hello world'
29
    test.store()
30
    test2 = Category.get(1)
31
    assert test.id == test2.id
32
    assert test.name == test2.name
33
    assert test.description == test2.description
34

  
35

  
36
def test_urlname():
37
    Category.wipe()
38
    test = Category()
39
    test.id = 1
40
    test.name = 'Test'
41
    test.description = 'Hello world'
42
    test.store()
43
    test = Category.get(1)
44
    assert test.url_name == 'test'
45

  
46

  
47
def test_sort_positions():
48
    Category.wipe()
49

  
50
    categories = []
51
    for i in range(10):
52
        test = Category()
53
        test.id = i+1
54
        test.name = 'Test %s' % i
55
        test.position = 10-i
56
        categories.append(test)
57

  
58
    Category.sort_by_position(categories)
59
    assert categories[0].name == 'Test 9'
60

  
61

  
62
def test_xml_export():
63
    Category.wipe()
64
    test = Category()
65
    test.id = 1
66
    test.name = 'Test'
67
    test.description = 'Hello world'
68
    test.store()
69
    test = Category.get(1)
70

  
71
    assert '<name>Test</name>' in test.export_to_xml_string(include_id=True)
72
    assert ' id="1"' in test.export_to_xml_string(include_id=True)
73
    assert ' id="1"' not in test.export_to_xml_string(include_id=False)
74

  
75

  
76
def test_xml_import():
77
    Category.wipe()
78
    test = Category()
79
    test.id = 1
80
    test.name = 'Test'
81
    test.description = 'Hello world'
82
    test.store()
83
    test = Category.get(1)
84

  
85
    fd = StringIO(test.export_to_xml_string(include_id=True))
86
    test2 = Category.import_from_xml(fd, include_id=True)
87
    assert test.id == test2.id
88
    assert test.name == test2.name
89
    assert test.description == test2.description
wcs/categories.py
14 14
# You should have received a copy of the GNU General Public License
15 15
# along with this program; if not, see <http://www.gnu.org/licenses/>.
16 16

  
17
import xml.etree.ElementTree as ET
18

  
17 19
from quixote import get_publisher, get_response
18 20
from quixote.html import TemplateIO, htmltext
19 21

  
20 22
from qommon.storage import StorableObject
21
from qommon.misc import simplify, is_user_admin
23
from qommon.misc import simplify, is_user_admin, indent_xml
22 24
from qommon.substitution import Substitutions
23 25

  
24 26
class Category(StorableObject):
......
28 30
    description = None
29 31
    position = None
30 32

  
33
    # declarations for serialization
34
    TEXT_ATTRIBUTES = ['name', 'url_name', 'description']
35
    INT_ATTRIBUTES = ['position']
36

  
31 37
    def __init__(self, name = None):
32 38
        StorableObject.__init__(self)
33 39
        self.name = name
......
75 81
            form.store()
76 82
        StorableObject.remove_self(self)
77 83

  
84
    def export_to_xml(self, include_id=False):
85
        charset = get_publisher().site_charset
86
        root = ET.Element('category')
87
        if include_id and self.id:
88
            root.attrib['id'] = str(self.id)
89
        for text_attribute in list(self.TEXT_ATTRIBUTES):
90
            if not hasattr(self, text_attribute) or not getattr(self, text_attribute):
91
                continue
92
            ET.SubElement(root, text_attribute).text = unicode(
93
                    getattr(self, text_attribute), charset)
94
        for int_attribute in list(self.INT_ATTRIBUTES):
95
            if not hasattr(self, int_attribute) or not getattr(self, int_attribute):
96
                continue
97
            ET.SubElement(root, int_attribute).text = str(getattr(self, int_attribute))
98
        return root
99

  
100
    def export_to_xml_string(self, include_id=False):
101
        x = self.export_to_xml(include_id=include_id)
102
        indent_xml(x)
103
        return ET.tostring(x)
104

  
105
    def import_from_xml(cls, fd, charset=None, include_id=False):
106
        try:
107
            tree = ET.parse(fd)
108
        except:
109
            raise ValueError()
110
        return cls.import_from_xml_tree(tree, charset=charset,
111
                include_id=include_id)
112
    import_from_xml = classmethod(import_from_xml)
113

  
114
    def import_from_xml_tree(cls, tree, include_id=False, charset=None):
115
        if charset is None:
116
            charset = get_publisher().site_charset
117
        category = cls()
118

  
119
        # if the tree we get is actually a ElementTree for real, we get its
120
        # root element and go on happily.
121
        if not ET.iselement(tree):
122
            tree = tree.getroot()
123

  
124
        if include_id and tree.attrib.get('id'):
125
            category.id = int(tree.attrib.get('id'))
126
        for text_attribute in list(cls.TEXT_ATTRIBUTES):
127
            value = tree.find(text_attribute)
128
            if value is None:
129
                continue
130
            setattr(category, text_attribute, value.text.encode(charset))
131
        for int_attribute in list(cls.INT_ATTRIBUTES):
132
            value = tree.find(int_attribute)
133
            if value is None:
134
                continue
135
            setattr(category, int_attribute, int(value.text))
136
        return category
137
    import_from_xml_tree = classmethod(import_from_xml_tree)
138

  
78 139
    def get_substitution_variables(self, minimal=False):
79 140
        d = {
80 141
            'category_name': self.name,
81
-