Projet

Général

Profil

0001-toulouse_axel-bool-mapping-38464.patch

Lauréline Guérin, 13 décembre 2019 10:26

Télécharger (6,68 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         | 90 ++++++++++++++++++++++
 2 files changed, 139 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': '(?i)(oui|non|true|false|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 ''
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
import pytest
19

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

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

  
26

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

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

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

  
47

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

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

  
85
    schema = AxelSchema(xsd, 'PORTAIL')
86
    xml_data = schema.encode({'PORTAIL': {'BOOL': value}})
87
    assert xml_data.find('BOOL').text == expected
88

  
89
    json_data = schema.decode(xml_data)
90
    assert json_data['BOOL'] is py_expected
0
-