Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A quick fix for DropboxSync to stop it crashing in Pythonista 1.4 when trying to write to Inbox by forcing it not to write to Inbox. There are probably more elegant solutions...
import os
import sys
import pickle
import console
# I moved 'dropboxlogin' into a sub folder so it doesn't clutter my main folder
sys.path += [os.path.join(os.path.dirname(os.path.abspath(__file__)), 'lib')]
import dropboxlogin # this code can be found here https://gist.github.com/4034526
STATE_FILE = '.dropbox_state'
class dropbox_state:
def __init__(self):
self.cursor = None
self.local_files = {}
self.remote_files = {}
# use ignore_path to prevent download of recently uploaded files
def execute_delta(self, client, ignore_path = None):
delta = client.delta(self.cursor)
self.cursor = delta['cursor']
for entry in delta['entries']:
path = entry[0][1:]
meta = entry[1]
# this skips the path if we just uploaded it
if path != ignore_path:
if meta != None:
path = meta['path'][1:] # caps sensitive
if meta['is_dir']:
print '\n\tMaking Directory:',path
self.makedir_local(path)
elif path not in self.remote_files:
print '\n\tNot in local'
self.download(client, path)
elif meta['rev'] != self.remote_files[path]['rev']:
print '\n\tOutdated revision'
self.download(client, path)
# remove file or directory
else:
if os.path.isdir(path):
print '\n\tRemoving Directory:', path
os.removedirs(path)
elif os.path.isfile(path):
print '\n\tRemoving File:', path
os.remove(path)
del self.local_files[path]
del self.remote_files[path]
else:
pass # file already doesn't exist localy
# makes dirs if necessary, downloads, and adds to local state data
def download(self, client, path):
print '\tDownloading:', path
# TODO: what if there is a folder there...?
head, tail = os.path.split(path)
# omit files in Inbox _ next line and indent added by sidewinder42
if not head=='Inbox':
# make the folder if it doesn't exist yet
if not os.path.exists(head) and head != '':
os.makedirs(head)
#open file to write
local = open(path,'w')
remote, meta = client.get_file_and_metadata(os.path.join('/',path))
local.write(remote.read())
#clean up
remote.close()
local.close()
# add to local repository
self.local_files[path] = {'modified': os.path.getmtime(path)}
self.remote_files[path] = meta
def upload(self, client, path):
print '\tUploading:', path
local = open(path,'r')
meta = client.put_file(os.path.join('/',path), local, True)
local.close()
self.local_files[path] = {'modified': os.path.getmtime(path)}
self.remote_files[path] = meta
# clean out the delta for the file upload
self.execute_delta(client, ignore_path=meta['path'])
def delete(self, client, path):
print '\tFile deleted locally. Deleting on Dropbox:',path
try:
client.file_delete(path)
except:
# file was probably already deleted
print '\tFile already removed from Dropbox'
del self.local_files[path]
del self.remote_files[path]
# safely makes local dir
def makedir_local(self,path):
if not os.path.exists(path): # no need to make a dir that exists
os.makedirs(path)
elif os.path.isfile(path): # if there is a file there ditch it
os.remove(path)
del self.files[path]
os.makedir(path)
# recursively list files on dropbox
def _listfiles(self, client, path = '/'):
meta = client.metadata(path)
filelist = []
for item in meta['contents']:
if item['is_dir']:
filelist += self._listfiles(client,item['path'])
else:
filelist.append(item['path'])
return filelist
def download_all(self, client, path = '/'):
filelist = self._listfiles(client)
for file in filelist:
self.download(client, file[1:]) # trim root slash
def check_state(self, client, path):
# lets see if we've seen it before
if path not in self.local_files:
# upload it!
self.upload(client, path)
elif os.path.getmtime(path) > self.local_files[path]['modified']:
# newer file than last sync
self.upload(client, path)
else:
pass # looks like everything is good
def loadstate():
fyle = open(STATE_FILE,'r')
state = pickle.load(fyle)
fyle.close()
return state
def savestate(state):
fyle = open(STATE_FILE,'w')
pickle.dump(state,fyle)
fyle.close()
if __name__ == '__main__':
console.show_activity()
print """
****************************************
* Dropbox File Syncronization *
****************************************"""
client = dropboxlogin.get_client()
print '\nLoading local state'
# lets see if we can unpickle
try:
state = loadstate()
except:
print '\nCannot find state file. ***Making new local state***'
# Aaaah, we have nothing, probably first run
state = dropbox_state()
print '\nDownloading everything from Dropbox'
# no way to check what we have locally is newer, gratuitous dl
state.download_all(client)
print '\nUpdating state from Dropbox'
state.execute_delta(client)
print '\nChecking for new or updated local files'
# back to business, lets see if there is anything new or changed localy
filelist = []
for root, dirnames, filenames in os.walk('.'):
for filename in filenames:
if filename != STATE_FILE:
filelist.append( os.path.join(root, filename)[2:])
for file in filelist:
state.check_state(client,file)
print '\nChecking for deleted local files'
old_list = state.local_files.keys()
for file in old_list:
if file not in filelist:
state.delete(client, file)
print '\nSaving local state'
savestate(state)
print '\nSync complete'
@henryiii

This comment has been minimized.

Copy link

henryiii commented Mar 4, 2014

Ideally, making an ignore list (ignore = ['Inbox']) at the beginning would be more ideal, because then people could add files/directories to it to ignore.

@cclauss

This comment has been minimized.

Copy link

cclauss commented Aug 18, 2014

You might try putting console.set_idle_timer_disabled(True) at the top of the script to keep your device awake for the longer syncs.

Could we make this a repo instead of a gist to improve collaboration?

@zencuke

This comment has been minimized.

Copy link

zencuke commented Sep 18, 2015

Shouldn't dropboxlogin go in the standard site-packages directory instead of the idiosyncratic lib directory?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.