Source code for zcooldl.utils
# @FILENAME : utils
# @AUTHOR : lonsty
# @DATE : 2019/9/9 11:09
import os
import random
import time
from collections import namedtuple
from functools import wraps
from typing import Iterable
[docs]def retry(exceptions, tries=3, delay=1, backoff=2, logger=None):
"""Retry calling the decorated function using an exponential backoff.
:param exceptions: The exception to check. may be a tuple of exceptions to check.
:param tries: Number of times to try (not retry) before giving up.
:param delay: Initial delay between retries in seconds.
:param backoff: Backoff multiplier (e.g. value of 2 will double the delay each retry).
:param logger: Logger to use. If None, print.
"""
def deco_retry(f):
@wraps(f)
def f_retry(*args, **kwargs):
mtries, mdelay = tries, delay or random.uniform(0.5, 1.5)
while mtries > 1:
try:
return f(*args, **kwargs)
except exceptions as e:
if logger:
logger.warning('{}, Retrying in {} seconds...'.format(e, mdelay))
# else:
# print('{}, Retrying in {} seconds...'.format(e, mdelay))
time.sleep(mdelay)
mtries -= 1
mdelay *= backoff
return f(*args, **kwargs)
return f_retry # true decorator
return deco_retry
[docs]def mkdirs_if_not_exist(dir):
"""文件夹不存在时则创建。
:param str dir: 文件夹路径,支持多级
"""
if not os.path.isdir(dir):
try:
os.makedirs(dir)
except FileExistsError:
pass
[docs]def safe_filename(filename):
"""去掉文件名中的非法字符。
:param str filename: 文件名
:return str: 合法文件名
"""
return "".join([c for c in filename if c not in r'\/:*?"<>|']).strip()
[docs]def parse_resources(ids, names, collections):
"""解析用户名或 ID。
:param str ids: 半角逗号分隔的用户 ID
:param str names: 半角逗号分隔的用户名
:return list: 包含 User 数据的列表
"""
Resource = namedtuple('Resource', 'id name collection')
resources = []
if collections:
resources = [Resource(None, None, collection) for collection in collections.split(',')]
elif names:
resources = [Resource(None, name, None) for name in names.split(',')]
elif ids:
resources = [Resource(uid, None, None) for uid in ids.split(',')]
return resources # TODO: 去重
[docs]def sort_records(records: Iterable, order: dict):
"""根据自定义的排序规则排序
:param Iterable records: 要排序的记录
:param dict order: 自定义的排序
:return:
"""
def _order_by(obj: namedtuple):
if obj.type == 'topic':
return (order[obj.type], obj.index, obj.objid, obj.title, obj.url)
return (order[obj.type], obj.objid, obj.index, obj.title, obj.url)
return sorted(records, key=_order_by)