ruby-dbus 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/NEWS +16 -0
- data/README +1 -1
- data/Rakefile +20 -10
- data/VERSION +1 -1
- data/lib/dbus/auth.rb +11 -5
- data/lib/dbus/bus.rb +57 -27
- data/lib/dbus/export.rb +9 -6
- data/lib/dbus/introspect.rb +24 -42
- data/lib/dbus/marshall.rb +20 -19
- data/lib/dbus/matchrule.rb +2 -1
- data/lib/dbus/message.rb +1 -1
- data/ruby-dbus.gemspec +2 -0
- data/test/binding_test.rb +1 -1
- data/test/bus_driver_test.rb +1 -1
- data/test/bus_test.rb +18 -0
- data/test/property_test.rb +1 -1
- data/test/server_robustness_test.rb +3 -3
- data/test/server_test.rb +1 -1
- data/test/service_newapi.rb +9 -1
- data/test/session_bus_test_manual.rb +1 -1
- data/test/signal_test.rb +1 -1
- data/test/t2.rb +7 -1
- data/test/t3-ticket27.rb +1 -1
- data/test/t5-report-dbus-interface.rb +1 -1
- data/test/t6-loop.rb +1 -1
- data/test/thread_safety_test.rb +35 -0
- data/test/variant_test.rb +1 -1
- metadata +15 -13
- data/doc/tutorial/index.html +0 -365
- data/examples/no-introspect/call-overloaded.rb +0 -22
data/NEWS
CHANGED
@@ -5,6 +5,22 @@ Note about bug numbers:
|
|
5
5
|
Issue#1 - http://github.com/mvidner/ruby-dbus/issues#issue/1
|
6
6
|
bnc#1 - https://bugzilla.novell.com/show_bug.cgi?id=1
|
7
7
|
|
8
|
+
== Ruby D-Bus 0.7.0 - 2011-07-26
|
9
|
+
|
10
|
+
Features:
|
11
|
+
* Added ASystemBus and ASessionBus, non-singletons useful in tests
|
12
|
+
and threads.
|
13
|
+
|
14
|
+
Bug fixes:
|
15
|
+
* Fixed handling of multibyte strings (Issue#8, by Takayuki YAMAGUCHI).
|
16
|
+
* Allow reopening of a dbus_interface declaration (Issue#9, by T. YAMAGUCHI).
|
17
|
+
* Fixed ruby-1.9.2 compatibility again (Issue#12).
|
18
|
+
* Fixed authentication on BSD (Issue#11, by Jonathan Walker)
|
19
|
+
* Fixed exiting a nested event loop for synchronous calls
|
20
|
+
(reported by Timo Warns).
|
21
|
+
* Fixed introspection calls leaking reply handlers.
|
22
|
+
* "rake test" now works, doing what was called "rake env:test"
|
23
|
+
|
8
24
|
== Ruby D-Bus 0.6.0 - 2010-12-11
|
9
25
|
|
10
26
|
Features:
|
data/README
CHANGED
data/Rakefile
CHANGED
@@ -3,33 +3,32 @@ require 'rake'
|
|
3
3
|
require 'rake/gempackagetask'
|
4
4
|
require 'fileutils'
|
5
5
|
include FileUtils
|
6
|
+
require 'tmpdir'
|
6
7
|
require 'rake/rdoctask'
|
7
8
|
require 'rake/testtask'
|
8
9
|
|
9
10
|
desc 'Default: run tests in the proper environment'
|
10
|
-
task :default =>
|
11
|
+
task :default => :test
|
11
12
|
|
12
13
|
def common_test_task(t)
|
13
14
|
t.libs << "lib"
|
14
|
-
t.test_files = FileList['test/*_test.rb', 'test/t*.rb']
|
15
|
+
t.test_files = FileList['test/*_test.rb', 'test/t[0-9]*.rb']
|
15
16
|
t.verbose = true
|
16
17
|
end
|
17
|
-
Rake::TestTask.new {|t| common_test_task t }
|
18
|
+
Rake::TestTask.new("bare:test") {|t| common_test_task t }
|
18
19
|
|
19
20
|
begin
|
20
21
|
require 'rcov/rcovtask'
|
21
|
-
Rcov::RcovTask.new {|t| common_test_task t }
|
22
|
+
Rcov::RcovTask.new("bare:rcov") {|t| common_test_task t }
|
22
23
|
rescue LoadError
|
23
24
|
# no rcov, never mind
|
24
25
|
end
|
25
26
|
|
26
27
|
%w(test rcov).each do |tname|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
system "./test_env rake #{tname}"
|
32
|
-
end
|
28
|
+
desc "Run bare:#{tname} in the proper environment"
|
29
|
+
task tname do |t|
|
30
|
+
cd "test" do
|
31
|
+
system "./test_env rake bare:#{tname}"
|
33
32
|
end
|
34
33
|
end
|
35
34
|
end
|
@@ -40,6 +39,17 @@ Rake::GemPackageTask.new(GEMSPEC) do |pkg|
|
|
40
39
|
# no other formats needed
|
41
40
|
end
|
42
41
|
|
42
|
+
desc "Build a package from a clone of the local Git repo"
|
43
|
+
task :package_git do |t|
|
44
|
+
Dir.mktmpdir do |temp|
|
45
|
+
sh "git clone . #{temp}"
|
46
|
+
cd temp do
|
47
|
+
sh "rake package"
|
48
|
+
end
|
49
|
+
cp_r "#{temp}/pkg", "."
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
43
53
|
Rake::RDocTask.new do |rd|
|
44
54
|
rd.rdoc_dir = 'doc/rdoc'
|
45
55
|
rd.rdoc_files.include("README", "lib/**/*.rb")
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.7.0
|
data/lib/dbus/auth.rb
CHANGED
@@ -8,6 +8,8 @@
|
|
8
8
|
|
9
9
|
$debug = $DEBUG #it's all over the state machine
|
10
10
|
|
11
|
+
require 'rbconfig'
|
12
|
+
|
11
13
|
module DBus
|
12
14
|
# Exception raised when authentication fails somehow.
|
13
15
|
class AuthenticationFailed < Exception
|
@@ -62,7 +64,7 @@ module DBus
|
|
62
64
|
# name of cookie file, id of cookie in file, servers random challenge
|
63
65
|
context, id, s_challenge = data.split(' ')
|
64
66
|
# Random client challenge
|
65
|
-
c_challenge = Array.new(s_challenge.
|
67
|
+
c_challenge = Array.new(s_challenge.bytesize/2).map{|obj|obj=rand(255).to_s}.join
|
66
68
|
# Search cookie file for id
|
67
69
|
path = File.join(ENV['HOME'], '.dbus-keyrings', context)
|
68
70
|
puts "DEBUG: path: #{path.inspect}" if $debug
|
@@ -118,7 +120,11 @@ module DBus
|
|
118
120
|
|
119
121
|
# Start the authentication process.
|
120
122
|
def authenticate
|
121
|
-
|
123
|
+
if (RbConfig::CONFIG["target_os"] =~ /bsd/)
|
124
|
+
@socket.sendmsg(0.chr, 0, nil, [:SOCKET, :SCM_CREDS, ""])
|
125
|
+
else
|
126
|
+
@socket.write(0.chr)
|
127
|
+
end
|
122
128
|
next_authenticator
|
123
129
|
@state = :Starting
|
124
130
|
while @state != :Authenticated
|
@@ -142,12 +148,12 @@ module DBus
|
|
142
148
|
# Try authentication using the next authenticator.
|
143
149
|
def next_authenticator
|
144
150
|
begin
|
145
|
-
raise
|
151
|
+
raise AuthenticationFailed if @auth_list.size == 0
|
146
152
|
@authenticator = @auth_list.shift.new
|
147
153
|
auth_msg = ["AUTH", @authenticator.name, @authenticator.authenticate]
|
148
154
|
puts "DEBUG: auth_msg: #{auth_msg.inspect}" if $debug
|
149
155
|
send(auth_msg)
|
150
|
-
rescue
|
156
|
+
rescue AuthenticationFailed
|
151
157
|
@socket.close
|
152
158
|
raise
|
153
159
|
end
|
@@ -161,7 +167,7 @@ module DBus
|
|
161
167
|
while left > 0
|
162
168
|
buf = @socket.read( left > 1 ? 1 : left )
|
163
169
|
break if buf.nil?
|
164
|
-
left -= buf.
|
170
|
+
left -= buf.bytesize
|
165
171
|
data += buf
|
166
172
|
break if data.include? crlf #crlf means line finished, the TCP socket keeps on listening, so we break
|
167
173
|
end
|
data/lib/dbus/bus.rb
CHANGED
@@ -140,6 +140,7 @@ module DBus
|
|
140
140
|
end
|
141
141
|
|
142
142
|
# Return an XML string representation of the node.
|
143
|
+
# It is shallow, not recursing into subnodes
|
143
144
|
def to_xml
|
144
145
|
xml = '<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
|
145
146
|
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
@@ -383,33 +384,52 @@ module DBus
|
|
383
384
|
'
|
384
385
|
# This apostroph is for syntax highlighting editors confused by above xml: "
|
385
386
|
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
send_sync(
|
387
|
+
# Send a _message_.
|
388
|
+
# If _reply_handler_ is not given, wait for the reply
|
389
|
+
# and return the reply, or raise the error.
|
390
|
+
# If _reply_handler_ is given, it will be called when the reply
|
391
|
+
# eventually arrives, with the reply message as the 1st param
|
392
|
+
# and its params following
|
393
|
+
def send_sync_or_async(message, &reply_handler)
|
394
|
+
ret = nil
|
395
|
+
if reply_handler.nil?
|
396
|
+
send_sync(message) do |rmsg|
|
396
397
|
if rmsg.is_a?(Error)
|
397
398
|
raise rmsg
|
398
399
|
else
|
399
|
-
|
400
|
+
ret = rmsg.params
|
400
401
|
end
|
401
402
|
end
|
402
403
|
else
|
403
|
-
|
404
|
-
on_return(m) do |rmsg|
|
404
|
+
on_return(message) do |rmsg|
|
405
405
|
if rmsg.is_a?(Error)
|
406
|
-
|
406
|
+
reply_handler.call(rmsg)
|
407
407
|
else
|
408
|
-
|
408
|
+
reply_handler.call(rmsg, * rmsg.params)
|
409
409
|
end
|
410
410
|
end
|
411
|
+
send(message.marshall)
|
412
|
+
end
|
413
|
+
ret
|
414
|
+
end
|
415
|
+
|
416
|
+
def introspect_data(dest, path, &reply_handler)
|
417
|
+
m = DBus::Message.new(DBus::Message::METHOD_CALL)
|
418
|
+
m.path = path
|
419
|
+
m.interface = "org.freedesktop.DBus.Introspectable"
|
420
|
+
m.destination = dest
|
421
|
+
m.member = "Introspect"
|
422
|
+
m.sender = unique_name
|
423
|
+
if reply_handler.nil?
|
424
|
+
send_sync_or_async(m).first
|
425
|
+
else
|
426
|
+
send_sync_or_async(m) do |*args|
|
427
|
+
# TODO test async introspection, is it used at all?
|
428
|
+
args.shift # forget the message, pass only the text
|
429
|
+
reply_handler.call(*args)
|
430
|
+
nil
|
431
|
+
end
|
411
432
|
end
|
412
|
-
nil
|
413
433
|
end
|
414
434
|
|
415
435
|
# Issues a call to the org.freedesktop.DBus.Introspectable.Introspect method
|
@@ -549,9 +569,7 @@ module DBus
|
|
549
569
|
return if retm.nil? #check if somethings wrong
|
550
570
|
|
551
571
|
process(retm)
|
552
|
-
|
553
|
-
DBus::Message::METHOD_RETURN].include?(retm.message_type) and
|
554
|
-
retm.reply_serial == m.serial
|
572
|
+
while @method_call_replies.has_key? m.serial
|
555
573
|
retm = wait_for_message
|
556
574
|
process(retm)
|
557
575
|
end
|
@@ -695,10 +713,10 @@ module DBus
|
|
695
713
|
# = D-Bus session bus class
|
696
714
|
#
|
697
715
|
# The session bus is a session specific bus (mostly for desktop use).
|
698
|
-
#
|
699
|
-
|
700
|
-
|
701
|
-
|
716
|
+
#
|
717
|
+
# Use SessionBus, the non-singleton ASessionBus is
|
718
|
+
# for the test suite.
|
719
|
+
class ASessionBus < Connection
|
702
720
|
# Get the the default session bus.
|
703
721
|
def initialize
|
704
722
|
super(ENV["DBUS_SESSION_BUS_ADDRESS"] || address_from_file)
|
@@ -719,13 +737,20 @@ module DBus
|
|
719
737
|
end
|
720
738
|
end
|
721
739
|
|
740
|
+
# See ASessionBus
|
741
|
+
class SessionBus < ASessionBus
|
742
|
+
include Singleton
|
743
|
+
end
|
744
|
+
|
745
|
+
|
722
746
|
# = D-Bus system bus class
|
723
747
|
#
|
724
748
|
# The system bus is a system-wide bus mostly used for global or
|
725
|
-
# system usages.
|
726
|
-
|
727
|
-
|
728
|
-
|
749
|
+
# system usages.
|
750
|
+
#
|
751
|
+
# Use SystemBus, the non-singleton ASystemBus is
|
752
|
+
# for the test suite.
|
753
|
+
class ASystemBus < Connection
|
729
754
|
# Get the default system bus.
|
730
755
|
def initialize
|
731
756
|
super(SystemSocketName)
|
@@ -755,6 +780,11 @@ module DBus
|
|
755
780
|
end
|
756
781
|
end
|
757
782
|
|
783
|
+
# See ASystemBus
|
784
|
+
class SystemBus < ASystemBus
|
785
|
+
include Singleton
|
786
|
+
end
|
787
|
+
|
758
788
|
# Shortcut for the SystemBus instance
|
759
789
|
def DBus.system_bus
|
760
790
|
SystemBus.instance
|
data/lib/dbus/export.rb
CHANGED
@@ -15,19 +15,20 @@ module DBus
|
|
15
15
|
# = Exportable D-Bus object class
|
16
16
|
#
|
17
17
|
# Objects that are going to be exported by a D-Bus service
|
18
|
-
# should inherit from this class.
|
18
|
+
# should inherit from this class. At the client side, use ProxyObject.
|
19
19
|
class Object
|
20
20
|
# The path of the object.
|
21
21
|
attr_reader :path
|
22
|
-
# The interfaces that the object supports.
|
22
|
+
# The interfaces that the object supports. Hash: String => Interface
|
23
23
|
class_attribute :intfs
|
24
24
|
# The service that the object is exported by.
|
25
25
|
attr_writer :service
|
26
26
|
|
27
|
-
@@cur_intf = nil
|
27
|
+
@@cur_intf = nil # Interface
|
28
28
|
@@intfs_mutex = Mutex.new
|
29
29
|
|
30
30
|
# Create a new object with a given _path_.
|
31
|
+
# Use Service#export to export it.
|
31
32
|
def initialize(path)
|
32
33
|
@path = path
|
33
34
|
@service = nil
|
@@ -39,7 +40,7 @@ module DBus
|
|
39
40
|
self.intfs = (self.intfs || {}).merge({intf.name => intf})
|
40
41
|
end
|
41
42
|
|
42
|
-
# Dispatch a message _msg_
|
43
|
+
# Dispatch a message _msg_ to call exported methods
|
43
44
|
def dispatch(msg)
|
44
45
|
case msg.message_type
|
45
46
|
when Message::METHOD_CALL
|
@@ -73,8 +74,10 @@ module DBus
|
|
73
74
|
# belong to.
|
74
75
|
def self.dbus_interface(s)
|
75
76
|
@@intfs_mutex.synchronize do
|
76
|
-
@@cur_intf =
|
77
|
-
|
77
|
+
unless @@cur_intf = (self.intfs && self.intfs[s])
|
78
|
+
@@cur_intf = Interface.new(s)
|
79
|
+
self.intfs = (self.intfs || {}).merge({s => @@cur_intf})
|
80
|
+
end
|
78
81
|
yield
|
79
82
|
@@cur_intf = nil
|
80
83
|
end
|
data/lib/dbus/introspect.rb
CHANGED
@@ -8,6 +8,7 @@
|
|
8
8
|
# License, version 2.1 as published by the Free Software Foundation.
|
9
9
|
# See the file "COPYING" for the exact licensing terms.
|
10
10
|
|
11
|
+
# TODO check if it is slow, make replaceable
|
11
12
|
require 'rexml/document'
|
12
13
|
|
13
14
|
module DBus
|
@@ -27,15 +28,16 @@ module DBus
|
|
27
28
|
# = D-Bus interface class
|
28
29
|
#
|
29
30
|
# This class is the interface descriptor. In most cases, the Introspect()
|
30
|
-
# method call
|
31
|
+
# method call instantiates and configures this class for us.
|
31
32
|
#
|
32
33
|
# It also is the local definition of interface exported by the program.
|
34
|
+
# At the client side, see ProxyObjectInterface
|
33
35
|
class Interface
|
34
|
-
# The name of the interface.
|
36
|
+
# The name of the interface. String
|
35
37
|
attr_reader :name
|
36
|
-
# The methods that are part of the interface.
|
38
|
+
# The methods that are part of the interface. Hash: Symbol => DBus::Method
|
37
39
|
attr_reader :methods
|
38
|
-
# The signals that are part of the interface.
|
40
|
+
# The signals that are part of the interface. Hash: Symbol => Signal
|
39
41
|
attr_reader :signals
|
40
42
|
|
41
43
|
# Creates a new interface with a given _name_.
|
@@ -47,7 +49,7 @@ module DBus
|
|
47
49
|
|
48
50
|
# Validates a service _name_.
|
49
51
|
def validate_name(name)
|
50
|
-
raise InvalidIntrospectionData if name.
|
52
|
+
raise InvalidIntrospectionData if name.bytesize > 255
|
51
53
|
raise InvalidIntrospectionData if name =~ /^\./ or name =~ /\.$/
|
52
54
|
raise InvalidIntrospectionData if name =~ /\.\./
|
53
55
|
raise InvalidIntrospectionData if not name =~ /\./
|
@@ -100,14 +102,14 @@ module DBus
|
|
100
102
|
# This is a generic class for entities that are part of the interface
|
101
103
|
# such as methods and signals.
|
102
104
|
class InterfaceElement
|
103
|
-
# The name of the interface element.
|
105
|
+
# The name of the interface element. Symbol
|
104
106
|
attr_reader :name
|
105
|
-
# The parameters of the interface element
|
107
|
+
# The parameters of the interface element. Array: FormalParameter
|
106
108
|
attr_reader :params
|
107
109
|
|
108
110
|
# Validates element _name_.
|
109
111
|
def validate_name(name)
|
110
|
-
if (not name =~ MethodSignalRE) or (name.
|
112
|
+
if (not name =~ MethodSignalRE) or (name.bytesize > 255)
|
111
113
|
raise InvalidMethodName, name
|
112
114
|
end
|
113
115
|
end
|
@@ -135,7 +137,7 @@ module DBus
|
|
135
137
|
#
|
136
138
|
# This is a class representing methods that are part of an interface.
|
137
139
|
class Method < InterfaceElement
|
138
|
-
# The list of return values for the method.
|
140
|
+
# The list of return values for the method. Array: FormalParameter
|
139
141
|
attr_reader :rets
|
140
142
|
|
141
143
|
# Creates a new method interface element with the given _name_.
|
@@ -227,10 +229,9 @@ module DBus
|
|
227
229
|
@xml = xml
|
228
230
|
end
|
229
231
|
|
230
|
-
#
|
232
|
+
# return the names of direct subnodes
|
231
233
|
def parse_subnodes
|
232
234
|
subnodes = Array.new
|
233
|
-
t = Time.now
|
234
235
|
d = REXML::Document.new(@xml)
|
235
236
|
d.elements.each("node/node") do |e|
|
236
237
|
subnodes << e.attributes["name"]
|
@@ -238,9 +239,9 @@ module DBus
|
|
238
239
|
subnodes
|
239
240
|
end
|
240
241
|
|
241
|
-
#
|
242
|
+
# return a pair: [list of Interfaces, list of direct subnode names]
|
242
243
|
def parse
|
243
|
-
|
244
|
+
interfaces = Array.new
|
244
245
|
subnodes = Array.new
|
245
246
|
t = Time.now
|
246
247
|
d = REXML::Document.new(@xml)
|
@@ -259,13 +260,13 @@ module DBus
|
|
259
260
|
parse_methsig(se, s)
|
260
261
|
i << s
|
261
262
|
end
|
262
|
-
|
263
|
+
interfaces << i
|
263
264
|
end
|
264
265
|
d = Time.now - t
|
265
266
|
if d > 2
|
266
267
|
puts "Some XML took more that two secs to parse. Optimize me!" if $DEBUG
|
267
268
|
end
|
268
|
-
[
|
269
|
+
[interfaces, subnodes]
|
269
270
|
end
|
270
271
|
|
271
272
|
######################################################################
|
@@ -342,7 +343,7 @@ module DBus
|
|
342
343
|
methdef = "def #{m.name}("
|
343
344
|
methdef += (0..(m.params.size - 1)).to_a.collect { |n|
|
344
345
|
"arg#{n}"
|
345
|
-
}.join(", ")
|
346
|
+
}.push("&reply_handler").join(", ")
|
346
347
|
methdef += %{)
|
347
348
|
msg = Message.new(Message::METHOD_CALL)
|
348
349
|
msg.path = @object.path
|
@@ -365,26 +366,7 @@ module DBus
|
|
365
366
|
idx += 1
|
366
367
|
end
|
367
368
|
methdef += "
|
368
|
-
|
369
|
-
if block_given?
|
370
|
-
@object.bus.on_return(msg) do |rmsg|
|
371
|
-
if rmsg.is_a?(Error)
|
372
|
-
yield(rmsg)
|
373
|
-
else
|
374
|
-
yield(rmsg, *rmsg.params)
|
375
|
-
end
|
376
|
-
end
|
377
|
-
@object.bus.send(msg.marshall)
|
378
|
-
else
|
379
|
-
@object.bus.send_sync(msg) do |rmsg|
|
380
|
-
if rmsg.is_a?(Error)
|
381
|
-
raise rmsg
|
382
|
-
else
|
383
|
-
ret = rmsg.params
|
384
|
-
end
|
385
|
-
end
|
386
|
-
end
|
387
|
-
ret
|
369
|
+
@object.bus.send_sync_or_async(msg, &reply_handler)
|
388
370
|
end
|
389
371
|
"
|
390
372
|
singleton_class.class_eval(methdef)
|
@@ -448,7 +430,7 @@ module DBus
|
|
448
430
|
# over the bus so that the method is executed remotely on the correctponding
|
449
431
|
# object.
|
450
432
|
class ProxyObject
|
451
|
-
# The subnodes of the object in the tree.
|
433
|
+
# The names of direct subnodes of the object in the tree.
|
452
434
|
attr_accessor :subnodes
|
453
435
|
# Flag determining whether the object has been introspected.
|
454
436
|
attr_accessor :introspected
|
@@ -458,7 +440,7 @@ module DBus
|
|
458
440
|
attr_reader :path
|
459
441
|
# The bus the object is reachable via.
|
460
442
|
attr_reader :bus
|
461
|
-
# The default interface of the object.
|
443
|
+
# The default interface of the object, as String.
|
462
444
|
attr_accessor :default_iface
|
463
445
|
|
464
446
|
# Creates a new proxy object living on the given _bus_ at destination _dest_
|
@@ -495,11 +477,12 @@ module DBus
|
|
495
477
|
|
496
478
|
# Returns whether the object has an interface with the given _name_.
|
497
479
|
def has_iface?(name)
|
498
|
-
raise "Cannot call has_iface?
|
480
|
+
raise "Cannot call has_iface? if not introspected" if not @introspected
|
499
481
|
@interfaces.member?(name)
|
500
482
|
end
|
501
483
|
|
502
484
|
# Registers a handler, the code block, for a signal with the given _name_.
|
485
|
+
# It uses _default_iface_ which must have been set.
|
503
486
|
def on_signal(name, &block)
|
504
487
|
if @default_iface and has_iface?(@default_iface)
|
505
488
|
@interfaces[@default_iface].on_signal(@bus, name, &block)
|
@@ -521,10 +504,9 @@ module DBus
|
|
521
504
|
rescue NameError => e
|
522
505
|
# interesting, foo.method("unknown")
|
523
506
|
# raises NameError, not NoMethodError
|
524
|
-
|
525
|
-
raise unless match and match[2] == "DBus::ProxyObjectInterface"
|
507
|
+
raise unless e.to_s =~ /undefined method `#{name}'/
|
526
508
|
# BTW e.exception("...") would preserve the class.
|
527
|
-
raise NoMethodError,"undefined method `#{
|
509
|
+
raise NoMethodError,"undefined method `#{name}' for DBus interface `#{@default_iface}' on object `#{@path}'"
|
528
510
|
end
|
529
511
|
else
|
530
512
|
# TODO distinguish:
|