8000 Implement open timeout for hislip by MatthieuDartiailh · Pull Request #430 · pyvisa/pyvisa-py · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Implement open timeout for hislip #430

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Dec 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ PyVISA-py Changelog
- Implemented partial USBTMC message functionality that allows reading the amount of bytes
specified by host PR #470
- add support for VI_ATTR_SUPPRESS_END_EN for USB resources PR #449
- support open_timeout for TCPIP hislip resources PR #430

0.7.2 (07/03/2024)
------------------
Expand Down
1 change: 1 addition & 0 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
ruff
pytest
sphinx
sphinx-rtd-theme
9 changes: 5 additions & 4 deletions pyvisa_py/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@

from importlib.metadata import PackageNotFoundError, version

# We need to import all attributes so that __init_subclass__() is executed once
# (hence the noqa)
from . import attributes # noqa: F401
from .highlevel import PyVisaLibrary

__version__ = "unknown"
try:
__version__ = version(__name__)
except PackageNotFoundError:
# package is not installed
pass

# We need to import all attributes so that __init_subclass__() is executed once
from . import attributes # noqa: F401
from .highlevel import PyVisaLibrary

WRAPPER_CLASS = PyVisaLibrary
2 changes: 1 addition & 1 deletion pyvisa_py/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

from pyvisa import logger

logger = logging.LoggerAdapter(logger, {"backend": "py"}) # type: ignore
LOGGER = logging.LoggerAdapter(logger, {"backend": "py"}) # type: ignore


class NamedObject(object):
Expand Down
23 changes: 12 additions & 11 deletions pyvisa_py/gpib.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@
from bisect import bisect
from typing import Any, Iterator, List, Tuple, Union

from pyvisa import attributes, constants, logger
from pyvisa import attributes, constants
from pyvisa.constants import ResourceAttribute, StatusCode
from pyvisa.rname import GPIBInstr, GPIBIntfc

from .common import LOGGER
from .sessions import Session, UnknownAttribute

try:
Expand Down Expand Up @@ -83,7 +84,7 @@
try:
yield board, gpib.ask(board, 1)
except gpib.GpibError as e:
logger.debug("GPIB board %i error in _find_boards(): %s", board, repr(e))
LOGGER.debug("GPIB board %i error in _find_boards(): %s", board, repr(e))

Check warning on line 87 in pyvisa_py/gpib.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/gpib.py#L87

Added line #L87 was not covered by tests


