Passed
Push — master ( 015759...93d3ae )
by Fabio
03:16
created

benedict.dicts.parse.parse_util._parse_list()   B

Complexity

Conditions 8

Size

Total Lines 14
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 14
dl 0
loc 14
rs 7.3333
c 0
b 0
f 0
cc 8
nop 2
1
# -*- coding: utf-8 -*-
2
3
from benedict.serializers import JSONSerializer
4
from benedict.utils import type_util
5
6
from datetime import datetime
7
from dateutil import parser as date_parser
8
from decimal import Decimal, DecimalException
9
from MailChecker import MailChecker
10
from phonenumbers import phonenumberutil, PhoneNumberFormat
11
from six import text_type
12
from slugify import slugify
13
14
import ftfy
15
import phonenumbers
16
import re
17
18
19
def _parse_with(val, type_checker, parser, **kwargs):
20
    if val is None:
21
        return None
22
    if callable(type_checker) and type_checker(val):
23
        return val
24
    s = text_type(val)
25
    if not len(s):
26
        return None
27
    return parser(s, **kwargs)
28
29
30
def _parse_bool(val):
31
    val = val.lower()
32
    if val in ['1', 'true', 'yes', 'ok', 'on']:
33
        return True
34
    elif val in ['0', 'false', 'no', 'ko', 'off']:
35
        return False
36
    return None
37
38
39
def parse_bool(val):
40
    return _parse_with(val, type_util.is_bool, _parse_bool)
41
42
43
def parse_date(val, format=None):
44
    val = parse_datetime(val, format)
45
    if val:
46
        return val.date()
47
    return None
48
49
50
def _parse_datetime_with_format(val, format):
51
    try:
52
        return datetime.strptime(val, format)
53
    except Exception:
54
        return None
55
56
57
def _parse_datetime_without_format(val):
58
    try:
59
        return date_parser.parse(val)
60
    except Exception:
61
        return _parse_datetime_from_timestamp(val)
62
63
64
def _parse_datetime_from_timestamp(val):
65
    try:
66
        return datetime.fromtimestamp(float(val))
67
    except Exception:
68
        return None
69
70
71
def parse_datetime(val, format=None):
72
    if type_util.is_datetime(val):
73
        return val
74
    s = text_type(val)
75
    if format:
76
        return _parse_datetime_with_format(s, format)
77
    else:
78
        return _parse_datetime_without_format(s)
79
80
81
def _parse_decimal(val):
82
    try:
83
        return Decimal(val)
84
    except (ValueError, DecimalException):
85
        return None
86
87
88
def parse_decimal(val):
89
    return _parse_with(val, type_util.is_decimal, _parse_decimal)
90
91
92
def _parse_dict(val):
93
    serializer = JSONSerializer()
94
    try:
95
        d = serializer.decode(val)
96
        if type_util.is_dict(d):
97
            return d
98
        return None
99
    except Exception:
100
        return None
101
102
103
def parse_dict(val):
104
    return _parse_with(val, type_util.is_dict, _parse_dict)
105
106
107
def _parse_float(val):
108
    try:
109
        return float(val)
110
    except ValueError:
111
        return None
112
113
114
def parse_float(val):
115
    return _parse_with(val, type_util.is_float, _parse_float)
116
117
118
def _parse_email(val, check_blacklist=True):
119
    val = val.lower()
120
    if check_blacklist:
121
        if not MailChecker.is_valid(val):
122
            return None
123
    else:
124
        if not MailChecker.is_valid_email_format(val):
125
            return None
126
    return val
127
128
129
def parse_email(val, check_blacklist=True):
130
    return _parse_with(
131
        val, None, _parse_email, check_blacklist=check_blacklist)
132
133
134
def _parse_int(val):
135
    try:
136
        return int(val)
137
    except ValueError:
138
        return None
139
140
141
def parse_int(val):
142
    return _parse_with(val, type_util.is_integer, _parse_int)
143
144
145
def _parse_list(val, separator=None):
146
    if val.startswith('{') and val.endswith('}') or val.startswith('[') and val.endswith(']'):
147
        try:
148
            serializer = JSONSerializer()
149
            l = serializer.decode(val)
150
            if type_util.is_list(l):
151
                return l
152
            return None
153
        except Exception:
154
            pass
155
    if separator:
156
        l = list(val.split(separator))
157
        return l
158
    return None
159
160
161
def parse_list(val, separator=None):
162
    val = _parse_with(val, type_util.is_list_or_tuple,
163
                      _parse_list, separator=separator)
164
    return list(val) if type_util.is_list_or_tuple(val) else val
165
166
167
def _parse_phonenumber(val, country_code=None):
168
    try:
169
        phone_obj = phonenumbers.parse(val, country_code)
170
        if phonenumbers.is_valid_number(phone_obj):
171
            return {
172
                'e164': phonenumbers.format_number(
173
                    phone_obj, PhoneNumberFormat.E164),
174
                'international': phonenumbers.format_number(
175
                    phone_obj, PhoneNumberFormat.INTERNATIONAL),
176
                'national': phonenumbers.format_number(
177
                    phone_obj, PhoneNumberFormat.NATIONAL),
178
            }
179
        return None
180
    except phonenumberutil.NumberParseException:
181
        return None
182
183
184
def parse_phonenumber(val, country_code=None):
185
    s = parse_str(val)
186
    if not s:
187
        return None
188
    phone_raw = re.sub(r'[^0-9\+]', ' ', s)
189
    phone_raw = phone_raw.strip()
190
    if phone_raw.startswith('00'):
191
        phone_raw = '+{}'.format(phone_raw[2:])
192
    if country_code and len(country_code) >= 2:
193
        country_code = country_code[0:2].upper()
194
    return _parse_with(
195
        phone_raw, None, _parse_phonenumber, country_code=country_code)
196
197
198
def _parse_slug(val):
199
    return slugify(val)
200
201
202
def parse_slug(val):
203
    s = parse_str(val)
204
    return _parse_slug(s)
205
206
207
def parse_str(val):
208
    if type_util.is_string(val):
209
        try:
210
            val = ftfy.fix_text(val)
211
        except UnicodeError:
212
            pass
213
    else:
214
        val = text_type(val)
215
    val = val.strip()
216
    val = ' '.join(val.split())
217
    return val
218
219
220
def parse_uuid(val):
221
    s = parse_str(val)
222
    return s if type_util.is_uuid(s) else None
223