Flask-Compress-1.4.0/0000775000175000017500000000000013033303450014301 5ustar willwill00000000000000Flask-Compress-1.4.0/MANIFEST.in0000664000175000017500000000013613033272651016047 0ustar willwill00000000000000include LICENSE.txt include README.md recursive-include tests * recursive-exclude tests *.pyc Flask-Compress-1.4.0/setup.cfg0000664000175000017500000000007313033303450016122 0ustar willwill00000000000000[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 Flask-Compress-1.4.0/setup.py0000664000175000017500000000241213033301310016003 0ustar willwill00000000000000import setuptools setuptools.setup( name='Flask-Compress', version='1.4.0', url='https://libwilliam.github.io/flask-compress/', license='MIT', author='William Fagan', author_email='libwilliam@gmail.com', description='Compress responses in your Flask app with gzip.', long_description='Full documentation can be found on the Flask-Compress "Home Page".', py_modules=['flask_compress'], zip_safe=False, include_package_data=True, platforms='any', install_requires=[ 'Flask' ], test_suite='tests', classifiers=[ 'Environment :: Web Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', 'Topic :: Software Development :: Libraries :: Python Modules' ] ) Flask-Compress-1.4.0/Flask_Compress.egg-info/0000775000175000017500000000000013033303450020706 5ustar willwill00000000000000Flask-Compress-1.4.0/Flask_Compress.egg-info/SOURCES.txt0000664000175000017500000000062613033303450022576 0ustar willwill00000000000000LICENSE.txt MANIFEST.in README.md flask_compress.py setup.py Flask_Compress.egg-info/PKG-INFO Flask_Compress.egg-info/SOURCES.txt Flask_Compress.egg-info/dependency_links.txt Flask_Compress.egg-info/not-zip-safe Flask_Compress.egg-info/requires.txt Flask_Compress.egg-info/top_level.txt tests/__init__.py tests/test_flask_compress.py tests/static/1.png tests/templates/large.html tests/templates/small.htmlFlask-Compress-1.4.0/Flask_Compress.egg-info/top_level.txt0000664000175000017500000000001713033303450023436 0ustar willwill00000000000000flask_compress Flask-Compress-1.4.0/Flask_Compress.egg-info/dependency_links.txt0000664000175000017500000000000113033303450024754 0ustar willwill00000000000000 Flask-Compress-1.4.0/Flask_Compress.egg-info/not-zip-safe0000664000175000017500000000000113033274323023142 0ustar willwill00000000000000 Flask-Compress-1.4.0/Flask_Compress.egg-info/requires.txt0000664000175000017500000000000613033303450023302 0ustar willwill00000000000000Flask Flask-Compress-1.4.0/Flask_Compress.egg-info/PKG-INFO0000664000175000017500000000203213033303450022000 0ustar willwill00000000000000Metadata-Version: 1.1 Name: Flask-Compress Version: 1.4.0 Summary: Compress responses in your Flask app with gzip. Home-page: https://libwilliam.github.io/flask-compress/ Author: William Fagan Author-email: libwilliam@gmail.com License: MIT Description: Full documentation can be found on the Flask-Compress "Home Page". Platform: any Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content Classifier: Topic :: Software Development :: Libraries :: Python Modules Flask-Compress-1.4.0/tests/0000775000175000017500000000000013033303450015443 5ustar willwill00000000000000Flask-Compress-1.4.0/tests/test_flask_compress.py0000664000175000017500000000653613033272651022111 0ustar willwill00000000000000import unittest import os from flask import Flask, render_template from flask_compress import Compress class DefaultsTest(unittest.TestCase): def setUp(self): self.app = Flask(__name__) self.app.testing = True Compress(self.app) def test_mimetypes_default(self): """ Tests COMPRESS_MIMETYPES default value is correctly set. """ defaults = ['text/html', 'text/css', 'text/xml', 'application/json', 'application/javascript'] self.assertEqual(self.app.config['COMPRESS_MIMETYPES'], defaults) def test_level_default(self): """ Tests COMPRESS_LEVEL default value is correctly set. """ self.assertEqual(self.app.config['COMPRESS_LEVEL'], 6) def test_min_size_default(self): """ Tests COMPRESS_MIN_SIZE default value is correctly set. """ self.assertEqual(self.app.config['COMPRESS_MIN_SIZE'], 500) class InitTests(unittest.TestCase): def setUp(self): self.app = Flask(__name__) self.app.testing = True def test_constructor_init(self): Compress(self.app) def test_delayed_init(self): compress = Compress() compress.init_app(self.app) class UrlTests(unittest.TestCase): def setUp(self): self.app = Flask(__name__) self.app.testing = True small_path = os.path.join(os.getcwd(), 'tests', 'templates', 'small.html') large_path = os.path.join(os.getcwd(), 'tests', 'templates', 'large.html') self.small_size = os.path.getsize(small_path) - 1 self.large_size = os.path.getsize(large_path) - 1 Compress(self.app) @self.app.route('/small/') def small(): return render_template('small.html') @self.app.route('/large/') def large(): return render_template('large.html') def client_get(self, ufs): client = self.app.test_client() response = client.get(ufs, headers=[('Accept-Encoding', 'gzip')]) self.assertEqual(response.status_code, 200) return response def test_compress_level(self): """ Tests COMPRESS_LEVEL correctly affects response data. """ self.app.config['COMPRESS_LEVEL'] = 1 response = self.client_get('/large/') response1_size = len(response.data) self.app.config['COMPRESS_LEVEL'] = 6 response = self.client_get('/large/') response6_size = len(response.data) self.assertNotEqual(response1_size, response6_size) def test_compress_min_size(self): """ Tests COMPRESS_MIN_SIZE correctly affects response data. """ response = self.client_get('/small/') self.assertEqual(self.small_size, len(response.data)) response = self.client_get('/large/') self.assertNotEqual(self.large_size, len(response.data)) def test_mimetype_mismatch(self): """ Tests if mimetype not in COMPRESS_MIMETYPES. """ response = self.client_get('/static/1.png') self.assertEqual(response.mimetype, 'image/png') def test_content_length_options(self): client = self.app.test_client() headers = [('Accept-Encoding', 'gzip')] response = client.options('/small/', headers=headers) self.assertEqual(response.status_code, 200) if __name__ == '__main__': unittest.main() Flask-Compress-1.4.0/tests/templates/0000775000175000017500000000000013033303450017441 5ustar willwill00000000000000Flask-Compress-1.4.0/tests/templates/small.html0000664000175000017500000000005513033272651021447 0ustar willwill00000000000000 Flask-Compress-1.4.0/tests/templates/large.html0000664000175000017500000000077313033272651021440 0ustar willwill00000000000000

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Flask-Compress-1.4.0/tests/static/0000775000175000017500000000000013033303450016732 5ustar willwill00000000000000Flask-Compress-1.4.0/tests/static/1.png0000664000175000017500000000035713033272651017615 0ustar willwill00000000000000PNG  IHDR7n$gAMA a cHRMz&u0`:pQ<bKGD݊ IDATchCj%tEXtdate:create2014-07-23T15:42:03+04:00%tEXtdate:modify2014-07-23T15:42:03+04:00jɧIENDB`Flask-Compress-1.4.0/tests/__init__.py0000664000175000017500000000000013033272651017552 0ustar willwill00000000000000Flask-Compress-1.4.0/LICENSE.txt0000664000175000017500000000207513033272651016140 0ustar willwill00000000000000The MIT License (MIT) Copyright (c) 2013-2016 William Fagan Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Flask-Compress-1.4.0/flask_compress.py0000664000175000017500000000753413033301130017670 0ustar willwill00000000000000import sys from gzip import GzipFile from io import BytesIO from flask import request, current_app if sys.version_info[:2] == (2, 6): class GzipFile(GzipFile): """ Backport of context manager support for python 2.6""" def __enter__(self): if self.fileobj is None: raise ValueError("I/O operation on closed GzipFile object") return self def __exit__(self, *args): self.close() class DictCache(object): def __init__(self): self.data = {} def get(self, key): return self.data.get(key) def set(self, key, value): self.data[key] = value class Compress(object): """ The Compress object allows your application to use Flask-Compress. When initialising a Compress 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. :param app: optional :class:`flask.Flask` application object :type app: :class:`flask.Flask` or None """ def __init__(self, app=None): """ An alternative way to pass your :class:`flask.Flask` application object to Flask-Compress. :meth:`init_app` also takes care of some default `settings`_. :param app: the :class:`flask.Flask` application object. """ self.app = app if app is not None: self.init_app(app) def init_app(self, app): defaults = [ ('COMPRESS_MIMETYPES', ['text/html', 'text/css', 'text/xml', 'application/json', 'application/javascript']), ('COMPRESS_LEVEL', 6), ('COMPRESS_MIN_SIZE', 500), ('COMPRESS_CACHE_KEY', None), ('COMPRESS_CACHE_BACKEND', None), ('COMPRESS_REGISTER', True), ] for k, v in defaults: app.config.setdefault(k, v) backend = app.config['COMPRESS_CACHE_BACKEND'] self.cache = backend() if backend else None self.cache_key = app.config['COMPRESS_CACHE_KEY'] if (app.config['COMPRESS_REGISTER'] and app.config['COMPRESS_MIMETYPES']): app.after_request(self.after_request) def after_request(self, response): app = self.app or current_app accept_encoding = request.headers.get('Accept-Encoding', '') if (response.mimetype not in app.config['COMPRESS_MIMETYPES'] or 'gzip' not in accept_encoding.lower() or not 200 <= response.status_code < 300 or (response.content_length is not None and response.content_length < app.config['COMPRESS_MIN_SIZE']) or 'Content-Encoding' in response.headers): return response response.direct_passthrough = False if self.cache: key = self.cache_key(response) gzip_content = self.cache.get(key) or self.compress(app, response) self.cache.set(key, gzip_content) else: gzip_content = self.compress(app, response) response.set_data(gzip_content) response.headers['Content-Encoding'] = 'gzip' response.headers['Content-Length'] = response.content_length vary = response.headers.get('Vary') if vary: if 'accept-encoding' not in vary.lower(): response.headers['Vary'] = '{}, Accept-Encoding'.format(vary) else: response.headers['Vary'] = 'Accept-Encoding' return response def compress(self, app, response): gzip_buffer = BytesIO() with GzipFile(mode='wb', compresslevel=app.config['COMPRESS_LEVEL'], fileobj=gzip_buffer) as gzip_file: gzip_file.write(response.get_data()) return gzip_buffer.getvalue() Flask-Compress-1.4.0/README.md0000664000175000017500000000701413033301630015560 0ustar willwill00000000000000# Flask-Compress [![Version](https://img.shields.io/pypi/v/flask-compress.svg)](https://pypi.python.org/pypi/Flask-Compress) [![Build Status](https://travis-ci.org/libwilliam/flask-compress.png)](https://travis-ci.org/libwilliam/flask-compress) [![Coverage](https://coveralls.io/repos/libwilliam/flask-compress/badge.svg)](https://coveralls.io/github/libwilliam/flask-compress) [![License](https://img.shields.io/pypi/l/flask-compress.svg)](https://github.com/libwilliam/flask-compress/blob/master/LICENSE.txt) Flask-Compress allows you to easily compress your [Flask](http://flask.pocoo.org/) application's responses with gzip. The preferred solution is to have a server (like [Nginx](http://wiki.nginx.org/Main)) automatically compress the static files for you. If you don't have that option Flask-Compress will solve the problem for you. ## How it works Flask-Compress both adds the various headers required for a compressed response and gzips the response data. This makes serving gzip compressed static files extremely easy. Internally, every time a request is made the extension will check if it matches one of the compressible MIME types and will automatically attach the appropriate headers. ## Installation If you use pip then installation is simply: ```shell $ pip install flask-compress ``` or, if you want the latest github version: ```shell $ pip install git+git://github.com/libwilliam/flask-compress.git ``` You can also install Flask-Compress via Easy Install: ```shell $ easy_install flask-compress ``` ## Using Flask-Compress Flask-Compress is incredibly simple to use. In order to start gzip'ing your Flask application's assets, the first thing to do is let Flask-Compress know about your [`flask.Flask`](http://flask.pocoo.org/docs/latest/api/#flask.Flask) application object. ```python from flask import Flask from flask_compress import Compress app = Flask(__name__) Compress(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-Compress provides a simple function, `flask_compress.Compress.init_app`, which takes your application as an argument. ```python from flask import Flask from flask_compress import Compress compress = Compress() def start_app(): app = Flask(__name__) compress.init_app(app) return app ``` In terms of automatically compressing your assets using gzip, passing your [`flask.Flask`](http://flask.pocoo.org/docs/latest/api/#flask.Flask) object to the `flask_compress.Compress` object is all that needs to be done. ## Options Within your Flask application's settings you can provide the following settings to control the behavior of Flask-Compress. None of the settings are required. | Option | Description | Default | | ------ | ----------- | ------- | | `COMPRESS_MIMETYPES` | Set the list of mimetypes to compress here. | `[`
`'text/html',`
`'text/css',`
`'text/xml',`
`'application/json',`
`'application/javascript'`
`]` | | `COMPRESS_LEVEL` | Specifies the gzip compression level. | `6` | | `COMPRESS_MIN_SIZE` | Specifies the minimum file size threshold for compressing files. | `500` | | `COMPRESS_CACHE_KEY` | Specifies the cache key method for lookup/storage of response data. | `None` | | `COMPRESS_CACHE_BACKEND` | Specified the backend for storing the cached response data. | `None` | | `COMPRESS_REGISTER` | Specifies if compression should be automatically registered. | `True` | Flask-Compress-1.4.0/PKG-INFO0000664000175000017500000000203213033303450015373 0ustar willwill00000000000000Metadata-Version: 1.1 Name: Flask-Compress Version: 1.4.0 Summary: Compress responses in your Flask app with gzip. Home-page: https://libwilliam.github.io/flask-compress/ Author: William Fagan Author-email: libwilliam@gmail.com License: MIT Description: Full documentation can be found on the Flask-Compress "Home Page". Platform: any Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content Classifier: Topic :: Software Development :: Libraries :: Python Modules