webutil

Common utilities and handler code for Python web apps.
- Install with
pip install webutil - Supports Python 3.9+
- Documentation
webutil is dedicated to the public domain. You may also use it under the CC0 public domain dedication.
Contents
flask_util: Flask decorators and handlers for caching, exception handling, regular expression URL routing, domain-wide redirects, rate limiting, headers, and serving XRD and JRD templates.logs: Flask request handler that collects full trace logs from Google Cloud Logging, formats them nicely, and serves themmodels: minor utility Model classes for the Google Cloud Datastore ndb librarytestutil: misc utilities and helpers for unittest, requests, and urllibutil: wide variety of utilities for data structures, web code, etc.webmention: Webmention endpoint discovery and sending
Changelog
3.0 - 2026-10-14
Breaking changes:
util:- Remove
if_changed. pretty_link: only linkhttpandhttpsURLs. For other URLs, return just the link text.
- Remove
Non-breaking changes:
flask_util:- Add
bool_paramfor getting boolean query params/form arguments. - Add
csp_reporthandler for loggingContent-Security-Policyviolation reports. MODERN_HEADERS: tightenContent-Security-Policysignificantly.
- Add
models:- Fix missing import in
Cache.get/Cache.put.
- Fix missing import in
testutil:- Add
assert_html_equals, which compares HTML strings and ignores insignificant whitespace and attribute order. requests_response: back the returned response with aurllib3.HTTPResponseinstead of a bareBytesIO, so thatresp.raw.stream()works for code that streams responses.
- Add
util:requests_*: addcachekwarg, an opt-in Flask-request-local cache of GET/HEAD responses and exceptions, keyed on method, URL, andAcceptheader.encode: fixencodingkwarg, it was ignored for nested values and always used UTF-8.is_connection_failure: makeprawcoreimport optional.linkify,tokenize_links: fix duplicated trailing punctuation after a link, eghttp://foo.com/a)..becamehttp://foo.com/a)......clean_url: fix query params with escaped delimiters, eg?a=b%26clost the%26c. The query string was unescaped before it was parsed.maybe_iso8601_to_rfc3339: return non-string inputs unchanged instead of raisingAttributeError.pretty_link: HTML-escape the URL inhrefand theattrsvalues.to_utc_timestamp: fix timezone aware datetimes, they were read as wall clock time and their UTC offset was ignored.trim_nulls: addkeep_empty_values_inkwarg.
2.0 - 2026-06-29
appengine_info:- Add Cloud Run support.
flask_util:- Add
block, abefore_requesthandler that blocks requests by client IP CIDR and/orUser-Agent.
- Add
models:- Add new
WriteOnce,WriteOnceBlobPropertyndb property classes. (Moved here from arroba.) - Add support for
$ENCRYPTED_PROPERTY_KEYenvironment variable.
- Add new
testutil:- Add new
@head_returns_200decorator. - Drop
moxfromTestCase. - Add new
unittest.mockandrequestshelpers toTestCase.
- Add new
util:requests_*: add newlog_databoolean kwarg.
1.0 - 2026-05-27
Initial PyPI release. Moved out of oauth-dropins, where it's been maintained for the last 10+ years, into its own dedicated package, pywebutil.
Release instructions
Here's how to package, test, and ship a new release.
- Pull from remote to make sure we're at head.
git checkout main git pull
- Run the unit tests.
source .venv/bin/activate.csh gcloud emulators firestore start --host-port=:8089 --database-mode=datastore-mode < /dev/null >& /dev/null & python -m unittest discover python -m unittest webutil/tests/hypothesis/*.py
- Bump the version number in
pyproject.tomlanddocs/conf.py.git grepthe old version number to make sure it only appears in the changelog. Change the current changelog entry inREADME.mdfor this new version from unreleased to the current date. - Build the docs. If you added any new modules, add them to the appropriate file(s) in
docs/source/. Then run./docs/build.sh. -
setenv ver X.Y git commit -am "release v$ver"
- Upload to test.pypi.org for testing.
uv build twine upload -r pypitest dist/pywebutil-$ver.tar.gz dist/pywebutil-$ver-py3-none-any.whl
- Install from test.pypi.org.
cd /tmp python3 -m venv .venv source .venv/bin/activate.csh pip3 install -i https://test.pypi.org/simple --extra-index-url https://pypi.org/simple pywebutil
- Smoke test that the code trivially loads and runs.
python # run test code belowTest code to paste into the interpreter:from webutil import util util.__file__ util.UrlCanonicalizer()('http://asdf.com') # should print 'https://asdf.com/' exit()
- Tag the release in git. In the tag message editor, delete the generated comments at bottom, leave the first line blank (to omit the release "title" in github), put
### Notable changeson the second line, then copy and paste this version's changelog contents below it.git tag -a v$ver --cleanup=verbatim git push git push --tags
- Click here to draft a new release on GitHub. Enter
vX.Yin the Tag version box. Leave Release title empty. Copy### Notable changesand the changelog contents into the description text box. - Upload to pypi.org!
twine upload dist/pywebutil-$ver-* dist/pywebutil-$ver.*
Metadata
Release files for pywebutil 3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| pywebutil-3.0.tar.gz | 66.0 kB | Without provenance | Details for pywebutil-3.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pywebutil-3.0-py3-none-any.whl | Python 3 | none | any | Details for pywebutil-3.0-py3-none-any.whl |
Total release size: 128.5 kB
Release files / pywebutil-3.0.tar.gz
| Download URL | pywebutil-3.0.tar.gz |
|---|---|
| Size | 66.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
73994d2e01695a8b5b9dfd86c46bc1d42669cc57048d13cff47cdacb98046bb6
|
|
BLAKE2b-256 checksum How to use checksums |
05184dc898e68f9c09aab0cd73ba038b74db04a9da6a27bb8a0a3c9d9d4dc8cf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / pywebutil-3.0-py3-none-any.whl
| Download URL | pywebutil-3.0-py3-none-any.whl |
|---|---|
| Size | 62.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9ad7586538928ae6f5b1e960d2c4e3c4b1b989f34dd352a83f2d00c2b477410a
|
|
BLAKE2b-256 checksum How to use checksums |
88fab4a58b2da3ea8b4cbcc79a679d45c0fe13156674fb10f6ab3c34a7db0972
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Security for pywebutil 3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.