ruby-dbus 0.16.0 → 0.18.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
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.