lewis.adapters.stream

Members

Cmd

This class is an implementation of CommandBase that can expose a callable object or a named method of the device/interface controlled by StreamAdapter.

CommandBase

This is the common base class of Cmd and Var.

Func

Objects of this type connect a callable object to a pattern matcher (PatternMatcher), which currently comprises regex and scanf.

PatternMatcher

This class defines an interface for general command-matchers that use any kind of technique to match a certain request in string form.

StreamAdapter

The StreamAdapter is the bridge between the Device Interface and the TCP Stream networking backend implementation.

StreamHandler

StreamInterface

This class is used to provide a TCP-stream based interface to a device.

StreamServer

Var

With this implementation of CommandBase it's possible to expose plain data attributes or properties of device or interface.

regex

Implementation of PatternMatcher that compiles the specified pattern into a regular expression.

scanf

Interprets the specified pattern as a scanf format.

class lewis.adapters.stream.Cmd(func, pattern, argument_mappings=None, return_mapping=<function Cmd.<lambda>>, doc=None)[source]

Bases: CommandBase

This class is an implementation of CommandBase that can expose a callable object or a named method of the device/interface controlled by StreamAdapter.

def random():
    return 6

SomeInterface(StreamInterface):
    commands = {
        Cmd(lambda: 4, pattern='^R$', doc='Returns a random number.'),
        Cmd('random', pattern='^RR$', doc='Better random number.'),
        Cmd(random, pattern='^RRR$', doc='The best random number.'),
    }

    def random(self):
        return 5

The interface defined by the above example has three commands, R which calls a lambda function that always returns 4, RR, which calls SomeInterface.random and returns 5 and lastly RRR which calls the free function defined above and returns the best random number.

For a detailed explanation of requirements to the constructor arguments, please refer to the documentation of Func, to which the arguments are forwarded.

See also

Var exposes attributes and properties of a device object. The documentation of Func provides more information about the common constructor arguments.

Parameters:
  • func – Function to be called when pattern matches or member of device/interface.

  • pattern – Pattern to match (PatternMatcher or string).

  • argument_mappings – Iterable with mapping functions from string to some type.

  • return_mapping – Mapping function for return value of method.

  • doc – Description of the command. If not supplied, the docstring is used.

class lewis.adapters.stream.CommandBase(func, pattern, argument_mappings=None, return_mapping=None, doc=None)[source]

Bases: object

This is the common base class of Cmd and Var. The concept of commands for the stream adapter is based on connecting a callable object to a pattern that matches an inbound request.

The type of pattern can be either an implementation of PatternMatcher (regex or scanf format specification) or a plain string (which is treated as a regular expression).

For free function and lambda expressions this is straightforward: the function object can simply be stored together with the pattern. Most often however, the callable is a method of the device or interface object - these do not exist when the commands are defined.

This problem is solved by introducing a “bind”-step in StreamAdapter. So instead of a function object, both Cmd and Var store the name of a member of device or interface. At “bind-time”, this is translated into the correct callable.

So instead of using Cmd or Var directly, both classes’ bind()-methods return an iterable of Func-objects which can be used for processing requests. StreamAdapter performs this bind-step when it’s constructed. For details regarding the implementations, please see the corresponding classes.

See also

Please take a look at Cmd for exposing callable objects or methods of device/interface and Var for exposing attributes and properties.

To see how argument_mappings, return_mapping and doc are applied, please look at Func.

Parameters:
  • func – Function to be called when pattern matches or member of device/interface.

  • pattern – Pattern to match (PatternMatcher or string).

  • argument_mappings – Iterable with mapping functions from string to some type.

  • return_mapping – Mapping function for return value of method.

  • doc – Description of the command. If not supplied, the docstring is used.

class lewis.adapters.stream.Func(func, pattern, argument_mappings=None, return_mapping=None, doc=None)[source]

Bases: object

Objects of this type connect a callable object to a pattern matcher (PatternMatcher), which currently comprises regex and scanf. Strings are also accepted, they are treated like a regular expression internally. This preserves default behavior from older versions of Lewis.

In general, Func-objects should not be created directly, instead they are created by one of the sub-classes of CommandBase using bind().

Function arguments are indicated by groups in the regular expression. The number of groups has to match the number of arguments of the function. In earlier versions of Lewis it was possible to pass flags to re.compile, this has been removed for consistency issues in Var. It is however still possible to use the exact same flags as part of the regular expression. In the documentation of re, this is outlined, simply add a group to the expression that contains the flags, for example (?i) to make the expression case insensitive. This special group does not count towards the matching groups used for argument capture.

