From 1081e6754e66ddc1c5904da527274a06c3f1ae70 Mon Sep 17 00:00:00 2001 From: Edd Robinson Date: Sun, 10 Mar 2013 16:17:31 +0000 Subject: [PATCH] general tidy up and version bump --- LICENSE | 2 +- docs/index.rst | 108 +++++++++++++++++++------------------ flask_s3.py | 78 +++++++++++++++++---------- setup.py | 4 +- tests/test_flask_static.py | 17 +++--- 5 files changed, 120 insertions(+), 89 deletions(-) diff --git a/LICENSE b/LICENSE index 35b9a5e..5f30d8f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,7 @@ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE Version 2, December 2004 -Copyright (C) 2004 Edward Robinson +Copyright (C) 2004 Sam Hocevar Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long diff --git a/docs/index.rst b/docs/index.rst index 155f11e..459ecde 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -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 ------------------ diff --git a/flask_s3.py b/flask_s3.py index 30a3bfc..c163c7d 100644 --- a/flask_s3.py +++ b/flask_s3.py @@ -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. """ diff --git a/setup.py b/setup.py index e5aae4c..834d6bd 100644 --- a/setup.py +++ b/setup.py @@ -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'], diff --git a/tests/test_flask_static.py b/tests/test_flask_static.py index 04da6e1..9cdf3fc 100644 --- a/tests/test_flask_static.py +++ b/tests/test_flask_static.py @@ -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, [])]}