def check_telnet_hooks(scpi_obj): _print_header("Telnet hooks") try: ipv4 = Telnet("127.0.0.1", 5025) ipv6 = Telnet("::1", 5025) cmd = "*IDN?" def hook(who, what): _print_info("\t\thook call, received: ({0!r}, {1!r})" "".format(who, what)) scpi_obj.addConnectionHook(hook) _print_info("\tipv4 send {0}".format(cmd)) ipv4.write(cmd) _print_info("\tipv4 answer {0!r}".format(ipv4.read_until('\n'))) _print_info("\tipv6 send {0}".format(cmd)) ipv6.write(cmd) _print_info("\tipv6 answer {0!r}".format(ipv6.read_until('\n'))) scpi_obj.removeConnectionHook(hook) ipv4.close() ipv6.close() result = True, "Telnet hooks test PASSED" except Exception as exc: print("\tUnexpected kind of exception! {0}".format(exc)) print_exc() result = False, "Telnet hooks test FAILED" _print_footer(result[1]) return result
def check_write_without_params(scpi_obj): _print_header("Attribute write without parameters") try: cmd = 'writter:without:parameters' switch = WattrTest() scpi_obj.add_command(cmd, read_cb=switch.switchTest) correct, failed = 0, 0 for i in range(3): cmd = "{0}{1}".format(cmd, " "*i) try: answer = _send2input(scpi_obj, cmd, expected_answer='ACK\r\n') except ValueError as exc: msg = "Error: {0}".format(exc) failed += 1 else: msg = "Answer: {0!r} (len ({1:d})" \ "".format(answer, len(answer)) correct += 1 print("\tRequest {0!r}\n\t{1}\n".format(cmd, msg)) if failed == 0: result = True, "Write without parameters test PASSED" else: print("Failed {0}/{1}".format(failed, correct+failed)) result = False, "Write without parameters test FAILED" except Exception as exc: print("\tUnexpected kind of exception! {0}".format(exc)) print_exc() result = False, "Write without parameters test FAILED" _print_footer(result[1]) return result
def add_invalid_cmds(scpi_obj): _print_header("Testing to build invalid commands") try: scpi_obj.add_command(":startswithcolon", read_cb=None) except NameError as exc: print("\tNull name test PASSED") except Exception as exc: print("\tUnexpected kind of exception! {0}".format(exc)) print_exc() return False, "Invalid commands test FAILED" try: scpi_obj.add_command("double::colons", read_cb=None) except NameError: print("\tDouble colon name test PASSED") except Exception as exc: print("\tUnexpected kind of exception! {0}".format(exc)) print_exc() return False, "Invalid commands test FAILED" try: scpi_obj.add_command("nestedSpecial:*special", read_cb=None) except NameError: scpi_obj.command_tree.pop('nestedSpecial') print("\tNested special command test PASSED") except Exception as exp: print("\tUnexpected kind of exception! {0}".format(exc)) print_exc() return False, "Invalid commands test FAILED" result = True, "Invalid commands test PASSED" _print_footer(result[1]) return result
def check_wo_special_cmds(scpi_obj): _print_header("Test Write Only special commands") wilco = "wilco\r\n" commands = [['SHT', sht, wilco], ['RST', rst, wilco], ['RAP', rap, wilco]] correct, failed = 0, 0 for cmd_name, write_cb, expected_answer in commands: try: scpi_obj.add_special_command(cmd_name, read_cb=None, write_cb=write_cb) answer = '' start_t = _time() answer = _send2input( scpi_obj, "*{0}".format(cmd_name), expected_answer=expected_answer) correct += 1 except ValueError as exc: print("\tSpecial command {0} answer failed: {0}" "".format(cmd_name, exc)) failed += 1 except Exception as exc: print("\tUnexpected kind of exception! {0}".format(exc)) print_exc() failed += 1 print("\tWrite Only special command *{0}\n" "\tAnswer: {1!r} ({2:g} ms)" "".format(cmd_name, answer, (_time()-start_t)*1000)) if failed == 0: result = True, "Write Only special commands test PASSED" else: print("Failed {0}/{1}".format(failed, correct+failed)) result = False, "Write Only special commands test FAILED" _print_footer(result[1]) return result
def check_locks(scpi_obj): _print_header("system [write]lock") try: LockThreadedTest(scpi_obj).launch_test() result = True, "system [write]lock test PASSED" except Exception as exc: print("\tUnexpected kind of exception! {0}".format(exc)) print_exc() result = False, "system [write]lock test FAILED" _print_footer(result[1]) return result
def check_nonexisting_commands(scpi_obj): _print_header("Testing to query commands that doesn't exist") base_cmd = _random_choice(['SOURce', 'BASIcloop', 'ITERative']) sub_cmd = _random_choice(['CURRent', 'VOLTage']) attr = _random_choice(['UPPEr', 'LOWEr', 'VALUe']) fake = "FAKE" ack = 'ACK\r\n' nok = 'NOK\r\n' start_t = _time() pairs = [ # * first level doesn't exist ["{0}:{1}:{2}?".format(fake, sub_cmd, attr), nok], # * intermediate level doesn't exist ["{0}:{1}:{2}?".format(base_cmd, fake, attr), nok], # * Attribute level doesn't exist ["{0}:{1}:{2}?".format(base_cmd, sub_cmd, fake), nok], # * Attribute that doesn't respond ['source:voltage:exception?', nok], # * Unexisting Channel ["CHANnel{0}".format(str(n_channels+3).zfill(2)), nok], # * Channel below the minimum reference ["CHANnel00:VOLTage:UPPEr?", nok], # * Channel above the maximum reference ["CHANnel99:VOLTage:UPPEr?", nok], ] correct, failed = 0, 0 for cmd, expected_answer in pairs: answer = '' try: start_t = _time() answer = _send2input( scpi_obj, cmd, expected_answer=expected_answer) correct += 1 except ValueError as exc: print("\tFake command answer failed: {0}".format(exc)) failed += 1 except Exception as exc: print("\tUnexpected kind of exception! {0}".format(exc)) print_exc() failed += 1 print("\tRequest non-existing command {0}\n" "\tAnswer: {1!r} ({2:g} ms)" "".format(cmd, answer, (_time()-start_t)*1000)) if failed == 0: result = True, "Non-existing commands test PASSED" else: print("Failed {0}/{1}".format(failed, correct+failed)) result = False, "Non-existing commands test FAILED" _print_footer(result[1]) return result
def check_array_answers(scpi_obj): _print_header("Requesting an attribute the answer of which is an array") try: base_cmd = 'source' attr_cmd = 'buffer' long_test = ArrayTest(100) scpi_obj.add_command(attr_cmd, read_cb=long_test.readTest) # current current_obj = ArrayTest(5) current_cmd = "{0}:current:{1}".format(base_cmd, attr_cmd) scpi_obj.add_command(current_cmd, read_cb=current_obj.readTest) # voltage voltage_obj = ArrayTest(5) voltage_cmd = "{0}:voltage:{1}".format(base_cmd, attr_cmd) scpi_obj.add_command(voltage_cmd, read_cb=voltage_obj.readTest) # queries answers_lengths = {} correct, failed = 0, 0 for cmd in [attr_cmd, current_cmd, voltage_cmd]: for format in ['ASCII', 'QUADRUPLE', 'DOUBLE', 'SINGLE', 'HALF']: _send2input(scpi_obj, "DataFormat {0}".format(format), check_answer=False) answer = None try: answer = _send2input( scpi_obj, cmd + '?', bad_answer='NOK\r\n') except ValueError as exc: msg = "Error: {0}".format(exc) failed += 1 else: msg = "Answer: {0!r} (len ({1:d})" \ "".format(answer, len(answer)) correct += 1 print("\tRequest {0!r}\n\t{1}\n".format(cmd, msg)) if format not in answers_lengths: answers_lengths[format] = [] answers_lengths[format].append( len(answer) if answer is not None else 0) print("\tanswer lengths summary: {0}".format( "".join('\n\t\t{0}:{1}'.format(k, v) for k, v in answers_lengths.iteritems()))) if failed == 0: result = True, "Array answers test PASSED" else: print("Failed {0}/{1}".format(failed, correct+failed)) result = False, "Array answers test FAILED" except Exception as e: print("\tUnexpected kind of exception! {0}".format(e)) print_exc() result = False, "Array answers test FAILED" _print_footer(result[1]) return result
def check_command_queries(scpi_obj): _print_header("Testing to command queries") try: print("Launch tests:") cmd = "*IDN?" answer = _send2input(scpi_obj, cmd) print("\tInstrument identification ({0})\n\tAnswer: {1}" "".format(cmd, answer)) for base_cmd in ['SOURce', 'BASIcloop', 'ITERative']: _print_header("Check {0} part of the tree".format(base_cmd)) _do_check_commands(scpi_obj, base_cmd) for ch in range(1, n_channels+1): base_cmd = "CHANnel{0}".format(str(ch).zfill(2)) _print_header("Check {0} part of the tree".format(base_cmd)) _do_check_commands(scpi_obj, base_cmd) fn = _random_choice(range(1, n_subchannels+1)) inner_cmd = "FUNCtion{0}".format(str(fn).zfill(2)) _print_header("Check {0} + MEAS:{1} part of the tree" "".format(base_cmd, inner_cmd)) _do_check_commands(scpi_obj, base_cmd, inner_cmd) result = True, "Command queries test PASSED" except Exception as exc: print("\tUnexpected kind of exception! {0}".format(e)) print_exc() result = False, "Command queries test FAILED" _print_footer(result[1]) return result
def check_multiple_commands(scpi_obj): _print_header("Requesting more than one attribute per query") try: log = {} correct, failed = 0, 0 for i in range(2, concatenated_cmds+1): lst = [] for j in range(i): bar = _build_command2test() lst.append(bar) cmds = ";".join(x for x in lst) cmds_repr = "".join("\t\t{0}\n".format(cmd) for cmd in cmds.split(';')) start_t = _time() answer = _send2input(scpi_obj, cmds) answers = _cut_multiple_answer(answer) n_answers = len(answers) if '' in answers or 'ACK' in answers or 'NOK' in answers: failed += 1 else: correct += 1 log[n_answers] = (_time() - start_t)*1000 print("\tRequest {0:d} attributes in a single query: \n" "{1}\tAnswer: {2!r} ({3:d}, {4:g} ms)\n" "".format(i, cmds_repr, answer, n_answers, log[n_answers])) if n_answers != i: raise AssertionError( "The answer doesn't have the {0:d} expected elements " "(but {1:d})" "".format(i, n_answers)) _inter_test_wait() msg = "\tSummary:" for length in log: t = log[length] msg += "\n\t\t{0}\t{1:6.3f} ms\t{2:6.3f} ms/cmd" \ "".format(length, t, t/length) print(msg) if failed == 0: result = True, "Many commands per query test PASSED" else: print("Failed {0}/{1}".format(failed, correct+failed)) result = False, "Many commands per query test FAILED" # TODO: multiple writes except Exception as exc: print("\tUnexpected kind of exception! {0}".format(exc)) print_exc() result = False, "Many commands per query test FAILED" _print_footer(result[1]) return result
def check_idn(scpi_obj): _print_header("Test instrument identification") try: identity = InstrumentIdentification('ALBA', 'test', 0, _version()) scpi_obj.add_special_command('IDN', identity.idn) cmd = "*idn?" answer = _send2input(scpi_obj, cmd) print("\tRequest identification: {0}\n\tAnswer: {1!r}" "".format(cmd, answer)) if answer.strip() != identity.idn(): result = False, "Identification test FAILED" else: result = True, "Identification test PASSED" except Exception as exp: print("\tUnexpected kind of exception! {0}".format(exp)) print_exc() result = False, "Identification test FAILED" _print_footer(result[1]) return result
def lock_take(lock_obj): test_name = "Initial state test" _print_header("Test the initial state of the {} object".format(lock_obj)) _print_info("{!r}".format(lock_obj), 1) _print_info("Check if it is lock", level=1, top=True) if lock_obj.isLock(): return False, "{} FAILED".format(test_name) _print_info("{} is not lock".format(lock_obj), level=1, bottom=True) _print_info("Check if it lock can be requested", level=1, top=True) if not lock_obj.request(): return False, "{} FAILED".format(test_name) _print_info("{!r} is now lock".format(lock_obj), level=1, bottom=True) _print_info("Check if it lock can be released", level=1, top=True) if not lock_obj.release(): return False, "{} FAILED".format(test_name) _print_info("{!r} is now released".format(lock_obj), level=1, bottom=True) return True, "{} PASSED".format(test_name)
def check_read_with_params(scpi_obj): _print_header("Attribute read with parameters after the '?'") try: cmd = 'reader:with:parameters' long_test = ArrayTest(100) scpi_obj.add_command(cmd, read_cb=long_test.readRange) answer = _send2input(scpi_obj, "DataFormat ASCII", check_answer=False) correct, failed = 0, 0 for i in range(10): bar, foo = _randint(0, 100), _randint(0, 100) start = min(bar, foo) end = max(bar, foo) # introduce a ' ' (write separator) after the '?' (read separator) cmd_with_params = "{0}?{1:>3},{2}".format(cmd, start, end) try: answer = _send2input( scpi_obj, cmd_with_params, bad_answer='NOK\r\n') except ValueError as exc: msg = "Error: {0}".format(exc) failed += 1 else: msg = "Answer: {0!r} (len ({1:d})" \ "".format(answer, len(answer)) correct += 1 print("\tRequest {0!r}\n\t{1}\n".format(cmd_with_params, msg)) if answer is None or len(answer) == 0: raise ValueError("Empty string") cmd_with_params = "{0}?{1},{2}".format(cmd, start, end) if failed == 0: result = True, "Read with parameters test PASSED" else: print("Failed {0}/{1}".format(failed, correct+failed)) result = False, "Read with parameters test FAILED" except Exception as exc: print("\tUnexpected kind of exception! {0}".format(exc)) print_exc() result = False, "Read with parameters test FAILED" _print_footer(result[1]) return result
def test_scpi(debug, pause, no_remove): start_t = _time() _print_header("Testing scpi main class (version {0})".format(_version())) # ---- BuildSpecial('IDN',specialSet,identity.idn) with scpi(local=True, debug=debug, write_lock=True) as scpi_obj: print("Log information: {0}".format(scpi_obj.logging_file())) results = [] result_msgs = [] try: for test in [ check_idn, check_wo_special_cmds, add_invalid_cmds, add_valid_commands, check_command_queries, check_command_writes, check_nonexisting_commands, check_array_answers, check_multiple_commands, check_read_with_params, check_write_without_params, # check_locks, # check_telnet_hooks, ]: result, msg = test(scpi_obj) results.append(result) tag, value = msg.rsplit(' ', 1) result_msgs.append([tag, value]) if _after_test_wait(pause) is False: break except KeyboardInterrupt: print("Test interrupted...") txt = "Tests completed (Ctrl+c to print the summary and end)" _after_test_wait(no_remove, msg=txt, wait_time=0) if all(results): _print_header("All tests passed: everything OK ({:g} s)" "".format(_time()-start_t)) else: _print_header("ALERT!! NOT ALL THE TESTS HAS PASSED. Check the list " "({:g} s)".format(_time()-start_t)) length = 0 for pair in result_msgs: if len(pair[0]) > length: length = len(pair[0]) for result in result_msgs: print("{0}{1}\t{2}{3}".format( result[0], " "*(length-len(result[0])), result[1], " *" if result[1] == 'FAILED' else "")) print("")
def multithreading_take(lock_obj): def send_event(event_lst, who): event_lst[who].set() while event_lst[who].isSet(): # wait to the thread to work _sleep(1) test_name = "Lock take test" _print_header("{} for {}".format(test_name, lock_obj)) joiner_event = _Event() joiner_event.clear() user_threads = [] request_events = [] access_events = [] release_events = [] print_lock = _Lock() for i in range(2): request_event = _Event() access_event = _Event() release_event = _Event() user_thread = _Thread(target=thread_function, args=(lock_obj, joiner_event, request_event, access_event, release_event, print_lock), name='{:d}'.format(i)) request_events.append(request_event) access_events.append(access_event) release_events.append(release_event) user_threads.append(user_thread) user_thread.start() # here is where the test starts --- try: _print_info("Initial state {!r}\n".format(lock_obj), level=1, lock=print_lock) if lock_obj.isLock(): return False, "{} FAILED".format(test_name) _print_info("Tell the threads to access", level=1, lock=print_lock, top=True) send_event(access_events, 0) send_event(access_events, 1) _print_info("both should have had access", level=1, lock=print_lock, bottom=True) _print_info("Thread 0 take the lock", level=1, lock=print_lock, top=True) send_event(request_events, 0) if not lock_obj.isLock() or lock_obj.owner != '0': raise Exception("It shall be lock by 0") _print_info("Tell the threads to access", level=1, lock=print_lock) send_event(access_events, 0) send_event(access_events, 1) _print_info("0 should, but 1 don't", level=1, lock=print_lock, bottom=True) _print_info("Try to lock when it is already", level=1, lock=print_lock, top=True) send_event(request_events, 1) if not lock_obj.isLock() or lock_obj.owner != '0': raise Exception("It shall be lock by user 0") _print_info("Tell the threads to access", level=1, lock=print_lock) send_event(access_events, 0) send_event(access_events, 1) _print_info("0 should, but 1 don't", level=1, lock=print_lock, bottom=True) _print_info("Try to release by a NON-owner", level=1, lock=print_lock, top=True) send_event(release_events, 1) if not lock_obj.isLock() or lock_obj.owner != '0': raise Exception("It shall be lock by user 0") _print_info("Tell the threads to access", level=1, lock=print_lock) send_event(access_events, 0) send_event(access_events, 1) _print_info("0 should, but 1 don't", level=1, lock=print_lock, bottom=True) _print_info("release the lock", level=1, lock=print_lock, top=True) send_event(release_events, 0) if lock_obj.isLock(): raise Exception("It shall be released") _print_info("Tell the threads to access", level=1, lock=print_lock) send_event(access_events, 0) send_event(access_events, 1) _print_info("both should have had to", level=1, lock=print_lock, bottom=True) # TODO: timeout _print_info("Thread 1 take the lock and expire it", level=1, lock=print_lock, top=True) send_event(request_events, 1) if not lock_obj.isLock() or lock_obj.owner != '1': raise Exception("It shall be lock by 1") _print_info("Tell the threads to access", level=1, lock=print_lock) send_event(access_events, 0) send_event(access_events, 1) _print_info("1 should, but 0 don't", level=1, lock=print_lock) _print_info("Sleep {:d} seconds to expire the lock".format( TEST_EXPIRATION_TIME), level=1, lock=print_lock) _sleep(TEST_EXPIRATION_TIME) _print_info("Tell the threads to access", level=1, lock=print_lock) send_event(access_events, 0) send_event(access_events, 1) _print_info("both should have had to", level=1, lock=print_lock, bottom=True) answer = True, "{} PASSED".format(test_name) except Exception as e: print(e) print_exc() answer = False, "{} FAILED".format(test_name) joiner_event.set() while len(user_threads) > 0: user_thread = user_threads.pop() user_thread.join(1) if user_thread.is_alive(): user_threads.append(user_thread) print("All threads has finished") return answer
def check_command_writes(scpi_obj): _print_header("Testing to command writes") try: # simple commands --- current_conf_obj = WattrTest() scpi_obj.add_command('source:current:configure', read_cb=current_conf_obj.readTest, write_cb=current_conf_obj.writeTest) voltage_conf_obj = WattrTest() scpi_obj.add_command('source:voltage:configure', read_cb=voltage_conf_obj.readTest, write_cb=voltage_conf_obj.writeTest) for inner in ['current', 'voltage']: _do_write_command(scpi_obj, "source:{0}:configure".format(inner)) _wait(1) # FIXME: remove # channel commands --- _print_header("Testing to channel command writes") base_cmd = 'writable' w_obj = scpi_obj.add_component(base_cmd, scpi_obj.command_tree) ch_cmd = 'channel' ch_obj = scpi_obj.add_channel(ch_cmd, n_channels, w_obj) ch_current_obj = WchannelTest(n_channels) ch_voltage_obj = WchannelTest(n_channels) for (subcomponent, sub_cmd_obj) in [('current', ch_current_obj), ('voltage', ch_voltage_obj)]: subcomponent_obj = scpi_obj.add_component(subcomponent, ch_obj) for (attr_name, attr_func) in [('upper', 'upperLimit'), ('lower', 'lowerLimit'), ('value', 'readTest')]: if hasattr(sub_cmd_obj, attr_func): if attr_name == 'value': attr_obj = scpi_obj.add_attribute( attr_name, subcomponent_obj, read_cb=sub_cmd_obj.readTest, write_cb=sub_cmd_obj.writeTest, default=True) else: cb_func = getattr(sub_cmd_obj, attr_func) attr_obj = scpi_obj.add_attribute( attr_name, subcomponent_obj, cb_func) print("\nChecking one write multiple reads\n") for i in range(n_channels): rnd_ch = _randint(1, n_channels) element = _random_choice(['current', 'voltage']) _do_write_channel_command( scpi_obj, "{0}:{1}".format(base_cmd, ch_cmd), rnd_ch, element, n_channels) _inter_test_wait() print("\nChecking multile writes multiple reads\n") for i in range(n_channels): test_nwrites = _randint(2, n_channels) rnd_chs = [] while len(rnd_chs) < test_nwrites: rnd_ch = _randint(1, n_channels) while rnd_ch in rnd_chs: rnd_ch = _randint(1, n_channels) rnd_chs.append(rnd_ch) element = _random_choice(['current', 'voltage']) values = [_randint(-1000, 1000)]*test_nwrites _do_write_channel_command( scpi_obj, "{0}:{1}".format(base_cmd, ch_cmd), rnd_chs, element, n_channels, values) _inter_test_wait() print("\nChecking write with allowed values limitation\n") selection_cmd = 'source:selection' selection_obj = WattrTest() selection_obj.writeTest(False) scpi_obj.add_command(selection_cmd, read_cb=selection_obj.readTest, write_cb=selection_obj.writeTest, allowed_argins=[True, False]) _do_write_command(scpi_obj, selection_cmd, True) # _do_write_command(scpi_obj, selection_cmd, 'Fals') # _do_write_command(scpi_obj, selection_cmd, 'True') try: _do_write_command(scpi_obj, selection_cmd, 0) except Exception: print("\tLimitation values succeed because it raises an exception " "as expected") else: raise AssertionError("It has been write a value that " "should not be allowed") _inter_test_wait() result = True, "Command writes test PASSED" except Exception as exc: print("\tUnexpected kind of exception! {0}".format(exc)) print_exc() result = False, "Command writes test FAILED" _print_footer(result[1]) return result
def add_valid_commands(scpi_obj): _print_header("Testing to build valid commands") try: # ---- valid commands section current_obj = AttrTest() voltage_obj = AttrTest() # * commands can de added by telling their full name: scpi_obj.add_command('source:current:upper', read_cb=current_obj.upperLimit, write_cb=current_obj.upperLimit) scpi_obj.add_command('source:current:lower', read_cb=current_obj.lowerLimit, write_cb=current_obj.lowerLimit) scpi_obj.add_command('source:current:value', read_cb=current_obj.readTest, default=True) scpi_obj.add_command('source:voltage:upper', read_cb=voltage_obj.upperLimit, write_cb=voltage_obj.upperLimit) scpi_obj.add_command('source:voltage:lower', read_cb=voltage_obj.lowerLimit, write_cb=voltage_obj.lowerLimit) scpi_obj.add_command('source:voltage:value', read_cb=voltage_obj.readTest, default=True) scpi_obj.add_command('source:voltage:exception', read_cb=voltage_obj.exceptionTest) # * They can be also created in an iterative way base_cmd_name = 'basicloop' for (sub_cmd_name, sub_cmd_obj) in [('current', current_obj), ('voltage', voltage_obj)]: for (attr_name, attr_func) in [('upper', 'upperLimit'), ('lower', 'lowerLimit'), ('value', 'readTest')]: if hasattr(sub_cmd_obj, attr_func): cb_func = getattr(sub_cmd_obj, attr_func) if attr_name == 'value': default = True else: default = False scpi_obj.add_command("{0}:{1}:{2}".format( base_cmd_name, sub_cmd_name, attr_name), read_cb=cb_func, default=default) # Basically is the same than the first example, # but the add_command is constructed with variables # in nested loops # * Another alternative to create the tree in an iterative way would be it_cmd = 'iterative' it_obj = scpi_obj.add_component(it_cmd, scpi_obj.command_tree) for (subcomponent, sub_cmd_obj) in [('current', current_obj), ('voltage', voltage_obj)]: subcomponent_obj = scpi_obj.add_component(subcomponent, it_obj) for (attr_name, attr_func) in [('upper', 'upperLimit'), ('lower', 'lowerLimit'), ('value', 'readTest')]: if hasattr(sub_cmd_obj, attr_func): cb_func = getattr(sub_cmd_obj, attr_func) if attr_name == 'value': default = True else: default = False attr_obj = scpi_obj.add_attribute( attr_name, subcomponent_obj, cb_func, default=default) else: print("{0} hasn't {1}".format(subcomponent_obj, attr_func)) # In this case, the intermediate objects of the tree are # build and it is in the inner loop where they have the # attributes created. # * Use with very big care this option because the library # * don't guarantee that all the branches of the tree will # * have the appropriate leafs. # * Example of how can be added a node with channels in the scpi tree ch_cmd = 'channel' ch_obj = scpi_obj.add_channel( ch_cmd, n_channels, scpi_obj.command_tree) ch_current_obj = ChannelTest(n_channels) ch_voltage_obj = ChannelTest(n_channels) for (subcomponent, sub_cmd_obj) in [('current', ch_current_obj), ('voltage', ch_voltage_obj)]: subcomponent_obj = scpi_obj.add_component(subcomponent, ch_obj) for (attr_name, attr_func) in [('upper', 'upperLimit'), ('lower', 'lowerLimit'), ('value', 'readTest')]: if hasattr(sub_cmd_obj, attr_func): cb_func = getattr(sub_cmd_obj, attr_func) if attr_name == 'value': default = True else: default = False attr_obj = scpi_obj.add_attribute( attr_name, subcomponent_obj, cb_func, default=default) # * Example of how can be nested channel type components in a tree that # already have this channels componets defined. meas_cmd = 'measurements' meas_obj = scpi_obj.add_component(meas_cmd, ch_obj) fn_cmd = 'function' fn_obj = scpi_obj.add_channel(fn_cmd, n_subchannels, meas_obj) chfn_current_obj = SubchannelTest(n_channels, n_subchannels) chfn_voltage_obj = SubchannelTest(n_channels, n_subchannels) for (subcomponent, sub_cmd_obj) in [('current', chfn_current_obj), ('voltage', chfn_voltage_obj)]: subcomponent_obj = scpi_obj.add_component(subcomponent, fn_obj) for (attr_name, attr_func) in [('upper', 'upperLimit'), ('lower', 'lowerLimit'), ('value', 'readTest')]: if hasattr(sub_cmd_obj, attr_func): cb_func = getattr(sub_cmd_obj, attr_func) if attr_name == 'value': default = True else: default = False attr_obj = scpi_obj.add_attribute( attr_name, subcomponent_obj, cb_func, default=default) print("Command tree build: {!r}".format(scpi_obj.command_tree)) result = True, "Valid commands test PASSED" # TODO: channels with channels until the attributes except Exception as exc: print("\tUnexpected kind of exception! {0}".format(exc)) print_exc() result = False, "Valid commands test FAILED" _print_footer(result[1]) return result