Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-Flask-Compress for
openSUSE:Factory checked in at 2021-07-23 23:41:12
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-Flask-Compress (Old)
and /work/SRC/openSUSE:Factory/.python-Flask-Compress.new.1899 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-Flask-Compress"
Fri Jul 23 23:41:12 2021 rev:6 rq:907904 version:1.10.1
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-Flask-Compress/python-Flask-Compress.changes
2021-06-01 10:41:45.081251235 +0200
+++
/work/SRC/openSUSE:Factory/.python-Flask-Compress.new.1899/python-Flask-Compress.changes
2021-07-23 23:41:30.773808249 +0200
@@ -1,0 +2,17 @@
+Thu Jul 22 01:46:11 UTC 2021 - Arun Persaud <[email protected]>
+
+- specfile:
+ * update copyright year
+ * include setuptools_scm, importlib-metadata
+ * updated %files section
+
+- update to version 1.10.1:
+ * no changelog available at the moment
+
+- changes from version 1.10.0 :
+ * Automate the release process with GitHub Actions
+ * Use setuptools_scm to manage package versions
+ * The layout is now an actual package rather than a single module
+ * Clean up unused files
+
+-------------------------------------------------------------------
Old:
----
Flask-Compress-1.8.0.tar.gz
New:
----
Flask-Compress-1.10.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-Flask-Compress.spec ++++++
--- /var/tmp/diff_new_pack.MBKOJd/_old 2021-07-23 23:41:31.189807717 +0200
+++ /var/tmp/diff_new_pack.MBKOJd/_new 2021-07-23 23:41:31.189807717 +0200
@@ -1,7 +1,7 @@
#
# spec file for package python-Flask-Compress
#
-# Copyright (c) 2020 SUSE LLC
+# Copyright (c) 2021 SUSE LLC
# Copyright (c) 2016, Martin Hauke <[email protected]>
#
# All modifications and additions to the file contributed by third parties
@@ -19,7 +19,7 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-Flask-Compress
-Version: 1.8.0
+Version: 1.10.1
Release: 0
Summary: Compress responses in Flask apps with gzip
License: MIT
@@ -27,6 +27,8 @@
URL: https://github.com/colour-science/flask-compress
Source:
https://files.pythonhosted.org/packages/source/F/Flask-Compress/Flask-Compress-%{version}.tar.gz
BuildRequires: %{python_module Brotli}
+BuildRequires: %{python_module importlib-metadata}
+BuildRequires: %{python_module setuptools_scm}
BuildRequires: %{python_module setuptools}
BuildRequires: fdupes
BuildRequires: python-rpm-macros
@@ -62,8 +64,8 @@
%files %{python_files}
%doc README.md
%license LICENSE.txt
-%{python_sitelib}/flask_compress.py*
+%{python_sitelib}/flask_compress
%{python_sitelib}/Flask_Compress-%{version}-py*.egg-info
-%pycache_only %{python_sitelib}/__pycache__
+%pycache_only %{python_sitelib}/flask_compress/__pycache__
%changelog
++++++ Flask-Compress-1.8.0.tar.gz -> Flask-Compress-1.10.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-Compress-1.8.0/.github/workflows/ci.yaml
new/Flask-Compress-1.10.1/.github/workflows/ci.yaml
--- old/Flask-Compress-1.8.0/.github/workflows/ci.yaml 1970-01-01
01:00:00.000000000 +0100
+++ new/Flask-Compress-1.10.1/.github/workflows/ci.yaml 2021-06-16
10:22:32.000000000 +0200
@@ -0,0 +1,91 @@
+name: Unit tests
+
+on:
+ pull_request:
+ push:
+ branches:
+ - master
+ tags:
+ - "v*"
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ python-version: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9, pypy2, pypy3]
+
+ name: Python ${{ matrix.python-version }}
+ steps:
+ - uses: actions/checkout@v2
+ - name: Get history and tags for SCM versioning to work
+ run: |
+ git fetch --prune --unshallow
+ git fetch --depth=1 origin +refs/tags/*:refs/tags/*
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v2
+ with:
+ python-version: ${{ matrix.python-version }}
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install tox
+ - name: Test with tox
+ run: tox -e py
+
+ dist:
+ runs-on: ubuntu-latest
+ needs: [test]
+ name: Build Python packages
+ steps:
+ - uses: actions/checkout@v2
+ - name: Get history and tags for SCM versioning to work
+ run: |
+ git fetch --prune --unshallow
+ git fetch --depth=1 origin +refs/tags/*:refs/tags/*
+ - uses: actions/setup-python@v2
+ with:
+ python-version: "3.8"
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install --upgrade wheel setuptools build
+ - name: Build package
+ run: python -m build -s -w -o dist/
+ - uses: actions/upload-artifact@v2
+ with:
+ name: dist
+ path: dist
+
+ dist_check:
+ runs-on: ubuntu-latest
+ needs: [dist]
+ name: Twine check
+ steps:
+ - uses: actions/setup-python@v2
+ with:
+ python-version: "3.8"
+ - name: Install dependencies
+ run: pip install twine
+ - uses: actions/download-artifact@v2
+ with:
+ name: dist
+ path: dist
+ - run: twine check dist/*
+
+ dist_upload:
+ runs-on: ubuntu-latest
+ if: github.event_name == 'push' && startsWith(github.event.ref,
'refs/tags')
+ needs: [dist_check]
+ name: PyPI upload
+ steps:
+ - uses: actions/download-artifact@v2
+ with:
+ name: dist
+ path: dist
+ - name: Publish package to PyPI
+ uses: pypa/gh-action-pypi-publish@master
+ with:
+ user: __token__
+ password: ${{ secrets.PYPI_API_TOKEN }}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-Compress-1.8.0/.gitignore
new/Flask-Compress-1.10.1/.gitignore
--- old/Flask-Compress-1.8.0/.gitignore 1970-01-01 01:00:00.000000000 +0100
+++ new/Flask-Compress-1.10.1/.gitignore 2021-06-16 10:22:32.000000000
+0200
@@ -0,0 +1,25 @@
+*~
+# vim
+*.sw[klmnop]
+# python
+*.py[co~]
+# Ignoring build dir
+/build
+/dist
+/*.egg-info/
+# Virtual environments
+venv*
+.env*
+# Coverage reports
+/cover/
+/.coverage
+/htmlcov
+# Ignoring profiling reports
+*.prof
+*.lprof
+# Tox and pytest
+/.tox
+/.cache
+/.pytest_cache
+# Generated by setuptools_scm
+flask_compress/_version.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-Compress-1.8.0/CHANGELOG.md
new/Flask-Compress-1.10.1/CHANGELOG.md
--- old/Flask-Compress-1.8.0/CHANGELOG.md 1970-01-01 01:00:00.000000000
+0100
+++ new/Flask-Compress-1.10.1/CHANGELOG.md 2021-06-16 10:22:32.000000000
+0200
@@ -0,0 +1,38 @@
+# Changelog
+
+All notable changes to `flask-compress` will be documented in this file.
+
+## 1.10.0 (2021-06-15)
+
+- Automate the release process with GitHub Actions
+- Use `setuptools_scm` to manage package versions
+- The layout is now an actual package rather than a single module
+- Clean up unused files
+
+## 1.9.0 (2021-02-12)
+
+- Add support for the `identity` value in *accept-encoding*, fixes
[#19](https://github.com/colour-science/flask-compress/issues/19)
+
+## 1.8.0 (2020-11-03)
+
+- Support ETag header as defined in *RFC7232*
[#17](https://github.com/colour-science/flask-compress/pull/17)
+- Implement per-view compression
[#14](https://github.com/colour-science/flask-compress/pull/14)
+
+## 1.7.0 (2020-10-09)
+
+- The following parameters to control Brotli compression are now available:
[#10](https://github.com/colour-science/flask-compress/pull/10)
+ - `COMPRESS_BR_MODE`
+ - `COMPRESS_BR_LEVEL`
+ - `COMPRESS_BR_WINDOW`
+ - `COMPRESS_BR_BLOCK`
+- Add deflate support, with `COMPRESS_DEFLATE_LEVEL` to control compression
level (default is `-1`)
[#8](https://github.com/colour-science/flask-compress/pull/8)
+- The default quality level for Brotli is now `4`, which provides compression
comparable to `gzip` at the default setting, while reducing the time required
versus the Brotli default of `11`
+
+## 1.6.0 (2020-10-05)
+
+- Support for multiple compression algorithms and quality factors
[#7](https://github.com/colour-science/flask-compress/pull/7)
+- Modified default compression settings to use Brotli when available before
`gzip`
+
+## 1.5.0 (2020-05-09)
+
+- Add Brotli support
[#1](https://github.com/colour-science/flask-compress/pull/1)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/Flask-Compress-1.8.0/Flask_Compress.egg-info/PKG-INFO
new/Flask-Compress-1.10.1/Flask_Compress.egg-info/PKG-INFO
--- old/Flask-Compress-1.8.0/Flask_Compress.egg-info/PKG-INFO 2020-11-03
14:25:41.000000000 +0100
+++ new/Flask-Compress-1.10.1/Flask_Compress.egg-info/PKG-INFO 2021-06-16
10:22:44.000000000 +0200
@@ -1,129 +1,11 @@
Metadata-Version: 2.1
Name: Flask-Compress
-Version: 1.8.0
+Version: 1.10.1
Summary: Compress responses in your Flask app with gzip, deflate or brotli.
Home-page: https://github.com/colour-science/flask-compress
Author: Thomas Mansencal
Author-email: [email protected]
License: MIT
-Description: # Flask-Compress
-
-
[](https://pypi.python.org/pypi/Flask-Compress)
- [](https://travis-ci.org/libwilliam/flask-compress)
-
[](https://coveralls.io/github/libwilliam/flask-compress)
-
[](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, deflate or
brotli.
-
- 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 compresses the response data.
- This makes serving 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 whether the client and the server use some common compression
algorithm, and will automatically attach the
- appropriate headers.
-
- To determine the compression algorithm, the `Accept-Encoding` request
header is inspected, respecting the
- quality factor as described in [MDN
docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding).
- If no requested compression algorithm is supported by the server, we
don't compress the response. If, on the other
- hand, multiple suitable algorithms are found and are requested with
the same quality factor, we choose the first one
- defined in the `COMPRESS_ALGORITHM` option (see below).
-
-
- ## 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/colour-science/flask-compress.git
- ```
-
- You can also install Flask-Compress via Easy Install:
-
- ```shell
- $ easy_install flask-compress
- ```
-
-
- ## Using Flask-Compress
-
- ### Globally
-
- Flask-Compress is incredibly simple to use. In order to start
compressing 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, 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.
-
- ### Per-view compression
-
- Compression is possible per view using the `@compress.compressed()`
decorator. Make sure to disable global compression first.
-
- ```python
- from flask import Flask
- from flask_compress import Compress
-
- app = Flask(__name__)
- app.config["COMPRESS_REGISTER"] = False # disable default compression
of all eligible requests
- compress = Compress()
- compress.init_app(app)
-
- # Compress this view specifically
- @app.route("/test")
- @compress.compressed()
- def view():
- pass
- ```
-
- ## 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. |
`[`<br>`'text/html',`<br>`'text/css',`<br>`'text/xml',`<br>`'application/json',`<br>`'application/javascript'`<br>`]`
|
- | `COMPRESS_LEVEL` | Specifies the gzip compression level. | `6` |
- | `COMPRESS_BR_LEVEL` | Specifies the Brotli compression level. Ranges
from 0 to 11. | `4` |
- | `COMPRESS_BR_MODE` | For Brotli, the compression mode. The options
are 0, 1, or 2. These correspond to "generic", "text" (for UTF-8 input), and
"font" (for WOFF 2.0). | `0` |
- | `COMPRESS_BR_WINDOW` | For Brotli, this specifies the base-2
logarithm of the sliding window size. Ranges from 10 to 24. | `22` |
- | `COMPRESS_BR_BLOCK` | For Brotli, this provides the base-2 logarithm
of the maximum input block size. If zero is provided, value will be determined
based on the quality. Ranges from 16 to 24. | `0` |
- | `COMPRESS_DEFLATE_LEVEL` | Specifies the deflate compression level.
| `-1` |
- | `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` |
- | `COMPRESS_ALGORITHM` | Supported compression algorithms. | `['br',
'gzip', 'deflate']` |
-
Platform: any
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
@@ -140,3 +22,123 @@
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Description-Content-Type: text/markdown
+License-File: LICENSE.txt
+
+# Flask-Compress
+
+[](https://github.com/colour-science/flask-compress/actions/workflows/ci.yaml)
+[](https://pypi.python.org/pypi/Flask-Compress)
+[](https://pypi.python.org/pypi/Flask-Compress)
+
+Flask-Compress allows you to easily compress your
[Flask](http://flask.pocoo.org/) application's responses with gzip, deflate or
brotli. It originally started as a fork of
[Flask-gzip](https://github.com/closeio/Flask-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 compresses the response data.
+This makes serving 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 whether the client and the server use some common compression algorithm,
and will automatically attach the
+appropriate headers.
+
+To determine the compression algorithm, the `Accept-Encoding` request header
is inspected, respecting the
+quality factor as described in [MDN
docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding).
+If no requested compression algorithm is supported by the server, we don't
compress the response. If, on the other
+hand, multiple suitable algorithms are found and are requested with the same
quality factor, we choose the first one
+defined in the `COMPRESS_ALGORITHM` option (see below).
+
+
+## Installation
+
+If you use pip then installation is simply:
+
+```shell
+$ pip install --user flask-compress
+```
+
+or, if you want the latest github version:
+
+```shell
+$ pip install --user git+git://github.com/colour-science/flask-compress.git
+```
+
+You can also install Flask-Compress via Easy Install:
+
+```shell
+$ easy_install flask-compress
+```
+
+
+## Using Flask-Compress
+
+### Globally
+
+Flask-Compress is incredibly simple to use. In order to start compressing 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, 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.
+
+### Per-view compression
+
+Compression is possible per view using the `@compress.compressed()` decorator.
Make sure to disable global compression first.
+
+```python
+from flask import Flask
+from flask_compress import Compress
+
+app = Flask(__name__)
+app.config["COMPRESS_REGISTER"] = False # disable default compression of all
eligible requests
+compress = Compress()
+compress.init_app(app)
+
+# Compress this view specifically
[email protected]("/test")
[email protected]()
+def view():
+ pass
+```
+
+## 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. |
`[`<br>`'text/html',`<br>`'text/css',`<br>`'text/xml',`<br>`'application/json',`<br>`'application/javascript'`<br>`]`
|
+| `COMPRESS_LEVEL` | Specifies the gzip compression level. | `6` |
+| `COMPRESS_BR_LEVEL` | Specifies the Brotli compression level. Ranges from 0
to 11. | `4` |
+| `COMPRESS_BR_MODE` | For Brotli, the compression mode. The options are 0, 1,
or 2. These correspond to "generic", "text" (for UTF-8 input), and "font" (for
WOFF 2.0). | `0` |
+| `COMPRESS_BR_WINDOW` | For Brotli, this specifies the base-2 logarithm of
the sliding window size. Ranges from 10 to 24. | `22` |
+| `COMPRESS_BR_BLOCK` | For Brotli, this provides the base-2 logarithm of the
maximum input block size. If zero is provided, value will be determined based
on the quality. Ranges from 16 to 24. | `0` |
+| `COMPRESS_DEFLATE_LEVEL` | Specifies the deflate compression level. | `-1` |
+| `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` |
+| `COMPRESS_ALGORITHM` | Supported compression algorithms. | `['br', 'gzip',
'deflate']` |
+
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/Flask-Compress-1.8.0/Flask_Compress.egg-info/SOURCES.txt
new/Flask-Compress-1.10.1/Flask_Compress.egg-info/SOURCES.txt
--- old/Flask-Compress-1.8.0/Flask_Compress.egg-info/SOURCES.txt
2020-11-03 14:25:41.000000000 +0100
+++ new/Flask-Compress-1.10.1/Flask_Compress.egg-info/SOURCES.txt
2021-06-16 10:22:44.000000000 +0200
@@ -1,15 +1,20 @@
+.gitignore
+CHANGELOG.md
LICENSE.txt
-MANIFEST.in
README.md
-flask_compress.py
+pyproject.toml
setup.py
+tox.ini
+.github/workflows/ci.yaml
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
+flask_compress/__init__.py
+flask_compress/_version.py
+flask_compress/flask_compress.py
tests/test_flask_compress.py
tests/static/1.png
tests/templates/large.html
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-Compress-1.8.0/MANIFEST.in
new/Flask-Compress-1.10.1/MANIFEST.in
--- old/Flask-Compress-1.8.0/MANIFEST.in 2020-04-21 09:38:27.000000000
+0200
+++ new/Flask-Compress-1.10.1/MANIFEST.in 1970-01-01 01:00:00.000000000
+0100
@@ -1,4 +0,0 @@
-include LICENSE.txt
-include README.md
-recursive-include tests *
-recursive-exclude tests *.pyc
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-Compress-1.8.0/PKG-INFO
new/Flask-Compress-1.10.1/PKG-INFO
--- old/Flask-Compress-1.8.0/PKG-INFO 2020-11-03 14:25:41.266460700 +0100
+++ new/Flask-Compress-1.10.1/PKG-INFO 2021-06-16 10:22:44.950378200 +0200
@@ -1,129 +1,11 @@
Metadata-Version: 2.1
Name: Flask-Compress
-Version: 1.8.0
+Version: 1.10.1
Summary: Compress responses in your Flask app with gzip, deflate or brotli.
Home-page: https://github.com/colour-science/flask-compress
Author: Thomas Mansencal
Author-email: [email protected]
License: MIT
-Description: # Flask-Compress
-
-
[](https://pypi.python.org/pypi/Flask-Compress)
- [](https://travis-ci.org/libwilliam/flask-compress)
-
[](https://coveralls.io/github/libwilliam/flask-compress)
-
[](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, deflate or
brotli.
-
- 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 compresses the response data.
- This makes serving 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 whether the client and the server use some common compression
algorithm, and will automatically attach the
- appropriate headers.
-
- To determine the compression algorithm, the `Accept-Encoding` request
header is inspected, respecting the
- quality factor as described in [MDN
docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding).
- If no requested compression algorithm is supported by the server, we
don't compress the response. If, on the other
- hand, multiple suitable algorithms are found and are requested with
the same quality factor, we choose the first one
- defined in the `COMPRESS_ALGORITHM` option (see below).
-
-
- ## 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/colour-science/flask-compress.git
- ```
-
- You can also install Flask-Compress via Easy Install:
-
- ```shell
- $ easy_install flask-compress
- ```
-
-
- ## Using Flask-Compress
-
- ### Globally
-
- Flask-Compress is incredibly simple to use. In order to start
compressing 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, 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.
-
- ### Per-view compression
-
- Compression is possible per view using the `@compress.compressed()`
decorator. Make sure to disable global compression first.
-
- ```python
- from flask import Flask
- from flask_compress import Compress
-
- app = Flask(__name__)
- app.config["COMPRESS_REGISTER"] = False # disable default compression
of all eligible requests
- compress = Compress()
- compress.init_app(app)
-
- # Compress this view specifically
- @app.route("/test")
- @compress.compressed()
- def view():
- pass
- ```
-
- ## 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. |
`[`<br>`'text/html',`<br>`'text/css',`<br>`'text/xml',`<br>`'application/json',`<br>`'application/javascript'`<br>`]`
|
- | `COMPRESS_LEVEL` | Specifies the gzip compression level. | `6` |
- | `COMPRESS_BR_LEVEL` | Specifies the Brotli compression level. Ranges
from 0 to 11. | `4` |
- | `COMPRESS_BR_MODE` | For Brotli, the compression mode. The options
are 0, 1, or 2. These correspond to "generic", "text" (for UTF-8 input), and
"font" (for WOFF 2.0). | `0` |
- | `COMPRESS_BR_WINDOW` | For Brotli, this specifies the base-2
logarithm of the sliding window size. Ranges from 10 to 24. | `22` |
- | `COMPRESS_BR_BLOCK` | For Brotli, this provides the base-2 logarithm
of the maximum input block size. If zero is provided, value will be determined
based on the quality. Ranges from 16 to 24. | `0` |
- | `COMPRESS_DEFLATE_LEVEL` | Specifies the deflate compression level.
| `-1` |
- | `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` |
- | `COMPRESS_ALGORITHM` | Supported compression algorithms. | `['br',
'gzip', 'deflate']` |
-
Platform: any
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
@@ -140,3 +22,123 @@
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Description-Content-Type: text/markdown
+License-File: LICENSE.txt
+
+# Flask-Compress
+
+[](https://github.com/colour-science/flask-compress/actions/workflows/ci.yaml)
+[](https://pypi.python.org/pypi/Flask-Compress)
+[](https://pypi.python.org/pypi/Flask-Compress)
+
+Flask-Compress allows you to easily compress your
[Flask](http://flask.pocoo.org/) application's responses with gzip, deflate or
brotli. It originally started as a fork of
[Flask-gzip](https://github.com/closeio/Flask-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 compresses the response data.
+This makes serving 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 whether the client and the server use some common compression algorithm,
and will automatically attach the
+appropriate headers.
+
+To determine the compression algorithm, the `Accept-Encoding` request header
is inspected, respecting the
+quality factor as described in [MDN
docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding).
+If no requested compression algorithm is supported by the server, we don't
compress the response. If, on the other
+hand, multiple suitable algorithms are found and are requested with the same
quality factor, we choose the first one
+defined in the `COMPRESS_ALGORITHM` option (see below).
+
+
+## Installation
+
+If you use pip then installation is simply:
+
+```shell
+$ pip install --user flask-compress
+```
+
+or, if you want the latest github version:
+
+```shell
+$ pip install --user git+git://github.com/colour-science/flask-compress.git
+```
+
+You can also install Flask-Compress via Easy Install:
+
+```shell
+$ easy_install flask-compress
+```
+
+
+## Using Flask-Compress
+
+### Globally
+
+Flask-Compress is incredibly simple to use. In order to start compressing 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, 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.
+
+### Per-view compression
+
+Compression is possible per view using the `@compress.compressed()` decorator.
Make sure to disable global compression first.
+
+```python
+from flask import Flask
+from flask_compress import Compress
+
+app = Flask(__name__)
+app.config["COMPRESS_REGISTER"] = False # disable default compression of all
eligible requests
+compress = Compress()
+compress.init_app(app)
+
+# Compress this view specifically
[email protected]("/test")
[email protected]()
+def view():
+ pass
+```
+
+## 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. |
`[`<br>`'text/html',`<br>`'text/css',`<br>`'text/xml',`<br>`'application/json',`<br>`'application/javascript'`<br>`]`
|
+| `COMPRESS_LEVEL` | Specifies the gzip compression level. | `6` |
+| `COMPRESS_BR_LEVEL` | Specifies the Brotli compression level. Ranges from 0
to 11. | `4` |
+| `COMPRESS_BR_MODE` | For Brotli, the compression mode. The options are 0, 1,
or 2. These correspond to "generic", "text" (for UTF-8 input), and "font" (for
WOFF 2.0). | `0` |
+| `COMPRESS_BR_WINDOW` | For Brotli, this specifies the base-2 logarithm of
the sliding window size. Ranges from 10 to 24. | `22` |
+| `COMPRESS_BR_BLOCK` | For Brotli, this provides the base-2 logarithm of the
maximum input block size. If zero is provided, value will be determined based
on the quality. Ranges from 16 to 24. | `0` |
+| `COMPRESS_DEFLATE_LEVEL` | Specifies the deflate compression level. | `-1` |
+| `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` |
+| `COMPRESS_ALGORITHM` | Supported compression algorithms. | `['br', 'gzip',
'deflate']` |
+
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-Compress-1.8.0/README.md
new/Flask-Compress-1.10.1/README.md
--- old/Flask-Compress-1.8.0/README.md 2020-11-02 09:38:17.000000000 +0100
+++ new/Flask-Compress-1.10.1/README.md 2021-06-16 10:22:32.000000000 +0200
@@ -1,11 +1,10 @@
# Flask-Compress
+[](https://github.com/colour-science/flask-compress/actions/workflows/ci.yaml)
[](https://pypi.python.org/pypi/Flask-Compress)
-[](https://travis-ci.org/libwilliam/flask-compress)
-[](https://coveralls.io/github/libwilliam/flask-compress)
-[](https://github.com/libwilliam/flask-compress/blob/master/LICENSE.txt)
+[](https://pypi.python.org/pypi/Flask-Compress)
-Flask-Compress allows you to easily compress your
[Flask](http://flask.pocoo.org/) application's responses with gzip, deflate or
brotli.
+Flask-Compress allows you to easily compress your
[Flask](http://flask.pocoo.org/) application's responses with gzip, deflate or
brotli. It originally started as a fork of
[Flask-gzip](https://github.com/closeio/Flask-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.
@@ -31,13 +30,13 @@
If you use pip then installation is simply:
```shell
-$ pip install flask-compress
+$ pip install --user flask-compress
```
or, if you want the latest github version:
```shell
-$ pip install git+git://github.com/colour-science/flask-compress.git
+$ pip install --user git+git://github.com/colour-science/flask-compress.git
```
You can also install Flask-Compress via Easy Install:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-Compress-1.8.0/flask_compress/__init__.py
new/Flask-Compress-1.10.1/flask_compress/__init__.py
--- old/Flask-Compress-1.8.0/flask_compress/__init__.py 1970-01-01
01:00:00.000000000 +0100
+++ new/Flask-Compress-1.10.1/flask_compress/__init__.py 2021-06-16
10:22:32.000000000 +0200
@@ -0,0 +1,9 @@
+from .flask_compress import Compress
+
+# _version.py is generated by setuptools_scm when building the package, it is
not versioned.
+# If missing, this means that the imported code was most likely the git
repository, that was
+# installed without the "editable" mode.
+try:
+ from ._version import __version__
+except ImportError:
+ __version__ = "0"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-Compress-1.8.0/flask_compress/_version.py
new/Flask-Compress-1.10.1/flask_compress/_version.py
--- old/Flask-Compress-1.8.0/flask_compress/_version.py 1970-01-01
01:00:00.000000000 +0100
+++ new/Flask-Compress-1.10.1/flask_compress/_version.py 2021-06-16
10:22:44.000000000 +0200
@@ -0,0 +1 @@
+__version__ = "1.10.1"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/Flask-Compress-1.8.0/flask_compress/flask_compress.py
new/Flask-Compress-1.10.1/flask_compress/flask_compress.py
--- old/Flask-Compress-1.8.0/flask_compress/flask_compress.py 1970-01-01
01:00:00.000000000 +0100
+++ new/Flask-Compress-1.10.1/flask_compress/flask_compress.py 2021-06-16
10:22:32.000000000 +0200
@@ -0,0 +1,237 @@
+
+# Authors: William Fagan
+# Copyright (c) 2013-2017 William Fagan
+# License: The MIT License (MIT)
+
+import sys
+import functools
+from gzip import GzipFile
+import zlib
+from io import BytesIO
+
+from collections import defaultdict
+
+import brotli
+from flask import request, after_this_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_BR_LEVEL', 4),
+ ('COMPRESS_BR_MODE', 0),
+ ('COMPRESS_BR_WINDOW', 22),
+ ('COMPRESS_BR_BLOCK', 0),
+ ('COMPRESS_DEFLATE_LEVEL', -1),
+ ('COMPRESS_MIN_SIZE', 500),
+ ('COMPRESS_CACHE_KEY', None),
+ ('COMPRESS_CACHE_BACKEND', None),
+ ('COMPRESS_REGISTER', True),
+ ('COMPRESS_ALGORITHM', ['br', 'gzip', 'deflate']),
+ ]
+
+ 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']
+
+ algo = app.config['COMPRESS_ALGORITHM']
+ if isinstance(algo, str):
+ self.enabled_algorithms = [i.strip() for i in algo.split(',')]
+ else:
+ self.enabled_algorithms = list(algo)
+
+ if (app.config['COMPRESS_REGISTER'] and
+ app.config['COMPRESS_MIMETYPES']):
+ app.after_request(self.after_request)
+
+ def _choose_compress_algorithm(self, accept_encoding_header):
+ """
+ Determine which compression algorithm we're going to use based on the
+ client request. The `Accept-Encoding` header may list one or more
desired
+ algorithms, together with a "quality factor" for each one (higher
quality
+ means the client prefers that algorithm more).
+
+ :param accept_encoding_header: Content of the `Accept-Encoding` header
+ :return: name of a compression algorithm (`gzip`, `deflate`, `br`) or
`None` if
+ the client and server don't agree on any.
+ """
+ # A flag denoting that client requested using any (`*`) algorithm,
+ # in case a specific one is not supported by the server
+ fallback_to_any = False
+
+ # Map quality factors to requested algorithm names.
+ algos_by_quality = defaultdict(set)
+
+ # Set of supported algorithms
+ server_algos_set = set(self.enabled_algorithms)
+
+ for part in accept_encoding_header.lower().split(','):
+ part = part.strip()
+ if ';q=' in part:
+ # If the client associated a quality factor with an algorithm,
+ # try to parse it. We could do the matching using a regex, but
+ # the format is so simple that it would be overkill.
+ algo = part.split(';')[0].strip()
+ try:
+ quality = float(part.split('=')[1].strip())
+ except ValueError:
+ quality = 1.0
+ else:
+ # Otherwise, use the default quality
+ algo = part
+ quality = 1.0
+
+ if algo == '*':
+ if quality > 0:
+ fallback_to_any = True
+ elif algo == 'identity': # identity means 'no compression asked'
+ algos_by_quality[quality].add(None)
+ elif algo in server_algos_set:
+ algos_by_quality[quality].add(algo)
+
+ # Choose the algorithm with the highest quality factor that the server
supports.
+ #
+ # If there are multiple equally good options, choose the first
supported algorithm
+ # from server configuration.
+ #
+ # If the server doesn't support any algorithm that the client
requested but
+ # there's a special wildcard algorithm request (`*`), choose the first
supported
+ # algorithm.
+ for _, viable_algos in sorted(algos_by_quality.items(), reverse=True):
+ if len(viable_algos) == 1:
+ return viable_algos.pop()
+ elif len(viable_algos) > 1:
+ for server_algo in self.enabled_algorithms:
+ if server_algo in viable_algos:
+ return server_algo
+
+ if fallback_to_any:
+ return self.enabled_algorithms[0]
+ return None
+
+ def after_request(self, response):
+ app = self.app or current_app
+
+ accept_encoding = request.headers.get('Accept-Encoding', '')
+ chosen_algorithm = self._choose_compress_algorithm(accept_encoding)
+
+ if (chosen_algorithm is None or
+ response.mimetype not in app.config["COMPRESS_MIMETYPES"] or
+ response.status_code < 200 or
+ response.status_code >= 300 or
+ "Content-Encoding" in response.headers or
+ (response.content_length is not None and
+ response.content_length < app.config["COMPRESS_MIN_SIZE"])):
+ return response
+
+ response.direct_passthrough = False
+
+ if self.cache is not None:
+ key = self.cache_key(request)
+ compressed_content = self.cache.get(key)
+ if compressed_content is None:
+ compressed_content = self.compress(app, response,
chosen_algorithm)
+ self.cache.set(key, compressed_content)
+ else:
+ compressed_content = self.compress(app, response, chosen_algorithm)
+
+ response.set_data(compressed_content)
+
+ response.headers['Content-Encoding'] = chosen_algorithm
+ response.headers['Content-Length'] = response.content_length
+
+ # "123456789" => "123456789:gzip" - A strong ETag validator
+ # W/"123456789" => W/"123456789:gzip" - A weak ETag validator
+ etag = response.headers.get('ETag')
+ if etag:
+ response.headers['ETag'] = '{0}:{1}"'.format(etag[:-1],
chosen_algorithm)
+
+ vary = response.headers.get('Vary')
+ if not vary:
+ response.headers['Vary'] = 'Accept-Encoding'
+ elif 'accept-encoding' not in vary.lower():
+ response.headers['Vary'] = '{}, Accept-Encoding'.format(vary)
+
+ return response
+
+ def compressed(self):
+ def decorator(f):
+ @functools.wraps(f)
+ def decorated_function(*args, **kwargs):
+ @after_this_request
+ def compressor(response):
+ return self.after_request(response)
+ return f(*args, **kwargs)
+ return decorated_function
+ return decorator
+
+ def compress(self, app, response, algorithm):
+ if algorithm == 'gzip':
+ 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()
+ elif algorithm == 'deflate':
+ return zlib.compress(response.get_data(),
+ app.config['COMPRESS_DEFLATE_LEVEL'])
+ elif algorithm == 'br':
+ return brotli.compress(response.get_data(),
+ mode=app.config['COMPRESS_BR_MODE'],
+ quality=app.config['COMPRESS_BR_LEVEL'],
+ lgwin=app.config['COMPRESS_BR_WINDOW'],
+ lgblock=app.config['COMPRESS_BR_BLOCK'])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-Compress-1.8.0/flask_compress.py
new/Flask-Compress-1.10.1/flask_compress.py
--- old/Flask-Compress-1.8.0/flask_compress.py 2020-11-03 09:34:40.000000000
+0100
+++ new/Flask-Compress-1.10.1/flask_compress.py 1970-01-01 01:00:00.000000000
+0100
@@ -1,233 +0,0 @@
-
-# Authors: William Fagan
-# Copyright (c) 2013-2017 William Fagan
-# License: The MIT License (MIT)
-
-import sys
-import functools
-from gzip import GzipFile
-import zlib
-from io import BytesIO
-
-from collections import defaultdict
-
-import brotli
-from flask import request, after_this_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_BR_LEVEL', 4),
- ('COMPRESS_BR_MODE', 0),
- ('COMPRESS_BR_WINDOW', 22),
- ('COMPRESS_BR_BLOCK', 0),
- ('COMPRESS_DEFLATE_LEVEL', -1),
- ('COMPRESS_MIN_SIZE', 500),
- ('COMPRESS_CACHE_KEY', None),
- ('COMPRESS_CACHE_BACKEND', None),
- ('COMPRESS_REGISTER', True),
- ('COMPRESS_ALGORITHM', ['br', 'gzip', 'deflate']),
- ]
-
- 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']
-
- algo = app.config['COMPRESS_ALGORITHM']
- if isinstance(algo, str):
- self.enabled_algorithms = [i.strip() for i in algo.split(',')]
- else:
- self.enabled_algorithms = algo
-
- if (app.config['COMPRESS_REGISTER'] and
- app.config['COMPRESS_MIMETYPES']):
- app.after_request(self.after_request)
-
- def _choose_compress_algorithm(self, accept_encoding_header):
- """
- Determine which compression algorithm we're going to use based on the
- client request. The `Accept-Encoding` header may list one or more
desired
- algorithms, together with a "quality factor" for each one (higher
quality
- means the client prefers that algorithm more).
-
- :param accept_encoding_header: Content of the `Accept-Encoding` header
- :return: name of a compression algorithm (`gzip`, `deflate`, `br`) or
`None` if
- the client and server don't agree on any.
- """
- # Map quality factors to requested algorithm names.
- algos_by_quality = defaultdict(set)
-
- # A flag denoting that client requested using any (`*`) algorithm,
- # in case a specific one is not supported by the server
- fallback_to_any = False
-
- for part in accept_encoding_header.lower().split(','):
- part = part.strip()
- quality = 1.0
-
- if ';q=' in part:
- # If the client associated a quality factor with an algorithm,
- # try to parse it. We could do the matching using a regex, but
- # the format is so simple that it would be overkill.
- algo = part.split(';')[0].strip()
- try:
- quality = float(part.split('=')[1].strip())
- except ValueError:
- pass
- else:
- # Otherwise, use the default quality
- algo = part
-
- algos_by_quality[quality].add(algo)
- fallback_to_any = fallback_to_any or (algo == '*')
-
- # Choose the algorithm with the highest quality factor that the server
supports.
- #
- # If there are multiple equally good options, choose the first
supported algorithm
- # from server configuration.
- #
- # If the server doesn't support any algorithm that the client
requested but
- # there's a special wildcard algorithm request (`*`), choose the first
supported
- # algorithm.
- server_algo_set = set(self.enabled_algorithms)
- for _, requested_algo_set in sorted(algos_by_quality.items(),
reverse=True):
- viable_algos = server_algo_set & requested_algo_set
- if len(viable_algos) == 1:
- return viable_algos.pop()
- elif len(viable_algos) > 1:
- for server_algo in self.enabled_algorithms:
- if server_algo in viable_algos:
- return server_algo
- else:
- if fallback_to_any:
- return self.enabled_algorithms[0]
-
- return None
-
- def after_request(self, response):
- app = self.app or current_app
-
- accept_encoding = request.headers.get('Accept-Encoding', '')
- chosen_algorithm = self._choose_compress_algorithm(accept_encoding)
-
- if (chosen_algorithm is None or
- response.mimetype not in app.config["COMPRESS_MIMETYPES"] or
- response.status_code < 200 or
- response.status_code >= 300 or
- "Content-Encoding" in response.headers or
- (response.content_length is not None and
- response.content_length < app.config["COMPRESS_MIN_SIZE"])):
- return response
-
- response.direct_passthrough = False
-
- if self.cache is not None:
- key = self.cache_key(request)
- compressed_content = self.cache.get(key)
- if compressed_content is None:
- compressed_content = self.compress(app, response,
chosen_algorithm)
- self.cache.set(key, compressed_content)
- else:
- compressed_content = self.compress(app, response, chosen_algorithm)
-
- response.set_data(compressed_content)
-
- response.headers['Content-Encoding'] = chosen_algorithm
- response.headers['Content-Length'] = response.content_length
-
- # "123456789" => "123456789:gzip" - A strong ETag validator
- # W/"123456789" => W/"123456789:gzip" - A weak ETag validator
- etag = response.headers.get('ETag')
- if etag:
- response.headers['ETag'] = '{0}:{1}"'.format(etag[:-1],
chosen_algorithm)
-
- vary = response.headers.get('Vary')
- if not vary:
- response.headers['Vary'] = 'Accept-Encoding'
- elif 'accept-encoding' not in vary.lower():
- response.headers['Vary'] = '{}, Accept-Encoding'.format(vary)
-
- return response
-
- def compressed(self):
- def decorator(f):
- @functools.wraps(f)
- def decorated_function(*args, **kwargs):
- @after_this_request
- def compressor(response):
- return self.after_request(response)
- return f(*args, **kwargs)
- return decorated_function
- return decorator
-
- def compress(self, app, response, algorithm):
- if algorithm == 'gzip':
- 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()
- elif algorithm == 'deflate':
- return zlib.compress(response.get_data(),
- app.config['COMPRESS_DEFLATE_LEVEL'])
- elif algorithm == 'br':
- return brotli.compress(response.get_data(),
- mode=app.config['COMPRESS_BR_MODE'],
- quality=app.config['COMPRESS_BR_LEVEL'],
- lgwin=app.config['COMPRESS_BR_WINDOW'],
- lgblock=app.config['COMPRESS_BR_BLOCK'])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-Compress-1.8.0/pyproject.toml
new/Flask-Compress-1.10.1/pyproject.toml
--- old/Flask-Compress-1.8.0/pyproject.toml 1970-01-01 01:00:00.000000000
+0100
+++ new/Flask-Compress-1.10.1/pyproject.toml 2021-06-16 10:22:32.000000000
+0200
@@ -0,0 +1,7 @@
+[build-system]
+requires = ["setuptools>=42", "wheel", "setuptools_scm[toml]>=3.4"]
+build-backend = "setuptools.build_meta"
+
+[tool.setuptools_scm]
+write_to = "flask_compress/_version.py"
+write_to_template = "__version__ = \"{version}\"\n"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-Compress-1.8.0/setup.py
new/Flask-Compress-1.10.1/setup.py
--- old/Flask-Compress-1.8.0/setup.py 2020-11-03 14:20:11.000000000 +0100
+++ new/Flask-Compress-1.10.1/setup.py 2021-06-16 10:22:32.000000000 +0200
@@ -1,11 +1,11 @@
-import setuptools
+from setuptools import setup, find_packages
with open('README.md') as fl:
LONG_DESCRIPTION = fl.read()
-setuptools.setup(
+setup(
name='Flask-Compress',
- version='1.8.0',
+ use_scm_version=True,
url='https://github.com/colour-science/flask-compress',
license='MIT',
author='Thomas Mansencal',
@@ -13,7 +13,7 @@
description='Compress responses in your Flask app with gzip, deflate or
brotli.',
long_description=LONG_DESCRIPTION,
long_description_content_type='text/markdown',
- py_modules=['flask_compress'],
+ packages=find_packages(exclude=['tests']),
zip_safe=False,
include_package_data=True,
platforms='any',
@@ -21,7 +21,6 @@
'flask',
'brotli'
],
- test_suite='tests',
classifiers=[
'Environment :: Web Environment',
'Intended Audience :: Developers',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-Compress-1.8.0/tests/test_flask_compress.py
new/Flask-Compress-1.10.1/tests/test_flask_compress.py
--- old/Flask-Compress-1.8.0/tests/test_flask_compress.py 2020-11-02
09:38:17.000000000 +0100
+++ new/Flask-Compress-1.10.1/tests/test_flask_compress.py 2021-06-16
10:22:32.000000000 +0200
@@ -273,6 +273,27 @@
c = Compress(self.app)
self.assertEqual(c._choose_compress_algorithm(accept_encoding), 'br')
+ def test_wildcard_quality(self):
+ """ Tests that a wildcard with q=0 is discarded """
+ accept_encoding = '*;q=0'
+ self.app.config['COMPRESS_ALGORITHM'] = ['gzip', 'br', 'deflate']
+ c = Compress(self.app)
+ self.assertEqual(c._choose_compress_algorithm(accept_encoding), None)
+
+ def test_identity(self):
+ """ Tests that identity is understood """
+ accept_encoding = 'identity;q=1, br;q=0.5, *;q=0'
+ self.app.config['COMPRESS_ALGORITHM'] = ['gzip', 'br', 'deflate']
+ c = Compress(self.app)
+ self.assertEqual(c._choose_compress_algorithm(accept_encoding), None)
+
+ def test_chrome_ranged_requests(self):
+ """ Tests that Chrome ranged requests behave as expected """
+ accept_encoding = 'identity;q=1, *;q=0'
+ self.app.config['COMPRESS_ALGORITHM'] = ['gzip', 'br', 'deflate']
+ c = Compress(self.app)
+ self.assertEqual(c._choose_compress_algorithm(accept_encoding), None)
+
def test_content_encoding_is_correct(self):
""" Test that the `Content-Encoding` header matches the compression
algorithm """
self.app.config['COMPRESS_ALGORITHM'] = ['br', 'gzip', 'deflate']
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-Compress-1.8.0/tox.ini
new/Flask-Compress-1.10.1/tox.ini
--- old/Flask-Compress-1.8.0/tox.ini 1970-01-01 01:00:00.000000000 +0100
+++ new/Flask-Compress-1.10.1/tox.ini 2021-06-16 10:22:32.000000000 +0200
@@ -0,0 +1,9 @@
+[tox]
+isolated_build = True
+skip_missing_interpreters = true
+envlist = py27,py35,py36,py37,py38,py39,pypy2,pypy3
+
+[testenv]
+deps =
+ pytest
+commands = py.test {posargs}