Instruction:
Write a Python 3 function for
converting the entire image to bytes.

Response:
def to_bytes(self):
		"""Convert the entire image to bytes.

		:rtype: bytes
		"""

		# grab the chunks we needs
		out = [PNG_SIGN]
		# FIXME: it's tricky to define "other_chunks". HoneyView stop the
		# animation if it sees chunks other than fctl or idat, so we put other
		# chunks to the end of the file
		other_chunks = []
		seq = 0

		# for first frame
		png, control = self.frames[0]

		# header
		out.append(png.hdr)

		# acTL
		out.append(make_chunk("acTL", struct.pack("!II", len(self.frames), self.num_plays)))

		# fcTL
		if control:
			out.append(make_chunk("fcTL", struct.pack("!I", seq) + control.to_bytes()))
			seq += 1

		# and others...
		idat_chunks = []
		for type_, data in png.chunks:
			if type_ in ("IHDR", "IEND"):
				continue
			if type_ == "IDAT":
				# put at last
				idat_chunks.append(data)
				continue
			out.append(data)
		out.extend(idat_chunks)

		# FIXME: we should do some optimization to frames...
		# for other frames
		for png, control in self.frames[1:]:
			# fcTL
			out.append(
				make_chunk("fcTL", struct.pack("!I", seq) + control.to_bytes())
			)
			seq += 1

			# and others...
			for type_, data in png.chunks:
				if type_ in ("IHDR", "IEND") or type_ in CHUNK_BEFORE_IDAT:
					continue
				elif type_ == "IDAT":
					# convert IDAT to fdAT
					out.append(
						make_chunk("fdAT", struct.pack("!I", seq) + data[8:-4])
					)
					seq += 1
				else:
					other_chunks.append(data)

		# end
		out.extend(other_chunks)
		out.append(png.end)

		return b"".join(out)


Instruction:
Make a summary of the following Python 3 code
def from_files(cls, files, **options):
		im = cls()
		for file in files:
			im.append_file(file, **options)
		return im

Response: Create an APNG from multiple files.


Instruction:
How would you implement a function in Python 3 that
creates an APNG from raw bytes.

Response:
def from_bytes(cls, b):
		"""Create an APNG from raw bytes.

		:arg bytes b: The raw bytes of the APNG file.
		:rtype: APNG
		"""
		hdr = None
		head_chunks = []
		end = ("IEND", make_chunk("IEND", b""))

		frame_chunks = []
		frames = []
		num_plays = 0
		frame_has_head_chunks = False

		control = None

		for type_, data in parse_chunks(b):
			if type_ == "IHDR":
				hdr = data
				frame_chunks.append((type_, data))
			elif type_ == "acTL":
				_num_frames, num_plays = struct.unpack("!II", data[8:-4])
				continue
			elif type_ == "fcTL":
				if any(type_ == "IDAT" for type_, data in frame_chunks):
					# IDAT inside chunk, go to next frame
					frame_chunks.append(end)
					frames.append((PNG.from_chunks(frame_chunks), control))
					frame_has_head_chunks = False
					control = FrameControl.from_bytes(data[12:-4])
					# https://github.com/PyCQA/pylint/issues/2072
					# pylint: disable=typecheck
					hdr = make_chunk("IHDR", struct.pack("!II", control.width, control.height) + hdr[16:-4])
					frame_chunks = [("IHDR", hdr)]
				else:
					control = FrameControl.from_bytes(data[12:-4])
			elif type_ == "IDAT":
				if not frame_has_head_chunks:
					frame_chunks.extend(head_chunks)
					frame_has_head_chunks = True
				frame_chunks.append((type_, data))
			elif type_ == "fdAT":
				# convert to IDAT
				if not frame_has_head_chunks:
					frame_chunks.extend(head_chunks)
					frame_has_head_chunks = True
				frame_chunks.append(("IDAT", make_chunk("IDAT", data[12:-4])))
			elif type_ == "IEND":
				# end
				frame_chunks.append(end)
				frames.append((PNG.from_chunks(frame_chunks), control))
				break
			elif type_ in CHUNK_BEFORE_IDAT:
				head_chunks.append((type_, data))
			else:
				frame_chunks.append((type_, data))

		o = cls()
		o.frames = frames
		o.num_plays = num_plays
		return o


Instruction:
Write a Python 3 script for
adding a sensor to the log

Response:
def request_add_sensor(self, sock, msg):
        """ add a sensor
        """
        self.add_sensor(Sensor(int, 'int_sensor%d' % len(self._sensors),
                               'descr', 'unit', params=[-10, 10]))
        return Message.reply('add-sensor', 'ok')


Instruction:
Create a Python 3 function to
normalize the strategy parameters to be a list of strings or numbers.

Response:
def normalize_strategy_parameters(params):
    """Normalize strategy parameters to be a list of strings.

    Parameters
    ----------
    params : (space-delimited) string or sequence of strings/numbers Parameters
        expected by :class:`SampleStrategy` object, in various forms, where the first
        parameter is the name of the strategy.

    Returns
    -------
    params : tuple of strings
        Strategy parameters as a list of strings

    """
    def fixup_numbers(val):
        try:
            # See if it is a number
            return str(float(val))
        except ValueError:
            # ok, it is not a number we know of, perhaps a string
            return str(val)
    if isinstance(params, basestring):
        params = params.split(' ')
    # No number
    return tuple(fixup_numbers(p) for p in params)


Instruction:
Can you tell what is the following Python 3 function doing
def wait(self, sensor_name, condition_or_value, timeout=5):
        sensor_name = escape_name(sensor_name)
        sensor = self.sensor[sensor_name]
        try:
            yield sensor.wait(condition_or_value, timeout)
        except tornado.gen.TimeoutError:
            raise tornado.gen.Return(False)
        else:
            raise tornado.gen.Return(True)

Response: Wait for a sensor in this resource to satisfy a condition.


Instruction:
How would you code a function in Python 3 to
list sensors available on this resource matching certain criteria.

Response:
def list_sensors(self, filter="", strategy=False, status="",
                     use_python_identifiers=True, tuple=False, refresh=False):
        """List sensors available on this resource matching certain criteria.

        Parameters
        ----------
        filter : string, optional
            Filter each returned sensor's name against this regexp if specified.
            To ease the dichotomy between Python identifier names and actual
            sensor names, the default is to search on Python identifier names
            rather than KATCP sensor names, unless `use_python_identifiers`
            below is set to False. Note that the sensors of subordinate
            KATCPResource instances may have inconsistent names and Python
            identifiers, better to always search on Python identifiers in this
            case.
        strategy : {False, True}, optional
            Only list sensors with a set strategy if True
        status : string, optional
            Filter each returned sensor's status against this regexp if given
        use_python_identifiers : {True, False}, optional
            Match on python identfiers even the the KATCP name is available.
        tuple : {True, False}, optional, Default: False
            Return backwards compatible tuple instead of SensorResultTuples
        refresh : {True, False}, optional, Default: False
            If set the sensor values will be refreshed with get_value before
            returning the results.

        Returns
        -------
        sensors : list of SensorResultTuples, or list of tuples
            List of matching sensors presented as named tuples. The `object`
            field is the :class:`KATCPSensor` object associated with the sensor.
            Note that the name of the object may not match `name` if it
            originates from a subordinate device.
        """


Instruction:
Can you generate a brief explanation for the following Python 3 code
def set_sampling_strategies(self, filter, strategy_and_params):
        sensors_strategies = {}
        sensor_results = yield self.list_sensors(filter)
        for sensor_reslt in sensor_results:
            norm_name = sensor_reslt.object.normalised_name
            try:
                sensor_strat = yield self.set_sampling_strategy(norm_name, strategy_and_params)
                sensors_strategies[norm_name] = sensor_strat[norm_name]
            except Exception:
                sensors_strategies[norm_name] = (
                    False, sys.exc_info())
        raise tornado.gen.Return(sensors_strategies)

Response: Set a sampling strategy for all sensors that match the regular expression filter.


Instruction:
Create a Python 3 function for
setting a sampling strategy for a specific sensor.

Response:
def set_sampling_strategy(self, sensor_name, strategy_and_params):
        """Set a sampling strategy for a specific sensor.

        Parameters
        ----------
        sensor_name : string
            The specific sensor.
        strategy_and_params : seq of str or str
            As tuple contains (<strat_name>, [<strat_parm1>, ...]) where the strategy
            names and parameters are as defined by the KATCP spec. As str contains the
            same elements in space-separated form.

        Returns
        -------
        sensors_strategies : tornado Future
           resolves with a dict with the Python identifier names of the sensors
           as keys and the value a tuple:

           (success, info) with

           sucess : bool
              True if setting succeeded for this sensor, else False
           info : tuple
               normalised sensor strategy and parameters as tuple if success == True
               else, sys.exc_info() tuple for the error that occured.
        """
        sensors_strategies = {}
        try:
            sensor_obj = self.sensor.get(sensor_name)
            yield sensor_obj.set_sampling_strategy(strategy_and_params)
            sensors_strategies[sensor_obj.normalised_name] = (
                    True, sensor_obj.sampling_strategy)
        except Exception:
            sensors_strategies[sensor_obj.normalised_name] = (
                    False, sys.exc_info())
        raise tornado.gen.Return(sensors_strategies)


Instruction:
How would you code a function in Python 3 to
set the current sampling strategy for this sensor.

Response:
def set_strategy(self, strategy, params=None):
        """Set current sampling strategy for sensor.
        Add this footprint for backwards compatibility.

        Parameters
        ----------

        strategy : seq of str or str
            As tuple contains (<strat_name>, [<strat_parm1>, ...]) where the strategy
            names and parameters are as defined by the KATCP spec. As str contains the
            same elements in space-separated form.
        params : seq of str or str
            (<strat_name>, [<strat_parm1>, ...])

        Returns
        -------
        done : tornado Future that resolves when done or raises KATCPSensorError

        """
        if not params:
            param_args = []
        elif isinstance(params, basestring):
            param_args = [str(p) for p in params.split(' ')]
        else:
            if not isinstance(params, collections.Iterable):
                params = (params,)
            param_args = [str(p) for p in params]
        samp_strategy = " ".join([strategy] + param_args)
        return self._manager.set_sampling_strategy(self.name, samp_strategy)