def _find_listeners() -> Iterator[Tuple[int, int, int]]:
Expand All @@ -99,7 +100,7 @@
if gpib.listener(board, i, j):
yield board, i, j
except gpib.GpibError as e:
logger.debug(
LOGGER.debug(

Check warning on line 103 in pyvisa_py/gpib.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/gpib.py#L103

Added line #L103 was not covered by tests
"GPIB board %i paddr %i saddr %i error in _find_listeners(): %s",
board,
i,
Expand Down Expand Up @@ -204,7 +205,7 @@
# feels brittle. As a consequence we only try to be smart when using
# gpib-ctypes. However in both cases we log the exception at debug level.
else:
logger.debug("Failed to %s.", operation, exc_info=error)
LOGGER.debug("Failed to %s.", operation, exc_info=error)

Check warning on line 208 in pyvisa_py/gpib.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/gpib.py#L208

Added line #L208 was not covered by tests
if not GPIB_CTYPES:
return StatusCode.error_system_error
if error.code == 1:
Expand Down Expand Up @@ -410,7 +411,7 @@
Return value of the library call.

"""
logger.debug("GPIB.write %r" % data)
LOGGER.debug("GPIB.write %r" % data)

Check warning on line 414 in pyvisa_py/gpib.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/gpib.py#L414

Added line #L414 was not covered by tests

# INTFC don't have an interface so use the controller
ifc = self.interface or self.controller
Expand Down Expand Up @@ -663,7 +664,7 @@
Return value of the library call.

"""
logger.debug("GPIB.device clear")
LOGGER.debug("GPIB.device clear")

Check warning on line 667 in pyvisa_py/gpib.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/gpib.py#L667

Added line #L667 was not covered by tests
try:
self.interface.clear()
return StatusCode.success
Expand All @@ -685,7 +686,7 @@
Return value of the library call.

"""
logger.debug("GPIB.device assert hardware trigger")
LOGGER.debug("GPIB.device assert hardware trigger")

Check warning on line 689 in pyvisa_py/gpib.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/gpib.py#L689

Added line #L689 was not covered by tests

try:
if protocol == constants.VI_TRIG_PROT_DEFAULT:
Expand Down Expand Up @@ -838,7 +839,7 @@
Corresponds to viGpibSendIFC function of the VISA library.

"""
logger.debug("GPIB.interface clear")
LOGGER.debug("GPIB.interface clear")

Check warning on line 842 in pyvisa_py/gpib.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/gpib.py#L842

Added line #L842 was not covered by tests
try:
self.controller.interface_clear()
return StatusCode.success
Expand All @@ -862,7 +863,7 @@
Return value of the library call.

"""
logger.debug("GPIB.control atn")
LOGGER.debug("GPIB.control atn")

Check warning on line 866 in pyvisa_py/gpib.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/gpib.py#L866

Added line #L866 was not covered by tests
if mode == constants.VI_GPIB_ATN_ASSERT:
status = gpib_lib.ibcac(self.controller.id, 0)
elif mode == constants.VI_GPIB_ATN_DEASSERT:
Expand Down Expand Up @@ -899,11 +900,11 @@

"""
# ibpct need to get the device id matching the primary and secondary address
logger.debug("GPIB.pass control")
LOGGER.debug("GPIB.pass control")
try:
did = gpib.dev(self.parsed.board, primary_address, secondary_address)
except gpib.GpibError:
logger.exception(
LOGGER.exception(
"Failed to get id for %s, %d", primary_address, secondary_address
)
return StatusCode.error_resource_not_found
Expand Down
23 changes: 13 additions & 10 deletions pyvisa_py/highlevel.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from pyvisa.util import DebugInfo, LibraryPath

from . import sessions
from .common import logger
from .common import LOGGER


class PyVisaLibrary(highlevel.VisaLibraryBase):
Expand Down Expand Up @@ -45,30 +45,30 @@
try:
from .serial import SerialSession

logger.debug("SerialSession was correctly imported.")
LOGGER.debug("SerialSession was correctly imported.")

Check warning on line 48 in pyvisa_py/highlevel.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/highlevel.py#L48

Added line #L48 was not covered by tests
except Exception as e:
logger.debug("SerialSession was not imported %s." % e)
LOGGER.debug("SerialSession was not imported %s." % e)

try:
from .usb import USBRawSession, USBSession

logger.debug("USBSession and USBRawSession were correctly imported.")
LOGGER.debug("USBSession and USBRawSession were correctly imported.")

Check warning on line 55 in pyvisa_py/highlevel.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/highlevel.py#L55

Added line #L55 was not covered by tests
except Exception as e:
logger.debug("USBSession and USBRawSession were not imported %s." % e)
LOGGER.debug("USBSession and USBRawSession were not imported %s." % e)

try:
from .tcpip import TCPIPInstrSession, TCPIPSocketSession

logger.debug("TCPIPSession was correctly imported.")
LOGGER.debug("TCPIPSession was correctly imported.")
except Exception as e:
logger.debug("TCPIPSession was not imported %s." % e)
LOGGER.debug("TCPIPSession was not imported %s." % e)

Check warning on line 64 in pyvisa_py/highlevel.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/highlevel.py#L64

Added line #L64 was not covered by tests

try:
from .gpib import GPIBSession

logger.debug("GPIBSession was correctly imported.")
LOGGER.debug("GPIBSession was correctly imported.")

Check warning on line 69 in pyvisa_py/highlevel.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/highlevel.py#L69

Added line #L69 was not covered by tests
except Exception as e:
logger.debug("GPIBSession was not imported %s." % e)
LOGGER.debug("GPIBSession was not imported %s." % e)

@staticmethod
def get_library_paths() -> Iterable[LibraryPath]:
Expand Down Expand Up @@ -165,7 +165,10 @@
parsed.interface_type_const, parsed.resource_class
)

sess = cls(session, resource_name, parsed, open_timeout)
try:
sess = cls(session, resource_name, parsed, open_timeout)
except sessions.OpenError as e:
return VISASession(0), self.handle_return_value(None, e.error_code)

Check warning on line 171 in pyvisa_py/highlevel.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/highlevel.py#L168-L171

Added lines #L168 - L171 were not covered by tests

return self._register(sess), StatusCode.success

Expand Down
14 changes: 12 additions & 2 deletions pyvisa_py/protocols/hislip.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@
while bytes_recvd < recv_len:
request_size = recv_len - bytes_recvd
data_len = sock.recv_into(view, request_size)
if data_len == 0:
raise RuntimeError("Connection was dropped by server.")

Check warning on line 166 in pyvisa_py/protocols/hislip.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/protocols/hislip.py#L166

Added line #L166 was not covered by tests
bytes_recvd += data_len
view = view[data_len:]

Expand Down Expand Up @@ -367,6 +369,7 @@
def __init__(
self,
ip_addr: str,
open_timeout: Optional[float] = 0.0,
timeout: Optional[float] = None,
port: int = PORT,
sub_address: str = "hislip0",
Expand All @@ -381,19 +384,26 @@

# open the synchronous socket and send an initialize packet
self._sync = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# The VISA spec does not allow to tune the socket timeout when opening
# a connection. ``open_timeout`` only applies to attempt to acquire a
# lock.
self._sync.settimeout(5.0)

Check warning on line 390 in pyvisa_py/protocols/hislip.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/protocols/hislip.py#L390

Added line #L390 was not covered by tests
self._sync.connect((ip_addr, port))
self._sync.settimeout(timeout)
self._sync.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
init = self.initialize(sub_address=sub_address.encode("ascii"))
if init.overlap != 0:
print("**** prefer overlap = %d" % init.overlap)
# We set the user timeout once we managed to initialize the connection.
self._sync.settimeout(timeout)

Check warning on line 397 in pyvisa_py/protocols/hislip.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/protocols/hislip.py#L397

Added line #L397 was not covered by tests

# open the asynchronous socket and send an initialize packet
self._async = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._async.connect((ip_addr, port))
self._async.settimeout(timeout)
self._async.settimeout(5.0)

Check warning on line 402 in pyvisa_py/protocols/hislip.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/protocols/hislip.py#L402

Added line #L402 was not covered by tests
self._async.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
self._async_init = self.async_initialize(session_id=init.session_id)
# We set the user timeout once we managed to initialize the connection.
self._async.settimeout(timeout)

Check warning on line 406 in pyvisa_py/protocols/hislip.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/protocols/hislip.py#L406

Added line #L406 was not covered by tests

# initialize variables
self.max_msg_size = DEFAULT_MAX_MSG_SIZE
Expand Down
28 changes: 14 additions & 14 deletions pyvisa_py/protocols/rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
import sys
import time

from ..common import logger
from ..common import LOGGER
from . import xdrlib

#: Version of the protocol
Expand Down Expand Up @@ -225,7 +225,7 @@

def make_call(self, proc, args, pack_func, unpack_func):
# Don't normally override this (but see Broadcast)
logger.debug("Make call %r, %r, %r, %r", proc, args, pack_func, unpack_func)
LOGGER.debug("Make call %r, %r, %r, %r", proc, args, pack_func, unpack_func)

Check warning on line 228 in pyvisa_py/protocols/rpc.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/protocols/rpc.py#L228

Added line #L228 was not covered by tests

if pack_func is None and args is not None:
raise TypeError("non-null args with null pack_func")
Expand Down Expand Up @@ -296,7 +296,7 @@


def _sendrecord(sock, record, fragsize=None, timeout=None):
logger.debug("Sending record through %s: %r", sock, record)
LOGGER.debug("Sending record through %s: %r", sock, record)

Check warning on line 299 in pyvisa_py/protocols/rpc.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/protocols/rpc.py#L299

Added line #L299 was not covered by tests
if timeout is not None:
r, w, x = select.select([], [sock], [], timeout)
if sock not in w:
Expand Down Expand Up @@ -330,7 +330,7 @@
packages_received = 0

if min_packages != 0:
logger.debug("Start receiving at least %i packages" % min_packages)
LOGGER.debug("Start receiving at least %i packages" % min_packages)

Check warning on line 333 in pyvisa_py/protocols/rpc.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/protocols/rpc.py#L333

Added line #L333 was not covered by tests

# minimum is in interval 1 - 100ms based on timeout or for infinite it is
# 1 sec
Expand All @@ -355,11 +355,11 @@
if sock in r:
read_data = read_fun(exp_length)
buffer.extend(read_data)
logger.debug("received %r" % read_data)
LOGGER.debug("received %r" % read_data)

Check warning on line 358 in pyvisa_py/protocols/rpc.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/protocols/rpc.py#L358

Added line #L358 was not covered by tests
# Timeout was reached
if not read_data: # no response or empty response
if timeout is not None and time.time() >= finish_time:
logger.debug(
LOGGER.debug(

Check warning on line 362 in pyvisa_py/protocols/rpc.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/protocols/rpc.py#L362

Added line #L362 was not covered by tests
(
"Time out encountered in %s."
"Already receieved %d bytes. Last fragment is %d "
Expand All @@ -376,7 +376,7 @@
)
raise socket.timeout(msg)
elif min_packages != 0 and packages_received >= min_packages:
logger.debug(
LOGGER.debug(

Check warning on line 379 in pyvisa_py/protocols/rpc.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/protocols/rpc.py#L379

Added line #L379 was not covered by tests
"Stop receiving after %i of %i requested packages. Received record through %s: %r",
packages_received,
min_packages,
Expand Down Expand Up @@ -404,7 +404,7 @@
record.extend(buffer[:exp_length])
buffer = buffer[exp_length:]
if last:
logger.debug("Received record through %s: %r", sock, record)
LOGGER.debug("Received record through %s: %r", sock, record)

Check warning on line 407 in pyvisa_py/protocols/rpc.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/protocols/rpc.py#L407

Added line #L407 was not covered by tests
return bytes(record)
else:
wait_header = True
Expand Down Expand Up @@ -480,15 +480,15 @@
return super(RawTCPClient, self).make_call(proc, args, pack_func, unpack_func)

def connect(self, timeout=5.0):
logger.debug(
LOGGER.debug(

Check warning on line 483 in pyvisa_py/protocols/rpc.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/protocols/rpc.py#L483

Added line #L483 was not covered by tests
"RawTCPClient: connecting to socket at (%s, %s)", self.host, self.port
)
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if not _connect(self.sock, self.host, self.port, timeout):
raise RPCError("can't connect to server")

def close(self):
logger.debug("RawTCPClient: closing socket")
LOGGER.debug("RawTCPClient: closing socket")

Check warning on line 491 in pyvisa_py/protocols/rpc.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/protocols/rpc.py#L491

Added line #L491 was not covered by tests
self.sock.close()

def do_call(self):
Expand All @@ -498,7 +498,7 @@

try:
min_packages = int(self.packer.proc == 3)
logger.debug("RawTCPClient: procedure type %i" % self.packer.proc)
LOGGER.debug("RawTCPClient: procedure type %i" % self.packer.proc)

Check warning on line 501 in pyvisa_py/protocols/rpc.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/protocols/rpc.py#L501

Added line #L501 was not covered by tests
# if the command is get_port, we only expect one package.
# This is a workaround for misbehaving instruments.
except AttributeError:
Expand Down Expand Up @@ -531,14 +531,14 @@
self.connect()

def connect(self):
logger.debug(
LOGGER.debug(

Check warning on line 534 in pyvisa_py/protocols/rpc.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/protocols/rpc.py#L534

Added line #L534 was not covered by tests
"RawTCPClient: connecting to socket at (%s, %s)", self.host, self.port
)
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.sock.connect((self.host, self.port))

def close(self):
logger.debug("RawTCPClient: closing socket")
LOGGER.debug("RawTCPClient: closing socket")

Check warning on line 541 in pyvisa_py/protocols/rpc.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/protocols/rpc.py#L541

Added line #L541 was not covered by tests
self.sock.close()

def do_call(self):
Expand Down Expand Up @@ -1005,7 +1005,7 @@
except EOFError:
break
except socket.error:
logger.exception("socket error: %r", sys.exc_info()[0])
LOGGER.exception("socket error: %r", sys.exc_info()[0])

Check warning on line 1008 in pyvisa_py/protocols/rpc.py

View check run for this annotation

Codecov / codecov/patch

pyvisa_py/protocols/rpc.py#L1008

Added line #L1008 was not covered by tests
break
reply = self.handle(call)
if reply is not None:
Expand Down
Loading
Loading
0