Skip to content

Commit

Permalink
All tests pass
Browse files Browse the repository at this point in the history
  • Loading branch information
noirbizarre committed Apr 25, 2016
1 parent b97cf15 commit e90a7f2
Show file tree
Hide file tree
Showing 16 changed files with 270 additions and 437 deletions.
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,7 @@ script:
- nosetests --with-coverage
after_success:
- coveralls --rcfile=coverage.rc

matrix:
allow_failures:
- python: pypy3
8 changes: 8 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,12 @@ Changelog
Current
-------

- Proper github publication
- GridFS and S3 backend implementations
- Python 3 fixes


0.1 (2015-04-07)
----------------

- Initial release
4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ Compatibility

Flask-FS requires Python 2.7+ and Flask 0.10+.

Amazon S3 support requires Boto3.

.. Amazon S3 support requires Boto.
GridFS support requires PyMongo 3+.

.. OpenStack Swift support requires python-swift-client.
.. GridFS support requires PyMongo.
Installation
Expand Down
8 changes: 4 additions & 4 deletions docs/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ Each backend has its own dependencies:

.. code-block:: console
$ pip install flask-fs[s3]
$ pip install flask-fs[swift]
$ pip install flask-fs[gridfs]
$ pip install flask-fs[all]
$ pip install flask-fs[s3] # For Amazon S3 backend support
$ pip install flask-fs[swift] # For OpenStack swift backend support
$ pip install flask-fs[gridfs] # For GridFS backend support
$ pip install flask-fs[all] # To include all dependencies for all backends
The development version can be downloaded from
Expand Down
5 changes: 3 additions & 2 deletions flask_fs/backends/gridfs.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals, absolute_import

import codecs
import io
import logging

Expand All @@ -27,7 +28,6 @@ class GridFsBackend(BaseBackend):
'''
def __init__(self, name, config):
super(GridFsBackend, self).__init__(name, config)
self.bucket = self.name

self.client = MongoClient(config.mongo_url)
self.db = self.client[config.mongo_db]
Expand All @@ -39,7 +39,8 @@ def exists(self, filename):
@contextmanager
def open(self, filename, mode='r', encoding='utf8'):
if 'r' in mode:
yield self.fs.get_last_version(filename)
f = self.fs.get_last_version(filename)
yield f if 'b' in mode else codecs.getreader(encoding)(f)
else: # mode == 'w'
f = io.BytesIO() if 'b' in mode else io.StringIO()
yield f
Expand Down
10 changes: 7 additions & 3 deletions flask_fs/backends/local.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

import io
import logging
import os

Expand Down Expand Up @@ -31,12 +32,15 @@ def exists(self, filename):
dest = self.path(filename)
return os.path.exists(dest)

def open(self, filename, *args, **kwargs):
def open(self, filename, mode='r', encoding='utf8'):
dest = self.path(filename)
return open(dest, *args, **kwargs)
if 'b' in mode:
return open(dest, mode)
else:
return io.open(dest, mode, encoding=encoding)

def read(self, filename):
with self.open(filename) as f:
with self.open(filename, 'rb') as f:
return f.read()

def write(self, filename, content):
Expand Down
4 changes: 3 additions & 1 deletion flask_fs/backends/s3.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

import codecs
import io
import logging

Expand Down Expand Up @@ -56,7 +57,8 @@ def exists(self, filename):
def open(self, filename, mode='r', encoding='utf8'):
obj = self.bucket.Object(filename)
if 'r' in mode:
yield obj.get()['Body']
f = obj.get()['Body']
yield f if 'b' in mode else codecs.getreader(encoding)(f)
else: # mode == 'w'
f = io.BytesIO() if 'b' in mode else io.StringIO()
yield f
Expand Down
2 changes: 0 additions & 2 deletions flask_fs/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,6 @@ class Storage(object):
'''

def __init__(self, name='files', extensions=DEFAULTS, upload_to=None, overwrite=False):
# if not name.isalnum():
# raise ValueError("Name must be alphanumeric (no underscores)")
self.name = name
self.extensions = extensions
self.config = Config()
Expand Down
5 changes: 5 additions & 0 deletions requirements/doc.pip
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
-r s3.pip
-r swift.pip
-r gridfs.pip
sphinx
alabaster
pillow
flask-mongoengine
18 changes: 12 additions & 6 deletions tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@

