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
@@ -15,13 +15,16 @@ module DBus
|
|
15
15
|
# Creates a new proxy object factory for the given introspection XML _xml_,
|
16
16
|
# _bus_, destination _dest_, and _path_.
|
17
17
|
def initialize(xml, bus, dest, path, api: ApiOptions::CURRENT)
|
18
|
-
@xml
|
18
|
+
@xml = xml
|
19
|
+
@bus = bus
|
20
|
+
@path = path
|
21
|
+
@dest = dest
|
19
22
|
@api = api
|
20
23
|
end
|
21
24
|
|
22
25
|
# Investigates the sub-nodes of the proxy object _po_ based on the
|
23
26
|
# introspection XML data _xml_ and sets them up recursively.
|
24
|
-
def
|
27
|
+
def self.introspect_into(po, xml)
|
25
28
|
intfs, po.subnodes = IntrospectXMLParser.new(xml).parse
|
26
29
|
intfs.each do |i|
|
27
30
|
poi = ProxyObjectInterface.new(po, i.name)
|
@@ -25,8 +25,10 @@ module DBus
|
|
25
25
|
# Creates a new proxy interface for the given proxy _object_
|
26
26
|
# and the given _name_.
|
27
27
|
def initialize(object, name)
|
28
|
-
@object
|
29
|
-
@
|
28
|
+
@object = object
|
29
|
+
@name = name
|
30
|
+
@methods = {}
|
31
|
+
@signals = {}
|
30
32
|
end
|
31
33
|
|
32
34
|
# Returns the string representation of the interface (the name).
|
@@ -77,9 +79,9 @@ module DBus
|
|
77
79
|
|
78
80
|
# Defines a signal or method based on the descriptor _m_.
|
79
81
|
def define(m)
|
80
|
-
if m.
|
82
|
+
if m.is_a?(Method)
|
81
83
|
define_method_from_descriptor(m)
|
82
|
-
elsif m.
|
84
|
+
elsif m.is_a?(Signal)
|
83
85
|
define_signal_from_descriptor(m)
|
84
86
|
end
|
85
87
|
end
|
@@ -107,12 +109,12 @@ module DBus
|
|
107
109
|
end
|
108
110
|
end
|
109
111
|
|
110
|
-
PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties"
|
112
|
+
PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties".freeze
|
111
113
|
|
112
114
|
# Read a property.
|
113
115
|
# @param propname [String]
|
114
116
|
def [](propname)
|
115
|
-
ret =
|
117
|
+
ret = object[PROPERTY_INTERFACE].Get(name, propname)
|
116
118
|
# this method always returns the single property
|
117
119
|
if @object.api.proxy_method_returns_array
|
118
120
|
ret[0]
|
@@ -125,13 +127,13 @@ module DBus
|
|
125
127
|
# @param propname [String]
|
126
128
|
# @param value [Object]
|
127
129
|
def []=(propname, value)
|
128
|
-
|
130
|
+
object[PROPERTY_INTERFACE].Set(name, propname, value)
|
129
131
|
end
|
130
132
|
|
131
133
|
# Read all properties at once, as a hash.
|
132
134
|
# @return [Hash{String}]
|
133
135
|
def all_properties
|
134
|
-
ret =
|
136
|
+
ret = object[PROPERTY_INTERFACE].GetAll(name)
|
135
137
|
# this method always returns the single property
|
136
138
|
if @object.api.proxy_method_returns_array
|
137
139
|
ret[0]
|
data/lib/dbus/type.rb
CHANGED
@@ -9,185 +9,183 @@
|
|
9
9
|
# See the file "COPYING" for the exact licensing terms.
|
10
10
|
|
11
11
|
module DBus
|
12
|
-
|
13
|
-
# = D-Bus type module
|
14
|
-
#
|
15
|
-
# This module containts the constants of the types specified in the D-Bus
|
16
|
-
# protocol.
|
17
|
-
module Type
|
18
|
-
# Mapping from type number to name and alignment.
|
19
|
-
TypeMapping = {
|
20
|
-
0 => ["INVALID", nil],
|
21
|
-
?y => ["BYTE", 1],
|
22
|
-
?b => ["BOOLEAN", 4],
|
23
|
-
?n => ["INT16", 2],
|
24
|
-
?q => ["UINT16", 2],
|
25
|
-
?i => ["INT32", 4],
|
26
|
-
?u => ["UINT32", 4],
|
27
|
-
?x => ["INT64", 8],
|
28
|
-
?t => ["UINT64", 8],
|
29
|
-
?d => ["DOUBLE", 8],
|
30
|
-
?r => ["STRUCT", 8],
|
31
|
-
?a => ["ARRAY", 4],
|
32
|
-
?v => ["VARIANT", 1],
|
33
|
-
?o => ["OBJECT_PATH", 4],
|
34
|
-
?s => ["STRING", 4],
|
35
|
-
?g => ["SIGNATURE", 1],
|
36
|
-
?e => ["DICT_ENTRY", 8],
|
37
|
-
?h => ["UNIX_FD", 4],
|
38
|
-
}
|
39
|
-
# Defines the set of constants
|
40
|
-
TypeMapping.each_pair do |key, value|
|
41
|
-
Type.const_set(value.first, key)
|
42
|
-
end
|
43
|
-
|
44
|
-
# Exception raised when an unknown/incorrect type is encountered.
|
45
|
-
class SignatureException < Exception
|
46
|
-
end
|
47
|
-
|
48
|
-
# = D-Bus type conversion class
|
12
|
+
# = D-Bus type module
|
49
13
|
#
|
50
|
-
#
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
14
|
+
# This module containts the constants of the types specified in the D-Bus
|
15
|
+
# protocol.
|
16
|
+
module Type
|
17
|
+
# Mapping from type number to name and alignment.
|
18
|
+
TypeMapping = {
|
19
|
+
0 => ["INVALID", nil],
|
20
|
+
"y" => ["BYTE", 1],
|
21
|
+
"b" => ["BOOLEAN", 4],
|
22
|
+
"n" => ["INT16", 2],
|
23
|
+
"q" => ["UINT16", 2],
|
24
|
+
"i" => ["INT32", 4],
|
25
|
+
"u" => ["UINT32", 4],
|
26
|
+
"x" => ["INT64", 8],
|
27
|
+
"t" => ["UINT64", 8],
|
28
|
+
"d" => ["DOUBLE", 8],
|
29
|
+
"r" => ["STRUCT", 8],
|
30
|
+
"a" => ["ARRAY", 4],
|
31
|
+
"v" => ["VARIANT", 1],
|
32
|
+
"o" => ["OBJECT_PATH", 4],
|
33
|
+
"s" => ["STRING", 4],
|
34
|
+
"g" => ["SIGNATURE", 1],
|
35
|
+
"e" => ["DICT_ENTRY", 8],
|
36
|
+
"h" => ["UNIX_FD", 4]
|
37
|
+
}.freeze
|
38
|
+
# Defines the set of constants
|
39
|
+
TypeMapping.each_pair do |key, value|
|
40
|
+
Type.const_set(value.first, key)
|
64
41
|
end
|
65
42
|
|
66
|
-
#
|
67
|
-
|
68
|
-
TypeMapping[@sigtype].last
|
43
|
+
# Exception raised when an unknown/incorrect type is encountered.
|
44
|
+
class SignatureException < Exception
|
69
45
|
end
|
70
46
|
|
71
|
-
#
|
72
|
-
#
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
if
|
83
|
-
raise
|
47
|
+
# = D-Bus type conversion class
|
48
|
+
#
|
49
|
+
# Helper class for representing a D-Bus type.
|
50
|
+
class Type
|
51
|
+
# Returns the signature type number.
|
52
|
+
attr_reader :sigtype
|
53
|
+
# Return contained member types.
|
54
|
+
attr_reader :members
|
55
|
+
|
56
|
+
# Create a new type instance for type number _sigtype_.
|
57
|
+
def initialize(sigtype)
|
58
|
+
if !TypeMapping.keys.member?(sigtype)
|
59
|
+
raise SignatureException, "Unknown key in signature: #{sigtype.chr}"
|
84
60
|
end
|
85
|
-
@sigtype
|
61
|
+
@sigtype = sigtype
|
62
|
+
@members = []
|
86
63
|
end
|
87
|
-
end
|
88
64
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
raise SignatureException
|
65
|
+
# Return the required alignment for the type.
|
66
|
+
def alignment
|
67
|
+
TypeMapping[@sigtype].last
|
93
68
|
end
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
69
|
+
|
70
|
+
# Return a string representation of the type according to the
|
71
|
+
# D-Bus specification.
|
72
|
+
def to_s
|
73
|
+
case @sigtype
|
74
|
+
when STRUCT
|
75
|
+
"(" + @members.collect(&:to_s).join + ")"
|
76
|
+
when ARRAY
|
77
|
+
"a" + child.to_s
|
78
|
+
when DICT_ENTRY
|
79
|
+
"{" + @members.collect(&:to_s).join + "}"
|
80
|
+
else
|
81
|
+
if !TypeMapping.keys.member?(@sigtype)
|
82
|
+
raise NotImplementedError
|
102
83
|
end
|
84
|
+
@sigtype.chr
|
103
85
|
end
|
104
86
|
end
|
105
|
-
@members << a
|
106
|
-
end
|
107
87
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
88
|
+
# Add a new member type _a_.
|
89
|
+
def <<(a)
|
90
|
+
if ![STRUCT, ARRAY, DICT_ENTRY].member?(@sigtype)
|
91
|
+
raise SignatureException
|
92
|
+
end
|
93
|
+
raise SignatureException if @sigtype == ARRAY && !@members.empty?
|
94
|
+
if @sigtype == DICT_ENTRY
|
95
|
+
if @members.size == 2
|
96
|
+
raise SignatureException, "Dict entries have exactly two members"
|
97
|
+
end
|
98
|
+
if @members.empty?
|
99
|
+
if [STRUCT, ARRAY, DICT_ENTRY].member?(a.sigtype)
|
100
|
+
raise SignatureException, "Dict entry keys must be basic types"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
@members << a
|
105
|
+
end
|
112
106
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
s += ": " + @members.inspect
|
107
|
+
# Return the first contained member type.
|
108
|
+
def child
|
109
|
+
@members[0]
|
117
110
|
end
|
118
|
-
s
|
119
|
-
end
|
120
|
-
end # class Type
|
121
111
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
112
|
+
def inspect
|
113
|
+
s = TypeMapping[@sigtype].first
|
114
|
+
if [STRUCT, ARRAY].member?(@sigtype)
|
115
|
+
s += ": " + @members.inspect
|
116
|
+
end
|
117
|
+
s
|
118
|
+
end
|
119
|
+
end # class Type
|
120
|
+
|
121
|
+
# = D-Bus type parser class
|
122
|
+
#
|
123
|
+
# Helper class to parse a type signature in the protocol.
|
124
|
+
class Parser
|
125
|
+
# Create a new parser for the given _signature_.
|
126
|
+
def initialize(signature)
|
127
|
+
@signature = signature
|
128
|
+
@idx = 0
|
129
|
+
end
|
131
130
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
131
|
+
# Returns the next character from the signature.
|
132
|
+
def nextchar
|
133
|
+
c = @signature[@idx]
|
134
|
+
@idx += 1
|
135
|
+
c
|
136
|
+
end
|
138
137
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
138
|
+
# Parse one character _c_ of the signature.
|
139
|
+
def parse_one(c)
|
140
|
+
res = nil
|
141
|
+
case c
|
142
|
+
when "a"
|
143
|
+
res = Type.new(ARRAY)
|
144
|
+
c = nextchar
|
145
|
+
raise SignatureException, "Parse error in #{@signature}" if c.nil?
|
146
|
+
child = parse_one(c)
|
147
|
+
res << child
|
148
|
+
when "("
|
149
|
+
res = Type.new(STRUCT)
|
150
|
+
while (c = nextchar) && c != ")"
|
151
|
+
res << parse_one(c)
|
152
|
+
end
|
153
|
+
raise SignatureException, "Parse error in #{@signature}" if c.nil?
|
154
|
+
when "{"
|
155
|
+
res = Type.new(DICT_ENTRY)
|
156
|
+
while (c = nextchar) && c != "}"
|
157
|
+
res << parse_one(c)
|
158
|
+
end
|
159
|
+
raise SignatureException, "Parse error in #{@signature}" if c.nil?
|
160
|
+
else
|
161
|
+
res = Type.new(c)
|
159
162
|
end
|
160
|
-
|
161
|
-
else
|
162
|
-
res = Type.new(c)
|
163
|
+
res
|
163
164
|
end
|
164
|
-
res
|
165
|
-
end
|
166
165
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
166
|
+
# Parse the entire signature, return a DBus::Type object.
|
167
|
+
def parse
|
168
|
+
@idx = 0
|
169
|
+
ret = []
|
170
|
+
while (c = nextchar)
|
171
|
+
ret << parse_one(c)
|
172
|
+
end
|
173
|
+
ret
|
173
174
|
end
|
174
|
-
|
175
|
-
|
176
|
-
end # class Parser
|
177
|
-
end # module Type
|
178
|
-
|
179
|
-
# shortcuts
|
175
|
+
end # class Parser
|
176
|
+
end # module Type
|
180
177
|
|
181
|
-
#
|
182
|
-
def type(string_type)
|
183
|
-
Type::Parser.new(string_type).parse[0]
|
184
|
-
end
|
185
|
-
module_function :type
|
178
|
+
# shortcuts
|
186
179
|
|
187
|
-
#
|
188
|
-
def
|
189
|
-
|
190
|
-
end
|
191
|
-
module_function :
|
180
|
+
# Parse a String to a DBus::Type::Type
|
181
|
+
def type(string_type)
|
182
|
+
Type::Parser.new(string_type).parse[0]
|
183
|
+
end
|
184
|
+
module_function :type
|
192
185
|
|
186
|
+
# Make an explicit [Type, value] pair
|
187
|
+
def variant(string_type, value)
|
188
|
+
[type(string_type), value]
|
189
|
+
end
|
190
|
+
module_function :variant
|
193
191
|
end # module DBus
|
data/lib/dbus/xml.rb
CHANGED
@@ -9,10 +9,10 @@
|
|
9
9
|
# License, version 2.1 as published by the Free Software Foundation.
|
10
10
|
# See the file "COPYING" for the exact licensing terms.
|
11
11
|
|
12
|
-
# TODO check if it is slow, make replaceable
|
13
|
-
require
|
12
|
+
# TODO: check if it is slow, make replaceable
|
13
|
+
require "rexml/document"
|
14
14
|
begin
|
15
|
-
require
|
15
|
+
require "nokogiri"
|
16
16
|
rescue LoadError
|
17
17
|
end
|
18
18
|
|
@@ -32,16 +32,18 @@ module DBus
|
|
32
32
|
|
33
33
|
class AbstractXML
|
34
34
|
def self.have_nokogiri?
|
35
|
-
Object.const_defined?(
|
35
|
+
Object.const_defined?("Nokogiri")
|
36
36
|
end
|
37
37
|
class Node
|
38
38
|
def initialize(node)
|
39
39
|
@node = node
|
40
40
|
end
|
41
|
+
|
41
42
|
# required methods
|
42
43
|
# returns node attribute value
|
43
44
|
def [](key)
|
44
45
|
end
|
46
|
+
|
45
47
|
# yields child nodes which match xpath of type AbstractXML::Node
|
46
48
|
def each(xpath)
|
47
49
|
end
|
@@ -50,6 +52,7 @@ module DBus
|
|
50
52
|
# initialize parser with xml string
|
51
53
|
def initialize(xml)
|
52
54
|
end
|
55
|
+
|
53
56
|
# yields nodes which match xpath of type AbstractXML::Node
|
54
57
|
def each(xpath)
|
55
58
|
end
|
@@ -60,6 +63,7 @@ module DBus
|
|
60
63
|
def [](key)
|
61
64
|
@node[key]
|
62
65
|
end
|
66
|
+
|
63
67
|
def each(path, &block)
|
64
68
|
@node.search(path).each { |node| block.call NokogiriNode.new(node) }
|
65
69
|
end
|
@@ -67,6 +71,7 @@ module DBus
|
|
67
71
|
def initialize(xml)
|
68
72
|
@doc = Nokogiri.XML(xml)
|
69
73
|
end
|
74
|
+
|
70
75
|
def each(path, &block)
|
71
76
|
@doc.search("//#{path}").each { |node| block.call NokogiriNode.new(node) }
|
72
77
|
end
|
@@ -77,6 +82,7 @@ module DBus
|
|
77
82
|
def [](key)
|
78
83
|
@node.attributes[key]
|
79
84
|
end
|
85
|
+
|
80
86
|
def each(path, &block)
|
81
87
|
@node.elements.each(path) { |node| block.call REXMLNode.new(node) }
|
82
88
|
end
|
@@ -84,18 +90,20 @@ module DBus
|
|
84
90
|
def initialize(xml)
|
85
91
|
@doc = REXML::Document.new(xml)
|
86
92
|
end
|
93
|
+
|
87
94
|
def each(path, &block)
|
88
95
|
@doc.elements.each(path) { |node| block.call REXMLNode.new(node) }
|
89
96
|
end
|
90
97
|
end
|
91
98
|
|
92
|
-
if AbstractXML.have_nokogiri?
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
99
|
+
@backend = if AbstractXML.have_nokogiri?
|
100
|
+
NokogiriParser
|
101
|
+
else
|
102
|
+
REXMLParser
|
103
|
+
end
|
97
104
|
|
98
|
-
# return
|
105
|
+
# @return [Array(Array<Interface>,Array<String>)]
|
106
|
+
# a pair: [list of Interfaces, list of direct subnode names]
|
99
107
|
def parse
|
100
108
|
# Using a Hash instead of a list helps merge split-up interfaces,
|
101
109
|
# a quirk observed in ModemManager (I#41).
|
@@ -105,7 +113,6 @@ module DBus
|
|
105
113
|
subnodes = []
|
106
114
|
t = Time.now
|
107
115
|
|
108
|
-
|
109
116
|
d = IntrospectXMLParser.backend.new(@xml)
|
110
117
|
d.each("node/node") do |e|
|
111
118
|
subnodes << e["name"]
|
@@ -140,17 +147,17 @@ module DBus
|
|
140
147
|
name = ae["name"]
|
141
148
|
dir = ae["direction"]
|
142
149
|
sig = ae["type"]
|
143
|
-
|
150
|
+
if m.is_a?(DBus::Signal)
|
144
151
|
# Direction can only be "out", ignore it
|
145
152
|
m.add_fparam(name, sig)
|
146
|
-
|
153
|
+
elsif m.is_a?(DBus::Method)
|
147
154
|
case dir
|
148
155
|
# This is a method, so dir defaults to "in"
|
149
156
|
when "in", nil
|
150
157
|
m.add_fparam(name, sig)
|
151
158
|
when "out"
|
152
|
-
|
153
|
-
|
159
|
+
m.add_return(name, sig)
|
160
|
+
end
|
154
161
|
else
|
155
162
|
raise NotImplementedError, dir
|
156
163
|
end
|
@@ -158,4 +165,3 @@ module DBus
|
|
158
165
|
end
|
159
166
|
end # class IntrospectXMLParser
|
160
167
|
end # module DBus
|
161
|
-
|