ruby-dbus 0.17.0 → 0.18.0.beta3

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.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/NEWS.md +38 -0
  3. data/README.md +1 -1
  4. data/Rakefile +3 -11
  5. data/VERSION +1 -1
  6. data/doc/Reference.md +10 -3
  7. data/examples/doc/_extract_examples +2 -0
  8. data/examples/gdbus/gdbus +11 -5
  9. data/examples/no-introspect/nm-test.rb +2 -0
  10. data/examples/no-introspect/tracker-test.rb +3 -1
  11. data/examples/rhythmbox/playpause.rb +2 -1
  12. data/examples/service/call_service.rb +1 -0
  13. data/examples/service/complex-property.rb +21 -0
  14. data/examples/service/service_newapi.rb +1 -1
  15. data/examples/simple/call_introspect.rb +1 -0
  16. data/examples/simple/get_id.rb +2 -1
  17. data/examples/simple/properties.rb +2 -0
  18. data/examples/utils/listnames.rb +1 -0
  19. data/examples/utils/notify.rb +1 -0
  20. data/lib/dbus/api_options.rb +9 -0
  21. data/lib/dbus/auth.rb +12 -7
  22. data/lib/dbus/bus.rb +114 -70
  23. data/lib/dbus/bus_name.rb +12 -8
  24. data/lib/dbus/data.rb +744 -0
  25. data/lib/dbus/error.rb +4 -2
  26. data/lib/dbus/introspect.rb +30 -18
  27. data/lib/dbus/logger.rb +3 -1
  28. data/lib/dbus/marshall.rb +229 -293
  29. data/lib/dbus/matchrule.rb +16 -16
  30. data/lib/dbus/message.rb +44 -37
  31. data/lib/dbus/message_queue.rb +10 -5
  32. data/lib/dbus/object.rb +36 -15
  33. data/lib/dbus/object_path.rb +11 -6
  34. data/lib/dbus/proxy_object.rb +18 -4
  35. data/lib/dbus/proxy_object_factory.rb +11 -7
  36. data/lib/dbus/proxy_object_interface.rb +26 -22
  37. data/lib/dbus/raw_message.rb +91 -0
  38. data/lib/dbus/type.rb +164 -80
  39. data/lib/dbus/xml.rb +28 -17
  40. data/lib/dbus.rb +13 -7
  41. data/ruby-dbus.gemspec +4 -2
  42. data/spec/async_spec.rb +2 -0
  43. data/spec/binding_spec.rb +2 -0
  44. data/spec/bus_and_xml_backend_spec.rb +2 -0
  45. data/spec/bus_driver_spec.rb +2 -0
  46. data/spec/bus_name_spec.rb +3 -1
  47. data/spec/bus_spec.rb +2 -0
  48. data/spec/byte_array_spec.rb +2 -0
  49. data/spec/client_robustness_spec.rb +4 -2
  50. data/spec/data/marshall.yaml +1639 -0
  51. data/spec/data_spec.rb +353 -0
  52. data/spec/err_msg_spec.rb +2 -0
  53. data/spec/introspect_xml_parser_spec.rb +2 -0
  54. data/spec/introspection_spec.rb +2 -0
  55. data/spec/main_loop_spec.rb +2 -0
  56. data/spec/node_spec.rb +23 -0
  57. data/spec/object_path_spec.rb +3 -0
  58. data/spec/packet_marshaller_spec.rb +34 -0
  59. data/spec/packet_unmarshaller_spec.rb +262 -0
  60. data/spec/property_spec.rb +60 -2
  61. data/spec/proxy_object_spec.rb +2 -0
  62. data/spec/server_robustness_spec.rb +2 -0
  63. data/spec/server_spec.rb +2 -0
  64. data/spec/service_newapi.rb +37 -4
  65. data/spec/session_bus_spec.rb +3 -1
  66. data/spec/session_bus_spec_manual.rb +2 -0
  67. data/spec/signal_spec.rb +2 -0
  68. data/spec/spec_helper.rb +19 -3
  69. data/spec/thread_safety_spec.rb +2 -0
  70. data/spec/type_spec.rb +69 -6
  71. data/spec/value_spec.rb +16 -1
  72. data/spec/variant_spec.rb +4 -2
  73. data/spec/zzz_quit_spec.rb +16 -0
  74. metadata +16 -7
