Skip to content

Commit 6da0797

Browse files
committed
Automatically reconnect to NetworkManager
When NetworkManager restarts, they will have different unique object names on the system bus. Trying to the old objects will fail, so when that happens we can simply reconnect. To activate automatic reconnection, call NetworkManager.NetworkManager.auto_reconnect after setting up your mainloop.
1 parent 535a846 commit 6da0797

File tree

3 files changed

+38
-2
lines changed

3 files changed

+38
-2
lines changed

NetworkManager.py

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import socket
1111
import struct
1212
import sys
13+
import weakref
1314

1415
PY3 = sys.version_info >= (3,0)
1516
if PY3:
@@ -26,17 +27,21 @@ def debug(msg, data):
2627
except:
2728
debug = lambda *args: None
2829

30+
auto_reconnect = True
31+
registry = []
32+
2933
class NMDbusInterface(object):
3034
bus = dbus.SystemBus()
3135
dbus_service = 'org.freedesktop.NetworkManager'
3236
object_path = None
3337

3438
def __init__(self, object_path=None):
39+
global registry
3540
if isinstance(object_path, NMDbusInterface):
3641
object_path = object_path.object_path
3742
self.object_path = self.object_path or object_path
38-
self.proxy = self.bus.get_object(self.dbus_service, self.object_path)
39-
self.interface = dbus.Interface(self.proxy, self.interface_name)
43+
self.signals = []
44+
self.connect()
4045

4146
properties = []
4247
try:
@@ -50,6 +55,25 @@ def __init__(self, object_path=None):
5055
if not hasattr(self.__class__, p):
5156
setattr(self.__class__, p, self._make_property(p))
5257

58+
registry.append(weakref.proxy(self))
59+
60+
def connect(self):
61+
self.proxy = self.bus.get_object(self.dbus_service, self.object_path)
62+
self.interface = dbus.Interface(self.proxy, self.interface_name)
63+
signals = self.signals[:]
64+
self.signals = []
65+
for signal, handler, args, kwargs in signals:
66+
self.connect_to_signal(signal, handler, *args, **kwargs)
67+
68+
def reconnect(self, name, old, new):
69+
if str(new) == "" or str(name) != 'org.freedesktop.NetworkManager':
70+
return
71+
for obj in registry:
72+
try:
73+
obj.connect()
74+
except ReferenceError:
75+
pass
76+
5377
def _make_property(self, name):
5478
def get_func(self):
5579
data = self.proxy.Get(self.interface_name, name, dbus_interface='org.freedesktop.DBus.Properties')
@@ -121,6 +145,7 @@ def proxy_call(*args, **kwargs):
121145
return proxy_call
122146

123147
def connect_to_signal(self, signal, handler, *args, **kwargs):
148+
self.signals.append((signal, handler, args, kwargs))
124149
def helper(*args, **kwargs):
125150
args = [self.unwrap(x) for x in args]
126151
handler(*args, **kwargs)
@@ -138,6 +163,11 @@ class NetworkManager(NMDbusInterface):
138163
interface_name = 'org.freedesktop.NetworkManager'
139164
object_path = '/org/freedesktop/NetworkManager'
140165

166+
def auto_reconnect(self):
167+
global auto_reconnect
168+
auto_reconnect = True
169+
self.bus.add_signal_receiver(self.reconnect, 'NameOwnerChanged', 'org.freedesktop.DBus')
170+
141171
def preprocess(self, name, args, kwargs):
142172
if name in ('AddConnection', 'Update', 'UpdateUnsaved', 'AddAndActivateConnection'):
143173
settings = copy.deepcopy(args[0])

docs/index.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ This class represents the :data:`org.freedesktop.NetworkManager` interface.
8282
Note that :data:`NetworkManager.NetworkManager` actually is the singleton
8383
instance of this class.
8484

85+
.. method:: auto_reconnect
86+
87+
Call this method to automatically update D-Bus paths and reconnect signals when
88+
NetworkManager restarts.
89+
8590
.. class:: Settings
8691

8792
This class represents the :data:`org.freedesktop.NetworkManager.Settings`

examples/listener.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import dbus.mainloop.glib; dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
66
from gi.repository import GObject
77
import NetworkManager
8+
NetworkManager.NetworkManager.auto_reconnect()
89

910
d_args = ('sender', 'destination', 'interface', 'member', 'path')
1011
d_args = dict([(x + '_keyword', 'd_' + x) for x in d_args])

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy