0001-add-possibility-to-create-a-formdef-object-from-a-js.patch
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 |
- |