+def load_device(filename, devices):
+ """Return an open device from `devices` which has a given `filename`.
+
+ Sometimes a caller will already have the required `Device`, in
+ which case we just pull that instance out of `devices`, check that
+ it's open, and return it. Other times, the caller may want us to
+ open the device ourselves, so if we can't find an appropriate
+ device in `devices`, we create a new one, append it to `devices`
+ (so the caller can close it later), and return it.
+
+ You will have to open the `Device` yourself, though, because the
+ open device instance should not be held by a particular
+ `PiezoAxis` instance. If you don't want to open devices yourself,
+ you can pass in a blank list of devices, and the initialization
+ routine will append any necessary-but-missing devices to it.
+
+ >>> from pycomedi.device import Device
+
+ >>> devices = [Device('/dev/comedi0')]
+ >>> device = load_device(filename='/dev/comedi0', devices=devices)
+ >>> device.filename
+ '/dev/comedi0'
+ >>> device.file is not None
+ True
+ >>> device.close()
+
+ >>> devices = []
+ >>> device = load_device(filename='/dev/comedi0', devices=devices)
+ >>> devices == [device]
+ True
+ >>> device.filename
+ '/dev/comedi0'
+ >>> device.file is not None
+ True
+ >>> device.close()
+
+ We try and return helpful errors when things go wrong:
+
+ >>> device = load_device(filename='/dev/comedi0', devices=None)
+ Traceback (most recent call last):
+ ...
+ TypeError: 'NoneType' object is not iterable
+ >>> device = load_device(filename='/dev/comedi0', devices=tuple())
+ Traceback (most recent call last):
+ ...
+ ValueError: none of the available devices ([]) match /dev/comedi0, and we cannot append to ()
+ >>> device = load_device(filename='/dev/comediX', devices=[])
+ Traceback (most recent call last):
+ ...
+ PyComediError: comedi_open (/dev/comediX): No such file or directory (None)
+ """
+ try:
+ matching_devices = [d for d in devices if d.filename == filename]
+ except TypeError:
+ _LOG.error('non-iterable devices? ({})'.format(devices))
+ raise
+ if matching_devices:
+ device = matching_devices[0]
+ if device.file is None:
+ device.open()
+ else:
+ device = Device(filename)
+ device.open()
+ try:
+ devices.append(device) # pass new device back to caller
+ except AttributeError:
+ device.close()
+ raise ValueError(
+ ('none of the available devices ({}) match {}, and we '
+ 'cannot append to {}').format(
+ [d.filename for d in devices], filename, devices))
+ return device
+
+def _load_channel_from_config(channel, devices, subdevice_type):
+ c = channel.config # reduce verbosity
+ if not channel.channel:
+ device = load_device(filename=c['device'], devices=devices)
+ if c['subdevice'] < 0:
+ subdevice = device.find_subdevice_by_type(
+ subdevice_type, factory=StreamingSubdevice)
+ else:
+ subdevice = device.subdevice(
+ index=c['subdevice'], factory=StreamingSubdevice)
+ channel.channel = subdevice.channel(
+ index=c['channel'], factory=AnalogChannel,
+ aref=c['analog-reference'])
+ channel.channel.range = channel.channel.get_range(index=c['range'])
+ channel.name = c['name']
+