Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoSign in
Socket

flask

Package Overview
Dependencies
Maintainers
0
Versions
64
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

flask - pypi Package Compare versions

Comparing version
3.1.0
to
3.1.1
uv.lock

Sorry, the diff of this file is too big to display

+4
-0

@@ -29,2 +29,3 @@ import packaging.version

"pr": ("https://github.com/pallets/flask/pull/%s", "#%s"),
"ghsa": ("https://github.com/pallets/flask/security/advisories/GHSA-%s", "GHSA-%s"),
}

@@ -66,2 +67,5 @@ intersphinx_mapping = {

gettext_uuid = True
gettext_compact = False
# Local Extensions -----------------------------------------------------

@@ -68,0 +72,0 @@

+6
-3

@@ -130,5 +130,5 @@ Configuration Handling

A list of old secret keys that can still be used for unsigning, most recent
first. This allows a project to implement key rotation without invalidating
active sessions or other recently-signed secrets.
A list of old secret keys that can still be used for unsigning. This allows
a project to implement key rotation without invalidating active sessions or
other recently-signed secrets.

@@ -138,2 +138,5 @@ Keys should be removed after an appropriate period of time, as checking each

Order should not matter, but the default implementation will test the last
key in the list first, so it might make sense to order oldest to newest.
Flask's built-in secure cookie session supports this. Extensions that use

@@ -140,0 +143,0 @@ :data:`SECRET_KEY` may not support this yet.

@@ -1,1 +0,8 @@

.. include:: ../CONTRIBUTING.rst
Contributing
============
See the Pallets `detailed contributing documentation <_contrib>`_ for many ways
to contribute, including reporting issues, requesting features, asking or
answering questions, and making PRs.
.. _contrib: https://palletsprojects.com/contributing/

@@ -102,5 +102,5 @@ Application Factories

$ flask --app hello:create_app(local_auth=True) run
$ flask --app 'hello:create_app(local_auth=True)' run
Then the ``create_app`` factory in ``myapp`` is called with the keyword
Then the ``create_app`` factory in ``hello`` is called with the keyword
argument ``local_auth=True``. See :doc:`/cli` for more detail.

@@ -107,0 +107,0 @@

@@ -27,4 +27,7 @@ Adding a favicon

app.add_url_rule('/favicon.ico',
redirect_to=url_for('static', filename='favicon.ico'))
app.add_url_rule(
"/favicon.ico",
endpoint="favicon",
redirect_to=url_for("static", filename="favicon.ico"),
)

@@ -31,0 +34,0 @@ If you want to save the extra redirect request you can also write a view

@@ -83,3 +83,3 @@ MongoDB with MongoEngine

bttf = Movies.objects(title="Back To The Future").get_or_404()
bttf = Movie.objects(title="Back To The Future").get_or_404()

@@ -86,0 +86,0 @@ Query operators may be used by concatenating them with the field name

@@ -272,15 +272,2 @@ Security Considerations

HTTP Public Key Pinning (HPKP)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This tells the browser to authenticate with the server using only the specific
certificate key to prevent MITM attacks.
.. warning::
Be careful when enabling this, as it is very difficult to undo if you set up
or upgrade your key incorrectly.
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Public_Key_Pinning
Copy/Paste to Terminal

@@ -287,0 +274,0 @@ ----------------------

+23
-15

@@ -1,4 +0,4 @@

Metadata-Version: 2.3
Metadata-Version: 2.4
Name: Flask
Version: 3.1.0
Version: 3.1.1
Summary: A simple framework for building complex web applications.

@@ -8,2 +8,3 @@ Maintainer-email: Pallets <contact@palletsprojects.com>

Description-Content-Type: text/markdown
License-Expression: BSD-3-Clause
Classifier: Development Status :: 5 - Production/Stable

@@ -13,3 +14,2 @@ Classifier: Environment :: Web Environment

Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent

@@ -22,11 +22,13 @@ Classifier: Programming Language :: Python

Classifier: Typing :: Typed
Requires-Dist: Werkzeug>=3.1
Requires-Dist: Jinja2>=3.1.2
Requires-Dist: itsdangerous>=2.2
License-File: LICENSE.txt
Requires-Dist: blinker>=1.9.0
Requires-Dist: click>=8.1.3
Requires-Dist: blinker>=1.9
Requires-Dist: importlib-metadata>=3.6; python_version < '3.10'
Requires-Dist: importlib-metadata>=3.6.0; python_version < '3.10'
Requires-Dist: itsdangerous>=2.2.0
Requires-Dist: jinja2>=3.1.2
Requires-Dist: markupsafe>=2.1.1
Requires-Dist: werkzeug>=3.1.0
Requires-Dist: asgiref>=3.2 ; extra == "async"
Requires-Dist: python-dotenv ; extra == "dotenv"
Project-URL: Changes, https://flask.palletsprojects.com/changes/
Project-URL: Changes, https://flask.palletsprojects.com/page/changes/
Project-URL: Chat, https://discord.gg/pallets

@@ -41,6 +43,6 @@ Project-URL: Documentation, https://flask.palletsprojects.com/

Flask is a lightweight [WSGI][] web application framework. It is designed
Flask is a lightweight [WSGI] web application framework. It is designed
to make getting started quick and easy, with the ability to scale up to
complex applications. It began as a simple wrapper around [Werkzeug][]
and [Jinja][], and has become one of the most popular Python web
complex applications. It began as a simple wrapper around [Werkzeug]
and [Jinja], and has become one of the most popular Python web
application frameworks.

@@ -57,3 +59,2 @@

## A Simple Example

@@ -77,3 +78,2 @@

## Donate

@@ -84,5 +84,13 @@

allow the maintainers to devote more time to the projects, [please
donate today][].
donate today].
[please donate today]: https://palletsprojects.com/donate
## Contributing
See our [detailed contributing documentation][contrib] for many ways to
contribute, including reporting issues, requesting features, asking or answering
questions, and making PRs.
[contrib]: https://palletsprojects.com/contributing/
[project]
name = "Flask"
version = "3.1.0"
version = "3.1.1"
description = "A simple framework for building complex web applications."
readme = "README.md"
license = {file = "LICENSE.txt"}
license = "BSD-3-Clause"
license-files = ["LICENSE.txt"]
maintainers = [{name = "Pallets", email = "contact@palletsprojects.com"}]

