Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code cleanups to comform with PEP8 #2

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.rst
Expand Up @@ -18,7 +18,7 @@ This package includes:

How does it work?
------------------
Dropbox its deduplication scheme works by breaking files into blocks.
The deduplication scheme used by Dropbox works by breaking files into blocks.
Each of these blocks is hashed with the SHA256__
algorithm and represented by the digest. Only blocks that are not yet
known are uploaded to the server when syncing.
Expand Down
7 changes: 4 additions & 3 deletions dropbox/exceptions.py
Expand Up @@ -4,9 +4,10 @@ def __init__(self, msg, e):
self.http_exc = e
self.code = e.code
IOError.__init__(self)

def __str__(self):
return "%s (code %i)" % (self.msg, self.code)

return '%s (code %i)' % (self.msg, self.code)


class UnknownBlocksError(ValueError):
pass
102 changes: 52 additions & 50 deletions dropbox/metadataclient.py
Expand Up @@ -10,7 +10,7 @@
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
Expand All @@ -21,16 +21,19 @@
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
import json, zlib, urllib2
from urllib import urlencode
import time
from binascii import a2b_hex
import json
import logging
import time
from urllib import urlencode
import urllib2
import zlib

from .util import digest_to_block_id, block_id_to_digest, BLOCK_SIZE, to_base64
from .exceptions import *
from .exceptions import APIError, UnknownBlocksError
from .util import digest_to_block_id, BLOCK_SIZE, to_base64

logger = logging.getLogger('metadataclient')

logger = logging.getLogger("metadataclient")

class MetadataClient(object):
def __init__(self, server, host_id, root_ns):
Expand All @@ -42,75 +45,74 @@ def inject_file(self, path, blocks, size, mtime=None):
"""
Inject a new file into account.
"""
blocklist = ",".join([digest_to_block_id(a2b_hex(id)) for id in blocks])
blocklist = ','.join([digest_to_block_id(a2b_hex(id)) for id in blocks])

if (size < ((len(blocks) - 1) * BLOCK_SIZE + 1) or
size > len(blocks) * BLOCK_SIZE):
raise ValueError('Invalid file size provided')

if (size < ((len(blocks)-1)*BLOCK_SIZE+1) or
size > len(blocks)*BLOCK_SIZE):
raise ValueError("Invalid file size provided")

if mtime is None:
mtime = time.time()

metadata = {
u'parent_blocklist': None,
u'blocklist': blocklist,
u'ns_id': self.root_ns,
u'parent_attrs': None,
u'mtime': int(mtime),
u'path': path,
u'is_dir': False,
u'size': size,
u'target_ns': None,
u'attrs': {u'mac': None} # basic attrs
u'parent_blocklist': None,
u'blocklist': blocklist,
u'ns_id': self.root_ns,
u'parent_attrs': None,
u'mtime': int(mtime),
u'path': path,
u'is_dir': False,
u'size': size,
u'target_ns': None,
u'attrs': {u'mac': None} # basic attrs
}

commit_info = [metadata]
logger.debug("commit_info %s", commit_info)
logger.debug('commit_info %s', commit_info)

url = "https://"+self.server+"/commit_batch"
url = 'https://' + self.server + '/commit_batch'
request = [
('host_id',self.host_id),
('extended_ret','True'),
('autoclose',''),
('changeset_map',''),
('commit_info',to_base64(zlib.compress(json.dumps(commit_info))))
('host_id', self.host_id),
('extended_ret', 'True'),
('autoclose', ''),
('changeset_map', ''),
('commit_info', to_base64(zlib.compress(json.dumps(commit_info))))
]
logger.debug("commit_batch %s", request)
logger.debug('commit_batch %s', request)
try:
rv = urllib2.urlopen(url, urlencode(request))
except urllib2.HTTPError,e:
raise APIError("Error during commit_batch", e)
except urllib2.HTTPError, e:
raise APIError('Error during commit_batch', e)

data = rv.read()
logger.debug("commit_batch returned %s", data)
logger.debug('commit_batch returned %s', data)

data = json.loads(data)

time.sleep(data["chillout"])

cur_revision = data["results"][0]
need_blocks = data["need_blocks"]
time.sleep(data['chillout'])

cur_revision = data['results'][0]
need_blocks = data['need_blocks']

if len(need_blocks) > 0:
raise UnknownBlocksError("Oops, blocks are not known: %s", need_blocks)
raise UnknownBlocksError('Oops, blocks are not known: %s', need_blocks)

logger.debug("Current revision %i", cur_revision)
logger.debug('Current revision %i', cur_revision)

changeset_ids = data["changeset_id"].items()
logger.debug("Changeset IDs %s", changeset_ids)
changeset_ids = data['changeset_id'].items()
logger.debug('Changeset IDs %s', changeset_ids)

url = "https://"+self.server+"/close_changeset"
url = 'https://' + self.server + '/close_changeset'
request = [
('host_id',self.host_id),
('changeset_id',str(changeset_ids[0][1])),
('ns_id',str(changeset_ids[0][0]))
('host_id', self.host_id),
('changeset_id', str(changeset_ids[0][1])),
('ns_id', str(changeset_ids[0][0]))
]
logger.debug("close_changeset %s", request)
logger.debug('close_changeset %s', request)
try:
rv = urllib2.urlopen(url, urlencode(request))
except urllib2.HTTPError,e:
raise APIError("Error during close_changeset", e)
except urllib2.HTTPError, e:
raise APIError('Error during close_changeset', e)

