← Back to team overview

duplicity-team team mailing list archive

[Merge] lp:~mterry/duplicity/pygi into lp:duplicity

 

Michael Terry has proposed merging lp:~mterry/duplicity/pygi into lp:duplicity.

Requested reviews:
  duplicity-team (duplicity-team)

For more details, see:
https://code.launchpad.net/~mterry/duplicity/pygi/+merge/143220

Python bindings for the gobject stack (used in the gio backend) have changed from static to dynamically-generated bindings.  The old static bindings are deprecated.  So here's a branch to change the gio backend from old to new ones.
-- 
https://code.launchpad.net/~mterry/duplicity/pygi/+merge/143220
Your team duplicity-team is requested to review the proposed merge of lp:~mterry/duplicity/pygi into lp:duplicity.
=== modified file 'duplicity/backends/giobackend.py'
--- duplicity/backends/giobackend.py	2012-03-19 19:04:35 +0000
+++ duplicity/backends/giobackend.py	2013-01-15 01:31:25 +0000
@@ -23,16 +23,14 @@
 import subprocess
 import atexit
 import signal
-import gio #@UnresolvedImport
-import glib #@UnresolvedImport
+from gi.repository import Gio #@UnresolvedImport
+from gi.repository import GLib #@UnresolvedImport
 
 import duplicity.backend
 from duplicity.backend import retry
 from duplicity import log
-from duplicity import globals
 from duplicity import util
 from duplicity.errors import * #@UnusedWildImport
-from duplicity.util import exception_traceback
 
 def ensure_dbus():
     # GIO requires a dbus session bus which can start the gvfs daemons
@@ -48,19 +46,19 @@
                     atexit.register(os.kill, int(parts[1]), signal.SIGTERM)
                 os.environ[parts[0]] = parts[1]
 
-class DupMountOperation(gio.MountOperation):
+class DupMountOperation(Gio.MountOperation):
     """A simple MountOperation that grabs the password from the environment
        or the user.
     """
     def __init__(self, backend):
-        gio.MountOperation.__init__(self)
+        Gio.MountOperation.__init__(self)
         self.backend = backend
         self.connect('ask-password', self.ask_password_cb)
         self.connect('ask-question', self.ask_question_cb)
 
     def ask_password_cb(self, *args, **kwargs):
         self.set_password(self.backend.get_password())
-        self.reply(gio.MOUNT_OPERATION_HANDLED)
+        self.reply(Gio.MountOperationResult.HANDLED)
 
     def ask_question_cb(self, *args, **kwargs):
         # Obviously just always answering with the first choice is a naive
@@ -70,7 +68,7 @@
         # new hosts and 'afc' does if the device is locked.  0 should be a
         # safe choice.
         self.set_choice(0)