@@ -13,3 +14,2 @@ classifiers = [

"Intended Audience :: Developers",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",

@@ -25,21 +25,61 @@ "Programming Language :: Python",

dependencies = [
"Werkzeug>=3.1",
"Jinja2>=3.1.2",
"itsdangerous>=2.2",
"blinker>=1.9.0",
"click>=8.1.3",
"blinker>=1.9",
"importlib-metadata>=3.6; python_version < '3.10'",
"importlib-metadata>=3.6.0; python_version < '3.10'",
"itsdangerous>=2.2.0",
"jinja2>=3.1.2",
"markupsafe>=2.1.1",
"werkzeug>=3.1.0",
]
[project.optional-dependencies]
async = ["asgiref>=3.2"]
dotenv = ["python-dotenv"]
[dependency-groups]
dev = [
"ruff",
"tox",
"tox-uv",
]
docs = [
"pallets-sphinx-themes",
"sphinx",
"sphinx-tabs",
"sphinxcontrib-log-cabinet",
]
docs-auto = [
"sphinx-autobuild",
]
gha-update = [
"gha-update ; python_full_version >= '3.12'",
]
pre-commit = [
"pre-commit",
"pre-commit-uv",
]
tests = [
"asgiref",
"greenlet ; python_version < '3.11'",
"pytest",
"python-dotenv",
]
typing = [
"asgiref",
"cryptography",
"mypy",
"pyright",
"pytest",
"python-dotenv",
"types-contextvars",
"types-dataclasses",
]
[project.urls]
Donate = "https://palletsprojects.com/donate"
Documentation = "https://flask.palletsprojects.com/"
Changes = "https://flask.palletsprojects.com/changes/"
Changes = "https://flask.palletsprojects.com/page/changes/"
Source = "https://github.com/pallets/flask/"
Chat = "https://discord.gg/pallets"
[project.optional-dependencies]
async = ["asgiref>=3.2"]
dotenv = ["python-dotenv"]
[project.scripts]

@@ -59,7 +99,5 @@ flask = "flask.cli:main"

"examples/",
"requirements/",
"tests/",
"CHANGES.rst",
"CONTRIBUTING.rst",
"tox.ini",
"uv.lock"
]