Instruction:
Can you create a Python 3 function that
registers a callback function that is called when sensor value is updated.

Response:
def register_listener(self, listener, reading=False):
        """Add a callback function that is called when sensor value is updated.
        The callback footprint is received_timestamp, timestamp, status, value.

        Parameters
        ----------
        listener : function
            Callback signature: if reading
            listener(katcp_sensor, reading) where
                `katcp_sensor` is this KATCPSensor instance
                `reading` is an instance of :class:`KATCPSensorReading`
            Callback signature: default, if not reading
                listener(received_timestamp, timestamp, status, value)
        """
        listener_id = hashable_identity(listener)
        self._listeners[listener_id] = (listener, reading)
        logger.debug(
                    'Register listener for {}'
                    .format(self.name))


Instruction:
Can you generate a brief explanation for the following Python 3 code
def unregister_listener(self, listener):
        listener_id = hashable_identity(listener)
        self._listeners.pop(listener_id, None)

Response: Unregister a callback function.


Instruction:
How would you code a function in Python 3 to
set sensor with a given received value matches a given status.

Response:
def set(self, timestamp, status, value):
        """Set sensor with a given received value, matches :meth:`katcp.Sensor.set`"""
        received_timestamp = self._manager.time()
        reading = KATCPSensorReading(received_timestamp, timestamp, status, value)
        self._reading = reading
        self.call_listeners(reading)


Instruction:
Implement a Python 3 function for
setting sensor value with optinal specification of status and timestamp

Response:
def set_value(self, value, status=Sensor.NOMINAL, timestamp=None):
        """Set sensor value with optinal specification of status and timestamp"""
        if timestamp is None:
            timestamp = self._manager.time()
        self.set(timestamp, status, value)


Instruction:
Can you implement a function in Python 3 that
gets a fresh sensor reading from the KATCP resource

Response:
def get_reading(self):
        """Get a fresh sensor reading from the KATCP resource

        Returns
        -------
        reply : tornado Future resolving with  :class:`KATCPSensorReading` object

        Note
        ----

        As a side-effect this will update the reading stored in this object, and result in
        registered listeners being called.
        """
        yield self._manager.poll_sensor(self._name)
        # By now the sensor manager should have set the reading
        raise Return(self._reading)


Instruction:
Here you have a function in Python 3, explain what it does
def get_value(self):
        yield self._manager.poll_sensor(self._name)
        # By now the sensor manager should have set the reading
        raise Return(self._reading.value)

Response: Get a fresh sensor value from the KATCP resource


Instruction:
Here you have a function in Python 3, explain what it does
def get_status(self):
        yield self._manager.poll_sensor(self._name)
        # By now the sensor manager should have set the reading
        raise Return(self._reading.status)

Response: Get a fresh sensor status from the KATCP resource


Instruction:
Implement a function in Python 3 to
wait for the current sensor to satisfy a condition.

Response:
def wait(self, condition_or_value, timeout=None):
        """Wait for the sensor to satisfy a condition.

        Parameters
        ----------
        condition_or_value : obj or callable, or seq of objs or callables
            If obj, sensor.value is compared with obj. If callable,
            condition_or_value(reading) is called, and must return True if its
            condition is satisfied. Since the reading is passed in, the value,
            status, timestamp or received_timestamp attributes can all be used
            in the check.
            TODO: Sequences of conditions (use SensorTransitionWaiter thingum?)
        timeout : float or None
            The timeout in seconds (None means wait forever)

        Returns
        -------
        This command returns a tornado Future that resolves with True when the
        sensor value satisfies the condition. It will never resolve with False;
        if a timeout is given a TimeoutError happens instead.

        Raises
        ------
        :class:`KATCPSensorError`
            If the sensor does not have a strategy set
        :class:`tornado.gen.TimeoutError`
            If the sensor condition still fails after a stated timeout period

        """
        if (isinstance(condition_or_value, collections.Sequence) and not
                isinstance(condition_or_value, basestring)):
            raise NotImplementedError(
                'Currently only single conditions are supported')
        condition_test = (condition_or_value if callable(condition_or_value)
                          else lambda s: s.value == condition_or_value)

        ioloop = tornado.ioloop.IOLoop.current()
        f = Future()
        if self.sampling_strategy == ('none', ):
            raise KATCPSensorError(
                'Cannot wait on a sensor that does not have a strategy set')

        def handle_update(sensor, reading):
            # This handler is called whenever a sensor update is received
            try:
                assert sensor is self
                if condition_test(reading):
                    self.unregister_listener(handle_update)
                    # Try and be idempotent if called multiple times after the
                    # condition is matched. This should not happen unless the
                    # sensor object is being updated in a thread outside of the
                    # ioloop.
                    if not f.done():
                        ioloop.add_callback(f.set_result, True)
            except Exception:
                f.set_exc_info(sys.exc_info())
                self.unregister_listener(handle_update)

        self.register_listener(handle_update, reading=True)
        # Handle case where sensor is already at the desired value
        ioloop.add_callback(handle_update, self, self._reading)

        if timeout:
            to = ioloop.time() + timeout
            timeout_f = with_timeout(to, f)
            # Make sure we stop listening if the wait times out to prevent a
            # buildup of listeners
            timeout_f.add_done_callback(
                lambda f: self.unregister_listener(handle_update))
            return timeout_f
        else:
            return f


Instruction:
Make a summary of the following Python 3 code
def fake_KATCP_client_resource_factory(
        KATCPClientResourceClass, fake_options, resource_spec, *args, **kwargs):
    """Create a fake KATCPClientResource-like class and a fake-manager

    Parameters
    ----------
    KATCPClientResourceClass : class
        Subclass of :class:`katcp.resource_client.KATCPClientResource`
    fake_options : dict
        Options for the faking process. Keys:
            allow_any_request : bool, default False
            (TODO not implemented behaves as if it were True)
    resource_spec, *args, **kwargs : passed to KATCPClientResourceClass

    A subclass of the passed-in KATCPClientResourceClass is created that replaces the
    internal InspecingClient instances with fakes using fake_inspecting_client_factory()
    based on the InspectingClient class used by KATCPClientResourceClass.

    Returns
    -------
    (fake_katcp_client_resource, fake_katcp_client_resource_manager):

    fake_katcp_client_resource : instance of faked subclass of KATCPClientResourceClass
    fake_katcp_client_resource_manager : :class:`FakeKATCPClientResourceManager` instance
        Bound to the `fake_katcp_client_resource` instance.

    """
    # TODO Implement allow_any_request functionality. When True, any unknown request (even
    # if there is no fake implementation) should succeed
    allow_any_request = fake_options.get('allow_any_request', False)

    class FakeKATCPClientResource(KATCPClientResourceClass):
        def inspecting_client_factory(self, host, port, ioloop_set_to):
            real_instance = (super(FakeKATCPClientResource, self)
                             .inspecting_client_factory(host, port, ioloop_set_to) )
            fic, fic_manager = fake_inspecting_client_factory(
                real_instance.__class__, fake_options, host, port,
                ioloop=ioloop_set_to, auto_reconnect=self.auto_reconnect)
            self.fake_inspecting_client_manager = fic_manager
            return fic

    fkcr = FakeKATCPClientResource(resource_spec, *args, **kwargs)
    fkcr_manager = FakeKATCPClientResourceManager(fkcr)
    return (fkcr, fkcr_manager)

Response: Create a fake KATCPClientResource - like class and a fake - manager for the given resource_spec.


Instruction:
How would you explain what the following Python 3 function does
def fake_KATCP_client_resource_container_factory(
        KATCPClientResourceContainerClass, fake_options, resources_spec,
        *args, **kwargs):
    """Create a fake KATCPClientResourceContainer-like class and a fake-manager

    Parameters
    ----------
    KATCPClientResourceContainerClass : class
        Subclass of :class:`katcp.resource_client.KATCPClientResourceContainer`
    fake_options : dict
        Options for the faking process. Keys:
            allow_any_request : bool, default False
            (TODO not implemented behaves as if it were True)
    resources_spec, *args, **kwargs : passed to KATCPClientResourceContainerClass

    A subclass of the passed-in KATCPClientResourceClassContainer is created that replaces the
    KATCPClientResource child instances with fakes using fake_KATCP_client_resource_factory()
    based on the KATCPClientResource class used by `KATCPClientResourceContainerClass`.

    Returns
    -------
    (fake_katcp_client_resource_container, fake_katcp_client_resource_container_manager):

    fake_katcp_client_resource_container : instance of faked subclass of
                                           KATCPClientResourceContainerClass
    fake_katcp_client_resource_manager : :class:`FakeKATCPClientResourceContainerManager`
                                         instance
        Bound to the `fake_katcp_client_resource_container` instance.

    """
    # TODO allow_any_request see comment in fake_KATCP_client_resource_factory()
    allow_any_request = fake_options.get('allow_any_request', False)

    class FakeKATCPClientResourceContainer(KATCPClientResourceContainerClass):
        def __init__(self, *args, **kwargs):
            self.fake_client_resource_managers = {}
            super(FakeKATCPClientResourceContainer, self).__init__(*args, **kwargs)

        def client_resource_factory(self, res_spec, parent, logger):
            real_instance = (super(FakeKATCPClientResourceContainer, self)
                             .client_resource_factory(res_spec, parent, logger) )
            fkcr, fkcr_manager = fake_KATCP_client_resource_factory(
                real_instance.__class__, fake_options,
                res_spec, parent=self, logger=logger)
            self.fake_client_resource_managers[
                resource.escape_name(fkcr.name)] = fkcr_manager
            return fkcr

    fkcrc = FakeKATCPClientResourceContainer(resources_spec, *args, **kwargs)
    fkcrc_manager = FakeKATCPClientResourceContainerManager(fkcrc)
    return (fkcrc, fkcrc_manager)

Response: Create a fake KATCPClientResourceContainer - like class and a fake - manager for the given resources_spec.


Instruction:
Implement a function in Python 3 to
request a list of sensors.

