Permalink
Browse files

First stable version

  • Loading branch information...
1 parent 05110af commit 49d0df2d4723010ce3cf082d9c990f5c1fc3bf5a @andres-torres-marroquin committed Dec 19, 2011
View
@@ -0,0 +1,10 @@
+.project
+.pydevproject
+.DS_Store
+*.pyc
+bin/
+lib/
+include/
+build/
+.Python
+local_settings.py
No changes.
@@ -0,0 +1,20 @@
+from django.core.management.base import NoArgsCommand
+from dropbox import rest, session
+from django_dropbox.settings import CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TYPE
+
+class Command(NoArgsCommand):
+
+ def handle_noargs(self, *args, **options):
+ sess = session.DropboxSession(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TYPE)
+ request_token = sess.obtain_request_token()
+
+ url = sess.build_authorize_url(request_token)
+ print "Url:", url
+ print "Please visit this website and press the 'Allow' button, then hit 'Enter' here."
+ raw_input()
+
+ # This will fail if the user didn't visit the above URL and hit 'Allow'
+ access_token = sess.obtain_access_token(request_token)
+
+ print "DROPBOX_ACCESS_TOKEN = '%s'" % access_token.key
+ print "DROPBOX_ACCESS_TOKEN_SECRET = '%s'" % access_token.secret
@@ -0,0 +1,10 @@
+from django.conf import settings
+
+CONSUMER_KEY = getattr(settings, 'DROPBOX_CONSUMER_KEY', None)
+CONSUMER_SECRET = getattr(settings, 'DROPBOX_CONSUMER_SECRET', None)
+ACCESS_TOKEN = getattr(settings, 'DROPBOX_ACCESS_TOKEN', None)
+ACCESS_TOKEN_SECRET = getattr(settings, 'DROPBOX_ACCESS_TOKEN_SECRET', None)
+
+# ACCESS_TYPE should be 'dropbox' or 'app_folder' as configured for your app
+ACCESS_TYPE = 'dropbox'
+
@@ -0,0 +1,139 @@
+import errno
+import os.path
+import re
+import urlparse
+import urllib
+import itertools
+try:
+ from cStringIO import StringIO
+except ImportError:
+ from StringIO import StringIO
+from dropbox.session import DropboxSession
+from dropbox.client import DropboxClient
+from dropbox.rest import ErrorResponse
+from django.core.files import File
+from django.core.files.storage import Storage
+from django.utils.encoding import filepath_to_uri
+
+from .settings import (CONSUMER_KEY, CONSUMER_SECRET,
+ ACCESS_TYPE, ACCESS_TOKEN, ACCESS_TOKEN_SECRET, CONFIG,
+ CONTENT_SERVER, PORT, SERVER)
+
+class DropboxStorage(Storage):
+ """
+ A storage class providing access to resources in a Dropbox Public folder.
+ """
+
+ def __init__(self, location='/Public'):
+ session = DropboxSession(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TYPE, locale=None)
+ session.set_token(ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
+ self.client = DropboxClient(session)
+ self.account_info = self.client.account_info()
+ self.location = location
+ self.base_url = 'http://dl.dropbox.com/u/{uid}/'.format(**self.account_info)
+
+ def _get_abs_path(self, name):
+ return os.path.realpath(os.path.join(self.location, name))
+
+ def _open(self, name, mode='rb'):
+ name = self._get_abs_path(name)
+ remote_file = DropboxFile(name, self, mode=mode)
+ return remote_file
+
+ def _save(self, name, content):
+ name = self._get_abs_path(name)
+ directory = os.path.dirname(name)
+ if not self.exists(directory) and directory:
+ self.client.file_create_folder(directory)
+ response = self.client.metadata(directory)
+ if not response['is_dir']:
+ raise IOError("%s exists and is not a directory." % directory)
+ abs_name = os.path.realpath(os.path.join(self.location, name))
+ self.client.put_file(abs_name, content)
+ return name
+
+ def delete(self, name):
+ name = self._get_abs_path(name)
+ self.client.file_delete(name)
+
+ def exists(self, name):
+ name = self._get_abs_path(name)
+ try:
+ metadata = self.client.metadata(name)
+ if metadata.get('is_deleted'):
+ return False
+ except ErrorResponse as e:
+ if e.status == 404: # not found
+ return False
+ raise e
+ return True
+
+ def listdir(self, path):
+ path = self._get_abs_path(path)
+ response = self.client.metadata(path)
+ directories = []
+ files = []
+ for entry in response.get('contents', []):
+ if entry['is_dir']:
+ directories.append(os.path.basename(entry['path']))
+ else:
+ files.append(os.path.basename(entry['path']))
+ return directories, files
+
+ def size(self, name):
+ path = os.path.realpath(os.path.join(self.location, name))
+ return self.client.metadata("dropbox", path).data['bytes']
+
+ def url(self, name):
+ if name.startswith(self.location):
+ name = name[len(self.location) + 1:]
+ if self.base_url is None:
+ raise ValueError("This file is not accessible via a URL.")
+ return urlparse.urljoin(self.base_url, filepath_to_uri(name))
+
+ def get_available_name(self, name):
+ """
+ Returns a filename that's free on the target storage system, and
+ available for new content to be written to.
+ """
+ name = self._get_abs_path(name)
+ dir_name, file_name = os.path.split(name)
+ file_root, file_ext = os.path.splitext(file_name)
+ # If the filename already exists, add an underscore and a number (before
+ # the file extension, if one exists) to the filename until the generated
+ # filename doesn't exist.
+ count = itertools.count(1)
+ while self.exists(name):
+ # file_ext includes the dot.
+ name = os.path.join(dir_name, "%s_%s%s" % (file_root, count.next(), file_ext))
+
+ return name
+
+class DropboxFile(File):
+ def __init__(self, name, storage, mode):
+ self._storage = storage
+ self._mode = mode
+ self._is_dirty = False
+ self.file = StringIO()
+ self.start_range = 0
+ self._name = name
+
+ @property
+ def size(self):
+ if not hasattr(self, '_size'):
+ self._size = self._storage.size(self._name)
+ return self._size
+
+ def read(self, num_bytes=None):
+ return self._storage.client.get_file(self._name).read()
+
+ def write(self, content):
+ if 'w' not in self._mode:
+ raise AttributeError("File was opened for read-only access.")
+ self.file = StringIO(content)
+ self._is_dirty = True
+
+ def close(self):
+ if self._is_dirty:
+ self._storage.client.put_file(self._name, self.file.getvalue())
+ self.file.close()
@@ -0,0 +1,75 @@
+#import os
+from django.core.files.base import ContentFile
+from django.test import TestCase
+from django_dropbox.storage import DropboxStorage
+
+class DropboxStorageTest(TestCase):
+
+ def setUp(self):
+ self.location = '/Public/testing'
+ self.storage = DropboxStorage(location=self.location)
+ self.storage.base_url = '/test_media_url/'
+
+ def test_file_access_options(self):
+ """
+ Standard file access options are available, and work as expected.
+ """
+ self.assertFalse(self.storage.exists('storage_test'))
+ f = self.storage.open('storage_test', 'w')
+ f.write('storage contents')
+ f.close()
+ self.assertTrue(self.storage.exists('storage_test'))
+
+ f = self.storage.open('storage_test', 'r')
+ self.assertEqual(f.read(), 'storage contents')
+ f.close()
+
+ self.storage.delete('storage_test')
+ self.assertFalse(self.storage.exists('storage_test'))
+
+ def test_exists_folder(self):
+ self.assertFalse(self.storage.exists('storage_test_exists'))
+ self.storage.client.file_create_folder(self.location + '/storage_test_exists')
+ self.assertTrue(self.storage.exists('storage_test_exists'))
+ self.storage.delete('storage_test_exists')
+ self.assertFalse(self.storage.exists('storage_test_exists'))
+
+ def test_listdir(self):
+ """
+ File storage returns a tuple containing directories and files.
+ """
+ self.assertFalse(self.storage.exists('storage_test_1'))
+ self.assertFalse(self.storage.exists('storage_test_2'))
+ self.assertFalse(self.storage.exists('storage_dir_1'))
+
+ f = self.storage.save('storage_test_1', ContentFile('custom content'))
+ f = self.storage.save('storage_test_2', ContentFile('custom content'))
+ self.storage.client.file_create_folder(self.location + '/storage_dir_1')
+
+ dirs, files = self.storage.listdir(self.location)
+ self.assertEqual(set(dirs), set([u'storage_dir_1']))
+ self.assertEqual(set(files),
+ set([u'storage_test_1', u'storage_test_2']))
+
+ self.storage.delete('storage_test_1')
+ self.storage.delete('storage_test_2')
+ self.storage.delete('storage_dir_1')
+
+ def test_file_url(self):
+ """
+ File storage returns a url to access a given file from the Web.
+ """
+ self.assertEqual(self.storage.url('test.file'),
+ '%s%s' % (self.storage.base_url, 'test.file'))
+
+ # should encode special chars except ~!*()'
+ # like encodeURIComponent() JavaScript function do
+ self.assertEqual(self.storage.url(r"""~!*()'@#$%^&*abc`+=.file"""),
+ """/test_media_url/~!*()'%40%23%24%25%5E%26*abc%60%2B%3D.file""")
+
+ # should stanslate os path separator(s) to the url path separator
+ self.assertEqual(self.storage.url("""a/b\\c.file"""),
+ """/test_media_url/a/b/c.file""")
+
+ self.storage.base_url = None
+ self.assertRaises(ValueError, self.storage.url, 'test.file')
@@ -0,0 +1,13 @@
+from django.contrib import admin
+from dropbox_testing.models import Person
+
+class PersonAdmin(admin.ModelAdmin):
+ list_display = ('image',)
+
+ def image(self, obj):
+ if obj.photo:
+ return '<img src="%s">' % obj.photo.url
+ return ''
+ image.allow_tags = True
+
+admin.site.register(Person, PersonAdmin)
@@ -0,0 +1,8 @@
+from django.db import models
+from django_dropbox.storage import DropboxStorage
+
+STORAGE = DropboxStorage()
+
+class Person(models.Model):
+ photo = models.ImageField(upload_to='photos', storage=STORAGE, null=True, blank=True)
+ resume = models.FileField(upload_to='resumes', storage=STORAGE, null=True, blank=True)
@@ -0,0 +1,16 @@
+"""
+This file demonstrates writing tests using the unittest module. These will pass
+when you run "manage.py test".
+
+Replace this with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+
+class SimpleTest(TestCase):
+ def test_basic_addition(self):
+ """
+ Tests that 1 + 1 always equals 2.
+ """
+ self.assertEqual(1 + 1, 2)
@@ -0,0 +1 @@
+# Create your views here.
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+from django.core.management import execute_manager
+import imp
+try:
+ imp.find_module('settings') # Assumed to be in the same directory.
+except ImportError:
+ import sys
+ sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n" % __file__)
+ sys.exit(1)
+
+import settings
+
+if __name__ == "__main__":
+ execute_manager(settings)
Oops, something went wrong.

0 comments on commit 49d0df2

Please sign in to comment.