The optional argument_mappings can be an iterable of callables with one parameter of the same length as the number of arguments of the function. The first parameter will be transformed using the first function, the second using the second function and so on. This can be useful to automatically transform strings provided by the adapter into a proper data type such as int or float before they are passed to the function. In case the pattern is of type scanf, this is optional (but will override the mappings provided by the matcher).

The return_mapping argument is similar, it should map the return value of the function to a string. The default map function only does that when the supplied value is not None. It can also be set to a numeric value or a string constant so that the command always returns the same value. If it is None, the return value is not modified at all.

Finally, documentation can be provided by passing the doc-argument. If it is omitted, the docstring of the bound function is used and if that is not present, left empty.

Parameters:
  • func – Function to be called when pattern matches or member of device/interface.

  • patternregex, scanf object or string.

  • argument_mappings – Iterable with mapping functions from string to some type.

  • return_mapping – Mapping function for return value of method.

  • doc – Description of the command. If not supplied, the docstring is used.

Raises:

RuntimeError: If the function cannot be mapped for any reason.

map_arguments(arguments)[source]

Returns the mapped function arguments. If no mapping functions are defined, the arguments are returned as they were supplied.

Parameters:

arguments – List of arguments for bound function as strings.

Returns:

Mapped arguments.

map_return_value(return_value)[source]

Returns the mapped return_value of a processed request. If no return_mapping has been defined, the value is returned as is. If return_mapping is a static value, that value is returned, ignoring return_value completely.

Parameters:

return_value – Value to map.

Returns:

Mapped return value.

class lewis.adapters.stream.PatternMatcher(pattern)[source]

Bases: object

This class defines an interface for general command-matchers that use any kind of technique to match a certain request in string form. It is used by Func to check whether a request can be processed using a function and to extract any function arguments.

Sub-classes must implement all defined abstract methods/properties.

See also

regex, scanf are concrete implementations of this class.

property arg_count: NoReturn

Number of arguments that are matched in a request.

property argument_mappings: NoReturn

Mapping functions that can be applied to the arguments returned by match().

match(request) NoReturn[source]

Tries to match the request against the internally stored pattern. Returns any matched function arguments.

Parameters:

request – Request to attempt matching.

Returns:

List of matched argument values (possibly empty) or None if not matching.

property pattern

The pattern definition used for matching a request.

class lewis.adapters.stream.StreamAdapter(options=None)[source]

Bases: Adapter

The StreamAdapter is the bridge between the Device Interface and the TCP Stream networking backend implementation.

Available adapter options are:

  • bind_address: IP of network adapter to bind on (defaults to 0.0.0.0, or all adapters)

  • port: Port to listen on (defaults to 9999)

  • telnet_mode: When True, overrides in- and out-terminator for CRNL (defaults to False)

Parameters:

options – Dictionary with options.

property documentation

This property can be overridden in a sub-class to provide protocol documentation to users at runtime. By default it returns the indentation cleaned-up docstring of the class.

handle(cycle_delay=0.1) None[source]

Spend approximately cycle_delay seconds to process requests to the server.

Parameters:

cycle_delay – S

property is_running

This property indicates whether the Adapter’s server is running and listening. The result of calls to start_server() and stop_server() should be reflected as expected.

start_server() None[source]

Starts the TCP stream server, binding to the configured host and port. Host and port are configured via the command line arguments.

Note

The server does not process requests unless handle() is called in regular intervals.

stop_server() None[source]

This method must be re-implemented to stop and tear down anything that has been setup in start_server(). This method should close all connections to clients that have been established since the adapter has been started.

Note

This method may be called multiple times over the lifetime of the Adapter, so it is important to make sure that this does not cause problems.

class lewis.adapters.stream.StreamHandler(sock, target, stream_server)[source]

Bases: async_chat

class lewis.adapters.stream.StreamInterface[source]

Bases: InterfaceBase

This class is used to provide a TCP-stream based interface to a device.

Many hardware devices use a protocol that is based on exchanging text with a client via a TCP stream. Sometimes RS232-based devices are also exposed this way via an adapter-box. This adapter makes it easy to mimic such a protocol.

This class has the following attributes which may be overridden by subclasses:

  • protocol: What this interface is called for purposes of the -p commandline option. Defaults to “stream”.

  • in_terminator, out_terminator: These define how lines are terminated when transferred to and from the device respectively. They are stripped/added automatically. Inverse of protocol file InTerminator and OutTerminator. The default is \\r.

  • readtimeout: How many msec to wait for additional data between packets, once transmission of an incoming command has begun. Inverse of ReadTimeout in protocol files. Defaults to 100 (ms). Set to 0 to disable timeout completely.

  • commands: A list of CommandBase-objects that define mappings between protocol and device/interface methods/attributes.

