188 lines
7.3 KiB
Python
Executable File
188 lines
7.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
from __future__ import print_function
|
|
import logging
|
|
import numbers
|
|
import sys
|
|
|
|
|
|
class DictUtils:
|
|
|
|
|
|
@staticmethod
|
|
# if a value for a given key is "empty" (like '',[],{}, None etc, except for zero) then the pair is removed
|
|
def cleanDictionary(dictIn):
|
|
for k,v in list(dictIn.items()):
|
|
if (not v) and not isinstance(v,numbers.Number):
|
|
del dictIn[k]
|
|
#keep going down the tree
|
|
elif isinstance(v,dict):
|
|
DictUtils.cleanDictionary(v)
|
|
|
|
return dictIn # doesn't have to return it, but just in case one wants to use it this way instead of passing by ref
|
|
|
|
@staticmethod
|
|
def renormalizeKey(s):
|
|
"""
|
|
staticmethod renormalizeKey(s):
|
|
Apply renormalization to a dictionary key,
|
|
i.e., transform key to a standard format,
|
|
by removing all white space and canverting
|
|
to lower case.
|
|
"""
|
|
from isceobj.Util.StringUtils import StringUtils
|
|
return StringUtils.lower_no_spaces(s)
|
|
|
|
#renormalize all the keys in the dictionary
|
|
@staticmethod
|
|
def renormalizeKeys(dictNow):
|
|
"""
|
|
staticmethod renormalizeKeys(d):
|
|
renormalize all keys in dictionary d by
|
|
applying renormalizeKey static method.
|
|
"""
|
|
for k,v in list(dictNow.items()):
|
|
kNow = DictUtils.renormalizeKey(k)
|
|
if kNow != k:
|
|
dictNow[kNow] = dictNow.pop(k)
|
|
if isinstance(v,dict):
|
|
DictUtils.renormalizeKeys(v)
|
|
return dictNow
|
|
#compares keys in dict with an input one. it's case and whitespace insensitive
|
|
#if replace is true it also changes the equivalent key with k
|
|
@staticmethod
|
|
def keyIsIn(k,dictNow,replace = None):
|
|
if(replace == None):
|
|
replace = True
|
|
ret = False
|
|
for k1 in dictNow.keys():
|
|
if (''.join(k1.split())).lower() == (''.join(k.split())).lower():
|
|
if replace:
|
|
dictNow[k] = dictNow.pop(k1)
|
|
ret = True
|
|
break
|
|
|
|
return ret
|
|
|
|
|
|
@staticmethod
|
|
# update the dictionary dict1 by the value in dict2.
|
|
# If the key exists and replace = True, then the value is overwritten
|
|
# otherwise it is appended.
|
|
# If it does not exist a new node is created.
|
|
# When replace is True if spare (a list of key or single key) is defined the values of these
|
|
# keys will be appended if they are not already present. Use it only for str values, i.e. for doc string
|
|
def updateDictionary(dict1,dict2,replace = None,spare = None):
|
|
if replace is None:
|
|
replace = False
|
|
if spare:#if it's a single key, put it into a list
|
|
if isinstance(spare,str):
|
|
spare = [spare]
|
|
else:
|
|
spare = []
|
|
|
|
# dict1 is the one to update
|
|
for k2,v2 in dict(dict2).items():
|
|
if DictUtils.keyIsIn(k2,dict1):
|
|
if isinstance(v2,dict):#if is a dict keep going down the node
|
|
DictUtils.updateDictionary(dict1[k2],v2,replace,spare)
|
|
else:
|
|
if replace:#replace the entry
|
|
append = False
|
|
if k2 in spare: #check if the key needs to be spared
|
|
append = True
|
|
if isinstance(dict1[k2],list):
|
|
if v2 in dict1[k2]: # if so then append the content
|
|
append = False
|
|
break
|
|
else:
|
|
if dict1[k2] == v2:
|
|
append = False
|
|
break
|
|
if not append:# same key but item already in. it will rewrite it. not a big deal
|
|
break
|
|
if append: #convert everything into a list
|
|
if not isinstance(v2,list):
|
|
v2 = [v2]
|
|
if not isinstance(dict1[k2],list):
|
|
dict1[k2] = [dict1[k2]]
|
|
#do not append if already there
|
|
for v22 in v2:
|
|
if v22 not in dict1[k2]:
|
|
dict1[k2].append(v22)
|
|
else:
|
|
dict1.update({k2:v2})
|
|
else:#update only if is not the same item or the item is not already present (if dict1[k2] is a list)
|
|
if isinstance(dict1[k2],list):
|
|
if v2 not in dict1[k2]: # if so then append the content
|
|
dict1[k2].append(v2)
|
|
else:
|
|
if dict1[k2] != v2:
|
|
dict1[k2] = [dict1[k2],v2]
|
|
|
|
else:
|
|
dict1.update({k2:v2})
|
|
|
|
#probably need to create a class with some dictionary utils. put also some of the methods in Parser()
|
|
# if we have a dict of dicts, keeping the structure, extract a particular key
|
|
# ex. {'n1':{n1_1:{'k1':v1},{'k2':v2},n1_2:{'k1':v11},{'k2':v22}}} extract the 'k2' the result is
|
|
# {'n1':{n1_1:{'k2':v2},n1_2:{'k2':v22}}}. in this case k1 could be the 'doc' string and 'k2' the units
|
|
|
|
@staticmethod
|
|
def extractDict(dictIn,key):
|
|
import copy
|
|
#put everything i
|
|
dictOut = copy.deepcopy(dictIn)
|
|
DictUtils.searchKey(dictIn,dictOut,key)
|
|
return dictOut
|
|
|
|
@staticmethod
|
|
#just wrapper of the _getDictWithey so the result can be returned instead of being an argument
|
|
def getDictWithKey(dictIn,key,includeKey=True):
|
|
dictOut = {}
|
|
DictUtils._getDictWithKey(dictIn,dictOut,key,includeKey)
|
|
return dictOut
|
|
|
|
|
|
@staticmethod
|
|
#it returns the first occurance of {key,val} where val is the corresponding value for that key
|
|
#if includeKey is True otherwise returns val
|
|
def _getDictWithKey(dictIn,dictOut,key,includeKey=True):
|
|
if(isinstance(dictIn,dict)):
|
|
for k in dictIn.keys():
|
|
if(k == key):
|
|
if includeKey:
|
|
dictOut.update({k:dictIn[k]})
|
|
else:
|
|
dictOut.update(dictIn[k])
|
|
break
|
|
else:
|
|
DictUtils._getDictWithKey(dictIn[k],dictOut,key,includeKey)
|
|
|
|
@staticmethod
|
|
#returns a dictionary where all the keys are removed but key
|
|
def searchKey(dictIn,dictOut,key):
|
|
for k,v in dictIn.items():
|
|
if(k == key):
|
|
break
|
|
if isinstance(v,dict):
|
|
DictUtils.searchKey(v,dictOut[k],key)
|
|
if dictOut[k] == {}:#if we removed everything in dictOut[k], then remove the branch
|
|
dictOut.pop(k)
|
|
|
|
elif (key != k):#this is a simple pair (k,v) but the key is not the one we want
|
|
dictOut.pop(k)
|
|
|
|
|
|
|
|
def __getstate__(self):
|
|
d = dict(self.__dict__)
|
|
del d['logger']
|
|
return d
|
|
def __setstate__(self,d):
|
|
self.__dict__.update(d)
|
|
self.logger = logging.getLogger('isce.iscesys.DictUtils')
|
|
def __init__(self):
|
|
self.logger = logging.getLogger('isce.iscesys.DictUtils')
|
|
|
|
|