0002-mdel-improve-code-style-36471.patch
passerelle/apps/mdel/mdel.py | ||
---|---|---|
1 |
# Passerelle - uniform access to data and services |
|
2 |
# Copyright (C) 2016 Entr'ouvert |
|
1 |
# coding: utf-8 |
|
2 |
# passerelle - uniform access to data and services- |
|
3 |
# Copyright (C) 2019 Entr'ouvert |
|
3 | 4 |
# |
4 | 5 |
# This program is free software: you can redistribute it and/or modify it |
5 | 6 |
# under the terms of the GNU Affero General Public License as published |
... | ... | |
14 | 15 |
# You should have received a copy of the GNU Affero General Public License |
15 | 16 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 | 17 | |
18 |
from __future__ import unicode_literals |
|
19 | ||
17 | 20 |
import os |
18 | 21 |
import base64 |
19 | 22 |
import datetime |
... | ... | |
51 | 54 | |
52 | 55 | |
53 | 56 |
class MDELBase(object): |
54 | ||
55 | 57 |
def to_string(self): |
56 | 58 |
raw_string = etree.tostring(self.xml, encoding='utf-8') |
57 | 59 |
parsed_string = minidom.parseString(raw_string) |
... | ... | |
247 | 249 | |
248 | 250 |
return data |
249 | 251 | |
252 |
@classmethod |
|
253 |
def path_to_xml(cls, path, value, parent): |
|
254 |
'''Resolve an XML `path` starting from `parent` and the target node content to `value`.''' |
|
255 | ||
256 |
if isinstance(path, list) and len(path) > 1: |
|
257 |
parent_child = parent.find(path[0]) |
|
258 |
if parent_child is not None: |
|
259 |
element = parent_child |
|
260 |
path.pop(0) |
|
261 |
else: |
|
262 |
element = ElementFactory(path.pop(0)) |
|
263 |
element.append(cls.path_to_xml(path, value, element), allow_new=False) |
|
264 |
else: |
|
265 |
element = ElementFactory(path[0], text=value) |
|
266 |
return element |
|
267 | ||
250 | 268 |
@property |
251 | 269 |
def xml(self): |
252 |
elements = []
|
|
270 |
'''Generate an XML document applying values from `self.data` to `self.mapping`'''
|
|
253 | 271 | |
272 |
# extract text content from data for each path in mapping |
|
273 |
elements = [] |
|
254 | 274 |
for key, path in self.mapping: |
255 | 275 |
if key in self.data: |
256 | 276 |
elements.append((path, self.data[key])) |
257 | 277 | |
278 |
# recursively create XML nodes using self.path_to_xml() |
|
258 | 279 |
root = ElementFactory(self.root_element, **self.root_attributes) |
259 | ||
260 | 280 |
for path, value in elements: |
261 | 281 |
path_splitted = path.split('_') |
262 |
root.append(json_to_xml(path_splitted, value, root), allow_new=False)
|
|
282 |
root.append(self.path_to_xml(path_splitted, value, root), allow_new=False)
|
|
263 | 283 | |
264 | 284 |
return root |
265 | 285 | |
286 | ||
266 | 287 |
class ILEData(Data): |
288 |
'''Démarche inscription sur les listes électorales''' |
|
267 | 289 | |
268 | 290 |
mapping = [ |
269 | 291 |
('nom_famille', 'Inscription_Electeur_Noms_NomFamille'), |
... | ... | |
359 | 381 | |
360 | 382 | |
361 | 383 |
class AECData(Data): |
384 |
'''Démarche acte d'état civil''' |
|
362 | 385 | |
363 | 386 |
mapping = [ |
364 | 387 |
('aec_type_raw', 'DemandeActe_TypeActe_Code'), |
... | ... | |
444 | 467 |
self.root_attributes = {'canal_utilise': '0'} |
445 | 468 | |
446 | 469 |
super(AECData, self).__init__(demand_id, data) |
447 | ||
448 | ||
449 |
def json_to_xml(path, value, parent): |
|
450 | ||
451 |
if isinstance(path, list) and len(path) > 1: |
|
452 |
parent_child = parent.find(path[0]) |
|
453 |
if parent_child is not None: |
|
454 |
element = parent_child |
|
455 |
path.pop(0) |
|
456 |
else: |
|
457 |
element = ElementFactory(path.pop(0)) |
|
458 | ||
459 |
element.append(json_to_xml(path, value, element), allow_new=False) |
|
460 |
else: |
|
461 |
element = ElementFactory(path[0], text=value) |
|
462 | ||
463 |
return element |
passerelle/apps/mdel/models.py | ||
---|---|---|
1 |
# -*- coding: utf-8 -*-
|
|
2 |
# Passerelle - uniform access to data and services
|
|
1 |
# coding: utf-8
|
|
2 |
# passerelle - uniform access to data and services
|
|
3 | 3 |
# Copyright (C) 2016 Entr'ouvert |
4 | 4 |
# |
5 | 5 |
# This program is free software: you can redistribute it and/or modify it |
... | ... | |
15 | 15 |
# You should have received a copy of the GNU Affero General Public License |
16 | 16 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | 17 | |
18 |
from __future__ import unicode_literals |
|
18 | 19 |
import os |
19 | 20 |
import json |
20 | 21 | |
21 | 22 |
from django.db import models |
22 | 23 |
from django.utils.translation import ugettext_lazy as _ |
24 |
from django.utils import six |
|
23 | 25 | |
24 | 26 |
from passerelle.base.models import BaseResource |
25 | 27 |
from passerelle.utils.api import endpoint |
... | ... | |
101 | 103 | |
102 | 104 |
demand_type = formdata.pop('demand_type', '').upper() |
103 | 105 |
if demand_type not in DEMAND_TYPES: |
104 |
raise APIError('demand_type must be : %r' % DEMAND_TYPES)
|
|
106 |
raise APIError('demand_type must be one of : %s' % ', '.join(DEMAND_TYPES))
|
|
105 | 107 | |
106 | 108 |
if 'display_id' not in formdata: |
107 | 109 |
raise APIError('display_id is required') |
... | ... | |
151 | 153 |
if item.get('id') not in without.split(',')]} |
152 | 154 | |
153 | 155 | |
156 |
@six.python_2_unicode_compatible |
|
154 | 157 |
class Demand(models.Model): |
155 | 158 |
created_at = models.DateTimeField(auto_now_add=True) |
156 | 159 |
updated_at = models.DateTimeField(auto_now=True) |
... | ... | |
162 | 165 |
step = models.IntegerField(default=0) |
163 | 166 |
demand_id = models.CharField(max_length=128, null=True) |
164 | 167 | |
165 |
def __unicode__(self):
|
|
168 |
def __str__(self):
|
|
166 | 169 |
return '%s - %s - %s' % (self.resource.slug, self.demand_id, self.status) |
167 | 170 | |
168 | 171 |
class Meta: |
... | ... | |
203 | 206 |
for proof_code, proof_attribute in proofs: |
204 | 207 | |
205 | 208 |
documents = [value for key, value in formdata.items() |
206 |
if key.startswith(proof_attribute) and isinstance(value, dict) and 'filename' in value and 'content' in value] |
|
209 |
if (key.startswith(proof_attribute) |
|
210 |
and isinstance(value, dict) |
|
211 |
and 'filename' in value |
|
212 |
and 'content' in value)] |
|
207 | 213 |
if not documents: |
208 | 214 |
raise APIError('%s and all its attributes are required' % proof_attribute) |
209 | 215 |
for document in documents: |
passerelle/apps/mdel/utils.py | ||
---|---|---|
1 |
# Passerelle - uniform access to data and services
|
|
1 |
# passerelle - uniform access to data and services
|
|
2 | 2 |
# Copyright (C) 2016 Entr'ouvert |
3 | 3 |
# |
4 | 4 |
# This program is free software: you can redistribute it and/or modify it |
... | ... | |
14 | 14 |
# You should have received a copy of the GNU Affero General Public License |
15 | 15 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 | 16 | |
17 |
from __future__ import unicode_literals |
|
18 | ||
17 | 19 |
import os |
18 | 20 |
import zipfile |
19 | 21 |
from xml.etree import ElementTree as etree |
... | ... | |
22 | 24 | |
23 | 25 |
from passerelle.utils.jsonresponse import APIError |
24 | 26 | |
27 | ||
25 | 28 |
def parse_date(date): |
26 | 29 |
try: |
27 | 30 |
parsed_date = django_parse_date(date) |
28 | 31 |
except ValueError as e: |
29 |
raise APIError('Invalid date: %r (%r)' % ( date, e))
|
|
32 |
raise APIError('invalid date: %s (%s)' % (date, e))
|
|
30 | 33 |
if not parsed_date: |
31 | 34 |
raise APIError('date %r not iso-formated' % date) |
32 | 35 |
return parsed_date.isoformat() |
33 | 36 | |
34 | 37 | |
35 | 38 |
class ElementFactory(etree.Element): |
36 | ||
37 | 39 |
def __init__(self, *args, **kwargs): |
38 | 40 |
self.text = kwargs.pop('text', None) |
39 | 41 |
namespace = kwargs.pop('namespace', None) |
... | ... | |
46 | 48 |
super(ElementFactory, self).__init__(*args, **kwargs) |
47 | 49 | |
48 | 50 |
def append(self, element, allow_new=True): |
49 | ||
50 | 51 |
if not allow_new: |
51 | 52 |
if isinstance(element.tag, etree.QName): |
52 | 53 |
found = self.find(element.tag.text) |
53 | 54 |
else: |
54 | 55 |
found = self.find(element.tag) |
55 | ||
56 | 56 |
if found is not None: |
57 | 57 |
return self |
58 | ||
59 | 58 |
super(ElementFactory, self).append(element) |
60 | 59 |
return self |
61 | 60 |
tests/test_mdel.py | ||
---|---|---|
109 | 109 |
ILE_PAYLOAD_INVALID = copy.deepcopy(ile_payload) |
110 | 110 |
ILE_PAYLOAD_INVALID['extra']['demand_type'] = 'whatever' |
111 | 111 |
resp = app.post_json('/mdel/test/create', params=ILE_PAYLOAD_INVALID, status=200) |
112 |
assert resp.json['err_desc'] == "demand_type must be : ['ILE-LA', 'RCO-LA', 'AEC-LA']"
|
|
112 |
assert resp.json['err_desc'] == "demand_type must be one of : ILE-LA, RCO-LA, AEC-LA"
|
|
113 | 113 | |
114 | 114 | |
115 | 115 |
def test_invalid_demand_no_form_number(app, ile_payload): |
116 |
- |