ruby-dbus 0.23.0.beta2 → 0.23.1
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 +10 -0
- data/VERSION +1 -1
- data/examples/utils/listnames.rb +9 -1
- data/lib/dbus/bus.rb +92 -5
- data/lib/dbus/connection.rb +21 -8
- data/lib/dbus/object.rb +24 -6
- data/spec/bus_connection_spec.rb +20 -7
- data/spec/mock-service/spaghetti-monster.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2465a9a90d0b4837640d475566edfde23aee4dc1d7d439d76d1f861b71f13033
|
4
|
+
data.tar.gz: 906288ee9d180ff0bfd4e53f45982040f240da983e23c818acd91d449d9f7f05
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f2939e81cff3f5db2dd768f9e0f1c04159b0285501c73840f14dd8f61ad9f539fbbbf35d7e408cca11847dcd31848131c1c4df69705798860f03e4255f02dedf
|
7
|
+
data.tar.gz: 553f1d4c97a284371d7a10a0f439a40d2861ff8c40c2318c09f6f818f5911644db05142dc7a8d5e377dac355ddc389fcc9858647a568184e8598fd3d3bb71154
|
data/NEWS.md
CHANGED
@@ -2,6 +2,16 @@
|
|
2
2
|
|
3
3
|
## Unreleased
|
4
4
|
|
5
|
+
## Ruby D-Bus 0.23.1 - 2023-10-03
|
6
|
+
|
7
|
+
API:
|
8
|
+
* Add DBus::Object.dbus_reader_attr_accessor to declare a common use case
|
9
|
+
with a single call ([#140][]).
|
10
|
+
* BusConnection#request_name defaults to the simple use case: single owner
|
11
|
+
without queuing, failing fast; documented the complex use cases.
|
12
|
+
|
13
|
+
[#140]: https://github.com/mvidner/ruby-dbus/pull/140
|
14
|
+
|
5
15
|
## Ruby D-Bus 0.23.0.beta2 - 2023-06-23
|
6
16
|
|
7
17
|
License:
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.23.
|
1
|
+
0.23.1
|
data/examples/utils/listnames.rb
CHANGED
@@ -8,4 +8,12 @@ d = if ARGV.member?("--system")
|
|
8
8
|
else
|
9
9
|
DBus::SessionBus.instance
|
10
10
|
end
|
11
|
-
d.proxy.ListNames[0].each
|
11
|
+
d.proxy.ListNames[0].each do |n|
|
12
|
+
puts "\t#{n}"
|
13
|
+
qns = d.proxy.ListQueuedOwners(n)[0]
|
14
|
+
next if qns.size == 1 && qns.first == n
|
15
|
+
|
16
|
+
qns.each do |qn|
|
17
|
+
puts "\t\t#{qn}"
|
18
|
+
end
|
19
|
+
end
|
data/lib/dbus/bus.rb
CHANGED
@@ -55,20 +55,107 @@ module DBus
|
|
55
55
|
@proxy
|
56
56
|
end
|
57
57
|
|
58
|
+
# Request a well-known name so that clients can find us.
|
59
|
+
# @note Parameters other than *name* are advanced, you probably don't need them.
|
60
|
+
#
|
61
|
+
# With no boolean flags, running a second instance of a program that calls `request_name`
|
62
|
+
# will result in the second one failing, which this library translates to an exception.
|
63
|
+
# If you want the second instance to take over, you need both
|
64
|
+
# `allow_replacement: true` and `replace_existing: true.`
|
65
|
+
#
|
58
66
|
# @param name [BusName] the requested name
|
59
|
-
# @param
|
60
|
-
#
|
61
|
-
# @
|
67
|
+
# @param replace_existing [Boolean]
|
68
|
+
# Replace an existing owner of the name, if that owner set *allow_replacement*.
|
69
|
+
# @param allow_replacement [Boolean]
|
70
|
+
# Other connections that specify *replace_existing* will be able to take
|
71
|
+
# the name from us. We will get {#on_name_lost NameLost}. If we specified *queue*
|
72
|
+
# we may get the name again, with {#on_name_acquired NameAcquired}.
|
73
|
+
# @param queue [Boolean]
|
74
|
+
# Affects the behavior when the bus denies the name (sooner or later).
|
75
|
+
# - If `false` (default), it is recommended to let the `NameRequestError` fall through and end your program.
|
76
|
+
# - If `true`, you should `rescue` the `NameRequestError` and set up
|
77
|
+
# {#on_name_acquired NameAcquired} and {#on_name_lost NameLost} handlers.
|
78
|
+
# Meanwhile, the bus will put us in a queue waiting for *name* (this is the "sooner" case).
|
79
|
+
# Also, if we had `allow_replacement: true`, another connection can cause us
|
80
|
+
# to lose the name. We will be moved back to the queue, waiting for when the other owners give up
|
81
|
+
# (the "later" case).
|
82
|
+
# @param flags [Integer,nil]
|
83
|
+
# If specified, overrides the boolean parameters.
|
84
|
+
# Use a bitwise sum `|` of:
|
85
|
+
# - NAME_FLAG_ALLOW_REPLACEMENT
|
86
|
+
# - NAME_FLAG_REPLACE_EXISTING
|
87
|
+
# - NAME_FLAG_DO_NOT_QUEUE
|
88
|
+
# Note that `0` implies `queue: true`.
|
89
|
+
#
|
90
|
+
# @return [REQUEST_NAME_REPLY_PRIMARY_OWNER,REQUEST_NAME_REPLY_ALREADY_OWNER] on success
|
91
|
+
# @raise [NameRequestError] with #error_code REQUEST_NAME_REPLY_EXISTS or REQUEST_NAME_REPLY_IN_QUEUE, on failure
|
92
|
+
# @raise DBus::Error another way to fail is being prohibited to own the name
|
93
|
+
# which is the default on the system bus
|
94
|
+
#
|
95
|
+
# @see https://dbus.freedesktop.org/doc/dbus-specification.html#bus-messages-request-name
|
96
|
+
#
|
97
|
+
# @example Simple usage
|
62
98
|
# bus = DBus.session_bus
|
63
99
|
# bus.object_server.export(DBus::Object.new("/org/example/Test"))
|
64
100
|
# bus.request_name("org.example.Test")
|
65
|
-
#
|
66
|
-
|
101
|
+
# # main loop
|
102
|
+
#
|
103
|
+
# @example Second instance taking over
|
104
|
+
# bus = DBus.session_bus
|
105
|
+
# bus.object_server.export(DBus::Object.new("/org/example/Test"))
|
106
|
+
# bus.on_name_lost { exit }
|
107
|
+
# bus.request_name("org.example.Test", allow_replacement: true, replace_existing: true)
|
108
|
+
# # main loop
|
109
|
+
#
|
110
|
+
# @example Second instance waiting for its turn
|
111
|
+
# bus = DBus.session_bus
|
112
|
+
# bus.object_server.export(DBus::Object.new("/org/example/Test"))
|
113
|
+
# bus.on_name_acquired { @owner = true }
|
114
|
+
# begin
|
115
|
+
# bus.request_name("org.example.Test", queue: true)
|
116
|
+
# rescue DBus::Connection::NameRequestError => e
|
117
|
+
# @owner = false
|
118
|
+
# end
|
119
|
+
# # main loop
|
120
|
+
def request_name(name,
|
121
|
+
allow_replacement: false,
|
122
|
+
replace_existing: false,
|
123
|
+
queue: false,
|
124
|
+
flags: nil)
|
125
|
+
if flags.nil?
|
126
|
+
flags = (allow_replacement ? NAME_FLAG_ALLOW_REPLACEMENT : 0) |
|
127
|
+
(replace_existing ? NAME_FLAG_REPLACE_EXISTING : 0) |
|
128
|
+
(queue ? 0 : NAME_FLAG_DO_NOT_QUEUE)
|
129
|
+
end
|
67
130
|
name = BusName.new(name)
|
68
131
|
r = proxy.RequestName(name, flags).first
|
69
132
|
handle_return_of_request_name(r, name)
|
70
133
|
end
|
71
134
|
|
135
|
+
# The caller has released his claim on the given name.
|
136
|
+
# Either the caller was the primary owner of the name, and the name is now unused
|
137
|
+
# or taken by somebody waiting in the queue for the name,
|
138
|
+
# or the caller was waiting in the queue for the name and has now been removed from the queue.
|
139
|
+
RELEASE_NAME_REPLY_RELEASED = 1
|
140
|
+
# The given name does not exist on this bus.
|
141
|
+
RELEASE_NAME_REPLY_NON_EXISTENT = 2
|
142
|
+
# The caller was not the primary owner of this name, and was also not waiting in the queue to own this name.
|
143
|
+
RELEASE_NAME_REPLY_NOT_OWNER = 3
|
144
|
+
|
145
|
+
# @param name [BusName] the name to release
|
146
|
+
def release_name(name)
|
147
|
+
name = BusName.new(name)
|
148
|
+
proxy.ReleaseName(name).first
|
149
|
+
end
|
150
|
+
|
151
|
+
def on_name_acquired(&handler)
|
152
|
+
proxy.on_signal("NameAcquired", &handler)
|
153
|
+
end
|
154
|
+
|
155
|
+
def on_name_lost(&handler)
|
156
|
+
proxy.on_signal("NameLost", &handler)
|
157
|
+
end
|
158
|
+
|
72
159
|
# Asks bus to send us messages matching mr, and execute slot when
|
73
160
|
# received
|
74
161
|
# @param match_rule [MatchRule,#to_s]
|
data/lib/dbus/connection.rb
CHANGED
@@ -153,17 +153,30 @@ module DBus
|
|
153
153
|
|
154
154
|
# Exception raised when a service name is requested that is not available.
|
155
155
|
class NameRequestError < Exception
|
156
|
+
# @return [Integer] one of
|
157
|
+
# REQUEST_NAME_REPLY_IN_QUEUE
|
158
|
+
# REQUEST_NAME_REPLY_EXISTS
|
159
|
+
attr_reader :error_code
|
160
|
+
|
161
|
+
def initialize(error_code)
|
162
|
+
@error_code = error_code
|
163
|
+
super()
|
164
|
+
end
|
156
165
|
end
|
157
166
|
|
167
|
+
# In case RequestName did not succeed, raise an exception but first ask the bus who owns the name instead of us
|
168
|
+
# @param ret [Integer] what RequestName returned
|
169
|
+
# @param name Name that was requested
|
170
|
+
# @return [REQUEST_NAME_REPLY_PRIMARY_OWNER,REQUEST_NAME_REPLY_ALREADY_OWNER] on success
|
171
|
+
# @raise [NameRequestError] with #error_code REQUEST_NAME_REPLY_EXISTS or REQUEST_NAME_REPLY_IN_QUEUE, on failure
|
172
|
+
# @api private
|
158
173
|
def handle_return_of_request_name(ret, name)
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
end
|
166
|
-
raise NameRequestError, "Could not request #{name}, #{details}" unless ret == REQUEST_NAME_REPLY_PRIMARY_OWNER
|
174
|
+
if [REQUEST_NAME_REPLY_EXISTS, REQUEST_NAME_REPLY_IN_QUEUE].include?(ret)
|
175
|
+
other = proxy.GetNameOwner(name).first
|
176
|
+
other_creds = proxy.GetConnectionCredentials(other).first
|
177
|
+
message = "Could not request #{name}, already owned by #{other}, #{other_creds.inspect}"
|
178
|
+
raise NameRequestError.new(ret), message
|
179
|
+
end
|
167
180
|
|
168
181
|
ret
|
169
182
|
end
|
data/lib/dbus/object.rb
CHANGED
@@ -156,18 +156,32 @@ module DBus
|
|
156
156
|
dbus_accessor(ruby_name, type, dbus_name: dbus_name, emits_changed_signal: emits_changed_signal)
|
157
157
|
end
|
158
158
|
|
159
|
+
# A read-only property accessing a read-write instance variable.
|
160
|
+
# A combination of `attr_accessor` and {.dbus_reader}.
|
161
|
+
#
|
162
|
+
# @param (see .dbus_attr_accessor)
|
163
|
+
# @return (see .dbus_attr_accessor)
|
164
|
+
def self.dbus_reader_attr_accessor(ruby_name, type, dbus_name: nil, emits_changed_signal: nil)
|
165
|
+
attr_accessor(ruby_name)
|
166
|
+
|
167
|
+
dbus_reader(ruby_name, type, dbus_name: dbus_name, emits_changed_signal: emits_changed_signal)
|
168
|
+
end
|
169
|
+
|
159
170
|
# A read-only property accessing an instance variable.
|
160
171
|
# A combination of `attr_reader` and {.dbus_reader}.
|
161
172
|
#
|
173
|
+
# You may be instead looking for a variant which is read-write from the Ruby side:
|
174
|
+
# {.dbus_reader_attr_accessor}.
|
175
|
+
#
|
162
176
|
# Whenever the property value gets changed from "inside" the object,
|
163
177
|
# you should emit the `PropertiesChanged` signal by calling
|
164
178
|
# {#dbus_properties_changed}.
|
165
179
|
#
|
166
|
-
#
|
180
|
+
# dbus_properties_changed(interface_name, {dbus_name.to_s => value}, [])
|
167
181
|
#
|
168
182
|
# or, omitting the value in the signal,
|
169
183
|
#
|
170
|
-
#
|
184
|
+
# dbus_properties_changed(interface_name, {}, [dbus_name.to_s])
|
171
185
|
#
|
172
186
|
# @param (see .dbus_attr_accessor)
|
173
187
|
# @return (see .dbus_attr_accessor)
|
@@ -213,18 +227,22 @@ module DBus
|
|
213
227
|
# implement it with a read-write attr_accessor. In that case this method
|
214
228
|
# uses {.dbus_watcher} to set up the PropertiesChanged signal.
|
215
229
|
#
|
216
|
-
#
|
217
|
-
#
|
230
|
+
# attr_accessor :foo_bar
|
231
|
+
# dbus_reader :foo_bar, "s"
|
232
|
+
#
|
233
|
+
# The above two declarations have a shorthand:
|
234
|
+
#
|
235
|
+
# dbus_reader_attr_accessor :foo_bar, "s"
|
218
236
|
#
|
219
237
|
# If the property value should change by other means than its attr_writer,
|
220
238
|
# you should emit the `PropertiesChanged` signal by calling
|
221
239
|
# {#dbus_properties_changed}.
|
222
240
|
#
|
223
|
-
#
|
241
|
+
# dbus_properties_changed(interface_name, {dbus_name.to_s => value}, [])
|
224
242
|
#
|
225
243
|
# or, omitting the value in the signal,
|
226
244
|
#
|
227
|
-
#
|
245
|
+
# dbus_properties_changed(interface_name, {}, [dbus_name.to_s])
|
228
246
|
#
|
229
247
|
# @param (see .dbus_attr_accessor)
|
230
248
|
# @return (see .dbus_attr_accessor)
|
data/spec/bus_connection_spec.rb
CHANGED
@@ -21,7 +21,6 @@ describe DBus::BusConnection do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
context "when the name is taken already", tag_service: true do
|
24
|
-
# formerly it returned Service, now ObjectServer takes its role
|
25
24
|
it "raises NameRequestError... too late" do
|
26
25
|
name = "org.ruby.service"
|
27
26
|
expect do
|
@@ -50,21 +49,35 @@ describe DBus::BusConnection do
|
|
50
49
|
|
51
50
|
describe "#request_name", tag_bus: true do
|
52
51
|
context "when the name request succeeds" do
|
53
|
-
it "returns
|
52
|
+
it "returns a success code" do
|
54
53
|
name = "org.rubygems.ruby_dbus.RequestNameTest"
|
55
|
-
expect
|
56
|
-
|
54
|
+
expect(bus.request_name(name)).to eq DBus::Connection::REQUEST_NAME_REPLY_PRIMARY_OWNER
|
55
|
+
# second time, considered also a success
|
56
|
+
expect(bus.request_name(name)).to eq DBus::Connection::REQUEST_NAME_REPLY_ALREADY_OWNER
|
57
|
+
bus.release_name(name)
|
57
58
|
end
|
58
59
|
end
|
59
60
|
|
60
61
|
context "when the name is taken already", tag_service: true do
|
61
|
-
# formerly it returned Service, now ObjectServer takes its role
|
62
62
|
it "raises NameRequestError" do
|
63
63
|
name = "org.ruby.service"
|
64
64
|
expect do
|
65
|
-
|
66
|
-
|
65
|
+
bus.request_name(name)
|
66
|
+
end.to raise_error(DBus::Connection::NameRequestError)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "when the name is taken already but we request queuing", tag_service: true do
|
71
|
+
it "raises NameRequestError but we are queued" do
|
72
|
+
name = "org.ruby.service"
|
73
|
+
owning = nil
|
74
|
+
# TODO: we do not expect the handlers to run
|
75
|
+
bus.on_name_acquired { owning = true }
|
76
|
+
bus.on_name_lost { owning = false }
|
77
|
+
expect do
|
78
|
+
bus.request_name(name, queue: true)
|
67
79
|
end.to raise_error(DBus::Connection::NameRequestError)
|
80
|
+
expect(bus.release_name(name)).to eq DBus::BusConnection::RELEASE_NAME_REPLY_RELEASED
|
68
81
|
end
|
69
82
|
end
|
70
83
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-dbus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.23.
|
4
|
+
version: 0.23.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ruby DBus Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-10-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rexml
|
@@ -235,9 +235,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
235
235
|
version: 2.4.0
|
236
236
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
237
237
|
requirements:
|
238
|
-
- - "
|
238
|
+
- - ">="
|
239
239
|
- !ruby/object:Gem::Version
|
240
|
-
version:
|
240
|
+
version: '0'
|
241
241
|
requirements: []
|
242
242
|
rubygems_version: 3.3.26
|
243
243
|
signing_key:
|