data/lib/dbus/message.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # dbus.rb - Module containing the low-level D-Bus implementation
2
4
  #
3
5
  # This file is part of the ruby-dbus project
@@ -27,7 +29,7 @@ module DBus
27
29
  # Mutex that protects updates on the serial number.
28
30
  @@serial_mutex = Mutex.new
29
31
  # Type of a message (by specification).
30
- MESSAGE_SIGNATURE = "yyyyuua(yv)".freeze
32
+ MESSAGE_SIGNATURE = "yyyyuua(yv)"
31
33
 
32
34
  # FIXME: following message type constants should be under Message::Type IMO
33
35
  # well, yeah sure
@@ -43,6 +45,9 @@ module DBus
43
45
  # Signal message type.
44
46
  SIGNAL = 4
45
47
 
48
+ # Names used by signal match rules
49
+ TYPE_NAMES = ["invalid", "method_call", "method_return", "error", "signal"].freeze
50
+
46
51
  # Message flag signyfing that no reply is expected.
47
52
  NO_REPLY_EXPECTED = 0x1
48
53
  # Message flag signifying that no automatic start is required/must be
@@ -66,11 +71,13 @@ module DBus
66
71
  attr_accessor :sender
67
72
  # The signature of the message contents.
68
73
  attr_accessor :signature
69
- # The serial number of the message this message is a reply for.
74
+ # @return [Integer] (u32)
75
+ # The serial number of the message this message is a reply for.
70
76
  attr_accessor :reply_serial
71
77
  # The protocol.
72
78
  attr_reader :protocol
73
- # The serial of the message.
79
+ # @return [Integer] (u32)
80
+ # The serial of the message.
74
81
  attr_reader :serial
75
82
  # The parameters of the message.
76
83
  attr_reader :params
@@ -105,22 +112,28 @@ module DBus
105
112
  "error_name=#{error_name}"
106
113
  end
107
114
 
108
- # Create a regular reply to a message _m_.
109
- def self.method_return(m)
110
- MethodReturnMessage.new.reply_to(m)
115
+ # @return [String] name of message type, as used in match rules:
116
+ # "method_call", "method_return", "signal", "error"
117
+ def message_type_s
118
+ TYPE_NAMES[message_type] || "unknown_type_#{message_type}"
111
119
  end
112
120
 
113
- # Create an error reply to a message _m_.
114
- def self.error(m, error_name, description = nil)
115
- ErrorMessage.new(error_name, description).reply_to(m)
121
+ # Create a regular reply to a message _msg_.
122
+ def self.method_return(msg)
123
+ MethodReturnMessage.new.reply_to(msg)
116
124
  end
117
125
 
118
- # Mark this message as a reply to a another message _m_, taking
119
- # the serial number of _m_ as reply serial and the sender of _m_ as
126
+ # Create an error reply to a message _msg_.
127
+ def self.error(msg, error_name, description = nil)
128
+ ErrorMessage.new(error_name, description).reply_to(msg)
129
+ end
130
+
131
+ # Mark this message as a reply to a another message _msg_, taking
132
+ # the serial number of _msg_ as reply serial and the sender of _msg_ as
120
133
  # destination.
121
- def reply_to(m)
122
- @reply_serial = m.serial
123
- @destination = m.sender
134
+ def reply_to(msg)
135
+ @reply_serial = msg.serial
136
+ @destination = msg.sender
124
137
  self
125
138
  end
126
139
 
@@ -159,7 +172,7 @@ module DBus
159
172
  @body_length = params.packet.bytesize
160
173
 
161
174
  marshaller = PacketMarshaller.new
162
- marshaller.append(Type::BYTE, HOST_END)
175
+ marshaller.append(Type::BYTE, HOST_END.ord)
163
176
  marshaller.append(Type::BYTE, @message_type)
164
177
  marshaller.append(Type::BYTE, @flags)
165
178
  marshaller.append(Type::BYTE, @protocol)
@@ -191,13 +204,7 @@ module DBus
191
204
  # the detected message (self) and
192
205
  # the index pointer of the buffer where the message data ended.
193
206
  def unmarshall_buffer(buf)
194
- buf = buf.dup
195
- endianness = if buf[0] == "l"
196
- LIL_END
197
- else
198
- BIG_END
199
- end
200
- pu = PacketUnmarshaller.new(buf, endianness)
207
+ pu = PacketUnmarshaller.new(buf, RawMessage.endianness(buf[0]))
201
208
  mdata = pu.unmarshall(MESSAGE_SIGNATURE)
