Open
Description
Description
Only one DynamicProvider
is really supported, the second one is dispatched incorrectly.
To reproduce
Run the following server:
from p4p.server import Server, DynamicProvider
from p4p.server.thread import SharedPV
from p4p.nt import NTScalar
class DynHandler(object):
def __init__(self, name):
self.name = name
self.pv = SharedPV(nt=NTScalar('d'), initial=0.0)
def testChannel(self, name): # return True, False, or DynamicProvider.NotYet
return name == self.name
def makeChannel(self, name, peer):
assert name == self.name
return self.pv
providers = [
DynamicProvider("foo", DynHandler("foo")),
DynamicProvider("bar", DynHandler("bar")),
]
server = Server.forever(providers)
Then run pvget foo
Observed behaviour
bar
is also called, raising an assertion error:
Unexpected
Traceback (most recent call last):
File "/ics/tools/p4p/python3.8/linux-x86_64/p4p/server/__init__.py", line 238, in makeChannel
return self._real.makeChannel(name, peer)
File "/tmp/multi_p4p.py", line 14, in makeChannel
assert name == self.name
AssertionError
TypeError: makeChannel("foo") must return SharedPV, not NoneType
Expected behaviour
Only foo
channel is called.
Stopgap solution
class MergeHandler:
def __init__(self, handlers):
self.handlers = handlers
def get_responsible(self, name):
responsible = [
handler for handler in self.handlers if handler.testChannel(name)
]
if len(responsible) == 1:
return responsible[0]
elif len(responsible) == 0:
return
else:
raise ValueError("More than one responsible handler~!")
def testChannel(self, name):
return self.get_responsible(name) is not None
def makeChannel(self, name, peer):
responsible = self.get_responsible(name)
return responsible.makeChannel(name, peer)