Source code for eppy.iddgaps
# Copyright (c) 2012, 2022 Santosh Philip
# =======================================================================
# Distributed under the MIT License.
# (See accompanying file LICENSE or copy at
# http://opensource.org/licenses/MIT)
# =======================================================================
"""idd comments have gaps in them.
With \note fields as indicated
This code fills those gaps
see: SCHEDULE:DAY:LIST as an example"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
# see iddgaps6.py on usage
# TODO : need unit tests for all htese functions
# works for all objects, including troublesome ones
# factor the code i iddgaps4.py into functions
# idd might look like this
# <snip>
# / field varA 1
# / field varB 1
# / field varC 1
# / field varA 2
# / field varB 2
# / field varC 2
# / above pattern continues
#
# find objects where the fields are not named
# do the following only for those objects
# find the first field that has an integer. This is a repeating field
# gather the repeating field names (without the integer)
# generate all the repeating fields for all variables
import eppy.bunchhelpers as bunchhelpers
[docs]def cleaniddfield(acomm):
"""make all the keys lower case"""
for key in list(acomm.keys()):
val = acomm[key]
acomm[key.lower()] = val
for key in list(acomm.keys()):
val = acomm[key]
if key != key.lower():
acomm.pop(key)
return acomm
[docs]def cleancommdct(commdct):
"""make all keys in commdct lower case"""
return [[cleaniddfield(fcomm) for fcomm in comm] for comm in commdct]
[docs]def getfields(comm):
"""get all the fields that have the key 'field'"""
fields = []
for field in comm:
if "field" in field:
fields.append(field)
return fields
[docs]def repeatingfieldsnames(fields, int_replace=None):
"""get the names of the repeating fields"""
if not int_replace:
int_replace = "%s"
fnames = [field["field"][0] for field in fields]
fnames = [bunchhelpers.onlylegalchar(fname) for fname in fnames]
fnames = [fname for fname in fnames if bunchhelpers.intinlist(fname.split())]
fnames = [(bunchhelpers.replaceint(fname, int_replace), None) for fname in fnames]
dct = dict(fnames)
repnames = fnames[: len(list(dct.keys()))]
return repnames
[docs]def a_missingkey_standard(commdct, key_i, key_txt, nofirstfields):
"""
sometimes IDD has fields with no field description. This happens in extensible.
This functions picks up the previous field description and adds them
to the fields that have no field descriptions. This update is done in place to commdct
commdct is not returned.
missing field descriptions are actually mising keys of a dict
hence the function is called a missingkey
This is very old function. Not sure how it works now.
"""
comm = commdct[key_i]
# get all fields
fields = getfields(comm)
# get repeating field names
repnames = repeatingfieldsnames(fields)
try:
first = repnames[0][0] % (1,)
except IndexError:
nofirstfields.append(key_txt)
return nofirstfields
# get all comments of the first repeating field names
firstnames = [repname[0] % (1,) for repname in repnames]
fcomments = [
field
for field in fields
if bunchhelpers.onlylegalchar(field["field"][0]) in firstnames
]
fcomments = [dict(fcomment) for fcomment in fcomments]
for cmt in fcomments:
fld = cmt["field"][0]
fld = bunchhelpers.onlylegalchar(fld)
fld = bunchhelpers.replaceint(fld)
cmt["field"] = [fld]
for i, cmt in enumerate(comm[1:]):
thefield = cmt["field"][0]
thefield = bunchhelpers.onlylegalchar(thefield)
if thefield == first:
break
first_i = i + 1
newfields = []
for i in range(1, len(comm[first_i:]) // len(repnames) + 1):
for fcomment in fcomments:
nfcomment = dict(fcomment)
fld = nfcomment["field"][0]
fld = fld % (i,)
nfcomment["field"] = [fld]
newfields.append(nfcomment)
for i, cmt in enumerate(comm):
if i < first_i:
continue
else:
afield = newfields.pop(0)
comm[i] = afield
commdct[key_i] = comm
return nofirstfields
[docs]def missingkeys_standard(commdct, dtls, skiplist=None):
"""put missing keys in commdct for standard objects
return a list of keys where it is unable to do so
commdct is not returned, but is updated"""
if skiplist == None:
skiplist = []
# find objects where all the fields are not named
gkeys = [dtls[i] for i in range(len(dtls)) if commdct[i].count({}) > 2]
nofirstfields = []
# operatie on those fields
for key_txt in gkeys:
if key_txt in skiplist:
continue
# return nofirstfields
key_i = dtls.index(key_txt.upper())
# a_missingkey_standard_1(commdct[key_i], key_txt, nofirstfields)
a_missingkey_standard(commdct, key_i, key_txt, nofirstfields)
return nofirstfields
[docs]def missingkeys_nonstandard(block, commdct, dtls, objectlist, afield="afiled %s"):
"""This is an object list where thre is no first field name
to give a hint of what the first field name should be"""
afield = "afield %s"
for key_txt in objectlist:
key_i = dtls.index(key_txt.upper())
comm = commdct[key_i]
if block:
blk = block[key_i]
for i, cmt in enumerate(comm):
if cmt == {}:
first_i = i
break
for i, cmt in enumerate(comm):
if i >= first_i:
if block:
comm[i]["field"] = ["%s" % (blk[i])]
else:
comm[i]["field"] = [afield % (i - first_i + 1,)]