fix: 修改 tools.helpers 结构
This commit is contained in:
@@ -1,174 +0,0 @@
|
|||||||
import random
|
|
||||||
import re
|
|
||||||
import string
|
|
||||||
|
|
||||||
from six.moves.urllib import parse as urlparse
|
|
||||||
|
|
||||||
"""
|
|
||||||
工具函数集
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def valid_email(email):
|
|
||||||
"""
|
|
||||||
验证字符串是否为合法电子邮件
|
|
||||||
:param email:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
email = str(email)
|
|
||||||
if len(email) > 7:
|
|
||||||
pattern = (
|
|
||||||
r"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@"
|
|
||||||
r"(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?"
|
|
||||||
)
|
|
||||||
if re.match(pattern, email) is not None:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
LETTERS = 0b001
|
|
||||||
DIGITS = 0b010
|
|
||||||
PUNCTUATION = 0b100
|
|
||||||
|
|
||||||
|
|
||||||
def random_ascii_string(length, mask=None):
|
|
||||||
"""
|
|
||||||
生成随机 ascii 字符串
|
|
||||||
:param length:
|
|
||||||
:param mask:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
|
|
||||||
if mask is None:
|
|
||||||
mask = LETTERS | DIGITS
|
|
||||||
|
|
||||||
unicode_ascii_characters = ''
|
|
||||||
if mask & LETTERS:
|
|
||||||
unicode_ascii_characters += string.ascii_letters
|
|
||||||
if mask & DIGITS:
|
|
||||||
unicode_ascii_characters += string.digits
|
|
||||||
if mask & PUNCTUATION:
|
|
||||||
unicode_ascii_characters += string.punctuation
|
|
||||||
|
|
||||||
if not unicode_ascii_characters:
|
|
||||||
return ''
|
|
||||||
|
|
||||||
rnd = random.SystemRandom()
|
|
||||||
return ''.join([rnd.choice(unicode_ascii_characters) for _ in range(length)])
|
|
||||||
|
|
||||||
|
|
||||||
def url_parse_query(url):
|
|
||||||
"""
|
|
||||||
从 url 提取 query string 字典
|
|
||||||
:param url:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
return dict(urlparse.parse_qsl(urlparse.urlparse(url).query, True))
|
|
||||||
|
|
||||||
|
|
||||||
def url_without_query(url):
|
|
||||||
"""
|
|
||||||
移除 url 中 query string
|
|
||||||
"""
|
|
||||||
url = urlparse.urlparse(url)
|
|
||||||
return urlparse.urlunparse((url.scheme, url.netloc, url.path, url.params, '', url.fragment))
|
|
||||||
|
|
||||||
|
|
||||||
def build_url(base, additional_params=None):
|
|
||||||
"""
|
|
||||||
url 中增加 query string 参数
|
|
||||||
:param base:
|
|
||||||
:param additional_params:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
url = urlparse.urlparse(base)
|
|
||||||
query_params = {}
|
|
||||||
query_params.update(urlparse.parse_qsl(url.query, True))
|
|
||||||
if additional_params is not None:
|
|
||||||
query_params.update(additional_params)
|
|
||||||
for k, v in additional_params.items():
|
|
||||||
if v is None:
|
|
||||||
query_params.pop(k)
|
|
||||||
|
|
||||||
return urlparse.urlunparse(
|
|
||||||
(url.scheme, url.netloc, url.path, url.params, urlparse.urlencode(query_params), url.fragment)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
COUNTRY_ZONE = ('86',)
|
|
||||||
|
|
||||||
|
|
||||||
def parse_mobile(mobile_str):
|
|
||||||
"""
|
|
||||||
解析手机号码
|
|
||||||
:param mobile_str:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
match = re.findall(r'^(\+({0}))?(\d+)$'.format('|'.join(COUNTRY_ZONE)), mobile_str)
|
|
||||||
if match:
|
|
||||||
zone, mobile = match[0][-2:]
|
|
||||||
if '+' in mobile_str and not zone:
|
|
||||||
return None
|
|
||||||
|
|
||||||
if not zone:
|
|
||||||
zone = '86'
|
|
||||||
|
|
||||||
if zone == '86' and re.match(r'^1\d{10}$', mobile) is not None:
|
|
||||||
return zone, mobile
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def list_to_tree(rows, id_key='id', parent_id_key='parent_id', i=0):
|
|
||||||
"""
|
|
||||||
list转tree的函数
|
|
||||||
:param rows:
|
|
||||||
:param id_key:
|
|
||||||
:param parent_id_key:
|
|
||||||
:param i:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
data = []
|
|
||||||
for row in rows:
|
|
||||||
if row[parent_id_key] == i:
|
|
||||||
row['children'] = list_to_tree(rows, id_key=id_key, parent_id_key=parent_id_key, i=row[id_key])
|
|
||||||
data.append(row)
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
def cut_tree(trees, nodes, id_key='id', parent_id_key='parent_id'):
|
|
||||||
"""
|
|
||||||
根据叶结点整理出包含所有叶节点的最小树结构
|
|
||||||
:param trees:
|
|
||||||
:param nodes: 叶结点
|
|
||||||
:param id_key:
|
|
||||||
:param parent_id_key:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
data = []
|
|
||||||
for row in trees:
|
|
||||||
children = cut_tree(row['children'], nodes, id_key=id_key, parent_id_key=parent_id_key)
|
|
||||||
if children or row['id'] in nodes:
|
|
||||||
row['children'] = children
|
|
||||||
data.append(row)
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
s = valid_email('wslstest@sample.com')
|
|
||||||
print(s)
|
|
||||||
|
|
||||||
s = random_ascii_string(40)
|
|
||||||
print(s)
|
|
||||||
|
|
||||||
s = url_parse_query('http://api_w.qiange.so/hz/shorturl_tongji?short_url=BkPMeb')
|
|
||||||
print(s)
|
|
||||||
|
|
||||||
s = url_without_query('http://api_w.qiange.so/hz/shorturl_tongji?short_url=BkPMeb')
|
|
||||||
print(s)
|
|
||||||
|
|
||||||
s = build_url('http://www.baidu.com', {'a': 1, 'b': 2})
|
|
||||||
print(s)
|
|
||||||
|
|
||||||
s = parse_mobile('+8615888888888')
|
|
||||||
print(s)
|
|
7
nc_http/tools/helpers/__init__.py
Normal file
7
nc_http/tools/helpers/__init__.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
"""
|
||||||
|
工具函数集
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .string import *
|
||||||
|
from .tree import *
|
||||||
|
from .url import *
|
134
nc_http/tools/helpers/string.py
Normal file
134
nc_http/tools/helpers/string.py
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
import random
|
||||||
|
import re
|
||||||
|
import string
|
||||||
|
|
||||||
|
from six import string_types
|
||||||
|
|
||||||
|
LETTERS = 0b001
|
||||||
|
DIGITS = 0b010
|
||||||
|
PUNCTUATION = 0b100
|
||||||
|
|
||||||
|
|
||||||
|
def random_ascii_string(length, mask=None):
|
||||||
|
"""
|
||||||
|
生成随机 ascii 字符串
|
||||||
|
:param length:
|
||||||
|
:param mask:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
if mask is None:
|
||||||
|
mask = LETTERS | DIGITS
|
||||||
|
|
||||||
|
unicode_ascii_characters = ''
|
||||||
|
if mask & LETTERS:
|
||||||
|
unicode_ascii_characters += string.ascii_letters
|
||||||
|
if mask & DIGITS:
|
||||||
|
unicode_ascii_characters += string.digits
|
||||||
|
if mask & PUNCTUATION:
|
||||||
|
unicode_ascii_characters += string.punctuation
|
||||||
|
|
||||||
|
if not unicode_ascii_characters:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
rnd = random.SystemRandom()
|
||||||
|
return ''.join([rnd.choice(unicode_ascii_characters) for _ in range(length)])
|
||||||
|
|
||||||
|
|
||||||
|
def valid_email(email):
|
||||||
|
"""
|
||||||
|
验证字符串是否为合法电子邮件
|
||||||
|
:param email:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
email = str(email)
|
||||||
|
if len(email) > 7:
|
||||||
|
pattern = (
|
||||||
|
r"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@"
|
||||||
|
r"(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?"
|
||||||
|
)
|
||||||
|
if re.match(pattern, email) is not None:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
COUNTRY_ZONE = ('86',)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_mobile(mobile_str):
|
||||||
|
"""
|
||||||
|
解析手机号码
|
||||||
|
:param mobile_str:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
match = re.findall(r'^(\+({0}))?(\d+)$'.format('|'.join(COUNTRY_ZONE)), mobile_str)
|
||||||
|
if match:
|
||||||
|
zone, mobile = match[0][-2:]
|
||||||
|
if '+' in mobile_str and not zone:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if not zone:
|
||||||
|
zone = '86'
|
||||||
|
|
||||||
|
if zone == '86' and re.match(r'^1\d{10}$', mobile) is not None:
|
||||||
|
return zone, mobile
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def camelize(uncamelized_str):
|
||||||
|
"""
|
||||||
|
小写下划线转驼峰
|
||||||
|
:param uncamelized_str:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if not uncamelized_str:
|
||||||
|
return uncamelized_str
|
||||||
|
result = ''.join(i.capitalize() for i in uncamelized_str.split('_'))
|
||||||
|
result = ''.join((result[0].lower(), result[1:]))
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def uncamelize(camelized_str):
|
||||||
|
"""
|
||||||
|
驼峰转小写下划线
|
||||||
|
:param camelized_str:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if not camelized_str:
|
||||||
|
return camelized_str
|
||||||
|
lst = []
|
||||||
|
for index, char in enumerate(camelized_str):
|
||||||
|
if char.isupper() and index != 0:
|
||||||
|
lst.append("_")
|
||||||
|
lst.append(char)
|
||||||
|
|
||||||
|
return ''.join(lst).lower()
|
||||||
|
|
||||||
|
|
||||||
|
def strip_value(data):
|
||||||
|
"""
|
||||||
|
递归处理字符占位符
|
||||||
|
:param data:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if isinstance(data, dict):
|
||||||
|
for key, value in data.items():
|
||||||
|
data[key] = strip_value(value)
|
||||||
|
elif isinstance(data, list):
|
||||||
|
for key, value in enumerate(data):
|
||||||
|
data[key] = strip_value(value)
|
||||||
|
elif isinstance(data, string_types):
|
||||||
|
data = data.strip()
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
s = valid_email('wslstest@sample.com')
|
||||||
|
print(s)
|
||||||
|
|
||||||
|
s = random_ascii_string(40)
|
||||||
|
print(s)
|
||||||
|
s = parse_mobile('+8615888888888')
|
||||||
|
print(s)
|
33
nc_http/tools/helpers/tree.py
Normal file
33
nc_http/tools/helpers/tree.py
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
def list_to_tree(rows, id_key='id', parent_id_key='parent_id', i=0):
|
||||||
|
"""
|
||||||
|
list转tree的函数
|
||||||
|
:param rows:
|
||||||
|
:param id_key:
|
||||||
|
:param parent_id_key:
|
||||||
|
:param i:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
data = []
|
||||||
|
for row in rows:
|
||||||
|
if row[parent_id_key] == i:
|
||||||
|
row['children'] = list_to_tree(rows, id_key=id_key, parent_id_key=parent_id_key, i=row[id_key])
|
||||||
|
data.append(row)
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def cut_tree(trees, nodes, id_key='id', parent_id_key='parent_id'):
|
||||||
|
"""
|
||||||
|
根据叶结点整理出包含所有叶节点的最小树结构
|
||||||
|
:param trees:
|
||||||
|
:param nodes: 叶结点
|
||||||
|
:param id_key:
|
||||||
|
:param parent_id_key:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
data = []
|
||||||
|
for row in trees:
|
||||||
|
children = cut_tree(row['children'], nodes, id_key=id_key, parent_id_key=parent_id_key)
|
||||||
|
if children or row['id'] in nodes:
|
||||||
|
row['children'] = children
|
||||||
|
data.append(row)
|
||||||
|
return data
|
50
nc_http/tools/helpers/url.py
Normal file
50
nc_http/tools/helpers/url.py
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
from six.moves.urllib import parse as urlparse
|
||||||
|
|
||||||
|
|
||||||
|
def url_parse_query(url):
|
||||||
|
"""
|
||||||
|
从 url 提取 query string 字典
|
||||||
|
:param url:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
return dict(urlparse.parse_qsl(urlparse.urlparse(url).query, True))
|
||||||
|
|
||||||
|
|
||||||
|
def url_without_query(url):
|
||||||
|
"""
|
||||||
|
移除 url 中 query string
|
||||||
|
"""
|
||||||
|
url = urlparse.urlparse(url)
|
||||||
|
return urlparse.urlunparse((url.scheme, url.netloc, url.path, url.params, '', url.fragment))
|
||||||
|
|
||||||
|
|
||||||
|
def build_url(base, additional_params=None):
|
||||||
|
"""
|
||||||
|
url 中增加 query string 参数
|
||||||
|
:param base:
|
||||||
|
:param additional_params:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
url = urlparse.urlparse(base)
|
||||||
|
query_params = {}
|
||||||
|
query_params.update(urlparse.parse_qsl(url.query, True))
|
||||||
|
if additional_params is not None:
|
||||||
|
query_params.update(additional_params)
|
||||||
|
for k, v in additional_params.items():
|
||||||
|
if v is None:
|
||||||
|
query_params.pop(k)
|
||||||
|
|
||||||
|
return urlparse.urlunparse(
|
||||||
|
(url.scheme, url.netloc, url.path, url.params, urlparse.urlencode(query_params), url.fragment)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
s = url_parse_query('http://api_w.qiange.so/hz/shorturl_tongji?short_url=BkPMeb')
|
||||||
|
print(s)
|
||||||
|
|
||||||
|
s = url_without_query('http://api_w.qiange.so/hz/shorturl_tongji?short_url=BkPMeb')
|
||||||
|
print(s)
|
||||||
|
|
||||||
|
s = build_url('http://www.baidu.com', {'a': 1, 'b': 2})
|
||||||
|
print(s)
|
Reference in New Issue
Block a user