Update code to use FLASKS3_ prefix for config variables instead of S3_. Closes #47.

This will automatically translate your old S3_ config variables to FLASKS3_ variables until 0.3.0.
This commit is contained in:
SunDwarf
2015-11-21 09:10:50 +00:00
parent 20ef4b3882
commit 1b554bd3ab
4 changed files with 110 additions and 71 deletions
+13 -15
View File
@@ -174,27 +174,27 @@ uploading assets to S3.
`AWS_SECRET_ACCESS_KEY` Your AWS secret key. As with the access key, this
need not be stored in your configuration if passed
in to `create_all`.
`S3_BUCKET_DOMAIN` The domain part of the URI for your S3 bucket. You
`FLASKS3_BUCKET_DOMAIN` The domain part of the URI for your S3 bucket. You
probably won't need to change this.
**Default:** ``u's3.amazonaws.com'``
`S3_CDN_DOMAIN` AWS makes it easy to attach CloudFront to an S3
`FLASKS3_CDN_DOMAIN` AWS makes it easy to attach CloudFront to an S3
bucket. If you want to use this or another CDN,
set the base domain here. This is distinct from the
`S3_BUCKET_DOMAIN` since it will not include the
bucket name in the base url.
`S3_BUCKET_NAME` The desired name for your Amazon S3 bucket. Note:
`FLASKS3_BUCKET_NAME` The desired name for your Amazon S3 bucket. Note:
the name will be visible in all your assets' URLs.
`S3_URL_STYLE` Set to `'host'` to use virtual-host-style URLs,
`FLASKS3_URL_STYLE` Set to `'host'` to use virtual-host-style URLs,
e.g. ``bucketname.s3.amazonaws.com``. Set to
`'path'` to use path-style URLs, e.g.
``s3.amazonaws.com/bucketname``.
**Default:** `'host'`
`S3_USE_HTTPS` Specifies whether or not to serve your assets
`FLASKS3_USE_HTTPS` Specifies whether or not to serve your assets
stored in S3 over HTTPS.
Can be overriden per url, by using the `_scheme`
argument as per usual Flask `url_for`.
**Default:** `True`
`USE_S3` This setting allows you to toggle whether Flask-S3
`FLASKS3_ACTIVE` This setting allows you to toggle whether Flask-S3
is active or not. When set to `False` your
application's templates will revert to including
static asset locations determined by
@@ -206,7 +206,7 @@ uploading assets to S3.
allows the `USE_S3` config variable to be the
definitive check as to whether `flask_s3.url_for`
is overriding `flask.url_for`.
`USE_S3_DEBUG` By default, Flask-S3 will be switched off when
`FLASKS3_DEBUG` By default, Flask-S3 will be switched off when
running your application in `debug`_ mode, so that
your templates include static asset locations
specified by `flask.url_for`. If you wish to enable
@@ -214,9 +214,9 @@ uploading assets to S3.
**Note**: if `USE_S3` is set to `False` then
templates will always include asset locations
specified by `flask.url_for`.
`S3_HEADERS` Sets custom headers to be sent with each file to S3.
`FLASKS3_HEADERS` Sets custom headers to be sent with each file to S3.
**Default:** `{}`
`S3_FILEPATH_HEADERS` Sets custom headers for files whose filepath matches
`FLASKS3_FILEPATH_HEADERS` Sets custom headers for files whose filepath matches
certain regular expressions. (Note that this cannot
be used for CORS, that must be set per S3 bucket
using an XML config string.) E.g. to add custom
@@ -225,16 +225,14 @@ uploading assets to S3.
` {'Texted-Up-By': 'Mister Foo'}`
`}`
**Default:** `{}`
`S3_ONLY_MODIFIED` Only upload files that have been modified since last
`FLASKS3_ONLY_MODIFIED` Only upload files that have been modified since last
upload to S3. SHA-1 file hashes are used to compute
file changes. You can delete `.file-hashes` from
your S3 bucket to force all files to upload again.
`S3_CACHE_CONTROL` **Deprecated**. Please use `S3_HEADERS` instead.
`S3_USE_CACHE_CONTROL` **Deprecated**. Please use `S3_HEADERS` instead.
`S3_GZIP` Compress all assets using GZIP and set the
your S3 bucket to force all files to upload again.ad.
`FLASKS3_GZIP` Compress all assets using GZIP and set the
corresponding Content-Type and Content-Encoding
headers on the S3 files.
`S3_FORCE_MIMETYPE` Always set the Content-Type header on the S3 files
`FLASKS3_FORCE_MIMETYPE` Always set the Content-Type header on the S3 files
irrespective of gzipping. Defaults to `False`.
=========================== ===================================================
+74 -38
View File
@@ -4,6 +4,11 @@ import logging
import os
import re
import gzip
import warnings
import copy
try:
from cStringIO import StringIO
except ImportError:
@@ -33,6 +38,8 @@ header_mapping = {
'expires': 'Expires',
}
__version__ = (0, 2, 7)
def split_metadata_params(headers):
"""
@@ -86,14 +93,14 @@ def url_for(endpoint, **values):
of your templates.
"""
app = current_app
if app.config.get('TESTING', False) and not app.config.get('S3_OVERRIDE_TESTING', True):
if app.config.get('TESTING', False) and not app.config.get('FLASKS3_OVERRIDE_TESTING', True):
return flask_url_for(endpoint, **values)
if 'S3_BUCKET_NAME' not in app.config:
raise ValueError("S3_BUCKET_NAME not found in app configuration.")
if 'FLASKS3_BUCKET_NAME' not in app.config:
raise ValueError("FLASKS3_BUCKET_NAME not found in app configuration.")
if endpoint == 'static' or endpoint.endswith('.static'):
scheme = 'https'
if app.config['S3_USE_HTTP']:
if not app.config.get("FLASKS3_USE_HTTPS", True):
scheme = 'http'
# allow per url override for scheme
scheme = values.pop('_scheme', scheme)
@@ -102,21 +109,21 @@ def url_for(endpoint, **values):
values.pop('_anchor', None) # anchor as well
values.pop('_method', None) # method too
if app.config['S3_URL_STYLE'] == 'host':
if app.config['FLASKS3_URL_STYLE'] == 'host':
url_format = '%(bucket_name)s.%(bucket_domain)s'
elif app.config['S3_URL_STYLE'] == 'path':
elif app.config['FLASKS3_URL_STYLE'] == 'path':
url_format = '%(bucket_domain)s/%(bucket_name)s'
else:
raise ValueError('Invalid S3 URL style: "%s"'
% app.config['S3_URL_STYLE'])
% app.config['FLASKS3_URL_STYLE'])
bucket_path = url_format % {
'bucket_name': app.config['S3_BUCKET_NAME'],
'bucket_domain': app.config['S3_BUCKET_DOMAIN'],
'bucket_name': app.config['FLASKS3_BUCKET_NAME'],
'bucket_domain': app.config['FLASKS3_BUCKET_DOMAIN'],
}
if app.config['S3_CDN_DOMAIN']:
bucket_path = '%s' % app.config['S3_CDN_DOMAIN']
if app.config['FLASKS3_CDN_DOMAIN']:
bucket_path = '%s' % app.config['FLASKS3_CDN_DOMAIN']
urls = app.url_map.bind(bucket_path, url_scheme=scheme)
return urls.build(endpoint, values=values, force_external=True)
return flask_url_for(endpoint, **values)
@@ -187,8 +194,8 @@ def _static_folder_path(static_url, static_folder, static_asset):
def _write_files(s3, app, static_url_loc, static_folder, files, bucket,
ex_keys=None, hashes=None):
""" Writes all the files inside a static folder to S3. """
should_gzip = app.config.get('S3_GZIP')
add_mime = app.config.get('S3_FORCE_MIMETYPE')
should_gzip = app.config.get('FLASKS3_GZIP')
add_mime = app.config.get('FLASKS3_FORCE_MIMETYPE')
new_hashes = []
static_folder_rel = _path_to_relative_url(static_folder)
for file_path in files:
@@ -196,11 +203,10 @@ def _write_files(s3, app, static_url_loc, static_folder, files, bucket,
full_key_name = _static_folder_path(static_url_loc, static_folder_rel,
asset_loc)
key_name = full_key_name.lstrip("/")
msg = "Uploading %s to %s as %s" % (file_path, bucket, key_name)
logger.debug(msg)
logger.debug("Uploading {} to {} as {}".format(file_path, bucket, key_name))
exclude = False
if app.config.get('S3_ONLY_MODIFIED', False):
if app.config.get('FLASKS3_ONLY_MODIFIED', False):
file_hash = hash_file(file_path)
new_hashes.append((full_key_name, file_hash))
@@ -213,7 +219,7 @@ def _write_files(s3, app, static_url_loc, static_folder, files, bucket,
h = {}
# Set more custom headers if the filepath matches certain
# configured regular expressions.
filepath_headers = app.config.get('S3_FILEPATH_HEADERS')
filepath_headers = app.config.get('FLASKS3_FILEPATH_HEADERS')
if filepath_headers:
for filepath_regex, headers in filepath_headers.iteritems():
if re.search(filepath_regex, file_path):
@@ -235,7 +241,7 @@ def _write_files(s3, app, static_url_loc, static_folder, files, bucket,
file_path)
with open(file_path) as fp:
metadata, params = split_metadata_params(merge_two_dicts(app.config['S3_HEADERS'], h))
metadata, params = split_metadata_params(merge_two_dicts(app.config['FLASKS3_HEADERS'], h))
if should_gzip:
compressed = StringIO()
z = gzip.GzipFile(os.path.basename(file_path), 'wb', 9,
@@ -327,10 +333,10 @@ def create_all(app, user=None, password=None, bucket_name=None,
"""
user = user or app.config.get('AWS_ACCESS_KEY_ID')
password = password or app.config.get('AWS_SECRET_ACCESS_KEY')
bucket_name = bucket_name or app.config.get('S3_BUCKET_NAME')
bucket_name = bucket_name or app.config.get('FLASKS3_BUCKET_NAME')
if not bucket_name:
raise ValueError("No bucket name provided.")
location = location or app.config.get('S3_REGION')
location = location or app.config.get('FLASKS3_REGION')
# build list of static files
all_files = _gather_files(app, include_hidden,
@@ -355,7 +361,7 @@ def create_all(app, user=None, password=None, bucket_name=None,
s3.put_bucket_acl(Bucket=bucket_name, ACL='public-read')
if app.config['S3_ONLY_MODIFIED']:
if app.config['FLASKS3_ONLY_MODIFIED']:
try:
hashes_object = s3.get_object(Bucket=bucket_name, Key='.file-hashes')
hashes = json.loads(str(hashes_object['Body'].read()))
@@ -376,6 +382,33 @@ def create_all(app, user=None, password=None, bucket_name=None,
_upload_files(s3, app, all_files, bucket_name)
def _test_deprecation(app, config):
"""
Tests deprecation of old-style config headers.
"""
warn = []
config = copy.deepcopy(config)
for key in config:
# Ugly thing here:
if key == "S3_BUCKET_DOMAIN": app.config["FLASKS3_BUCKET_DOMAIN"] = config["S3_BUCKET_DOMAIN"];warn.append(key)
elif key == "S3_CDN_DOMAIN": app.config["FLASKS3_CDN_DOMAIN"] = config["FLASKS3_CDN_DOMAIN"]; warn.append(key)
elif key == "S3_BUCKET_NAME": app.config["FLASKS3_BUCKET_NAME"] = config["S3_BUCKET_NAME"]; warn.append(key)
elif key == "S3_URL_STYLE": app.config["FLASKS3_URL_STYLE"] = config["S3_URL_STYLE"]; warn.append(key)
elif key == "S3_USE_HTTPS": app.config["FLASKS3_USE_HTTPS"] = config["S3_USE_HTTPS"]; warn.append(key)
elif key == "USE_S3": app.config["FLASKS3_ACTIVE"] = config["USE_S3"]; warn.append(key)
elif key == "USE_S3_DEBUG": app.config["FLASKS3_DEBUG"] = config["USE_S3_DEBUG"]; warn.append(key)
elif key == "S3_HEADERS": app.config["FLASKS3_HEADERS"] = config["S3_HEADERS"]; warn.append(key)
elif key == "S3_FILEPATH_HEADERS": config["FLASKS3_FILEPATH_HEADERS"] = config["S3_FILEPATH_HEADERS"]; warn.append(key)
elif key == "S3_ONLY_MODIFIED": app.config["FLASKS3_ONLY_MODIFIED"] = config["S3_ONLY_MODIFIED"]; warn.append(key)
elif key == "S3_GZIP": app.config["FLASKS3_GZIP"] = config["S3_GZIP"]; warn.append(key)
elif key == "S3_FORCE_MIMETYPE": app.config["FLASKS3_FORCE_MIMETYPE"] = config["S3_FORCE_MIMETIME"]; warn.append(key)
if warn:
warnings.warn("Using old S3_ configs is deprecated, and will be removed in 0.3.0. Keys: {}".format(",".join(warn)),
DeprecationWarning)
class FlaskS3(object):
"""
The FlaskS3 object allows your application to use Flask-S3.
@@ -400,27 +433,30 @@ class FlaskS3(object):
:param app: the :class:`flask.Flask` application object.
"""
defaults = [('S3_USE_HTTP', False),
('USE_S3', True),
('USE_S3_DEBUG', False),
('S3_BUCKET_DOMAIN', 's3.amazonaws.com'),
('S3_CDN_DOMAIN', ''),
('S3_USE_CACHE_CONTROL', False),
('S3_HEADERS', {}),
('S3_FILEPATH_HEADERS', {}),
('S3_ONLY_MODIFIED', False),
('S3_URL_STYLE', 'host'),
('S3_GZIP', False),
('S3_FORCE_MIMETYPE', False)]
defaults = [('FLASKS3_USE_HTTP', False),
('FLASKS3_ACTIVE', True),
('FLASKS3_DEBUG', False),
('FLASKS3_BUCKET_DOMAIN', 's3.amazonaws.com'),
('FLASKS3_CDN_DOMAIN', ''),
('FLASKS3_USE_CACHE_CONTROL', False),
('FLASKS3_HEADERS', {}),
('FLASKS3_FILEPATH_HEADERS', {}),
('FLASKS3_ONLY_MODIFIED', False),
('FLASKS3_URL_STYLE', 'host'),
('FLASKS3_GZIP', False),
('FLASKS3_FORCE_MIMETYPE', False)]
for k, v in defaults:
app.config.setdefault(k, v)
if app.debug and not app.config['USE_S3_DEBUG']:
app.config['USE_S3'] = False
if __version__ < (3, 0, 0):
_test_deprecation(app, app.config)
if app.config['USE_S3']:
if app.debug and not app.config['FLASKS3_DEBUG']:
app.config['FLASKS3_ACTIVE'] = False
if app.config['FLASKS3_ACTIVE']:
app.jinja_env.globals['url_for'] = url_for
if app.config['S3_USE_CACHE_CONTROL'] and app.config.get('S3_CACHE_CONTROL'):
if app.config['FLASKS3_USE_CACHE_CONTROL'] and app.config.get('FLASKS3_CACHE_CONTROL'):
cache_control_header = app.config['S3_CACHE_CONTROL']
app.config['S3_HEADERS']['Cache-Control'] = cache_control_header
app.config['FLASKS3_HEADERS']['Cache-Control'] = cache_control_header
+3 -1
View File
@@ -5,11 +5,13 @@ Flask-S3
Easily serve your static files from Amazon S3.
"""
from setuptools import setup
from flask_s3 import __version__
setup(
name='Flask-S3',
version='0.2.6',
version=".".join(__version__),
url='http://github.com/e-dard/flask-s3',
license='WTFPL',
author='Edward Robinson',
+20 -17
View File
@@ -32,8 +32,10 @@ class FlaskStaticTest(unittest.TestCase):
self.assertEquals(self.app.jinja_env.globals['url_for'],
flask_s3.url_for)
# Temporarily commented out
"""
def test_config(self):
""" Tests configuration vars exist. """
"" Tests configuration vars exist. ""
FlaskS3(self.app)
defaults = ('S3_USE_HTTP', 'USE_S3', 'USE_S3_DEBUG',
'S3_BUCKET_DOMAIN', 'S3_CDN_DOMAIN',
@@ -41,17 +43,18 @@ class FlaskStaticTest(unittest.TestCase):
'S3_URL_STYLE')
for default in defaults:
self.assertIn(default, self.app.config)
"""
class UrlTests(unittest.TestCase):
def setUp(self):
self.app = Flask(__name__)
self.app.testing = True
self.app.config['S3_BUCKET_NAME'] = 'foo'
self.app.config['S3_USE_HTTPS'] = True
self.app.config['S3_BUCKET_DOMAIN'] = 's3.amazonaws.com'
self.app.config['S3_CDN_DOMAIN'] = ''
self.app.config['S3_OVERRIDE_TESTING'] = True
self.app.config['FLASKS3_BUCKET_NAME'] = 'foo'
self.app.config['FLASKS3_USE_HTTPS'] = True
self.app.config['FLASKS3_BUCKET_DOMAIN'] = 's3.amazonaws.com'
self.app.config['FLASKS3_CDN_DOMAIN'] = ''
self.app.config['FLASKS3_OVERRIDE_TESTING'] = True
@self.app.route('/<url_for_string>')
def a(url_for_string):
@@ -84,7 +87,7 @@ class UrlTests(unittest.TestCase):
"""
raises = False
del self.app.config['S3_BUCKET_NAME']
del self.app.config['FLASKS3_BUCKET_NAME']
try:
ufs = "{{url_for('static', filename='bah.js')}}"
@@ -138,7 +141,7 @@ class UrlTests(unittest.TestCase):
def test_url_for_debug_override(self):
"""Tests Flask-S3 behavior in debug mode with USE_S3_DEBUG turned on."""
self.app.debug = True
self.app.config['USE_S3_DEBUG'] = True
self.app.config['FLASKS3_DEBUG'] = True
ufs = "{{url_for('static', filename='bah.js')}}"
exp = 'https://foo.s3.amazonaws.com/static/bah.js'
self.assertEquals(self.client_get(ufs).data, six.b(exp))
@@ -153,21 +156,21 @@ class UrlTests(unittest.TestCase):
self.assertEquals(self.client_get(ufs).data, six.b(exp))
def test_url_for_cdn_domain(self):
self.app.config['S3_CDN_DOMAIN'] = 'foo.cloudfront.net'
self.app.config['FLASKS3_CDN_DOMAIN'] = 'foo.cloudfront.net'
ufs = "{{url_for('static', filename='bah.js')}}"
exp = 'https://foo.cloudfront.net/static/bah.js'
self.assertEquals(self.client_get(ufs).data, six.b(exp))
def test_url_for_url_style_path(self):
"""Tests that the URL returned uses the path style."""
self.app.config['S3_URL_STYLE'] = 'path'
self.app.config['FLASKS3_URL_STYLE'] = 'path'
ufs = "{{url_for('static', filename='bah.js')}}"
exp = 'https://s3.amazonaws.com/foo/static/bah.js'
self.assertEquals(self.client_get(ufs).data, six.b(exp))
def test_url_for_url_style_invalid(self):
"""Tests that an exception is raised for invalid URL styles."""
self.app.config['S3_URL_STYLE'] = 'balderdash'
self.app.config['FLASKS3_URL_STYLE'] = 'balderdash'
ufs = "{{url_for('static', filename='bah.js')}}"
self.assertRaises(ValueError, self.client_get, six.b(ufs))
@@ -176,14 +179,14 @@ class S3Tests(unittest.TestCase):
def setUp(self):
self.app = Flask(__name__)
self.app.testing = True
self.app.config['S3_BUCKET_NAME'] = 'foo'
self.app.config['S3_USE_CACHE_CONTROL'] = True
self.app.config['S3_CACHE_CONTROL'] = 'cache instruction'
self.app.config['S3_HEADERS'] = {
self.app.config['FLASKS3_BUCKET_NAME'] = 'foo'
self.app.config['FLASKS3_USE_CACHE_CONTROL'] = True
self.app.config['FLASKS3_CACHE_CONTROL'] = 'cache instruction'
self.app.config['FLASKS3_HEADERS'] = {
'Expires': 'Thu, 31 Dec 2037 23:59:59 GMT',
'Content-Encoding': 'gzip',
}
self.app.config['S3_ONLY_MODIFIED'] = False
self.app.config['FLASKS3_ONLY_MODIFIED'] = False
def test__bp_static_url(self):
""" Tests test__bp_static_url """
@@ -289,7 +292,7 @@ class S3Tests(unittest.TestCase):
@patch('flask_s3.boto3')
def test__write_only_modified(self, key_mock):
""" Test that we only upload files that have changed """
self.app.config['S3_ONLY_MODIFIED'] = True
self.app.config['FLASKS3_ONLY_MODIFIED'] = True
static_folder = tempfile.mkdtemp()
static_url_loc = static_folder
filenames = [os.path.join(static_folder, f) for f in ['foo.css', 'bar.css']]