gallery.accords-library.com/server/szurubooru/func/util.py

172 lines
4.9 KiB
Python
Raw Normal View History

import os
2016-04-30 21:17:08 +00:00
import hashlib
2016-04-02 12:13:26 +00:00
import re
import tempfile
2017-04-24 21:30:53 +00:00
from typing import Any, Optional, Union, Tuple, List, Dict, Generator, TypeVar
from datetime import datetime, timedelta
from contextlib import contextmanager
from szurubooru import errors
T = TypeVar('T')
def snake_case_to_lower_camel_case(text: str) -> str:
components = text.split('_')
2016-08-14 10:30:37 +00:00
return components[0].lower() + \
''.join(word[0].upper() + word[1:].lower() for word in components[1:])
def snake_case_to_upper_train_case(text: str) -> str:
return '-'.join(
word[0].upper() + word[1:].lower() for word in text.split('_'))
def snake_case_to_lower_camel_case_keys(
source: Dict[str, Any]) -> Dict[str, Any]:
target = {}
for key, value in source.items():
target[snake_case_to_lower_camel_case(key)] = value
return target
@contextmanager
def create_temp_file(**kwargs: Any) -> Generator:
(descriptor, path) = tempfile.mkstemp(**kwargs)
os.close(descriptor)
try:
with open(path, 'r+b') as handle:
yield handle
finally:
os.remove(path)
@contextmanager
def create_temp_file_path(**kwargs: Any) -> Generator:
(descriptor, path) = tempfile.mkstemp(**kwargs)
os.close(descriptor)
try:
yield path
finally:
os.remove(path)
def unalias_dict(source: List[Tuple[List[str], T]]) -> Dict[str, T]:
output_dict = {} # type: Dict[str, T]
for aliases, value in source:
for alias in aliases:
output_dict[alias] = value
2016-05-07 19:42:03 +00:00
return output_dict
def get_md5(source: Union[str, bytes]) -> str:
2016-04-30 21:17:08 +00:00
if not isinstance(source, bytes):
source = source.encode('utf-8')
md5 = hashlib.md5()
md5.update(source)
return md5.hexdigest()
def get_sha1(source: Union[str, bytes]) -> str:
if not isinstance(source, bytes):
source = source.encode('utf-8')
sha1 = hashlib.sha1()
sha1.update(source)
return sha1.hexdigest()
def flip(source: Dict[Any, Any]) -> Dict[Any, Any]:
2016-04-30 21:17:08 +00:00
return {v: k for k, v in source.items()}
def is_valid_email(email: Optional[str]) -> bool:
2016-04-03 20:03:58 +00:00
''' Return whether given email address is valid or empty. '''
return not email or re.match(r'^[^@]*@[^@]*\.[^@]*$', email) is not None
2016-04-03 16:00:38 +00:00
class dotdict(dict): # pylint: disable=invalid-name
2016-04-03 16:00:38 +00:00
''' dot.notation access to dictionary attributes. '''
def __getattr__(self, attr: str) -> Any:
return self.get(attr)
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
2016-04-02 12:13:26 +00:00
def parse_time_range(value: str) -> Tuple[datetime, datetime]:
2016-04-03 20:03:58 +00:00
''' Return tuple containing min/max time for given text representation. '''
one_day = timedelta(days=1)
one_second = timedelta(seconds=1)
2017-02-03 20:42:15 +00:00
almost_one_day = one_day - one_second
2016-04-02 12:13:26 +00:00
value = value.lower()
if not value:
raise errors.ValidationError('Empty date format.')
2016-04-02 12:13:26 +00:00
if value == 'today':
now = datetime.utcnow()
2016-04-02 12:13:26 +00:00
return (
datetime(now.year, now.month, now.day, 0, 0, 0),
2017-02-03 20:42:15 +00:00
datetime(now.year, now.month, now.day, 0, 0, 0) + almost_one_day
)
2016-04-02 12:13:26 +00:00
if value == 'yesterday':
now = datetime.utcnow()
2016-04-02 12:13:26 +00:00
return (
datetime(now.year, now.month, now.day, 0, 0, 0) - one_day,
datetime(now.year, now.month, now.day, 0, 0, 0) - one_second)
2016-04-02 12:13:26 +00:00
match = re.match(r'^(\d{4})$', value)
2016-04-02 12:13:26 +00:00
if match:
year = int(match.group(1))
return (datetime(year, 1, 1), datetime(year + 1, 1, 1) - one_second)
2016-04-02 12:13:26 +00:00
match = re.match(r'^(\d{4})-(\d{1,2})$', value)
2016-04-02 12:13:26 +00:00
if match:
year = int(match.group(1))
month = int(match.group(2))
return (
datetime(year, month, 1),
datetime(year, month + 1, 1) - one_second)
2016-04-02 12:13:26 +00:00
match = re.match(r'^(\d{4})-(\d{1,2})-(\d{1,2})$', value)
2016-04-02 12:13:26 +00:00
if match:
year = int(match.group(1))
month = int(match.group(2))
day = int(match.group(3))
return (
datetime(year, month, day),
datetime(year, month, day + 1) - one_second)
2016-04-02 12:13:26 +00:00
raise errors.ValidationError('Invalid date format: %r.' % value)
2016-04-15 20:49:55 +00:00
def icase_unique(source: List[str]) -> List[str]:
target = [] # type: List[str]
target_low = [] # type: List[str]
2016-04-15 20:49:55 +00:00
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: Optional[str], column: Any) -> bool:
2016-04-30 21:17:08 +00:00
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
def get_column_size(column: Any) -> Optional[int]:
if not column:
return None
return column.property.columns[0].type.length
def chunks(source_list: List[Any], part_size: int) -> Generator:
for i in range(0, len(source_list), part_size):
yield source_list[i:i + part_size]