Response:
def request_sensor_list(self, req, msg):
        """Sensor list"""
        if msg.arguments:
            name = (msg.arguments[0],)
            keys = (name, )
            if name not in self.fake_sensor_infos:
                return ("fail", "Unknown sensor name.")
        else:
            keys = self.fake_sensor_infos.keys()

        num_informs = 0
        for sensor_name in keys:
            infos = self.fake_sensor_infos[sensor_name]
            num_informs += 1
            req.inform(sensor_name, *infos)

        return ('ok', num_informs)


Instruction:
Explain what the following Python 3 code does
def add_sensors(self, sensor_infos):
        # Check sensor validity. parse_type() and parse_params should raise if not OK
        for s_name, s_info in sensor_infos.items():
            s_type = Sensor.parse_type(s_info[2])
            s_params = Sensor.parse_params(s_type, s_info[3:])
        self.fake_sensor_infos.update(sensor_infos)
        self._fic._interface_changed.set()

Response: Add fake sensors to the internal list of sensors.


Instruction:
How would you explain what the following Python 3 function does
def add_request_handlers_object(self, rh_obj):
        rh_dict = {}
        for name in dir(rh_obj):
            if not callable(getattr(rh_obj, name)):
                continue
            if name.startswith("request_"):
                request_name = convert_method_name("request_", name)
                req_meth = getattr(rh_obj, name)
                rh_dict[request_name] = req_meth

        self.add_request_handlers_dict(rh_dict)

Response: Add fake request handlers from an object with request_ * method s.


Instruction:
Can you implement a function in Python 3 that
adds fake request handlers from a dict keyed by request name and request - handler interface.

Response:
def add_request_handlers_dict(self, rh_dict):
        """Add fake request handler functions from a dict keyed by request name

        Note the keys must be the KATCP message name (i.e. "the-request", not
        "the_request")

        The request-handler interface is more or less compatible with request handler API
        in :class:`katcp.server.DeviceServerBase`. The fake ClientRequestConnection req
        object does not support mass_inform() or reply_with_message.

        """
        # Check that all the callables have docstrings as strings
        for req_func in rh_dict.values():
            assert req_func.__doc__, "Even fake request handlers must have docstrings"
        self._fkc.request_handlers.update(rh_dict)
        self._fic._interface_changed.set()


Instruction:
Write a Python 3 script for
sending a request message with future replies.

Response:
def future_request(self, msg, timeout=None, use_mid=None):
        """Send a request messsage, with future replies.

        Parameters
        ----------
        msg : Message object
            The request Message to send.
        timeout : float in seconds
            How long to wait for a reply. The default is the
            the timeout set when creating the AsyncClient.
        use_mid : boolean, optional
            Whether to use message IDs. Default is to use message IDs
            if the server supports them.

        Returns
        -------
        A tornado.concurrent.Future that resolves with:

        reply : Message object
            The reply message received.
        informs : list of Message objects
            A list of the inform messages received.

        """
        mid = self._get_mid_and_update_msg(msg, use_mid)

        if msg.name in self.request_handlers:
            req = FakeClientRequestConnection(self.client_connection, msg)
            reply_msg = yield tornado.gen.maybe_future(
                self.request_handlers[msg.name](req, msg))
            reply_informs = req.informs_sent
        else:
            reply_msg = Message.reply(msg.name, 'ok')
            reply_informs = []

        reply_msg.mid = mid
        raise Return((reply_msg, reply_informs))


Instruction:
Create a Python 3 function to
call whenever an action has failed

Response:
def failed(self):
        """Call whenever an action has failed, grows delay exponentially

        After calling failed(), the `delay` property contains the next delay
        """
        try:
            self._validate_parameters()
            self._base_delay = min(
                self._base_delay * self.exp_fac,
                self.delay_max)
            self._update_delay()
        except Exception:
            ic_logger.exception(
                'Unhandled exception trying to calculate a retry timout')


Instruction:
Here you have a function in Python 3, explain what it does
def hook_inform(self, inform_name, callback):
        # Do not hook the same callback multiple times
        if callback not in self._inform_hooks[inform_name]:
            self._inform_hooks[inform_name].append(callback)

Response: Hookup a function to be called when an inform is received.


Instruction:
Write a Python 3 function for
calling callbacks on hooked informs followed by normal processing

Response:
def handle_inform(self, msg):
        """Call callbacks on hooked informs followed by normal processing"""
        try:
            for func in self._inform_hooks.get(msg.name, []):
                func(msg)
        except Exception:
            self._logger.warning('Call to function "{0}" with message "{1}".'
                                 .format(func, msg), exc_info=True)
        super(_InformHookDeviceClient, self).handle_inform(msg)


Instruction:
Implement a function in Python 3 to
return an instance of _InformHookDeviceClient or similar

Response:
def inform_hook_client_factory(self, host, port, *args, **kwargs):
        """Return an instance of :class:`_InformHookDeviceClient` or similar

        Provided to ease testing. Dynamically overriding this method after instantiation
        but before start() is called allows for deep brain surgery. See
        :class:`katcp.fake_clients.TBD`

        """
        return _InformHookDeviceClient(host, port, *args, **kwargs)


Instruction:
Write a Python 3 script for
waiting until state is desired_state

Response:
def until_state(self, desired_state, timeout=None):
        """
        Wait until state is desired_state, InspectingClientStateType instance

        Returns a future

        """
        return self._state.until_state(desired_state, timeout=timeout)


Instruction:
Given the following Python 3 function, write the documentation
def connect(self, timeout=None):
        # Start KATCP device client.
        assert not self._running
        maybe_timeout = future_timeout_manager(timeout)

        self._logger.debug('Starting katcp client')
        self.katcp_client.start()
        try:
            yield maybe_timeout(self.katcp_client.until_running())
            self._logger.debug('Katcp client running')
        except tornado.gen.TimeoutError:
            self.katcp_client.stop()
            raise

        if timeout:
            yield maybe_timeout(self.katcp_client.until_connected())
        self._logger.debug('Katcp client connected')

        self._running = True
        self._state_loop()

Response: Connect to KATCP interface.


Instruction:
Can you tell what is the following Python 3 function doing
def inspect(self):
        timeout_manager = future_timeout_manager(self.sync_timeout)
        sensor_index_before = copy.copy(self._sensors_index)
        request_index_before = copy.copy(self._requests_index)
        try:
            request_changes = yield self.inspect_requests(
                timeout=timeout_manager.remaining())
            sensor_changes = yield self.inspect_sensors(
                timeout=timeout_manager.remaining())
        except Exception:
            # Ensure atomicity of sensor and request updates ; if the one
            # fails, the other should act as if it has failed too.
            self._sensors_index = sensor_index_before
            self._requests_index = request_index_before
            raise

        model_changes = AttrDict()
        if request_changes:
            model_changes.requests = request_changes
        if sensor_changes:
            model_changes.sensors = sensor_changes
        if model_changes:
            raise Return(model_changes)

Response:
Inspect device requests and sensors update model
            Returns ------- Tornado future that resolves with :


Instruction:
Write a Python 3 script for
inspecting all or one requests on the device.

Response:
def inspect_requests(self, name=None, timeout=None):
        """Inspect all or one requests on the device. Update requests index.

        Parameters
        ----------
        name : str or None, optional
            Name of the request or None to get all requests.
        timeout : float or None, optional
            Timeout for request inspection, None for no timeout

        Returns
        -------
        Tornado future that resolves with:

        changes : :class:`~katcp.core.AttrDict`
            AttrDict with keys ``added`` and ``removed`` (of type
            :class:`set`), listing the requests that have been added or removed
            respectively.  Modified requests are listed in both. If there are
            no changes, returns ``None`` instead.

            Example structure:

            {'added': set(['req1', 'req2']),
             'removed': set(['req10', 'req20'])}

        """
        maybe_timeout = future_timeout_manager(timeout)
        if name is None:
            msg = katcp.Message.request('help')
        else:
            msg = katcp.Message.request('help', name)
        reply, informs = yield self.katcp_client.future_request(
            msg, timeout=maybe_timeout.remaining())
        if not reply.reply_ok():
            # If an unknown request is specified the desired result is to return
            # an empty list even though the request will fail
            if name is None or 'Unknown request' not in reply.arguments[1]:
                raise SyncError(
                    'Error reply during sync process for {}: {}'
                    .format(self.bind_address_string, reply))

        # Get recommended timeouts hints for slow requests if the server
        # provides them
        timeout_hints_available = (
            self.katcp_client.protocol_flags.request_timeout_hints)
        if timeout_hints_available:
            timeout_hints = yield self._get_request_timeout_hints(
                name, timeout=maybe_timeout.remaining())
        else:
            timeout_hints = {}

        requests_old = set(self._requests_index.keys())
        requests_updated = set()
        for msg in informs:
            req_name = msg.arguments[0]
            req = {'name': req_name,
                   'description': msg.arguments[1],
                   'timeout_hint': timeout_hints.get(req_name)}
            requests_updated.add(req_name)
            self._update_index(self._requests_index, req_name, req)

        added, removed = self._difference(
            requests_old, requests_updated, name, self._requests_index)
        if added or removed:
            raise Return(AttrDict(added=added, removed=removed))


Instruction:
Create a Python 3 function to
get request timeout hints from device.

Response:
def _get_request_timeout_hints(self, name=None, timeout=None):
        """Get request timeout hints from device

        Parameters
        =========
        name : str or None, optional
            Name of the request or None to get all request timeout hints.
        timeout : float seconds
            Timeout for ?request-timeout-hint

        Returns
        -------
        Tornado future that resolves with:

        timeout_hints : dict request_name -> timeout_hint

        where

        request_name : str
            Name of the request
        timeout_hint : float
            Suggested request timeout hint from device ?request-timeout_hint

        Note, if there is no request hint, there will be no entry in the
        dict. If you request the hint for a named request that has no hint, an
        empty dict will be returned.

        """
        timeout_hints = {}
        req_msg_args = ['request-timeout-hint']
        if name:
            req_msg_args.append(name)
        req_msg = katcp.Message.request(*req_msg_args)
        reply, informs = yield self.katcp_client.future_request(
            req_msg, timeout=timeout)
        if not reply.reply_ok():
            raise SyncError('Error retrieving request timeout hints: "{}"\n'
                            'in reply to request {}, continuing with sync'
                            .format(reply, req_msg))
        for inform in informs:
            request_name = inform.arguments[0]
            timeout_hint = float(inform.arguments[1])
            if timeout_hint > 0:
                timeout_hints[request_name] = timeout_hint
        raise Return(timeout_hints)