By default, commands are expressed as regular expressions, a simple example may look like this:

class SimpleDeviceStreamInterface(StreamInterface):
    commands = [
        Cmd('set_speed', r'^S=([0-9]+)$', argument_mappings=[int]),
        Cmd('get_speed', r'^S\?$')
        Var('speed', read_pattern=r'^V\?$', write_pattern=r'^V=([0-9]+)$')
    ]

    def set_speed(self, new_speed):
        self.device.speed = new_speed

    def get_speed(self):
        return self.device.speed

The interface has two commands, S? to return the speed and S=10 to set the speed to an integer value. It also exposes the same speed attribute as a variable, using auto- generated V? and V=10 commands.

As in the lewis.adapters.epics.EpicsInterface, it does not matter whether the wrapped method is a part of the device or of the interface, this is handled automatically when a new device is assigned to the device-property.

In addition, the handle_error()-method can be overridden. It is called when an exception is raised while handling commands.

property adapter

Adapter type that is required to process and expose interfaces of this type. Must be implemented in subclasses.

handle_error(request, error) None[source]

Override this method to handle exceptions that are raised during command processing. The default implementation does nothing, so that any errors are silently ignored.

Parameters:
  • request – The request that resulted in the error.

  • error – The exception that was raised.

class lewis.adapters.stream.Var(target_member, read_pattern=None, write_pattern=None, argument_mappings=None, return_mapping=<function Var.<lambda>>, doc=None)[source]

Bases: CommandBase

With this implementation of CommandBase it’s possible to expose plain data attributes or properties of device or interface. Getting and setting a value are separate procedures which both have their own pattern, read_pattern and write_pattern to match a command each. Please note that write_pattern has to have exactly one group defined to match a parameter.

Due to this separation, parameters can be made read-only, write-only or read-write in the interface:

class SomeInterface(StreamInterface):
    commands = {
        Var('foo', read_pattern='^F$', write_pattern=r'^F=(\d+)$',
            argument_mappings=(int,), doc='An integer attribute.'),
        Var('bar' read_pattern='^B$')
    }

    foo = 10

    @property
    def bar(self):
        return self.foo + 5

    @bar.setter
    def bar(self, new_bar):
        self.foo = new_bar - 5

In the above example, the foo attribute can be read and written, it’s automatically converted to an integer, while bar is a property that can only be read via the stream protocol.

See also

For exposing methods and free functions, there’s the Cmd-class.

Parameters:
  • target_member – Attribute or property of device/interface to expose.

  • read_pattern – Pattern to match for getter (PatternMatcher or string).

  • write_pattern – Pattern to match for setter (PatternMatcher or string).

  • argument_mappings – Iterable with mapping functions from string to some type, only applied to setter.

  • return_mapping – Mapping function for return value of method, applied to getter and setter.

  • doc – Description of the command. If not supplied, the docstring is used. For plain data attributes the only way to get docs is to supply this argument.

class lewis.adapters.stream.regex(pattern)[source]

Bases: PatternMatcher

Implementation of PatternMatcher that compiles the specified pattern into a regular expression.

property arg_count

Number of arguments that are matched in a request.

property argument_mappings: None

Mapping functions that can be applied to the arguments returned by match().

match(request)[source]

Tries to match the request against the internally stored pattern. Returns any matched function arguments.

Parameters:

request – Request to attempt matching.

Returns:

List of matched argument values (possibly empty) or None if not matching.

class lewis.adapters.stream.scanf(pattern, exact_match=True)[source]

Bases: regex

Interprets the specified pattern as a scanf format. Internally, the scanf package is used to transform the format into a regular expression. Please consult the documentation of scanf for valid pattern specifications.

By default, the resulting regular expression matches exactly. Consider this example:

exact = scanf("T=%f")
not_exact = scanf("T=%f", exact_match=False)

The first pattern only matches the string T=4.0, whereas the second would also match T=4.0garbage. Please note that the specifiers like %f are automatically turned into groups in the generated regular expression.

Parameters:
  • pattern – Scanf format specification.

  • exact_match – Match only if the entire string matches.

property argument_mappings

Mapping functions that can be applied to the arguments returned by match().

property pattern

The pattern definition used for matching a request.