Skip to content

Commit

Permalink
Update code to use FLASKS3_ prefix for config variables instead of S3_.
Browse files Browse the repository at this point in the history
Closes #47.

This will automatically translate your old S3_ config variables to FLASKS3_ variables until 0.3.0.
  • Loading branch information
Fuyukai committed Nov 21, 2015
1 parent 20ef4b3 commit 1b554bd
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 71 deletions.
28 changes: 13 additions & 15 deletions docs/index.rst
Expand Up @@ -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
Expand All @@ -206,17 +206,17 @@ 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
Flask-S3 in debug mode, set this value to `True`.
**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
Expand All @@ -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`.
=========================== ===================================================

Expand Down
112 changes: 74 additions & 38 deletions flask_s3.py
Expand Up @@ -4,6 +4,11 @@
import os
import re
import gzip

import warnings
import copy


try:
from cStringIO import StringIO
except ImportError:
Expand Down Expand Up @@ -33,6 +38,8 @@
'expires': 'Expires',
}

__version__ = (0, 2, 7)


def split_metadata_params(headers):
"""
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -187,20 +194,19 @@ 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:
asset_loc = _path_to_relative_url(file_path)
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))

Expand All @@ -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):
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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()))
Expand All @@ -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.
Expand All @@ -400,27 +433,30 @@ def init_app(self, app):
: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.debug and not app.config['FLASKS3_DEBUG']:
app.config['FLASKS3_ACTIVE'] = False

if app.config['USE_S3']:
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
4 changes: 3 additions & 1 deletion setup.py
Expand Up @@ -5,11 +5,13 @@
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',
Expand Down

0 comments on commit 1b554bd

Please sign in to comment.