-        self.reply(gio.MOUNT_OPERATION_HANDLED)
+        self.reply(Gio.MountOperationResult.HANDLED)
 
 class GIOBackend(duplicity.backend.Backend):
     """Use this backend when saving to a GIO URL.
@@ -82,21 +80,29 @@
 
         ensure_dbus()
 
-        self.remote_file = gio.File(uri=parsed_url.url_string)
+        self.remote_file = Gio.File.new_for_uri(parsed_url.url_string)
 
         # Now we make sure the location is mounted
         op = DupMountOperation(self)
-        loop = glib.MainLoop()
-        self.remote_file.mount_enclosing_volume(op, self.done_with_mount,
-                                                0, user_data=loop)
+        loop = GLib.MainLoop()
+        self.remote_file.mount_enclosing_volume(Gio.MountMountFlags.NONE,
+                                                op, None, self.done_with_mount,
+                                                loop)
         loop.run() # halt program until we're done mounting
 
+        # Now make the directory if it doesn't exist
+        try:
+            self.remote_file.make_directory_with_parents(None)
+        except GLib.GError, e:
+            if e.code != Gio.IOErrorEnum.EXISTS:
+                raise
+
     def done_with_mount(self, fileobj, result, loop):
         try:
             fileobj.mount_enclosing_volume_finish(result)
-        except gio.Error, e:
+        except GLib.GError, e:
             # check for NOT_SUPPORTED because some schemas (e.g. file://) validly don't
-            if e.code != gio.ERROR_ALREADY_MOUNTED and e.code != gio.ERROR_NOT_SUPPORTED:
+            if e.code != Gio.IOErrorEnum.ALREADY_MOUNTED and e.code != Gio.IOErrorEnum.NOT_SUPPORTED:
                 log.FatalError(_("Connection failed, please check your password: %s")
                                % str(e), log.ErrorCode.connection_failed)
         loop.quit()
@@ -105,12 +111,12 @@
         if raise_error:
             raise e
         code = log.ErrorCode.backend_error
-        if isinstance(e, gio.Error):
-            if e.code == gio.ERROR_PERMISSION_DENIED:
+        if isinstance(e, GLib.GError):
+            if e.code == Gio.IOErrorEnum.PERMISSION_DENIED:
                 code = log.ErrorCode.backend_permission_denied
-            elif e.code == gio.ERROR_NOT_FOUND:
+            elif e.code == Gio.IOErrorEnum.NOT_FOUND:
                 code = log.ErrorCode.backend_not_found
-            elif e.code == gio.ERROR_NO_SPACE:
+            elif e.code == Gio.IOErrorEnum.NO_SPACE:
                 code = log.ErrorCode.backend_no_space
         extra = ' '.join([util.escape(x) for x in [file1, file2] if x])
         extra = ' '.join([op, extra])
@@ -123,8 +129,9 @@
     def copy_file(self, op, source, target, raise_errors=False):
         log.Info(_("Writing %s") % target.get_parse_name())
         try:
-            source.copy(target, self.copy_progress,
-                        gio.FILE_COPY_OVERWRITE | gio.FILE_COPY_NOFOLLOW_SYMLINKS)
+            source.copy(target,
+                        Gio.FileCopyFlags.OVERWRITE | Gio.FileCopyFlags.NOFOLLOW_SYMLINKS,
+                        None, self.copy_progress, None)
         except Exception, e:
             self.handle_error(raise_errors, e, op, source.get_parse_name(),
                               target.get_parse_name())
@@ -133,14 +140,14 @@
         """Copy file to remote"""
         if not remote_filename:
             remote_filename = source_path.get_filename()
-        source_file = gio.File(path=source_path.name)
+        source_file = Gio.File.new_for_path(source_path.name)
         target_file = self.remote_file.get_child(remote_filename)
         self.copy_file('put', source_file, target_file)
 
     def get(self, filename, local_path):
         """Get file and put in local_path (Path object)"""
         source_file = self.remote_file.get_child(filename)
-        target_file = gio.File(path=local_path.name)
+        target_file = Gio.File.new_for_path(local_path.name)
         self.copy_file('get', source_file, target_file)
         local_path.setdata()
 
@@ -149,12 +156,13 @@
         """List files in that directory"""
         files = []
         try:
-            enum = self.remote_file.enumerate_children(gio.FILE_ATTRIBUTE_STANDARD_NAME,
-                                                       gio.FILE_QUERY_INFO_NOFOLLOW_SYMLINKS)
-            info = enum.next_file()
+            enum = self.remote_file.enumerate_children(Gio.FILE_ATTRIBUTE_STANDARD_NAME,
+                                                       Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
+                                                       None)
+            info = enum.next_file(None)
             while info:
                 files.append(info.get_name())
-                info = enum.next_file()
+                info = enum.next_file(None)
         except Exception, e:
             self.handle_error(raise_errors, e, 'list',
                               self.remote_file.get_parse_name())
@@ -167,10 +175,10 @@
         for filename in filename_list:
             target_file = self.remote_file.get_child(filename)
             try:
-                target_file.delete()
+                target_file.delete(None)
             except Exception, e:
-                if isinstance(e, gio.Error):
-                    if e.code == gio.ERROR_NOT_FOUND:
+                if isinstance(e, GLib.GError):
+                    if e.code == Gio.IOErrorEnum.NOT_FOUND:
                         continue
                 self.handle_error(raise_errors, e, 'delete',
                                   target_file.get_parse_name())
@@ -180,13 +188,14 @@
     def _query_file_info(self, filename, raise_errors=False):
         """Query attributes on filename"""
         target_file = self.remote_file.get_child(filename)
-        attrs = gio.FILE_ATTRIBUTE_STANDARD_SIZE
+        attrs = Gio.FILE_ATTRIBUTE_STANDARD_SIZE
         try:
-            info = target_file.query_info(attrs, gio.FILE_QUERY_INFO_NONE)
+            info = target_file.query_info(attrs, Gio.FileQueryInfoFlags.NONE,
+                                          None)
             return {'size': info.get_size()}
         except Exception, e:
-            if isinstance(e, gio.Error):
-                if e.code == gio.ERROR_NOT_FOUND:
+            if isinstance(e, GLib.GError):
+                if e.code == Gio.IOErrorEnum.NOT_FOUND:
                     return {'size': -1} # early exit, no need to retry
             if raise_errors:
                 raise e


Follow ups