|
1
|
1 |
|
import collections |
|
2
|
1 |
|
import hashlib |
|
3
|
1 |
|
import re |
|
4
|
1 |
|
import unicodedata |
|
5
|
|
|
|
|
6
|
|
|
|
|
7
|
1 |
|
def dict_path(d, path): |
|
8
|
1 |
|
if not isinstance(path, (list, tuple)): |
|
9
|
1 |
|
raise ValueError() |
|
10
|
|
|
|
|
11
|
1 |
|
for keys in path: |
|
12
|
1 |
|
if type(keys) is not list: |
|
13
|
1 |
|
keys = [keys] |
|
14
|
|
|
|
|
15
|
1 |
|
value = None |
|
16
|
|
|
|
|
17
|
1 |
|
for key in keys: |
|
18
|
1 |
|
if key not in d: |
|
19
|
1 |
|
continue |
|
20
|
|
|
|
|
21
|
1 |
|
value = d[key] |
|
22
|
|
|
|
|
23
|
1 |
|
if value is None: |
|
24
|
1 |
|
value = {} |
|
25
|
|
|
|
|
26
|
1 |
|
for key in keys: |
|
27
|
1 |
|
d[key] = value |
|
28
|
|
|
|
|
29
|
1 |
|
d = value |
|
30
|
|
|
|
|
31
|
1 |
|
return d |
|
32
|
|
|
|
|
33
|
|
|
|
|
34
|
1 |
|
def flatten(text): |
|
35
|
1 |
|
if text is None: |
|
36
|
1 |
|
return None |
|
37
|
|
|
|
|
38
|
|
|
# Normalize `text` to ascii |
|
39
|
1 |
|
text = normalize(text) |
|
40
|
|
|
|
|
41
|
|
|
# Remove special characters |
|
42
|
1 |
|
text = re.sub('[^A-Za-z0-9\s]+', '', text) |
|
|
|
|
|
|
43
|
|
|
|
|
44
|
|
|
# Merge duplicate spaces |
|
45
|
1 |
|
text = ' '.join(text.split()) |
|
46
|
|
|
|
|
47
|
|
|
# Convert to lower-case |
|
48
|
1 |
|
return text.lower() |
|
49
|
|
|
|
|
50
|
|
|
|
|
51
|
1 |
|
def merge(a, b, recursive=False): |
|
52
|
1 |
|
if not recursive: |
|
53
|
1 |
|
a.update(b) |
|
54
|
1 |
|
return a |
|
55
|
|
|
|
|
56
|
|
|
# Merge child dictionaries |
|
57
|
1 |
|
for k, v in b.iteritems(): |
|
58
|
1 |
|
if isinstance(v, collections.Mapping): |
|
59
|
1 |
|
r = merge(a.get(k, {}), v, recursive=True) |
|
60
|
1 |
|
a[k] = r |
|
61
|
|
|
else: |
|
62
|
1 |
|
a[k] = b[k] |
|
63
|
|
|
|
|
64
|
1 |
|
return a |
|
65
|
|
|
|
|
66
|
|
|
|
|
67
|
1 |
|
def md5(value): |
|
68
|
|
|
# Generate MD5 hash of `value` |
|
69
|
|
|
m = hashlib.md5() |
|
70
|
|
|
m.update(value) |
|
71
|
|
|
|
|
72
|
|
|
return m.hexdigest() |
|
73
|
|
|
|
|
74
|
|
|
|
|
75
|
1 |
|
def normalize(text): |
|
76
|
1 |
|
if text is None: |
|
77
|
1 |
|
return None |
|
78
|
|
|
|
|
79
|
|
|
# Normalize unicode characters |
|
80
|
1 |
|
if type(text) is unicode: |
|
|
|
|
|
|
81
|
1 |
|
text = unicodedata.normalize('NFKD', text) |
|
82
|
|
|
|
|
83
|
|
|
# Ensure text is ASCII, ignore unknown characters |
|
84
|
1 |
|
return text.encode('ascii', 'ignore') |
|
85
|
|
|
|
|
86
|
|
|
|
|
87
|
1 |
|
def pms_path(): |
|
88
|
1 |
|
file_path = __file__.lower() |
|
89
|
|
|
|
|
90
|
1 |
|
if 'plug-ins' not in file_path: |
|
91
|
1 |
|
return None |
|
92
|
|
|
|
|
93
|
|
|
return __file__[:file_path.index('plug-ins')] |
|
94
|
|
|
|
|
95
|
|
|
|
|
96
|
1 |
|
def resolve(value, *args, **kwargs): |
|
97
|
1 |
|
if hasattr(value, '__call__'): |
|
98
|
1 |
|
return value(*args, **kwargs) |
|
99
|
|
|
|
|
100
|
1 |
|
return value |
|
101
|
|
|
|
|
102
|
|
|
|
|
103
|
1 |
|
def to_integer(value): |
|
104
|
1 |
|
if value is None: |
|
105
|
1 |
|
return None |
|
106
|
|
|
|
|
107
|
1 |
|
try: |
|
108
|
1 |
|
return int(value) |
|
109
|
1 |
|
except: |
|
|
|
|
|
|
110
|
1 |
|
return None |
|
111
|
|
|
|
|
112
|
|
|
|
|
113
|
1 |
|
def to_tuple(value): |
|
114
|
1 |
|
if type(value) is tuple: |
|
115
|
1 |
|
return value |
|
116
|
|
|
|
|
117
|
1 |
|
return value, |
|
118
|
|
|
|
|
119
|
|
|
|
|
120
|
1 |
|
def try_convert(value, value_type, default=None): |
|
121
|
1 |
|
try: |
|
122
|
1 |
|
return value_type(value) |
|
123
|
1 |
|
except ValueError: |
|
124
|
1 |
|
return default |
|
125
|
1 |
|
except TypeError: |
|
126
|
|
|
return default |
|
127
|
|
|
|
Escape sequences in Python are generally interpreted according to rules similar to standard C. Only if strings are prefixed with
rorRare they interpreted as regular expressions.The escape sequence that was used indicates that you might have intended to write a regular expression.
Learn more about the available escape sequences. in the Python documentation.