202
209
  _, @message_type, @flags, @protocol, @body_length, @serial,
203
210
  headers = mdata
@@ -222,21 +229,21 @@ module DBus
222
229
  @signature = struct[1]
223
230
  end
224
231
  end
225
- pu.align(8)
226
- if @body_length > 0 && @signature
232
+ pu.align_body
233
+ if @body_length.positive? && @signature
227
234
  @params = pu.unmarshall(@signature, @body_length)
228
235
  end
229
- [self, pu.idx]
236
+ [self, pu.consumed_size]
230
237
  end
231
238
 
232
239
  # Make a new exception from ex, mark it as being caused by this message
233
240
  # @api private
234
- def annotate_exception(ex)
235
- new_ex = ex.exception("#{ex}; caused by #{self}")
236
- new_ex.set_backtrace(ex.backtrace)
237
- new_ex
241
+ def annotate_exception(exc)
242
+ new_exc = exc.exception("#{exc}; caused by #{self}")
243
+ new_exc.set_backtrace(exc.backtrace)
244
+ new_exc
238
245
  end
239
- end # class Message
246
+ end
240
247
 
241
248
  class MethodReturnMessage < Message
242
249
  def initialize
@@ -251,17 +258,17 @@ module DBus
251
258
  add_param(Type::STRING, description) unless description.nil?
252
259
  end
253
260
 
254
- def self.from_exception(ex)
255
- name = if ex.is_a? DBus::Error
256
- ex.name
261
+ def self.from_exception(exc)
262
+ name = if exc.is_a? DBus::Error
263
+ exc.name
257
264
  else
258
265
  "org.freedesktop.DBus.Error.Failed"
259
- # ex.class.to_s # RuntimeError is not a valid name, has no dot
266
+ # exc.class.to_s # RuntimeError is not a valid name, has no dot
260
267
  end
261
- description = ex.message
268
+ description = exc.message
262
269
  msg = new(name, description)
263
- msg.add_param(DBus.type("as"), ex.backtrace)
270
+ msg.add_param(DBus.type("as"), exc.backtrace)
264
271
  msg
265
272
  end
266
273
  end
267
- end # module DBus
274
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of the ruby-dbus project
2
4
  # Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
3
5
  # Copyright (C) 2009-2014 Martin Vidner
@@ -23,14 +25,16 @@ module DBus
23
25
  connect
24
26
  end
25
27
 
26
- # @param non_block [Boolean] if true, return nil instead of waiting
28
+ # @param blocking [Boolean]
29
+ # true: wait to return a {Message};
30
+ # false: may return `nil`
27
31
  # @return [Message,nil] one message or nil if unavailable
28
32
  # @raise EOFError
29
33
  # @todo failure modes
30
- def pop(non_block = false)
34
+ def pop(blocking: true)
31
35
  buffer_from_socket_nonblock
32
36
  message = message_from_buffer_nonblock
33
- unless non_block
37
+ if blocking
34
38
  # we can block
35
39
  while message.nil?
36
40
  r, _d, _d = IO.select([@socket])
@@ -54,7 +58,7 @@ module DBus
54
58
  def connect
55
59
  addresses = @address.split ";"
56
60
  # connect to first one that succeeds
57
- worked = addresses.find do |a|
61
+ addresses.find do |a|
58
62
  transport, keyvaluestring = a.split ":"
59
63
  kv_list = keyvaluestring.split ","
60
64
  kv_hash = {}
@@ -74,7 +78,6 @@ module DBus
74
78
  # ignore, report?
75
79
  end
76
80
  end
77
- worked
78
81
  # returns the address that worked or nil.
79
82
  # how to report failure?
80
83
  end
@@ -136,6 +139,7 @@ module DBus
136
139
  # @return [Message,nil] the message or nil if unavailable
137
140
  def message_from_buffer_nonblock
138
141
  return nil if @buffer.empty?
142
+
139
143
  ret = nil
140
144
  begin
141
145
  ret, size = Message.new.unmarshall_buffer(@buffer)
@@ -162,6 +166,7 @@ module DBus
162
166
  rescue Exception => e
163
167
  puts "Oops:", e
164
168
  raise if @is_tcp # why?