Instruction:
How would you code a function in Python 3 to
inspect all or one sensor on the device.

Response:
def inspect_sensors(self, name=None, timeout=None):
        """Inspect all or one sensor on the device. Update sensors index.

        Parameters
        ----------
        name : str or None, optional
            Name of the sensor or None to get all sensors.
        timeout : float or None, optional
            Timeout for sensors inspection, None for no timeout

        Returns
        -------
        Tornado future that resolves with:

        changes : :class:`~katcp.core.AttrDict`
            AttrDict with keys ``added`` and ``removed`` (of type
            :class:`set`), listing the sensors that have been added or removed
            respectively.  Modified sensors are listed in both. If there are no
            changes, returns ``None`` instead.

        Example structure:

            {'added': set(['sens1', 'sens2']),
             'removed': set(['sens10', 'sens20'])}

        """
        if name is None:
            msg = katcp.Message.request('sensor-list')
        else:
            msg = katcp.Message.request('sensor-list', name)

        reply, informs = yield self.katcp_client.future_request(
            msg, timeout=timeout)
        self._logger.debug('{} received {} sensor-list informs, reply: {}'
            .format(self.bind_address_string, len(informs), reply))
        if not reply.reply_ok():
            # If an unknown sensor is specified the desired result is to return
            # an empty list, even though the request will fail
            if name is None or 'Unknown sensor' not in reply.arguments[1]:
                raise SyncError('Error reply during sync process: {}'
                                .format(reply))

        sensors_old = set(self._sensors_index.keys())
        sensors_updated = set()
        for msg in informs:
            sen_name = msg.arguments[0]
            sensors_updated.add(sen_name)
            sen = {'description': msg.arguments[1],
                   'units': msg.arguments[2],
                   'sensor_type': msg.arguments[3],
                   'params': msg.arguments[4:]}
            self._update_index(self._sensors_index, sen_name, sen)

        added, removed = self._difference(
            sensors_old, sensors_updated, name, self._sensors_index)

        for sensor_name in removed:
            if sensor_name in self._sensor_object_cache:
                del self._sensor_object_cache[sensor_name]

        if added or removed:
            raise Return(AttrDict(added=added, removed=removed))


Instruction:
How would you explain what the following Python 3 function does
def future_check_sensor(self, name, update=None):
        exist = False
        yield self.until_data_synced()
        if name in self._sensors_index:
            exist = True
        else:
            if update or (update is None and self._update_on_lookup):
                yield self.inspect_sensors(name)
                exist = yield self.future_check_sensor(name, False)

        raise tornado.gen.Return(exist)

Response: Check if the sensor exists.


Instruction:
How would you implement a function in Python 3 that
gets the sensor object.

Response:
def future_get_sensor(self, name, update=None):
        """Get the sensor object.

        Check if we have information for this sensor, if not connect to server
        and update (if allowed) to get information.

        Parameters
        ----------
        name : string
            Name of the sensor.
        update : bool or None, optional
            True allow inspect client to inspect katcp server if the sensor
            is not known.

        Returns
        -------
        Sensor created by :meth:`sensor_factory` or None if sensor not found.

        Notes
        -----
        Ensure that self.state.data_synced == True if yielding to future_get_sensor from
        a state-change callback, or a deadlock will occur.

        """
        obj = None
        exist = yield self.future_check_sensor(name, update)
        if exist:
            sensor_info = self._sensors_index[name]
            obj = sensor_info.get('obj')
            if obj is None:
                sensor_type = katcp.Sensor.parse_type(
                    sensor_info.get('sensor_type'))
                sensor_params = katcp.Sensor.parse_params(
                    sensor_type,
                    sensor_info.get('params'))
                obj = self.sensor_factory(
                    name=name,
                    sensor_type=sensor_type,
                    description=sensor_info.get('description'),
                    units=sensor_info.get('units'),
                    params=sensor_params)
                self._sensors_index[name]['obj'] = obj
                self._sensor_object_cache[name] = obj

        raise tornado.gen.Return(obj)


Instruction:
Can you generate a brief explanation for the following Python 3 code
def future_check_request(self, name, update=None):
        exist = False
        yield self.until_data_synced()
        if name in self._requests_index:
            exist = True
        else:
            if update or (update is None and self._update_on_lookup):
                yield self.inspect_requests(name)
                exist = yield self.future_check_request(name, False)
        raise tornado.gen.Return(exist)

Response: Checks if the request exists.


Instruction:
Given the following Python 3 function, write the documentation
def future_get_request(self, name, update=None):
        obj = None
        exist = yield self.future_check_request(name, update)
        if exist:
            request_info = self._requests_index[name]
            obj = request_info.get('obj')
            if obj is None:
                obj = self.request_factory(**request_info)
                self._requests_index[name]['obj'] = obj

        raise tornado.gen.Return(obj)

Response: Get the request object.


Instruction:
Given the following Python 3 function, write the documentation
def _cb_inform_sensor_status(self, msg):
        timestamp = msg.arguments[0]
        num_sensors = int(msg.arguments[1])
        assert len(msg.arguments) == 2 + num_sensors * 3
        for n in xrange(num_sensors):
            name = msg.arguments[2 + n * 3]
            status = msg.arguments[3 + n * 3]
            value = msg.arguments[4 + n * 3]
            self.update_sensor(name, timestamp, status, value)

Response: Update received for an sensor.


Instruction:
Write a Python 3 function that can
update the sensors and requests available.

Response:
def _cb_inform_interface_change(self, msg):
        """Update the sensors and requests available."""
        self._logger.debug('cb_inform_interface_change(%s)', msg)
        self._interface_changed.set()


Instruction:
Make a summary of the following Python 3 code
def simple_request(self, request, *args, **kwargs):
        # TODO (NM 2016-11-03) This method should really live on the lower level
        # katcp_client in client.py, is generally useful IMHO
        use_mid = kwargs.get('use_mid')
        timeout = kwargs.get('timeout')
        mid = kwargs.get('mid')
        msg = katcp.Message.request(request, *args, mid=mid)
        return self.katcp_client.future_request(msg, timeout, use_mid)

Response: Create and send a request to the server.


Instruction:
How would you code a function in Python 3 to
calculate the difference between the original and updated sets of keys.

Response:
def _difference(self, original_keys, updated_keys, name, item_index):
        """Calculate difference between the original and updated sets of keys.

        Removed items will be removed from item_index, new items should have
        been added by the discovery process. (?help or ?sensor-list)

        This method is for use in inspect_requests and inspect_sensors only.

        Returns
        -------

        (added, removed)
        added : set of str
            Names of the keys that were added
        removed : set of str
            Names of the keys that were removed

        """
        original_keys = set(original_keys)
        updated_keys = set(updated_keys)
        added_keys = updated_keys.difference(original_keys)
        removed_keys = set()
        if name is None:
            removed_keys = original_keys.difference(updated_keys)
        elif name not in updated_keys and name in original_keys:
            removed_keys = set([name])

        for key in removed_keys:
            if key in item_index:
                del(item_index[key])

        # Check the keys that was not added now or not lined up for removal,
        # and see if they changed.
        for key in updated_keys.difference(added_keys.union(removed_keys)):
            if item_index[key].get('_changed'):
                item_index[key]['_changed'] = False
                removed_keys.add(key)
                added_keys.add(key)

        return added_keys, removed_keys


Instruction:
Create a Python 3 function for
picking a random fruit.

Response:
def request_pick_fruit(self, req):
        """Pick a random fruit."""
        r = random.choice(self.FRUIT + [None])
        if r is None:
            return ("fail", "No fruit.")
        delay = random.randrange(1,5)
        req.inform("Picking will take %d seconds" % delay)

        def pick_handler():
            self._fruit_result.set_value(r)
            req.reply("ok", r)

        self.ioloop.add_callback(
            self.ioloop.call_later, delay, pick_handler)

        raise AsyncReply


Instruction:
Here you have a function in Python 3, explain what it does
def update_in_ioloop(update):
    @wraps(update)
    def wrapped_update(self, sensor, reading):
        if get_thread_ident() == self._ioloop_thread_id:
            update(self, sensor, reading)
        else:
            self.ioloop.add_callback(update, self, sensor, reading)

    return wrapped_update

Response: Decorator that ensures an update method is run in the tornado ioloop.


Instruction:
Given the following Python 3 function, write the documentation
def get_strategy(cls, strategyName, inform_callback, sensor,
                     *params, **kwargs):
        """Factory method to create a strategy object.

        Parameters
        ----------
        strategyName : str
            Name of strategy.
        inform_callback : callable, signature inform_callback(sensor, reading)
            Callback to receive inform messages.
        sensor : Sensor object
            Sensor to sample.
        params : list of objects
            Custom sampling parameters for specified strategy.

        Keyword Arguments
        -----------------
        ioloop : tornado.ioloop.IOLoop instance, optional
            Tornado ioloop to use, otherwise tornado.ioloop.IOLoop.current()

        Returns
        -------
        strategy : :class:`SampleStrategy` object
            The created sampling strategy.

        """
        if strategyName not in cls.SAMPLING_LOOKUP_REV:
            raise ValueError("Unknown sampling strategy '%s'. "
                             "Known strategies are %s."
                             % (strategyName, cls.SAMPLING_LOOKUP.values()))

        strategyType = cls.SAMPLING_LOOKUP_REV[strategyName]
        if strategyType == cls.NONE:
            return SampleNone(inform_callback, sensor, *params, **kwargs)
        elif strategyType == cls.AUTO:
            return SampleAuto(inform_callback, sensor, *params, **kwargs)
        elif strategyType == cls.EVENT:
            return SampleEvent(inform_callback, sensor, *params, **kwargs)
        elif strategyType == cls.DIFFERENTIAL:
            return SampleDifferential(inform_callback, sensor,
                                      *params, **kwargs)
        elif strategyType == cls.PERIOD:
            return SamplePeriod(inform_callback, sensor, *params, **kwargs)
        elif strategyType == cls.EVENT_RATE:
            return SampleEventRate(inform_callback, sensor, *params, **kwargs)
        elif strategyType == cls.DIFFERENTIAL_RATE:
            return SampleDifferentialRate(inform_callback, sensor,
                                          *params, **kwargs)

