176 lines
4.1 KiB
Python
176 lines
4.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
from datetime import datetime
|
|
from dateutil import parser as date_parser
|
|
from decimal import Decimal, DecimalException
|
|
from MailChecker import MailChecker
|
|
from phonenumbers import phonenumberutil, PhoneNumberFormat
|
|
from six import string_types, text_type
|
|
from slugify import slugify
|
|
|
|
import ftfy
|
|
import json
|
|
import phonenumbers
|
|
import re
|
|
|
|
|
|
def parse_bool(val):
|
|
if isinstance(val, bool):
|
|
return val
|
|
str_val = text_type(val).lower()
|
|
val = None
|
|
if str_val in ['1', 'true', 'yes', 'ok', 'on']:
|
|
val = True
|
|
elif str_val in ['0', 'false', 'no', 'ko', 'off']:
|
|
val = False
|
|
return val
|
|
|
|
|
|
def parse_datetime(val, format=None):
|
|
if isinstance(val, datetime):
|
|
return val
|
|
str_val = text_type(val)
|
|
val = None
|
|
if format:
|
|
try:
|
|
val = datetime.strptime(str_val, format)
|
|
except Exception:
|
|
val = None
|
|
else:
|
|
try:
|
|
val = date_parser.parse(str_val)
|
|
except Exception:
|
|
try:
|
|
val = datetime.fromtimestamp(float(str_val))
|
|
except Exception:
|
|
val = None
|
|
return val
|
|
|
|
|
|
def parse_decimal(val):
|
|
if isinstance(val, Decimal):
|
|
return val
|
|
str_val = text_type(val)
|
|
val = None
|
|
try:
|
|
val = Decimal(str_val)
|
|
except (ValueError, DecimalException):
|
|
pass
|
|
return val
|
|
|
|
|
|
def parse_dict(val):
|
|
if isinstance(val, dict):
|
|
return val
|
|
str_val = text_type(val)
|
|
if not len(str_val):
|
|
return None
|
|
try:
|
|
val = json.loads(str_val)
|
|
if not isinstance(val, dict):
|
|
val = None
|
|
except Exception:
|
|
val = None
|
|
return val
|
|
|
|
|
|
def parse_float(val):
|
|
if isinstance(val, float):
|
|
return val
|
|
str_val = text_type(val)
|
|
val = None
|
|
try:
|
|
val = float(str_val)
|
|
except ValueError:
|
|
pass
|
|
return val
|
|
|
|
|
|
def parse_email(val, check_blacklist=True):
|
|
val = parse_str(val)
|
|
if not val:
|
|
return None
|
|
val = val.lower()
|
|
if check_blacklist:
|
|
if not MailChecker.is_valid(val):
|
|
return None
|
|
else:
|
|
if not MailChecker.is_valid_email_format(val):
|
|
return None
|
|
return val
|
|
|
|
|
|
def parse_int(val):
|
|
if isinstance(val, int):
|
|
return val
|
|
str_val = text_type(val)
|
|
val = None
|
|
try:
|
|
val = int(str_val)
|
|
except ValueError:
|
|
pass
|
|
return val
|
|
|
|
|
|
def parse_list(val, separator=None):
|
|
if isinstance(val, (list, tuple, )):
|
|
return list(val)
|
|
str_val = text_type(val)
|
|
if not len(str_val):
|
|
return None
|
|
val = None
|
|
try:
|
|
val = json.loads(str_val)
|
|
if not isinstance(val, list):
|
|
val = None
|
|
except Exception:
|
|
if separator:
|
|
val = list(str_val.split(separator))
|
|
return val
|
|
|
|
|
|
def parse_phonenumber(val, country_code=None):
|
|
val = parse_str(val)
|
|
if not val:
|
|
return None
|
|
phone_raw = re.sub(r'[^0-9\+]', ' ', val)
|
|
phone_raw = phone_raw.strip()
|
|
if phone_raw.startswith('00'):
|
|
phone_raw = '+{}'.format(phone_raw[2:])
|
|
if country_code and len(country_code) >= 2:
|
|
country_code = country_code[0:2].upper()
|
|
else:
|
|
country_code = None
|
|
try:
|
|
phone_obj = phonenumbers.parse(phone_raw, country_code)
|
|
if phonenumbers.is_valid_number(phone_obj):
|
|
return {
|
|
'e164': phonenumbers.format_number(
|
|
phone_obj, PhoneNumberFormat.E164),
|
|
'international': phonenumbers.format_number(
|
|
phone_obj, PhoneNumberFormat.INTERNATIONAL),
|
|
'national': phonenumbers.format_number(
|
|
phone_obj, PhoneNumberFormat.NATIONAL),
|
|
}
|
|
else:
|
|
return None
|
|
except phonenumberutil.NumberParseException:
|
|
return None
|
|
|
|
|
|
def parse_slug(val):
|
|
return slugify(parse_str(val))
|
|
|
|
|
|
def parse_str(val):
|
|
if (isinstance(val, string_types)):
|
|
try:
|
|
val = ftfy.fix_text(val)
|
|
except UnicodeError:
|
|
pass
|
|
else:
|
|
val = text_type(val)
|
|
val = val.strip()
|
|
val = ' '.join(val.split())
|
|
return val
|