BIN_FILE = os.path.join(os.path.dirname(__file__), 'flask.png')

S3_SERVER = 'http://localhost:9000'
S3_REGION = 'us-east-1'
S3_ACCESS_KEY = 'ABCDEFGHIJKLMNOQRSTU'
S3_SECRET_KEY = 'abcdefghiklmnoqrstuvwxyz1234567890abcdef'

fake = Faker()


Expand All @@ -39,6 +34,17 @@ def file(self, content):
if isinstance(content, six.binary_type):
return io.BytesIO(content)
elif isinstance(content, six.string_types):
return io.StringIO(content)
return io.BytesIO(content.encode('utf-8'))
else:
return content

def b(self, content):
if isinstance(content, six.string_types):
content = six.b(content)
return content

def text(self):
return six.text_type(fake.sentence())

def binary(self):
return six.binary_type(fake.binary())
134 changes: 134 additions & 0 deletions tests/test_backend_mixin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

import six

from . import fake


class BackendTestMixin(object):

def put_file(self, filename, content):
raise NotImplementedError('You should implement this method')

def get_file(self, filename):
raise NotImplementedError('You should implement this method')

def file_exists(self, filename):
raise NotImplementedError('You should implement this method')

def assert_bin_equal(self, filename, expected):
data = self.get_file(filename)
self.assertEqual(data, self.b(expected))

def assert_text_equal(self, filename, expected):
data = self.get_file(filename)
# self.assertIsInstance(data, six.string_types)
self.assertEqual(data, six.b(expected))

def test_exists(self):
self.put_file('file.test', 'test')
self.assertTrue(self.backend.exists('file.test'))
self.assertFalse(self.backend.exists('other.test'))

def test_open_read(self):
content = self.text()
self.put_file('file.test', content)

with self.backend.open('file.test') as f:
data = f.read()
self.assertIsInstance(data, six.text_type)
self.assertEqual(data, content)

def test_open_read_binary(self):
content = self.binary()
self.put_file('file.test', content)

with self.backend.open('file.test', 'rb') as f:
data = f.read()
self.assertIsInstance(data, six.binary_type)
self.assertEqual(data, content)

def test_open_write_new_file(self):
filename = 'test.text'
content = self.text()

with self.backend.open(filename, 'w') as f:
f.write(content)

self.assert_text_equal(filename, content)

def test_open_write_new_binary_file(self):
filename = 'test.bin'
content = self.binary()

with self.backend.open(filename, 'wb') as f:
f.write(content)

self.assert_bin_equal(filename, content)

def test_open_write_existing_file(self):
filename = 'test.txt'
content = self.text()
self.put_file(filename, self.text())

with self.backend.open(filename, 'w') as f:
f.write(content)

self.assert_text_equal(filename, content)

def test_read(self):
content = self.text()
self.put_file('file.test', content)

self.assertEqual(self.backend.read('file.test'), six.b(content))

def test_write_text(self):
content = self.text()
self.backend.write('test.txt', content)

self.assert_text_equal('test.txt', content)

def test_write_binary(self):
content = self.binary()
self.backend.write('test.bin', content)

self.assert_bin_equal('test.bin', content)

def test_write_file(self):
content = self.binary()
self.backend.write('test.bin', self.file(content))

self.assert_bin_equal('test.bin', content)

def test_delete(self):
content = fake.sentence()
self.put_file('file.test', content)

self.backend.delete('file.test')

self.assertFalse(self.file_exists('file.test'))

def test_save_content(self):
content = self.text()
storage = self.filestorage('test.txt', content)
self.backend.save(storage, 'test.txt')

self.assert_text_equal('test.txt', content)

def test_save_from_file(self):
content = self.binary()
f = self.file(content)
self.backend.save(f, 'test.png')

f.seek(0)

self.assert_bin_equal('test.png', content)

def test_save_with_filename(self):
filename = 'somewhere/test.test'
content = self.text()
storage = self.filestorage('test.txt', content)
self.backend.save(storage, filename)

self.assert_text_equal(filename, content)

0 comments on commit e90a7f2

Please sign in to comment.