Skip to content
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
3 changes: 1 addition & 2 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,10 @@ jobs:
fail-fast: false
matrix:
python-version:
- "3.9"
- "3.10"
- "3.11"
- "3.12"
- "3.13"
- "3.14"
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
Expand Down
8 changes: 4 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
---
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
rev: v6.0.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: 'v0.5.0'
rev: 'v0.15.12'
hooks:
- id: ruff
- repo: https://github.com/pycqa/flake8
rev: 7.1.0
rev: 7.3.0
hooks:
- id: flake8
- repo: https://github.com/Lucas-C/pre-commit-hooks-markup
Expand All @@ -29,7 +29,7 @@ repos:
- id: pylint
language: system
- repo: https://github.com/pre-commit/mirrors-mypy
rev: 'v1.10.1' # Use the sha / tag you want to point at
rev: 'v1.20.2' # Use the sha / tag you want to point at
hooks:
- id: mypy
args: [--explicit-package-bases]
Expand Down
9 changes: 9 additions & 0 deletions doc/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
==== 2.8.0.dev ====
* Fix I/O operation on closed file/buffer error in Response classes (#21)
* Validate route filter definitions to reject spaces with clear error
messages (#25)
* Bad PATH_INFO encoding exception handling (#37, #38)
* Updated openapi3.py example to openapi-core 0.23+ API (Spec replaced
by OpenAPI)
* Drop Python 3.9 and 3.10 support, require Python >= 3.11

==== 2.7.0 ====
* Reserved Request.db attribute for usage
* Right HTTPException type annotation
Expand Down
23 changes: 14 additions & 9 deletions examples/openapi3.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@
import logging as log
import json

from openapi_core import (
Spec,
unmarshal_request, unmarshal_response,
)
from openapi_core import OpenAPI

from openapi_core.exceptions import OpenAPIError
from openapi_core.templating.paths.exceptions import PathNotFound, \
Expand Down Expand Up @@ -56,7 +53,7 @@

with open(path.join(path.dirname(__file__), "openapi.json"),
"r", encoding="utf-8") as openapi:
app.openapi_spec = Spec.from_dict(json.load(openapi)) # type: ignore
app.openapi_spec = OpenAPI.from_dict(json.load(openapi)) # type: ignore


@app.before_response()
Expand Down Expand Up @@ -86,7 +83,8 @@ def before_each_response(req):
"""Checks the API before processing each response."""
req.api = OpenAPIRequest(req)
try:
unmarshal_request(req.api, app.openapi_spec)
result = app.openapi_spec.unmarshal_request(req.api)
result.raise_for_errors()
except (OperationNotFound, PathNotFound) as error:
log.debug("%s", error)
return # not found
Expand All @@ -105,10 +103,10 @@ def after_each_response(req, res):
if not hasattr(req, "api"):
req.api = OpenAPIRequest(req)
try:
unmarshal_response(
result = app.openapi_spec.unmarshal_response(
req.api,
OpenAPIResponse(res),
app.openapi_spec)
OpenAPIResponse(res))
result.raise_for_errors()
except (OperationNotFound, PathNotFound):
return res
except OpenAPIError as error:
Expand Down Expand Up @@ -170,6 +168,13 @@ def ajax_uuid(req, arg):
return json.dumps({"arg": str(arg)}), "application/json"


@app.route("/arg/<arg>")
def ajax_arg_fallback(req, arg):
"""Catch-all for /arg/{arg} - OpenAPI validation handles invalid types."""
assert req
return json.dumps({"arg": arg}), "application/json"


@app.route('/internal-server-error')
def method_raises_errror(req):
"""Internal server error test."""
Expand Down
4 changes: 2 additions & 2 deletions examples/simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
import uwsgi # type: ignore

except ModuleNotFoundError:
uwsgi = None # pylint: disable=invalid-name
uwsgi = None # type: ignore[assignment] # pylint: disable=invalid-name

logger = log.getLogger()
logger.setLevel("DEBUG")
Expand Down Expand Up @@ -275,7 +275,7 @@ def style(_):
@app.route('/test/<variable:int>')
@app.route('/test/<variable:uuid>')
@app.route('/test/static')
def test_dynamic(req, variable=None):
def test_dynamic(req, variable=None): # noqa: PT028
"""Tests dynamic values."""
if not variable and req.headers.get('ETag') == 'W/"0123"':
return not_modified(req)
Expand Down
4 changes: 2 additions & 2 deletions poorwsgi/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
import warnings

__author__ = "Ondrej Tuma (McBig) <mcbig@zeropage.cz>"
__date__ = "14 Oct 2024"
__date__ = "1 May 2026"
# PEP 0386 -- Version Identification and Dependency Specification
__version__ = "2.7.0"
__version__ = "2.8.0.dev"

DECLINED = 0

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ def doc():
"Topic :: Internet :: WWW/HTTP :: WSGI :: Middleware",
"Topic :: Software Development :: Libraries :: Python Modules"
],
python_requires=">=3.8",
python_requires=">=3.11",
cmdclass={
'build_doc': BuildDoc,
'clean_doc': CleanDoc,
Expand Down
4 changes: 2 additions & 2 deletions tests_integrity/openapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from email.message import Message
from urllib.parse import parse_qs, urlparse

from openapi_core import Spec # type: ignore
from openapi_core import OpenAPI # type: ignore
from openapi_core.validation.request.datatypes import ( # type: ignore
RequestParameters)

Expand Down Expand Up @@ -83,7 +83,7 @@ def headers(self):
def response_spec_json(filename):
"""Initializes a response_validator for openapi.json."""
with open(filename, "r", encoding="utf-8") as openapi:
return Spec.from_dict(json.load(openapi))
return OpenAPI.from_dict(json.load(openapi))


__all__ = ["OpenAPIRequest", "OpenAPIResponse", "response_spec_json"]
7 changes: 3 additions & 4 deletions tests_integrity/support.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

from requests import Request, Session
from requests.exceptions import RequestException
from openapi_core import unmarshal_response
from openapi_core.contrib.requests import (RequestsOpenAPIRequest,
RequestsOpenAPIResponse)
from openapi_core.exceptions import OpenAPIError
Expand Down Expand Up @@ -95,10 +94,10 @@ def check_api(url, method="GET", status_code=200,
status_code = [status_code]
assert response.status_code in status_code
try:
unmarshal_response(
result = response_spec.unmarshal_response(
RequestsOpenAPIRequest(request),
RequestsOpenAPIResponse(response),
response_spec)
RequestsOpenAPIResponse(response))
result.raise_for_errors()
except PathNotFound:
if response.status_code == 404:
return response
Expand Down
2 changes: 2 additions & 0 deletions tests_integrity/test_response_closed.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ def url(request):
class TestResponseClosed:
"""Test for Response with closed buffer handling."""

# pylint: disable=no-self-use

def test_simple_response(self, url):
"""Test that a simple response works normally."""
check_url(url+"/test")
Expand Down
Loading