data = rv.read()
logger.debug("close_changeset returned %s", data)

logger.debug('close_changeset returned %s', data)
22 changes: 13 additions & 9 deletions dropbox/util.py
Expand Up @@ -9,7 +9,7 @@
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
Expand All @@ -24,26 +24,30 @@
from binascii import a2b_base64, b2a_base64
import string

BLOCK_SIZE=4*1024*1024
HASH_SIZE=43
BLOCK_SIZE = 4 * 1024 * 1024
HASH_SIZE = 43

DIGEST_TO_BLOCK_ID = string.maketrans('=+/', '~-_')
BLOCK_ID_TO_DIGEST = string.maketrans('~-_', '=+/')

DIGEST_TO_BLOCK_ID=string.maketrans("=+/", "~-_")
BLOCK_ID_TO_DIGEST=string.maketrans("~-_", "=+/")

def digest_to_block_id(digest):
block_id = b2a_base64(digest)[0:HASH_SIZE]
block_id = block_id.translate(DIGEST_TO_BLOCK_ID)
return block_id



def block_id_to_digest(block_id):
block_id = block_id.translate(BLOCK_ID_TO_DIGEST)
return a2b_base64(block_id + "=")
return a2b_base64(block_id + '=')


def to_base64(binary):
base64 = b2a_base64(binary)
base64 = base64.translate(DIGEST_TO_BLOCK_ID, "\n")
base64 = base64.translate(DIGEST_TO_BLOCK_ID, '\n')
return base64



def from_base64(base64):
base64 = base64.translate(BLOCK_ID_TO_DIGEST)
return a2b_base64(base64)
41 changes: 20 additions & 21 deletions dropship
Expand Up @@ -10,7 +10,7 @@ Inject file into account without possessing the original data.
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
Expand All @@ -21,40 +21,40 @@ Inject file into account without possessing the original data.
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
from config import host_id, root_ns
import logging
import json
import sys

from dropbox.exceptions import *
from dropbox.exceptions import APIError, UnknownBlocksError
from dropbox.metadataclient import MetadataClient

SERVER_ADDRESS = 'client-lb.dropbox.com'


if __name__ == '__main__':
from config import host_id,root_ns
import sys
from sys import stderr as err, stdout as out

logging.basicConfig(level=logging.INFO, # Change to DEBUG to show details
logging.basicConfig(level=logging.INFO, # Change to DEBUG to show details
datefmt='%a, %d %b %Y %H:%M:%S',
format='%(asctime)s %(levelname)-8s %(name)-8s %(message)s',
stream=sys.stdout)

server = "client-lb.dropbox.com"

try:
infile = sys.argv[1]
except IndexError:
err.write('Usage: %s <infile.json> [<path>]\n' %
sys.stderr.write('Usage: %s <infile.json> [<path>]\n' %
sys.argv[0])
exit(1)

if len(sys.argv)>2:
if len(sys.argv) > 2:
path = sys.argv[2]
else:
path = None
path = None

f = open(infile, 'r')
try:
indata = json.load(f)
except ValueError,e:
err.write('Error parsing input file: %s\n' % e)
except ValueError, e:
sys.stderr.write('Error parsing input file: %s\n' % e)
exit(1)
f.close()

Expand All @@ -63,13 +63,12 @@ if __name__ == '__main__':
if not path.startswith('/'):
path = '/' + path

s = MetadataClient(server, host_id, root_ns)
s = MetadataClient(SERVER_ADDRESS, host_id, root_ns)
try:
s.inject_file(path, indata['blocks'], indata['size'],
s.inject_file(path, indata['blocks'], indata['size'],
indata.get('mtime', None))
except (APIError,UnknownBlocksError),e:
err.write('%s\n' % e)
except (APIError, UnknownBlocksError), e:
sys.stderr.write('%s\n' % e)
exit(1)

out.write("File %s dropshipped succesfully.\n" % path)

sys.stdout.write('File %s dropshipped succesfully.\n' % path)
37 changes: 15 additions & 22 deletions hash_blocks
Expand Up @@ -11,7 +11,7 @@ Hash a file per 4MB. Produce a blocklist that can be used with
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
Expand All @@ -22,43 +22,36 @@ Hash a file per 4MB. Produce a blocklist that can be used with
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
import json
import hashlib
from sys import stdout as out, stderr as err
import json
import os
from os import path
import sys

BLOCKSIZE = 4*1024*1024
BLOCKSIZE = 4 * 1024 * 1024

if __name__ == "__main__":
import sys
if __name__ == '__main__':
try:
filename = sys.argv[1]
except IndexError:
err.write("Usage: %s <file>\n" % sys.argv[0])
sys.stderr.write('Usage: %s <file>\n' % sys.argv[0])
exit(1)
f = open(filename, "rb")
f = open(filename, 'rb')
barray = []

while True:
data = f.read(BLOCKSIZE)
if not data:
break
barray.append(hashlib.sha256(data).hexdigest())

size = f.tell()
stat = os.stat(filename)

outdata = {
"blocks":barray,
"size":size,
"name":path.basename(filename),
"mtime":stat.st_mtime,
'blocks': barray,
'size': size,
'name': os.path.basename(filename),
'mtime': stat.st_mtime,
}
outdata = json.dumps(outdata) + '\n'

out.write(outdata)




sys.stdout.write(outdata)