Response: Returns an instance of the appropriate subclass of SampleStrategy.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def get_sampling_formatted(self):
        strategy = self.get_sampling()
        strategy = self.SAMPLING_LOOKUP[strategy]
        params = [str(p) for p in self._params]
        return strategy, params

Response: Returns the current sampling strategy and parameters.


Instruction:
Can you implement a function in Python 3 that
attaches strategy to its sensor and send initial update.

Response:
def attach(self):
        """Attach strategy to its sensor and send initial update."""
        s = self._sensor
        self.update(s, s.read())
        self._sensor.attach(self)


Instruction:
How would you code a function in Python 3 to
detach strategy from its sensor and cancel ioloop callbacks.

Response:
def cancel(self):
        """Detach strategy from its sensor and cancel ioloop callbacks."""
        if self.OBSERVE_UPDATES:
            self.detach()
        self.ioloop.add_callback(self.cancel_timeouts)


Instruction:
Write a Python 3 function that can
start operating the strategy.

Response:
def start(self):
        """Start operating the strategy.

        Subclasses that override start() should call the super method before
        it does anything that uses the ioloop. This will attach to the sensor
        as an observer if :attr:`OBSERVE_UPDATES` is True, and sets
        :attr:`_ioloop_thread_id` using `thread.get_ident()`.

        """
        def first_run():
            self._ioloop_thread_id = get_thread_ident()
            if self.OBSERVE_UPDATES:
                self.attach()
        self.ioloop.add_callback(first_run)


Instruction:
Implement a Python 3 function for
informing strategy creator of the sensor status.

Response:
def inform(self, reading):
        """Inform strategy creator of the sensor status."""
        try:
            self._inform_callback(self._sensor, reading)
        except Exception:
            log.exception('Unhandled exception trying to send {!r} '
                          'for sensor {!r} of type {!r}'
                          .format(reading, self._sensor.name, self._sensor.type))


Instruction:
Given the following Python 3 function, write the documentation
def start(self, timeout=None):
        if not self._ioloop:
            raise RuntimeError('Call get_ioloop() or set_ioloop() first')

        self._ioloop.add_callback(self._running.set)

        if self._ioloop_managed:
            self._run_managed_ioloop()
        else:            #  TODO this seems inconsistent with what the docstring describes
            self._running.set()

        if timeout:
            return self._running.wait(timeout)

Response: Start managed ioloop thread or do nothing if not managed.


Instruction:
How would you code a function in Python 3 to
stop the ioloop and wait for it to finish.

Response:
def stop(self, timeout=None, callback=None):
        """Stop ioloop (if managed) and call callback in ioloop before close.

        Parameters
        ----------
        timeout : float or None
            Seconds to wait for ioloop to have *started*.

        Returns
        -------
        stopped : thread-safe Future
            Resolves when the callback() is done

        """
        if timeout:
            self._running.wait(timeout)

        stopped_future = Future()

        @gen.coroutine
        def _stop():
            if callback:
                try:
                    yield gen.maybe_future(callback())
                except Exception:
                    self._logger.exception('Unhandled exception calling stop callback')
            if self._ioloop_managed:
                self._logger.info('Stopping ioloop {0!r}'.format(self._ioloop))
                # Allow ioloop to run once before stopping so that callbacks
                # scheduled by callback() above get a chance to run.
                yield gen.moment
                self._ioloop.stop()
            self._running.clear()

        try:
            self._ioloop.add_callback(
                lambda: gen.chain_future(_stop(), stopped_future))
        except AttributeError:
            # Probably we have been shut-down already
            pass

        return stopped_future


Instruction:
Can you generate a brief explanation for the following Python 3 code
def join(self, timeout=None):
        if not self._ioloop_managed:
            # Do nothing if the loop is not managed
            return
        try:
            self._ioloop_thread.join(timeout)
        except AttributeError:
            raise RuntimeError('Cannot join if not started')

Response: Join managed ioloop thread or do nothing if not managed.


Instruction:
Make a summary of the following Python 3 code
def decorate_callable(self, callable_):
        @wraps(callable_)
        def decorated(*args, **kwargs):
            # Extract timeout from request itself or use default for ioloop wrapper
            timeout = kwargs.get('timeout')
            return self.call_in_ioloop(callable_, args, kwargs, timeout)

        decorated.__doc__ = '\n\n'.join((
"""Wrapped async call. Will call in ioloop.

This call will block until the original callable has finished running on the ioloop, and
will pass on the return value. If the original callable returns a future, this call will
wait for the future to resolve and return the value or raise the exception that the future
resolves with.

Original Callable Docstring
---------------------------
""",
            textwrap.dedent(decorated.__doc__ or '')))

        return decorated

Response: Decorate a callable to use call_in_ioloop


Instruction:
How would you explain what the following Python 3 function does
def update(self, sensor, reading):
        parents = list(self._child_to_parents[sensor])
        for parent in parents:
            self.recalculate(parent, (sensor,))

Response: Update callback used by sensors to notify obervers of changes.


Instruction:
Create a Python 3 function to
add a new sensor to the tree.

Response:
def _add_sensor(self, sensor):
        """Add a new sensor to the tree.

        Parameters
        ----------
        sensor : :class:`katcp.Sensor` object
            New sensor to add to the tree.

        """
        self._parent_to_children[sensor] = set()
        self._child_to_parents[sensor] = set()


Instruction:
Explain what the following Python 3 code does
def add_links(self, parent, children):
        new_sensors = []
        if parent not in self:
            self._add_sensor(parent)
            new_sensors.append(parent)
        for child in children:
            if child not in self:
                self._add_sensor(child)
                new_sensors.append(child)
            self._parent_to_children[parent].add(child)
            self._child_to_parents[child].add(parent)

        self.recalculate(parent, children)
        for sensor in new_sensors:
            sensor.attach(self)

Response: Create dependency links from parent to child.


Instruction:
Write a Python 3 function for
removing dependency links from parent to children.

Response:
def remove_links(self, parent, children):
        """Remove dependency links from parent to child.

        Any sensors that have no dependency links are removed from the tree and
        the tree detaches from each sensor removed. After all dependency links
        have been removed the parent is recalculated. Links that don't exist
        are ignored.

        Parameters
        ----------
        parent : :class:`katcp.Sensor` object
            The sensor that used to depend on children.
        children : sequence of :class:`katcp.Sensor` objects
            The sensors that parent used to depend on.

        """
        old_sensors = []
        if parent in self:
            for child in children:
                if child not in self:
                    continue
                self._parent_to_children[parent].discard(child)
                self._child_to_parents[child].discard(parent)
                if not self._child_to_parents[child] and \
                        not self._parent_to_children[child]:
                    self._remove_sensor(child)
                    old_sensors.append(child)
            if not self._child_to_parents[parent] and \
                    not self._parent_to_children[parent]:
                self._remove_sensor(parent)
                old_sensors.append(parent)

        for sensor in old_sensors:
            sensor.detach(self)
        self.recalculate(parent, children)


Instruction:
Given the following Python 3 function, write the documentation
def children(self, parent):
        if parent not in self._parent_to_children:
            raise ValueError("Parent sensor %r not in tree." % parent)
        return self._parent_to_children[parent].copy()

Response: Return set of children of parent.


Instruction:
Explain what the following Python 3 code does
def parents(self, child):
        if child not in self._child_to_parents:
            raise ValueError("Child sensor %r not in tree." % child)
        return self._child_to_parents[child].copy()

Response: Return set of parents of child.


Instruction:
Write a Python 3 function for
adding a pair of boolean sensors. Parent depends on child.

Response:
def add(self, parent, child):
        """Add a pair of boolean sensors.

        Parent depends on child.

        Parameters
        ----------
        parent : boolean instance of :class:`katcp.Sensor`
            The sensor that depends on child.
        child : boolean instance of :class:`katcp.Sensor`
            The sensor parent depends on.

        """
        if parent not in self:
            if parent.stype != "boolean":
                raise ValueError("Parent sensor %r is not boolean" % child)
            self._parent_to_not_ok[parent] = set()
        if child not in self:
            if child.stype != "boolean":
                raise ValueError("Child sensor %r is not booelan" % child)
            self._parent_to_not_ok[child] = set()
        self.add_links(parent, (child,))


Instruction:
Write a Python 3 function that can
remove a dependency between parent and child.

Response:
def remove(self, parent, child):
        """Remove a dependency between parent and child.

        Parameters
        ----------
        parent : boolean instance of :class:`katcp.Sensor`
            The sensor that used to depend on child.
        child : boolean instance of :class:`katcp.Sensor` or None
            The sensor parent used to depend on.

        """
        self.remove_links(parent, (child,))
        if parent not in self and parent in self._parent_to_not_ok:
            del self._parent_to_not_ok[parent]
        if child not in self and child in self._parent_to_not_ok:
            del self._parent_to_not_ok[child]


Instruction:
Write a Python 3 script to
add an aggregation rule.

Response:
def add(self, parent, rule_function, children):
        """Create an aggregation rule.

        Parameters
        ----------
        parent : :class:`katcp.Sensor` object
            The aggregate sensor.
        rule_function : f(parent, children)
            Function to update the parent sensor value.
        children : sequence of :class:`katcp.Sensor` objects
            The sensors the aggregate sensor depends on.

        """
        if parent in self._aggregates or parent in self._incomplete_aggregates:
            raise ValueError("Sensor %r already has an aggregate rule "
                             "associated" % parent)
        self._aggregates[parent] = (rule_function, children)
        self.add_links(parent, children)


Instruction:
How would you code a function in Python 3 to
add an aggregation rule before child sensors are present.

Response:
def add_delayed(self, parent, rule_function, child_names):
        """Create an aggregation rule before child sensors are present.

        Parameters
        ----------
        parent : :class:`katcp.Sensor` object
            The aggregate sensor.
        rule_function : f(parent, children)
            Function to update the parent sensor value.
        child_names : sequence of str
            The names of the sensors the aggregate sensor depends on. These
            sensor must be registered using :meth:`register_sensor` to become
            active.

        """
        if parent in self._aggregates or parent in self._incomplete_aggregates:
            raise ValueError("Sensor %r already has an aggregate rule"
                             " associated" % parent)
        reg = self._registered_sensors
        names = set(name for name in child_names if name not in reg)
        sensors = set(reg[name] for name in child_names if name in reg)
        if names:
            self._incomplete_aggregates[parent] = (rule_function, names,
                                                   sensors)
        else:
            self.add(parent, rule_function, sensors)


