Projet

Général

Profil

0001-toulouse_axel-bool-mapping-38464.patch

Lauréline Guérin, 13 décembre 2019 15:38

Télécharger (6,98 ko)

Voir les différences:

Subject: [PATCH] toulouse_axel: bool mapping (#38464)

 passerelle/contrib/toulouse_axel/models.py | 51 ++++++++++-
 tests/test_toulouse_axel_schema.py         | 98 ++++++++++++++++++++++
 2 files changed, 147 insertions(+), 2 deletions(-)
 create mode 100644 tests/test_toulouse_axel_schema.py
passerelle/contrib/toulouse_axel/models.py
43 43
class AxelSchema(JSONSchemaFromXMLSchema):
44 44
    type_map = {
45 45
        '{urn:AllAxelTypes}DATEREQUIREDType': 'date',
46
        '{urn:AllAxelTypes}DATEType': 'date',
46
        '{urn:AllAxelTypes}DATEType': 'date_optional',
47
        '{urn:AllAxelTypes}OUINONREQUIREDType': 'bool',
48
        '{urn:AllAxelTypes}OUINONType': 'bool_optional',
47 49
    }
48 50

  
49 51
    @classmethod
......
56 58
    def encode_date(self, obj):
57 59
        return datetime.datetime.strptime(obj, '%Y-%m-%d').strftime('%d/%m/%Y')
58 60

  
61
    def encode_date_optional(self, obj):
62
        return self.encode_date(obj)
63

  
59 64
    def decode_date(self, data):
65
        value = datetime.datetime.strptime(data.text, '%d/%m/%Y').strftime('%Y-%m-%d')
66
        return xmlschema.ElementData(tag=data.tag, text=value, content=data.content, attributes=data.attributes)
67

  
68
    def decode_date_optional(self, data):
60 69
        if not data.text:
61 70
            return data
62
        value = datetime.datetime.strptime(data.text, '%d/%m/%Y').strftime('%Y-%m-%d')
71
        return self.decode_date(data)
72

  
73
    @classmethod
74
    def schema_bool(cls):
75
        return {
76
            'oneOf': [
77
                {'type': 'boolean'},
78
                {
79
                    'type': 'string',
80
                    'pattern': '[Oo][Uu][Ii]|[Nn][Oo][Nn]|[Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee]|1|0',
81
                }
82
            ]
83
        }
84

  
85
    def encode_bool(self, obj):
86
        if obj is True or str(obj).lower() in ['true', 'oui', '1']:
87
            return 'OUI'
88
        if obj is False or str(obj).lower() in ['false', 'non', '0']:
89
            return 'NON'
90
        return obj
91

  
92
    def decode_bool(self, data):
93
        value = False
94
        if data.text.lower() == 'oui':
95
            value = True
63 96
        return xmlschema.ElementData(tag=data.tag, text=value, content=data.content, attributes=data.attributes)
64 97

  
98
    @classmethod
99
    def schema_bool_optional(cls):
100
        schema_bool_optional = cls.schema_bool()
101
        schema_bool_optional['oneOf'].append({'type': 'string', 'enum': ['']})
102
        return schema_bool_optional
103

  
104
    def encode_bool_optional(self, obj):
105
        return self.encode_bool(obj)
106

  
107
    def decode_bool_optional(self, data):
108
        if not data.text:
109
            return data
110
        return self.decode_bool(data)
111

  
65 112

  
66 113
class AxelError(Exception):
67 114
    pass
tests/test_toulouse_axel_schema.py
1
# passerelle - uniform access to multiple data sources and services
2
# Copyright (C) 2019 Entr'ouvert
3
#
4
# This program is free software: you can redistribute it and/or modify it
5
# under the terms of the GNU Affero General Public License as published
6
# by the Free Software Foundation, either version 3 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU Affero General Public License for more details.
13
#
14
# You should have received a copy of the GNU Affero General Public License
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16

  
17
import os
18

  
19
from passerelle.contrib.toulouse_axel.models import AxelSchema
20

  
21
import pytest
22
import xmlschema
23

  
24
XSD_BASE_DIR = os.path.join(
25
    os.path.dirname(os.path.abspath(__file__)),
26
    '../passerelle/contrib/toulouse_axel/xsd')
27

  
28

  
29
@pytest.mark.parametrize('date_type', ['DATEREQUIREDType', 'DATEType'])
30
def test_date_mapping(date_type):
31
    xsd = """<?xml version="1.0" encoding="utf-8" ?>
32
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:all="urn:AllAxelTypes">
33
    <xsd:import schemaLocation="{path}/AllAxelTypes.xsd" namespace="urn:AllAxelTypes"  />
34
    <xsd:complexType name="PORTAILType">
35
        <xsd:sequence>
36
            <xsd:element name="DATE" type="all:{date_type}"/>
37
        </xsd:sequence>
38
    </xsd:complexType>
39
    <xsd:element name="PORTAIL" type="PORTAILType"/>
40
</xsd:schema>""".format(path=XSD_BASE_DIR, date_type=date_type)
41

  
42
    schema = AxelSchema(xsd, 'PORTAIL')
43
    xml_data = schema.encode({'PORTAIL': {'DATE': '2019-12-12'}})
44
    assert xml_data.find('DATE').text == '12/12/2019'
45

  
46
    json_data = schema.decode(xml_data)
47
    assert json_data['DATE'] == '2019-12-12'
48

  
49

  
50
@pytest.mark.parametrize('bool_type', ['OUINONREQUIREDType', 'OUINONType'])
51
@pytest.mark.parametrize('value, expected, py_expected', [
52
    ('OUI', 'OUI', True),
53
    ('oui', 'OUI', True),
54
    ('Oui', 'OUI', True),
55
    ('TRUE', 'OUI', True),
56
    ('true', 'OUI', True),
57
    ('True', 'OUI', True),
58
    (True, 'OUI', True),
59
    ('1', 'OUI', True),
60
    ('NON', 'NON', False),
61
    ('non', 'NON', False),
62
    ('Non', 'NON', False),
63
    ('FALSE', 'NON', False),
64
    ('false', 'NON', False),
65
    ('False', 'NON', False),
66
    (False, 'NON', False),
67
    ('0', 'NON', False),
68
    ('FOOBAR', 'FOOBAR', None),
69
    ('42', '42', None),
70
    ('OUIFOOBAR', 'OUIFOOBAR', None),
71
    ('FOONONBAR', 'FOONONBAR', None),
72
])
73
def test_bool_mapping(bool_type, value, expected, py_expected):
74
    if expected == '' and bool_type == 'OUINONREQUIREDType':
75
        # required, can't be empty
76
        return
77

  
78
    xsd = """<?xml version="1.0" encoding="utf-8" ?>
79
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:all="urn:AllAxelTypes">
80
    <xsd:import schemaLocation="{path}/AllAxelTypes.xsd" namespace="urn:AllAxelTypes"  />
81
    <xsd:complexType name="PORTAILType">
82
        <xsd:sequence>
83
            <xsd:element name="BOOL" type="all:{bool_type}"/>
84
        </xsd:sequence>
85
    </xsd:complexType>
86
    <xsd:element name="PORTAIL" type="PORTAILType"/>
87
</xsd:schema>""".format(path=XSD_BASE_DIR, bool_type=bool_type)
88

  
89
    schema = AxelSchema(xsd, 'PORTAIL')
90
    xml_data = schema.encode({'PORTAIL': {'BOOL': value}})
91
    assert xml_data.find('BOOL').text == expected
92

  
93
    if py_expected is None:
94
        with pytest.raises(xmlschema.XMLSchemaValidationError):
95
            json_data = schema.decode(xml_data)
96
    else:
97
        json_data = schema.decode(xml_data)
98
        assert json_data['BOOL'] is py_expected
0
-