ruby-dbus 0.16.0 → 0.18.0.beta2

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 (75) hide show
  1. checksums.yaml +4 -4
  2. data/NEWS.md +46 -0
  3. data/README.md +3 -5
  4. data/Rakefile +18 -8
  5. data/VERSION +1 -1
  6. data/doc/Reference.md +94 -4
  7. data/examples/doc/_extract_examples +7 -0
  8. data/examples/gdbus/gdbus +31 -24
  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 +2 -1
  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 +20 -15
  22. data/lib/dbus/bus.rb +126 -74
  23. data/lib/dbus/bus_name.rb +12 -8
  24. data/lib/dbus/core_ext/class/attribute.rb +1 -1
  25. data/lib/dbus/data.rb +725 -0
  26. data/lib/dbus/error.rb +4 -2
  27. data/lib/dbus/introspect.rb +91 -30
  28. data/lib/dbus/logger.rb +3 -1
  29. data/lib/dbus/marshall.rb +228 -294
  30. data/lib/dbus/matchrule.rb +16 -16
  31. data/lib/dbus/message.rb +44 -37
  32. data/lib/dbus/message_queue.rb +16 -10
  33. data/lib/dbus/object.rb +296 -24
  34. data/lib/dbus/object_path.rb +11 -6
  35. data/lib/dbus/proxy_object.rb +22 -1
  36. data/lib/dbus/proxy_object_factory.rb +11 -7
  37. data/lib/dbus/proxy_object_interface.rb +26 -21
  38. data/lib/dbus/raw_message.rb +91 -0
  39. data/lib/dbus/type.rb +182 -80
  40. data/lib/dbus/xml.rb +28 -17
  41. data/lib/dbus.rb +13 -7
  42. data/ruby-dbus.gemspec +7 -3
  43. data/spec/async_spec.rb +2 -0
  44. data/spec/binding_spec.rb +2 -0
  45. data/spec/bus_and_xml_backend_spec.rb +2 -0
  46. data/spec/bus_driver_spec.rb +2 -0
  47. data/spec/bus_name_spec.rb +3 -1
  48. data/spec/bus_spec.rb +2 -0
  49. data/spec/byte_array_spec.rb +2 -0
  50. data/spec/client_robustness_spec.rb +4 -2
  51. data/spec/data/marshall.yaml +1639 -0
  52. data/spec/data_spec.rb +298 -0
  53. data/spec/err_msg_spec.rb +2 -0
  54. data/spec/introspect_xml_parser_spec.rb +2 -0
  55. data/spec/introspection_spec.rb +2 -0
  56. data/spec/main_loop_spec.rb +3 -1
  57. data/spec/node_spec.rb +23 -0
  58. data/spec/object_path_spec.rb +3 -0
  59. data/spec/packet_marshaller_spec.rb +34 -0
  60. data/spec/packet_unmarshaller_spec.rb +262 -0
  61. data/spec/property_spec.rb +88 -5
  62. data/spec/proxy_object_spec.rb +2 -0
  63. data/spec/server_robustness_spec.rb +2 -0
  64. data/spec/server_spec.rb +2 -0
  65. data/spec/service_newapi.rb +39 -70
  66. data/spec/session_bus_spec.rb +3 -1
  67. data/spec/session_bus_spec_manual.rb +2 -0
  68. data/spec/signal_spec.rb +5 -3
  69. data/spec/spec_helper.rb +35 -9
  70. data/spec/thread_safety_spec.rb +2 -0
  71. data/spec/tools/dbus-limited-session.conf +4 -0
  72. data/spec/type_spec.rb +69 -6
  73. data/spec/value_spec.rb +16 -1
  74. data/spec/variant_spec.rb +4 -2
  75. metadata +32 -10
data/lib/dbus/bus.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
@@ -9,7 +11,6 @@
9
11
  # See the file "COPYING" for the exact licensing terms.
10
12
 
11
13
  require "socket"
12
- require "thread"
13
14
  require "singleton"
14
15
 
15
16
  # = D-Bus main module
@@ -17,7 +18,7 @@ require "singleton"
17
18
  # Module containing all the D-Bus modules and classes.
18
19
  module DBus