169
+
165
170
  puts "WARNING: read_nonblock failed, falling back to .recv"
166
171
  @buffer += @socket.recv(MSG_BUF_SIZE)
167
172
  end
data/lib/dbus/object.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of the ruby-dbus project
2
4
  # Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
3
5
  #
@@ -6,11 +8,10 @@
6
8
  # License, version 2.1 as published by the Free Software Foundation.
7
9
  # See the file "COPYING" for the exact licensing terms.
8
10
 
9
- require "thread"
10
11
  require_relative "core_ext/class/attribute"
11
12
 
12
13
  module DBus
13
- PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties".freeze
14
+ PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties"
14
15
 
15
16
  # Exported object type
16
17
  # = Exportable D-Bus object class
@@ -20,6 +21,7 @@ module DBus
20
21
  class Object
21
22
  # The path of the object.
22
23
  attr_reader :path
24
+
23
25
  # The interfaces that the object supports. Hash: String => Interface
24
26
  my_class_attribute :intfs
25
27
  self.intfs = {}
@@ -43,11 +45,13 @@ module DBus
43
45
  when Message::METHOD_CALL
44
46
  reply = nil
45
47
  begin
46
- if !intfs[msg.interface]
48
+ iface = intfs[msg.interface]
49
+ if !iface
47
50
  raise DBus.error("org.freedesktop.DBus.Error.UnknownMethod"),
48
51
  "Interface \"#{msg.interface}\" of object \"#{msg.path}\" doesn't exist"
49
52
  end
50
- meth = intfs[msg.interface].methods[msg.member.to_sym]
53
+ member_sym = msg.member.to_sym
54
+ meth = iface.methods[member_sym]
51
55
  if !meth
52
56
  raise DBus.error("org.freedesktop.DBus.Error.UnknownMethod"),
53
57
  "Method \"#{msg.member}\" on interface \"#{msg.interface}\" of object \"#{msg.path}\" doesn't exist"
@@ -57,11 +61,12 @@ module DBus
57
61
  retdata = [*retdata]
58
62
 
59
63
  reply = Message.method_return(msg)
60
- meth.rets.zip(retdata).each do |rsig, rdata|
61
- reply.add_param(rsig.type, rdata)
64
+ rsigs = meth.rets.map(&:type)
65
+ rsigs.zip(retdata).each do |rsig, rdata|
66
+ reply.add_param(rsig, rdata)
62
67
  end
63
- rescue StandardError => ex
64
- dbus_msg_exc = msg.annotate_exception(ex)
68
+ rescue StandardError => e
69
+ dbus_msg_exc = msg.annotate_exception(e)
65
70
  reply = ErrorMessage.from_exception(dbus_msg_exc).reply_to(msg)
66
71
  end
67
72
  @service.bus.message_queue.push(reply)
@@ -70,17 +75,19 @@ module DBus
70
75
 
71
76
  # Select (and create) the interface that the following defined methods
72
77
  # belong to.
73
- def self.dbus_interface(s)
78
+ # @param name [String] interface name like "org.example.ManagerManager"
79
+ # @see https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names-interface
80
+ def self.dbus_interface(name)
74
81
  @@intfs_mutex.synchronize do
75
- @@cur_intf = intfs[s]
82
+ @@cur_intf = intfs[name]
76
83
  if !@@cur_intf
77
- @@cur_intf = Interface.new(s)
84
+ @@cur_intf = Interface.new(name) # validates the name
78
85
  # As this is a mutable class_attr, we cannot use
79
- # self.intfs[s] = @@cur_intf # Hash#[]=
86
+ # self.intfs[name] = @@cur_intf # Hash#[]=
80
87
  # as that would modify parent class attr in place.
81
88
  # Using the setter lets a subclass have the new value
82
89
  # while the superclass keeps the old one.
83
- self.intfs = intfs.merge(s => @@cur_intf)
90
+ self.intfs = intfs.merge(name => @@cur_intf)
84
91
  end
85
92
  yield
86
93
  @@cur_intf = nil
@@ -110,6 +117,7 @@ module DBus
110
117
  # @return [void]
111
118
  def self.dbus_attr_accessor(ruby_name, type, dbus_name: nil)
112
119
  attr_accessor(ruby_name)
120
+
113
121
  dbus_accessor(ruby_name, type, dbus_name: dbus_name)
