Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more pre-commit hooks #49

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,22 @@ repos:
- "--fix=lf"
- id: "trailing-whitespace"

- repo: "https://github.com/pycqa/isort"
rev: "5.13.2"
hooks:
- id: "isort"

- repo: "https://github.com/pycqa/flake8"
rev: "7.1.1"
hooks:
- id: "flake8"
additional_dependencies:
- "flake8-bugbear==24.8.19"

- repo: "https://github.com/python-jsonschema/check-jsonschema"
rev: "0.29.2"
hooks:
- id: "check-dependabot"
- id: "check-github-workflows"

- repo: "https://github.com/rhysd/actionlint"
Expand Down
9 changes: 6 additions & 3 deletions flask_compress/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
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.
# _version.py is generated by setuptools_scm when building the package.
# It is not version-controlled, so if it is missing, this likely means that
# the imported code was installed from the git repo without using "editable" mode.
try:
from ._version import __version__
except ImportError:
__version__ = "0"


__all__ = ("Compress",)
23 changes: 11 additions & 12 deletions flask_compress/flask_compress.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,20 @@
# Copyright (c) 2013-2017 William Fagan
# License: The MIT License (MIT)

import sys
import functools
from gzip import GzipFile
import sys
import zlib
from io import BytesIO

from collections import defaultdict
from gzip import GzipFile
from io import BytesIO

try:
import brotlicffi as brotli
except ImportError:
import brotli

import zstandard

from flask import request, after_this_request, current_app

from flask import after_this_request, current_app, request

