3
The module provides a client to the PackageKit DBus interface. It allows to
4
perform basic package manipulation tasks in a cross distribution way, e.g.
5
to search for packages, install packages or codecs.
7
# Copyright (C) 2008 Canonical Ltd.
8
# Copyright (C) 2008 Aidan Skinner <aidan@skinner.me.uk>
9
# Copyright (C) 2008 Martin Pitt <martin.pitt@ubuntu.com>
10
# Copyright (C) 2008 Tim Lauridsen <timlau@fedoraproject.org>
11
# Copyright (C) 2008-2009 Sebastian Heinlein <devel@glatzor.de>
13
# Licensed under the GNU General Public License Version 2
15
# This program is free software; you can redistribute it and/or modify
16
# it under the terms of the GNU General Public License as published by
17
# the Free Software Foundation; either version 2 of the License, or
18
# (at your option) any later version.
20
# This program is distributed in the hope that it will be useful,
21
# but WITHOUT ANY WARRANTY; without even the implied warranty of
22
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
# GNU General Public License for more details.
25
# You should have received a copy of the GNU General Public License
26
# along with this program; if not, write to the Free Software
27
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34
import dbus.mainloop.glib
35
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
41
from errors import convert_dbus_exception, TransactionFailed
43
__all__ = ("AptTransaction", "AptClient", "get_transaction", "get_daemon")
46
class MemoizedTransaction(type):
48
"""Metaclass to cache transactions."""
50
cache = weakref.WeakValueDictionary()
52
def __call__(mcs, *args):
57
mcs.cache[tid] = value = \
58
super(MemoizedTransaction, mcs).__call__(*args)
62
class MemoizedMixIn(MemoizedTransaction, gobject.GObjectMeta):
64
"""Helper meta class for merging"""
67
class AptTransaction(gobject.GObject):
69
"""Represents an aptdaemon transaction. It allows asynchronous and
70
synchronous processing.
73
__metaclass__ = MemoizedMixIn
75
__gsignals__ = {"finished": (gobject.SIGNAL_RUN_FIRST,
77
(gobject.TYPE_STRING,)),
78
"dependencies-changed": (gobject.SIGNAL_RUN_FIRST,
80
(gobject.TYPE_PYOBJECT,
81
gobject.TYPE_PYOBJECT,
82
gobject.TYPE_PYOBJECT,
83
gobject.TYPE_PYOBJECT,
84
gobject.TYPE_PYOBJECT,
85
gobject.TYPE_PYOBJECT,
86
gobject.TYPE_PYOBJECT)),
87
"download-changed": (gobject.SIGNAL_RUN_FIRST,
90
"space-changed": (gobject.SIGNAL_RUN_FIRST,
93
"error": (gobject.SIGNAL_RUN_FIRST,
95
(gobject.TYPE_STRING, gobject.TYPE_STRING)),
96
"role-changed": (gobject.SIGNAL_RUN_FIRST,
98
(gobject.TYPE_STRING,)),
99
"terminal-attached-changed": (gobject.SIGNAL_RUN_FIRST,
101
(gobject.TYPE_BOOLEAN,)),
102
"cancellable-changed": (gobject.SIGNAL_RUN_FIRST,
104
(gobject.TYPE_BOOLEAN,)),
105
"meta-data-changed": (gobject.SIGNAL_RUN_FIRST,
107
(gobject.TYPE_PYOBJECT,)),
108
"status-changed": (gobject.SIGNAL_RUN_FIRST,
110
(gobject.TYPE_STRING,)),
111
"status-details-changed": (gobject.SIGNAL_RUN_FIRST,
113
(gobject.TYPE_STRING,)),
114
"progress-changed": (gobject.SIGNAL_RUN_FIRST,
116
(gobject.TYPE_INT,)),
117
"progress-details-changed": (gobject.SIGNAL_RUN_FIRST,
119
(gobject.TYPE_INT, gobject.TYPE_INT,
120
gobject.TYPE_INT, gobject.TYPE_INT,
121
gobject.TYPE_INT, gobject.TYPE_INT)),
122
"progress-download-changed": (gobject.SIGNAL_RUN_FIRST,
124
(gobject.TYPE_STRING,
129
gobject.TYPE_STRING)),
130
"packages-changed": (gobject.SIGNAL_RUN_FIRST,
132
(gobject.TYPE_PYOBJECT,
133
gobject.TYPE_PYOBJECT,
134
gobject.TYPE_PYOBJECT,
135
gobject.TYPE_PYOBJECT,
136
gobject.TYPE_PYOBJECT)),
137
"paused": (gobject.SIGNAL_RUN_FIRST,
140
"resumed": (gobject.SIGNAL_RUN_FIRST,
143
"allow-unauthenticated-changed": (gobject.SIGNAL_RUN_FIRST,
145
(gobject.TYPE_BOOLEAN,)),
146
"remove-obsoleted-depends-changed": (gobject.SIGNAL_RUN_FIRST,
148
(gobject.TYPE_BOOLEAN,)),
149
"locale-changed": (gobject.SIGNAL_RUN_FIRST,
151
(gobject.TYPE_STRING,)),
152
"terminal-changed": (gobject.SIGNAL_RUN_FIRST,
154
(gobject.TYPE_STRING,)),
155
"debconf-socket-changed": (gobject.SIGNAL_RUN_FIRST,
157
(gobject.TYPE_STRING,)),
158
"http-proxy-changed": (gobject.SIGNAL_RUN_FIRST,
160
(gobject.TYPE_STRING,)),
161
"medium-required": (gobject.SIGNAL_RUN_FIRST,
163
(gobject.TYPE_STRING,
164
gobject.TYPE_STRING)),
165
"config-file-conflict": (gobject.SIGNAL_RUN_FIRST,
167
(gobject.TYPE_STRING,
168
gobject.TYPE_STRING)),
171
def __init__(self, tid, bus=None):
172
gobject.GObject.__init__(self)
174
self.role = enums.ROLE_UNSET
176
self.error_code = None
177
self.error_details = None
178
self.exit = enums.EXIT_UNFINISHED
179
self.cancellable = False
180
self.term_attached = False
181
self.required_medium = None
182
self.config_file_conflict = None
184
self.status_details = ""
187
self.http_proxy = None
188
self.dependencies = [[], [], [], [], [], [], []]
189
self.packages = [[], [], [], [], []]
191
self.remove_obsoleted_depends = False
198
self._debconf_helper = None
199
# Connect the signal handlers to the DBus iface
201
bus = dbus.SystemBus()
202
self._proxy = bus.get_object("org.debian.apt", tid)
203
self._iface = dbus.Interface(self._proxy, "org.debian.apt.transaction")
204
# Watch for a crashed daemon which orphaned the dbus object
205
self._owner_watcher = bus.watch_name_owner("org.debian.apt",
206
self._on_name_owner_changed)
208
self._signal_matcher = \
209
self._iface.connect_to_signal("PropertyChanged",
210
self._on_property_changed,
213
def _on_name_owner_changed(self, connection):
214
"""Fail the transaction if the daemon died."""
215
if connection == "" and self.exit == enums.EXIT_UNFINISHED:
216
self._on_property_changed("Error", (enums.ERROR_DAEMON_DIED,
217
"It seems that the daemon "
219
self._on_property_changed("Cancellable", False)
220
self._on_property_changed("TerminalAttached", False)
221
self._on_property_changed("ExitState", enums.EXIT_FAILED)
223
def _on_property_changed(self, property_name, value):
224
"""Callback for the PropertyChanged signal."""
225
if property_name == "TerminalAttached":
226
self.term_attached = value
227
self.emit("terminal-attached-changed", value)
228
elif property_name == "Cancellable":
229
self.cancellable = value
230
self.emit("cancellable-changed", value)
231
elif property_name == "DebconfSocket":
232
self.emit("debconf-socket-changed", value)
233
elif property_name == "RemoveObsoletedDepends":
234
self.emit("remove-obsoleted-depends-changed", value)
235
self.remove_obsoleted_depends = value
236
elif property_name == "AllowUnauthenticated":
237
self.emit("allow-unauthenticated-changed", value)
238
elif property_name == "Terminal":
239
self.emit("terminal-changed", value)
240
elif property_name == "Dependencies":
241
self.dependencies = value
242
self.emit("dependencies-changed", *value)
243
elif property_name == "Packages":
244
self.packages = value
245
self.emit("packages-changed", *value)
246
elif property_name == "Locale":
248
self.emit("locale-changed", value)
249
elif property_name == "Role":
251
self.emit("role-changed", value)
252
elif property_name == "Status":
254
self.emit("status-changed", value)
255
elif property_name == "StatusDetails":
256
self.status_details = value
257
self.emit("status-details-changed", value)
258
elif property_name == "ProgressDownload":
259
uri, status, desc, size, download, msg = value
261
self.downloads[uri] = (status, desc, size, download, msg)
262
self.emit("progress-download-changed", *value)
263
elif property_name == "Progress":
264
self.progress = value
265
self.emit("progress-changed", value)
266
elif property_name == "ConfigFileConflict":
267
self.config_file_conflict = value
268
if value != ("", ""):
269
self.emit("config-file-conflict", *value)
270
elif property_name == "MetaData":
271
self.meta_data = value
272
self.emit("meta-data-changed", value)
273
elif property_name == "Paused":
279
elif property_name == "RequiredMedium":
280
self.required_medium = value
281
if value != ("", ""):
282
self.emit("medium-required", *value)
283
elif property_name == "ProgressDetails":
284
self.progress_details = value
285
self.emit("progress-details-changed", *value)
286
elif property_name == "Download":
287
self.download = value
288
self.emit("download-changed", value)
289
elif property_name == "Space":
291
self.emit("space-changed", value)
292
elif property_name == "HttpProxy":
293
self.http_proxy = value
294
self.emit("http-proxy-changed", value)
295
elif property_name == "Error":
296
self.error_code, self.error_details = value
297
if self.error_code != -1:
298
self.error = TransactionFailed(self.error_code,
300
self.emit("error", *value)
301
elif property_name == "ExitState":
303
if value != enums.EXIT_UNFINISHED:
304
self.emit("finished", value)
305
self._owner_watcher.cancel()
306
if self._debconf_helper:
307
self._debconf_helper.stop()
310
@defer.deferable_function
311
@convert_dbus_exception
312
def sync(self, reply_handler=None, error_handler=None):
313
"""Sync the client transaction properites with the backend one.
316
reply_handler - callback function. If specified in combination with
317
error_handler the method will be called asynchrounsouly.
318
error_handler - in case of an error the given callback gets the
319
corresponding DBus exception instance
321
def sync_properties(prop_dict):
322
for property_name, value in prop_dict.iteritems():
323
self._on_property_changed(property_name, value)
326
if reply_handler and error_handler:
327
self._proxy.GetAll("org.debian.apt.transaction",
328
dbus_interface=dbus.PROPERTIES_IFACE,
329
reply_handler=sync_properties,
330
error_handler=error_handler)
332
properties = self._proxy.GetAll("org.debian.apt.transaction",
333
dbus_interface=dbus.PROPERTIES_IFACE)
334
sync_properties(properties)
337
@defer.deferable_function
338
@convert_dbus_exception
339
def run(self, reply_handler=None, error_handler=None):
340
"""Start processing the transaction.
343
reply_handler - callback function. If specified in combination with
344
error_handler the method will be called asynchrounsouly.
345
error_handler - in case of an error the given callback gets the
346
corresponding DBus exception instance
349
return self._iface.Run(error_handler=error_handler,
350
reply_handler=reply_handler)
351
except Exception, error:
357
@defer.deferable_function
358
@convert_dbus_exception
359
def simulate(self, reply_handler=None, error_handler=None):
360
"""Simulate the transaction to calculate the dependencies, the
361
required download size and the required disk space.
363
The corresponding properties of the transaction will be updated.
365
Also TransactionFailed exceptions could be raised, if e.g. a
366
requested package could not be installed or the cache is currently
370
reply_handler - callback function. If specified in combination with
371
error_handler the method will be called asynchrounsouly.
372
error_handler - in case of an error the given callback gets the
373
corresponding DBus exception instance
375
self._iface.Simulate(reply_handler=reply_handler,
376
error_handler=error_handler)
378
@defer.deferable_function
379
@convert_dbus_exception
380
def cancel(self, reply_handler=None, error_handler=None):
381
"""Cancel the running transaction.
384
reply_handler - callback function. If specified in combination with
385
error_handler the method will be called asynchrounsouly.
386
error_handler - in case of an error the given callback gets the
387
corresponding DBus exception instance
389
self._iface.Cancel(reply_handler=reply_handler,
390
error_handler=error_handler)
392
@defer.deferable_function
393
@convert_dbus_exception
394
def set_http_proxy(self, proxy, reply_handler=None, error_handler=None):
395
"""Set the HttpProxy property of the transaction.
398
proxy - the URL of the proxy server, e.g. "http://proxy:8080"
399
reply_handler - callback function. If specified in combination with
400
error_handler the method will be called asynchrounsouly.
401
error_handler - in case of an error the given callback gets the
402
corresponding DBus exception instance
405
_reply_handler = lambda: reply_handler(self)
407
_reply_handler = None
408
self._proxy.Set("org.debian.apt.transaction", "HttpProxy", proxy,
409
dbus_interface=dbus.PROPERTIES_IFACE,
410
reply_handler=_reply_handler,
411
error_handler=error_handler)
413
@defer.deferable_function
414
@convert_dbus_exception
415
def set_remove_obsoleted_depends(self, remove_obsoleted_depends,
416
reply_handler=None, error_handler=None):
417
"""Set the RemoveObsoletedDepends protperty of the transaction.
420
remove_obsoleted_depends - if True also remove no longer required
421
dependencies which have been installed automatically before
422
reply_handler - callback function. If specified in combination with
423
error_handler the method will be called asynchrounsouly.
424
error_handler - in case of an error the given callback gets the
425
corresponding DBus exception instance
428
_reply_handler = lambda: reply_handler(self)
430
_reply_handler = None
431
self._proxy.Set("org.debian.apt.transaction",
432
"RemoveObsoletedDepends", remove_obsoleted_depends,
433
dbus_interface=dbus.PROPERTIES_IFACE,
434
reply_handler=_reply_handler,
435
error_handler=error_handler)
437
@defer.deferable_function
438
@convert_dbus_exception
439
def set_allow_unauthenticated(self, allow_unauthenticated,
440
reply_handler=None, error_handler=None):
441
"""Set AllowUnauthencitaed property of the transaction.
444
allow_unauthenticated - if True the installation of packages which
445
have not been signed by a trusted software vendor are allowed
446
to be installed. Defaults to False.
447
reply_handler - callback function. If specified in combination with
448
error_handler the method will be called asynchrounsouly.
449
error_handler - in case of an error the given callback gets the
450
corresponding DBus exception instance
453
_reply_handler = lambda: reply_handler(self)
455
_reply_handler = None
456
self._proxy.Set("org.debian.apt.transaction",
457
"AllowUnauthenticated", allow_unauthenticated,
458
dbus_interface=dbus.PROPERTIES_IFACE,
459
reply_handler=_reply_handler,
460
error_handler=error_handler)
462
@defer.deferable_function
463
@convert_dbus_exception
464
def set_debconf_frontend(self, frontend, reply_handler=None,
466
"""Set the DebconfSocket property of the transaction.
469
debconf_socket - a socket to which the debconf proxy frontend should
470
be attached. A debconf frontend running in the user's session
471
should listen to the socket.
472
reply_handler - callback function. If specified in combination with
473
error_handler the method will be called asynchrounsouly.
474
error_handler - in case of an error the given callback gets the
475
corresponding DBus exception instance
478
_reply_handler = lambda: reply_handler(self)
480
_reply_handler = None
481
self._debconf_helper = debconf.DebconfProxy(frontend)
482
self._proxy.Set("org.debian.apt.transaction", "DebconfSocket",
483
self._debconf_helper.socket_path,
484
dbus_interface=dbus.PROPERTIES_IFACE,
485
reply_handler=_reply_handler,
486
error_handler=error_handler)
487
self._debconf_helper.start()
489
@defer.deferable_function
490
@convert_dbus_exception
491
def set_meta_data(self, **kwargs):
492
"""Store additional meta information of the transaction in the
493
MetaData property of the transaction.
495
The method accepts of key=value pairs. The key has to be prefixed with
496
an underscore separated identifier of the client application.
498
In the following example Software-Center sets an application name
501
>>> Transaction.set_meta_data(sc_icon="shiny", sc_app="xterm")
503
Special keyword arguments:
504
reply_handler - callback function. If specified in combination with
505
error_handler the method will be called asynchrounsouly.
506
error_handler - in case of an error the given callback gets the
507
corresponding DBus exception instance
509
reply_handler = kwargs.pop("reply_handler", None)
510
error_handler = kwargs.pop("error_handler", None)
512
_reply_handler = lambda: reply_handler(self)
514
_reply_handler = None
515
self._proxy.Set("org.debian.apt.transaction", "MetaData", kwargs,
516
dbus_interface=dbus.PROPERTIES_IFACE,
517
reply_handler=_reply_handler,
518
error_handler=error_handler)
520
@defer.deferable_function
521
@convert_dbus_exception
522
def set_terminal(self, ttyname, reply_handler=None, error_handler=None):
523
"""Set the Terminal property of the transaction to attach a
524
controlling terminal to the dpkg call.
527
ttyname - the path to the master tty
528
reply_handler - callback function. If specified in combination with
529
error_handler the method will be called asynchrounsouly.
530
error_handler - in case of an error the given callback gets the
531
corresponding DBus exception instance
534
_reply_handler = lambda: reply_handler(self)
536
_reply_handler = None
537
self._proxy.Set("org.debian.apt.transaction", "Terminal", ttyname,
538
dbus_interface=dbus.PROPERTIES_IFACE,
539
reply_handler=_reply_handler,
540
error_handler=error_handler)
542
def disconnect(self):
543
"""Stop monitoring the progress of the transaction."""
544
self._signal_matcher.remove()
545
del self._signal_matcher
547
@defer.deferable_function
548
@convert_dbus_exception
549
def set_locale(self, locale_name, reply_handler=None, error_handler=None):
550
"""Set the language for status and error messages.
553
locale_name - a supported locale, e.g. "de_DE@UTF-8"
554
reply_handler - callback function. If specified in combination with
555
error_handler the method will be called asynchrounsouly.
556
error_handler - in case of an error the given callback gets the
557
corresponding DBus exception instance
560
_reply_handler = lambda: reply_handler(self)
562
_reply_handler = None
563
self._proxy.Set("org.debian.apt.transaction", "Locale", locale_name,
564
dbus_interface=dbus.PROPERTIES_IFACE,
565
reply_handler=_reply_handler,
566
error_handler=error_handler)
568
@defer.deferable_function
569
@convert_dbus_exception
570
def provide_medium(self, medium, reply_handler=None, error_handler=None):
571
"""Continue a paused transaction which waited for a medium to install
575
medium - the name of the provided medium
576
reply_handler - callback function. If specified in combination with
577
error_handler the method will be called asynchrounsouly.
578
error_handler - in case of an error the given callback gets the
579
corresponding DBus exception instance
581
self._iface.ProvideMedium(medium, reply_handler=reply_handler,
582
error_handler=error_handler)
584
@defer.deferable_function
585
@convert_dbus_exception
586
def resolve_config_file_conflict(self, config, answer, reply_handler=None,
588
"""Continue a paused transaction that waits for the resolution of a
589
configuration file conflict.
592
config - the path of the corresponding config file
593
answer - can be either "keep" or "replace"
594
reply_handler - callback function. If specified in combination with
595
error_handler the method will be called asynchrounsouly.
596
error_handler - in case of an error the given callback gets the
597
corresponding DBus exception instance
599
self._iface.ResolveConfigFileConflict(config, answer,
600
reply_handler=reply_handler,
601
error_handler=error_handler)
606
"""Provides a complete client for aptdaemon."""
609
"""Return a new AptClient instance."""
610
self.bus = dbus.SystemBus()
611
# Catch an invalid locale
613
self._locale = "%s.%s" % locale.getdefaultlocale()
618
@convert_dbus_exception
619
def get_trusted_vendor_keys(self, reply_handler=None, error_handler=None):
620
"""Return the list of trusted vendors.
623
reply_handler - callback function. If specified in combination with
624
error_handler the method will be called asynchrounsouly.
625
error_handler - in case of an error the given callback gets the
626
corresponding DBus exception instance
628
daemon = get_aptdaemon()
629
keys = daemon.GetTrustedVendorKeys(reply_handler=reply_handler,
630
error_handler=error_handler)
633
@defer.deferable_function
634
@convert_dbus_exception
635
def upgrade_system(self, safe_mode=True, wait=False, reply_handler=None,
637
"""Return a transaction which upgrades the software installed on
641
safe_mode - if True skip upgrades which require the installation or
642
removal of other packages. Defaults to True.
643
wait - if True run the transaction immediately and return its exit
644
state instead of the transaction itself.
645
reply_handler - callback function. If specified in combination with
646
error_handler the method will be called asynchrounsouly.
647
error_handler - in case of an error the given callback gets the
648
corresponding DBus exception instance
650
return self._run_transaction("UpgradeSystem", [safe_mode],
651
wait, reply_handler, error_handler)
653
@defer.deferable_function
654
@convert_dbus_exception
655
def install_packages(self, package_names, wait=False, reply_handler=None,
657
"""Return a transaction which will the install the given packages.
660
package_names - a list of package names
661
wait - if True run the transaction immediately and return its exit
662
state instead of the transaction itself.
663
reply_handler - callback function. If specified in combination with
664
error_handler the method will be called asynchrounsouly.
665
error_handler - in case of an error the given callback gets the
666
corresponding DBus exception instance
668
return self._run_transaction("InstallPackages", [package_names],
669
wait, reply_handler, error_handler)
671
@defer.deferable_function
672
@convert_dbus_exception
673
def add_repository(self, src_type, uri, dist, comps=[], comment="",
674
sourcesfile="", reply_handler=None, error_handler=None):
675
"""Add repository to the sources list.
678
src_type -- the type of the entry (deb, deb-src)
679
uri -- the main repository uri (e.g. http://archive.ubuntu.com/ubuntu)
680
dist -- the distribution to use (e.g. karmic, "/")
681
comps -- a (possible empty) list of components (main, restricted)
682
comment -- an (optional) comment
683
sourcesfile -- an (optinal) filename in sources.list.d
684
reply_handler - callback function. If specified in combination with
685
error_handler the method will be called asynchrounsouly.
686
error_handler - in case of an error the given callback gets the
687
corresponding DBus exception instance
689
daemon = get_aptdaemon()
690
# dbus can not deal with empty lists and will error
693
return daemon.AddRepository(src_type, uri, dist, comps, comment,
694
sourcesfile, reply_handler=reply_handler,
695
error_handler=error_handler)
697
@defer.deferable_function
698
@convert_dbus_exception
699
def add_vendor_key_from_file(self, path, wait=False, reply_handler=None,
701
"""Return a transaction which add the GPG key of a software vendor
702
to the list of trusted ones.
705
path - location of the key file
706
wait - if True run the transaction immediately and return its exit
707
state instead of the transaction itself.
708
reply_handler - callback function. If specified in combination with
709
error_handler the method will be called asynchrounsouly.
710
error_handler - in case of an error the given callback gets the
711
corresponding DBus exception instance
713
return self._run_transaction("AddVendorKeyFromFile", [path],
714
wait, reply_handler, error_handler)
716
@defer.deferable_function
717
@convert_dbus_exception
718
def remove_vendor_key(self, fingerprint, wait=False, reply_handler=None,
720
"""Return a transaction which will remove the GPG of a software vendor
721
from the list of trusted ones.
724
fingerprint - identifier of the GPG key
725
wait - if True run the transaction immediately and return its exit
726
state instead of the transaction itself.
727
reply_handler - callback function. If specified in combination with
728
error_handler the method will be called asynchrounsouly.
729
error_handler - in case of an error the given callback gets the
730
corresponding DBus exception instance
732
return self._run_transaction("RemoveVendorKey", [fingerprint],
733
wait, reply_handler, error_handler)
735
@defer.deferable_function
736
@convert_dbus_exception
737
def install_file(self, path, wait=False, reply_handler=None,
739
"""Return a transaction which installs a local package file.
742
path - location of the package file
743
wait - if True run the transaction immediately and return its exit
744
state instead of the transaction itself.
745
reply_handler - callback function. If specified in combination with
746
error_handler the method will be called asynchrounsouly.
747
error_handler - in case of an error the given callback gets the
748
corresponding DBus exception instance
750
return self._run_transaction("InstallFile", [path],
751
wait, reply_handler, error_handler)
753
@defer.deferable_function
754
@convert_dbus_exception
755
def upgrade_packages(self, package_names, wait=False, reply_handler=None,
757
"""Return a transaction which upgrades the given packages.
760
package_names - list of package names which should be upgraded
761
wait - if True run the transaction immediately and return its exit
762
state instead of the transaction itself.
763
reply_handler - callback function. If specified in combination with
764
error_handler the method will be called asynchrounsouly.
765
error_handler - in case of an error the given callback gets the
766
corresponding DBus exception instance
768
return self._run_transaction("UpgradePackages", [package_names],
769
wait, reply_handler, error_handler)
771
@defer.deferable_function
772
@convert_dbus_exception
773
def remove_packages(self, package_names, wait=False,
774
reply_handler=None, error_handler=None):
775
"""Return a transaction which removes the given packages.
778
package_names - list of package names which should be removed
779
wait - if True run the transaction immediately and return its exit
780
state instead of the transaction itself.
781
reply_handler - callback function. If specified in combination with
782
error_handler the method will be called asynchrounsouly.
783
error_handler - in case of an error the given callback gets the
784
corresponding DBus exception instance
786
return self._run_transaction("RemovePackages", [package_names],
787
wait, reply_handler, error_handler)
789
@defer.deferable_function
790
@convert_dbus_exception
791
def commit_packages(self, install, reinstall, remove, purge, upgrade,
792
wait=False, reply_handler=None, error_handler=None):
793
"""Return a transaction which performs a complex package managagement
794
task which consits of installing, reinstalling, removing,
795
purging and upgrading packages at the same time.
798
install - list of package names to install
799
reinstall - list of package names to reinstall
800
remove - list of package names to remove
801
purge - list of package names to purge
802
upgrade - list of package names to upgrade
803
wait - if True run the transaction immediately and return its exit
804
state instead of the transaction itself.
805
reply_handler - callback function. If specified in combination with
806
error_handler the method will be called asynchrounsouly.
807
error_handler - in case of an error the given callback gets the
808
corresponding DBus exception instance
810
def check_empty_list(lst):
815
pkgs = [check_empty_list(lst) for lst in [install, reinstall, remove,
817
return self._run_transaction("CommitPackages", pkgs,
818
wait, reply_handler, error_handler)
820
@defer.deferable_function
821
@convert_dbus_exception
822
def fix_broken_depends(self, wait=False, reply_handler=None,
824
"""Return a transacation which tries to fix broken dependencies.
825
Use with care since currently there isn't any preview of the
829
wait - if True run the transaction immediately and return its exit
830
state instead of the transaction itself.
831
reply_handler - callback function. If specified in combination with
832
error_handler the method will be called asynchrounsouly.
833
error_handler - in case of an error the given callback gets the
834
corresponding DBus exception instance
836
return self._run_transaction("FixBrokenDepends", [],
837
wait, reply_handler, error_handler)
839
@defer.deferable_function
840
@convert_dbus_exception
841
def fix_incomplete_install(self, wait=False, reply_handler=None,
843
"""Return a transaction which tries to complete cancelled installations
844
by calling dpkg --configure -a.
847
wait - if True run the transaction immediately and return its exit
848
state instead of the transaction itself.
849
reply_handler - callback function. If specified in combination with
850
error_handler the method will be called asynchrounsouly.
851
error_handler - in case of an error the given callback gets the
852
corresponding DBus exception instance
854
return self._run_transaction("FixIncompleteInstall", [], wait,
855
reply_handler, error_handler)
857
@defer.deferable_function
858
@convert_dbus_exception
859
def update_cache(self, wait=False, reply_handler=None, error_handler=None):
860
"""Return a transaction which queries the software sources
861
(package repositories) for available packages.
864
wait - if True run the transaction immediately and return its exit
865
state instead of the transaction itself.
866
reply_handler - callback function. If specified in combination with
867
error_handler the method will be called asynchrounsouly.
868
error_handler - in case of an error the given callback gets the
869
corresponding DBus exception instance
871
return self._run_transaction("UpdateCache", [], wait, reply_handler,
874
@defer.deferable_function
875
@convert_dbus_exception
876
def enable_distro_component(self, component, reply_handler=None,
878
"""Add component to the sources list.
881
component -- a components e.g. main or universe
882
reply_handler - callback function. If specified in combination with
883
error_handler the method will be called asynchrounsouly.
884
error_handler - in case of an error the given callback gets the
885
corresponding DBus exception instance
887
daemon = get_aptdaemon()
888
return daemon.EnableDistroComponent(component,
889
reply_handler=reply_handler,
890
error_handler=error_handler)
892
def _run_transaction(self, method_name, args, wait, reply_handler,
894
async = reply_handler and error_handler
896
deferred = self._run_transaction_helper(method_name, args, wait,
898
except Exception, error:
904
deferred.add_callbacks(reply_handler)
905
deferred.add_errback(error_handler)
907
elif isinstance(deferred.result, defer.DeferredException):
908
raise deferred.result.value
910
return deferred.result
912
@defer.inline_callbacks
913
def _run_transaction_helper(self, method_name, args, wait, async):
914
daemon = get_aptdaemon()
915
dbus_method = daemon.get_dbus_method(method_name)
917
deferred = defer.Deferred()
918
dbus_method(reply_handler=deferred.callback,
919
error_handler=deferred.errback, *args)
922
tid = dbus_method(*args)
923
trans = AptTransaction(tid, self.bus)
925
yield trans.set_locale(self._locale, defer=async)
927
yield trans.set_terminal(self.terminal, defer=async)
928
yield trans.sync(defer=async)
930
deferred_wait = defer.Deferred()
931
trans.connect("finished",
932
lambda trans, exit: deferred_wait.callback(exit))
933
yield trans.run(defer=True)
937
while trans.exit == enums.EXIT_UNFINISHED:
938
context = gobject.main_context_default()
939
context.iteration(True)
942
defer.return_value(trans)
945
@defer.deferable_function
946
@convert_dbus_exception
947
def get_transaction(tid, bus=None, reply_handler=None, error_handler=None):
948
"""Return an AptTransaction instance connected to the given transaction.
951
tid -- the identifier of the transaction
952
bus -- the D-Bus connection that should be used (defaults to the system bus)
955
bus = dbus.SystemBus()
956
trans = AptTransaction(tid, bus)
957
if error_handler and reply_handler:
958
trans.sync(reply_handler=reply_handler, error_handler=error_handler)
963
def get_aptdaemon(bus=None):
964
"""Return the aptdaemon D-Bus interface.
967
bus -- the D-Bus connection that should be used (defaults to the system bus)
970
bus = dbus.SystemBus()
971
return dbus.Interface(bus.get_object("org.debian.apt",