Projet

Général

Profil

0001-add-possibility-to-create-a-formdef-object-from-a-js.patch

Frédéric Péters, 29 août 2014 17:31

Télécharger (12,7 ko)

Voir les différences:

Subject: [PATCH] add possibility to create a formdef object from a json value
 (#5348)

 tests/test_formdef_import.py |  54 ++++++++++++++++----
 wcs/fields.py                |  27 ++++------
 wcs/formdef.py               | 117 ++++++++++++++++++++++++++++++++++++-------
 3 files changed, 153 insertions(+), 45 deletions(-)
tests/test_formdef_import.py
22 22
def teardown_module(module):
23 23
    shutil.rmtree(pub.APP_DIR)
24 24

  
25
def assert_import_export_works(formdef, include_id=False):
25
def export_to_indented_xml(formdef, include_id=False):
26
    formdef_xml = formdef.export_to_xml(include_id=include_id)
27
    indent(formdef_xml)
28
    return formdef_xml
29

  
30
def assert_compare_formdef(formdef1, formdef2, include_id=False):
31
    assert ET.tostring(export_to_indented_xml(formdef1, include_id=include_id)) == \
32
            ET.tostring(export_to_indented_xml(formdef2, include_id=include_id))
33
    assert formdef1.export_to_json(include_id=include_id, indent=2) == \
34
            formdef2.export_to_json(include_id=include_id, indent=2)
35

  
36
def assert_xml_import_export_works(formdef, include_id=False):
26 37
    formdef2 = FormDef.import_from_xml_tree(
27 38
            formdef.export_to_xml(include_id=include_id), include_id=include_id)
28
    assert ET.tostring(indent(formdef.export_to_xml(include_id=include_id))
29
            ) == ET.tostring(indent(formdef2.export_to_xml(include_id=include_id)))
39
    assert_compare_formdef(formdef, formdef2, include_id=include_id)
40
    return formdef2
41

  
42
def assert_json_import_export_works(formdef, include_id=False):
43
    formdef2 = FormDef.import_from_json(
44
            StringIO.StringIO(formdef.export_to_json(include_id=include_id)), include_id=include_id)
45
    assert_compare_formdef(formdef, formdef2, include_id=include_id)
30 46
    return formdef2
31 47

  
32 48
def test_empty():
33 49
    formdef = FormDef()
34 50
    formdef.name = 'empty'
35
    assert_import_export_works(formdef)
51
    assert_xml_import_export_works(formdef)
52
    assert_json_import_export_works(formdef)
36 53

  
37 54
def test_text_attributes():
38 55
    formdef = FormDef()
39 56
    formdef.name = 'Foo'
40 57
    formdef.url_name = 'foo'
41
    f2 = assert_import_export_works(formdef)
58
    f2 = assert_xml_import_export_works(formdef)
59
    assert f2.url_name == formdef.url_name
60
    f2 = assert_json_import_export_works(formdef)
42 61
    assert f2.url_name == formdef.url_name
43 62

  
44 63
def test_boolean_attributes():
......
47 66
    formdef.url_name = 'foo'
48 67
    formdef.confirmation = True
49 68
    formdef.allow_drafts = True
50
    f2 = assert_import_export_works(formdef)
69
    f2 = assert_xml_import_export_works(formdef)
70
    assert f2.allow_drafts == formdef.allow_drafts
71
    assert f2.confirmation == formdef.confirmation
72
    f2 = assert_json_import_export_works(formdef)
51 73
    assert f2.allow_drafts == formdef.allow_drafts
52 74
    assert f2.confirmation == formdef.confirmation
53 75

  
......
55 77
    formdef = FormDef()
56 78
    formdef.name = 'Foo'
57 79
    formdef.fields = [
58
            fields.StringField(type='string', id=1, label='Bar', size=40)
80
            fields.StringField(type='string', id=1, label='Bar', size='40')
59 81
            ]
60
    f2 = assert_import_export_works(formdef)
82
    f2 = assert_xml_import_export_works(formdef)
83
    assert len(f2.fields) == len(formdef.fields)
84
    f2 = assert_json_import_export_works(formdef)
61 85
    assert len(f2.fields) == len(formdef.fields)
62 86

  
63 87
def test_more_fields():
......
70 94
            fields.DateField(type='date', label='Bar', minimum_date='2014-01-01'),
71 95
            fields.ItemField(type='item', label='Bar', items=['foo', 'bar', 'baz']),
72 96
            ]
73
    f2 = assert_import_export_works(formdef)
97
    f2 = assert_xml_import_export_works(formdef)
98
    assert len(f2.fields) == len(formdef.fields)
99
    assert f2.fields[2].type == formdef.fields[2].type
100
    assert f2.fields[3].minimum_date == formdef.fields[3].minimum_date
101
    assert f2.fields[4].items == formdef.fields[4].items
102

  
103
    f2 = assert_json_import_export_works(formdef)
74 104
    assert len(f2.fields) == len(formdef.fields)
75 105
    assert f2.fields[2].type == formdef.fields[2].type
76 106
    assert f2.fields[3].minimum_date == formdef.fields[3].minimum_date
......
89 119
    for field in formdef.fields:
90 120
        field.id = formdef.get_new_field_id()
91 121
    formdef.fields[4].id = '10'
92
    f2 = assert_import_export_works(formdef, include_id=True)
122
    f2 = assert_xml_import_export_works(formdef, include_id=True)
93 123
    assert len(f2.fields) == len(formdef.fields)
94 124
    assert f2.fields[0].id == formdef.fields[0].id
95 125
    assert f2.fields[4].id == formdef.fields[4].id
96 126

  
127
    f2 = assert_json_import_export_works(formdef, include_id=True)
128
    assert len(f2.fields) == len(formdef.fields)
129
    assert f2.fields[0].id == formdef.fields[0].id
130
    assert f2.fields[4].id == formdef.fields[4].id
wcs/fields.py
125 125
    def get_admin_attributes(self):
126 126
        return ['label', 'type']
127 127

  
128
    def export_to_json(self, charset, include_id=False):
128
    def export_to_json(self, include_id=False):
129 129
        field = {}
130 130
        if include_id:
131 131
            extra_fields = ['id']
......
136 136
                continue
137 137
            if hasattr(self, attribute) and getattr(self, attribute) is not None:
138 138
                val = getattr(self, attribute)
139
                if type(val) is dict:
140
                    if not val: continue
141
                    field[attribute] = {}
142
                    for k, v in val.items():
143
                        field[attribute][k] = unicode(v, charset, 'replace')
144
                elif type(val) is list:
145
                    if not val: continue
146
                    field[attribute] = []
147
                    for v in val:
148
                        field[attribute].append(unicode(v, charset, 'replace'))
149
                elif type(val) in (str, unicode):
150
                    if type(val) is unicode:
151
                        field[attribute] = val
152
                    else:
153
                        field[attribute] = unicode(val, charset, 'replace')
154
                else:
155
                    field[attribute] = str(val)
139
                field[attribute] = val
156 140
        return field
157 141

  
142
    def init_with_json(self, elem, include_id=False):
143
        if include_id:
144
            self.id = elem.get('id')
145
        for attribute in self.get_admin_attributes():
146
            if attribute in elem:
147
                setattr(self, attribute, elem.get(attribute))
148

  
158 149
    def export_to_xml(self, charset, include_id=False):
159 150
        field = ET.Element('field')
160 151
        if include_id:
wcs/formdef.py
80 80

  
81 81
    max_field_id = None
82 82

  
83

  
84 83
    # declarations for serialization
85
    TEXT_ATTRIBUTES = ('name', 'url_name',
86
            'publication_date', 'expiration_date')
87
    BOOLEAN_ATTRIBUTES = ('discussion', 'detailed_emails', 'disabled',
88
            'only_allow_one', 'allow_drafts', 'disabled_redirection',
89
            'always_advertise', 'private_status_and_history')
84
    TEXT_ATTRIBUTES = ['name', 'url_name',
85
            'publication_date', 'expiration_date',
86
            'disabled_redirection',]
87
    BOOLEAN_ATTRIBUTES = ['discussion', 'detailed_emails', 'disabled',
88
            'only_allow_one', 'allow_drafts',
89
            'always_advertise', 'private_status_and_history']
90 90

  
91 91
    def migrate(self):
92 92
        changed = False
......
386 386

  
387 387
        return d
388 388

  
389
    def export_to_json(self, include_id=False):
389
    def export_to_json(self, include_id=False, indent=None):
390 390
        charset = get_publisher().site_charset
391 391
        root = {}
392 392
        root['name'] = unicode(self.name, charset)
393
        if include_id and self.id:
394
            root['id'] = str(self.id)
393 395
        if self.category:
394 396
            root['category'] = unicode(self.category.name, charset)
