Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix handling of multiple DynamicProvider #138

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/p4p/server/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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])
"""
Expand Down
20 changes: 20 additions & 0 deletions src/p4p/test/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -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')
Expand Down
5 changes: 4 additions & 1 deletion src/pvxs_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Loading