From 452a683ff56a16c1718ea8ffdafe0819a3095159 Mon Sep 17 00:00:00 2001 From: Sveto Krchnavy Date: Thu, 30 Nov 2017 12:00:58 +0100 Subject: [PATCH 01/20] support for getters and setters (as tupple) into Session.attrs --- pyvisa-py/sessions.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/pyvisa-py/sessions.py b/pyvisa-py/sessions.py index 6053d975..cbf514f9 100644 --- a/pyvisa-py/sessions.py +++ b/pyvisa-py/sessions.py @@ -216,7 +216,12 @@ def get_attribute(self, attribute): # First try to answer those attributes that are common to all session types # or user defined because they are not defined by the interface. if attribute in self.attrs: - return self.attrs[attribute], constants.StatusCode.success + value = self.attrs[attribute] + status = constants.StatusCode.success + if isinstance(value, tuple): + getter = value[0] + value, status = getter(attribute) if getter else (0, constants.StatusCode.error_nonsupported_attribute) + return value, status elif attribute == constants.VI_ATTR_TMO_VALUE: return self.timeout, constants.StatusCode.success @@ -257,8 +262,12 @@ def set_attribute(self, attribute, attribute_state): # First try to answer those attributes that are common to all session types # or user defined because they are not defined by the interface. if attribute in self.attrs: - self.attrs[attribute] = attribute_state - return constants.StatusCode.success + value = self.attrs[attribute] + status = constants.StatusCode.success + if isinstance(value, tuple): + setter = value[1] + status = setter(attribute, attribute_state) if setter else constants.StatusCode.error_nonsupported_attribute + return status elif attribute == constants.VI_ATTR_TMO_VALUE: try: From b998891e3305b47854f3552bcb6a2f81e1cbd259 Mon Sep 17 00:00:00 2001 From: Sveto Krchnavy Date: Thu, 30 Nov 2017 15:12:46 +0100 Subject: [PATCH 02/20] updated handling of timeout in *Session objects --- pyvisa-py/gpib.py | 24 ++++++++++++++++++------ pyvisa-py/serial.py | 35 ++++++++++++----------------------- pyvisa-py/sessions.py | 42 +++++++++++++++++++++++++++++------------- pyvisa-py/tcpip.py | 10 +++++----- pyvisa-py/usb.py | 30 ++++++++++-------------------- 5 files changed, 74 insertions(+), 67 deletions(-) diff --git a/pyvisa-py/gpib.py b/pyvisa-py/gpib.py index 09e445a2..929f8a63 100644 --- a/pyvisa-py/gpib.py +++ b/pyvisa-py/gpib.py @@ -73,16 +73,21 @@ def after_parsing(self): pad = self.parsed.primary_address self.handle = gpib.dev(int(minor), int(pad)) self.interface = Gpib(self.handle) + attribute = getattr(constants, 'VI_ATTR_TMO_VALUE') + self.set_attribute(constants.VI_ATTR_TMO_VALUE, attributes.AttributesByID[attribute].default) - @property - def timeout(self): + def _get_timeout(self, attribute): # 0x3 is the hexadecimal reference to the IbaTMO (timeout) configuration # option in linux-gpib. - return TIMETABLE[self.interface.ask(3)] + timeout = self.interface.ask(3) + if timeout and timeout < len(TIMETABLE): + timeout = int(TIMETABLE[timeout]) + else: + timeout = constants.VI_TMO_INFINITE + return timeout, constants.StatusCode.success - @timeout.setter - def timeout(self, value): + def _set_timeout(self, attribute, value): """ linux-gpib only supports 18 discrete timeout values. If a timeout @@ -108,7 +113,14 @@ def timeout(self, value): 16 300 seconds 17 1000 seconds """ - self.interface.timeout(bisect(TIMETABLE, value)) + if value == constants.VI_TMO_INFINITE: + timeout = 0 + self.timeout = None + else: + timeout = min(bisect(TIMETABLE, value - value / 1000.0), 17) + self.timeout = TIMETABLE[timeout] / 1000.0 + self.interface.timeout(timeout) + return constants.StatusCode.success def close(self): gpib.close(self.handle) diff --git a/pyvisa-py/serial.py b/pyvisa-py/serial.py index 3e4cfb50..283e6c09 100644 --- a/pyvisa-py/serial.py +++ b/pyvisa-py/serial.py @@ -65,35 +65,24 @@ def after_parsing(self): else: cls = Serial - self.interface = cls(port=self.parsed.board, timeout=2000, write_timeout=2000) + self.interface = cls(port=self.parsed.board, timeout=self.timeout, write_timeout=2000) for name in ('ASRL_END_IN', 'ASRL_END_OUT', 'SEND_END_EN', 'TERMCHAR', 'TERMCHAR_EN', 'SUPPRESS_END_EN'): attribute = getattr(constants, 'VI_ATTR_' + name) self.attrs[attribute] = attributes.AttributesByID[attribute].default - @property - def timeout(self): - value = self.interface.timeout - - if value is None: - return constants.VI_TMO_INFINITE - elif value == 0: - return constants.VI_TMO_IMMEDIATE - else: - return int(value * 1000) - - @timeout.setter - def timeout(self, value): - if value == constants.VI_TMO_INFINITE: - value = None - elif value == constants.VI_TMO_IMMEDIATE: - value = 0 - else: - value = value / 1000. - - self.interface.timeout = value - self.interface.write_timeout = value + def _get_timeout(self): + if self.interface: + self.timeout = self.interface.timeout + return super(SerialSession, self)._get_timeout() + + def _set_timeout(self, attribute, value): + status = super(SerialSession, self)._set_timeout() + if self.interface: + self.interface.timeout = self.timeout + self.interface.write_timeout = self.timeout + return status def close(self): self.interface.close() diff --git a/pyvisa-py/sessions.py b/pyvisa-py/sessions.py index cbf514f9..52bebb5e 100644 --- a/pyvisa-py/sessions.py +++ b/pyvisa-py/sessions.py @@ -171,6 +171,9 @@ def __init__(self, resource_manager_session, resource_name, parsed=None, open_ti self.parsed = parsed self.open_timeout = open_timeout + #: get default timeout from constants + attribute = getattr(constants, 'VI_ATTR_TMO_VALUE') + self.timeout = attributes.AttributesByID[attribute].default / 1000.0 #: Used as a place holder for the object doing the lowlevel communication. self.interface = None @@ -181,7 +184,8 @@ def __init__(self, resource_manager_session, resource_name, parsed=None, open_ti self.attrs = {constants.VI_ATTR_RM_SESSION: resource_manager_session, constants.VI_ATTR_RSRC_NAME: str(parsed), constants.VI_ATTR_RSRC_CLASS: parsed.resource_class, - constants.VI_ATTR_INTF_TYPE: parsed.interface_type} + constants.VI_ATTR_INTF_TYPE: parsed.interface_type, + constants.VI_ATTR_TMO_VALUE: (self._get_timeout, self._set_timeout)} self.after_parsing() def after_parsing(self): @@ -223,9 +227,6 @@ def get_attribute(self, attribute): value, status = getter(attribute) if getter else (0, constants.StatusCode.error_nonsupported_attribute) return value, status - elif attribute == constants.VI_ATTR_TMO_VALUE: - return self.timeout, constants.StatusCode.success - # Dispatch to `_get_attribute`, which must be implemented by subclasses. try: @@ -269,14 +270,6 @@ def set_attribute(self, attribute, attribute_state): status = setter(attribute, attribute_state) if setter else constants.StatusCode.error_nonsupported_attribute return status - elif attribute == constants.VI_ATTR_TMO_VALUE: - try: - self.timeout = attribute_state - except: - return constants.StatusCode.error_nonsupported_attribute_state - - return constants.StatusCode.success - # Dispatch to `_set_attribute`, which must be implemented by subclasses. try: @@ -318,7 +311,8 @@ def _read(self, reader, count, end_indicator_checker, suppress_end_en, # NOTE: Some interfaces return not only a single byte but a complete block for each read # therefore we must handle the case that the termination character is in the middle of the block # or that the maximum number of bytes is exceeded - timeout = self.get_attribute(constants.VI_ATTR_TMO_VALUE)[0] / 1000. + timeout, _ = self.get_attribute(constants.VI_ATTR_TMO_VALUE) + timeout /= 1000.0 # Make sure termination_char is a string try: @@ -353,3 +347,25 @@ def _read(self, reader, count, end_indicator_checker, suppress_end_en, if time.time() - start > timeout: return out, constants.StatusCode.error_timeout + + def _get_timeout(self, attribute_name): + """ Returns timeout calculated value from python way to VI_ way + """ + if self.timeout is None: + ret_value = constants.VI_TMO_INFINITE + elif self.timeout == 0: + ret_value = constants.VI_TMO_IMMEDIATE + else: + ret_value = int(self.timeout * 1000.0) + return ret_value, constants.StatusCode.success + + def _set_timeout(self, attribute_name, new_value): + """ Sets timeout calculated value from python way to VI_ way + """ + if new_value == constants.VI_TMO_INFINITE: + self.timeout = None + elif new_value == constants.VI_TMO_IMMEDIATE: + self.timeout = 0 + else: + self.timeout = new_value / 1000.0 + return constants.StatusCode.success; diff --git a/pyvisa-py/tcpip.py b/pyvisa-py/tcpip.py index 47f7c67f..fde879aa 100644 --- a/pyvisa-py/tcpip.py +++ b/pyvisa-py/tcpip.py @@ -33,7 +33,6 @@ class TCPIPInstrSession(Session): """ lock_timeout = 1000 - timeout = 1000 client_id = None link = None max_recv_size = 1024 @@ -49,7 +48,6 @@ def after_parsing(self): self.interface = vxi11.CoreClient(self.parsed.host_address) self.lock_timeout = 10000 - self.timeout = 10000 self.client_id = random.getrandbits(31) error, link, abort_port, max_recv_size = self.interface.create_link( @@ -96,6 +94,8 @@ def read(self, count): else: term_char = flags = 0 + timeout, _ = self.get_attribute(constants.VI_ATTR_TMO_VALUE) + read_data = bytearray() reason = 0 end_reason = vxi11.RX_END | vxi11.RX_CHR @@ -103,7 +103,7 @@ def read(self, count): status = SUCCESS while reason & end_reason == 0: - error, reason, data = read_fun(self.link, chunk_length, self.timeout, + error, reason, data = read_fun(self.link, chunk_length, timeout, self.lock_timeout, flags, term_char) if error == vxi11.ErrorCodes.io_timeout: @@ -135,6 +135,7 @@ def write(self, data): send_end, _ = self.get_attribute(constants.VI_ATTR_SEND_END_EN) chunk_size = 1024 + timeout, _ = self.get_attribute(constants.VI_ATTR_TMO_VALUE) try: if send_end: @@ -152,7 +153,7 @@ def write(self, data): block = data[offset:offset + self.max_recv_size] error, size = self.interface.device_write( - self.link, self.timeout, self.lock_timeout, flags, block) + self.link, timeout, self.lock_timeout, flags, block) if error == vxi11.ErrorCodes.io_timeout: return offset, StatusCode.error_timeout @@ -319,7 +320,6 @@ class TCPIPSocketSession(Session): # Tis is valid for connect and read operations lock_timeout = 1000 - timeout = 1000 max_recv_size = 4096 diff --git a/pyvisa-py/usb.py b/pyvisa-py/usb.py index 2b2c6f95..931ef1b1 100644 --- a/pyvisa-py/usb.py +++ b/pyvisa-py/usb.py @@ -53,8 +53,6 @@ class USBSession(Session): via usb port using pyUSB """ - timeout = 2000 - @staticmethod def list_resources(): """Return list of resources for this type of USB device""" @@ -75,24 +73,16 @@ def get_low_level_info(cls): return 'via PyUSB (%s). Backend: %s' % (ver, backend) - @property - def timeout(self): - value = self.interface.timeout - - if value is None: - return constants.VI_TMO_INFINITE - elif value == 0: - return constants.VI_TMO_IMMEDIATE - else: - return value - - @timeout.setter - def timeout(self, value): - if value == constants.VI_TMO_INFINITE: - value = None - elif value == constants.VI_TMO_IMMEDIATE: - value = 0 - self.interface.timeout = value + def _get_timeout(self): + if self.interface: + self.timeout = self.interface.timeout + return super(USBSession, self)._get_timeout() + + def _set_timeout(self, attribute, value): + status = super(USBSession, self)._set_timeout() + if self.interface: + self.interface.timeout = self.timeout + return status def read(self, count): """Reads data from device or interface synchronously. From 01d7807c37ae8121c00a7690e67c06fe9a79e928 Mon Sep 17 00:00:00 2001 From: Sveto Krchnavy Date: Thu, 30 Nov 2017 16:11:05 +0100 Subject: [PATCH 03/20] fixed set_attribute for attributes withtou setter --- pyvisa-py/sessions.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyvisa-py/sessions.py b/pyvisa-py/sessions.py index 52bebb5e..baa67474 100644 --- a/pyvisa-py/sessions.py +++ b/pyvisa-py/sessions.py @@ -268,6 +268,8 @@ def set_attribute(self, attribute, attribute_state): if isinstance(value, tuple): setter = value[1] status = setter(attribute, attribute_state) if setter else constants.StatusCode.error_nonsupported_attribute + else: + self.attrs[attribute] = attribute_state return status # Dispatch to `_set_attribute`, which must be implemented by subclasses. From 7968301f7b313e3c346f92047f657668b9abc88a Mon Sep 17 00:00:00 2001 From: Sveto Krchnavy Date: Thu, 30 Nov 2017 17:32:32 +0100 Subject: [PATCH 04/20] forgotten import in gpib --- pyvisa-py/gpib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyvisa-py/gpib.py b/pyvisa-py/gpib.py index 929f8a63..5fb9245d 100644 --- a/pyvisa-py/gpib.py +++ b/pyvisa-py/gpib.py @@ -13,7 +13,7 @@ from __future__ import division, unicode_literals, print_function, absolute_import from bisect import bisect -from pyvisa import constants, logger +from pyvisa import constants, logger, attributes from .sessions import Session, UnknownAttribute From 82a90c7c08ac50cc80392525eabc75b4d7d46f90 Mon Sep 17 00:00:00 2001 From: Sveto Krchnavy Date: Thu, 30 Nov 2017 17:33:13 +0100 Subject: [PATCH 05/20] attributes implemented using defined getters and setters in TCPIPSocketSession --- pyvisa-py/tcpip.py | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/pyvisa-py/tcpip.py b/pyvisa-py/tcpip.py index fde879aa..639fdf95 100644 --- a/pyvisa-py/tcpip.py +++ b/pyvisa-py/tcpip.py @@ -342,12 +342,15 @@ def after_parsing(self): self.attrs[constants.VI_ATTR_TCPIP_ADDR] = self.parsed.host_address self.attrs[constants.VI_ATTR_TCPIP_PORT] = self.parsed.port self.attrs[constants.VI_ATTR_INTF_NUM] = self.parsed.board + self.attrs[constants.VI_ATTR_TCPIP_NODELAY] = (self._get_tcpip_nodelay, self._set_attribute) + self.attrs[constants.VI_ATTR_TCPIP_HOSTNAME] = '' + self.attrs[constants.VI_ATTR_TCPIP_KEEPALIVE] = (self._get_tcpip_keepalive, self._set_tcpip_keepalive) + # to use default as ni visa driver (NI-VISA 15.0) + self.attrs[constants.VI_ATTR_SUPPRESS_END_EN] = True - for name in ('TERMCHAR', 'TERMCHAR_EN', 'SUPPRESS_END_EN'): + for name in ('TERMCHAR', 'TERMCHAR_EN'): attribute = getattr(constants, 'VI_ATTR_' + name) self.attrs[attribute] = attributes.AttributesByID[attribute].default - # to use default as ni visa driver (NI-VISA 15.0) - self.attrs[getattr(constants, 'VI_ATTR_SUPPRESS_END_EN')] = True def _connect(self): timeout = self.open_timeout / 1000.0 if self.open_timeout is not None else None @@ -488,6 +491,30 @@ def write(self, data): return offset, SUCCESS + def _get_tcpip_nodelay(self, attribute): + if self.interface: + value = self.interface.getsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY) + return constants.VI_TRUE if value == 1 else constants.VI_FALSE, constants.StatusCode.success + return 0, constants.StatusCode.error_nonsupported_attribute + + def _set_tcpip_nodelay(self, attribute, attribute_state): + if self.interface: + self.interface.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1 if attribute_state else 0) + return constants.StatusCode.success + return 0, constants.StatusCode.error_nonsupported_attribute + + def _get_tcpip_keepalive(self, attribute): + if self.interface: + value = self.interface.getsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE) + return constants.VI_TRUE if value == 1 else constants.VI_FALSE, constants.StatusCode.success + return 0, constants.StatusCode.error_nonsupported_attribute + + def _set_tcpip_keepalive(self, attribute, attribute_state): + if self.interface: + self.interface.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1 if attribute_state else 0) + return constants.StatusCode.success + return 0, constants.StatusCode.error_nonsupported_attribute + def _get_attribute(self, attribute): """Get the value for a given VISA attribute for this session. @@ -497,16 +524,6 @@ def _get_attribute(self, attribute): :return: The state of the queried attribute for a specified resource, return value of the library call. :rtype: (unicode | str | list | int, VISAStatus) """ - - if attribute == constants.VI_ATTR_TCPIP_HOSTNAME: - raise NotImplementedError - - elif attribute == constants.VI_ATTR_TCPIP_KEEPALIVE: - raise NotImplementedError - - elif attribute == constants.VI_ATTR_TCPIP_NODELAY: - raise NotImplementedError - raise UnknownAttribute(attribute) def _set_attribute(self, attribute, attribute_state): From ed5379a3ab5f7ad7ff83acc85fcbe044c255b2e1 Mon Sep 17 00:00:00 2001 From: Sveto Krchnavy Date: Thu, 30 Nov 2017 19:02:53 +0100 Subject: [PATCH 06/20] code cleanup to unify status codes and remove unused class variables --- pyvisa-py/tcpip.py | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/pyvisa-py/tcpip.py b/pyvisa-py/tcpip.py index 639fdf95..a5080b9b 100644 --- a/pyvisa-py/tcpip.py +++ b/pyvisa-py/tcpip.py @@ -319,8 +319,6 @@ class TCPIPSocketSession(Session): # and select timeout is not lower that that minimum timeout # Tis is valid for connect and read operations - lock_timeout = 1000 - max_recv_size = 4096 # This buffer is used to store the bytes that appeared after termination char @@ -335,7 +333,7 @@ def after_parsing(self): # TODO: board_number not handled ret_status = self._connect() - if ret_status != constants.StatusCode.success: + if ret_status != SUCCESS: self.close() raise Exception("could not connect: {0}".format(str(ret_status))) @@ -374,11 +372,11 @@ def _connect(self): # use select to wait for socket ready, max `select_timout` seconds r, w, x = select.select([self.interface], [self.interface], [], select_timout) if self.interface in r or self.interface in w: - return constants.StatusCode.success + return SUCCESS if time.time() >= finish_time: # reached timeout - return constants.StatusCode.error_timeout + return StatusCode.error_timeout # `select_timout` decreased to 50% of previous or min_select_timeout select_timout = max(select_timout/2.0, min_select_timeout) @@ -426,11 +424,11 @@ def read(self, count): if term_char_en and term_byte in out: term_byte_index = out.index(term_byte) + 1 self._pending_buffer = out[term_byte_index:] - return bytes(out[:term_byte_index]), constants.StatusCode.success_termination_character_read + return bytes(out[:term_byte_index]), StatusCode.success_termination_character_read if len(out) >= count: self._pending_buffer = out[count:] - return bytes(out[:count]), constants.StatusCode.success_max_count_read + return bytes(out[:count]), StatusCode.success_max_count_read # use select to wait for read ready, max `select_timout` seconds r, w, x = select.select([self.interface], [], [], select_timout) @@ -445,12 +443,12 @@ def read(self, count): if out and not suppress_end_en: # we have some data without termchar but no further data expected self._pending_buffer = out[count:] - return bytes(out[:count]), constants.StatusCode.success + return bytes(out[:count]), SUCCESS if time.time() >= finish_time: # reached timeout self._pending_buffer = out[count:] - return bytes(out[:count]), constants.StatusCode.error_timeout + return bytes(out[:count]), StatusCode.error_timeout # `select_timout` decreased to 50% of previous or min_select_timeout select_timout = max(select_timout/2.0, min_select_timeout) @@ -494,26 +492,26 @@ def write(self, data): def _get_tcpip_nodelay(self, attribute): if self.interface: value = self.interface.getsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY) - return constants.VI_TRUE if value == 1 else constants.VI_FALSE, constants.StatusCode.success - return 0, constants.StatusCode.error_nonsupported_attribute + return constants.VI_TRUE if value == 1 else constants.VI_FALSE, SUCCESS + return 0, StatusCode.error_nonsupported_attribute def _set_tcpip_nodelay(self, attribute, attribute_state): if self.interface: self.interface.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1 if attribute_state else 0) - return constants.StatusCode.success - return 0, constants.StatusCode.error_nonsupported_attribute + return SUCCESS + return 0, StatusCode.error_nonsupported_attribute def _get_tcpip_keepalive(self, attribute): if self.interface: value = self.interface.getsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE) - return constants.VI_TRUE if value == 1 else constants.VI_FALSE, constants.StatusCode.success - return 0, constants.StatusCode.error_nonsupported_attribute + return constants.VI_TRUE if value == 1 else constants.VI_FALSE, SUCCESS + return 0, StatusCode.error_nonsupported_attribute def _set_tcpip_keepalive(self, attribute, attribute_state): if self.interface: self.interface.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1 if attribute_state else 0) - return constants.StatusCode.success - return 0, constants.StatusCode.error_nonsupported_attribute + return SUCCESS + return 0, StatusCode.error_nonsupported_attribute def _get_attribute(self, attribute): """Get the value for a given VISA attribute for this session. From 6bd719d91a2101bcfee50a73a0ef88573ab01a75 Mon Sep 17 00:00:00 2001 From: Sveto Krchnavy Date: Thu, 30 Nov 2017 19:07:13 +0100 Subject: [PATCH 07/20] fixed write timeout in serial --- pyvisa-py/serial.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyvisa-py/serial.py b/pyvisa-py/serial.py index 283e6c09..3fad7da9 100644 --- a/pyvisa-py/serial.py +++ b/pyvisa-py/serial.py @@ -65,7 +65,7 @@ def after_parsing(self): else: cls = Serial - self.interface = cls(port=self.parsed.board, timeout=self.timeout, write_timeout=2000) + self.interface = cls(port=self.parsed.board, timeout=self.timeout, write_timeout=self.timeout) for name in ('ASRL_END_IN', 'ASRL_END_OUT', 'SEND_END_EN', 'TERMCHAR', 'TERMCHAR_EN', 'SUPPRESS_END_EN'): From 48cf33468dd80b8ca785688470df8108881481ab Mon Sep 17 00:00:00 2001 From: Sveto Krchnavy Date: Thu, 30 Nov 2017 19:13:12 +0100 Subject: [PATCH 08/20] import in serial.py simplified --- pyvisa-py/serial.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyvisa-py/serial.py b/pyvisa-py/serial.py index 3fad7da9..01c12bdf 100644 --- a/pyvisa-py/serial.py +++ b/pyvisa-py/serial.py @@ -19,7 +19,6 @@ try: import serial - from serial import Serial from serial.tools.list_ports import comports except ImportError as e: Session.register_unavailable(constants.InterfaceType.asrl, 'INSTR', @@ -63,7 +62,7 @@ def after_parsing(self): if 'mock' in self.parsed: cls = self.parsed.mock else: - cls = Serial + cls = serial.Serial self.interface = cls(port=self.parsed.board, timeout=self.timeout, write_timeout=self.timeout) From ecacc0f04810596e8ef970478e6ec04989a81c69 Mon Sep 17 00:00:00 2001 From: Sveto Krchnavy Date: Thu, 30 Nov 2017 19:36:01 +0100 Subject: [PATCH 09/20] class variables becomes instance variables --- pyvisa-py/tcpip.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pyvisa-py/tcpip.py b/pyvisa-py/tcpip.py index a5080b9b..003d491c 100644 --- a/pyvisa-py/tcpip.py +++ b/pyvisa-py/tcpip.py @@ -319,10 +319,6 @@ class TCPIPSocketSession(Session): # and select timeout is not lower that that minimum timeout # Tis is valid for connect and read operations - max_recv_size = 4096 - - # This buffer is used to store the bytes that appeared after termination char - _pending_buffer = bytearray() @staticmethod def list_resources(): @@ -337,6 +333,10 @@ def after_parsing(self): self.close() raise Exception("could not connect: {0}".format(str(ret_status))) + self.max_recv_size = 4096 + # This buffer is used to store the bytes that appeared after termination char + self._pending_buffer = bytearray() + self.attrs[constants.VI_ATTR_TCPIP_ADDR] = self.parsed.host_address self.attrs[constants.VI_ATTR_TCPIP_PORT] = self.parsed.port self.attrs[constants.VI_ATTR_INTF_NUM] = self.parsed.board From 2a552c02496ab51a47ec916d50872a912dec1b31 Mon Sep 17 00:00:00 2001 From: Sveto Krchnavy Date: Thu, 30 Nov 2017 19:48:44 +0100 Subject: [PATCH 10/20] pending buffer is used as main buffer for session --- pyvisa-py/tcpip.py | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/pyvisa-py/tcpip.py b/pyvisa-py/tcpip.py index 003d491c..cab67a64 100644 --- a/pyvisa-py/tcpip.py +++ b/pyvisa-py/tcpip.py @@ -408,9 +408,6 @@ def read(self, count): read_fun = self.interface.recv - out = bytearray() - out.extend(self._pending_buffer) - # minimum is in interval 1 - 100ms based on timeout min_select_timeout = max(min(timeout/100.0, 0.1), 0.001) # initial 'select_timout' is half of timeout or max 2 secs (max blocking time). @@ -421,14 +418,16 @@ def read(self, count): while True: # check, if we have any data received (from pending buffer or further reading) - if term_char_en and term_byte in out: - term_byte_index = out.index(term_byte) + 1 - self._pending_buffer = out[term_byte_index:] - return bytes(out[:term_byte_index]), StatusCode.success_termination_character_read + if term_char_en and term_byte in self._pending_buffer: + term_byte_index = self._pending_buffer.index(term_byte) + 1 + out = bytes(self._pending_buffer[:term_byte_index]) + self._pending_buffer = self._pending_buffer[term_byte_index:] + return out, StatusCode.success_termination_character_read - if len(out) >= count: - self._pending_buffer = out[count:] - return bytes(out[:count]), StatusCode.success_max_count_read + if len(self._pending_buffer) >= count: + out = bytes(self._pending_buffer[:count]) + self._pending_buffer = self._pending_buffer[count:] + return out, StatusCode.success_max_count_read # use select to wait for read ready, max `select_timout` seconds r, w, x = select.select([self.interface], [], [], select_timout) @@ -436,19 +435,21 @@ def read(self, count): read_data = b'' if self.interface in r: read_data = read_fun(chunk_length) - out.extend(read_data) + self._pending_buffer.extend(read_data) if not read_data: # can't read chunk or timeout - if out and not suppress_end_en: + if self._pending_buffer and not suppress_end_en: # we have some data without termchar but no further data expected - self._pending_buffer = out[count:] - return bytes(out[:count]), SUCCESS + out = bytes(self._pending_buffer[:count]) + self._pending_buffer = self._pending_buffer[count:] + return out, SUCCESS if time.time() >= finish_time: # reached timeout - self._pending_buffer = out[count:] - return bytes(out[:count]), StatusCode.error_timeout + out = bytes(self._pending_buffer[:count]) + self._pending_buffer = self._pending_buffer[count:] + return out, StatusCode.error_timeout # `select_timout` decreased to 50% of previous or min_select_timeout select_timout = max(select_timout/2.0, min_select_timeout) From 4123d1e247f6fe9ef723431b76f7206007a4ab02 Mon Sep 17 00:00:00 2001 From: Sveto Krchnavy Date: Thu, 30 Nov 2017 19:49:31 +0100 Subject: [PATCH 11/20] processing of case, when expected less data then position of termchar --- pyvisa-py/tcpip.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pyvisa-py/tcpip.py b/pyvisa-py/tcpip.py index cab67a64..b077fa24 100644 --- a/pyvisa-py/tcpip.py +++ b/pyvisa-py/tcpip.py @@ -420,9 +420,14 @@ def read(self, count): # check, if we have any data received (from pending buffer or further reading) if term_char_en and term_byte in self._pending_buffer: term_byte_index = self._pending_buffer.index(term_byte) + 1 + if term_byte_index > count: + term_byte_index = count + status = StatusCode.success_max_count_read + else: + status = StatusCode.success_termination_character_read out = bytes(self._pending_buffer[:term_byte_index]) self._pending_buffer = self._pending_buffer[term_byte_index:] - return out, StatusCode.success_termination_character_read + return out, status if len(self._pending_buffer) >= count: out = bytes(self._pending_buffer[:count]) From 8c916c5182b0a5182afc3dc632d3d5de20651dfc Mon Sep 17 00:00:00 2001 From: Sveto Krchnavy Date: Fri, 1 Dec 2017 09:53:59 +0100 Subject: [PATCH 12/20] self.timeout used in sessions instead of reading visa attribute to avoud double conversion --- pyvisa-py/sessions.py | 6 ++---- pyvisa-py/tcpip.py | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/pyvisa-py/sessions.py b/pyvisa-py/sessions.py index baa67474..80cfa247 100644 --- a/pyvisa-py/sessions.py +++ b/pyvisa-py/sessions.py @@ -313,8 +313,6 @@ def _read(self, reader, count, end_indicator_checker, suppress_end_en, # NOTE: Some interfaces return not only a single byte but a complete block for each read # therefore we must handle the case that the termination character is in the middle of the block # or that the maximum number of bytes is exceeded - timeout, _ = self.get_attribute(constants.VI_ATTR_TMO_VALUE) - timeout /= 1000.0 # Make sure termination_char is a string try: @@ -322,7 +320,7 @@ def _read(self, reader, count, end_indicator_checker, suppress_end_en, except TypeError: pass - start = time.time() + finish_time = None if self.timeout is None else (time.time() + self.timeout) out = b'' while True: try: @@ -347,7 +345,7 @@ def _read(self, reader, count, end_indicator_checker, suppress_end_en, # Return at most the number of bytes requested return out[:count], constants.StatusCode.success_max_count_read - if time.time() - start > timeout: + if finish_time and time.time() > finish_timeout: return out, constants.StatusCode.error_timeout def _get_timeout(self, attribute_name): diff --git a/pyvisa-py/tcpip.py b/pyvisa-py/tcpip.py index b077fa24..55fa6111 100644 --- a/pyvisa-py/tcpip.py +++ b/pyvisa-py/tcpip.py @@ -94,6 +94,7 @@ def read(self, count): else: term_char = flags = 0 + # ToDo self.timeout shall be used as timeout, requires changes in read_fun timeout, _ = self.get_attribute(constants.VI_ATTR_TMO_VALUE) read_data = bytearray() @@ -135,6 +136,7 @@ def write(self, data): send_end, _ = self.get_attribute(constants.VI_ATTR_SEND_END_EN) chunk_size = 1024 + # ToDo self.timeout shall be used as timeout, requires changes in read_fun timeout, _ = self.get_attribute(constants.VI_ATTR_TMO_VALUE) try: @@ -351,7 +353,7 @@ def after_parsing(self): self.attrs[attribute] = attributes.AttributesByID[attribute].default def _connect(self): - timeout = self.open_timeout / 1000.0 if self.open_timeout is not None else None + timeout = self.open_timeout / 1000.0 if self.open_timeout else 10.0 try: self.interface = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.interface.setblocking(0) @@ -379,7 +381,7 @@ def _connect(self): return StatusCode.error_timeout # `select_timout` decreased to 50% of previous or min_select_timeout - select_timout = max(select_timout/2.0, min_select_timeout) + select_timout = max(select_timout / 2.0, min_select_timeout) def close(self): self.interface.close() @@ -402,19 +404,17 @@ def read(self, count): term_char, _ = self.get_attribute(constants.VI_ATTR_TERMCHAR) term_byte = common.int_to_byte(term_char) if term_char else b'' term_char_en, _ = self.get_attribute(constants.VI_ATTR_TERMCHAR_EN) - timeout, _ = self.get_attribute(constants.VI_ATTR_TMO_VALUE) - timeout /= 1000.0 suppress_end_en, _ = self.get_attribute(constants.VI_ATTR_SUPPRESS_END_EN) read_fun = self.interface.recv - # minimum is in interval 1 - 100ms based on timeout - min_select_timeout = max(min(timeout/100.0, 0.1), 0.001) + # minimum is in interval 1 - 100ms based on timeout, 1sec if no timeut defined + min_select_timeout = 1 if self.timeout is None else max(min(self.timeout / 100.0, 0.1), 0.001) # initial 'select_timout' is half of timeout or max 2 secs (max blocking time). # min is from 'min_select_timeout' - select_timout = max(min(timeout/2.0, 2.0), min_select_timeout) - # time, when loop shall finish - finish_time = time.time() + timeout + select_timout = 2.0 if self.timeout is None else max(min(self.timeout / 2.0, 2.0), min_select_timeout) + # time, when loop shall finish, None means never ending story if no data arrives + finish_time = None if self.timeout is None else (time.time() + self.timeout) while True: # check, if we have any data received (from pending buffer or further reading) @@ -450,14 +450,14 @@ def read(self, count): self._pending_buffer = self._pending_buffer[count:] return out, SUCCESS - if time.time() >= finish_time: + if finish_time and time.time() >= finish_time: # reached timeout out = bytes(self._pending_buffer[:count]) self._pending_buffer = self._pending_buffer[count:] return out, StatusCode.error_timeout # `select_timout` decreased to 50% of previous or min_select_timeout - select_timout = max(select_timout/2.0, min_select_timeout) + select_timout = max(select_timout / 2.0, min_select_timeout) def write(self, data): """Writes data to device or interface synchronously. From 18971d4f47ed83642b51dca4248609f287271ebe Mon Sep 17 00:00:00 2001 From: Sveto Krchnavy Date: Fri, 1 Dec 2017 09:54:21 +0100 Subject: [PATCH 13/20] simplified usege of attributes constants --- pyvisa-py/gpib.py | 4 ++-- pyvisa-py/sessions.py | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/pyvisa-py/gpib.py b/pyvisa-py/gpib.py index 5fb9245d..3296fa95 100644 --- a/pyvisa-py/gpib.py +++ b/pyvisa-py/gpib.py @@ -73,8 +73,8 @@ def after_parsing(self): pad = self.parsed.primary_address self.handle = gpib.dev(int(minor), int(pad)) self.interface = Gpib(self.handle) - attribute = getattr(constants, 'VI_ATTR_TMO_VALUE') - self.set_attribute(constants.VI_ATTR_TMO_VALUE, attributes.AttributesByID[attribute].default) + # force timeout setting to interface + self.set_attribute(constants.VI_ATTR_TMO_VALUE, attributes.AttributesByID[constants.VI_ATTR_TMO_VALUE].default) def _get_timeout(self, attribute): diff --git a/pyvisa-py/sessions.py b/pyvisa-py/sessions.py index 80cfa247..7ff88558 100644 --- a/pyvisa-py/sessions.py +++ b/pyvisa-py/sessions.py @@ -172,8 +172,7 @@ def __init__(self, resource_manager_session, resource_name, parsed=None, open_ti self.parsed = parsed self.open_timeout = open_timeout #: get default timeout from constants - attribute = getattr(constants, 'VI_ATTR_TMO_VALUE') - self.timeout = attributes.AttributesByID[attribute].default / 1000.0 + self.timeout = attributes.AttributesByID[constants.VI_ATTR_TMO_VALUE].default / 1000.0 #: Used as a place holder for the object doing the lowlevel communication. self.interface = None From e19314872fb9fe89f93703eb0713884ff11cde2a Mon Sep 17 00:00:00 2001 From: Sveto Krchnavy Date: Fri, 1 Dec 2017 10:57:34 +0100 Subject: [PATCH 14/20] TODO unification and code cleanup --- pyvisa-py/gpib.py | 3 --- pyvisa-py/tcpip.py | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/pyvisa-py/gpib.py b/pyvisa-py/gpib.py index 3296fa95..0c157fd6 100644 --- a/pyvisa-py/gpib.py +++ b/pyvisa-py/gpib.py @@ -20,11 +20,9 @@ try: import gpib from Gpib import Gpib - except ImportError as e: Session.register_unavailable(constants.InterfaceType.gpib, 'INSTR', 'Please install linux-gpib to use this resource type.\n%s' % e) - raise @@ -88,7 +86,6 @@ def _get_timeout(self, attribute): return timeout, constants.StatusCode.success def _set_timeout(self, attribute, value): - """ linux-gpib only supports 18 discrete timeout values. If a timeout value other than these is requested, it will be rounded up to the closest diff --git a/pyvisa-py/tcpip.py b/pyvisa-py/tcpip.py index 55fa6111..7b0fb0a4 100644 --- a/pyvisa-py/tcpip.py +++ b/pyvisa-py/tcpip.py @@ -94,7 +94,7 @@ def read(self, count): else: term_char = flags = 0 - # ToDo self.timeout shall be used as timeout, requires changes in read_fun + # TODO: self.timeout shall be used as timeout, requires changes in read_fun timeout, _ = self.get_attribute(constants.VI_ATTR_TMO_VALUE) read_data = bytearray() @@ -136,7 +136,7 @@ def write(self, data): send_end, _ = self.get_attribute(constants.VI_ATTR_SEND_END_EN) chunk_size = 1024 - # ToDo self.timeout shall be used as timeout, requires changes in read_fun + # TODO: self.timeout shall be used as timeout, requires changes in read_fun timeout, _ = self.get_attribute(constants.VI_ATTR_TMO_VALUE) try: From ad70cade3e93a0055fb8b69b8917700953477f32 Mon Sep 17 00:00:00 2001 From: Sveto Krchnavy Date: Fri, 1 Dec 2017 11:18:09 +0100 Subject: [PATCH 15/20] fixed set/get timeout handling in serial and usb and unification of methods --- pyvisa-py/serial.py | 6 +++--- pyvisa-py/sessions.py | 10 +++++----- pyvisa-py/usb.py | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/pyvisa-py/serial.py b/pyvisa-py/serial.py index 01c12bdf..f34eb815 100644 --- a/pyvisa-py/serial.py +++ b/pyvisa-py/serial.py @@ -71,13 +71,13 @@ def after_parsing(self): attribute = getattr(constants, 'VI_ATTR_' + name) self.attrs[attribute] = attributes.AttributesByID[attribute].default - def _get_timeout(self): + def _get_timeout(self, attribute): if self.interface: self.timeout = self.interface.timeout - return super(SerialSession, self)._get_timeout() + return super(SerialSession, self)._get_timeout(attribute) def _set_timeout(self, attribute, value): - status = super(SerialSession, self)._set_timeout() + status = super(SerialSession, self)._set_timeout(attribute, value) if self.interface: self.interface.timeout = self.timeout self.interface.write_timeout = self.timeout diff --git a/pyvisa-py/sessions.py b/pyvisa-py/sessions.py index 7ff88558..367c1765 100644 --- a/pyvisa-py/sessions.py +++ b/pyvisa-py/sessions.py @@ -347,7 +347,7 @@ def _read(self, reader, count, end_indicator_checker, suppress_end_en, if finish_time and time.time() > finish_timeout: return out, constants.StatusCode.error_timeout - def _get_timeout(self, attribute_name): + def _get_timeout(self, attribute): """ Returns timeout calculated value from python way to VI_ way """ if self.timeout is None: @@ -358,13 +358,13 @@ def _get_timeout(self, attribute_name): ret_value = int(self.timeout * 1000.0) return ret_value, constants.StatusCode.success - def _set_timeout(self, attribute_name, new_value): + def _set_timeout(self, attribute, value): """ Sets timeout calculated value from python way to VI_ way """ - if new_value == constants.VI_TMO_INFINITE: + if value == constants.VI_TMO_INFINITE: self.timeout = None - elif new_value == constants.VI_TMO_IMMEDIATE: + elif value == constants.VI_TMO_IMMEDIATE: self.timeout = 0 else: - self.timeout = new_value / 1000.0 + self.timeout = value / 1000.0 return constants.StatusCode.success; diff --git a/pyvisa-py/usb.py b/pyvisa-py/usb.py index 931ef1b1..c817a34e 100644 --- a/pyvisa-py/usb.py +++ b/pyvisa-py/usb.py @@ -73,13 +73,13 @@ def get_low_level_info(cls): return 'via PyUSB (%s). Backend: %s' % (ver, backend) - def _get_timeout(self): + def _get_timeout(self, attribute): if self.interface: self.timeout = self.interface.timeout - return super(USBSession, self)._get_timeout() + return super(USBSession, self)._get_timeout(attribute) def _set_timeout(self, attribute, value): - status = super(USBSession, self)._set_timeout() + status = super(USBSession, self)._set_timeout(attribute, value) if self.interface: self.interface.timeout = self.timeout return status From 3593f9dda1864502c1fcd15f75210ebfb71cad0c Mon Sep 17 00:00:00 2001 From: Sveto Krchnavy Date: Fri, 1 Dec 2017 11:23:13 +0100 Subject: [PATCH 16/20] using self.timeout in GPIBSession in get and set timeout methods --- pyvisa-py/gpib.py | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/pyvisa-py/gpib.py b/pyvisa-py/gpib.py index 0c157fd6..bfed3744 100644 --- a/pyvisa-py/gpib.py +++ b/pyvisa-py/gpib.py @@ -40,10 +40,9 @@ def _find_listeners(): StatusCode = constants.StatusCode SUCCESS = StatusCode.success -# linux-gpib timeout constants, in milliseconds. See self.timeout. -TIMETABLE = (0, 1e-2, 3e-2, 1e-1, 3e-1, 1e0, 3e0, 1e1, 3e1, 1e2, 3e2, 1e3, 3e3, - 1e4, 3e4, 1e5, 3e5, 1e6) - +# linux-gpib timeout constants, in milliseconds. See GPIBSession._set_timeout. +TIMETABLE = (0, 10e-6, 30e-6, 100e-6, 300e-6, 1e-3, 3e-3, 10e-3, 30e-3, 100e-3, 300e-3, 1.0, 3.0, + 10.0, 30.0, 100.0, 300.0, 1000.0) # TODO: Check board indices other than 0. BOARD = 0 @@ -75,15 +74,16 @@ def after_parsing(self): self.set_attribute(constants.VI_ATTR_TMO_VALUE, attributes.AttributesByID[constants.VI_ATTR_TMO_VALUE].default) def _get_timeout(self, attribute): - - # 0x3 is the hexadecimal reference to the IbaTMO (timeout) configuration - # option in linux-gpib. - timeout = self.interface.ask(3) - if timeout and timeout < len(TIMETABLE): - timeout = int(TIMETABLE[timeout]) - else: - timeout = constants.VI_TMO_INFINITE - return timeout, constants.StatusCode.success + if self.interface: + # 0x3 is the hexadecimal reference to the IbaTMO (timeout) configuration + # option in linux-gpib. + gpib_timeout = self.interface.ask(3) + if gpib_timeout and gpib_timeout < len(TIMETABLE): + self.timeout = TIMETABLE[gpib_timeout] + else: + # value is 0 or out of range -> infinite + self.timeout = None + return super(GPIBSession, self)._get_timeout(attribute) def _set_timeout(self, attribute, value): """ @@ -110,14 +110,16 @@ def _set_timeout(self, attribute, value): 16 300 seconds 17 1000 seconds """ - if value == constants.VI_TMO_INFINITE: - timeout = 0 - self.timeout = None - else: - timeout = min(bisect(TIMETABLE, value - value / 1000.0), 17) - self.timeout = TIMETABLE[timeout] / 1000.0 - self.interface.timeout(timeout) - return constants.StatusCode.success + status = super(GPIBSession, self)._set_timeout(attribute, value) + if self.interface: + if self.timeout is None: + gpib_timeout = 0 + else: + # round up only values that are higher by 0.1% then discrete values + gpib_timeout = min(bisect(TIMETABLE, 0.999 * self.timeout), 17) + self.timeout = TIMETABLE[gpib_timeout] + self.interface.timeout(gpib_timeout) + return status def close(self): gpib.close(self.handle) From 1f9092e0f7f76726e7eae557887eb1b0cd952dc8 Mon Sep 17 00:00:00 2001 From: Sveto Krchnavy Date: Fri, 1 Dec 2017 11:55:17 +0100 Subject: [PATCH 17/20] cosmetic changes in code to unify sources --- pyvisa-py/serial.py | 1 - pyvisa-py/usb.py | 7 +------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/pyvisa-py/serial.py b/pyvisa-py/serial.py index f34eb815..fb3d31cb 100644 --- a/pyvisa-py/serial.py +++ b/pyvisa-py/serial.py @@ -23,7 +23,6 @@ except ImportError as e: Session.register_unavailable(constants.InterfaceType.asrl, 'INSTR', 'Please install PySerial (>=3.0) to use this resource type.\n%s' % e) - raise diff --git a/pyvisa-py/usb.py b/pyvisa-py/usb.py index c817a34e..b0be487d 100644 --- a/pyvisa-py/usb.py +++ b/pyvisa-py/usb.py @@ -15,6 +15,7 @@ from pyvisa import constants, attributes from .sessions import Session, UnknownAttribute +from . import common try: import usb @@ -22,7 +23,6 @@ except ImportError as e: Session.register_unavailable(constants.InterfaceType.usb, 'INSTR', 'Please install PyUSB to use this resource type.\n%s' % e) - Session.register_unavailable(constants.InterfaceType.usb, 'RAW', 'Please install PyUSB to use this resource type.\n%s' % e) raise @@ -35,16 +35,11 @@ 'install a suitable backend like \n' \ 'libusb 0.1, libusb 1.0, libusbx, \n' \ 'libusb-win32 or OpenUSB.\n%s' % e - Session.register_unavailable(constants.InterfaceType.usb, 'INSTR', msg) - Session.register_unavailable(constants.InterfaceType.usb, 'RAW', msg) - raise -from . import common - StatusCode = constants.StatusCode SUCCESS = StatusCode.success From 5c7185b184692eb4f3421683b9621a73814be5e3 Mon Sep 17 00:00:00 2001 From: Sveto Krchnavy Date: Fri, 1 Dec 2017 12:28:46 +0100 Subject: [PATCH 18/20] added documentation haw to register attribute handler --- pyvisa-py/sessions.py | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/pyvisa-py/sessions.py b/pyvisa-py/sessions.py index 367c1765..adc1fb34 100644 --- a/pyvisa-py/sessions.py +++ b/pyvisa-py/sessions.py @@ -190,6 +190,24 @@ def __init__(self, resource_manager_session, resource_name, parsed=None, open_ti def after_parsing(self): """Override this method to provide custom initialization code, to be called after the resourcename is properly parsed + + ResourceSession can register resource specific attributes handling of them into self.attrs. + It is also possible to change handling of already registerd common attributes. + + For static (read only) values, simple readonly and also readwrite attributes simplified construction can be used: + ` self.attrs[constants.VI_ATTR_] = 100` + or + ` self.attrs[constants.VI_ATTR_] = ` + + For more complex handling of attributes, it is possible to register getter and/or setter. When Null is used, NotSupported error is returned. + Getter has same signature as see Session._get_attribute and setter has same signature as see Session._set_attribute. (It is possible to register also + see Session._get_attribute and see Session._set_attribute as getter/setter). Getter and Setter are registered as tupple. + For readwrite attribute: + ` self.attrs[constants.VI_ATTR_] = (, )` + For readonly attribute: + ` self.attrs[constants.VI_ATTR_] = (, None)` + For reusing of see Session._get_attribute and see Session._set_attribute + ` self.attrs[constants.VI_ATTR_] = (self._get_attribute, self._set_attribute)` """ def get_attribute(self, attribute): @@ -216,8 +234,7 @@ def get_attribute(self, attribute): if not attr.read: raise Exception('Do not now how to handle write only attributes.') - # First try to answer those attributes that are common to all session types - # or user defined because they are not defined by the interface. + # First try to answer those attributes that are registered in self.attrs, see Session.after_parsing if attribute in self.attrs: value = self.attrs[attribute] status = constants.StatusCode.success @@ -259,8 +276,7 @@ def set_attribute(self, attribute, attribute_state): if not attr.write: return constants.StatusCode.error_attribute_read_only - # First try to answer those attributes that are common to all session types - # or user defined because they are not defined by the interface. + # First try to answer those attributes that are registered in self.attrs, see Session.after_parsing if attribute in self.attrs: value = self.attrs[attribute] status = constants.StatusCode.success From 8ecfbb9b58343a0d1d04067c336b7a00f97c54da Mon Sep 17 00:00:00 2001 From: Sveto Krchnavy Date: Fri, 1 Dec 2017 12:36:26 +0100 Subject: [PATCH 19/20] improved comment for registration of attributes --- pyvisa-py/sessions.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pyvisa-py/sessions.py b/pyvisa-py/sessions.py index adc1fb34..ccca64c9 100644 --- a/pyvisa-py/sessions.py +++ b/pyvisa-py/sessions.py @@ -192,7 +192,9 @@ def after_parsing(self): called after the resourcename is properly parsed ResourceSession can register resource specific attributes handling of them into self.attrs. - It is also possible to change handling of already registerd common attributes. + It is also possible to change handling of already registerd common attributes. List of attributes is available in pyvisa package: + * name is in constants module as: VI_ATTR_ + * validity of attribute for resource is defined module attributes, AttrVI_ATTR_.resources For static (read only) values, simple readonly and also readwrite attributes simplified construction can be used: ` self.attrs[constants.VI_ATTR_] = 100` From 1e05128b3bd31e833297ed63961f405d75a6d56e Mon Sep 17 00:00:00 2001 From: Sveto Krchnavy Date: Sun, 3 Dec 2017 20:04:06 +0100 Subject: [PATCH 20/20] comment to timetable corrected --- pyvisa-py/gpib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyvisa-py/gpib.py b/pyvisa-py/gpib.py index c4a2c37f..d17096a8 100644 --- a/pyvisa-py/gpib.py +++ b/pyvisa-py/gpib.py @@ -39,7 +39,7 @@ def _find_listeners(): StatusCode = constants.StatusCode -# linux-gpib timeout constants, in milliseconds. See GPIBSession._set_timeout. +# linux-gpib timeout constants, in seconds. See GPIBSession._set_timeout. TIMETABLE = (0, 10e-6, 30e-6, 100e-6, 300e-6, 1e-3, 3e-3, 10e-3, 30e-3, 100e-3, 300e-3, 1.0, 3.0, 10.0, 30.0, 100.0, 300.0, 1000.0)