spqr 0.0.4 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +19 -0
- data/TODO +2 -3
- data/VERSION +1 -1
- data/examples/agent-app.rb +10 -0
- data/examples/examples/codegen/EchoAgent.rb +39 -0
- data/examples/hello.rb +41 -10
- data/examples/logservice.rb +14 -14
- data/lib/spqr/app.rb +34 -10
- data/lib/spqr/codegen.rb +47 -12
- data/lib/spqr/manageable.rb +45 -14
- data/test/example-apps.rb +19 -19
- data/test/test_spqr_clicker.rb +3 -3
- data/test/test_spqr_hello.rb +1 -4
- data/test/test_spqr_integerprop.rb +4 -1
- metadata +3 -1
data/CHANGES
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
version 0.1.0 (3a3ca52c4f086d1f20fdf5ed89dda262622c171d)
|
2
|
+
|
3
|
+
* Note that this version breaks backwards compatibility, for reasons
|
4
|
+
mentioned below. Most notably, the Manageable API names have changed,
|
5
|
+
and the old-style exposed-method declarations (with hash args) are no
|
6
|
+
longer supported in favor of a more idiomatic style.
|
7
|
+
|
8
|
+
* Exposed methods now use idiomatic parameter-passing style: input
|
9
|
+
(and in/out) parameters are passed in to methods by name (in the
|
10
|
+
order that they appear in the expose declaration), and output (and
|
11
|
+
in/out) values are returned in a list via a standard return
|
12
|
+
statement. (Again, the order of output and in/out parameters is
|
13
|
+
specified by the order that they appear in the expose declaration.)
|
14
|
+
|
15
|
+
* Code generation now uses idiomatic parameter-passing style. Code
|
16
|
+
generation should still be considered "alpha"-quality.
|
17
|
+
|
18
|
+
* Changed mixed-in method names from Manageable.
|
19
|
+
|
1
20
|
version 0.0.4 (180897a77b55400b31d364a08cb9f81c423eb59f)
|
2
21
|
|
3
22
|
* Test suite is mainly stable (individual tests will sometimes hang
|
data/TODO
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
To do, overall:
|
2
2
|
|
3
|
-
* packaging
|
3
|
+
* packaging (partially done)
|
4
4
|
|
5
5
|
|
6
6
|
To do for spqr:
|
@@ -8,12 +8,11 @@ To do for spqr:
|
|
8
8
|
! Event support
|
9
9
|
* Broader query support (partially done)
|
10
10
|
* Documentation
|
11
|
-
* Test suite
|
11
|
+
* Test suite (partially done)
|
12
12
|
- Automatic generation of smoke tests for services (either from schema or manageable class)
|
13
13
|
- Automatic schema generation from agent apps
|
14
14
|
- Usability improvements:
|
15
15
|
- Fewer required annotations
|
16
|
-
- Eliminate requirement for kwargs-style methods
|
17
16
|
- Automatic decoration of certain methods
|
18
17
|
|
19
18
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spqr/spqr'
|
2
|
+
|
3
|
+
module Examples
|
4
|
+
module Codegen
|
5
|
+
class EchoAgent
|
6
|
+
include ::SPQR::Manageable
|
7
|
+
|
8
|
+
qmf_package_name 'examples.codegen'
|
9
|
+
qmf_class_name 'EchoAgent'
|
10
|
+
# Find method (NB: you must implement this)
|
11
|
+
def EchoAgent.find_by_id(objid)
|
12
|
+
EchoAgent.new
|
13
|
+
end
|
14
|
+
|
15
|
+
# Find-all method (NB: you must implement this)
|
16
|
+
def EchoAgent.find_all
|
17
|
+
[EchoAgent.new]
|
18
|
+
end
|
19
|
+
### Schema method declarations
|
20
|
+
|
21
|
+
# echo returns its argument
|
22
|
+
# * arg (lstr/IO)
|
23
|
+
#
|
24
|
+
def echo(arg)
|
25
|
+
# Print values of in/out parameters
|
26
|
+
log.debug "echo: arg => #{arg.inspect}"
|
27
|
+
# Assign values to in/out parameters
|
28
|
+
arg ||= ""
|
29
|
+
# Return value
|
30
|
+
log.debug "echo: returning #{arg.inspect}"
|
31
|
+
return arg
|
32
|
+
end
|
33
|
+
|
34
|
+
expose :echo do |args|
|
35
|
+
args.declare :arg, :lstr, :inout, {}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/examples/hello.rb
CHANGED
@@ -1,30 +1,57 @@
|
|
1
|
-
require 'rubygems'
|
2
1
|
require 'spqr/spqr'
|
3
2
|
require 'spqr/app'
|
4
3
|
require 'logger'
|
5
4
|
|
6
5
|
class Hello
|
7
6
|
include SPQR::Manageable
|
8
|
-
|
9
|
-
|
7
|
+
|
8
|
+
# Input (in and inout) parameters are passed to exposed methods in
|
9
|
+
# the order they are declared in the expose block (see below).
|
10
|
+
def hello(name)
|
11
|
+
# We will keep track of the number of people we have greeted over
|
12
|
+
# the lifetime of this agent (see below for the people_greeted
|
13
|
+
# statistic declaration).
|
10
14
|
@people_greeted = @people_greeted + 1
|
11
|
-
|
15
|
+
|
16
|
+
# In methods that return only one value --- that is, those which
|
17
|
+
# have only one parameter that is either out or inout --- the
|
18
|
+
# return value is provided normally. Methods that have multiple
|
19
|
+
# out and inout parameters should return a list that includes the
|
20
|
+
# returned values in the order they are specified in the expose block.
|
21
|
+
"Hello, #{name}!"
|
12
22
|
end
|
13
23
|
|
14
|
-
|
24
|
+
# This block indicates that we intend to expose the "hello" method
|
25
|
+
# over QMF, that "name" is the first (and only) formal input
|
26
|
+
# parameter, and "result" is the first (and only) formal output
|
27
|
+
# parameter. Argument declarations include a name, a type, a
|
28
|
+
# direction, and optional keyword arguments.
|
29
|
+
expose :hello do |args|
|
15
30
|
args.declare :name, :lstr, :in
|
16
31
|
args.declare :result, :lstr, :out
|
17
32
|
end
|
18
33
|
|
19
|
-
# This is
|
34
|
+
# This is the method that will be called to get the value of the
|
35
|
+
# service_name property
|
20
36
|
def service_name
|
21
37
|
@service_name = "HelloAgent"
|
22
38
|
end
|
23
39
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
40
|
+
# The following two declarations provide the QMF package and class
|
41
|
+
# names for the published class. These can be provided either as
|
42
|
+
# symbols or as strings. If the class name is omitted, it will be
|
43
|
+
# generated from the class name.
|
44
|
+
qmf_package_name :hello
|
45
|
+
qmf_class_name :Hello
|
46
|
+
|
47
|
+
# The following two declarations create named QMF statistics and
|
48
|
+
# properties with given types. The value for a statistic or
|
49
|
+
# property is taken from the return values of the instance method
|
50
|
+
# with the same name as that statistic or property. If a method
|
51
|
+
# with this name does not exist, one is created with attr_reader
|
52
|
+
# and attr_writer.
|
53
|
+
qmf_statistic :people_greeted, :int
|
54
|
+
qmf_property :service_name, :lstr
|
28
55
|
|
29
56
|
# These should return the same object for the lifetime of the agent
|
30
57
|
# app, since this example has no persistent objects.
|
@@ -36,6 +63,10 @@ class Hello
|
|
36
63
|
@@hellos ||= [Hello.new]
|
37
64
|
@@hellos[0]
|
38
65
|
end
|
66
|
+
|
67
|
+
def initialize
|
68
|
+
@people_greeted = 0
|
69
|
+
end
|
39
70
|
end
|
40
71
|
|
41
72
|
app = SPQR::App.new(:loglevel => :debug)
|
data/examples/logservice.rb
CHANGED
@@ -22,7 +22,6 @@
|
|
22
22
|
# generated log records in that file, and they will persist between
|
23
23
|
# invocations.
|
24
24
|
|
25
|
-
require 'rubygems'
|
26
25
|
require 'spqr/spqr'
|
27
26
|
require 'spqr/app'
|
28
27
|
require 'rhubarb/rhubarb'
|
@@ -31,11 +30,11 @@ class LogService
|
|
31
30
|
include SPQR::Manageable
|
32
31
|
|
33
32
|
[:debug, :warn, :info, :error].each do |name|
|
34
|
-
define_method name do |
|
35
|
-
|
33
|
+
define_method name do |msg|
|
34
|
+
LogRecord.create(:l_when=>Time.now.to_i, :severity=>"#{name.to_s.upcase}", :msg=>msg.dup)
|
36
35
|
end
|
37
36
|
|
38
|
-
|
37
|
+
expose name do |args|
|
39
38
|
args.declare :msg, :lstr, :in
|
40
39
|
args.declare :result, :objId, :out
|
41
40
|
end
|
@@ -50,8 +49,8 @@ class LogService
|
|
50
49
|
@@singleton ||= LogService.new
|
51
50
|
end
|
52
51
|
|
53
|
-
|
54
|
-
|
52
|
+
qmf_package_name :examples
|
53
|
+
qmf_class_name :LogService
|
55
54
|
end
|
56
55
|
|
57
56
|
class LogRecord
|
@@ -65,22 +64,23 @@ class LogRecord
|
|
65
64
|
# XXX: rhubarb should create a find_all by default
|
66
65
|
declare_query :find_all, "1"
|
67
66
|
|
68
|
-
|
69
|
-
|
70
|
-
|
67
|
+
qmf_property :l_when, :uint
|
68
|
+
qmf_property :severity, :lstr
|
69
|
+
qmf_property :msg, :lstr
|
71
70
|
|
72
|
-
|
73
|
-
|
71
|
+
qmf_package_name :examples
|
72
|
+
qmf_class_name :LogRecord
|
74
73
|
|
75
74
|
def spqr_object_id
|
76
75
|
row_id
|
77
76
|
end
|
78
77
|
end
|
79
78
|
|
80
|
-
|
81
|
-
|
79
|
+
DBLOC = (ARGV[0] or ":memory:")
|
80
|
+
puts "storing results to #{DBLOC}"
|
81
|
+
DO_CREATE = (DBLOC == ":memory:" or not File.exist?(DBLOC))
|
82
82
|
|
83
|
-
Rhubarb::Persistence::open(
|
83
|
+
Rhubarb::Persistence::open(DBLOC)
|
84
84
|
|
85
85
|
LogRecord.create_table if DO_CREATE
|
86
86
|
|
data/lib/spqr/app.rb
CHANGED
@@ -56,7 +56,7 @@ module SPQR
|
|
56
56
|
|
57
57
|
schemaclass = schematize(klass)
|
58
58
|
|
59
|
-
klass.
|
59
|
+
klass.log = @log
|
60
60
|
|
61
61
|
@classes_by_id[klass.class_id] = klass
|
62
62
|
@classes_by_name[klass.name] = ClassMeta.new(klass, schemaclass)
|
@@ -75,21 +75,41 @@ module SPQR
|
|
75
75
|
|
76
76
|
@log.debug "calling method: context=#{context} method=#{name} object_id=#{obj_id}, args=#{args}, user=#{user_id}"
|
77
77
|
|
78
|
-
|
78
|
+
managed_object = find_object(context, class_id, obj_id)
|
79
|
+
@log.debug("managed object is #{managed_object}")
|
80
|
+
managed_method = managed_object.class.spqr_meta.mmethods[name.to_sym]
|
81
|
+
|
82
|
+
raise RuntimeError.new("#{managed_object.class} does not have #{name} exposed as a manageable method; has #{managed_object.class.spqr_meta.mmethods.inspect}") unless managed_method
|
83
|
+
|
84
|
+
# Extract actual parameters from the Qmf::Arguments structure into a proper ruby list
|
79
85
|
|
80
86
|
# XXX: consider adding appropriate impl method to Manageable
|
81
87
|
# to avoid this little dance
|
82
|
-
|
88
|
+
actuals_in = managed_method.formals_in.inject([]) {|acc,nm| acc << args[nm]}
|
89
|
+
actuals_in = actuals_in[0] if actuals_in.size == 1
|
83
90
|
|
84
|
-
managed_object
|
85
|
-
@log.debug("
|
91
|
+
@log.debug("managed_object.respond_to? #{managed_method.name.to_sym} ==> #{managed_object.respond_to? managed_method.name.to_sym}")
|
92
|
+
@log.debug("managed_object.class.spqr_meta.mmethods.include? #{name.to_sym} ==> #{managed_object.class.spqr_meta.mmethods.include? name.to_sym}")
|
93
|
+
@log.debug("formals: #{managed_method.formals_in.inspect}")
|
94
|
+
@log.debug("actuals: #{actuals_in.inspect}")
|
86
95
|
|
87
|
-
|
88
|
-
|
96
|
+
actuals_out = actuals_in.size > 0 ? managed_object.send(name.to_sym, actuals_in) : managed_object.send(name.to_sym)
|
97
|
+
|
98
|
+
raise RuntimeError.new("#{managed_object.class} did not return the appropriate number of return values; got '#{actuals_out.inspect}', but expected #{managed_method.types_out.inspect}") unless result_valid(actuals_out, managed_method)
|
99
|
+
|
100
|
+
if managed_method.formals_out.size == 0
|
101
|
+
actuals_out = [] # ignore return value in this case
|
102
|
+
elsif managed_method.formals_out.size == 1
|
103
|
+
actuals_out = [actuals_out] # wrap this up in a list
|
104
|
+
end
|
89
105
|
|
90
|
-
|
106
|
+
@log.debug("formals_out == #{managed_method.formals_out.inspect}")
|
107
|
+
@log.debug("actuals_out == #{actuals_out.inspect}")
|
108
|
+
|
109
|
+
# Copy any out parameters from return value to the
|
91
110
|
# Qmf::Arguments structure; see XXX above
|
92
|
-
|
111
|
+
managed_method.formals_out.zip(actuals_out).each do |k,v|
|
112
|
+
@log.debug("fixing up out params: #{k.inspect} --> #{v.inspect}")
|
93
113
|
encoded_val = encode_object(v)
|
94
114
|
args[k] = encoded_val
|
95
115
|
end
|
@@ -160,6 +180,10 @@ module SPQR
|
|
160
180
|
|
161
181
|
private
|
162
182
|
|
183
|
+
def result_valid(actuals, mm)
|
184
|
+
(actuals.kind_of?(Array) and mm.formals_out.size == actuals.size) or mm.formals_out.size <= 1
|
185
|
+
end
|
186
|
+
|
163
187
|
def qmf_arguments_to_hash(args)
|
164
188
|
result = {}
|
165
189
|
args.each do |k,v|
|
@@ -189,7 +213,7 @@ module SPQR
|
|
189
213
|
|
190
214
|
sc = Qmf::SchemaObjectClass.new(package, classname)
|
191
215
|
|
192
|
-
meta.
|
216
|
+
meta.manageable_methods.each do |mm|
|
193
217
|
@log.info("+-- creating a QMF schema for method #{mm}")
|
194
218
|
m_opts = mm.options
|
195
219
|
m_opts[:desc] ||= mm.description if mm.description
|
data/lib/spqr/codegen.rb
CHANGED
@@ -182,15 +182,17 @@ module SPQR
|
|
182
182
|
pp "include ::SPQR::Manageable"
|
183
183
|
pp ""
|
184
184
|
|
185
|
-
pp "
|
186
|
-
pp "
|
185
|
+
pp "qmf_package_name '#{@package_list.join(".")}'"
|
186
|
+
pp "qmf_class_name '#{@sc.name.split("::")[-1]}'"
|
187
187
|
|
188
188
|
pp '# Find method (NB: you must implement this)'
|
189
189
|
pp_decl :def, "#{@sc.name}.find_by_id", "(objid)" do
|
190
190
|
pp "#{@sc.name}.new"
|
191
191
|
end
|
192
192
|
|
193
|
-
pp "
|
193
|
+
pp ""
|
194
|
+
|
195
|
+
pp '# Find-all method (NB: you must implement this)'
|
194
196
|
pp_decl :def, "#{@sc.name}.find_all" do
|
195
197
|
pp "[#{@sc.name}.new]"
|
196
198
|
end
|
@@ -237,7 +239,7 @@ module SPQR
|
|
237
239
|
property.options[:desc] = property.desc if property.desc
|
238
240
|
|
239
241
|
pp ""
|
240
|
-
pp "
|
242
|
+
pp "qmf_property #{property.name.to_sym.inspect}, #{property.kind.to_sym.inspect}, #{property.options.inspect.gsub(/[{}]/, '')}"
|
241
243
|
end
|
242
244
|
|
243
245
|
def gen_statistic(statistic)
|
@@ -251,7 +253,7 @@ module SPQR
|
|
251
253
|
statistic.options[:desc] = statistic.desc if statistic.desc
|
252
254
|
|
253
255
|
pp ""
|
254
|
-
pp "
|
256
|
+
pp "qmf_property #{statistic.name.to_sym.inspect}, #{statistic.kind.to_sym.inspect}, #{statistic.options.inspect.gsub(/[{}]/, '')}"
|
255
257
|
end
|
256
258
|
|
257
259
|
def gen_method(method)
|
@@ -265,8 +267,22 @@ module SPQR
|
|
265
267
|
in_params = method.args.select {|arg| ['in', 'i', 'qmf::dir_in'].include? arg.dir.to_s.downcase }
|
266
268
|
out_params = method.args.select {|arg| ['out', 'o', 'qmf::dir_out'].include? arg.dir.to_s.downcase }
|
267
269
|
inout_params = method.args.select {|arg| ['inout', 'io', 'qmf::dir_inout'].include? arg.dir.to_s.downcase }
|
268
|
-
|
269
|
-
|
270
|
+
|
271
|
+
formals_in = method.args.select {|arg| ['in','i','qmf::dir_in','io','inout','qmf::dir_inout'].include? arg.dir.to_s.downcase}.map{|arg| arg.name}.join(",")
|
272
|
+
formals_out = method.args.select {|arg| ['out','o','qmf::dir_out','io','inout','qmf::dir_inout'].include? arg.dir.to_s.downcase}.map{|arg| arg.name}
|
273
|
+
|
274
|
+
actuals_out = case formals_out.size
|
275
|
+
when 0 then nil.inspect
|
276
|
+
when 1 then formals_out[0].to_s
|
277
|
+
else "[#{formals_out.join(", ")}]"
|
278
|
+
end
|
279
|
+
|
280
|
+
param_types = method.args.inject({}) do |acc, arg|
|
281
|
+
acc[arg.name.to_s] = arg.kind.to_s
|
282
|
+
acc
|
283
|
+
end
|
284
|
+
|
285
|
+
pp_decl :def, method.name, "(#{formals_in})" do
|
270
286
|
|
271
287
|
if in_params.size + inout_params.size > 0
|
272
288
|
what = "in"
|
@@ -279,8 +295,8 @@ module SPQR
|
|
279
295
|
|
280
296
|
pp "\# Print values of #{what} parameters"
|
281
297
|
(in_params + inout_params).each do |arg|
|
282
|
-
argdisplay = arg.name.to_s
|
283
|
-
pp('log.debug "' + "#{arg.name} => " + '#{
|
298
|
+
argdisplay = arg.name.to_s
|
299
|
+
pp('log.debug "' + "#{method.name}: #{arg.name} => " + '#{' + "#{argdisplay}" + '}"')
|
284
300
|
end
|
285
301
|
end
|
286
302
|
|
@@ -296,15 +312,21 @@ module SPQR
|
|
296
312
|
pp "\# Assign values to #{what} parameters"
|
297
313
|
|
298
314
|
(out_params + inout_params).each do |arg|
|
299
|
-
argdisplay = arg.name.to_s
|
300
|
-
|
315
|
+
argdisplay = arg.name.to_s
|
316
|
+
argtype = param_types[argdisplay]
|
317
|
+
raise RuntimeError.new("Can't find type for #{argdisplay} in #{param_types.inspect}") unless argtype
|
318
|
+
pp "#{argdisplay} ||= #{default_val(argtype)}"
|
301
319
|
end
|
320
|
+
|
321
|
+
pp "\# Return value"
|
322
|
+
pp "return #{actuals_out}"
|
323
|
+
|
302
324
|
end
|
303
325
|
end
|
304
326
|
|
305
327
|
|
306
328
|
pp ""
|
307
|
-
pp_decl :
|
329
|
+
pp_decl :expose, "#{method.name.to_sym.inspect} do |args|" do
|
308
330
|
{:in => in_params, :inout => inout_params, :out => out_params}.each do |dir,coll|
|
309
331
|
coll.each do |arg|
|
310
332
|
arg_nm = arg.name
|
@@ -315,6 +337,19 @@ module SPQR
|
|
315
337
|
end
|
316
338
|
end
|
317
339
|
end
|
340
|
+
|
341
|
+
def default_val(ty)
|
342
|
+
case ty
|
343
|
+
when 'array', 'list' then [].inspect
|
344
|
+
when 'bool' then false.inspect
|
345
|
+
when 'double', 'float' then 0.0.inspect
|
346
|
+
when 'absTime', 'deltaTime', 'int16', 'int32', 'int64', 'int', 'int8', 'uint16', 'uint32', 'uint64', 'uint', 'uint8' then 0.inspect
|
347
|
+
when 'lstr', 'string', 'sstr', 'uuid' then "".inspect
|
348
|
+
when 'map' then {}.inspect
|
349
|
+
when 'objId' then nil.inspect
|
350
|
+
else raise RuntimeError.new("Unknown type #{ty.inspect}")
|
351
|
+
end
|
352
|
+
end
|
318
353
|
end
|
319
354
|
|
320
355
|
class AppBoilerplateGenerator
|
data/lib/spqr/manageable.rb
CHANGED
@@ -19,16 +19,19 @@ module SPQR
|
|
19
19
|
self.options = (({} unless self.options) or self.options.dup)
|
20
20
|
self.statistics = [] unless self.statistics
|
21
21
|
self.properties = [] unless self.properties
|
22
|
-
self.mmethods ||=
|
22
|
+
self.mmethods ||= {}
|
23
23
|
end
|
24
24
|
|
25
25
|
def declare_method(name, desc, options, blk=nil)
|
26
26
|
result = MethodMeta.new name, desc, options
|
27
27
|
blk.call(result.args) if blk
|
28
|
-
self.mmethods
|
29
|
-
self.mmethods[-1]
|
28
|
+
self.mmethods[name] = result
|
30
29
|
end
|
31
30
|
|
31
|
+
def manageable_methods
|
32
|
+
self.mmethods.values
|
33
|
+
end
|
34
|
+
|
32
35
|
def declare_statistic(name, kind, options)
|
33
36
|
declare_basic(:statistic, name, kind, options)
|
34
37
|
end
|
@@ -57,6 +60,34 @@ module SPQR
|
|
57
60
|
self.args = gen_args
|
58
61
|
end
|
59
62
|
|
63
|
+
def formals_in
|
64
|
+
self.args.select {|arg| arg.direction == :in or arg.direction == :inout}.collect{|arg| arg.name.to_s}
|
65
|
+
end
|
66
|
+
|
67
|
+
def formals_out
|
68
|
+
self.args.select {|arg| arg.direction == :inout or arg.direction == :out}.collect{|arg| arg.name.to_s}
|
69
|
+
end
|
70
|
+
|
71
|
+
def types_in
|
72
|
+
self.args.select {|arg| arg.direction == :in or arg.direction == :inout}.collect{|arg| arg.kind.to_s}
|
73
|
+
end
|
74
|
+
|
75
|
+
def types_out
|
76
|
+
self.args.select {|arg| arg.direction == :inout or arg.direction == :out}.collect{|arg| arg.kind.to_s}
|
77
|
+
end
|
78
|
+
|
79
|
+
def type_of(param)
|
80
|
+
@types_for ||= self.args.inject({}) do |acc,arg|
|
81
|
+
k = arg.name
|
82
|
+
v = arg.kind.to_s
|
83
|
+
acc[k] = v
|
84
|
+
acc[k.to_s] = v
|
85
|
+
acc
|
86
|
+
end
|
87
|
+
|
88
|
+
@types_for[param]
|
89
|
+
end
|
90
|
+
|
60
91
|
private
|
61
92
|
def gen_args
|
62
93
|
result = []
|
@@ -97,36 +128,36 @@ module SPQR
|
|
97
128
|
@spqr_meta ||= ::SPQR::ManageableMeta.new
|
98
129
|
end
|
99
130
|
|
100
|
-
def
|
131
|
+
def log=(logger)
|
101
132
|
@spqr_log = logger
|
102
133
|
end
|
103
134
|
|
104
|
-
def
|
135
|
+
def log
|
105
136
|
@spqr_log || ::SPQR::Sink.new
|
106
137
|
end
|
107
138
|
|
108
139
|
# Exposes a method to QMF
|
109
|
-
def
|
140
|
+
def expose(name, description=nil, options=nil, &blk)
|
110
141
|
spqr_meta.declare_method(name, description, options, blk)
|
111
142
|
end
|
112
143
|
|
113
|
-
def
|
144
|
+
def qmf_package_name(nm)
|
114
145
|
spqr_meta.package = nm
|
115
146
|
end
|
116
147
|
|
117
|
-
def
|
148
|
+
def qmf_class_name(nm)
|
118
149
|
spqr_meta.classname = nm
|
119
150
|
end
|
120
151
|
|
121
|
-
def
|
152
|
+
def qmf_description(d)
|
122
153
|
spqr_meta.description = d
|
123
154
|
end
|
124
155
|
|
125
|
-
def
|
156
|
+
def qmf_options(opts)
|
126
157
|
spqr_meta.options = opts.dup
|
127
158
|
end
|
128
159
|
|
129
|
-
def
|
160
|
+
def qmf_statistic(name, kind, options=nil)
|
130
161
|
spqr_meta.declare_statistic(name, kind, options)
|
131
162
|
|
132
163
|
self.class_eval do
|
@@ -142,7 +173,7 @@ module SPQR
|
|
142
173
|
end
|
143
174
|
end
|
144
175
|
|
145
|
-
def
|
176
|
+
def qmf_property(name, kind, options=nil)
|
146
177
|
spqr_meta.declare_property(name, kind, options)
|
147
178
|
|
148
179
|
# add a property accessor to instances of other
|
@@ -188,7 +219,7 @@ module SPQR
|
|
188
219
|
end
|
189
220
|
|
190
221
|
def log
|
191
|
-
self.class.
|
222
|
+
self.class.log
|
192
223
|
end
|
193
224
|
|
194
225
|
def self.included(other)
|
@@ -216,7 +247,7 @@ module SPQR
|
|
216
247
|
end
|
217
248
|
end
|
218
249
|
|
219
|
-
other.
|
250
|
+
other.qmf_class_name other.name.to_sym
|
220
251
|
end
|
221
252
|
end
|
222
253
|
end
|
data/test/example-apps.rb
CHANGED
@@ -15,17 +15,17 @@ class QmfClicker
|
|
15
15
|
@clicks = 0
|
16
16
|
end
|
17
17
|
|
18
|
-
def click
|
18
|
+
def click
|
19
19
|
@clicks = @clicks.succ
|
20
20
|
end
|
21
21
|
|
22
|
-
|
22
|
+
expose :click do |args|
|
23
23
|
end
|
24
24
|
|
25
|
-
|
25
|
+
qmf_statistic :clicks, :int
|
26
26
|
|
27
|
-
|
28
|
-
|
27
|
+
qmf_package_name :example
|
28
|
+
qmf_class_name :QmfClicker
|
29
29
|
end
|
30
30
|
|
31
31
|
class QmfHello
|
@@ -41,17 +41,17 @@ class QmfHello
|
|
41
41
|
@qmf_hellos
|
42
42
|
end
|
43
43
|
|
44
|
-
def hello(
|
45
|
-
|
44
|
+
def hello(name)
|
45
|
+
"Hello, #{name}!"
|
46
46
|
end
|
47
47
|
|
48
|
-
|
48
|
+
expose :hello do |args|
|
49
49
|
args.declare :name, :lstr, :in
|
50
50
|
args.declare :result, :lstr, :out
|
51
51
|
end
|
52
52
|
|
53
|
-
|
54
|
-
|
53
|
+
qmf_package_name :example
|
54
|
+
qmf_class_name :QmfHello
|
55
55
|
end
|
56
56
|
|
57
57
|
class QmfDummyProp
|
@@ -71,10 +71,10 @@ class QmfDummyProp
|
|
71
71
|
"DummyPropService"
|
72
72
|
end
|
73
73
|
|
74
|
-
|
74
|
+
qmf_property :service_name, :lstr
|
75
75
|
|
76
|
-
|
77
|
-
|
76
|
+
qmf_class_name :QmfDummyProp
|
77
|
+
qmf_package_name :example
|
78
78
|
end
|
79
79
|
|
80
80
|
|
@@ -109,18 +109,18 @@ class QmfIntegerProp
|
|
109
109
|
@qmf_ips
|
110
110
|
end
|
111
111
|
|
112
|
-
def next
|
113
|
-
|
112
|
+
def next
|
113
|
+
QmfIntegerProp.find_by_id((@int_id + 1) % QmfIntegerProp::SIZE)
|
114
114
|
end
|
115
115
|
|
116
|
-
|
116
|
+
expose :next do |args|
|
117
117
|
args.declare :result, :objId, :out
|
118
118
|
end
|
119
119
|
|
120
|
-
|
120
|
+
qmf_property :int_id, :int, :index=>true
|
121
121
|
|
122
|
-
|
123
|
-
|
122
|
+
qmf_class_name :QmfIntegerProp
|
123
|
+
qmf_package_name :example
|
124
124
|
end
|
125
125
|
|
126
126
|
|
data/test/test_spqr_clicker.rb
CHANGED
@@ -15,7 +15,7 @@ class TestSpqrClicker < Test::Unit::TestCase
|
|
15
15
|
assert_nothing_raised do
|
16
16
|
obj = $console.objects(:class=>"QmfClicker", :agent=>@ag)[0]
|
17
17
|
|
18
|
-
obj.click
|
18
|
+
obj.click
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -36,7 +36,7 @@ class TestSpqrClicker < Test::Unit::TestCase
|
|
36
36
|
obj = $console.objects(:class=>"QmfClicker", :agent=>@ag)[0]
|
37
37
|
assert_equal x, obj[:clicks]
|
38
38
|
|
39
|
-
obj.click
|
39
|
+
obj.click
|
40
40
|
x = x.succ
|
41
41
|
end
|
42
42
|
end
|
@@ -51,7 +51,7 @@ class TestSpqrClicker < Test::Unit::TestCase
|
|
51
51
|
obj.update
|
52
52
|
assert_equal x, obj[:clicks]
|
53
53
|
|
54
|
-
obj.click
|
54
|
+
obj.click
|
55
55
|
x = x.succ
|
56
56
|
end
|
57
57
|
end
|
data/test/test_spqr_hello.rb
CHANGED
@@ -18,12 +18,9 @@ class TestSpqrHello < Test::Unit::TestCase
|
|
18
18
|
def test_hello_call
|
19
19
|
app_setup QmfHello
|
20
20
|
obj = $console.objects(:class=>"QmfHello", :agent=>@ag)[0]
|
21
|
-
|
22
21
|
val = obj.hello("ruby").result
|
23
|
-
args = { 'name' => 'ruby' }
|
24
|
-
QmfHello.find_by_id(0).hello(args)
|
25
22
|
|
26
|
-
expected =
|
23
|
+
expected = QmfHello.find_by_id(0).hello("ruby")
|
27
24
|
|
28
25
|
assert_equal expected, val
|
29
26
|
end
|
@@ -16,7 +16,10 @@ class TestSpqrIntegerProp < Test::Unit::TestCase
|
|
16
16
|
|
17
17
|
objs.size.times do |x|
|
18
18
|
expected = objs[(x + 1) % QmfIntegerProp::SIZE]
|
19
|
-
|
19
|
+
o = objs[x]
|
20
|
+
next_o = o.next.result
|
21
|
+
puts ("next_o: #{next_o}")
|
22
|
+
actual = $console.object(:object_id=>next_o)
|
20
23
|
assert_equal expected.int_id, actual.int_id
|
21
24
|
end
|
22
25
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spqr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- William Benton
|
@@ -101,5 +101,7 @@ test_files:
|
|
101
101
|
- test/test_spqr_integerprop.rb
|
102
102
|
- test/test_rhubarb.rb
|
103
103
|
- test/test_spqr_hello.rb
|
104
|
+
- examples/agent-app.rb
|
105
|
+
- examples/examples/codegen/EchoAgent.rb
|
104
106
|
- examples/hello.rb
|
105
107
|
- examples/logservice.rb
|