"""
projectsetup.
Created on Thu Jan 7 17:18:03 2021
"""
import os
import sys
import json
import time
import getpass
import datetime
from pathlib import Path
from inspect import isclass
from pylab_ml.common import environment
from pylab_ml.common import common
from pylab_ml.common import file_io
from ate_common.logger import (LogLevel)
__author__ = "Zlin526F"
__credits__ = ["Zlin526F"]
__email__ = "Zlin526F@github"
__version__ = '0.0.1'
mylogger = None
[docs]
class JsonDecoder(json.JSONDecoder):
[docs]
def decode(self, obj):
# TODO: implementend parser for hexnumbers and other special formats....
# or better use YAML-files.....
return json.JSONDecoder.decode(self, obj)
[docs]
class diclist(list):
"""Dictionary list."""
[docs]
def __init__(*args, **kwargs):
global myparent
if len(args) > 1:
myparent = args[1]
args = list(args)
del args[1]
list.__init__(*args, **kwargs)
def __getattr__(mylist, key):
if key in mylist:
list.__getattribute__(mylist, key)
else:
return diclist.values(mylist, key)
def keys(mylist):
result = []
for item in mylist:
result.append(list(item.keys())[0])
return result
[docs]
def values(mylist, key=None):
"""Get the value(s) from the key found in mylist.
"""
result = None
if key is not None and key in diclist.keys(mylist):
result = list(mylist[diclist.keys(mylist).index(key)].values())
elif len(mylist) > 0:
result = []
for item in mylist:
if key is None:
value = list(item.values())[0]
elif key in list(item.values())[0].keys():
value = list(item.values())[0][key]
else:
value = None
if type(value) is str:
value = common.str2num(value)
result.append(value)
if result is not None and len(result) == 1:
result = result[0]
return result
[docs]
def run(mylist, **kwargs):
"""Call the runmacro from the parent.
"""
result = None
if myparent is not None and hasattr(myparent, 'runmacro'):
mylogger.log_message(LogLevel.Debug(), f'run macro {myparent.mylastdotdic}: {mylist}')
result = myparent.runmacro(mylist, **kwargs)
else:
mylogger.log_message(LogLevel.Error(), f'No instruction how to should interprete the list: {mylist}')
return result
[docs]
class setupstr(str):
def arange(items):
return (common.arange(items))
def start(items):
return (common.arange(items)[0])
def end(items):
return (common.arange(items)[-1])
[docs]
class dotdict(dict):
"""dot.notation access to dictionary attributes."""
def myget(keyname, value):
result = dict.get(keyname, value)
if value not in ['size', 'shape']:
myparent.mylastdotdic = value
# print(f'keyname: {keyname},\nvalue: {value},\nresult: {result},\n')
if result is None:
# self.logger.log_message(LogLevel.Warning(), f"'dotdict' has no attribute {value} -> result is None")
raise AttributeError(f"'dotdict' has no attribute {value} ")
return result
__getattr__ = myget # __getattr__ = dict.get
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
[docs]
class ProjectSetup(object):
"""
Class for the Setup from your project.
read the tb_projectsetup.json file in the directory ..../projec/version/workarea/..../harness
and create instance slicing
with init.'yourpath' you have access to the initialisation setup, which is defined in the tb_projectsetup.json
Example:
"instruments": {
"smu" : [
{"voltage": 0},
{"i_clamp": 0.2}
]
}
==> create dictionary self.init.instruments.smu = [{'voltage': 0}, {'i_clamp': 0.2}]
TODO: possibility to overwrite the values in tb_projectsetup.json with the file in tb_ate/src/'Hardware'/'Base'/tb_projectsetup.json
"""
_RESULT = 'result_projectsetup.json'
_SETUPFILE = 'tb_projectsetup.json'
_MYCLASS = 'myclass'
[docs]
def __init__(self, logger=None, filename=None):
"""
Initialise and save setup configuration to the setup-dictionary.
read the setup-file tb_projectsetup.json
and create all values in self.init.......
Args: None
*Examples:*
* Initialization
>>> setup = ProjectSetup()
* Append some setup information:
>>> tcc.setup.append('instruments.matrix', 'port', 'pxie6')
>>> tcc.setup.append('instruments.smu', 'voltage', 5)
>>> tcc.setup.append('instruments.smu', 'limit', 0.1)
"""
global mylogger
self.main_path = str(Path(sys.modules['__main__'].__file__).parent) + os.sep
os.environ['PROJECT_PATH'] = str(Path(self.main_path).parent.parent.parent) + os.sep
self.network = '' if os.environ.get('NETWORK') is None else os.environ.get('NETWORK')
self.logger = logger
mylogger = logger
self.instName = 'setup'
self.mylastdotdic = None
self.lastresult = None
self.lastmacro = None
self.running = False
self._setupfile = None
self.testbench_name = None
if filename is not None:
self.apply_configuration({'filename': filename})
[docs]
def create_dotdic(self, dic, root=None):
"""Make from a dictionary a dot-dictionary with diclist."""
for mydic in dic.keys():
if type(dic[mydic]) is dict:
if root is not None:
object.__setattr__(root, mydic, self.create_dotdic(dic[mydic]))
dic[mydic] = self.create_dotdic(dic[mydic])
elif type(dic[mydic]) is list:
dic[mydic] = diclist(self, dic[mydic])
elif type(dic[mydic]) is str and dic[mydic].find(':') > 0: # found an arange-function -> change to setupstr
dic[mydic] = setupstr(dic[mydic])
return dotdict(dic)
[docs]
def initialization(self, parent=None):
"""Set the instruments with the specified instname to its setup values in self.init.instruments.
and save information (if instname exist!) from the instruments to result.instruments:
- used class, version, id
"""
self.parent = parent
if not self.running:
for instName in dir(parent): # add information from each instrument to result.instruments
if instName.find('_') != -1:
continue
instrument = getattr(parent, instName)
if not isclass(instrument): # filter out the class-definitions
if instrument.__class__.__name__ == 'RegisterMaster':
self._registermaster = instrument.filename
if hasattr(instrument, 'instName'):
name = instrument.instName
else:
name = instrument.__class__.__name__
if name in ['Logger', 'module', 'function'] or instName in ['Type', 'base', 'run', 'do', 'hardware', 'sbins']:
continue
# self.write('instruments', name, instrument.__class__) # default is 'self.result.instruments'
self.write('instruments', instName, str(instrument.__class__)) # default is 'self.result.instruments'
self.running = True
# TODO!: call runmacro and merge missing function
if not hasattr(self, 'init'):
self.logger.log_message(LogLevel.Warning(), f"no instrument init found in actual initialsation: {self.setup['Setupfile']}")
return
for instrument in self.init: # initialise the instances to their values in self.init
items = self.init[instrument]
self.init_instrument(parent, instrument, items)
self.logger.log_message(LogLevel.Info(), f"{self.__class__}.init: set instruments to its setup values, defined in {self.setup.Setupfile}")
def init_instrument(self, parent, instrument, items):
if type(items) is dotdict and list(items.keys())[0] == self._MYCLASS:
for myclass in items[self._MYCLASS]:
if hasattr(parent, instrument) and myclass == getattr(parent, instrument).__class__.__name__:
self.init_instrument(parent, instrument, items[self._MYCLASS][myclass])
return
if instrument not in dir(parent):
self.logger.info(f"{self.setup.Setupfile}: Instrument '{instrument}' not found in your Hardware configuration -> do nothing")
return
if type(items) is dotdict and len(items.keys()) > 1:
for item in items:
self.init_instrument(getattr(parent, instrument), item, items[item])
return
for item in items:
error = False
cpitem = item
mypath = getattr(parent, instrument) # set mypath to the instrument
if type(item) is dict:
item = tuple(item.items())[0]
cmd = item[0]
value = item[1]
getattribute = False
if type(item) is str:
cmd = item
getattribute = True
command = cmd
if len(cmd.split('.')) > 1:
split = cmd.split('.')
if split[0] == 'parent':
mypath = parent
split.pop(0)
for index in range(len(split)-1):
try:
mypath = getattr(mypath, split[index])
except Exception:
self.logger.info(f'{self.setup.Setupfile}: {instrument} path from {cpitem} not found --> do nothing')
error = True
cmd = split[index+1]
if error:
continue
result = None
try:
if getattribute:
result = getattr(mypath, cmd, None)
self.logger.info(f'{instrument}.{item} == {result}')
elif cmd.find('(') < 0:
setattr(mypath, cmd, value)
else: # it is a function call
cmd = cmd[0:cmd.find('(')]
result = getattr(mypath, cmd, None)(value)
except Exception:
error = True
if not error:
self.write(f'setup.instruments.{instrument}', command, (value, result))
else:
self.logger.error(f'{self.setup.Setupfile}: {instrument}.{cpitem} not found --> do nothing')
def _replaceSomeThing(self, jsontable):
"""
Check if jsontable has environment-variables starts with $, or jsontable has path-value.
if yes than replace environment-variables with its value,
if it a path-value than add //samba
"""
for key in jsontable:
if type(jsontable) is dict:
value = jsontable[key]
else:
value = key
if type(value) is dict or type(value) is list:
self._replaceSomeThing(value)
elif type(value) is str and value.find('$') > -1: # find environment variables inside the value?
tmp = value.split('/')
nvalue = ''
for s in tmp:
if s.find('$') == 0:
env = s[1:]
s = os.environ.get(env)
if s is None:
self.logger.log_message(LogLevel.Error(), f'environment {env} not defined')
s = ''
nvalue += s + '/'
if nvalue != '':
if type(jsontable) is dict:
jsontable[key] = nvalue[:-1]
else:
jsontable[1] = nvalue[:-1]
elif type(value) is str and len(value) > 0 and value[0] == '/' and os.name == "nt" and value.find(f'{self.network}') != 0:
if type(jsontable) is dict:
jsontable[key] = self.network + value
else:
jsontable[1] = self.network + value
[docs]
def write(self, path, name=None, value=None):
"""Write path to the dictionary in my class ProjectSetup.
Path must be a string like 'instruments.smu'
normaly append this path to result
if path start with setup than write to setup.path
e.q. write('instruments.smu', 'port', 'pxie5')
write('setup.HostName', os.environ.get('COMPUTERNAME'))
"""
path = path.split('.')
lastindex = 'result'
if path[0] == 'setup':
lastindex = 'setup'
path.pop(0)
mydic = self.__dict__[lastindex]
lastdic = mydic
for index in path:
if index not in mydic.keys(): # than create new dictionary
if type(mydic) is diclist:
if mydic == []:
lastdic[lastindex] = dotdict({index: diclist(self)})
mydic = lastdic[lastindex]
else:
mydic.append(dotdict({index: diclist(self)}))
mydic = lastdic[lastindex][-1]
else:
mydic[index] = diclist(self)
lastdic = mydic
if type(mydic) is diclist:
mydic = mydic.values(index)
else:
mydic = mydic[index]
lastindex = index
if name is None:
mydic += [value]
else:
mydic += [{name: value}]
def _configsave2setup(self):
self.setup.Date = datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S")
self.setup.Timestamp = time.time()
self.setup.PROJECT = os.environ.get('PROJECT')
self.setup.VERSION = os.environ.get('VERSION')
self.setup.USER = os.environ.get('USER') if os.environ.get('USER') is not None else getpass.getuser()
self.setup.WORKAREA = os.environ.get('WORKAREA')
self.setup.COMPUTERNAME = os.environ.get('COMPUTERNAME')
self.setup.Setupfile = self._setupfile
self.setup.Registermaster = self._registermaster if hasattr(self, '_registermaster') else os.environ.get('Registermaster')
# self.setup.conda = check_output('conda -V', shell=True)[:-2].decode('utf-8') with maxiconda doesnt' running anymore!?
# self.setup.python = check_output('python -V', shell=True)[:-2].decode('utf-8')
[docs]
def runmacro(self, cmdlist, **kwargs):
"""Execute commands in the cmdlist.
kwargs: 'wr2setup' : write result to the setup.result json file.
"""
wr2setup = False
if 'output' in kwargs:
wr2setup = kwargs['output'] == 'wr2setup'
result = []
macro = myparent.mylastdotdic
self.lastmacro = macro
for cmd in cmdlist:
myresult = self.call(cmd)
if myresult is not None:
result.append(myresult)
self.lastresult = result
if wr2setup:
self.write(macro, cmd, myresult)
if len(result) == 1:
result = result[0]
self.lastresult = result
if cmdlist == []:
self.logger.log_message(LogLevel.Warning(), f'Macro {macro} not defined in setup')
if wr2setup:
self.write('macro', macro, 'not defined in setup')
return result
def call(self, mycmd, value=None, senderror=True): # TODO! : replace call with common.strcall()
if type(mycmd) is str:
mycmd = mycmd.split(',')
result = []
for cmd in mycmd:
cmdsplit = cmd.split('.')
found = False
if cmdsplit[0] == 'tcc':
cmdsplit.pop(0)
if hasattr(self.result, 'instruments') and cmdsplit[0] in self.result.instruments.keys():
path = self.parent
found = True
elif cmdsplit[0] in self.__dict__:
path = self
found = True
if not found:
if senderror:
self.logger.log_message(LogLevel.Error(), f'{cmdsplit[0]} not found in instrumentlist or in {self.instName}, {cmd} not performed')
result.append(cmd)
continue
mypath = getattr(path, cmdsplit[0])
cmdsplit.pop(0)
if len(cmdsplit) > 1:
for index in range(len(cmdsplit)-1):
mypath = getattr(mypath, cmdsplit[index])
command = cmdsplit[index+1]
else:
command = cmdsplit[0]
myresult = None
if command.find('(') < 0:
if value is None:
myresult = getattr(mypath, command, None)
else:
myresult = setattr(mypath, command, value)
else: # it is a function call
value = command[command.find('(')+1:command.find(')')]
command = command[0:command.find('(')]
if not hasattr(mypath, command):
self.logger.log_message(LogLevel.Error(), f"call error: '{mypath.instName}' has no attribute '{command}'")
return None
if value == '':
myresult = getattr(mypath, command, None)()
else:
value = common.str2num(value)
if type(value) is str and value.find("'") == 0:
value = value[value.find("'")+1:]
value = value[:value.find("'")]
# else:
# logger.error('macro: variable not supported yet')
if type(value) is str and value.find('=') > 0:
mydic = {}
for arg in value.split(','):
tr2dic = arg.split('=')
mydic[tr2dic[0]] = common.str2num(tr2dic[1])
myresult = getattr(mypath, command, None)(**mydic)
else:
myresult = getattr(mypath, command, None)(value)
if myresult is not None:
result.append(myresult)
if len(result) == 1:
result = result[0]
return result
[docs]
def regDump(self, liste='default', invert=False, output=None, bwidth=16):
"""Read values from Register and return with a list of their values.
Parameters
----------
liste :
* 'default' : if define setup.reg.nodump -> read register without the registers which are defined in setup.reg.nodump
if define setup.reg.dump -> read register which are defined in setup.reg.dump
* 'all' : read all register
* type(liste) == list : use liste as a list
invert :
* True : use reg that are not in the list
* False : use reg that are in the list
output :
= None : return with a list of all registers (or adresses) and their values
= 'wr2setup' : write return with a list of all registers and their values to setup.result.regs.regDump
"""
knownParameter = [None, 'wr2setup']
if output not in knownParameter:
self.logger.log_message(LogLevel.Error(), f'output = {output} not found as parameter')
error = 0
allregs = []
allregs = diclist()
memdump = []
dumplist = []
mylist = self.parent.regs.register
invert = False
if type(liste) is list:
dumplist = liste
if liste == 'default' and hasattr(self.regs, 'dump'):
dumplist = self.regs.dump
elif type(liste) is dotdict:
dumplist = liste
elif hasattr(self.regs, 'nodump'):
dumplist = self.regs.nodump
invert = True
elif liste == 'all':
dumplist = self.parent.regs.register
else:
dumplist = liste
if type(dumplist) is str:
foundtcc = dumplist.find('self.')
dumplist = dumplist[5:] if foundtcc == 0 else dumplist
dump = self.call(dumplist, senderror=False)
else:
dump = dumplist
if type(dump) is dotdict: # if it's a memorymap with different addr for the protocoll?
try:
dump = dump[self.parent.regs.use]
except Exception:
pass
self.logger.log_message(LogLevel.Info(), f' regDump: read {dump}')
if type(dump) in [str, setupstr] and dump.find(':') > 0:
dump = common.arange(dump)
mylist = dump
index = 0
for regname in mylist:
if (invert and regname not in dump) or (not invert and regname in dump):
if type(regname) is str:
addr = self.parent.regs.register[regname].addr
bank = self.parent.regs.register[regname]._bank
value = self.parent.regs.register[regname].read()
width = self.parent.regs.register[regname]._len_slices() // 4
else:
addr = regname
value = self.parent.regs.readreg(regname)
bank = 0 # self.parent.regs._bank
if self.parent.regs._len_slices is not None:
width = self.parent.regs._len_slices // 4
else:
width = bwidth // 4
regname = self.parent.regs.find(addr)
if regname is None:
regname = f'{dumplist}_{hex(index)}'
error += 1 if value < 0 else error
if output is not None and 'wr2setup' in output:
bank = 0 if bank is None else bank
addr = 0 if addr is None else addr
self.write(f'{self.testbench_name}.regDump', regname, [f'0x{bank+addr:03x}', f'0x{value:0{width}x}'])
allregs.append([f'0x{bank+addr:03x}', f'0x{value:0{width}x}'])
memdump.append(value)
index += 1
if self.testbench_name is not None:
dumpname = liste.split('.')[-1] if type(liste) is str else 'dump'
self.write(f'{self.testbench_name}.regDumpDat', dumpname, memdump)
else:
self.logger.log_message(LogLevel.Info(), 'testbench name not defined, could not write regDumpDat to {self._SETUPFILE}')
return error, memdump, allregs
[docs]
def regDumpSave2DUT(self, mode='default', compare='cache'):
"""Write the register with values to the device.
Parameters
----------
mode :
* 'default' use the values from parent.setup.result.regs.dump
* type(mode) == list : use mode as a list (not yet implemented)
compare :
* 'cache' : compare with the Register cache value and write if orginal different from last cache value (faster as to read the register value)
* True : write only if value different from actual values
* False : write always
"""
result = 0
start = False
if not hasattr(self, 'parent') or not hasattr(self, 'result') or not hasattr(self.result, 'regs'):
self.logger.log_message(LogLevel.Warning(), f"{self.__class__}.regDumpSave2DUT: no setup.result.regs found, could'nt write back the original register values")
return -1
if type(mode) is list:
dump = mode
elif mode == 'default' and 'dump' in self.result.regs:
dump = self.result.regs.dump
# dump = self.result.regs.dump.keys() # TODO: bei hana überpruefen, so war es bei HANA!!
elif mode == 'default' and 'dump' in self.result.regs.keys():
dump = self.result.regs.dump.values('addr')
dump = self.result.regs.dump
else:
self.logger.log_message(LogLevel.Error(), f'{self.instName}.reg_dump_load: mode == {mode} is not available')
return
for reg in dump:
if reg is str and not self.parent.regs.register[reg]._rw: # TODO: check rw if a real rw-information
continue
addr = -1
if type(mode) is not list:
if type(reg) is dict or type(reg) is dotdict:
originial = common.str2num(tuple(reg.values())[0]['dat'])
addr = common.str2num(tuple(reg.values())[0]['addr'])
else:
originial = common.str2num(self.result.regs.dump.value(reg)['dat'])
else:
self.logger.log_message(LogLevel.Error(), '{self.instName}.regDumpSave2DUT: sorry this mode is not implemented yet, please investigate')
if compare == 'cache' and addr == -1:
actual = self.parent.regs.register[reg].value
elif addr == -1:
actual = self.parent.regs.register[reg].read()
else: # no cache available... have to be read to get the value
actual = self.parent.regs.readreg(addr)
if not compare or actual != originial:
if not start:
self.logger.log_message(LogLevel.Info(), f'{self.instName}.regDumpSave2DUT: some values have been changed in the tests:')
self.logger.log_message(LogLevel.Info(), f' write back originial register values {reg} actual={hex(actual)}')
start = True
if addr == -1:
self.parent.regs.register[reg].write(originial)
else:
self.parent.regs.writereg(addr, originial)
if not start:
self.logger.log_message(LogLevel.Info(), f'{self.instName}.regDumpSave2DUT: no register values changed in the tests')
return result
[docs]
def close(self):
"""Write EEPROM/NVRAM with the rescue values and close all instruments.
Close all instruments and write the dictionary to the log-file.
Returns
-------
None.
"""
if not self.running: # nothing to do, already closed
return
if hasattr(self, 'regs') and hasattr(self.regs, 'wrbackdump') and self.regs.wrbackdump:
try:
self.regDumpSave2DUT() # write the orginal data to the device only if cache value different
except Exception:
self.logger.log_message(LogLevel.Error(), "setup.close(): Couln't execute reg_dump_load")
self.running = False
self._write()
self.logger.log_message(LogLevel.Info(), "setup closed")
def _write(self):
"""Write the dictionary to the logfile."""
# self.__dict__.pop('init')
with open(os.getenv('PROJECT_PATH') + "output" + os.sep + self._RESULT, 'w') as outfile:
outfile.write('{')
self.jsondump(outfile, self.setup)
outfile.write(' ,\n')
self.jsondump(outfile, 'result')
# json.dump(self.setup, outfile, indent=2) # json.dump(self.result, outfile, indent=2) # sort_keys=True
outfile.write('\n}')
self.logger.log_message(LogLevel.Info(), f'write results to {self._RESULT}')
[docs]
def jsondump(self, file, dictionary, ident=4):
'''dump the dictionary to json-format
you can also use json.dump but I think this generated output-format is better for easy reading
'''
def space(ident, lenght=2):
if lenght < 2 and ident > 4:
return
for i in range(0, ident):
file.write(' ')
end = ''
spara = '{'
if type(dictionary) is str:
space(ident, 3)
file.write(f'"{dictionary}": {spara}')
dictionary = self.__dict__[dictionary]
end = '}'
ident = 8
space(ident, 3)
length = len(dictionary)
index = 0
more = ','
cr = '\n'
if length < 2 and ident > 4:
cr = ''
else:
pass
file.write(f'{cr}')
for item in dictionary:
index += 1
if index == length:
more = ''
if type(dictionary) in [dict, dotdict]:
value = dictionary[item]
else:
value = dictionary[index-1]
spara = '{'
epara = '}'
if type(value) in [list, diclist]:
spara = '['
epara = ']'
if type(value) in [dict, dotdict, list, diclist]:
space(ident, length)
try:
if item == value and type(item) is dict: # is it a list with dictionaries
json.dump(item, file)
file.write(f'{more}{cr}')
elif item == value: # it is a list with dotdictionaries
file.write(f'{spara}')
self.jsondump(file, value, ident+4)
file.write(f'{epara}{more}{cr}')
else: # it is dict or dotdict
file.write(f'"{item}": {spara}')
self.jsondump(file, value, ident+4)
file.write(f'{epara}{more}{cr}')
except Exception:
file.write(f"ERROR!!!: coudn't write {item} as json dump {more}{cr}")
else:
if type(value) is str:
value = f'"{value.replace(os.sep, "/")}"'
space(ident, length)
if item != value:
file.write(f'"{item}": {value}{more}{cr}')
else:
file.write(f'{value}{more}{cr}')
if cr != '':
space(ident-4, length)
file.write(f'{end}')
def __repr__(self):
return f"{self.__class__}"
[docs]
def set_configuration_values(self, data):
"""Only empty dummy function."""
self.logger.log_message(LogLevel.Warning(), 'Semi-ATE Labor.ProjectSetup: set_configuration_values only dummy function..................')
pass
def do_fetch(self, idnr):
if idnr != 1:
self.logger.log_message(LogLevel.Error(), f'The projectsetup modul supports only one id, but get id number={idnr}')
pass
def apply_configuration(self, data):
if 'Network prefix' in data and data['Network prefix'] != '' and os.name == "nt":
self.network = data['Network prefix']
os.environ['NETWORK'] = self.network
config = environment.replaceEnvs(data)
project_path = os.environ['PROJECT_PATH']
harness = ''
working_dir = ''
if 'working directory' in config and config['working directory'] != '':
for path in config['working directory'].split(';'):
if os.path.exists(path):
working_dir = path
if working_dir == '':
working_dir = str(Path(os.environ['PROJECT_PATH']).parent) + os.sep
os.environ['WORKING_DIR'] = working_dir
self.logger.log_message(LogLevel.Info(), f'Semi-ATE Labor.ProjectSetup: WORKING_DIR = {working_dir}')
self.logger.log_message(LogLevel.Info(), f'$LOGGINGFILENAME$ {project_path}log/;{self.logger.get_log_file_information()["filename"]}')
if 'add path' in config and config['add path'] != '':
harness = config['add path']
environment.environ_getpath(self, 'registermaster') # replace environment for registermaster if os='nt'
harness = working_dir + harness
sys.path.append(working_dir)
os.environ['HARNESS'] = harness
data['Network prefix'] = self.network
data['working directory'] = working_dir
self.logger.log_message(LogLevel.Info(), f'Semi-ATE Labor.ProjectSetup: apply_configuration {config}')
setupfile = config['filename'] if 'filename' in config and config['filename'] != '' else None
readonly = True
if setupfile is None:
setupfile = file_io.replaceFilename(f'$HARNESS/{self._SETUPFILE}')
readonly = False
if os.path.isfile(setupfile):
with file_io.openFile(setupfile, 'r') as file:
try:
self.setup = json.load(file, cls=JsonDecoder)
except Exception as error:
self.logger.error(f"{self.instName}: syntax error in {setupfile} : {error}") # TODO!: add json validator: pip install jsonschema
sys.exit()
self._replaceSomeThing(self.setup) # replace path-variables if windows, replace env-variable with their values
else:
self.setup = {'Setupfile': None}
level = LogLevel.Warning() if setupfile is None else LogLevel.Error()
self.logger.log_message(level, "Semi-ATE Labor.ProjectSetup: setup file not exist !!")
setupfile = None
self.create_dotdic(self.setup, self)
self.setup = dotdict({})
self._setupfile = setupfile
self.mylastdotdic = None
self.lastresult = None
self.lastmacro = None
self.running = False
# if not readonly:
if True:
self._configsave2setup()
self.result = dotdict([])
if __name__ == '__main__':
from ATE.common.logger import Logger
logger = Logger('logger')
jsonSetupFile = 'your_setup_json_file.json'
setup = ProjectSetup(logger, jsonSetupFile)
print(setup.result.regs.dump.keys())
setup.initialization()
print(setup.init.smu)
print(setup.init.matrix)
setup.write('regs', 'EEPROM1', 5)
setup.write('regs', 'EEPROM2', 15)
setup.write('empty', 'Idontknow', 'test')
print(setup.result.instruments)
print(setup.result.regs)
print(type(setup.result.regs))
print(setup.result.regs.keys())
setup.result.regs.value('EEPROM2')
setup.result.regs.value('Mytest')
setup.result.regs.value()
setup.macro.hwid.run()
setup.close()