19
20
  # This represents a remote service. It should not be instantiated directly
20
- # Use {Bus#service}
21
+ # Use {Connection#service}
21
22
  class Service
22
23
  # The service name.
23
24
  attr_reader :name
@@ -48,6 +49,7 @@ module DBus
48
49
  end
49
50
 
50
51
  # Retrieves an object at the given _path_.
52
+ # @param path [ObjectPath]
51
53
  # @return [ProxyObject]
52
54
  def [](path)
53
55
  object(path, api: ApiOptions::A1)
@@ -55,9 +57,11 @@ module DBus
55
57
 
56
58
  # Retrieves an object at the given _path_
57
59
  # whose methods always return an array.
60
+ # @param path [ObjectPath]
61
+ # @param api [ApiOptions]
58
62
  # @return [ProxyObject]
59
63
  def object(path, api: ApiOptions::A0)
60
- node = get_node(path, _create = true)
64
+ node = get_node(path, create: true)
61
65
  if node.object.nil? || node.object.api != api
62
66
  node.object = ProxyObject.new(
63
67
  @bus, @name, path,
@@ -67,35 +71,43 @@ module DBus
67
71
  node.object
68
72
  end
69
73
 
70
- # Export an object _obj_ (an DBus::Object subclass instance).
74
+ # Export an object
75
+ # @param obj [DBus::Object]
71
76
  def export(obj)
72
77
  obj.service = self
73
- get_node(obj.path, true).object = obj
78
+ get_node(obj.path, create: true).object = obj
74
79
  end
75
80
 
76
81
  # Undo exporting an object _obj_.
77
82
  # Raises ArgumentError if it is not a DBus::Object.
78
83
  # Returns the object, or false if _obj_ was not exported.
84
+ # @param obj [DBus::Object]
79
85
  def unexport(obj)
80
86
  raise ArgumentError, "DBus::Service#unexport() expects a DBus::Object argument" unless obj.is_a?(DBus::Object)
81
87
  return false unless obj.path
88
+
82
89
  last_path_separator_idx = obj.path.rindex("/")
83
90
  parent_path = obj.path[1..last_path_separator_idx - 1]
84
91
  node_name = obj.path[last_path_separator_idx + 1..-1]
85
92
 
86
- parent_node = get_node(parent_path, false)
93
+ parent_node = get_node(parent_path, create: false)
87
94
  return false unless parent_node
95
+
88
96
  obj.service = nil
89
97
  parent_node.delete(node_name).object
90
98
  end
91
99
 
92
- # Get the object node corresponding to the given _path_. if _create_ is
93
- # true, the the nodes in the path are created if they do not already exist.
94
- def get_node(path, create = false)
100
+ # Get the object node corresponding to the given *path*.
101
+ # @param path [ObjectPath]
102
+ # @param create [Boolean] if true, the the {Node}s in the path are created
103
+ # if they do not already exist.
104
+ # @return [Node,nil]
105
+ def get_node(path, create: false)
95
106
  n = @root
96
107
  path.sub(%r{^/}, "").split("/").each do |elem|
97
108
  if !(n[elem])
98
109
  return nil if !create
110
+
99
111
  n[elem] = Node.new(elem)
100
112
  end
101
113
  n = n[elem]
@@ -120,13 +132,14 @@ module DBus
120
132
  subnodes.each do |nodename|
121
133
  subnode = node[nodename] = Node.new(nodename)
122
134
  subpath = if path == "/"
123
- "/" + nodename
135
+ "/#{nodename}"
124
136
  else
125
- path + "/" + nodename
137
+ "#{path}/#{nodename}"
126
138
  end
127
139
  rec_introspect(subnode, subpath)
128
140
  end
129
141
  return if intfs.empty?
142
+
130
143
  node.object = ProxyObjectFactory.new(xml, @bus, @name, path).build
131
144
  end
132
145
  end
@@ -135,34 +148,38 @@ module DBus
135
148
  #
136
149
  # Class representing a node on an object path.
137
150
  class Node < Hash
138
- # The D-Bus object contained by the node.
151
+ # @return [DBus::Object,DBus::ProxyObject,nil]
152
+ # The D-Bus object contained by the node.
139
153
  attr_accessor :object
154
+
140
155
  # The name of the node.
156
+ # @return [String] the last component of its object path, or "/"
141
157
  attr_reader :name
142
158
 
143
159
  # Create a new node with a given _name_.
144
160
  def initialize(name)
161
+ super()
145
162
  @name = name
146
163
  @object = nil
147
164
  end
148
165
 
149
166
  # Return an XML string representation of the node.
150
167
  # It is shallow, not recursing into subnodes
151
- def to_xml
168
+ # @param node_opath [String]
169
+ def to_xml(node_opath)
152
170
  xml = '<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
153
171
  "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
154
- <node>
155
172
  '
173
+ xml += "<node name=\"#{node_opath}\">\n"
156
174
  each_pair do |k, _v|
157
- xml += "<node name=\"#{k}\" />"
175
+ xml += " <node name=\"#{k}\" />\n"
158
176
  end
159
- if @object
160
- @object.intfs.each_pair do |_k, v|
161
- xml += %(<interface name="#{v.name}">\n)
162
- v.methods.each_value { |m| xml += m.to_xml }
163
- v.signals.each_value { |m| xml += m.to_xml }
164
- xml += "</interface>\n"
165
- end
177
+ @object&.intfs&.each_pair do |_k, v|
178
+ xml += " <interface name=\"#{v.name}\">\n"
179
+ v.methods.each_value { |m| xml += m.to_xml }
180
+ v.signals.each_value { |m| xml += m.to_xml }
181
+ v.properties.each_value { |m| xml += m.to_xml }
182
+ xml += " </interface>\n"
166
183
  end
167
184
  xml += "</node>"
168
185
  xml
@@ -180,9 +197,12 @@ module DBus
180
197
  if !@object.nil?
181
198
  s += format("%x ", @object.object_id)
182
199
  end
183
- s + "{" + keys.collect { |k| "#{k} => #{self[k].sub_inspect}" }.join(",") + "}"
200
+ contents_sub_inspect = keys
201
+ .map { |k| "#{k} => #{self[k].sub_inspect}" }
202
+ .join(",")
203
+ "#{s}{#{contents_sub_inspect}}"
184
204
  end
185
- end # class Inspect
205
+ end
186
206
 
187
207
  # FIXME: rename Connection to Bus?
188
208
 
@@ -205,7 +225,15 @@ module DBus
205
225
  def initialize(path)
206
226
  @message_queue = MessageQueue.new(path)
207
227
  @unique_name = nil
228
+
229
+ # @return [Hash{Integer => Proc}]
230
+ # key: message serial
231
+ # value: block to be run when the reply to that message is received
208
232
  @method_call_replies = {}
233
+
234
+ # @return [Hash{Integer => Message}]
235
+ # for debugging only: messages for which a reply was not received yet;
236
+ # key == value.serial
209
237
  @method_call_msgs = {}
210
238
  @signal_matchrules = {}
211
239
  @proxy = nil
@@ -216,7 +244,7 @@ module DBus
216
244
  # but do not block on the queue.
217
245
  # Called by a main loop when something is available in the queue
218
246
  def dispatch_message_queue
219
- while (msg = @message_queue.pop(:non_block)) # FIXME: EOFError
247
+ while (msg = @message_queue.pop(blocking: false)) # FIXME: EOFError
220
248
  process(msg)
221
249
  end
222
250
  end
@@ -323,7 +351,7 @@ module DBus
323
351
  </signal>
324
352
  </interface>
325
353
  </node>
326
- '.freeze
354
+ '
327
355
  # This apostroph is for syntax highlighting editors confused by above xml: "
328
356
 
329
357
  # @api private
@@ -338,6 +366,7 @@ module DBus
338
366
  if reply_handler.nil?
339
367
  send_sync(message) do |rmsg|
340
368
  raise rmsg if rmsg.is_a?(Error)
369
+
341
370
  ret = rmsg.params
342
371
  end
343
372
  else
@@ -442,44 +471,52 @@ module DBus
442
471
  end
443
472
 
444
473
  # @api private
445
- # Send a message _m_ on to the bus. This is done synchronously, thus
474
+ # Send a message _msg_ on to the bus. This is done synchronously, thus
446
475
  # the call will block until a reply message arrives.
447
- def send_sync(m, &retc) # :yields: reply/return message
448
- return if m.nil? # check if somethings wrong
449
- @message_queue.push(m)
450
- @method_call_msgs[m.serial] = m
451
- @method_call_replies[m.serial] = retc
476
+ # @param msg [Message]
477
+ # @param retc [Proc] the reply handler
478
+ # @yieldparam rmsg [MethodReturnMessage] the reply
479
+ # @yieldreturn [Array<Object>] the reply (out) parameters
480
+ def send_sync(msg, &retc) # :yields: reply/return message
481
+ return if msg.nil? # check if somethings wrong
482
+
483
+ @message_queue.push(msg)
484
+ @method_call_msgs[msg.serial] = msg
485
+ @method_call_replies[msg.serial] = retc
452
486
 
453
487
  retm = wait_for_message
454
488
  return if retm.nil? # check if somethings wrong
455
489
 
456
490
  process(retm)
457
- while @method_call_replies.key? m.serial
491
+ while @method_call_replies.key? msg.serial
458
492
  retm = wait_for_message
459
493
  process(retm)
460
494
  end
461
495
  rescue EOFError
462
- new_err = DBus::Error.new("Connection dropped after we sent #{m.inspect}")
496
+ new_err = DBus::Error.new("Connection dropped after we sent #{msg.inspect}")
463
497
  raise new_err
464
498
  end
465
499
 
466
500
  # @api private
467
501
  # Specify a code block that has to be executed when a reply for
468
- # message _m_ is received.
469
- def on_return(m, &retc)
502
+ # message _msg_ is received.
503
+ # @param msg [Message]
504
+ def on_return(msg, &retc)
470
505
  # Have a better exception here
471
- if m.message_type != Message::METHOD_CALL
506
+ if msg.message_type != Message::METHOD_CALL
472
507
  raise "on_return should only get method_calls"
473
508
  end
474
- @method_call_msgs[m.serial] = m
475
- @method_call_replies[m.serial] = retc
509
+
510
+ @method_call_msgs[msg.serial] = msg
511
+ @method_call_replies[msg.serial] = retc
476
512
  end
477
513
 
478
514
  # Asks bus to send us messages matching mr, and execute slot when
479
515
  # received
480
- def add_match(mr, &slot)
516
+ # @param match_rule [MatchRule,#to_s]
517
+ def add_match(match_rule, &slot)
481
518
  # check this is a signal.
482
- mrs = mr.to_s
519
+ mrs = match_rule.to_s
483
520
  DBus.logger.debug "#{@signal_matchrules.size} rules, adding #{mrs.inspect}"
484
521
  # don't ask for the same match if we override it
485
522
  unless @signal_matchrules.key?(mrs)
@@ -489,69 +526,77 @@ module DBus
489
526
  @signal_matchrules[mrs] = slot
490
527
  end
491
528
 
492
- def remove_match(mr)
493
- mrs = mr.to_s
529
+ # @param match_rule [MatchRule,#to_s]
530
+ def remove_match(match_rule)
531
+ mrs = match_rule.to_s
494
532
  rule_existed = @signal_matchrules.delete(mrs).nil?
495
533
  # don't remove nonexisting matches.
496
534
  return if rule_existed
535
+
497
536
  # FIXME: if we do try, the Error.MatchRuleNotFound is *not* raised
498
537
  # and instead is reported as "no return code for nil"
499
538
  proxy.RemoveMatch(mrs)
500
539
  end
501
540
 
502
541
  # @api private
503
- # Process a message _m_ based on its type.
504
- def process(m)
505
- return if m.nil? # check if somethings wrong
506
- case m.message_type
542
+ # Process a message _msg_ based on its type.
543
+ # @param msg [Message]
544
+ def process(msg)
545
+ return if msg.nil? # check if somethings wrong
546
+
547
+ case msg.message_type
507
548
  when Message::ERROR, Message::METHOD_RETURN
508
- raise InvalidPacketException if m.reply_serial.nil?
509
- mcs = @method_call_replies[m.reply_serial]
549
+ raise InvalidPacketException if msg.reply_serial.nil?
550
+
551
+ mcs = @method_call_replies[msg.reply_serial]
510
552
  if !mcs
511
- DBus.logger.debug "no return code for mcs: #{mcs.inspect} m: #{m.inspect}"
553
+ DBus.logger.debug "no return code for mcs: #{mcs.inspect} msg: #{msg.inspect}"
512
554
  else
513
- if m.message_type == Message::ERROR
514
- mcs.call(Error.new(m))
555
+ if msg.message_type == Message::ERROR
556
+ mcs.call(Error.new(msg))
515
557
  else
516
- mcs.call(m)
558
+ mcs.call(msg)
517
559
  end
518
- @method_call_replies.delete(m.reply_serial)
519
- @method_call_msgs.delete(m.reply_serial)
560
+ @method_call_replies.delete(msg.reply_serial)
561
+ @method_call_msgs.delete(msg.reply_serial)
520
562
  end
521
563
  when DBus::Message::METHOD_CALL
522
- if m.path == "/org/freedesktop/DBus"
564
+ if msg.path == "/org/freedesktop/DBus"
523
565
  DBus.logger.debug "Got method call on /org/freedesktop/DBus"
524
566
  end
525
- node = @service.get_node(m.path)
567
+ node = @service.get_node(msg.path, create: false)
526
568
  if !node
527
- reply = Message.error(m, "org.freedesktop.DBus.Error.UnknownObject",
528
- "Object #{m.path} doesn't exist")
569
+ reply = Message.error(msg, "org.freedesktop.DBus.Error.UnknownObject",
570
+ "Object #{msg.path} doesn't exist")
529
571
  @message_queue.push(reply)
530
572
  # handle introspectable as an exception:
531
- elsif m.interface == "org.freedesktop.DBus.Introspectable" &&
532
- m.member == "Introspect"
533
- reply = Message.new(Message::METHOD_RETURN).reply_to(m)
573
+ elsif msg.interface == "org.freedesktop.DBus.Introspectable" &&
574
+ msg.member == "Introspect"
575
+ reply = Message.new(Message::METHOD_RETURN).reply_to(msg)
534
576
  reply.sender = @unique_name
535
- reply.add_param(Type::STRING, node.to_xml)
577
+ xml = node.to_xml(msg.path)
578
+ reply.add_param(Type::STRING, xml)
536
579
  @message_queue.push(reply)
537
580
  else
538
581
  obj = node.object
539
582
  return if obj.nil? # FIXME, pushes no reply
540
- obj.dispatch(m) if obj
583
+
584
+ obj&.dispatch(msg)
541
585
  end
542
586
  when DBus::Message::SIGNAL
543
587
  # the signal can match multiple different rules
544
588
  # clone to allow new signale handlers to be registered
545
589
  @signal_matchrules.dup.each do |mrs, slot|
546
- if DBus::MatchRule.new.from_s(mrs).match(m)
547
- slot.call(m)
590
+ if DBus::MatchRule.new.from_s(mrs).match(msg)
591
+ slot.call(msg)
548
592
  end
549
593
  end
550
594
  else
551
- DBus.logger.debug "Unknown message type: #{m.message_type}"
595
+ # spec(Message Format): Unknown types must be ignored.
596
+ DBus.logger.debug "Unknown message type: #{msg.message_type}"
552
597
  end
553
- rescue Exception => ex
554
- raise m.annotate_exception(ex)
598
+ rescue Exception => e
599
+ raise msg.annotate_exception(e)
555
600
  end
556
601
 
557
602
  # Retrieves the Service with the given _name_.
@@ -566,6 +611,11 @@ module DBus
566
611
  # @api private
567
612
  # Emit a signal event for the given _service_, object _obj_, interface
568
613
  # _intf_ and signal _sig_ with arguments _args_.
614
+ # @param service [Service]
615
+ # @param obj [DBus::Object]
616
+ # @param intf [Interface]
617
+ # @param sig [Signal]
618
+ # @param args arguments for the signal
569
619
  def emit(service, obj, intf, sig, *args)
570
620
  m = Message.new(DBus::Message::SIGNAL)
571
621
  m.path = obj.path
@@ -596,7 +646,7 @@ module DBus
596
646
  end
597
647
  @service = Service.new(@unique_name, self)
598
648
  end
599
- end # class Connection
649
+ end
600
650
 
601
651
  # = D-Bus session bus class
602
652
  #
@@ -622,6 +672,7 @@ module DBus
622
672
  # traditional dbus uses /var/lib/dbus/machine-id
623
673
  machine_id_path = Dir["{/etc,/var/lib/dbus,/var/db/dbus}/machine-id"].first
624
674
  return nil unless machine_id_path
675
+
625
676
  machine_id = File.read(machine_id_path).chomp
626
677
 
627
678
  display = ENV["DISPLAY"][/:(\d+)\.?/, 1]
@@ -653,7 +704,7 @@ module DBus
653
704
  class ASystemBus < Connection
654
705
  # Get the default system bus.
655
706
  def initialize
656
- super(SystemSocketName)
707
+ super(SYSTEM_BUS_ADDRESS)
657
708
  send_hello
658
709
  end
659
710
  end
@@ -668,7 +719,7 @@ module DBus
668
719
  # (for Unix-socket) unix:path=/tmp/my_funky_bus_socket
669
720
  #
670
721
  # you'll need to take care about authentification then, more info here:
671
- # http://github.com/pangdudu/ruby-dbus/blob/master/README.rdoc
722
+ # https://gitlab.com/pangdudu/ruby-dbus/-/blob/master/README.rdoc
672
723
  class RemoteBus < Connection
673
724
  # Get the remote bus.
674
725
  def initialize(socket_name)
@@ -728,6 +779,7 @@ module DBus
728
779
  while !@quitting && !@buses.empty?
729
780
  ready = IO.select(@buses.keys, [], [], 5) # timeout 5 seconds
730
781
  next unless ready # timeout exceeds so continue unless quitting
782
+
731
783
  ready.first.each do |socket|
732
784
  b = @buses[socket]
733
785
  begin
@@ -742,5 +794,5 @@ module DBus
742
794
  end
743
795
  end
744
796
  end
745
- end # class Main
746
- end # module DBus
797
+ end
798
+ end
data/lib/dbus/bus_name.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) 2019 Martin Vidner
3
5
  #
