1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
import datetime
import hashlib
import re
from sqlalchemy.inspection import inspect
from szurubooru.errors import ValidationError
def unalias_dict(input_dict):
output_dict = {}
for key_list, value in input_dict.items():
if isinstance(key_list, str):
key_list = [key_list]
for key in key_list:
output_dict[key] = value
return output_dict
def get_md5(source):
if not isinstance(source, bytes):
source = source.encode('utf-8')
md5 = hashlib.md5()
md5.update(source)
return md5.hexdigest()
def flip(source):
return {v: k for k, v in source.items()}
def get_resource_info(entity):
serializers = {
'tag': lambda tag: tag.first_name,
'tag_category': lambda category: category.name,
'comment': lambda comment: comment.comment_id,
'post': lambda post: post.post_id,
}
resource_type = entity.__table__.name
assert resource_type in serializers
primary_key = inspect(entity).identity
assert primary_key is not None
assert len(primary_key) == 1
resource_repr = serializers[resource_type](entity)
assert resource_repr
resource_id = primary_key[0]
assert resource_id
return (resource_type, resource_id, resource_repr)
def is_valid_email(email):
''' Return whether given email address is valid or empty. '''
return not email or re.match(r'^[^@]*@[^@]*\.[^@]*$', email)
class dotdict(dict): # pylint: disable=invalid-name
''' dot.notation access to dictionary attributes. '''
def __getattr__(self, attr):
return self.get(attr)
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
def parse_time_range(value, timezone=datetime.timezone(datetime.timedelta())):
''' Return tuple containing min/max time for given text representation. '''
one_day = datetime.timedelta(days=1)
one_second = datetime.timedelta(seconds=1)
value = value.lower()
if not value:
raise ValidationError('Empty date format.')
if value == 'today':
now = datetime.datetime.now(tz=timezone)
return (
datetime.datetime(now.year, now.month, now.day, 0, 0, 0),
datetime.datetime(now.year, now.month, now.day, 0, 0, 0) \
+ one_day - one_second)
if value == 'yesterday':
now = datetime.datetime.now(tz=timezone)
return (
datetime.datetime(now.year, now.month, now.day, 0, 0, 0) - one_day,
datetime.datetime(now.year, now.month, now.day, 0, 0, 0) \
- one_second)
match = re.match(r'^(\d{4})$', value)
if match:
year = int(match.group(1))
return (
datetime.datetime(year, 1, 1),
datetime.datetime(year + 1, 1, 1) - one_second)
match = re.match(r'^(\d{4})-(\d{1,2})$', value)
if match:
year = int(match.group(1))
month = int(match.group(2))
return (
datetime.datetime(year, month, 1),
datetime.datetime(year, month + 1, 1) - one_second)
match = re.match(r'^(\d{4})-(\d{1,2})-(\d{1,2})$', value)
if match:
year = int(match.group(1))
month = int(match.group(2))
day = int(match.group(3))
return (
datetime.datetime(year, month, day),
datetime.datetime(year, month, day + 1) - one_second)
raise ValidationError('Invalid date format: %r.' % value)
def icase_unique(source):
target = []
target_low = []
for source_item in source:
if source_item.lower() not in target_low:
target.append(source_item)
target_low.append(source_item.lower())
return target
def value_exceeds_column_size(value, column):
if not value:
return False
max_length = column.property.columns[0].type.length
if max_length is None:
return False
return len(value) > max_length
|