ruby-dbus 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/NEWS.md +344 -0
- data/Rakefile +21 -15
- data/VERSION +1 -1
- data/doc/Reference.md +26 -37
- data/examples/doc/_extract_examples +4 -4
- data/examples/gdbus/gdbus +40 -39
- data/examples/no-introspect/nm-test.rb +1 -3
- data/examples/no-introspect/tracker-test.rb +2 -4
- data/examples/rhythmbox/playpause.rb +1 -2
- data/examples/service/call_service.rb +0 -3
- data/examples/service/service_newapi.rb +3 -4
- data/examples/simple/call_introspect.rb +0 -3
- data/examples/simple/get_id.rb +1 -3
- data/examples/simple/properties.rb +3 -4
- data/examples/utils/listnames.rb +6 -7
- data/examples/utils/notify.rb +3 -5
- data/lib/dbus.rb +8 -20
- data/lib/dbus/auth.rb +59 -61
- data/lib/dbus/bus.rb +86 -97
- data/lib/dbus/error.rb +1 -1
- data/lib/dbus/export.rb +20 -18
- data/lib/dbus/introspect.rb +26 -28
- data/lib/dbus/logger.rb +1 -1
- data/lib/dbus/marshall.rb +72 -74
- data/lib/dbus/matchrule.rb +22 -26
- data/lib/dbus/message.rb +24 -33
- data/lib/dbus/message_queue.rb +30 -30
- data/lib/dbus/proxy_object.rb +34 -30
- data/lib/dbus/proxy_object_factory.rb +5 -2
- data/lib/dbus/proxy_object_interface.rb +10 -8
- data/lib/dbus/type.rb +154 -156
- data/lib/dbus/xml.rb +22 -16
- data/ruby-dbus.gemspec +15 -3
- data/spec/async_spec.rb +2 -4
- data/spec/binding_spec.rb +1 -5
- data/spec/bus_and_xml_backend_spec.rb +6 -9
- data/spec/bus_spec.rb +1 -1
- data/spec/byte_array_spec.rb +0 -2
- data/spec/err_msg_spec.rb +13 -10
- data/spec/introspect_xml_parser_spec.rb +2 -2
- data/spec/introspection_spec.rb +1 -1
- data/spec/main_loop_spec.rb +4 -5
- data/spec/property_spec.rb +0 -3
- data/spec/proxy_object_spec.rb +42 -0
- data/spec/server_robustness_spec.rb +0 -2
- data/spec/service_newapi.rb +51 -41
- data/spec/session_bus_spec.rb +6 -7
- data/spec/signal_spec.rb +2 -3
- data/spec/spec_helper.rb +28 -24
- data/spec/thread_safety_spec.rb +1 -2
- data/spec/type_spec.rb +2 -2
- data/spec/value_spec.rb +7 -10
- data/spec/variant_spec.rb +15 -16
- metadata +60 -3
- data/NEWS +0 -279
data/lib/dbus/matchrule.rb
CHANGED
@@ -16,7 +16,7 @@ module DBus
|
|
16
16
|
# FIXME
|
17
17
|
class MatchRule
|
18
18
|
# The list of possible match filters. TODO argN, argNpath
|
19
|
-
FILTERS = [:sender, :interface, :member, :path, :destination, :type]
|
19
|
+
FILTERS = [:sender, :interface, :member, :path, :destination, :type].freeze
|
20
20
|
# The sender filter.
|
21
21
|
attr_accessor :sender
|
22
22
|
# The interface filter.
|
@@ -38,35 +38,31 @@ module DBus
|
|
38
38
|
# Set the message types to filter to type _t_.
|
39
39
|
# Possible message types are: signal, method_call, method_return, and error.
|
40
40
|
def type=(t)
|
41
|
-
if
|
41
|
+
if !["signal", "method_call", "method_return", "error"].member?(t)
|
42
42
|
raise MatchRuleException, t
|
43
43
|
end
|
44
44
|
@type = t
|
45
45
|
end
|
46
46
|
|
47
|
-
# Returns a match rule string version of the object.
|
48
|
-
#
|
47
|
+
# Returns a match rule string version of the object. E.g.:
|
48
|
+
# "type='signal',sender='org.freedesktop.DBus'," +
|
49
|
+
# "interface='org.freedesktop.DBus',member='Foo'," +
|
50
|
+
# "path='/bar/foo',destination=':452345.34',arg2='bar'"
|
49
51
|
def to_s
|
50
|
-
FILTERS.select
|
51
|
-
|
52
|
-
|
53
|
-
"#{sym.to_s}='#{method(sym).call}'"
|
54
|
-
end.join(",")
|
52
|
+
present_rules = FILTERS.select { |sym| method(sym).call }
|
53
|
+
present_rules.map! { |sym| "#{sym}='#{method(sym).call}'" }
|
54
|
+
present_rules.join(",")
|
55
55
|
end
|
56
56
|
|
57
57
|
# Parses a match rule string _s_ and sets the filters on the object.
|
58
58
|
def from_s(str)
|
59
59
|
str.split(",").each do |eq|
|
60
|
-
|
61
|
-
# "
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
else
|
67
|
-
raise MatchRuleException, name
|
68
|
-
end
|
69
|
-
end
|
60
|
+
next unless eq =~ /^(.*)='([^']*)'$/
|
61
|
+
# "
|
62
|
+
name = Regexp.last_match(1)
|
63
|
+
val = Regexp.last_match(2)
|
64
|
+
raise MatchRuleException, name unless FILTERS.member?(name.to_sym)
|
65
|
+
method(name + "=").call(val)
|
70
66
|
end
|
71
67
|
self
|
72
68
|
end
|
@@ -85,16 +81,16 @@ module DBus
|
|
85
81
|
# Determines whether a message _msg_ matches the match rule.
|
86
82
|
def match(msg)
|
87
83
|
if @type
|
88
|
-
if {Message::SIGNAL => "signal", Message::METHOD_CALL => "method_call",
|
89
|
-
|
90
|
-
|
84
|
+
if { Message::SIGNAL => "signal", Message::METHOD_CALL => "method_call",
|
85
|
+
Message::METHOD_RETURN => "method_return",
|
86
|
+
Message::ERROR => "error" }[msg.message_type] != @type
|
91
87
|
return false
|
92
88
|
end
|
93
89
|
end
|
94
|
-
return false if @interface
|
95
|
-
return false if @member
|
96
|
-
return false if @path
|
97
|
-
# FIXME sender and destination are ignored
|
90
|
+
return false if @interface && @interface != msg.interface
|
91
|
+
return false if @member && @member != msg.member
|
92
|
+
return false if @path && @path != msg.path
|
93
|
+
# FIXME: sender and destination are ignored
|
98
94
|
true
|
99
95
|
end
|
100
96
|
end # class MatchRule
|
data/lib/dbus/message.rb
CHANGED
@@ -27,7 +27,7 @@ module DBus
|
|
27
27
|
# Mutex that protects updates on the serial number.
|
28
28
|
@@serial_mutex = Mutex.new
|
29
29
|
# Type of a message (by specification).
|
30
|
-
MESSAGE_SIGNATURE = "yyyyuua(yv)"
|
30
|
+
MESSAGE_SIGNATURE = "yyyyuua(yv)".freeze
|
31
31
|
|
32
32
|
# FIXME: following message type constants should be under Message::Type IMO
|
33
33
|
# well, yeah sure
|
@@ -45,7 +45,7 @@ module DBus
|
|
45
45
|
|
46
46
|
# Message flag signyfing that no reply is expected.
|
47
47
|
NO_REPLY_EXPECTED = 0x1
|
48
|
-
# Message flag signifying that no automatic start is required/must be
|
48
|
+
# Message flag signifying that no automatic start is required/must be
|
49
49
|
# performed.
|
50
50
|
NO_AUTO_START = 0x2
|
51
51
|
|
@@ -83,26 +83,26 @@ module DBus
|
|
83
83
|
@flags = 0
|
84
84
|
@protocol = 1
|
85
85
|
@body_length = 0
|
86
|
-
@signature =
|
86
|
+
@signature = ""
|
87
87
|
@@serial_mutex.synchronize do
|
88
88
|
@serial = @@serial
|
89
89
|
@@serial += 1
|
90
90
|
end
|
91
|
-
@params =
|
91
|
+
@params = []
|
92
92
|
@destination = nil
|
93
93
|
@interface = nil
|
94
94
|
@error_name = nil
|
95
95
|
@member = nil
|
96
96
|
@path = nil
|
97
97
|
@reply_serial = nil
|
98
|
-
|
99
|
-
if mtype == METHOD_RETURN
|
100
|
-
@flags = NO_REPLY_EXPECTED
|
101
|
-
end
|
98
|
+
@flags = NO_REPLY_EXPECTED if mtype == METHOD_RETURN
|
102
99
|
end
|
103
100
|
|
104
101
|
def to_s
|
105
|
-
"#{message_type} sender=#{sender} -> dest=#{destination}
|
102
|
+
"#{message_type} sender=#{sender} -> dest=#{destination} " \
|
103
|
+
"serial=#{serial} reply_serial=#{reply_serial} " \
|
104
|
+
"path=#{path}; interface=#{interface}; member=#{member} " \
|
105
|
+
"error_name=#{error_name}"
|
106
106
|
end
|
107
107
|
|
108
108
|
# Create a regular reply to a message _m_.
|
@@ -111,7 +111,7 @@ module DBus
|
|
111
111
|
end
|
112
112
|
|
113
113
|
# Create an error reply to a message _m_.
|
114
|
-
def self.error(m, error_name, description=nil)
|
114
|
+
def self.error(m, error_name, description = nil)
|
115
115
|
ErrorMessage.new(error_name, description).reply_to(m)
|
116
116
|
end
|
117
117
|
|
@@ -126,7 +126,7 @@ module DBus
|
|
126
126
|
|
127
127
|
# Add a parameter _val_ of type _type_ to the message.
|
128
128
|
def add_param(type, val)
|
129
|
-
type = type.chr if type.
|
129
|
+
type = type.chr if type.is_a?(Fixnum)
|
130
130
|
@signature += type.to_s
|
131
131
|
@params << [type, val]
|
132
132
|
end
|
@@ -187,18 +187,19 @@ module DBus
|
|
187
187
|
# Unmarshall a packet contained in the buffer _buf_ and set the
|
188
188
|
# parameters of the message object according the data found in the
|
189
189
|
# buffer.
|
190
|
-
#
|
191
|
-
#
|
190
|
+
# @return [Array(Message,Integer)]
|
191
|
+
# the detected message (self) and
|
192
|
+
# the index pointer of the buffer where the message data ended.
|
192
193
|
def unmarshall_buffer(buf)
|
193
194
|
buf = buf.dup
|
194
|
-
if buf[0] ==
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
195
|
+
endianness = if buf[0] == "l"
|
196
|
+
LIL_END
|
197
|
+
else
|
198
|
+
BIG_END
|
199
|
+
end
|
199
200
|
pu = PacketUnmarshaller.new(buf, endianness)
|
200
201
|
mdata = pu.unmarshall(MESSAGE_SIGNATURE)
|
201
|
-
_, @message_type, @flags, @protocol, @body_length, @serial,
|
202
|
+
_, @message_type, @flags, @protocol, @body_length, @serial,
|
202
203
|
headers = mdata
|
203
204
|
|
204
205
|
headers.each do |struct|
|
@@ -222,18 +223,10 @@ module DBus
|
|
222
223
|
end
|
223
224
|
end
|
224
225
|
pu.align(8)
|
225
|
-
if @body_length > 0
|
226
|
+
if @body_length > 0 && @signature
|
226
227
|
@params = pu.unmarshall(@signature, @body_length)
|
227
228
|
end
|
228
229
|
[self, pu.idx]
|
229
|
-
end # def unmarshall_buf
|
230
|
-
|
231
|
-
# Unmarshall the data of a message found in the buffer _buf_ using
|
232
|
-
# Message#unmarshall_buf.
|
233
|
-
# Return the message.
|
234
|
-
def unmarshall(buf)
|
235
|
-
ret, _ = unmarshall_buffer(buf)
|
236
|
-
ret
|
237
230
|
end
|
238
231
|
|
239
232
|
# Make a new exception from ex, mark it as being caused by this message
|
@@ -252,12 +245,10 @@ module DBus
|
|
252
245
|
end
|
253
246
|
|
254
247
|
class ErrorMessage < Message
|
255
|
-
def initialize(error_name, description=nil)
|
248
|
+
def initialize(error_name, description = nil)
|
256
249
|
super(ERROR)
|
257
250
|
@error_name = error_name
|
258
|
-
unless description.nil?
|
259
|
-
add_param(Type::STRING, description)
|
260
|
-
end
|
251
|
+
add_param(Type::STRING, description) unless description.nil?
|
261
252
|
end
|
262
253
|
|
263
254
|
def self.from_exception(ex)
|
@@ -268,7 +259,7 @@ module DBus
|
|
268
259
|
# ex.class.to_s # RuntimeError is not a valid name, has no dot
|
269
260
|
end
|
270
261
|
description = ex.message
|
271
|
-
msg =
|
262
|
+
msg = new(name, description)
|
272
263
|
msg.add_param(DBus.type("as"), ex.backtrace)
|
273
264
|
msg
|
274
265
|
end
|
data/lib/dbus/message_queue.rb
CHANGED
@@ -22,7 +22,7 @@ module DBus
|
|
22
22
|
connect
|
23
23
|
end
|
24
24
|
|
25
|
-
# TODO failure modes
|
25
|
+
# TODO: failure modes
|
26
26
|
#
|
27
27
|
# If _non_block_ is true, return nil instead of waiting
|
28
28
|
# EOFError may be raised
|
@@ -32,8 +32,8 @@ module DBus
|
|
32
32
|
unless non_block
|
33
33
|
# we can block
|
34
34
|
while message.nil?
|
35
|
-
r,
|
36
|
-
if r
|
35
|
+
r, _d, _d = IO.select([@socket])
|
36
|
+
if r && r[0] == @socket
|
37
37
|
buffer_from_socket_nonblock
|
38
38
|
message = message_from_buffer_nonblock
|
39
39
|
end
|
@@ -45,7 +45,7 @@ module DBus
|
|
45
45
|
def push(message)
|
46
46
|
@socket.write(message.marshall)
|
47
47
|
end
|
48
|
-
alias
|
48
|
+
alias << push
|
49
49
|
|
50
50
|
private
|
51
51
|
|
@@ -56,20 +56,20 @@ module DBus
|
|
56
56
|
worked = addresses.find do |a|
|
57
57
|
transport, keyvaluestring = a.split ":"
|
58
58
|
kv_list = keyvaluestring.split ","
|
59
|
-
kv_hash =
|
59
|
+
kv_hash = {}
|
60
60
|
kv_list.each do |kv|
|
61
61
|
key, escaped_value = kv.split "="
|
62
|
-
value = escaped_value.gsub(/%(..)/) {|
|
62
|
+
value = escaped_value.gsub(/%(..)/) { |_m| [Regexp.last_match(1)].pack "H2" }
|
63
63
|
kv_hash[key] = value
|
64
64
|
end
|
65
65
|
case transport
|
66
|
-
|
66
|
+
when "unix"
|
67
67
|
connect_to_unix kv_hash
|
68
|
-
|
68
|
+
when "tcp"
|
69
69
|
connect_to_tcp kv_hash
|
70
|
-
|
70
|
+
when "launchd"
|
71
71
|
connect_to_launchd kv_hash
|
72
|
-
|
72
|
+
else
|
73
73
|
# ignore, report?
|
74
74
|
end
|
75
75
|
end
|
@@ -80,46 +80,46 @@ module DBus
|
|
80
80
|
|
81
81
|
# Connect to a bus over tcp and initialize the connection.
|
82
82
|
def connect_to_tcp(params)
|
83
|
-
#check if the path is sufficient
|
84
|
-
if params.key?("host")
|
83
|
+
# check if the path is sufficient
|
84
|
+
if params.key?("host") && params.key?("port")
|
85
85
|
begin
|
86
|
-
#initialize the tcp socket
|
87
|
-
@socket = TCPSocket.new(params["host"],params["port"].to_i)
|
86
|
+
# initialize the tcp socket
|
87
|
+
@socket = TCPSocket.new(params["host"], params["port"].to_i)
|
88
88
|
@socket.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
89
89
|
init_connection
|
90
90
|
@is_tcp = true
|
91
91
|
rescue Exception => e
|
92
92
|
puts "Oops:", e
|
93
93
|
puts "Error: Could not establish connection to: #{@path}, will now exit."
|
94
|
-
exit(1) #a little harsh
|
94
|
+
exit(1) # a little harsh
|
95
95
|
end
|
96
96
|
else
|
97
|
-
#Danger, Will Robinson: the specified "path" is not usable
|
97
|
+
# Danger, Will Robinson: the specified "path" is not usable
|
98
98
|
puts "Error: supplied path: #{@path}, unusable! sorry."
|
99
99
|
end
|
100
100
|
end
|
101
101
|
|
102
102
|
# Connect to an abstract unix bus and initialize the connection.
|
103
103
|
def connect_to_unix(params)
|
104
|
-
@socket = Socket.new(Socket::Constants::PF_UNIX,Socket::Constants::SOCK_STREAM, 0)
|
104
|
+
@socket = Socket.new(Socket::Constants::PF_UNIX, Socket::Constants::SOCK_STREAM, 0)
|
105
105
|
@socket.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
106
|
-
if !
|
107
|
-
if HOST_END == LIL_END
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
elsif !
|
113
|
-
sockaddr = Socket.pack_sockaddr_un(params[
|
106
|
+
if !params["abstract"].nil?
|
107
|
+
sockaddr = if HOST_END == LIL_END
|
108
|
+
"\1\0\0#{params["abstract"]}"
|
109
|
+
else
|
110
|
+
"\0\1\0#{params["abstract"]}"
|
111
|
+
end
|
112
|
+
elsif !params["path"].nil?
|
113
|
+
sockaddr = Socket.pack_sockaddr_un(params["path"])
|
114
114
|
end
|
115
115
|
@socket.connect(sockaddr)
|
116
116
|
init_connection
|
117
117
|
end
|
118
118
|
|
119
119
|
def connect_to_launchd(params)
|
120
|
-
socket_var = params[
|
120
|
+
socket_var = params["env"]
|
121
121
|
socket = `launchctl getenv #{socket_var}`.chomp
|
122
|
-
connect_to_unix
|
122
|
+
connect_to_unix "path" => socket
|
123
123
|
end
|
124
124
|
|
125
125
|
# Initialize the connection to the bus.
|
@@ -128,7 +128,7 @@ module DBus
|
|
128
128
|
@client.authenticate
|
129
129
|
end
|
130
130
|
|
131
|
-
public
|
131
|
+
public # FIXME: fix Main loop instead
|
132
132
|
|
133
133
|
# Get and remove one message from the buffer.
|
134
134
|
# Return the message or nil.
|
@@ -153,12 +153,12 @@ module DBus
|
|
153
153
|
def buffer_from_socket_nonblock
|
154
154
|
@buffer += @socket.read_nonblock(MSG_BUF_SIZE)
|
155
155
|
rescue EOFError
|
156
|
-
raise
|
156
|
+
raise # the caller expects it
|
157
157
|
rescue Errno::EAGAIN
|
158
158
|
# fine, would block
|
159
159
|
rescue Exception => e
|
160
160
|
puts "Oops:", e
|
161
|
-
raise if @is_tcp
|
161
|
+
raise if @is_tcp # why?
|
162
162
|
puts "WARNING: read_nonblock failed, falling back to .recv"
|
163
163
|
@buffer += @socket.recv(MSG_BUF_SIZE)
|
164
164
|
end
|
data/lib/dbus/proxy_object.rb
CHANGED
@@ -34,14 +34,18 @@ module DBus
|
|
34
34
|
# Creates a new proxy object living on the given _bus_ at destination _dest_
|
35
35
|
# on the given _path_.
|
36
36
|
def initialize(bus, dest, path, api: ApiOptions::CURRENT)
|
37
|
-
@bus
|
38
|
-
@
|
39
|
-
@
|
37
|
+
@bus = bus
|
38
|
+
@destination = dest
|
39
|
+
@path = path
|
40
|
+
@introspected = false
|
41
|
+
@interfaces = {}
|
42
|
+
@subnodes = []
|
40
43
|
@api = api
|
41
44
|
end
|
42
45
|
|
43
46
|
# Returns the interfaces of the object.
|
44
47
|
def interfaces
|
48
|
+
introspect unless introspected
|
45
49
|
@interfaces.keys
|
46
50
|
end
|
47
51
|
|
@@ -49,6 +53,7 @@ module DBus
|
|
49
53
|
# @param [String] intfname
|
50
54
|
# @return [ProxyObjectInterface]
|
51
55
|
def [](intfname)
|
56
|
+
introspect unless introspected
|
52
57
|
@interfaces[intfname]
|
53
58
|
end
|
54
59
|
|
@@ -56,6 +61,7 @@ module DBus
|
|
56
61
|
# @param [String] intfname
|
57
62
|
# @param [ProxyObjectInterface] intf
|
58
63
|
# @return [ProxyObjectInterface]
|
64
|
+
# @api private
|
59
65
|
def []=(intfname, intf)
|
60
66
|
@interfaces[intfname] = intf
|
61
67
|
end
|
@@ -66,7 +72,7 @@ module DBus
|
|
66
72
|
# Synchronous call here.
|
67
73
|
xml = @bus.introspect_data(@destination, @path)
|
68
74
|
ProxyObjectFactory.introspect_into(self, xml)
|
69
|
-
define_shortcut_methods
|
75
|
+
define_shortcut_methods
|
70
76
|
xml
|
71
77
|
end
|
72
78
|
|
@@ -76,14 +82,15 @@ module DBus
|
|
76
82
|
# introspected.
|
77
83
|
def define_shortcut_methods
|
78
84
|
# builds a list of duplicated methods
|
79
|
-
dup_meths
|
85
|
+
dup_meths = []
|
86
|
+
univocal_meths = {}
|
80
87
|
@interfaces.each_value do |intf|
|
81
88
|
intf.methods.each_value do |meth|
|
82
89
|
name = meth.name.to_sym
|
83
90
|
# don't overwrite instance methods!
|
84
|
-
if dup_meths.include?
|
85
|
-
|
86
|
-
|
91
|
+
next if dup_meths.include?(name)
|
92
|
+
next if self.class.instance_methods.include?(name)
|
93
|
+
if univocal_meths.include? name
|
87
94
|
univocal_meths.delete name
|
88
95
|
dup_meths << name
|
89
96
|
else
|
@@ -95,7 +102,7 @@ module DBus
|
|
95
102
|
# creates a shortcut function that forwards each call to the method on
|
96
103
|
# the appropriate intf
|
97
104
|
singleton_class.class_eval do
|
98
|
-
|
105
|
+
redefine_method name do |*args, &reply_handler|
|
99
106
|
intf.method(name).call(*args, &reply_handler)
|
100
107
|
end
|
101
108
|
end
|
@@ -104,20 +111,17 @@ module DBus
|
|
104
111
|
|
105
112
|
# Returns whether the object has an interface with the given _name_.
|
106
113
|
def has_iface?(name)
|
107
|
-
|
108
|
-
@interfaces.
|
114
|
+
introspect unless introspected
|
115
|
+
@interfaces.key?(name)
|
109
116
|
end
|
110
117
|
|
111
118
|
# Registers a handler, the code block, for a signal with the given _name_.
|
112
119
|
# It uses _default_iface_ which must have been set.
|
113
120
|
# @return [void]
|
114
121
|
def on_signal(name, &block)
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
# TODO improve
|
119
|
-
raise NoMethodError
|
120
|
-
end
|
122
|
+
# TODO: improve
|
123
|
+
raise NoMethodError unless @default_iface && has_iface?(@default_iface)
|
124
|
+
@interfaces[@default_iface].on_signal(name, &block)
|
121
125
|
end
|
122
126
|
|
123
127
|
####################################################
|
@@ -126,23 +130,23 @@ module DBus
|
|
126
130
|
# Handles all unkown methods, mostly to route method calls to the
|
127
131
|
# default interface.
|
128
132
|
def method_missing(name, *args, &reply_handler)
|
129
|
-
|
130
|
-
|
131
|
-
@interfaces[@default_iface].method(name).call(*args, &reply_handler)
|
132
|
-
rescue NameError => e
|
133
|
-
# interesting, foo.method("unknown")
|
134
|
-
# raises NameError, not NoMethodError
|
135
|
-
raise unless e.to_s =~ /undefined method `#{name}'/
|
136
|
-
# BTW e.exception("...") would preserve the class.
|
137
|
-
raise NoMethodError,"undefined method `#{name}' for DBus interface `#{@default_iface}' on object `#{@path}'"
|
138
|
-
end
|
139
|
-
else
|
140
|
-
# TODO distinguish:
|
133
|
+
unless @default_iface && has_iface?(@default_iface)
|
134
|
+
# TODO: distinguish:
|
141
135
|
# - di not specified
|
142
|
-
#TODO
|
136
|
+
# TODO
|
143
137
|
# - di is specified but not found in introspection data
|
144
138
|
raise NoMethodError, "undefined method `#{name}' for DBus interface `#{@default_iface}' on object `#{@path}'"
|
145
139
|
end
|
140
|
+
|
141
|
+
begin
|
142
|
+
@interfaces[@default_iface].method(name).call(*args, &reply_handler)
|
143
|
+
rescue NameError => e
|
144
|
+
# interesting, foo.method("unknown")
|
145
|
+
# raises NameError, not NoMethodError
|
146
|
+
raise unless e.to_s =~ /undefined method `#{name}'/
|
147
|
+
# BTW e.exception("...") would preserve the class.
|
148
|
+
raise NoMethodError, "undefined method `#{name}' for DBus interface `#{@default_iface}' on object `#{@path}'"
|
149
|
+
end
|
146
150
|
end
|
147
151
|
end # class ProxyObject
|
148
152
|
end
|