@@ -70,2 +108,5 @@ exclude = [

[tool.uv]
default-groups = ["dev", "pre-commit", "tests", "typing"]
[tool.pytest.ini_options]

@@ -84,5 +125,12 @@ testpaths = ["tests"]

[tool.coverage.report]
exclude_also = [
"if t.TYPE_CHECKING",
"raise NotImplementedError",
": \\.{3}",
]
[tool.mypy]
python_version = "3.9"
files = ["src/flask", "tests/type_check"]
files = ["src", "tests/type_check"]
show_error_codes = true

@@ -103,3 +151,3 @@ pretty = true

pythonVersion = "3.9"
include = ["src/flask", "tests/type_check"]
include = ["src", "tests/type_check"]
typeCheckingMode = "basic"

@@ -131,1 +179,109 @@

]
[tool.tox]
env_list = [
"py3.13", "py3.12", "py3.11", "py3.10", "py3.9",
"pypy3.11",
"tests-min", "tests-dev",
"style",
"typing",
"docs",
]
[tool.tox.env_run_base]
description = "pytest on latest dependency versions"
runner = "uv-venv-lock-runner"
package = "wheel"
wheel_build_env = ".pkg"
constrain_package_deps = true
use_frozen_constraints = true
dependency_groups = ["tests"]
env_tmp_dir = "{toxworkdir}/tmp/{envname}"
commands = [[
"pytest", "-v", "--tb=short", "--basetemp={env_tmp_dir}",
{replace = "posargs", default = [], extend = true},
]]
[tool.tox.env.tests-min]
description = "pytest on minimum dependency versions"
base_python = ["3.13"]
commands = [
[
"uv", "pip", "install",
"blinker==1.9.0",
"click==8.1.3",
"itsdangerous==2.2.0",
"jinja2==3.1.2",
"markupsafe==2.1.1",
"werkzeug==3.1.0",
],
[
"pytest", "-v", "--tb=short", "--basetemp={env_tmp_dir}",
{replace = "posargs", default = [], extend = true},
],
]
[tool.tox.env.tests-dev]
description = "pytest on development dependency versions (git main branch)"
base_python = ["3.10"]
commands = [
[
"uv", "pip", "install",
"https://github.com/pallets-eco/blinker/archive/refs/heads/main.tar.gz",
"https://github.com/pallets/click/archive/refs/heads/main.tar.gz",
"https://github.com/pallets/itsdangerous/archive/refs/heads/main.tar.gz",
"https://github.com/pallets/jinja/archive/refs/heads/main.tar.gz",
"https://github.com/pallets/markupsafe/archive/refs/heads/main.tar.gz",
"https://github.com/pallets/werkzeug/archive/refs/heads/main.tar.gz",
],
[
"pytest", "-v", "--tb=short", "--basetemp={env_tmp_dir}",
{replace = "posargs", default = [], extend = true},
],
]
[tool.tox.env.style]
description = "run all pre-commit hooks on all files"
dependency_groups = ["pre-commit"]
skip_install = true
commands = [["pre-commit", "run", "--all-files"]]
[tool.tox.env.typing]
description = "run static type checkers"
dependency_groups = ["typing"]
commands = [
["mypy"],
["pyright"],
]
[tool.tox.env.docs]
description = "build docs"
dependency_groups = ["docs"]
commands = [["sphinx-build", "-E", "-W", "-b", "dirhtml", "docs", "docs/_build/dirhtml"]]
[tool.tox.env.docs-auto]
description = "continuously rebuild docs and start a local server"
dependency_groups = ["docs", "docs-auto"]
commands = [["sphinx-autobuild", "-W", "-b", "dirhtml", "--watch", "src", "docs", "docs/_build/dirhtml"]]
[tool.tox.env.update-actions]
description = "update GitHub Actions pins"
labels = ["update"]
dependency_groups = ["gha-update"]
skip_install = true
commands = [["gha-update"]]
[tool.tox.env.update-pre_commit]
description = "update pre-commit pins"
labels = ["update"]
dependency_groups = ["pre-commit"]
skip_install = true
commands = [["pre-commit", "autoupdate", "--freeze", "-j4"]]
[tool.tox.env.update-requirements]
description = "update uv lock"
labels = ["update"]
dependency_groups = []
no_default_groups = true
skip_install = true
commands = [["uv", "lock", {replace = "posargs", default = ["-U"], extend = true}]]
# Flask
Flask is a lightweight [WSGI][] web application framework. It is designed
Flask is a lightweight [WSGI] web application framework. It is designed
to make getting started quick and easy, with the ability to scale up to
complex applications. It began as a simple wrapper around [Werkzeug][]
and [Jinja][], and has become one of the most popular Python web
complex applications. It began as a simple wrapper around [Werkzeug]
and [Jinja], and has become one of the most popular Python web
application frameworks.

@@ -18,3 +18,2 @@

## A Simple Example

@@ -38,3 +37,2 @@

## Donate

@@ -45,4 +43,12 @@

allow the maintainers to devote more time to the projects, [please
donate today][].
donate today].
[please donate today]: https://palletsprojects.com/donate
## Contributing
See our [detailed contributing documentation][contrib] for many ways to
contribute, including reporting issues, requesting features, asking or answering
questions, and making PRs.
[contrib]: https://palletsprojects.com/contributing/

@@ -45,17 +45,18 @@ from __future__ import annotations

if not t.TYPE_CHECKING:
def __getattr__(name: str) -> t.Any:
if name == "__version__":
import importlib.metadata
import warnings
def __getattr__(name: str) -> t.Any:
if name == "__version__":
import importlib.metadata
import warnings
warnings.warn(
"The '__version__' attribute is deprecated and will be removed in"
" Flask 3.1. Use feature detection or"
" 'importlib.metadata.version(\"flask\")' instead.",
DeprecationWarning,
stacklevel=2,
)
return importlib.metadata.version("flask")
warnings.warn(
"The '__version__' attribute is deprecated and will be removed in"
" Flask 3.2. Use feature detection or"
" 'importlib.metadata.version(\"flask\")' instead.",
DeprecationWarning,
stacklevel=2,
)
return importlib.metadata.version("flask")
raise AttributeError(name)
raise AttributeError(name)

@@ -268,5 +268,5 @@ from __future__ import annotations