Instruction:
Make a summary of the following Python 3 code
def register_sensor(self, child):
        child_name = self._get_sensor_reference(child)
        if child_name in self._registered_sensors:
            raise ValueError("Sensor %r already registered with aggregate"
                             " tree" % child)
        self._registered_sensors[child_name] = child
        completed = []
        for parent, (_rule, names, sensors) in \
                self._incomplete_aggregates.iteritems():
            if child_name in names:
                names.remove(child_name)
                sensors.add(child)
                if not names:
                    completed.append(parent)
        for parent in completed:
            rule_function, _names, sensors = \
                self._incomplete_aggregates[parent]
            del self._incomplete_aggregates[parent]
            self.add(parent, rule_function, sensors)

Response: Register a sensor required by an aggregate sensor registered with add_delayed.


Instruction:
Implement a function in Python 3 to
return the child sensor from its reference.

Response:
def _child_from_reference(self, reference):
        """Returns the child sensor from its reference.

        Parameters
        ----------
        reference : str
            Reference to sensor (typically its name).

        Returns
        -------
        child : :class:`katcp.Sensor` object
            A child sensor linked to one or more aggregate sensors.

        """
        for child in self._child_to_parents:
            if self._get_sensor_reference(child) == reference:
                return child


Instruction:
Can you generate a brief explanation for the following Python 3 code
def remove(self, parent):
        if parent not in self._aggregates:
            raise ValueError("Sensor %r does not have an aggregate rule "
                             "associated" % parent)
        children = self.children(parent)
        try:
            self.remove_links(parent, children)
        except Exception:
            pass
        del self._aggregates[parent]

Response: Removes an aggregation rule.


Instruction:
Explain what the following Python 3 code does
def request_timeout_hint(timeout_hint):
    if timeout_hint is not None:
        timeout_hint = float(timeout_hint)

    def decorator(handler):
        handler.request_timeout_hint = timeout_hint
        return handler

    return decorator

Response: Decorator that adds recommended client timeout hint to a request for a specific KATCP server.


Instruction:
Implement a Python 3 function for
wrapping future that will resolve with arguments needed by make_reply.

Response:
def async_make_reply(msgname, types, arguments_future, major):
    """Wrap future that will resolve with arguments needed by make_reply()."""
    arguments = yield arguments_future
    raise gen.Return(make_reply(msgname, types, arguments, major))


Instruction:
Make a summary of the following Python 3 code
def unpack_types(types, args, argnames, major):
    if len(types) > 0:
        multiple = types[-1]._multiple
    else:
        multiple = False

    if len(types) < len(args) and not multiple:
        raise FailReply("Too many parameters given.")

    # Wrap the types in parameter objects
    params = []
    for i, kattype in enumerate(types):
        name = ""
        if i < len(argnames):
            name = argnames[i]
        params.append(Parameter(i+1, name, kattype, major))

    if len(args) > len(types) and multiple:
        for i in range(len(types), len(args)):
            params.append(Parameter(i+1, name, kattype, major))

    # if len(args) < len(types) this passes in None for missing args
    return map(lambda param, arg: param.unpack(arg), params, args)

Response: Unpacks the types of the arguments according to types list.


Instruction:
Make a summary of the following Python 3 code
def pack_types(types, args, major):
    if len(types) > 0:
        multiple = types[-1]._multiple
    else:
        multiple = False

    if len(types) < len(args) and not multiple:
        raise ValueError("Too many arguments to pack.")

    if len(args) < len(types):
        # this passes in None for missing args
        retvals = map(lambda ktype, arg: ktype.pack(arg, major=major),
                      types, args)
    else:
        retvals = [ktype.pack(arg, major=major)
                   for ktype, arg in zip(types, args)]

    if len(args) > len(types) and multiple:
        last_ktype = types[-1]
        for arg in args[len(types):]:
            retvals.append(last_ktype.pack(arg, major=major))

    return retvals

Response: Packs the types according to the types list.


Instruction:
How would you explain what the following Python 3 function does
def pack(self, value, nocheck=False, major=DEFAULT_KATCP_MAJOR):
        if value is None:
            value = self.get_default()
        if value is None:
            raise ValueError("Cannot pack a None value.")
        if not nocheck:
            self.check(value, major)
        return self.encode(value, major)

Response: Pack the value into a KATCP parameter.


Instruction:
Given the following Python 3 function, write the documentation
def unpack(self, packed_value, major=DEFAULT_KATCP_MAJOR):
        if packed_value is None:
            value = self.get_default()
        else:
            try:
                value = self.decode(packed_value, major)
            except Exception:
                raise
        if value is not None:
            self.check(value, major)
        return value

Response: Parse a KATCP parameter into an object.


Instruction:
Can you tell what is the following Python 3 function doing
def check(self, value, major):
        if self._min is not None and value < self._min:
            raise ValueError("Integer %d is lower than minimum %d."
                             % (value, self._min))
        if self._max is not None and value > self._max:
            raise ValueError("Integer %d is higher than maximum %d."
                             % (value, self._max))

Response: Check whether the value is between the minimum and maximum. Raise a ValueError if it is not.


Instruction:
Write a Python 3 script for
checking whether the value is in the set of allowed values. Raise a ValueError if it is not.

Response:
def check(self, value, major):
        """Check whether the value in the set of allowed values.

        Raise a ValueError if it is not.

        """
        if self._case_insensitive:
            value = value.lower()
            values = self._valid_values_lower
            caseflag = " (case-insensitive)"
        else:
            values = self._valid_values
            caseflag = ""
        if value not in values:
            raise ValueError("Discrete value '%s' is not one of %s%s."
                             % (value, list(self._values), caseflag))


Instruction:
Here you have a function in Python 3, explain what it does
def check(self, value, major):
        for v in value:
            super(DiscreteMulti, self).check(v, major)

Response: Check that each item in the value list is in the allowed set.


Instruction:
How would you code a function in Python 3 to
unpack the parameter using its kattype.

Response:
def unpack(self, value):
        """Unpack the parameter using its kattype.

        Parameters
        ----------
        packed_value : str
            The unescaped KATCP string to unpack.

        Returns
        -------
        value : object
            The unpacked value.

        """
        # Wrap errors in FailReplies with information identifying the parameter
        try:
            return self._kattype.unpack(value, self.major)
        except ValueError, message:
            raise FailReply("Error in parameter %s (%s): %s" %
                            (self.position, self.name, message))


Instruction:
Can you generate the documentation for the following Python 3 function
def return_future(fn):
    @wraps(fn)
    def decorated(*args, **kwargs):
        return gen.maybe_future(fn(*args, **kwargs))

    return decorated

Response: Decorator that turns a synchronous function into one returning a future.


Instruction:
Write a Python 3 script to
construct a function that returns True if a name matches a pattern.

Response:
def construct_name_filter(pattern):
    """Return a function for filtering sensor names based on a pattern.

    Parameters
    ----------
    pattern : None or str
        If None, the returned function matches all names.
        If pattern starts and ends with '/' the text between the slashes
        is used as a regular expression to search the names.
        Otherwise the pattern must match the name of the sensor exactly.

    Returns
    -------
    exact : bool
        Return True if pattern is expected to match exactly. Used to
        determine whether having no matching sensors constitutes an error.
    filter_func : f(str) -> bool
        Function for determining whether a name matches the pattern.

    """
    if pattern is None:
        return False, lambda name: True
    if pattern.startswith('/') and pattern.endswith('/'):
        name_re = re.compile(pattern[1:-1])
        return False, lambda name: name_re.search(name) is not None
    return True, lambda name: name == pattern


Instruction:
Given the following Python 3 function, write the documentation
def disconnect(self, reason):
        self._server._disconnect_client(self._conn_key, self, reason)

Response: Disconnect this client connection for specified reason


Instruction:
Can you generate the documentation for the following Python 3 function
def inform(self, msg):
        assert (msg.mtype == Message.INFORM)
        return self._send_message(msg)

Response: Send an inform message to a particular client.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def reply_inform(self, inform, orig_req):
        assert (inform.mtype == Message.INFORM)
        assert (inform.name == orig_req.name)
        inform.mid = orig_req.mid
        return self._send_message(inform)

Response: Send an inform message to an earlier request.


Instruction:
Write a Python 3 script to
send an inform message to all clients.

Response:
def mass_inform(self, msg):
        """Send an inform message to all clients.

        Parameters
        ----------
        msg : Message object
            The inform message to send.

        """
        assert (msg.mtype == Message.INFORM)
        return self._mass_send_message(msg)


Instruction:
Write a Python 3 script to
send an asynchronous reply to an earlier request.

Response:
def reply(self, reply, orig_req):
        """Send an asynchronous reply to an earlier request.

        Parameters
        ----------
        reply : Message object
            The reply message to send.
        orig_req : Message object
            The request message being replied to. The reply message's
            id is overridden with the id from orig_req before the
            reply is sent.

        """
        assert (reply.mtype == Message.REPLY)
        assert reply.name == orig_req.name
        reply.mid = orig_req.mid
        return self._send_message(reply)


Instruction:
Write a Python 3 function for
installing the server on its IOLoop optionally starting the IOLoop.

Response:
def start(self, timeout=None):
        """Install the server on its IOLoop, optionally starting the IOLoop.

        Parameters
        ----------
        timeout : float or None, optional
            Time in seconds to wait for server thread to start.

        """
        if self._running.isSet():
            raise RuntimeError('Server already started')
        self._stopped.clear()
        # Make sure we have an ioloop
        self.ioloop = self._ioloop_manager.get_ioloop()
        self._ioloop_manager.start()
        # Set max_buffer_size to ensure streams are closed
        # if too-large messages are received
        self._tcp_server = tornado.tcpserver.TCPServer(
            self.ioloop, max_buffer_size=self.MAX_MSG_SIZE)
        self._tcp_server.handle_stream = self._handle_stream
        self._server_sock = self._bind_socket(self._bindaddr)
        self._bindaddr = self._server_sock.getsockname()

        self.ioloop.add_callback(self._install)
        if timeout:
            return self._running.wait(timeout)


