diff options
author | Ted Ross <tross@apache.org> | 2010-01-13 11:57:19 +0000 |
---|---|---|
committer | Ted Ross <tross@apache.org> | 2010-01-13 11:57:19 +0000 |
commit | 79a29f32ef84c26de35d3e75c3acff314b727f56 (patch) | |
tree | d66d4d2a8a6cc2d9836fd1816b818a1c6e859e35 /cpp/bindings | |
parent | ac53f58b4387bc54b186a9ac3a8933ecce77790e (diff) | |
download | qpid-python-79a29f32ef84c26de35d3e75c3acff314b727f56.tar.gz |
Added raise_event support to the Ruby and Python wrapped agent APIs.
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@898727 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/bindings')
-rw-r--r-- | cpp/bindings/qmf/python/qmf.py | 109 | ||||
-rw-r--r-- | cpp/bindings/qmf/qmfengine.i | 1 | ||||
-rw-r--r-- | cpp/bindings/qmf/ruby/qmf.rb | 94 | ||||
-rwxr-xr-x | cpp/bindings/qmf/tests/agent_ruby.rb | 32 | ||||
-rw-r--r-- | cpp/bindings/qmf/tests/python_agent.py | 31 | ||||
-rwxr-xr-x | cpp/bindings/qmf/tests/python_console.py | 38 |
6 files changed, 295 insertions, 10 deletions
diff --git a/cpp/bindings/qmf/python/qmf.py b/cpp/bindings/qmf/python/qmf.py index c00c777878..eec975c50f 100644 --- a/cpp/bindings/qmf/python/qmf.py +++ b/cpp/bindings/qmf/python/qmf.py @@ -34,6 +34,8 @@ from qmfengine import (TYPE_ABSTIME, TYPE_ARRAY, TYPE_BOOL, TYPE_DELTATIME, TYPE_UINT8, TYPE_UUID) from qmfengine import (O_EQ, O_NE, O_LT, O_LE, O_GT, O_GE, O_RE_MATCH, O_RE_NOMATCH, E_NOT, E_AND, E_OR, E_XOR) +from qmfengine import (SEV_EMERG, SEV_ALERT, SEV_CRIT, SEV_ERROR, SEV_WARN, SEV_NOTICE, + SEV_INFORM, SEV_DEBUG) def qmf_to_native(val): @@ -351,9 +353,103 @@ class Session: ##============================================================================== - ## OBJECTS + ## OBJECTS and EVENTS ##============================================================================== +class QmfEvent(object): + # attr_reader :impl, :event_class + def __init__(self, cls, kwargs={}): + self._allow_sets = True + if kwargs.has_key("broker"): + self._broker = kwargs["broker"] + else: + self._broker = None + if cls: + self.event_class = cls + self.impl = qmfengine.Event(self.event_class.impl) + elif kwargs.has_key("impl"): + self.impl = qmfengine.Event(kwargs["impl"]) + self.event_class = SchemaEventClass(None, None, 0, + {"impl":self.impl.getClass()}) + else: + raise Exception("Argument error: required parameter ('impl') not supplied") + + + def arguments(self): + list = [] + for arg in self.event_class.arguments: + list.append([arg, self.get_attr(arg.name())]) + return list + + + def get_attr(self, name): + val = self._value(name) + return qmf_to_native(val) + + + def set_attr(self, name, v): + val = self._value(name) + native_to_qmf(val, v) + + + def __getitem__(self, name): + return self.get_attr(name) + + + def __setitem__(self, name, value): + self.set_attr(name, value) + + + def __setattr__(self, name, value): + # + # Ignore the internal attributes, set them normally... + # + if (name[0] == '_' or + name == 'impl' or + name == 'event_class'): + return super.__setattr__(self, name, value) + + if not self._allow_sets: + raise Exception("'Set' operations not permitted on this object") + + # + # If the name matches an argument name, set the value of the argument. + # + # print "set name=%s" % str(name) + for arg in self.event_class.arguments: + if arg.name() == name: + return self.set_attr(name, value) + + # unrecognized name? should I raise an exception? + super.__setattr__(self, name, value) + + + def __getattr__(self, name, *args): + # + # If the name matches an argument name, return the value of the argument. + # + for arg in self.event_class.arguments: + if arg.name() == name: + return self.get_attr(name) + + # + # This name means nothing to us, pass it up the line to the parent + # class's handler. + # + # print "__getattr__=%s" % str(name) + super.__getattr__(self, name) + + + def _value(self, name): + val = self.impl.getValue(name) + if not val: + raise Exception("Argument error: attribute named '%s' not defined for package %s, class %s" % + (name, + self.event_class.impl.getClassKey().getPackageName(), + self.event_class.impl.getClassKey().getClassName())) + return val + + class QmfObject(object): # attr_reader :impl, :object_class def __init__(self, cls, kwargs={}): @@ -922,14 +1018,14 @@ class SchemaObjectClass: class SchemaEventClass: # attr_reader :impl :arguments - def __init__(self, package, name, kwargs={}): + def __init__(self, package, name, sev, kwargs={}): self.arguments = [] if "impl" in kwargs: self.impl = kwargs["impl"] for i in range(self.impl.getArgumentCount()): self.arguments.append(SchemaArgument(nil, nil, {"impl":self.impl.getArgument(i)})) else: - self.impl = qmfengine.SchemaEventClass(package, name) + self.impl = qmfengine.SchemaEventClass(package, name, sev) if kwargs.has_key("desc"): self.impl.setDesc(kwargs["desc"]) @@ -1026,7 +1122,7 @@ class Console(Thread): if kind == CLASS_OBJECT: clist.append(SchemaObjectClass(None, None, {"impl":self.impl.getObjectClass(key)})) elif kind == CLASS_EVENT: - clist.append(SchemaEventClass(None, None, {"impl":self.impl.getEventClass(key)})) + clist.append(SchemaEventClass(None, None, 0, {"impl":self.impl.getEventClass(key)})) return clist @@ -1436,7 +1532,10 @@ class Agent(ConnectionHandler): def alloc_object_id(self, low = 0, high = 0): return ObjectId(self.impl.allocObjectId(low, high)) - + + def raise_event(self, event): + self.impl.raiseEvent(event.impl) + def query_response(self, context, obj): self.impl.queryResponse(context, obj.impl) diff --git a/cpp/bindings/qmf/qmfengine.i b/cpp/bindings/qmf/qmfengine.i index 3477215254..eb350115a3 100644 --- a/cpp/bindings/qmf/qmfengine.i +++ b/cpp/bindings/qmf/qmfengine.i @@ -37,6 +37,7 @@ %include <qmf/engine/Value.h> %include <qmf/engine/ObjectId.h> %include <qmf/engine/Object.h> +%include <qmf/engine/Event.h> %inline { diff --git a/cpp/bindings/qmf/ruby/qmf.rb b/cpp/bindings/qmf/ruby/qmf.rb index ea085d1be2..cc2aadc337 100644 --- a/cpp/bindings/qmf/ruby/qmf.rb +++ b/cpp/bindings/qmf/ruby/qmf.rb @@ -26,7 +26,8 @@ module Qmf # Pull all the TYPE_* constants into Qmf namespace. Maybe there's an easier way? Qmfengine.constants.each do |c| - if c.index('TYPE_') == 0 or c.index('ACCESS_') == 0 or c.index('DIR_') == 0 or c.index('CLASS_') == 0 + if c.index('TYPE_') == 0 or c.index('ACCESS_') == 0 or c.index('DIR_') == 0 or + c.index('CLASS_') == 0 or c.index('SEV_') == 0 const_set(c, Qmfengine.const_get(c)) end end @@ -307,9 +308,90 @@ module Qmf end ##============================================================================== - ## OBJECTS + ## OBJECTS and EVENTS ##============================================================================== + class QmfEvent + attr_reader :impl, :event_class + def initialize(cls, kwargs={}) + @broker = kwargs[:broker] if kwargs.include?(:broker) + @allow_sets = :true + + if cls: + @event_class = cls + @impl = Qmfengine::Event.new(@event_class.impl) + elsif kwargs.include?(:impl) + @impl = Qmfengine::Event.new(kwargs[:impl]) + @event_class = SchemaEventClass.new(nil, nil, :impl => @impl.getClass) + end + end + + def arguments + list = [] + @event_class.arguments.each do |arg| + list << [arg, get_attr(arg.name)] + end + return list + end + + def get_attr(name) + val = value(name) + $util.qmf_to_native(val) + end + + def set_attr(name, v) + val = value(name) + $util.native_to_qmf(val, v) + end + + def [](name) + get_attr(name) + end + + def []=(name, value) + set_attr(name, value) + end + + def method_missing(name_in, *args) + # + # Convert the name to a string and determine if it represents an + # attribute assignment (i.e. "attr=") + # + name = name_in.to_s + attr_set = (name[name.length - 1] == 61) + name = name[0..name.length - 2] if attr_set + raise "Sets not permitted on this object" if attr_set && !@allow_sets + + # + # If the name matches an argument name, set or return the value of the argument. + # + @event_class.arguments.each do |arg| + if arg.name == name + if attr_set + return set_attr(name, args[0]) + else + return get_attr(name) + end + end + end + + # + # This name means nothing to us, pass it up the line to the parent + # class's handler. + # + super.method_missing(name_in, args) + end + + private + def value(name) + val = @impl.getValue(name.to_s) + if val.nil? + raise ArgumentError, "Attribute '#{name}' not defined for event #{@event_class.impl.getClassKey.getPackageName}:#{@object_class.impl.getClassKey.getClassName}" + end + return val + end + end + class QmfObject include MonitorMixin attr_reader :impl, :object_class @@ -845,7 +927,7 @@ module Qmf class SchemaEventClass attr_reader :impl, :arguments - def initialize(package, name, kwargs={}) + def initialize(package, name, sev, kwargs={}) @arguments = [] if kwargs.include?(:impl) @impl = kwargs[:impl] @@ -853,7 +935,7 @@ module Qmf @arguments << SchemaArgument.new(nil, nil, :impl => @impl.getArgument(i)) end else - @impl = Qmfengine::SchemaEventClass.new(package, name) + @impl = Qmfengine::SchemaEventClass.new(package, name, sev) @impl.setDesc(kwargs[:desc]) if kwargs.include?(:desc) end end @@ -1288,6 +1370,10 @@ module Qmf ObjectId.new(@impl.allocObjectId(low, high)) end + def raise_event(event) + @impl.raiseEvent(event.impl) + end + def query_response(context, object) @impl.queryResponse(context, object.impl) end diff --git a/cpp/bindings/qmf/tests/agent_ruby.rb b/cpp/bindings/qmf/tests/agent_ruby.rb index 0be779994a..86eefc59a6 100755 --- a/cpp/bindings/qmf/tests/agent_ruby.rb +++ b/cpp/bindings/qmf/tests/agent_ruby.rb @@ -23,7 +23,7 @@ require 'qmf' require 'socket' class Model - attr_reader :parent_class, :child_class + attr_reader :parent_class, :child_class, :event_class def initialize @parent_class = Qmf::SchemaObjectClass.new("org.apache.qpid.qmf", "parent") @@ -79,11 +79,16 @@ class Model @child_class = Qmf::SchemaObjectClass.new("org.apache.qpid.qmf", "child") @child_class.add_property(Qmf::SchemaProperty.new("name", Qmf::TYPE_SSTR, :index => true)) + + @event_class = Qmf::SchemaEventClass.new("org.apache.qpid.qmf", "test_event", Qmf::SEV_INFORM) + @event_class.add_argument(Qmf::SchemaArgument.new("uint32val", Qmf::TYPE_UINT32)) + @event_class.add_argument(Qmf::SchemaArgument.new("strval", Qmf::TYPE_LSTR)) end def register(agent) agent.register_class(@parent_class) agent.register_class(@child_class) + agent.register_class(@event_class) end end @@ -139,6 +144,11 @@ class App < Qmf::AgentHandler 'sstr' => "Short String", 'map' => {'first' => 'FIRST', 'second' => 'SECOND'}} + event = Qmf::QmfEvent.new(@model.event_class) + event.uint32val = @parent.uint32val + event.strval = "Unused" + @agent.raise_event(event) + elsif args['test'] == "small" @parent.uint64val = 4 @parent.uint32val = 5 @@ -150,6 +160,11 @@ class App < Qmf::AgentHandler @parent.int16val = 10 @parent.int8val = 11 + event = Qmf::QmfEvent.new(@model.event_class) + event.uint32val = @parent.uint32val + event.strval = "Unused" + @agent.raise_event(event) + elsif args['test'] == "negative" @parent.uint64val = 0 @parent.uint32val = 0 @@ -161,6 +176,11 @@ class App < Qmf::AgentHandler @parent.int16val = -1000 @parent.int8val = -100 + event = Qmf::QmfEvent.new(@model.event_class) + event.uint32val = @parent.uint32val + event.strval = "Unused" + @agent.raise_event(event) + else retCode = 1 retText = "Invalid argument value for test" @@ -169,9 +189,19 @@ class App < Qmf::AgentHandler elsif name == "set_short_string" @parent.sstrval = args['value'] + event = Qmf::QmfEvent.new(@model.event_class) + event.uint32val = 0 + event.strval = @parent.sstrval + @agent.raise_event(event) + elsif name == "set_long_string" @parent.lstrval = args['value'] + event = Qmf::QmfEvent.new(@model.event_class) + event.uint32val = 0 + event.strval = @parent.lstrval + @agent.raise_event(event) + elsif name == "create_child" oid = @agent.alloc_object_id(2) args['child_ref'] = oid diff --git a/cpp/bindings/qmf/tests/python_agent.py b/cpp/bindings/qmf/tests/python_agent.py index c42273d7b2..83531830b1 100644 --- a/cpp/bindings/qmf/tests/python_agent.py +++ b/cpp/bindings/qmf/tests/python_agent.py @@ -82,10 +82,15 @@ class Model: self.child_class = qmf.SchemaObjectClass("org.apache.qpid.qmf", "child") self.child_class.add_property(qmf.SchemaProperty("name", qmf.TYPE_SSTR, {"index":True})) + self.event_class = qmf.SchemaEventClass("org.apache.qpid.qmf", "test_event", qmf.SEV_NOTICE) + self.event_class.add_argument(qmf.SchemaArgument("uint32val", qmf.TYPE_UINT32)) + self.event_class.add_argument(qmf.SchemaArgument("strval", qmf.TYPE_LSTR)) + def register(self, agent): agent.register_class(self.parent_class) agent.register_class(self.child_class) + agent.register_class(self.event_class) @@ -151,6 +156,12 @@ class App(qmf.AgentHandler): 'sstr' : "Short String", 'map' : {'first' : 'FIRST', 'second' : 'SECOND'}}) + event = qmf.QmfEvent(self._model.event_class) + event.uint32val = self._parent.get_attr("uint32val") + event.strval = "Unused" + + self._agent.raise_event(event) + ## Test the __getattr__ implementation: ## @todo: remove once python_client implements this ## form of property access @@ -169,6 +180,11 @@ class App(qmf.AgentHandler): self._parent.set_attr("int16val", 10) self._parent.set_attr("int8val", 11) + event = qmf.QmfEvent(self._model.event_class) + event.uint32val = self._parent.uint32val + event.strval = "Unused" + self._agent.raise_event(event) + elif args['test'] == "negative": self._parent.set_attr("uint64val", 0) self._parent.set_attr("uint32val", 0) @@ -180,6 +196,11 @@ class App(qmf.AgentHandler): self._parent.set_attr("int16val", -1000) self._parent.set_attr("int8val", -100) + event = qmf.QmfEvent(self._model.event_class) + event.uint32val = self._parent.uint32val + event.strval = "Unused" + self._agent.raise_event(event) + else: _retCode = 1 _retText = "Invalid argument value for test" @@ -188,10 +209,20 @@ class App(qmf.AgentHandler): elif name == "set_short_string": self._parent.set_attr('sstrval', args['value']) + event = qmf.QmfEvent(self._model.event_class) + event.uint32val = 0 + event.strval = self._parent.sstrval + self._agent.raise_event(event) + self._agent.method_response(context, 0, "OK", args) elif name == "set_long_string": self._parent.set_attr('lstrval', args['value']) + event = qmf.QmfEvent(self._model.event_class) + event.uint32val = 0 + event.strval = self._parent.lstrval + self._agent.raise_event(event) + self._agent.method_response(context, 0, "OK", args) elif name == "create_child": diff --git a/cpp/bindings/qmf/tests/python_console.py b/cpp/bindings/qmf/tests/python_console.py index 6f366d1a3d..fe27c33c4b 100755 --- a/cpp/bindings/qmf/tests/python_console.py +++ b/cpp/bindings/qmf/tests/python_console.py @@ -23,6 +23,7 @@ from qpid.testlib import TestBase010 from qpid.datatypes import Message from qpid.queue import Empty from time import sleep +import qmf.console class QmfInteropTests(TestBase010): @@ -166,6 +167,43 @@ class QmfInteropTests(TestBase010): for binding in bindings: self.assertEqual(binding.exchangeRef, mgmt_exchange.getObjectId()) + def test_F_events(self): + class Handler(qmf.console.Console): + def __init__(self): + self.queue = [] + + def event(self, broker, event): + if event.getClassKey().getClassName() == "test_event": + self.queue.append(event) + + handler = Handler() + self.startQmf(handler) + + parents = self.qmf.getObjects(_class="parent") + self.assertEqual(len(parents), 1) + parent = parents[0] + + parent.set_numerics("big") + parent.set_numerics("small") + parent.set_numerics("negative") + parent.set_short_string("TEST") + parent.set_long_string("LONG_TEST") + parent.probe_userid() + + queue = handler.queue + self.assertEqual(len(queue), 5) + self.assertEqual(queue[0].arguments["uint32val"], 0xA5A55A5A) + self.assertEqual(queue[0].arguments["strval"], "Unused") + self.assertEqual(queue[1].arguments["uint32val"], 5) + self.assertEqual(queue[1].arguments["strval"], "Unused") + self.assertEqual(queue[2].arguments["uint32val"], 0) + self.assertEqual(queue[2].arguments["strval"], "Unused") + self.assertEqual(queue[3].arguments["uint32val"], 0) + self.assertEqual(queue[3].arguments["strval"], "TEST") + self.assertEqual(queue[4].arguments["uint32val"], 0) + self.assertEqual(queue[4].arguments["strval"], "LONG_TEST") + + def getProperty(self, msg, name): for h in msg.headers: if hasattr(h, name): return getattr(h, name) |