# encoding=utf-8
from __future__ import absolute_import
import json
[docs]class AttrDict(dict):
"""
Use dict key as attr
**examples**
.. code-block:: python
:linenos:
data = Attrdict()
# after two lines are equal statement
data.key1 = 1
data["key1"] = 1
# defaut value also is Attrdict after line is allowed
data.key2.key.key.key = 5
# if plus or minus a number the default value is 0
data.key3 += 5
assest(data.key2 == 5)
enjoys!!!
"""
DICT_ATTRS = set(dir(dict))
def __init__(self, dic={}, json_string=None, *args, **kwargs):
self.update(dict(args))
self.update(kwargs)
self.update(dic)
if json_string:
dic = json.loads(json_string)
self.update(dic)
for key, value in self.items():
if type(value) in (dict, list):
self[key] = self.__updatevalue__(value)
def __getattr__(self, key):
if key in self.DICT_ATTRS:
return dict.__getattr__(self, key)
if key not in self:
self[key] = AttrDict()
return self[key]
def __setattr__(self, key, value):
if key in self.DICT_ATTRS:
return dict.__setattr__(self, key, value)
self[key] = value
def __delattr__(self, key):
if key in self.DICT_ATTRS:
return dict.__delattr__(self, key)
del self[key]
def __delitem__(self, key):
if key not in self:
return
dict.__delitem__(self, key)
def __getitem__(self, key):
if key in self.DICT_ATTRS:
return dict.__getitem__(self, key)
elif key not in self:
self[key] = type(self)()
return dict.__getitem__(self, key)
def __updatevalue__(self, value):
if type(value) is dict:
value = type(self)(value)
elif type(value) is list:
for index, item in enumerate(value):
if type(item) is dict:
value[index] = type(self)(item)
return value
def __setitem__(self, key, value):
if key in self.DICT_ATTRS:
return dict.__setitem__(self, key, value)
dict.__setitem__(self, key, self.__updatevalue__(value))
[docs] def dict(self):
"""
return dict object of current instance
Returns:
* dict: convert from current instance
"""
res = {}
for var in self:
value = self[var]
if isinstance(value, type(self)):
value = value.dict()
if isinstance(value, list):
values = []
for item in value:
if isinstance(item, type(self)):
values.append(item.dict())
else:
values.append(item)
value = values
res[var] = value
return res
def __getstate__(self):
return self.dict()
def __setstate__(self, state):
pass
def __add__(self, other):
if not self:
return other
raise ValueError("Dict not empty.")
def __sub__(self, other):
if not self:
return -other
raise ValueError("Dict not empty.")
def __str__(self):
return super(AttrDict, self).__str__()
def __unicode__(self):
return super(AttrDict, self).__str__()
def __copy__(self):
import copy
return type(self)(copy.copy(self.dict()))
def __deepcopy__(self, memo):
from copy import deepcopy
return type(self)(deepcopy(self.dict()))
def __reduce__(self):
return super(AttrDict, self).__reduce__()
# function
[docs]def get_pickle(filename):
"""
Load file as pickle object
Args:
* filename (string): local system filename
Returns:
* object: if file is pickled data else None
"""
import os
import pickle
if not os.path.exists(filename):
return None
try:
with open(filename, "rb") as f:
data = pickle.load(f)
return data
except Exception:
return None
[docs]def put_pickle(data, filename):
"""
Save object as pickle to filename
Args:
* data (object): any can pickled object
* filename (string): local system filename
"""
import os
import pickle
filename = os.path.abspath(filename)
dirname = os.path.dirname(filename)
if not os.path.exists(dirname):
os.makedirs(dirname)
with open(filename, "wb") as f:
pickle.dump(data, f)
[docs]def get_json(filename):
"""
Load file as pickle object
Args:
* filename (string): local system filename
Returns:
* object: if file is json data else None
"""
import os
import json
if not os.path.exists(filename):
return None
try:
with open(filename, "rb") as f:
data = json.loads(f.read())
return data
except Exception:
return None
[docs]def put_json(data, filename, indent=None):
"""
Save object as json string to filename
Args:
* data (object): any can jsoned object
* filename (string): local system filename
* indent (None, optional): json indent width default None
"""
import os
import json
filename = os.path.abspath(filename)
dirname = os.path.dirname(filename)
if not os.path.exists(dirname):
os.makedirs(dirname)
with open(filename, "w") as f:
f.write(json.dumps(data, indent=indent))
[docs]def md5(data=None, filename=None, encoding="utf8"):
'''
get data or file md5 checksum
Args:
* data (string, optional): string
* filename (string, optional): local system filename
Returns:
* string: md5 checksum
'''
import hashlib
m = hashlib.md5()
if data:
m.update(data.encode(encoding=encoding))
if filename:
with open(filename, "rb") as f:
while True:
block = f.read(16 * 1024)
if not block:
break
m.update(block)
return m.hexdigest()
[docs]def sha1(data=None, filename=None, encoding="utf8"):
'''
get data or file sha1 checksum
Args:
* data (string, optional): string
* filename (string, optional): local system filename
Returns:
* string: sha1 checksum
'''
import hashlib
m = hashlib.sha1()
if data:
m.update(data.encode(encoding=encoding))
if filename:
with open(filename, "rb") as f:
while True:
block = f.read(16 * 1024)
if not block:
break
m.update(block)
return m.hexdigest()
[docs]def is_number(number):
'''
Test parameter is number True or False
Args:
* number (TYPE): any object
Returns:
* bool: True if number is float value or False
'''
try:
float(number)
return True
except Exception:
return False
[docs]def number(num):
'''
convert parameter to float or None
Args:
* num (TYPE): any object
Returns:
* float: num float value or None
'''
try:
return float(num)
except Exception:
return None
[docs]def length(string):
'''
Get true size of string or char, char might be 1 or 2, string accumulate all of char
**example**
.. code-block:: python
:linenos:
dandan.value.length("test string") == 11
dandan.value.length("测试字符串") == 10
dandan.value.length("测试字符串 test string") == 22
Args:
string (string or char): requested
Returns:
int: size of string or char
'''
import six
if six.PY2:
string = unicode(string)
if len(string) == 0:
return 0
if len(string) > 1:
accumulate = 0
for char in string:
accumulate += length(char)
return accumulate
import unicodedata
if unicodedata.east_asian_width(string) in {'F', 'W', 'A'}:
return 2
else:
return 1