From d418e614f928add3b81128a61f42240cb124c846 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Wed, 17 Jan 2024 16:25:09 -0800 Subject: [PATCH] Fix handling of multiple DynamicProvider --- src/p4p/server/__init__.py | 5 +++-- src/p4p/test/test_server.py | 20 ++++++++++++++++++++ src/pvxs_source.cpp | 5 ++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/p4p/server/__init__.py b/src/p4p/server/__init__.py index 3b47744d..48e20bf9 100644 --- a/src/p4p/server/__init__.py +++ b/src/p4p/server/__init__.py @@ -205,8 +205,9 @@ def __init__(self): def testChannel(self, name): # return True, False, or DynamicProvider.NotYet return name=="blah" def makeChannel(self, name, peer): - assert name=="blah" - return self.pv + if name=="blah": + return self.pv + # return None falls through to next source provider = DynamicProvider("arbitrary", DynHandler()) server = Server(providers=[provider]) """ diff --git a/src/p4p/test/test_server.py b/src/p4p/test/test_server.py index 1646c191..9710efcf 100644 --- a/src/p4p/test/test_server.py +++ b/src/p4p/test/test_server.py @@ -8,7 +8,9 @@ import threading from ..server import Server, installProvider, removeProvider, DynamicProvider, StaticProvider +from ..server.thread import SharedPV from ..client.thread import Context +from ..nt import NTScalar from .utils import RefTestCase @@ -96,6 +98,24 @@ def test_client(self): finally: removeProvider("foo") +class TestMultipleProviders(RefTestCase): + class Single(DynamicProvider): + def __init__(self, pv): + super(TestMultipleProviders.Single, self).__init__(pv, self) + self._name = pv + self._pv = SharedPV(nt=NTScalar('s'), initial=pv) + def testChannel(self, name): + return name==self._name + def makeChannel(self, name, peer): + if name==self._name: + return self._pv + + def test_multiple(self): + with Server([self.Single('one'), self.Single('two')], isolate=True) as S: + with Context('pva', conf=S.conf(), useenv=False) as C: + self.assertEqual('one', C.get('one')) + self.assertEqual('two', C.get('two')) + class TestServerConf(RefTestCase): def test_bad_iface(self): P = StaticProvider('x') diff --git a/src/pvxs_source.cpp b/src/pvxs_source.cpp index 6304b487..5c0da041 100644 --- a/src/pvxs_source.cpp +++ b/src/pvxs_source.cpp @@ -111,11 +111,14 @@ struct DynamicSource : public server::Source PyErr_Print(); PyErr_Clear(); + } else if(ret.obj==Py_None) { + // This source will not provide. + } else if(auto pv = SharedPV_unwrap(ret.obj)) { pv.attach(std::move(op)); } else { - PyErr_Format(PyExc_TypeError, "makeChannel(\"%s\") must return SharedPV, not %s", + PyErr_Format(PyExc_TypeError, "makeChannel(\"%s\") must return SharedPV or None, not %s", op->name().c_str(), Py_TYPE(ret.obj)->tp_name); PyErr_Print();