114
122
  end
115
123
 
@@ -129,6 +137,7 @@ module DBus
129
137
  # @return (see .dbus_attr_accessor)
130
138
  def self.dbus_attr_reader(ruby_name, type, dbus_name: nil)
131
139
  attr_reader(ruby_name)
140
+
132
141
  dbus_reader(ruby_name, type, dbus_name: dbus_name)
133
142
  end
134
143
 
@@ -139,6 +148,7 @@ module DBus
139
148
  # @return (see .dbus_attr_accessor)
140
149
  def self.dbus_attr_writer(ruby_name, type, dbus_name: nil)
141
150
  attr_writer(ruby_name)
151
+
142
152
  dbus_writer(ruby_name, type, dbus_name: dbus_name)
143
153
  end
144
154
 
@@ -211,6 +221,7 @@ module DBus
211
221
  # @return [void]
212
222
  def self.dbus_watcher(ruby_name, dbus_name: nil)
213
223
  raise UndefinedInterface, ruby_name if @@cur_intf.nil?
224
+
214
225
  cur_intf = @@cur_intf
215
226
 
216
227
  ruby_name = ruby_name.to_s.sub(/=$/, "").to_sym
@@ -235,6 +246,7 @@ module DBus
235
246
  # @param prototype [Prototype]
236
247
  def self.dbus_method(sym, prototype = "", &block)
237
248
  raise UndefinedInterface, sym if @@cur_intf.nil?
249
+
238
250
  @@cur_intf.define(Method.new(sym.to_s).from_prototype(prototype))
239
251
 
240
252
  ruby_name = Object.make_method_name(@@cur_intf.name, sym.to_s)
@@ -254,6 +266,7 @@ module DBus
254
266
  # Defines a signal for the object with a given name _sym_ and _prototype_.
255
267
  def self.dbus_signal(sym, prototype = "")
256
268
  raise UndefinedInterface, sym if @@cur_intf.nil?
269
+
257
270
  cur_intf = @@cur_intf
258
271
  signal = Signal.new(sym.to_s).from_prototype(prototype)
259
272
  cur_intf.define(Signal.new(sym.to_s).from_prototype(prototype))
@@ -324,7 +337,9 @@ module DBus
324
337
  if property.readable?
325
338
  ruby_name = property.ruby_name
326
339
  value = public_send(ruby_name)
327
- [value]
340
+ # may raise, DBus.error or https://ruby-doc.com/core-3.1.0/TypeError.html
341
+ typed_value = Data.make_typed(property.type, value)
342
+ [typed_value]
328
343
  else
329
344
  raise DBus.error("org.freedesktop.DBus.Error.PropertyWriteOnly"),
330
345
  "Property '#{interface_name}.#{property_name}' (on object '#{@path}') is not readable"
@@ -336,6 +351,9 @@ module DBus
336
351
 
337
352
  if property.writable?
338
353
  ruby_name_eq = "#{property.ruby_name}="
354
+ # TODO: declare dbus_method :Set to take :exact argument
355
+ # and type check it here before passing its :plain value
356
+ # to the implementation
339
357
  public_send(ruby_name_eq, value)
340
358
  else
341
359
  raise DBus.error("org.freedesktop.DBus.Error.PropertyReadOnly"),
@@ -364,7 +382,10 @@ module DBus
364
382
  # > array.
365
383
  # so we will silently omit properties that fail to read.
366
384
  # Get'ting them individually will send DBus.Error
367
- p_hash[p_name.to_s] = public_send(ruby_name)
385
+ value = public_send(ruby_name)
386
+ # may raise, DBus.error or https://ruby-doc.com/core-3.1.0/TypeError.html
387
+ typed_value = Data.make_typed(property.type, value)
388
+ p_hash[p_name.to_s] = typed_value
368
389
  rescue StandardError
369
390
  DBus.logger.debug "Property '#{interface_name}.#{p_name}' (on object '#{@path}')" \
370
391
  " has raised during GetAll, omitting it"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of the ruby-dbus project
2
4
  # Copyright (C) 2019 Martin Vidner
3
5
  #
@@ -7,18 +9,21 @@
7
9
  # See the file "COPYING" for the exact licensing terms.
8
10
 
9
11
  module DBus