if self.has_static_folder:
assert (
bool(static_host) == host_matching
), "Invalid static_host/host_matching combination"
assert bool(static_host) == host_matching, (
"Invalid static_host/host_matching combination"
)
# Use a weakref to avoid creating a reference cycle between the app

@@ -1226,3 +1226,3 @@ # and the view function (see #3761).

rv = self.response_class(
rv,
rv, # pyright: ignore
status=status,

@@ -1229,0 +1229,0 @@ headers=headers, # type: ignore[arg-type]

@@ -687,3 +687,5 @@ from __future__ import annotations

def parse_args(self, ctx: click.Context, args: list[str]) -> list[str]:
if not args and self.no_args_is_help:
if (not args and self.no_args_is_help) or (
len(args) == 1 and args[0] in self.get_help_option_names(ctx)
):
# Attempt to load --env-file and --app early in case they

@@ -690,0 +692,0 @@ # were given as env vars. Otherwise no_args_is_help will not

@@ -321,3 +321,3 @@ from __future__ import annotations

keys: list[str | bytes] = [app.secret_key]
keys: list[str | bytes] = []

@@ -327,2 +327,3 @@ if fallbacks := app.config["SECRET_KEY_FALLBACKS"]:

keys.append(app.secret_key) # itsdangerous expects current key at top
return URLSafeTimedSerializer(

@@ -329,0 +330,0 @@ keys, # type: ignore[arg-type]

@@ -13,2 +13,3 @@ from __future__ import annotations

from click.testing import CliRunner
from click.testing import Result
from werkzeug.test import Client

@@ -61,5 +62,5 @@ from werkzeug.wrappers import Request as BaseRequest

base_url is not None
) != bool(
subdomain or url_scheme
), 'Cannot pass "subdomain" or "url_scheme" with "base_url".'
) != bool(subdomain or url_scheme), (
'Cannot pass "subdomain" or "url_scheme" with "base_url".'
)

@@ -278,3 +279,3 @@ if base_url is None:

self, cli: t.Any = None, args: t.Any = None, **kwargs: t.Any
) -> t.Any:
) -> Result:
"""Invokes a CLI command in an isolated environment. See

@@ -281,0 +282,0 @@ :meth:`CliRunner.invoke <click.testing.CliRunner.invoke>` for

from __future__ import annotations
import collections.abc as cabc
import typing as t

@@ -20,2 +21,4 @@

t.Iterator[bytes],
cabc.AsyncIterable[str], # for Quart, until App is generic.
cabc.AsyncIterable[bytes],
]

@@ -22,0 +25,0 @@

import os
import pkgutil
import sys

@@ -99,33 +98,2 @@

@pytest.fixture(params=(True, False))
def limit_loader(request, monkeypatch):
"""Patch pkgutil.get_loader to give loader without get_filename or archive.
This provides for tests where a system has custom loaders, e.g. Google App
Engine's HardenedModulesHook, which have neither the `get_filename` method
nor the `archive` attribute.
This fixture will run the testcase twice, once with and once without the
limitation/mock.
"""
if not request.param:
return
class LimitedLoader:
def __init__(self, loader):
self.loader = loader
def __getattr__(self, name):
if name in {"archive", "get_filename"}:
raise AttributeError(f"Mocking a loader which does not have {name!r}.")
return getattr(self.loader, name)
old_get_loader = pkgutil.get_loader
def get_loader(*args, **kwargs):
return LimitedLoader(old_get_loader(*args, **kwargs))
monkeypatch.setattr(pkgutil, "get_loader", get_loader)
@pytest.fixture

@@ -132,0 +100,0 @@ def modules_tmp_path(tmp_path, monkeypatch):

@@ -384,10 +384,17 @@ import gc

# Set session with initial secret key
# Set session with initial secret key, and two valid expiring keys
app.secret_key, app.config["SECRET_KEY_FALLBACKS"] = (
"0 key",
["-1 key", "-2 key"],
)
client.post()
assert client.get().json == {"a": 1}
# Change secret key, session can't be loaded and appears empty
app.secret_key = "new test key"
app.secret_key = "? key"
assert client.get().json == {}
# Add initial secret key as fallback, session can be loaded
app.config["SECRET_KEY_FALLBACKS"] = ["test key"]
# Rotate the valid keys, session can be loaded
app.secret_key, app.config["SECRET_KEY_FALLBACKS"] = (
"+1 key",
["0 key", "-1 key"],
)
assert client.get().json == {"a": 1}

@@ -394,0 +401,0 @@

@@ -66,3 +66,3 @@ import os

def test_installed_module_paths(
modules_tmp_path, modules_tmp_path_prefix, purge_module, site_packages, limit_loader
modules_tmp_path, modules_tmp_path_prefix, purge_module, site_packages
):

@@ -82,3 +82,3 @@ (site_packages / "site_app.py").write_text(

def test_installed_package_paths(
limit_loader, modules_tmp_path, modules_tmp_path_prefix, purge_module, monkeypatch
modules_tmp_path, modules_tmp_path_prefix, purge_module, monkeypatch
):

@@ -102,3 +102,3 @@ installed_path = modules_tmp_path / "path"

def test_prefix_package_paths(
limit_loader, modules_tmp_path, modules_tmp_path_prefix, purge_module, site_packages
modules_tmp_path, modules_tmp_path_prefix, purge_module, site_packages
):

@@ -105,0 +105,0 @@ app = site_packages / "site_package"

How to contribute to Flask
==========================
Thank you for considering contributing to Flask!
Support questions
-----------------
Please don't use the issue tracker for this. The issue tracker is a tool
to address bugs and feature requests in Flask itself. Use one of the
following resources for questions about using Flask or issues with your
own code:
- The ``#questions`` channel on our Discord chat:
https://discord.gg/pallets
- Ask on `Stack Overflow`_. Search with Google first using:
``site:stackoverflow.com flask {search term, exception message, etc.}``
- Ask on our `GitHub Discussions`_ for long term discussion or larger
questions.
.. _Stack Overflow: https://stackoverflow.com/questions/tagged/flask?tab=Frequent
.. _GitHub Discussions: https://github.com/pallets/flask/discussions
Reporting issues
----------------
Include the following information in your post:
- Describe what you expected to happen.
- If possible, include a `minimal reproducible example`_ to help us
identify the issue. This also helps check that the issue is not with
your own code.
- Describe what actually happened. Include the full traceback if there
was an exception.
- List your Python and Flask versions. If possible, check if this
issue is already fixed in the latest releases or the latest code in
the repository.
.. _minimal reproducible example: https://stackoverflow.com/help/minimal-reproducible-example
Submitting patches
------------------
If there is not an open issue for what you want to submit, prefer
opening one for discussion before working on a PR. You can work on any
issue that doesn't have an open PR linked to it or a maintainer assigned
to it. These show up in the sidebar. No need to ask if you can work on
an issue that interests you.
Include the following in your patch:
- Use `Black`_ to format your code. This and other tools will run
automatically if you install `pre-commit`_ using the instructions
below.
- Include tests if your patch adds or changes code. Make sure the test
fails without your patch.
- Update any relevant docs pages and docstrings. Docs pages and
docstrings should be wrapped at 72 characters.
- Add an entry in ``CHANGES.rst``. Use the same style as other
entries. Also include ``.. versionchanged::`` inline changelogs in
relevant docstrings.
.. _Black: https://black.readthedocs.io
.. _pre-commit: https://pre-commit.com
First time setup using GitHub Codespaces
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`GitHub Codespaces`_ creates a development environment that is already set up for the
project. By default it opens in Visual Studio Code for the Web, but this can
be changed in your GitHub profile settings to use Visual Studio Code or JetBrains
PyCharm on your local computer.
- Make sure you have a `GitHub account`_.
- From the project's repository page, click the green "Code" button and then "Create
codespace on main".
- The codespace will be set up, then Visual Studio Code will open. However, you'll
need to wait a bit longer for the Python extension to be installed. You'll know it's
ready when the terminal at the bottom shows that the virtualenv was activated.
- Check out a branch and `start coding`_.
.. _GitHub Codespaces: https://docs.github.com/en/codespaces
.. _devcontainer: https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/adding-a-dev-container-configuration/introduction-to-dev-containers
First time setup in your local environment
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Make sure you have a `GitHub account`_.
- Download and install the `latest version of git`_.
- Configure git with your `username`_ and `email`_.
.. code-block:: text
$ git config --global user.name 'your name'
$ git config --global user.email 'your email'
- Fork Flask to your GitHub account by clicking the `Fork`_ button.
- `Clone`_ your fork locally, replacing ``your-username`` in the command below with
your actual username.
.. code-block:: text
$ git clone https://github.com/your-username/flask
$ cd flask
- Create a virtualenv. Use the latest version of Python.
- Linux/macOS
.. code-block:: text
$ python3 -m venv .venv
$ . .venv/bin/activate
- Windows
.. code-block:: text
> py -3 -m venv .venv
> .venv\Scripts\activate
- Install the development dependencies, then install Flask in editable mode.
.. code-block:: text
$ python -m pip install -U pip
$ pip install -r requirements/dev.txt && pip install -e .
- Install the pre-commit hooks.
.. code-block:: text
$ pre-commit install --install-hooks
.. _GitHub account: https://github.com/join
.. _latest version of git: https://git-scm.com/downloads
.. _username: https://docs.github.com/en/github/using-git/setting-your-username-in-git
.. _email: https://docs.github.com/en/github/setting-up-and-managing-your-github-user-account/setting-your-commit-email-address
.. _Fork: https://github.com/pallets/flask/fork
.. _Clone: https://docs.github.com/en/github/getting-started-with-github/fork-a-repo#step-2-create-a-local-clone-of-your-fork
.. _start coding:
Start coding
~~~~~~~~~~~~
- Create a branch to identify the issue you would like to work on. If you're
submitting a bug or documentation fix, branch off of the latest ".x" branch.
.. code-block:: text
$ git fetch origin
$ git checkout -b your-branch-name origin/2.0.x
If you're submitting a feature addition or change, branch off of the "main" branch.
.. code-block:: text
$ git fetch origin
$ git checkout -b your-branch-name origin/main
- Using your favorite editor, make your changes, `committing as you go`_.
- If you are in a codespace, you will be prompted to `create a fork`_ the first
time you make a commit. Enter ``Y`` to continue.
- Include tests that cover any code changes you make. Make sure the test fails without
your patch. Run the tests as described below.
- Push your commits to your fork on GitHub and `create a pull request`_. Link to the
issue being addressed with ``fixes #123`` in the pull request description.
.. code-block:: text
$ git push --set-upstream origin your-branch-name
.. _committing as you go: https://afraid-to-commit.readthedocs.io/en/latest/git/commandlinegit.html#commit-your-changes
.. _create a fork: https://docs.github.com/en/codespaces/developing-in-codespaces/using-source-control-in-your-codespace#about-automatic-forking
.. _create a pull request: https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request
.. _Running the tests:
Running the tests
~~~~~~~~~~~~~~~~~
Run the basic test suite with pytest.
.. code-block:: text
$ pytest
This runs the tests for the current environment, which is usually
sufficient. CI will run the full suite when you submit your pull
request. You can run the full test suite with tox if you don't want to
wait.
.. code-block:: text
$ tox
Running test coverage
~~~~~~~~~~~~~~~~~~~~~
Generating a report of lines that do not have test coverage can indicate
where to start contributing. Run ``pytest`` using ``coverage`` and
generate a report.
If you are using GitHub Codespaces, ``coverage`` is already installed
so you can skip the installation command.
.. code-block:: text
$ pip install coverage
$ coverage run -m pytest
$ coverage html
Open ``htmlcov/index.html`` in your browser to explore the report.
Read more about `coverage <https://coverage.readthedocs.io>`__.
Building the docs
~~~~~~~~~~~~~~~~~
Build the docs in the ``docs`` directory using Sphinx.
.. code-block:: text
$ cd docs
$ make html
Open ``_build/html/index.html`` in your browser to view the docs.
Read more about `Sphinx <https://www.sphinx-doc.org/en/stable/>`__.
#
# This file is autogenerated by pip-compile with Python 3.13
# by the following command:
#
# pip-compile build.in
#
build==1.2.2.post1
# via -r build.in
packaging==24.2
# via build
pyproject-hooks==1.2.0
# via build
-r docs.txt
-r tests.txt
-r typing.txt
pre-commit
tox
#
# This file is autogenerated by pip-compile with Python 3.13
# by the following command:
#
# pip-compile dev.in
#
alabaster==1.0.0
# via
# -r /Users/david/Projects/flask/requirements/docs.txt
# sphinx
asgiref==3.8.1
# via
# -r /Users/david/Projects/flask/requirements/tests.txt
# -r /Users/david/Projects/flask/requirements/typing.txt
babel==2.16.0
# via
# -r /Users/david/Projects/flask/requirements/docs.txt
# sphinx
cachetools==5.5.0
# via tox
certifi==2024.8.30
# via
# -r /Users/david/Projects/flask/requirements/docs.txt
# requests
cffi==1.17.1
# via
# -r /Users/david/Projects/flask/requirements/typing.txt
# cryptography
cfgv==3.4.0
# via pre-commit
chardet==5.2.0
# via tox
charset-normalizer==3.4.0
# via
# -r /Users/david/Projects/flask/requirements/docs.txt
# requests
colorama==0.4.6
# via tox
cryptography==43.0.3
# via -r /Users/david/Projects/flask/requirements/typing.txt
distlib==0.3.9
# via virtualenv
docutils==0.21.2
# via
# -r /Users/david/Projects/flask/requirements/docs.txt
# sphinx
# sphinx-tabs
filelock==3.16.1
# via
# tox
# virtualenv
identify==2.6.2
# via pre-commit
idna==3.10
# via
# -r /Users/david/Projects/flask/requirements/docs.txt
# requests
imagesize==1.4.1
# via
# -r /Users/david/Projects/flask/requirements/docs.txt
# sphinx
iniconfig==2.0.0
# via
# -r /Users/david/Projects/flask/requirements/tests.txt
# -r /Users/david/Projects/flask/requirements/typing.txt
# pytest
jinja2==3.1.4
# via
# -r /Users/david/Projects/flask/requirements/docs.txt
# sphinx
markupsafe==3.0.2
# via
# -r /Users/david/Projects/flask/requirements/docs.txt
# jinja2
mypy==1.13.0
# via -r /Users/david/Projects/flask/requirements/typing.txt
mypy-extensions==1.0.0
# via
# -r /Users/david/Projects/flask/requirements/typing.txt
# mypy
nodeenv==1.9.1
# via
# -r /Users/david/Projects/flask/requirements/typing.txt
# pre-commit
# pyright
packaging==24.2
# via
# -r /Users/david/Projects/flask/requirements/docs.txt
# -r /Users/david/Projects/flask/requirements/tests.txt
# -r /Users/david/Projects/flask/requirements/typing.txt
# pallets-sphinx-themes
# pyproject-api
# pytest
# sphinx
# tox
pallets-sphinx-themes==2.3.0
# via -r /Users/david/Projects/flask/requirements/docs.txt
platformdirs==4.3.6
# via
# tox
# virtualenv
pluggy==1.5.0
# via
# -r /Users/david/Projects/flask/requirements/tests.txt
# -r /Users/david/Projects/flask/requirements/typing.txt
# pytest
# tox
pre-commit==4.0.1
# via -r dev.in
pycparser==2.22
# via
# -r /Users/david/Projects/flask/requirements/typing.txt
# cffi
pygments==2.18.0
# via
# -r /Users/david/Projects/flask/requirements/docs.txt
# sphinx
# sphinx-tabs
pyproject-api==1.8.0
# via tox
pyright==1.1.389
# via -r /Users/david/Projects/flask/requirements/typing.txt
pytest==8.3.3
# via
# -r /Users/david/Projects/flask/requirements/tests.txt
# -r /Users/david/Projects/flask/requirements/typing.txt
python-dotenv==1.0.1
# via
# -r /Users/david/Projects/flask/requirements/tests.txt
# -r /Users/david/Projects/flask/requirements/typing.txt
pyyaml==6.0.2
# via pre-commit
requests==2.32.3
# via
# -r /Users/david/Projects/flask/requirements/docs.txt
# sphinx
snowballstemmer==2.2.0
# via
# -r /Users/david/Projects/flask/requirements/docs.txt
# sphinx
sphinx==8.1.3
# via
# -r /Users/david/Projects/flask/requirements/docs.txt
# pallets-sphinx-themes
# sphinx-notfound-page
# sphinx-tabs
# sphinxcontrib-log-cabinet
sphinx-notfound-page==1.0.4
# via
# -r /Users/david/Projects/flask/requirements/docs.txt
# pallets-sphinx-themes
sphinx-tabs==3.4.7
# via -r /Users/david/Projects/flask/requirements/docs.txt
sphinxcontrib-applehelp==2.0.0
# via
# -r /Users/david/Projects/flask/requirements/docs.txt
# sphinx
sphinxcontrib-devhelp==2.0.0
# via
# -r /Users/david/Projects/flask/requirements/docs.txt
# sphinx
sphinxcontrib-htmlhelp==2.1.0
# via
# -r /Users/david/Projects/flask/requirements/docs.txt
# sphinx
sphinxcontrib-jsmath==1.0.1
# via
# -r /Users/david/Projects/flask/requirements/docs.txt
# sphinx
sphinxcontrib-log-cabinet==1.0.1
# via -r /Users/david/Projects/flask/requirements/docs.txt
sphinxcontrib-qthelp==2.0.0
# via
# -r /Users/david/Projects/flask/requirements/docs.txt
# sphinx
sphinxcontrib-serializinghtml==2.0.0
# via
# -r /Users/david/Projects/flask/requirements/docs.txt
# sphinx
tox==4.23.2
# via -r dev.in
types-contextvars==2.4.7.3
# via -r /Users/david/Projects/flask/requirements/typing.txt
types-dataclasses==0.6.6
# via -r /Users/david/Projects/flask/requirements/typing.txt
typing-extensions==4.12.2
# via
# -r /Users/david/Projects/flask/requirements/typing.txt
# mypy
# pyright
urllib3==2.2.3
# via
# -r /Users/david/Projects/flask/requirements/docs.txt
# requests
virtualenv==20.27.1
# via
# pre-commit
# tox
pallets-sphinx-themes
sphinx
sphinxcontrib-log-cabinet
sphinx-tabs
#
# This file is autogenerated by pip-compile with Python 3.13
# by the following command:
#
# pip-compile docs.in
#
alabaster==1.0.0
# via sphinx
babel==2.16.0
# via sphinx
certifi==2024.8.30
# via requests
charset-normalizer==3.4.0
# via requests
docutils==0.21.2
# via
# sphinx
# sphinx-tabs
idna==3.10
# via requests
imagesize==1.4.1
# via sphinx
jinja2==3.1.4
# via sphinx
markupsafe==3.0.2
# via jinja2
packaging==24.2
# via
# pallets-sphinx-themes
# sphinx
pallets-sphinx-themes==2.3.0
# via -r docs.in
pygments==2.18.0
# via
# sphinx
# sphinx-tabs
requests==2.32.3
# via sphinx
snowballstemmer==2.2.0
# via sphinx
sphinx==8.1.3
# via
# -r docs.in
# pallets-sphinx-themes
# sphinx-notfound-page
# sphinx-tabs
# sphinxcontrib-log-cabinet
sphinx-notfound-page==1.0.4
# via pallets-sphinx-themes
sphinx-tabs==3.4.7
# via -r docs.in
sphinxcontrib-applehelp==2.0.0
# via sphinx
sphinxcontrib-devhelp==2.0.0
# via sphinx
sphinxcontrib-htmlhelp==2.1.0
# via sphinx
sphinxcontrib-jsmath==1.0.1
# via sphinx
sphinxcontrib-log-cabinet==1.0.1
# via -r docs.in
sphinxcontrib-qthelp==2.0.0
# via sphinx
sphinxcontrib-serializinghtml==2.0.0
# via sphinx
urllib3==2.2.3
# via requests
https://github.com/pallets/werkzeug/archive/refs/heads/main.tar.gz
https://github.com/pallets/jinja/archive/refs/heads/main.tar.gz
https://github.com/pallets/markupsafe/archive/refs/heads/main.tar.gz
https://github.com/pallets/itsdangerous/archive/refs/heads/main.tar.gz
https://github.com/pallets/click/archive/refs/heads/main.tar.gz
https://github.com/pallets-eco/blinker/archive/refs/heads/main.tar.gz
werkzeug==3.1.0
jinja2==3.1.2
markupsafe==2.1.1
itsdangerous==2.2.0
click==8.1.3
blinker==1.9.0
#
# This file is autogenerated by pip-compile with Python 3.13
# by the following command:
#
# pip-compile tests-min.in
#
blinker==1.9.0
# via -r tests-min.in
click==8.1.3
# via -r tests-min.in
itsdangerous==2.2.0
# via -r tests-min.in
jinja2==3.1.2
# via -r tests-min.in
markupsafe==2.1.1
# via
# -r tests-min.in
# jinja2
# werkzeug
werkzeug==3.1.0
# via -r tests-min.in
pytest
asgiref
greenlet ; python_version < "3.11"
python-dotenv
#
# This file is autogenerated by pip-compile with Python 3.13
# by the following command:
#
# pip-compile tests.in
#
asgiref==3.8.1
# via -r tests.in
iniconfig==2.0.0
# via pytest
packaging==24.2
# via pytest
pluggy==1.5.0
# via pytest
pytest==8.3.3
# via -r tests.in
python-dotenv==1.0.1
# via -r tests.in
mypy
pyright
pytest
types-contextvars
types-dataclasses
asgiref
cryptography
python-dotenv
#
# This file is autogenerated by pip-compile with Python 3.13
# by the following command:
#
# pip-compile typing.in
#
asgiref==3.8.1
# via -r typing.in
cffi==1.17.1
# via cryptography
cryptography==43.0.3
# via -r typing.in
iniconfig==2.0.0
# via pytest
mypy==1.13.0
# via -r typing.in
mypy-extensions==1.0.0
# via mypy
nodeenv==1.9.1
# via pyright
packaging==24.2
# via pytest
pluggy==1.5.0
# via pytest
pycparser==2.22
# via cffi
pyright==1.1.389
# via -r typing.in
pytest==8.3.3
# via -r typing.in
python-dotenv==1.0.1
# via -r typing.in
types-contextvars==2.4.7.3
# via -r typing.in
types-dataclasses==0.6.6
# via -r typing.in
typing-extensions==4.12.2
# via
# mypy
# pyright
[tox]
envlist =
py3{13,12,11,10,9}
pypy310
py313-min
py39-dev
style
typing
docs
skip_missing_interpreters = true
[testenv]
package = wheel
wheel_build_env = .pkg
envtmpdir = {toxworkdir}/tmp/{envname}
constrain_package_deps = true
use_frozen_constraints = true
deps =
-r requirements/tests.txt
min: -r requirements/tests-min.txt
dev: -r requirements/tests-dev.txt
commands = pytest -v --tb=short --basetemp={envtmpdir} {posargs}
[testenv:style]
deps = pre-commit
skip_install = true
commands = pre-commit run --all-files
[testenv:typing]
deps = -r requirements/typing.txt
commands =
mypy
pyright
[testenv:docs]
deps = -r requirements/docs.txt
commands = sphinx-build -E -W -b dirhtml docs docs/_build/dirhtml
[testenv:update-actions]
labels = update
deps = gha-update
skip_install = true
commands = gha-update
[testenv:update-pre_commit]
labels = update
deps = pre-commit
skip_install = true
commands = pre-commit autoupdate -j4
[testenv:update-requirements]
labels = update
deps = pip-tools
skip_install = true
change_dir = requirements
commands =
pip-compile build.in -q {posargs:-U}
pip-compile docs.in -q {posargs:-U}
pip-compile tests.in -q {posargs:-U}
pip-compile tests-min.in -q
pip-compile typing.in -q {posargs:-U}
pip-compile dev.in -q {posargs:-U}

Sorry, the diff of this file is too big to display