Roman Yepishev has proposed merging lp:~rye/duplicity/mediafire into lp:duplicity.
Requested reviews: duplicity-team (duplicity-team) For more details, see: https://code.launchpad.net/~rye/duplicity/mediafire/+merge/285547 Backend for https://www.mediafire.com Requires https://pypi.python.org/pypi/mediafire/ installed. Requires MEDIAFIRE_EMAIL, MEDIAFIRE_PASSWORD environment variables as described in the man page. To test: 1. Create an account at https://www.mediafire.com 2. Run: pip install mediafire export [email protected] export MEDIAFIRE_PASSWORD=your-mediafire-password duplicity /path/to/dir mf:///backup-directory -- Your team duplicity-team is requested to review the proposed merge of lp:~rye/duplicity/mediafire into lp:duplicity.
=== modified file 'bin/duplicity.1' --- bin/duplicity.1 2016-02-05 09:58:57 +0000 +++ bin/duplicity.1 2016-02-10 00:40:35 +0000 @@ -1205,6 +1205,16 @@ .B "A NOTE ON MULTI BACKEND" below. .RE +.PP +.BR "MediaFire" +.PP +.RS +mf:///some_dir +.PP +See also +.B "A NOTE ON MEDIAFIRE BACKEND" +below. +.RE .SH TIME FORMATS duplicity uses time strings in two places. Firstly, many of the files @@ -1871,6 +1881,20 @@ .B SWIFT_AUTHVERSION is unspecified, it will default to version 1. +.SH A NOTE ON MEDIAFIRE BACKEND +This backend requires +.B mediafire +python library to be installed on the system. See +.BR REQUIREMENTS . + +It uses the following environment variables for authentication: +.B MEDIAFIRE_EMAIL +- account email, +.B MEDIAFIRE_PASSWORD +- account password. + +The destination folder will be created for you if it does not exist. + .SH A NOTE ON SYMMETRIC ENCRYPTION AND SIGNING Signing and symmetrically encrypt at the same time with the gpg binary on the command line, as used within duplicity, is a specifically challenging issue. @@ -2075,6 +2099,10 @@ .B Python kerberos module for kerberos authentication - https://github.com/02strich/pykerberos +.TP +.BR "MediaFire backend" +.B MediaFire Python Open SDK +- https://pypi.python.org/pypi/mediafire/ .SH AUTHOR .TP === added file 'duplicity/backends/mediafirebackend.py' --- duplicity/backends/mediafirebackend.py 1970-01-01 00:00:00 +0000 +++ duplicity/backends/mediafirebackend.py 2016-02-10 00:40:35 +0000 @@ -0,0 +1,144 @@ +# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- +# +# Copyright 2016 Roman Yepishev <[email protected]> +# +# This file is part of duplicity. +# +# Duplicity is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# Duplicity is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with duplicity; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +"""MediaFire Duplicity Backend""" + +import os + +import duplicity.backend + +from duplicity.errors import BackendException + +DUPLICITY_APP_ID = '45593' + + +class MediafireBackend(duplicity.backend.Backend): + """Use this backend when saving to MediaFire + + URLs look like mf:/root/folder. + """ + def __init__(self, parsed_url): + try: + import mediafire.client + except ImportError: + raise BackendException("This backend requires " + "the mediafire library") + + if "MEDIAFIRE_EMAIL" not in os.environ: + raise BackendException("MEDIAFIRE_EMAIL environment variable " + "is not set") + if "MEDIAFIRE_PASSWORD" not in os.environ: + raise BackendException("MEDIAFIRE_PASSWORD environment variable " + "is not set") + + self._file_res = mediafire.client.File + self._folder_res = mediafire.client.Folder + self._downloaderror_exc = mediafire.client.DownloadError + self._notfound_exc = mediafire.client.ResourceNotFoundError + + mediafire_email = os.environ["MEDIAFIRE_EMAIL"] + mediafire_password = os.environ["MEDIAFIRE_PASSWORD"] + + duplicity.backend.Backend.__init__(self, parsed_url) + + self.client = mediafire.client.MediaFireClient() + self.client.login(app_id=DUPLICITY_APP_ID, + email=mediafire_email, + password=mediafire_password) + + uri = 'mf:' + parsed_url.path + + # Create folder if it does not exist and make sure it is private + # See MediaFire Account Settings /Security and Privacy / Share Link + # to set "Inherit from parent folder" + try: + folder = self.client.get_resource_by_uri(uri) + if not isinstance(folder, self._folder_res): + raise BackendException("target_url already exists " + "and is not a folder") + except mediafire.client.ResourceNotFoundError: + # force folder to be private + folder = self.client.create_folder(uri, recursive=True) + self.client.update_folder_metadata(uri, privacy='private') + + self.folder = folder + + def _put(self, source_path, remote_filename=None): + """Upload file""" + # Use source file name if remote one is not defined + if remote_filename is None: + remote_filename = os.path.basename(source_path.name) + + uri = self._build_uri(remote_filename) + + with self.client.upload_session(): + self.client.upload_file(source_path.open('rb'), uri) + + def _get(self, filename, local_path): + """Download file""" + uri = self._build_uri(filename) + try: + self.client.download_file(uri, local_path.open('wb')) + except self._downloaderror_exc as ex: + raise BackendException(ex) + + def _list(self): + """List files in backup directory""" + uri = self._build_uri() + filenames = [] + for item in self.client.get_folder_contents_iter(uri): + if not isinstance(item, self._file_res): + continue + + filenames.append(item['filename'].encode('utf-8')) + + return filenames + + def _delete(self, filename): + """Delete single file""" + uri = self._build_uri(filename) + self.client.delete_file(uri) + + def _delete_list(self, filename_list): + """Delete list of files""" + for filename in filename_list: + self._delete(filename) + + def _query(self, filename): + """Stat the remote file""" + uri = self._build_uri(filename) + + try: + resource = self.client.get_resource_by_uri(uri) + size = int(resource['size']) + except self._notfound_exc: + size = -1 + + return {'size': size} + + def _build_uri(self, filename=None): + """Build relative URI""" + return ( + 'mf:' + self.folder["folderkey"] + + ('/' + filename if filename else '') + ) + + +duplicity.backend.register_backend("mf", MediafireBackend) === modified file 'duplicity/commandline.py' --- duplicity/commandline.py 2016-02-02 12:20:14 +0000 +++ duplicity/commandline.py 2016-02-10 00:40:35 +0000 @@ -918,6 +918,7 @@ onedrive://%(some_dir)s azure://%(container_name)s b2://%(account_id)s[:%(application_key)s]@%(bucket_name)s/[%(some_dir)s/] + mf:///%(some_dir)s """ % dict
_______________________________________________ Mailing list: https://launchpad.net/~duplicity-team Post to : [email protected] Unsubscribe : https://launchpad.net/~duplicity-team More help : https://help.launchpad.net/ListHelp