if sys.version_info[:2] == (2, 6):
class GzipFile(GzipFile):
Expand Down Expand Up @@ -118,8 +115,8 @@ def _choose_compress_algorithm(self, accept_encoding_header):
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`, 'zstd') or `None` if
the client and server don't agree on any.
:return: name of a compression algorithm (`gzip`, `deflate`, `br`, 'zstd')
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
Expand Down Expand Up @@ -157,8 +154,8 @@ def _choose_compress_algorithm(self, accept_encoding_header):

# 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 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
Expand Down Expand Up @@ -250,4 +247,6 @@ def compress(self, app, response, algorithm):
lgwin=app.config['COMPRESS_BR_WINDOW'],
lgblock=app.config['COMPRESS_BR_BLOCK'])
elif algorithm == 'zstd':
return zstandard.ZstdCompressor(app.config['COMPRESS_ZSTD_LEVEL']).compress(response.get_data())
return zstandard.ZstdCompressor(app.config['COMPRESS_ZSTD_LEVEL']).compress(
response.get_data()
)
6 changes: 4 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from setuptools import setup, find_packages
from setuptools import find_packages, setup

with open('README.md') as fl:
LONG_DESCRIPTION = fl.read()
Expand All @@ -10,7 +10,9 @@
license='MIT',
author='Thomas Mansencal',
author_email='thomas.mansencal@gmail.com',
description='Compress responses in your Flask app with gzip, deflate, brotli or zstandard.',
description=(
'Compress responses in your Flask app with gzip, deflate, brotli or zstandard.'
),
long_description=LONG_DESCRIPTION,
long_description_content_type='text/markdown',
packages=find_packages(exclude=['tests']),
Expand Down
32 changes: 20 additions & 12 deletions tests/test_flask_compress.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import unittest
import os
import unittest

from flask import Flask, render_template

Expand Down Expand Up @@ -35,7 +35,9 @@ def test_min_size_default(self):

def test_algorithm_default(self):
""" Tests COMPRESS_ALGORITHM default value is correctly set. """
self.assertEqual(self.app.config['COMPRESS_ALGORITHM'], ['zstd', 'br', 'gzip', 'deflate'])
self.assertEqual(
self.app.config['COMPRESS_ALGORITHM'], ['zstd', 'br', 'gzip', 'deflate']
)

def test_default_deflate_settings(self):
""" Tests COMPRESS_DELATE_LEVEL default value is correctly set. """
Expand Down Expand Up @@ -65,6 +67,7 @@ def test_quality_level_default_zstd(self):
""" Tests COMPRESS_ZSTD_LEVEL default value is correctly set. """
self.assertEqual(self.app.config['COMPRESS_ZSTD_LEVEL'], 3)


class InitTests(unittest.TestCase):
def setUp(self):
self.app = Flask(__name__)
Expand Down Expand Up @@ -203,6 +206,7 @@ def test_zstd_compression_level(self):

self.assertNotEqual(response1_size, response11_size)


class CompressionAlgoTests(unittest.TestCase):
"""
Test different scenarios for compression algorithm negotiation between
Expand All @@ -213,9 +217,10 @@ class CompressionAlgoTests(unittest.TestCase):
def setUp(self):
super(CompressionAlgoTests, self).setUp()

# Create the app here but don't call `Compress()` on it just yet; we need
# to be able to modify the settings in various tests. Calling `Compress(self.app)`
# twice would result in two `@after_request` handlers, which would be bad.
# Create the app here but don't call `Compress()` on it just yet;
# we need to be able to modify the settings in various tests.
# Calling `Compress(self.app)` twice would result in
# two `@after_request` handlers, which would be bad.
self.app = Flask(__name__)
self.app.testing = True

Expand All @@ -227,7 +232,9 @@ def small():
return render_template('small.html')

def test_setting_compress_algorithm_simple_string(self):
""" Test that a single entry in `COMPRESS_ALGORITHM` still works for backwards compatibility """
"""Test that a single entry in `COMPRESS_ALGORITHM` still works.

This is a backwards-compatibility test."""
self.app.config['COMPRESS_ALGORITHM'] = 'gzip'
c = Compress(self.app)
self.assertListEqual(c.enabled_algorithms, ['gzip'])
Expand Down Expand Up @@ -263,7 +270,7 @@ def test_multiple_algos_supported(self):
accept_encoding = 'br, gzip, zstd'
self.app.config['COMPRESS_ALGORITHM'] = ['zstd', 'br', 'gzip']
c = Compress(self.app)
# When the decision is tied, we expect to see the first server-configured algorithm
# When the decision is tied, we expect the first server-configured algorithm
self.assertEqual(c._choose_compress_algorithm(accept_encoding), 'zstd')

def test_multiple_algos_unsupported(self):
Expand All @@ -274,30 +281,30 @@ def test_multiple_algos_unsupported(self):
self.assertIsNone(c._choose_compress_algorithm(accept_encoding))

def test_multiple_algos_with_wildcard(self):
""" Tests requesting multiple unsupported compression algorithms and a wildcard """
"""Request multiple unsupported compression algorithms and a wildcard"""
accept_encoding = 'future-algo, alien-algo, forbidden-algo, *'
self.app.config['COMPRESS_ALGORITHM'] = ['zstd', 'br', 'gzip']
c = Compress(self.app)
# We expect to see the first server-configured algorithm
self.assertEqual(c._choose_compress_algorithm(accept_encoding), 'zstd')

def test_multiple_algos_with_different_quality(self):
""" Tests requesting multiple supported compression algorithms with different q-factors """
"""Request multiple supported compression algorithms with different q-factors"""
accept_encoding = 'zstd;q=0.8, br;q=0.9, gzip;q=0.5'
self.app.config['COMPRESS_ALGORITHM'] = ['zstd', 'br', 'gzip']
c = Compress(self.app)
self.assertEqual(c._choose_compress_algorithm(accept_encoding), 'br')

def test_multiple_algos_with_equal_quality(self):
""" Tests requesting multiple supported compression algorithms with equal q-factors """
"""Request multiple supported compression algorithms with equal q-factors"""
accept_encoding = 'zstd;q=0.5, br;q=0.5, gzip;q=0.5'
self.app.config['COMPRESS_ALGORITHM'] = ['gzip', 'br', 'zstd']
c = Compress(self.app)
# We expect to see the first server-configured algorithm
self.assertEqual(c._choose_compress_algorithm(accept_encoding), 'gzip')

def test_default_quality_is_1(self):
""" Tests that when making mixed-quality requests, the default q-factor is 1.0 """
"""Tests that when making mixed-quality requests, the default q-factor is 1.0"""
accept_encoding = 'deflate, br;q=0.999, gzip;q=0.5'
self.app.config['COMPRESS_ALGORITHM'] = ['gzip', 'br', 'deflate']
c = Compress(self.app)
Expand Down Expand Up @@ -332,7 +339,7 @@ def test_chrome_ranged_requests(self):
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 """
"""Test that the `Content-Encoding` header matches the compression algorithm"""
self.app.config['COMPRESS_ALGORITHM'] = ['zstd', 'br', 'gzip', 'deflate']
Compress(self.app)

Expand Down Expand Up @@ -360,6 +367,7 @@ def test_content_encoding_is_correct(self):
self.assertIn('Content-Encoding', response_zstd.headers)
self.assertEqual(response_zstd.headers.get('Content-Encoding'), 'zstd')


class CompressionPerViewTests(unittest.TestCase):
def setUp(self):
self.app = Flask(__name__)
Expand Down
4 changes: 4 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ wheel_build_env = .pkg
deps =
pytest
commands = py.test {posargs}

[flake8]
max-line-length = 88
extend-ignore = E203