Instruction:
Make a summary of the following Python 3 code
def stop(self, timeout=1.0):
        if timeout:
            self._running.wait(timeout)
        return self._ioloop_manager.stop(callback=self._uninstall)

Response: Stop a running server.


Instruction:
Write a Python 3 function that can
rejoin the server thread.

Response:
def join(self, timeout=None):
        """Rejoin the server thread.

        Parameters
        ----------
        timeout : float or None, optional
            Time in seconds to wait for the thread to finish.

        Notes
        -----
        If the ioloop is not managed, this function will block until the server
        port is closed, meaning a new server can be started on the same port.

        """
        t0 = time.time()
        self._ioloop_manager.join(timeout=timeout)
        if timeout:
            self._stopped.wait(timeout - (time.time() - t0))


Instruction:
How would you code a function in Python 3 to
create a listening server socket.

Response:
def _bind_socket(self, bindaddr):
        """Create a listening server socket."""
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        sock.setblocking(0)
        try:
            sock.bind(bindaddr)
        except Exception:
            self._logger.exception("Unable to bind to %s" % str(bindaddr))
            raise
        sock.listen(self.BACKLOG)
        return sock


Instruction:
Write a Python 3 script to
handle a new connection as a tornado. iostream. IOStream instance.

Response:
def _handle_stream(self, stream, address):
        """Handle a new connection as a tornado.iostream.IOStream instance."""
        try:
            assert get_thread_ident() == self.ioloop_thread_id
            stream.set_close_callback(partial(self._stream_closed_callback,
                                              stream))
            # Our message packets are small, don't delay sending them.
            stream.set_nodelay(True)
            stream.max_write_buffer_size = self.MAX_WRITE_BUFFER_SIZE

            # Abuse IOStream object slightly by adding 'address' and 'closing'
            # attributes. Use nasty prefix to prevent naming collisions.
            stream.KATCPServer_address = address
            # Flag to indicate that no more write should be accepted so that
            # we can flush the write buffer when closing a connection
            stream.KATCPServer_closing = False

            client_conn = self.client_connection_factory(self, stream)
            self._connections[stream] = client_conn
            try:
                yield gen.maybe_future(self._device.on_client_connect(client_conn))
            except Exception:
                # If on_client_connect fails there is no reason to continue
                # trying to handle this connection. Try and send exception info
                # to the client and disconnect
                e_type, e_value, trace = sys.exc_info()
                reason = "\n".join(traceback.format_exception(
                    e_type, e_value, trace, self._tb_limit))
                log_msg = 'Device error initialising connection {0}'.format(reason)
                self._logger.error(log_msg)
                stream.write(str(Message.inform('log', log_msg)))
                stream.close(exc_info=True)
            else:
                self._line_read_loop(stream, client_conn)
        except Exception:
            self._logger.error('Unhandled exception trying '
                               'to handle new connection', exc_info=True)


Instruction:
Implement a function in Python 3 to
return the network address of a connection stream.

Response:
def get_address(self, stream):
        """Text representation of the network address of a connection stream.

        Notes
        -----
        This method is thread-safe

        """
        try:
            addr = ":".join(str(part) for part in stream.KATCPServer_address)
        except AttributeError:
            # Something weird happened, but keep trucking
            addr = '<error>'
            self._logger.warn('Could not determine address of stream',
                              exc_info=True)
        return addr


Instruction:
Here you have a function in Python 3, explain what it does
def send_message(self, stream, msg):
        assert get_thread_ident() == self.ioloop_thread_id
        try:
            if stream.KATCPServer_closing:
                raise RuntimeError('Stream is closing so we cannot '
                                   'accept any more writes')
            return stream.write(str(msg) + '\n')
        except Exception:
            addr = self.get_address(stream)
            self._logger.warn('Could not send message {0!r} to {1}'
                              .format(str(msg), addr), exc_info=True)
            stream.close(exc_info=True)

Response: Send an arbitrary message to a particular client.


Instruction:
How would you explain what the following Python 3 function does
def flush_on_close(self, stream):
        assert get_thread_ident() == self.ioloop_thread_id
        # Prevent futher writes
        stream.KATCPServer_closing = True
        # Write empty message to get future that resolves when buffer is flushed
        return stream.write('\n')

Response: Flush tornado iostream write buffer and prevent further writes.


Instruction:
Write a Python 3 function that can
thread - safe version of send_message that returns a Future that resolves with the future s result.

Response:
def send_message_from_thread(self, stream, msg):
        """Thread-safe version of send_message() returning a Future instance.

        Returns
        -------
        A Future that will resolve without raising an exception as soon as
        the call to send_message() completes. This does not guarantee that the
        message has been delivered yet. If the call to send_message() failed,
        the exception will be logged, and the future will resolve with the
        exception raised. Since a failed call to send_message() will result
        in the connection being closed, no real error handling apart from
        logging will be possible.

        Notes
        -----
        This method is thread-safe. If called from within the ioloop,
        send_message is called directly and a resolved tornado.concurrent.Future
        is returned, otherwise a callback is submitted to the ioloop that will
        resolve a thread-safe concurrent.futures.Future instance.

        """
        return self.call_from_thread(partial(self.send_message, stream, msg))


Instruction:
Implement a function in Python 3 to
send a message to all connected clients.

Response:
def mass_send_message(self, msg):
        """Send a message to all connected clients.

        Notes
        -----
        This method can only be called in the IOLoop thread.

        """
        for stream in self._connections.keys():
            if not stream.closed():
                # Don't cause noise by trying to write to already closed streams
                self.send_message(stream, msg)


Instruction:
How would you implement a function in Python 3 that
sends a reply message to the client connection.

Response:
def reply_with_message(self, rep_msg):
        """Send a pre-created reply message to the client connection.

        Will check that rep_msg.name matches the bound request.

        """
        self._post_reply()
        return self.client_connection.reply(rep_msg, self.msg)


Instruction:
Can you generate the documentation for the following Python 3 function
def on_message(self, client_conn, msg):
        MAX_QUEUE_SIZE = 30
        if len(self._msg_queue) >= MAX_QUEUE_SIZE:
            # This should never happen if callers to handle_message wait
            # for its futures to resolve before sending another message.
            # NM 2014-10-06: Except when there are multiple clients. Oops.
            raise RuntimeError('MessageHandlerThread unhandled '
                               'message queue full, not handling message')
        ready_future = Future()
        self._msg_queue.append((ready_future, client_conn, msg))
        self._wake.set()
        return ready_future

Response:
Handle message.

        Returns
        -------
        ready : Future
            A future that will resolve once we're ready, else None.

        Notes
        -----
        *on_message* should not be called again until *ready* has resolved.


Instruction:
Make a summary of the following Python 3 code
def stop(self, timeout=1.0):
        if timeout:
            self._running.wait(timeout)
        self._running.clear()
        # Make sure to wake the run thread.
        self._wake.set()

Response: Stop the handler thread.


Instruction:
Explain what the following Python 3 code does
def create_log_inform(self, level_name, msg, name, timestamp=None):
        if timestamp is None:
            timestamp = time.time()

        katcp_version = self.PROTOCOL_INFO.major
        timestamp_msg = ('%.6f' % timestamp
                         if katcp_version >= SEC_TS_KATCP_MAJOR
                         else str(int(timestamp*1000)))
        return Message.inform("log", level_name, timestamp_msg, name, msg)

Response: Create a katcp logging inform message.


Instruction:
Given the following Python 3 function, write the documentation
def handle_message(self, client_conn, msg):
        # log messages received so that no one else has to
        self._logger.debug('received: {0!s}'.format(msg))

        if msg.mtype == msg.REQUEST:
            return self.handle_request(client_conn, msg)
        elif msg.mtype == msg.INFORM:
            return self.handle_inform(client_conn, msg)
        elif msg.mtype == msg.REPLY:
            return self.handle_reply(client_conn, msg)
        else:
            reason = "Unexpected message type received by server ['%s']." \
                     % (msg,)
            client_conn.inform(self.create_log_inform("error", reason, "root"))

Response: Handle a single message from the server.


Instruction:
Write a Python 3 script for
dispatching a request message to the appropriate method.

Response:
def handle_request(self, connection, msg):
        """Dispatch a request message to the appropriate method.

        Parameters
        ----------
        connection : ClientConnection object
            The client connection the message was from.
        msg : Message object
            The request message to process.

        Returns
        -------
        done_future : Future or None
            Returns Future for async request handlers that will resolve when
            done, or None for sync request handlers once they have completed.

        """
        send_reply = True
        # TODO Should check presence of Message-ids against protocol flags and
        # raise an error as needed.
        if msg.name in self._request_handlers:
            req_conn = ClientRequestConnection(connection, msg)
            handler = self._request_handlers[msg.name]
            try:
                reply = handler(self, req_conn, msg)
                # If we get a future, assume this is an async message handler
                # that will resolve the future with the reply message when it
                # is complete. Attach a message-sending callback to the future,
                # and return the future.
                if gen.is_future(reply):
                    concurrent = getattr(handler, '_concurrent_reply', False)
                    concurrent_str = ' CONCURRENT' if concurrent else ''

                    done_future = Future()
                    def async_reply(f):
                        try:
                            connection.reply(f.result(), msg)
                            self._logger.debug("%s FUTURE%s replied",
                                               msg.name, concurrent_str)
                        except FailReply, e:
                            reason = str(e)
                            self._logger.error("Request %s FUTURE%s FAIL: %s",
                                               msg.name, concurrent_str, reason)
                            reply = Message.reply(msg.name, "fail", reason)
                            connection.reply(reply, msg)
                        except AsyncReply:
                            self._logger.debug("%s FUTURE ASYNC OK"
                                               % (msg.name,))
                        except Exception:
                            error_reply = self.create_exception_reply_and_log(
                                msg, sys.exc_info())
                            connection.reply(error_reply, msg)
                        finally:
                            done_future.set_result(None)

                    # TODO When using the return_reply() decorator the future
                    # returned is not currently threadsafe, must either deal
                    # with it here, or in kattypes.py. Would be nice if we don't
                    # have to always fall back to adding a callback, or wrapping
                    # a thread-safe future. Supporting sync-with-thread and
                    # async futures is turning out to be a pain in the ass ;)
                    self.ioloop.add_callback(reply.add_done_callback, async_reply)
                    # reply.add_done_callback(async_reply)

                    if concurrent:
                        # Return immediately if this is a concurrent handler
                        self._logger.debug("%s FUTURE CONCURRENT OK", msg.name)
                        return
                    else:
                        self._logger.debug("%s FUTURE OK", msg.name)
                        return done_future
                else:
                    assert (reply.mtype == Message.REPLY)
                    assert (reply.name == msg.name)
                    self._logger.debug("%s OK" % (msg.name,))
            except AsyncReply, e:
                self._logger.debug("%s ASYNC OK" % (msg.name,))
                send_reply = False
            except FailReply, e:
                reason = str(e)
                self._logger.error("Request %s FAIL: %s" % (msg.name, reason))
                reply = Message.reply(msg.name, "fail", reason)
            except Exception:
                reply = self.create_exception_reply_and_log(msg, sys.exc_info())
        else:
            self._logger.error("%s INVALID: Unknown request." % (msg.name,))
            reply = Message.reply(msg.name, "invalid", "Unknown request.")

        if send_reply:
            connection.reply(reply, msg)


