"""
Model utilities, unclassified functions
"""
def expand(docs):
"""
Expand a doclist sent from the client side. (Internally used by the request handler)
"""
def xzip(a,b):
d = {}
for i in range(len(a)):
d[a[i]] = b[i]
return d
from webnotes.utils import load_json
docs = load_json(docs)
clist = []
for d in docs['_vl']:
doc = xzip(docs['_kl'][d[0]], d);
clist.append(doc)
return clist
def compress(doclist):
"""
Compress a doclist before sending it to the client side. (Internally used by the request handler)
"""
if doclist and hasattr(doclist[0],'fields'):
docs = [d.fields for d in doclist]
else:
docs = doclist
kl, vl = {}, []
for d in docs:
dt = d['doctype']
if not (dt in kl.keys()):
fl = d.keys()
forbidden = ['server_code_compiled']
nl = ['doctype','localname','__oldparent','__unsaved']
# add client script for doctype, doctype due to ambiguity
if dt=='DocType': nl.append('__client_script')
for f in fl:
if not (f in nl) and not (f in forbidden):
nl.append(f)
kl[dt] = nl
## values
fl = kl[dt]
nl = []
for f in fl:
v = d.get(f)
if type(v)==long:
v=int(v)
nl.append(v)
vl.append(nl)
#errprint(str({'_vl':vl,'_kl':kl}))
return {'_vl':vl,'_kl':kl}
def getlist(doclist, field):
"""
Filter a list of records for a specific field from the full doclist
Example::
# find all phone call details
dl = getlist(self.doclist, 'contact_updates')
pl = []
for d in dl:
if d.type=='Phone':
pl.append(d)
"""
from webnotes.utils import cint
l = []
for d in doclist:
if d.parent and (not d.parent.lower().startswith('old_parent:')) and d.parentfield == field:
l.append(d)
l.sort(lambda a, b: cint(a.idx) - cint(b.idx))
return l
# Copy doclist
# ------------
def copy_doclist(doclist, no_copy = []):
"""
Save & return a copy of the given doclist
Pass fields that are not to be copied in `no_copy`
"""
from webnotes.model.doc import Document
cl = []
# main doc
c = Document(fielddata = doclist[0].fields.copy())
# clear no_copy fields
for f in no_copy:
if c.fields.has_key(f):
c.fields[f] = None
c.name = None
c.save(1)
cl.append(c)
# new parent name
parent = c.name
# children
for d in doclist[1:]:
c = Document(fielddata = d.fields.copy())
c.name = None
# clear no_copy fields
for f in no_copy:
if c.fields.has_key(f):
c.fields[f] = None
c.parent = parent
c.save(1)
cl.append(c)
return cl
def getvaluelist(doclist, fieldname):
"""
Returns a list of values of a particualr fieldname from all Document object in a doclist
"""
l = []
for d in doclist:
l.append(d.fields[fieldname])
return l
def _make_html(doc, link_list):
from webnotes.utils import cstr
out = '
'
for k in doc.fields.keys():
if k!='server_code_compiled':
v = cstr(doc.fields[k])
# link field
if v and (k in link_list.keys()):
dt = link_list[k]
if type(dt)==str and dt.startswith('link:'):
dt = dt[5:]
v = '%s' % (dt, v, v)
out += '\t%s | %s |
\n' % (cstr(k), v)
out += '
'
return out
def to_html(doclist):
"""
Return a simple HTML format of the doclist
"""
out = ''
link_lists = {}
for d in doclist:
if not link_lists.get(d.doctype):
link_lists[d.doctype] = d.make_link_list()
out += _make_html(d, link_lists[d.doctype])
return out
def commonify_doclist(doclist, with_comments=1):
"""
Makes a doclist more readable by extracting common properties.
This is used for printing Documents in files
"""
from webnotes.utils import get_common_dict, get_diff_dict
def make_common(doclist):
c = {}
if with_comments:
c['##comment'] = 'These values are common in all dictionaries'
for k in common_keys:
c[k] = doclist[0][k]
return c
def strip_common_and_idx(d):
for k in common_keys:
if k in d: del d[k]
if 'idx' in d: del d['idx']
return d
def make_common_dicts(doclist):
common_dict = {} # one per doctype
# make common dicts for all records
for d in doclist:
if not d['doctype'] in common_dict:
d1 = d.copy()
del d1['name']
common_dict[d['doctype']] = d1
else:
common_dict[d['doctype']] = get_common_dict(common_dict[d['doctype']], d)
return common_dict
common_keys = ['owner','docstatus','creation','modified','modified_by']
common_dict = make_common_dicts(doclist)
# make docs
final = []
for d in doclist:
f = strip_common_and_idx(get_diff_dict(common_dict[d['doctype']], d))
f['doctype'] = d['doctype'] # keep doctype!
# strip name for child records (only an auto generated number!)
if f['doctype'] != doclist[0]['doctype']:
del f['name']
if with_comments:
f['##comment'] = d['doctype'] + ('name' in f and (', ' + f['name']) or '')
final.append(f)
# add commons
commons = []
for d in common_dict.values():
d['name']='__common__'
if with_comments:
d['##comment'] = 'These values are common for all ' + d['doctype']
commons.append(strip_common_and_idx(d))
common_values = make_common(doclist)
return [common_values]+commons+final
def uncommonify_doclist(dl):
"""
Expands an commonified doclist
"""
# first one has common values
common_values = dl[0]
common_dict = {}
final = []
idx_dict = {}
for d in dl[1:]:
if 'name' in d and d['name']=='__common__':
# common for a doctype -
del d['name']
common_dict[d['doctype']] = d
else:
dt = d['doctype']
if not dt in idx_dict: idx_dict[dt] = 0;
d1 = common_values.copy()
# update from common and global
d1.update(common_dict[dt])
d1.update(d)
# idx by sequence
d1['idx'] = idx_dict[dt]
# increment idx
idx_dict[dt] += 1
final.append(d1)
return final
def pprint_doclist(doclist, with_comments = 1):
"""
Pretty Prints a doclist with common keys separated and comments
"""
from webnotes.utils import pprint_dict
dictlist =[pprint_dict(d) for d in commonify_doclist(doclist, with_comments)]
title = '# '+doclist[0]['doctype']+', '+doclist[0]['name']
return title + '\n[\n' + ',\n'.join(dictlist) + '\n]'
def peval_doclist(txt):
"""
Restore a pretty printed doclist
"""
if txt.startswith('#'):
return uncommonify_doclist(eval(txt))
else:
return eval(txt)
return uncommonify_doclist(eval(txt))