395
        for boolean_attribute in self.BOOLEAN_ATTRIBUTES:
396
            value = getattr(self, boolean_attribute)
397
            if value:
398
                value = 'true'
399
            else:
400
                value = 'false'
401
            root[boolean_attribute] = value
397
            root['category_id'] = str(self.category.id)
398
        if self.workflow:
399
            root['workflow'] = unicode(self.workflow.name, charset)
400
            root['workflow_id'] = str(self.workflow.id)
401

  
402
        if self.max_field_id is None and self.fields:
403
            self.max_field_id = max([lax_int(x.id) for x in self.fields])
404

  
405
        more_attributes = []
406
        if self.max_field_id:
407
            more_attributes.append('max_field_id')
408
        if self.last_modification_time:
409
            more_attributes.append('last_modification_time')
410
            if include_id:
411
                more_attributes.append('last_modification_user_id')
412

  
413
        for attribute in self.TEXT_ATTRIBUTES + self.BOOLEAN_ATTRIBUTES + more_attributes:
414
            if not hasattr(self, attribute):
415
                continue
416
            root[attribute] = getattr(self, attribute)
417

  
402 418
        root['fields'] = []
403
        for field in self.fields:
404
            root['fields'].append(field.export_to_json(charset=charset, include_id=include_id))
419
        if self.fields:
420
            for field in self.fields:
421
                root['fields'].append(field.export_to_json(include_id=include_id))
422

  
423
        return json.dumps(root, indent=indent)
424

  
425
    def import_from_json(cls, fd, charset=None, include_id=False):
426
        if charset is None:
427
            charset = get_publisher().site_charset
428
        formdef = cls()
429

  
430
        def unicode2str(v):
431
            if isinstance(v, dict):
432
                return dict([(unicode2str(k), unicode2str(v)) for k, v in v.items()])
433
            elif isinstance(v, list):
434
                return [unicode2str(x) for x in v]
435
            elif isinstance(v, unicode):
436
                return v.encode(charset)
437
            else:
438
                return v
439

  
440
        # we have to make sure all strings are str object, not unicode.
441
        value = unicode2str(json.load(fd))
442

  
443
        if include_id and 'id' in value:
444
            formdef.id = value.get('id')
445

  
446
        if include_id and 'category_id' in value:
447
            formdef.category_id = value.get('category_id')
448
        elif 'category' in value:
449
            category = value.get('category')
450
            for c in Category.select():
451
                if c.name == category:
452
                    formdef.category_id = c.id
453
                    break
454

  
455
        if include_id and 'workflow_id' in value:
456
            formdef.workflow_id = value.get('workflow_id')
457
        elif 'workflow' in value:
458
            workflow = value.get('workflow')
459
            for w in Workflow.select():
460
                if w.name == workflow:
461
                    formdef.workflow_id = w.id
462
                    break
463

  
464
        more_attributes = ['max_field_id', 'last_modification_time',
465
                'last_modification_user_id']
466
        for attribute in cls.TEXT_ATTRIBUTES + cls.BOOLEAN_ATTRIBUTES + more_attributes:
467
            if attribute in value:
468
                setattr(formdef, attribute, value.get(attribute))
469

  
470
        formdef.fields = []
471
        for i, field in enumerate(value.get('fields', [])):
472
            try:
473
                field_o = fields.get_field_class_by_type(field.get('type'))()
474
            except KeyError:
475
                raise ValueError()
476
            field_o.init_with_json(field, include_id=include_id)
477
            if not field_o.id:
478
                # this assumes all fields will have id, or none of them
479
                field_o.id = str(i)
480
            formdef.fields.append(field_o)
481

  
482
        if formdef.fields and not formdef.max_field_id:
483
            formdef.max_field_id = max([lax_int(x.id) for x in formdef.fields])+1
405 484

  
406
        return json.dumps(root)
485
        return formdef
486
    import_from_json = classmethod(import_from_json)
407 487

  
408 488
    def export_to_xml(self, include_id=False):
409 489
        charset = get_publisher().site_charset
......
437 517
            if include_id:
438 518
                elem.attrib['workflow_id'] = str(self.workflow.id)
439 519

  
520
        if self.max_field_id is None and self.fields:
521
            self.max_field_id = max([lax_int(x.id) for x in self.fields])
522

  
440 523
        if self.max_field_id:
441 524
            ET.SubElement(root, 'max_field_id').text = str(self.max_field_id)
442 525

  
443
-