mirror of
https://github.com/wassname/flask-s3.git
synced 2026-06-27 15:50:06 +08:00
general tidy up and version bump
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) 2004 Edward Robinson <me@eddrobinson.net>
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified
|
||||
copies of this license document, and changing it is allowed as long
|
||||
|
||||
+57
-51
@@ -2,8 +2,9 @@ Flask-S3
|
||||
********
|
||||
.. module:: flask_s3
|
||||
|
||||
Flask-S3 allows you to easily serve all your `Flask`_ application's static
|
||||
assets from `Amazon S3`_, without having to modify your templates.
|
||||
Flask-S3 allows you to easily serve all your `Flask`_ application's
|
||||
static assets from `Amazon S3`_, without having to modify your
|
||||
templates.
|
||||
|
||||
.. _Amazon S3: http://aws.amazon.com/s3
|
||||
.. _Flask: http://flask.pocoo.org/
|
||||
@@ -14,24 +15,26 @@ How it works
|
||||
|
||||
Flask-S3 has two main functions:
|
||||
|
||||
1. Walk through your application's static folders, gather all your static
|
||||
assets together, and upload them to a bucket of your choice on S3;
|
||||
1. Walk through your application's static folders, gather all your
|
||||
static assets together, and upload them to a bucket of your choice
|
||||
on S3;
|
||||
|
||||
2. Replace the URLs that Flask's :func:`flask.url_for` function would insert
|
||||
into your templates, with URLs that point to the static assets in your S3
|
||||
bucket.
|
||||
2. Replace the URLs that Flask's :func:`flask.url_for` function would
|
||||
insert into your templates, with URLs that point to the static
|
||||
assets in your S3 bucket.
|
||||
|
||||
The process of gathering and uploading your static assets to S3 need only be
|
||||
done once, and your application does not need to be running for it to work. The
|
||||
location of the S3 bucket can be inferred from Flask-S3 `settings`_ specified in
|
||||
your Flask application, therefore when your application is running there need
|
||||
not be any communication between the Flask application and Amazon S3.
|
||||
The process of gathering and uploading your static assets to S3 need
|
||||
only be done once, and your application does not need to be running for
|
||||
it to work. The location of the S3 bucket can be inferred from Flask-S3
|
||||
`settings`_ specified in your Flask application, therefore when your
|
||||
application is running there need not be any communication between the
|
||||
Flask application and Amazon S3.
|
||||
|
||||
Internally, every time ``url_for`` is called in one of your application's
|
||||
templates, `flask_s3.url_for` is instead invoked. If the endpoint provided is
|
||||
deemed to refer to static assets, then the S3 URL for the asset specified in the
|
||||
`filename` argument is instead returned. Otherwise, `flask_s3.url_for` passes
|
||||
the call on to `flask.url_for`.
|
||||
Internally, every time ``url_for`` is called in one of your
|
||||
application's templates, `flask_s3.url_for` is instead invoked. If the
|
||||
endpoint provided is deemed to refer to static assets, then the S3 URL
|
||||
for the asset specified in the `filename` argument is instead returned.
|
||||
Otherwise, `flask_s3.url_for` passes the call on to `flask.url_for`.
|
||||
|
||||
|
||||
Installation
|
||||
@@ -52,9 +55,10 @@ You can also install Flask-S3 via Easy Install::
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
Aside from the obvious dependency of Flask itself, Flask-S3 makes use of the
|
||||
`boto`_ library for uploading assets to Amazon S3. **Note**: Flask-S3 currently
|
||||
only supports applications that use the `jinja2`_ templating system.
|
||||
Aside from the obvious dependency of Flask itself, Flask-S3 makes use of
|
||||
the `boto`_ library for uploading assets to Amazon S3. **Note**:
|
||||
Flask-S3 currently only supports applications that use the `jinja2`_
|
||||
templating system.
|
||||
|
||||
.. _boto: http://docs.pythonboto.org/en/latest/
|
||||
.. _jinja2: http://jinja.pocoo.org/docs/
|
||||
@@ -63,9 +67,9 @@ only supports applications that use the `jinja2`_ templating system.
|
||||
Using Flask-S3
|
||||
==============
|
||||
|
||||
Flask-S3 is incredibly simple to use. In order to start serving your Flask
|
||||
application's assets from Amazon S3, the first thing to do is let Flask-S3 know
|
||||
about your :class:`flask.Flask` application object.
|
||||
Flask-S3 is incredibly simple to use. In order to start serving your
|
||||
Flask application's assets from Amazon S3, the first thing to do is let
|
||||
Flask-S3 know about your :class:`flask.Flask` application object.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -76,11 +80,11 @@ about your :class:`flask.Flask` application object.
|
||||
app.config['S3_BUCKET_NAME'] = 'mybucketname'
|
||||
s3 = FlaskS3(app)
|
||||
|
||||
In many cases, however, one cannot expect a Flask instance to be ready at
|
||||
import time, and a common pattern is to return a Flask instance from within a
|
||||
function only after other configuration details have been taken care of. In
|
||||
these cases, Flask-S3 provides a simple function, ``init_app``, which takes your
|
||||
application as an argument.
|
||||
In many cases, however, one cannot expect a Flask instance to be ready
|
||||
at import time, and a common pattern is to return a Flask instance from
|
||||
within a function only after other configuration details have been taken
|
||||
care of. In these cases, Flask-S3 provides a simple function,
|
||||
``init_app``, which takes your application as an argument.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -94,20 +98,21 @@ application as an argument.
|
||||
s3.init_app(app)
|
||||
return app
|
||||
|
||||
In terms of getting your application to use external Amazon S3 URLs when
|
||||
referring to your application's static assets, passing your ``Flask`` object to
|
||||
the ``FlaskS3`` object is all that needs to be done. Once your app is running,
|
||||
any templates that contained relative static asset locations, will instead
|
||||
contain hosted counterparts on Amazon S3.
|
||||
In terms of getting your application to use external Amazon S3 URLs when
|
||||
referring to your application's static assets, passing your ``Flask``
|
||||
object to the ``FlaskS3`` object is all that needs to be done. Once your
|
||||
app is running, any templates that contained relative static asset
|
||||
locations, will instead contain hosted counterparts on Amazon S3.
|
||||
|
||||
Uploading your Static Assets
|
||||
----------------------------
|
||||
|
||||
You only need to upload your static assets to Amazon S3 once. Of course, if you
|
||||
add or modify your existing assets then you will need to repeat the uploading
|
||||
process.
|
||||
You only need to upload your static assets to Amazon S3 once. Of course,
|
||||
if you add or modify your existing assets then you will need to repeat
|
||||
the uploading process.
|
||||
|
||||
Uploading your static assets from a Python console is as simple as follows.
|
||||
Uploading your static assets from a Python console is as simple as
|
||||
follows.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -116,23 +121,23 @@ Uploading your static assets from a Python console is as simple as follows.
|
||||
>>> flask_s3.create_all(app)
|
||||
>>>
|
||||
|
||||
Flask-S3 will proceed to walk through your application's static assets,
|
||||
including those belonging to *registered* `blueprints`_, and upload them to your
|
||||
Amazon S3 bucket.
|
||||
Flask-S3 will proceed to walk through your application's static assets,
|
||||
including those belonging to *registered* `blueprints`_, and upload them
|
||||
to your Amazon S3 bucket.
|
||||
|
||||
.. _blueprints: http://flask.pocoo.org/docs/blueprints/
|
||||
|
||||
Static Asset URLs
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Within your bucket on S3, Flask-S3 replicates the static file hierarchy defined
|
||||
in your application object and any registered blueprints. URLs generated by
|
||||
Flask-S3 will look like the following:
|
||||
Within your bucket on S3, Flask-S3 replicates the static file hierarchy
|
||||
defined in your application object and any registered blueprints. URLs
|
||||
generated by Flask-S3 will look like the following:
|
||||
|
||||
``/static/foo/style.css`` becomes
|
||||
``https://mybucketname.s3.amazonaws.com/static/foo/style.css``,
|
||||
assuming that ``mybucketname`` is the name of your S3 bucket, and you have
|
||||
chosen to have assets served over HTTPS.
|
||||
``https://mybucketname.s3.amazonaws.com/static/foo/style.css``, assuming
|
||||
that ``mybucketname`` is the name of your S3 bucket, and you have chosen
|
||||
to have assets served over HTTPS.
|
||||
|
||||
|
||||
.. _settings:
|
||||
@@ -141,9 +146,10 @@ chosen to have assets served over HTTPS.
|
||||
Flask-S3 Options
|
||||
----------------
|
||||
|
||||
Within your Flask application's settings you can provide the following settings
|
||||
to control the behvaiour of Flask-S3. None of the settings are required, but if
|
||||
not present, some will need to be provided when uploading assets to S3.
|
||||
Within your Flask application's settings you can provide the following
|
||||
settings to control the behvaiour of Flask-S3. None of the settings are
|
||||
required, but if not present, some will need to be provided when
|
||||
uploading assets to S3.
|
||||
|
||||
=========================== ===================================================
|
||||
`AWS_ACCESS_KEY_ID` Your AWS access key. This does not need to be
|
||||
@@ -188,8 +194,8 @@ not present, some will need to be provided when uploading assets to S3.
|
||||
API Documentation
|
||||
=================
|
||||
|
||||
Flask-S3 is a very simple extension. The few exposed objects, methods and
|
||||
functions are as follows.
|
||||
Flask-S3 is a very simple extension. The few exposed objects, methods
|
||||
and functions are as follows.
|
||||
|
||||
The FlaskS3 Object
|
||||
------------------
|
||||
|
||||
+49
-29
@@ -18,10 +18,11 @@ def url_for(endpoint, **values):
|
||||
generated, otherwise the call is passed on to `flask.url_for`.
|
||||
|
||||
Because this function is set as a jinja environment variable when
|
||||
`FlaskS3.init_app` is invoked, this function replaces `flask.url_for` in
|
||||
templates automatically. It is unlikely that this function will
|
||||
need to be directly called from within your application code, unless you
|
||||
need to refer to static assets outside of your templates.
|
||||
`FlaskS3.init_app` is invoked, this function replaces
|
||||
`flask.url_for` in templates automatically. It is unlikely that this
|
||||
function will need to be directly called from within your
|
||||
application code, unless you need to refer to static assets outside
|
||||
of your templates.
|
||||
"""
|
||||
app = current_app
|
||||
if 'S3_BUCKET_NAME' not in app.config:
|
||||
@@ -42,7 +43,8 @@ def url_for(endpoint, **values):
|
||||
|
||||
def _bp_static_url(blueprint):
|
||||
""" builds the absolute url path for a blueprint's static folder """
|
||||
return u'%s%s' % (blueprint.url_prefix or '', blueprint.static_url_path or '')
|
||||
u = u'%s%s' % (blueprint.url_prefix or '', blueprint.static_url_path or '')
|
||||
return u
|
||||
|
||||
def _gather_files(app, hidden):
|
||||
""" Gets all files in static folders and returns in dict."""
|
||||
@@ -76,8 +78,9 @@ def _static_folder_path(static_url, static_folder, static_asset):
|
||||
|
||||
Returns a path relative to static_url for static_asset
|
||||
"""
|
||||
# first get the asset path relative to the static folder. static_asset is
|
||||
# not simply a filename because it could be sub-directory then file etc.
|
||||
# first get the asset path relative to the static folder.
|
||||
# static_asset is not simply a filename because it could be
|
||||
# sub-directory then file etc.
|
||||
if not static_asset.startswith(static_folder):
|
||||
raise ValueError("%s startic asset must be under %s static folder" %
|
||||
(static_asset, static_folder))
|
||||
@@ -90,8 +93,10 @@ def _write_files(app, static_url_loc, static_folder, files, bucket,
|
||||
""" Writes all the files inside a static folder to S3. """
|
||||
for file_path in files:
|
||||
asset_loc = _path_to_relative_url(file_path)
|
||||
key_name = _static_folder_path(static_url_loc, static_folder, asset_loc)
|
||||
logger.debug("Uploading %s to %s as %s" % (file_path, bucket, key_name))
|
||||
key_name = _static_folder_path(static_url_loc, static_folder,
|
||||
asset_loc)
|
||||
msg = "Uploading %s to %s as %s" % (file_path, bucket, key_name)
|
||||
logger.debug(msg)
|
||||
if ex_keys and key_name in ex_keys:
|
||||
logger.debug("%s excluded from upload" % key_name)
|
||||
else:
|
||||
@@ -109,38 +114,53 @@ def _upload_files(app, files_, bucket):
|
||||
def create_all(app, user=None, password=None, bucket_name=None,
|
||||
location='', include_hidden=False):
|
||||
"""
|
||||
Uploads of the static assets associated with a Flask application to Amazon S3.
|
||||
Uploads of the static assets associated with a Flask application to
|
||||
Amazon S3.
|
||||
|
||||
All static assets are identified on the local filesystem, including
|
||||
any static assets associated with *registered* blueprints. In turn, each
|
||||
asset is uploaded to the bucket described by `bucket_name`. If the bucket
|
||||
does not exist then it is created.
|
||||
any static assets associated with *registered* blueprints. In turn,
|
||||
each asset is uploaded to the bucket described by `bucket_name`. If
|
||||
the bucket does not exist then it is created.
|
||||
|
||||
Flask-S3 creates the same relative static asset folder structure on S3 as
|
||||
can be found within your Flask application.
|
||||
Flask-S3 creates the same relative static asset folder structure on
|
||||
S3 as can be found within your Flask application.
|
||||
|
||||
Many of the optional arguments to `create_all` can be specified instead in
|
||||
your application's configuration using the Flask-S3 `configuration`_ variables.
|
||||
Many of the optional arguments to `create_all` can be specified
|
||||
instead in your application's configuration using the Flask-S3
|
||||
`configuration`_ variables.
|
||||
|
||||
:param app: a :class:`flask.Flask` application object.
|
||||
|
||||
:param user: an AWS Access Key ID. You can find this key in the Security Credentials section of your AWS account.
|
||||
:param user: an AWS Access Key ID. You can find this key in the
|
||||
Security Credentials section of your AWS account.
|
||||
:type user: `basestring` or None
|
||||
|
||||
:param password: an AWS Secret Access Key. You can find this key in the Security Credentials section of your AWS account.
|
||||
:param password: an AWS Secret Access Key. You can find this key in
|
||||
the Security Credentials section of your AWS
|
||||
account.
|
||||
:type password: `basestring` or None
|
||||
|
||||
:param bucket_name: the name of the bucket you wish to server your static assets from. **Note**: while a valid character, it is recommended that you do not include periods in bucket_name if you wish to serve over HTTPS. See Amazon's `bucket restrictions`_ for more details.
|
||||
:param bucket_name: the name of the bucket you wish to server your
|
||||
static assets from. **Note**: while a valid
|
||||
character, it is recommended that you do not
|
||||
include periods in bucket_name if you wish to
|
||||
serve over HTTPS. See Amazon's `bucket
|
||||
restrictions`_ for more details.
|
||||
:type bucket_name: `basestring` or None
|
||||
|
||||
:param location: the AWS region to host the bucket in; an empty string indicates the default region should be used, which is the US Standard region. Possible location values include: `'DEFAULT'`, `'EU'`, `'USWest'`, `'APSoutheast'`
|
||||
:param location: the AWS region to host the bucket in; an empty
|
||||
string indicates the default region should be used,
|
||||
which is the US Standard region. Possible location
|
||||
values include: `'DEFAULT'`, `'EU'`, `'USWest'`,
|
||||
`'APSoutheast'`
|
||||
:type location: `basestring` or None
|
||||
|
||||
:param include_hidden: by default Flask-S3 will not upload hidden files. Set this to true to force the upload of hidden files.
|
||||
:param include_hidden: by default Flask-S3 will not upload hidden
|
||||
files. Set this to true to force the upload of hidden files.
|
||||
:type include_hidden: `bool`
|
||||
|
||||
.. _bucket restrictions: http://docs.amazonwebservices.com/AmazonS3/latest\
|
||||
/dev/BucketRestrictions.html
|
||||
.. _bucket restrictions: http://docs.amazonwebservices.com/AmazonS3\
|
||||
/latest/dev/BucketRestrictions.html
|
||||
|
||||
"""
|
||||
if user is None and 'AWS_ACCESS_KEY_ID' in app.config:
|
||||
@@ -169,8 +189,8 @@ class FlaskS3(object):
|
||||
The FlaskS3 object allows your application to use Flask-S3.
|
||||
|
||||
When initialising a FlaskS3 object you may optionally provide your
|
||||
:class:`flask.Flask` application object if it is ready. Otherwise, you may
|
||||
provide it later by using the :meth:`init_app` method.
|
||||
:class:`flask.Flask` application object if it is ready. Otherwise,
|
||||
you may provide it later by using the :meth:`init_app` method.
|
||||
|
||||
:param app: optional :class:`flask.Flask` application object
|
||||
:type app: :class:`flask.Flask` or None
|
||||
@@ -181,9 +201,9 @@ class FlaskS3(object):
|
||||
|
||||
def init_app(self, app):
|
||||
"""
|
||||
An alternative way to pass your :class:`flask.Flask` application object
|
||||
to Flask-S3. :meth:`init_app` also takes care of some default
|
||||
`settings`_.
|
||||
An alternative way to pass your :class:`flask.Flask` application
|
||||
object to Flask-S3. :meth:`init_app` also takes care of some
|
||||
default `settings`_.
|
||||
|
||||
:param app: the :class:`flask.Flask` application object.
|
||||
"""
|
||||
|
||||
@@ -9,11 +9,11 @@ from setuptools import setup
|
||||
|
||||
setup(
|
||||
name='Flask-S3',
|
||||
version='0.1.3',
|
||||
version='0.1.4',
|
||||
url='http://github.com/e-dard/flask-s3',
|
||||
license='WTFPL',
|
||||
author='Edward Robinson',
|
||||
author_email='me@eddrobinson.net',
|
||||
author_email='hi@edd.io',
|
||||
description='Seamlessly serve the static files of your Flask app from Amazon S3',
|
||||
long_description=__doc__,
|
||||
py_modules=['flask_s3'],
|
||||
|
||||
@@ -3,7 +3,6 @@ import ntpath
|
||||
|
||||
from mock import Mock, patch, call
|
||||
from flask import Flask, render_template_string, Blueprint
|
||||
from boto.s3.key import Key
|
||||
|
||||
import flask_s3
|
||||
from flask_s3 import FlaskS3
|
||||
@@ -64,7 +63,9 @@ class UrlTests(unittest.TestCase):
|
||||
return client.get('/%s' % ufs)
|
||||
|
||||
def test_required_config(self):
|
||||
""" Tests that ValueError raised if bucket address not provided."""
|
||||
"""
|
||||
Tests that ValueError raised if bucket address not provided.
|
||||
"""
|
||||
raises = False
|
||||
|
||||
del self.app.config['S3_BUCKET_NAME']
|
||||
@@ -77,7 +78,9 @@ class UrlTests(unittest.TestCase):
|
||||
self.assertTrue(raises)
|
||||
|
||||
def test_url_for(self):
|
||||
"""Tests that correct url formed for static asset in self.app."""
|
||||
"""
|
||||
Tests that correct url formed for static asset in self.app.
|
||||
"""
|
||||
# non static endpoint url_for in template
|
||||
self.assertEquals(self.client_get('').data, '/')
|
||||
# static endpoint url_for in template
|
||||
@@ -97,7 +100,9 @@ class UrlTests(unittest.TestCase):
|
||||
self.assertEquals(self.client_get(ufs).data, exp)
|
||||
|
||||
def test_url_for_blueprint(self):
|
||||
"""Tests that correct url formed for static asset in blueprint."""
|
||||
"""
|
||||
Tests that correct url formed for static asset in blueprint.
|
||||
"""
|
||||
# static endpoint url_for in template
|
||||
ufs = "{{url_for('admin.static', filename='bah.js')}}"
|
||||
exp = 'https://foo.s3.amazonaws.com/admin-static/bah.js'
|
||||
@@ -159,8 +164,8 @@ class S3Tests(unittest.TestCase):
|
||||
@patch('os.path.isdir')
|
||||
def test__gather_files_no_blueprints_no_files(self, path_mock, os_mock):
|
||||
"""
|
||||
Tests that _gather_files works when there are no blueprints and no
|
||||
files available in the static folder
|
||||
Tests that _gather_files works when there are no blueprints and
|
||||
no files available in the static folder
|
||||
"""
|
||||
self.app.static_folder = '/foo'
|
||||
dirs = {'/foo': [('/foo', None, [])]}
|
||||
|
||||
Reference in New Issue
Block a user