10
- # A {::String} that validates at initialization time
12
+ # A {::String} that validates at initialization time.
13
+ # See also {DBus::Data::ObjectPath}
14
+ # @see https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-marshaling-object-path
11
15
  class ObjectPath < String
12
16
  # @raise Error if not a valid object path
13
- def initialize(s)
14
- unless self.class.valid?(s)
15
- raise DBus::Error, "Invalid object path #{s.inspect}"
17
+ def initialize(str)
18
+ unless self.class.valid?(str)
19
+ raise DBus::Error, "Invalid object path #{str.inspect}"
16
20
  end
21
+
17
22
  super
18
23
  end
19
24
 
20
- def self.valid?(s)
21
- s == "/" || s =~ %r{\A(/[A-Za-z0-9_]+)+\z}
25
+ def self.valid?(str)
26
+ str == "/" || str =~ %r{\A(/[A-Za-z0-9_]+)+\z}
22
27
  end
23
28
  end
24
29
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of the ruby-dbus project
2
4
  # Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
3
5
  # Copyright (C) 2009-2014 Martin Vidner
@@ -57,6 +59,7 @@ module DBus
57
59
  introspect unless introspected
58
60
  ifc = @interfaces[intfname]
59
61
  raise DBus::Error, "no such interface `#{intfname}' on object `#{@path}'" unless ifc
62
+
60
63
  ifc
61
64
  end
62
65
 
@@ -93,6 +96,7 @@ module DBus
93
96
  # don't overwrite instance methods!
94
97
  next if dup_meths.include?(name)
95
98
  next if self.class.instance_methods.include?(name)
99
+
96
100
  if univocal_meths.include? name
97
101
  univocal_meths.delete name
98
102
  dup_meths << name
@@ -124,14 +128,17 @@ module DBus
124
128
  def on_signal(name, &block)
125
129
  # TODO: improve
126
130
  raise NoMethodError unless @default_iface && has_iface?(@default_iface)
131
+
127
132
  @interfaces[@default_iface].on_signal(name, &block)
128
133
  end
129
134
 
130
135
  ####################################################
131
136
  private
132
137
 
133
- # rubocop:disable Style/MethodMissing
134
- # but https://github.com/rubocop-hq/ruby-style-guide#no-method-missing
138
+ # rubocop:disable Lint/MissingSuper
139
+ # as this should forward everything
140
+ #
141
+ # https://github.com/rubocop-hq/ruby-style-guide#no-method-missing
135
142
  # and http://blog.marc-andre.ca/2010/11/15/methodmissing-politely/
136
143
  # have a point to be investigated
137
144
 
@@ -152,10 +159,17 @@ module DBus
152
159
  # interesting, foo.method("unknown")
153
160
  # raises NameError, not NoMethodError
154
161
  raise unless e.to_s =~ /undefined method `#{name}'/
162
+
155
163
  # BTW e.exception("...") would preserve the class.
156
164
  raise NoMethodError, "undefined method `#{name}' for DBus interface `#{@default_iface}' on object `#{@path}'"
157
165
  end
158
166
  end
159
- # rubocop:enable Style/MethodMissing
160
- end # class ProxyObject
167
+ # rubocop:enable Lint/MissingSuper
168
+
169
+ def respond_to_missing?(name, _include_private = false)
170
+ @default_iface &&
171
+ has_iface?(@default_iface) &&
172
+ @interfaces[@default_iface].methods.key?(name) or super
173
+ end
174
+ end
161
175
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of the ruby-dbus project
2
4
  # Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
3
5
  # Copyright (C) 2009-2014 Martin Vidner
@@ -22,17 +24,19 @@ module DBus
22
24
  @api = api
23
25
  end
24
26
 
25
- # Investigates the sub-nodes of the proxy object _po_ based on the
27
+ # Investigates the sub-nodes of the proxy object _pobj_ based on the
26
28
  # introspection XML data _xml_ and sets them up recursively.
27
- def self.introspect_into(po, xml)
28
- intfs, po.subnodes = IntrospectXMLParser.new(xml).parse
29
+ # @param pobj [ProxyObject]
30
+ # @param xml [String]
31
+ def self.introspect_into(pobj, xml)
32
+ intfs, pobj.subnodes = IntrospectXMLParser.new(xml).parse
29
33
  intfs.each do |i|
30
- poi = ProxyObjectInterface.new(po, i.name)
34
+ poi = ProxyObjectInterface.new(pobj, i.name)
31
35
  i.methods.each_value { |m| poi.define(m) }
