<commit_before>

import socket, select, struct, logging
import os.path
import zmq

log = logging.getLogger(__name__)

try:
	from finders import BonjourFinder
except (ImportError, OSError):
	log.warning("Can't import the Bonjour libraries, I won't be able to automatically detect Mokus")

class MokuException(Exception):	"""Base class for other Exceptions""";	pass
class MokuNotFound(MokuException): """Can't find Moku. Raised from discovery factory functions."""; pass
class NetworkError(MokuException): """Network connection to Moku failed"""; pass
class DeployException(MokuException): """Couldn't start instrument. Moku may not be licenced to use that instrument"""; pass
class StreamException(MokuException): """Data logging was interrupted or failed"""; pass
class InvalidOperationException(MokuException): """Can't perform that operation at this time"""; pass
class ValueOutOfRangeException(MokuException): """Invalid value for this operation"""; pass
class NotDeployedException(MokuException): """Tried to perform an action on an Instrument before it was deployed to a Moku"""; pass
class FrameTimeout(MokuException): """No new :any:`DataFrame` arrived within the given timeout"""; pass
class NoDataException(MokuException): """A request has been made for data but none will be generated """; pass

class Moku(object):
	"""
	Core class representing a connection to a physical Moku:Lab unit.

	This must always be created first. Once a :any:`Moku` object exists, it can be queried for running instruments
	or new instruments deployed to the device.
	"""
	PORT = 27184

	def __init__(self, ip_addr):
		"""Create a connection to the Moku:Lab unit at the given IP address

		:type ip_addr: string
		:param ip_addr: The address to connect to. This should be in IPv4 dotted notation."""
		self._ip = ip_addr
		self._seq = 0
		self._instrument = None
		self._known_mokus = []

		self._ctx = zmq.Context()
		self._conn = self._ctx.socket(zmq.REQ)
		self._conn.connect("tcp://%s:%d" % (self._ip, Moku.PORT))

		self.name = None
		self.led = None
		self.led_colours = None

	@staticmethod
	def list_mokus():
		""" Discovers all compatible Moku instances on the network.
		This list can be interrogated to find the IP address of the target Moku:Lab hardware, suitable
		to be passed to the :any:`Moku` constructor.<commit_msg>Network: Set ZMQ linger to help cleanly close connections<commit_after>

import socket, select, struct, logging
import os.path
import zmq

log = logging.getLogger(__name__)

try:
	from finders import BonjourFinder
except (ImportError, OSError):
	log.warning("Can't import the Bonjour libraries, I won't be able to automatically detect Mokus")

class MokuException(Exception):	"""Base class for other Exceptions""";	pass
class MokuNotFound(MokuException): """Can't find Moku. Raised from discovery factory functions."""; pass
class NetworkError(MokuException): """Network connection to Moku failed"""; pass
class DeployException(MokuException): """Couldn't start instrument. Moku may not be licenced to use that instrument"""; pass
class StreamException(MokuException): """Data logging was interrupted or failed"""; pass
class InvalidOperationException(MokuException): """Can't perform that operation at this time"""; pass
class ValueOutOfRangeException(MokuException): """Invalid value for this operation"""; pass
class NotDeployedException(MokuException): """Tried to perform an action on an Instrument before it was deployed to a Moku"""; pass
class FrameTimeout(MokuException): """No new :any:`DataFrame` arrived within the given timeout"""; pass
class NoDataException(MokuException): """A request has been made for data but none will be generated """; pass

class Moku(object):
	"""
	Core class representing a connection to a physical Moku:Lab unit.

	This must always be created first. Once a :any:`Moku` object exists, it can be queried for running instruments
	or new instruments deployed to the device.
	"""
	PORT = 27184

	def __init__(self, ip_addr):
		"""Create a connection to the Moku:Lab unit at the given IP address

		:type ip_addr: string
		:param ip_addr: The address to connect to. This should be in IPv4 dotted notation."""
		self._ip = ip_addr
		self._seq = 0
		self._instrument = None
		self._known_mokus = []

		self._ctx = zmq.Context()
		self._conn = self._ctx.socket(zmq.REQ)
		self._conn.setsockopt(zmq.LINGER, 5000)
		self._conn.connect("tcp://%s:%d" % (self._ip, Moku.PORT))

		self.name = None
		self.led = None
		self.led_colours = None

	@staticmethod
	def list_mokus():
		""" Discovers all compatible Moku instances on the network.
		This list can be interrogated to find the IP address of the target Moku:Lab hardware, suitable
		to be passed to the :any:`Moku` constructor.
{'fraction_non_alphanumeric': 0.09915433403805497, 'fraction_numerical': 0.0038054968287526427, 'mean_word_length': 5.208661417322834, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1732231', 'n_tokens_mistral': 1411, 'n_tokens_neox': 1325, 'n_words': 551}