Instruction:
Given the following Python 3 function, write the documentation
def handle_inform(self, connection, msg):
        if msg.name in self._inform_handlers:
            try:
                self._inform_handlers[msg.name](self, connection, msg)
            except Exception:
                e_type, e_value, trace = sys.exc_info()
                reason = "\n".join(traceback.format_exception(
                    e_type, e_value, trace, self._tb_limit))
                self._logger.error("Inform %s FAIL: %s" % (msg.name, reason))
        else:
            self._logger.warn("%s INVALID: Unknown inform." % (msg.name,))

Response: Dispatch an inform message to the appropriate method.


Instruction:
How would you code a function in Python 3 to
send an inform message to a particular client.

Response:
def inform(self, connection, msg):
        """Send an inform message to a particular client.

        Should only be used for asynchronous informs. Informs
        that are part of the response to a request should use
        :meth:`reply_inform` so that the message identifier
        from the original request can be attached to the
        inform.

        Parameters
        ----------
        connection : ClientConnection object
            The client to send the message to.
        msg : Message object
            The inform message to send.

        """
        if isinstance(connection, ClientRequestConnection):
            self._logger.warn(
                'Deprecation warning: do not use self.inform() '
                'within a reply handler context -- use req.inform()\n'
                'Traceback:\n %s', "".join(traceback.format_stack()))
            # Get the underlying ClientConnection instance
            connection = connection.client_connection
        connection.inform(msg)


Instruction:
Make a summary of the following Python 3 code
def mass_inform(self, msg):
        assert (msg.mtype == Message.INFORM)
        self._server.mass_send_message_from_thread(msg)

Response: Send an inform message to all clients.


Instruction:
Make a summary of the following Python 3 code
def reply(self, connection, reply, orig_req):
        if isinstance(connection, ClientRequestConnection):
            self._logger.warn(
                'Deprecation warning: do not use self.reply() '
                'within a reply handler context -- use req.reply(*msg_args)\n'
                'or req.reply_with_message(msg) Traceback:\n %s',
                "".join(traceback.format_stack()))
            # Get the underlying ClientConnection instance
            connection = connection.client_connection
        connection.reply(reply, orig_req)

Response: Sends an asynchronous reply to an earlier request.


Instruction:
Given the following Python 3 function, write the documentation
def reply_inform(self, connection, inform, orig_req):
        if isinstance(connection, ClientRequestConnection):
            self._logger.warn(
                'Deprecation warning: do not use self.reply_inform() '
                'within a reply handler context -- '
                'use req.inform(*inform_arguments)\n'
                'Traceback:\n %s', "".join(traceback.format_stack()))
            # Get the underlying ClientConnection instance
            connection = connection.client_connection
        connection.reply_inform(inform, orig_req)

Response: Send an inform to an earlier request.


Instruction:
How would you explain what the following Python 3 function does
def set_ioloop(self, ioloop=None):
        self._server.set_ioloop(ioloop)
        self.ioloop = self._server.ioloop

Response: Sets the tornado. ioloop. IOLoop instance to use.


Instruction:
How would you explain what the following Python 3 function does
def set_concurrency_options(self, thread_safe=True, handler_thread=True):
        if handler_thread:
            assert thread_safe, "handler_thread=True requires thread_safe=True"
        self._server.client_connection_factory = (
            ThreadsafeClientConnection if thread_safe else ClientConnection)
        if handler_thread:
            self._handler_thread = MessageHandlerThread(
                self.handle_message, self.create_log_inform, self._logger)
            self.on_message = self._handler_thread.on_message
        else:
            self.on_message = return_future(self.handle_message)
            self._handler_thread = None

        self._concurrency_options = ObjectDict(
            thread_safe=thread_safe, handler_thread=handler_thread)

Response: Sets the concurrency options for this device server.


Instruction:
How would you explain what the following Python 3 function does
def start(self, timeout=None):
        if self._handler_thread and self._handler_thread.isAlive():
            raise RuntimeError('Message handler thread already started')
        self._server.start(timeout)
        self.ioloop = self._server.ioloop
        if self._handler_thread:
            self._handler_thread.set_ioloop(self.ioloop)
            self._handler_thread.start(timeout)

Response: Start the server in a new thread.


Instruction:
Can you implement a function in Python 3 that
rejoins the server thread.

Response:
def join(self, timeout=None):
        """Rejoin the server thread.

        Parameters
        ----------
        timeout : float or None, optional
            Time in seconds to wait for the thread to finish.

        """
        self._server.join(timeout)
        if self._handler_thread:
            self._handler_thread.join(timeout)


Instruction:
Here you have a function in Python 3, explain what it does
def stop(self, timeout=1.0):
        stopped = self._server.stop(timeout)
        if self._handler_thread:
            self._handler_thread.stop(timeout)

        return stopped

Response: Stop a running server from another thread.


Instruction:
Write a Python 3 script to
block for ioloop to complete a loop if called from another thread.

Response:
def sync_with_ioloop(self, timeout=None):
        """Block for ioloop to complete a loop if called from another thread.

        Returns a future if called from inside the ioloop.

        Raises concurrent.futures.TimeoutError if timed out while blocking.

        """
        in_ioloop = self._server.in_ioloop_thread()
        if in_ioloop:
            f = tornado_Future()
        else:
            f = Future()

        def cb():
            f.set_result(None)

        self.ioloop.add_callback(cb)

        if in_ioloop:
            return f
        else:
            f.result(timeout)


Instruction:
Explain what the following Python 3 code does
def on_client_connect(self, client_conn):
        assert get_thread_ident() == self._server.ioloop_thread_id
        self._client_conns.add(client_conn)
        self._strategies[client_conn] = {}  # map sensors -> sampling strategies

        katcp_version = self.PROTOCOL_INFO.major
        if katcp_version >= VERSION_CONNECT_KATCP_MAJOR:
            client_conn.inform(Message.inform(
                "version-connect", "katcp-protocol", self.PROTOCOL_INFO))
            client_conn.inform(Message.inform(
                "version-connect", "katcp-library",
                "katcp-python-%s" % katcp.__version__))
            client_conn.inform(Message.inform(
                "version-connect", "katcp-device",
                self.version(), self.build_state()))
        else:
            client_conn.inform(Message.inform("version", self.version()))
            client_conn.inform(Message.inform("build-state", self.build_state()))

Response: Inform client of build state and version on connect.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def clear_strategies(self, client_conn, remove_client=False):
        assert get_thread_ident() == self._server.ioloop_thread_id

        getter = (self._strategies.pop if remove_client
                  else self._strategies.get)
        strategies = getter(client_conn, None)
        if strategies is not None:
            for sensor, strategy in list(strategies.items()):
                strategy.cancel()
                del strategies[sensor]

Response: Clears the sensor strategies of a client connection.


Instruction:
How would you explain what the following Python 3 function does
def on_client_disconnect(self, client_conn, msg, connection_valid):
        f = tornado_Future()
        @gen.coroutine
        def remove_strategies():
            self.clear_strategies(client_conn, remove_client=True)
            if connection_valid:
                client_conn.inform(Message.inform("disconnect", msg))
                yield client_conn.flush_on_close()

        try:
            self._client_conns.remove(client_conn)
            self.ioloop.add_callback(lambda: chain_future(remove_strategies(), f))
        except Exception:
            f.set_exc_info(sys.exc_info())
        return f

Response: Called when a client connection is about to be disconnected.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def remove_sensor(self, sensor):
        if isinstance(sensor, basestring):
            sensor_name = sensor
        else:
            sensor_name = sensor.name
        sensor = self._sensors.pop(sensor_name)

        def cancel_sensor_strategies():
            for conn_strategies in self._strategies.values():
                strategy = conn_strategies.pop(sensor, None)
                if strategy:
                    strategy.cancel()
        self.ioloop.add_callback(cancel_sensor_strategies)

Response: Removes a sensor from the device.


Instruction:
Implement a function in Python 3 to
fetch the sensor with the given name.

Response:
def get_sensor(self, sensor_name):
        """Fetch the sensor with the given name.

        Parameters
        ----------
        sensor_name : str
            Name of the sensor to retrieve.

        Returns
        -------
        sensor : Sensor object
            The sensor with the given name.

        """
        sensor = self._sensors.get(sensor_name, None)
        if not sensor:
            raise ValueError("Unknown sensor '%s'." % (sensor_name,))
        return sensor


Instruction:
Create a Python 3 function to
halt the device server.

Response:
def request_halt(self, req, msg):
        """Halt the device server.

        Returns
        -------
        success : {'ok', 'fail'}
            Whether scheduling the halt succeeded.

        Examples
        --------
        ::

            ?halt
            !halt ok

        """
        f = Future()
        @gen.coroutine
        def _halt():
            req.reply("ok")
            yield gen.moment
            self.stop(timeout=None)
            raise AsyncReply

        self.ioloop.add_callback(lambda: chain_future(_halt(), f))
        return f