32
36
  i.signals.each_value { |s| poi.define(s) }
33
- po[i.name] = poi
37
+ pobj[i.name] = poi
34
38
  end
35
- po.introspected = true
39
+ pobj.introspected = true
36
40
  end
37
41
 
38
42
  # Generates, sets up and returns the proxy object.
@@ -41,5 +45,5 @@ module DBus
41
45
  ProxyObjectFactory.introspect_into(po, @xml)
42
46
  po
43
47
  end
44
- end # class ProxyObjectFactory
48
+ end
45
49
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is part of the ruby-dbus project
2
4
  # Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
3
5
  # Copyright (C) 2009-2014 Martin Vidner
@@ -36,27 +38,28 @@ module DBus
36
38
  @name
37
39
  end
38
40
 
39
- # Defines a method on the interface from the Method descriptor _m_.
40
- def define_method_from_descriptor(m)
41
- m.params.each do |fpar|
41
+ # Defines a method on the interface from the Method descriptor _method_.
42
+ # @param method [Method]
43
+ def define_method_from_descriptor(method)
44
+ method.params.each do |fpar|
42
45
  par = fpar.type
43
46
  # This is the signature validity check
44
47
  Type::Parser.new(par).parse
45
48
  end
46
49
 
47
50
  singleton_class.class_eval do
48
- define_method m.name do |*args, &reply_handler|
49
- if m.params.size != args.size
50
- raise ArgumentError, "wrong number of arguments (#{args.size} for #{m.params.size})"
51
+ define_method method.name do |*args, &reply_handler|
52
+ if method.params.size != args.size
53
+ raise ArgumentError, "wrong number of arguments (#{args.size} for #{method.params.size})"
51
54
  end
52
55
 
53
56
  msg = Message.new(Message::METHOD_CALL)
54
57
  msg.path = @object.path
55
58
  msg.interface = @name
56
59
  msg.destination = @object.destination
57
- msg.member = m.name
60
+ msg.member = method.name
58
61
  msg.sender = @object.bus.unique_name
59
- m.params.each do |fpar|
62
+ method.params.each do |fpar|
60
63
  par = fpar.type
61
64
  msg.add_param(par, args.shift)
62
65
  end
@@ -64,30 +67,31 @@ module DBus
64
67
  if ret.nil? || @object.api.proxy_method_returns_array
65
68
  ret
66
69
  else
67
- m.rets.size == 1 ? ret.first : ret
70
+ method.rets.size == 1 ? ret.first : ret
68
71
  end
69
72
  end
70
73
  end
71
74
 
72
- @methods[m.name] = m
75
+ @methods[method.name] = method
73
76
  end
74
77
 
75
- # Defines a signal from the descriptor _s_.
76
- def define_signal_from_descriptor(s)
77
- @signals[s.name] = s
78
+ # Defines a signal from the descriptor _sig_.
79
+ # @param sig [Signal]
80
+ def define_signal_from_descriptor(sig)
81
+ @signals[sig.name] = sig
78
82
  end
79
83
 
80
- # Defines a signal or method based on the descriptor _m_.
81
- def define(m)
82
- if m.is_a?(Method)
83
- define_method_from_descriptor(m)
84
- elsif m.is_a?(Signal)
85
- define_signal_from_descriptor(m)
84
+ # Defines a signal or method based on the descriptor _ifc_el_.
85
+ def define(ifc_el)
86
+ case ifc_el
87
+ when Method
88
+ define_method_from_descriptor(ifc_el)
89
+ when Signal
90
+ define_signal_from_descriptor(ifc_el)
86
91
  end
87
92
  end
88
93
 
89
94
  # Defines a proxied method on the interface.
90
- # Better name: declare_method
91
95
  def define_method(methodname, prototype)
92
96
  m = Method.new(methodname)
93
97
  m.from_prototype(prototype)
@@ -110,7 +114,7 @@ module DBus
110
114
  end
111
115
  end
112
116
 
113
- PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties".freeze
117
+ PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties"
114
118
 
115
119
  # Read a property.
116
120
  # @param propname [String]
@@ -142,5 +146,5 @@ module DBus
142
146
  ret
143
147
  end
144
148
  end
145
- end # class ProxyObjectInterface
149
+ end
146
150
  end