@@ -7,21 +9,23 @@
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
+ # D-Bus: a name for a connection, like ":1.3" or "org.example.ManagerManager".
13
+ # Implemented as a {::String} that validates at initialization time.
11
14
  # @see https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names-bus
12
15
  class BusName < String
13
16
  # @raise Error if not a valid bus name
14
- def initialize(s)
15
- unless self.class.valid?(s)
16
- raise DBus::Error, "Invalid bus name #{s.inspect}"
17
+ def initialize(name)
18
+ unless self.class.valid?(name)
19
+ raise DBus::Error, "Invalid bus name #{name.inspect}"
17
20
  end
21
+
18
22
  super
19
23
  end
20
24
 
21
- def self.valid?(s)
22
- s.size <= 255 &&
23
- (s =~ /\A:[A-Za-z0-9_-]+(\.[A-Za-z0-9_-]+)+\z/ ||
24
- s =~ /\A[A-Za-z_-][A-Za-z0-9_-]*(\.[A-Za-z_-][A-Za-z0-9_-]*)+\z/)
25
+ def self.valid?(name)
26
+ name.size <= 255 &&
27
+ (name =~ /\A:[A-Za-z0-9_-]+(\.[A-Za-z0-9_-]+)+\z/ ||
28
+ name =~ /\A[A-Za-z_-][A-Za-z0-9_-]*(\.[A-Za-z_-][A-Za-z0-9_-]*)+\z/)
25
29
  end
26
30
  end
27
31
  end
@@ -2,7 +2,7 @@
2
2
  # copied from activesupport/core_ext from Rails, MIT license
3
3
  # https://github.com/rails/rails/tree/9794e85351243cac6d4e78adaba634b8e4ecad0a/activesupport/lib/active_support/core_ext
4
4
 
5
- require "dbus/core_ext/module/redefine_method"
5
+ require_relative "../module/redefine_method"
6
6
 
7
7
  class Class
8
8
  # Declare a class-level attribute whose value is inheritable by subclasses.