lewis.core.devices
This module contains DeviceBase
as a base class for other device classes and
infrastructure that can import devices from a module (DeviceRegistry
). The latter also
produces factory-like objects that create device instances and interfaces based on setups
(DeviceBuilder
).
Members
This class is a common base for |
|
This class takes a module object (for example imported via importlib.import_module or via the |
|
This class takes the name of a module and constructs a |
|
This class is a common base for protocol specific interfaces that are exposed by a subclass of |
|
Returns True if obj is a device type (derived from DeviceBase), but not defined in |
|
Returns True if obj is an interface (derived from |
- class lewis.core.devices.DeviceBase[source]
Bases:
object
This class is a common base for
Device
andStateMachineDevice
. It is mainly used in the device discovery process.
- class lewis.core.devices.DeviceBuilder(module)[source]
Bases:
object
This class takes a module object (for example imported via importlib.import_module or via the
DeviceRegistry
) and inspects it so that it’s possible to construct devices and interfaces.In order for the class to work properly, the device module has to adhere to a few rules. Device types, which means classes inheriting from
DeviceBase
, are imported directly from the device module, equivalent to the following:from device_name import SimulatedDeviceType
If
SimulatedDeviceType
is defined in the__init__.py
, there’s nothing else to do. If the device class is defined elsewhere, it must be imported in the__init__.py
file as written above. If there is only one device type (which is probably the most common case), it is assumed to be default device type.Setups are discovered in two locations, the first one is a dict called
setups
in the device module, which must contain setup names as keys and as values again a dict. This inner dict has one mandatory key calleddevice_type
and one optional keyparameters
containing the constructor arguments for the specified device type:setups = dict( broken=dict( device_type=SimulatedDeviceType, parameters=dict( override_initial_state="error", override_initial_data=dict(target=-10, position=-20.0), ), ) )
The other location is a sub-package called setups, which should in turn contain modules. Each module must contain a variable
device_type
and a variableparameters
which are analogous to the keys in the dict described above. This allows for more complex setups which define additional classes and so on.The
default
setup is special, it is used when no setup is supplied tocreate_device()
. If the setupdefault
is not defined, one is created with the default device type. This has two consequences, no setups need to be defined for very simple devices, but if multiple device types are defined, adefault
setup must be defined.A setup can be supplied to the
create_device()
.Lastly, the builder tries to discover device interfaces, which are currently classes based on
lewis.adapters.InterfaceBase
. These are looked for in the module and in a sub-package calledinterfaces
(which should contain modules with adapters like thesetups
package).Each interface has a protocol, if a protocol occurs more than once in a device module, a RuntimeError is raised.
- create_device(setup=None)[source]
Creates a device object according to the provided setup. If no setup is provided, the default setup is used. If the setup can’t be found, a LewisException is raised. This can also happen if the device type specified in the setup is invalid.
- Parameters:
setup – Name of the setup from which to create device.
- Returns:
Device object initialized according to the provided setup.
- create_interface(protocol=None, *args, **kwargs)[source]
Returns an interface that implements the provided protocol. If the protocol is not known, a LewisException is raised. All additional arguments are forwarded to the interface constructor (see
Adapter
for details).- Parameters:
protocol – Protocol which the interface must implement.
args – Positional arguments that are passed on to the interface.
kwargs – Keyword arguments that are passed on to the interface.
- Returns:
Instance of the interface type.
- property default_device_type
If the module only defines one device type, it is the default device type. It is used whenever a setup does not provide a
device_type
.
- property default_protocol
In case only one protocol exists for the device, this is the default protocol.
- property device_types
This property contains a dict of all device types in the device module. The keys are type names, the values are the types themselves.
- property interfaces
This property contains a map with protocols as keys and interface types as values. The types are imported from the
interfaces
sub-module and from the device module itself. If two interfaces with the same protocol are discovered, a RuntimeError is raiesed.
- property name
The name of the device, which is also the name of the device module.
- property protocols
All available protocols for this device.
- property setups
A map with all available setups. Setups are imported from the
setups
dictionary in a device module and from thesetups
sub-module. If nodefault
-setup exists, one is created using the default_device_type. If there are several device types in the module, the default setup must be provided explicitly.
- class lewis.core.devices.DeviceRegistry(device_module)[source]
Bases:
object
This class takes the name of a module and constructs a
DeviceBuilder
from each sub-module. The available devices can be queried and a DeviceBuilder can be obtained for each device:from lewis.core.devices import DeviceRegistry registry = DeviceRegistry("lewis.devices") chopper_builder = registry.device_builder("chopper") # construct device, interface, ...
If the module can not be imported, a LewisException is raised.
- Parameters:
device_module – Name of device module from which devices are loaded.
- device_builder(name)[source]
Returns a
DeviceBuilder
instance that can be used to create device objects based on setups, as well as device interfaces. If the device name is not stored in the internal map, a LewisException is raised.Each DeviceBuilder has a
framework_version
-member, which specifies the version of Lewis the device has been written for. If the version does not match the current framework version, it is only possible to obtain those device builders calling the method withstrict_versions
set toFalse
, otherwise aLewisException
is raised. A warning message is logged in all cases. Ifframework_version
isNone
(e.g. not specified at all), it is accepted unlessstrict_versions
is set toTrue
.- Parameters:
name – Name of the device.
- Returns:
DeviceBuilder
-object for requested device.
- property devices
All available device names.
- class lewis.core.devices.InterfaceBase[source]
Bases:
object
This class is a common base for protocol specific interfaces that are exposed by a subclass of
Adapter
. This base class is not meant to be used directly in a device package - this is what the interfaces inlewis.adapters
are for.There is a 1:1 correspondence between device and interface, where the interface holds a reference to the device. It can be changed through the
device
-property.- property adapter: NoReturn
Adapter type that is required to process and expose interfaces of this type. Must be implemented in subclasses.
- property device
The device this interface is bound to. When a new device is set,
_bind_device()
is called, where the interface can react to the device change if necessary.
- lewis.core.devices.is_device(obj)[source]
Returns True if obj is a device type (derived from DeviceBase), but not defined in
lewis.core.devices
orlewis.devices
.- Parameters:
obj – Object to test.
- Returns:
True if obj is a device type.
- lewis.core.devices.is_interface(obj)[source]
Returns True if obj is an interface (derived from
InterfaceBase
), but not defined inlewis.adapters
, where concrete interfaces for protocols are defined.- Parameters:
obj – Object to test.
- Returns:
True if obj is an interface type.