mirror of
https://github.com/LukeHagar/connexion.git
synced 2025-12-06 04:19:26 +00:00
(One was enountered manually, the other found via Sphinx's builtin linkcheck builder, which also confirms there aren't really any others.) I often suggest using Sphinx's [`default_role`](https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-default_role) setting to make writing docs quite a bit less noisy in a fairly uncontroversial way. A toxenv / docs setup in CI also seems like a decent idea. As is, there is a small part of the docs which isn't being rendered because it contains errors (in the output below it's the one `CRITICAL`), and there are some other interlinks which are broken. Essentially, IMHO, running Sphinx without `-n -T -W` is a recipe for brokenness unfortunately. This is what one sees when doing so, even after this PR: <details> ``` /Users/julian/Development/connexion/docs/request.rst:194: CRITICAL: Unexpected section title. Form data /Users/julian/Development/connexion/connexion/lifecycle.py:docstring of connexion.lifecycle.ConnexionRequest.from_starlette_request:1: WARNING: py:class reference target not found: starlette.requests.Request /Users/julian/Development/connexion/connexion/operations/openapi.py:docstring of connexion.operations.openapi.OpenAPIOperation:1: WARNING: py:class reference target not found: integer /Users/julian/Development/connexion/connexion/operations/openapi.py:docstring of connexion.operations.openapi.OpenAPIOperation:1: WARNING: py:class reference target not found: AbstractURIParser /Users/julian/Development/connexion/connexion/operations/openapi.py:docstring of connexion.operations.OpenAPIOperation.function:1: WARNING: py:class reference target not found: types.FunctionType /Users/julian/Development/connexion/connexion/operations/swagger2.py:docstring of connexion.operations.swagger2.Swagger2Operation:1: WARNING: py:class reference target not found: integer /Users/julian/Development/connexion/connexion/operations/swagger2.py:docstring of connexion.operations.swagger2.Swagger2Operation:1: WARNING: py:class reference target not found: AbstractURIParser /Users/julian/Development/connexion/connexion/operations/swagger2.py:docstring of connexion.operations.Swagger2Operation.function:1: WARNING: py:class reference target not found: types.FunctionType /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp.add_error_handler:1: WARNING: py:class reference target not found: connexion.lifecycle.ConnexionResponse /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp.add_error_handler:1: WARNING: py:class reference target not found: connexion.lifecycle.ConnexionResponse /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp.add_error_handler:1: WARNING: py:class reference target not found: connexion.lifecycle.ConnexionResponse /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp.add_error_handler:1: WARNING: py:class reference target not found: connexion.lifecycle.ConnexionResponse /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware.add_error_handler:1: WARNING: py:class reference target not found: connexion.lifecycle.ConnexionResponse /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware.add_error_handler:1: WARNING: py:class reference target not found: connexion.lifecycle.ConnexionResponse /Users/julian/Development/connexion/connexion/problem.py:docstring of connexion.problem.problem:14: WARNING: py:class reference target not found: type: str /Users/julian/Development/connexion/connexion/problem.py:docstring of connexion.problem.problem:1: WARNING: py:class reference target not found: ConnexionResponse /Users/julian/Development/connexion/connexion/exceptions.py:docstring of connexion.exceptions:1: WARNING: py:class reference target not found: jsonschema.exceptions.ValidationError /Users/julian/Development/connexion/connexion/exceptions.py:docstring of connexion.exceptions:1: WARNING: py:class reference target not found: starlette.exceptions.HTTPException /Users/julian/Development/connexion/connexion/exceptions.py:docstring of connexion.exceptions:1: WARNING: py:class reference target not found: starlette.exceptions.HTTPException /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp.add_wsgi_middleware:1: WARNING: py:class reference target not found: types.TracebackType /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.MiddlewarePosition:1: WARNING: py:class reference target not found: ExceptionMiddleware /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.MiddlewarePosition:1: WARNING: py:class reference target not found: SwaggerUIMiddleware /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.MiddlewarePosition:1: WARNING: py:class reference target not found: RoutingMiddleware /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.MiddlewarePosition:1: WARNING: py:class reference target not found: SecurityMiddleware /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.MiddlewarePosition:1: WARNING: py:class reference target not found: RequestValidationMiddleware /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.MiddlewarePosition:1: WARNING: py:class reference target not found: ContextMiddleware /Users/julian/Development/connexion/docs/middleware.rst:121: WARNING: py:class reference target not found: SecurityMiddleware /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:1: WARNING: py:class reference target not found: pathlib.Path /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:1: WARNING: py:class reference target not found: connexion.jsonifier.Jsonifier /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:1: WARNING: py:class reference target not found: connexion.uri_parsing.AbstractURIParser /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:3: WARNING: py:obj reference target not found: middleware.main.ConnexionMiddleware.default_middlewares /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:21: WARNING: py:class reference target not found: options.ConnexionOptions /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:23: WARNING: py:mod reference target not found: uri_parsing /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:26: WARNING: py:obj reference target not found: validators.VALIDATOR_MAP /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:28: WARNING: py:obj reference target not found: security.SECURITY_HANDLERS /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:1: WARNING: py:class reference target not found: pathlib.Path /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:1: WARNING: py:class reference target not found: connexion.jsonifier.Jsonifier /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:1: WARNING: py:class reference target not found: connexion.uri_parsing.AbstractURIParser /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:2: WARNING: py:obj reference target not found: middleware.main.ConnexionMiddleware.default_middlewares /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:12: WARNING: py:class reference target not found: options.ConnexionOptions /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:23: WARNING: py:class reference target not found: options.ConnexionOptions /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:25: WARNING: py:mod reference target not found: uri_parsing /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:28: WARNING: py:obj reference target not found: validators.VALIDATOR_MAP /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:30: WARNING: py:obj reference target not found: security.SECURITY_HANDLERS /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:1: WARNING: py:class reference target not found: pathlib.Path /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:1: WARNING: py:class reference target not found: connexion.jsonifier.Jsonifier /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:1: WARNING: py:class reference target not found: connexion.uri_parsing.AbstractURIParser /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:1: WARNING: py:obj reference target not found: middleware.main.ConnexionmMiddleware.default_middlewares /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:19: WARNING: py:class reference target not found: options.ConnexionOptions /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:21: WARNING: py:mod reference target not found: uri_parsing /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:24: WARNING: py:obj reference target not found: validators.VALIDATOR_MAP /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:26: WARNING: py:obj reference target not found: security.SECURITY_HANDLERS /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:1: WARNING: py:class reference target not found: pathlib.Path /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:1: WARNING: py:class reference target not found: connexion.jsonifier.Jsonifier /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:1: WARNING: py:class reference target not found: connexion.uri_parsing.AbstractURIParser /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:3: WARNING: py:obj reference target not found: middleware.main.ConnexionMiddleware.default_middlewares /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:21: WARNING: py:class reference target not found: options.ConnexionOptions /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:23: WARNING: py:mod reference target not found: uri_parsing /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:26: WARNING: py:obj reference target not found: validators.VALIDATOR_MAP /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:28: WARNING: py:obj reference target not found: security.SECURITY_HANDLERS /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:1: WARNING: py:class reference target not found: pathlib.Path /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:1: WARNING: py:class reference target not found: connexion.jsonifier.Jsonifier /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:1: WARNING: py:class reference target not found: connexion.uri_parsing.AbstractURIParser /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:2: WARNING: py:obj reference target not found: middleware.main.ConnexionMiddleware.default_middlewares /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:12: WARNING: py:class reference target not found: options.ConnexionOptions /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:23: WARNING: py:class reference target not found: options.ConnexionOptions /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:25: WARNING: py:mod reference target not found: uri_parsing /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:28: WARNING: py:obj reference target not found: validators.VALIDATOR_MAP /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:30: WARNING: py:obj reference target not found: security.SECURITY_HANDLERS /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:1: WARNING: py:class reference target not found: pathlib.Path /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:1: WARNING: py:class reference target not found: connexion.jsonifier.Jsonifier /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:1: WARNING: py:class reference target not found: connexion.uri_parsing.AbstractURIParser /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:1: WARNING: py:obj reference target not found: middleware.main.ConnexionmMiddleware.default_middlewares /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:19: WARNING: py:class reference target not found: options.ConnexionOptions /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:21: WARNING: py:mod reference target not found: uri_parsing /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:24: WARNING: py:obj reference target not found: validators.VALIDATOR_MAP /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:26: WARNING: py:obj reference target not found: security.SECURITY_HANDLERS /Users/julian/Development/connexion/connexion/apps/abstract.py:docstring of connexion.apps.abstract.AbstractApp.add_api:1: WARNING: py:class reference target not found: pathlib.Path /Users/julian/Development/connexion/connexion/apps/abstract.py:docstring of connexion.apps.abstract.AbstractApp.add_api:1: WARNING: py:class reference target not found: connexion.jsonifier.Jsonifier /Users/julian/Development/connexion/connexion/apps/abstract.py:docstring of connexion.apps.abstract.AbstractApp.add_api:1: WARNING: py:class reference target not found: connexion.uri_parsing.AbstractURIParser /Users/julian/Development/connexion/connexion/apps/abstract.py:docstring of connexion.apps.abstract.AbstractApp.add_api:11: WARNING: py:class reference target not found: resolver.Resolver /Users/julian/Development/connexion/connexion/apps/abstract.py:docstring of connexion.apps.abstract.AbstractApp.add_api:18: WARNING: py:class reference target not found: options.ConnexionOptions /Users/julian/Development/connexion/connexion/apps/abstract.py:docstring of connexion.apps.abstract.AbstractApp.add_api:20: WARNING: py:mod reference target not found: uri_parsing /Users/julian/Development/connexion/connexion/apps/abstract.py:docstring of connexion.apps.abstract.AbstractApp.add_api:23: WARNING: py:obj reference target not found: validators.VALIDATOR_MAP /Users/julian/Development/connexion/connexion/apps/abstract.py:docstring of connexion.apps.abstract.AbstractApp.add_api:25: WARNING: py:obj reference target not found: security.SECURITY_HANDLERS /Users/julian/Development/connexion/connexion/apps/abstract.py:docstring of connexion.apps.abstract.AbstractApp.add_api:1: WARNING: py:class reference target not found: pathlib.Path /Users/julian/Development/connexion/connexion/apps/abstract.py:docstring of connexion.apps.abstract.AbstractApp.add_api:1: WARNING: py:class reference target not found: connexion.jsonifier.Jsonifier /Users/julian/Development/connexion/connexion/apps/abstract.py:docstring of connexion.apps.abstract.AbstractApp.add_api:1: WARNING: py:class reference target not found: connexion.uri_parsing.AbstractURIParser /Users/julian/Development/connexion/connexion/apps/abstract.py:docstring of connexion.apps.abstract.AbstractApp.add_api:11: WARNING: py:class reference target not found: resolver.Resolver /Users/julian/Development/connexion/connexion/apps/abstract.py:docstring of connexion.apps.abstract.AbstractApp.add_api:18: WARNING: py:class reference target not found: options.ConnexionOptions /Users/julian/Development/connexion/connexion/apps/abstract.py:docstring of connexion.apps.abstract.AbstractApp.add_api:20: WARNING: py:mod reference target not found: uri_parsing /Users/julian/Development/connexion/connexion/apps/abstract.py:docstring of connexion.apps.abstract.AbstractApp.add_api:23: WARNING: py:obj reference target not found: validators.VALIDATOR_MAP /Users/julian/Development/connexion/connexion/apps/abstract.py:docstring of connexion.apps.abstract.AbstractApp.add_api:25: WARNING: py:obj reference target not found: security.SECURITY_HANDLERS /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware.add_api:1: WARNING: py:class reference target not found: pathlib.Path /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware.add_api:1: WARNING: py:class reference target not found: connexion.jsonifier.Jsonifier /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware.add_api:1: WARNING: py:class reference target not found: connexion.uri_parsing.AbstractURIParser /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware.add_api:11: WARNING: py:class reference target not found: resolver.Resolver /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware.add_api:18: WARNING: py:class reference target not found: options.ConnexionOptions /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware.add_api:20: WARNING: py:mod reference target not found: uri_parsing /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware.add_api:23: WARNING: py:obj reference target not found: validators.VALIDATOR_MAP /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware.add_api:25: WARNING: py:obj reference target not found: security.SECURITY_HANDLERS /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:1: WARNING: py:class reference target not found: pathlib.Path /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:1: WARNING: py:class reference target not found: connexion.jsonifier.Jsonifier /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:1: WARNING: py:class reference target not found: connexion.uri_parsing.AbstractURIParser /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:4: WARNING: py:obj reference target not found: middleware.main.ConnexionMiddleware.default_middlewares /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:22: WARNING: py:class reference target not found: options.ConnexionOptions /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:24: WARNING: py:mod reference target not found: uri_parsing /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:27: WARNING: py:obj reference target not found: validators.VALIDATOR_MAP /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:29: WARNING: py:obj reference target not found: security.SECURITY_HANDLERS /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.abstract.AbstractApp.add_api:1: WARNING: py:class reference target not found: pathlib.Path /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.abstract.AbstractApp.add_api:1: WARNING: py:class reference target not found: connexion.jsonifier.Jsonifier /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.abstract.AbstractApp.add_api:1: WARNING: py:class reference target not found: connexion.uri_parsing.AbstractURIParser /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:18: WARNING: py:class reference target not found: options.ConnexionOptions /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:20: WARNING: py:mod reference target not found: uri_parsing /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:23: WARNING: py:obj reference target not found: validators.VALIDATOR_MAP /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp:25: WARNING: py:obj reference target not found: security.SECURITY_HANDLERS /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp.add_error_handler:1: WARNING: py:class reference target not found: connexion.lifecycle.ConnexionResponse /Users/julian/Development/connexion/connexion/apps/asynchronous.py:docstring of connexion.apps.asynchronous.AsyncApp.add_error_handler:1: WARNING: py:class reference target not found: connexion.lifecycle.ConnexionResponse /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:1: WARNING: py:class reference target not found: pathlib.Path /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:1: WARNING: py:class reference target not found: connexion.jsonifier.Jsonifier /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:1: WARNING: py:class reference target not found: connexion.uri_parsing.AbstractURIParser /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:3: WARNING: py:obj reference target not found: middleware.main.ConnexionMiddleware.default_middlewares /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:13: WARNING: py:class reference target not found: options.ConnexionOptions /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:24: WARNING: py:class reference target not found: options.ConnexionOptions /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:26: WARNING: py:mod reference target not found: uri_parsing /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:29: WARNING: py:obj reference target not found: validators.VALIDATOR_MAP /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:31: WARNING: py:obj reference target not found: security.SECURITY_HANDLERS /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.abstract.AbstractApp.add_api:1: WARNING: py:class reference target not found: pathlib.Path /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.abstract.AbstractApp.add_api:1: WARNING: py:class reference target not found: connexion.jsonifier.Jsonifier /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.abstract.AbstractApp.add_api:1: WARNING: py:class reference target not found: connexion.uri_parsing.AbstractURIParser /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:18: WARNING: py:class reference target not found: options.ConnexionOptions /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:20: WARNING: py:mod reference target not found: uri_parsing /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:23: WARNING: py:obj reference target not found: validators.VALIDATOR_MAP /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp:25: WARNING: py:obj reference target not found: security.SECURITY_HANDLERS /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp.add_error_handler:1: WARNING: py:class reference target not found: connexion.lifecycle.ConnexionResponse /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp.add_error_handler:1: WARNING: py:class reference target not found: connexion.lifecycle.ConnexionResponse /Users/julian/Development/connexion/connexion/apps/flask.py:docstring of connexion.apps.flask.FlaskApp.add_wsgi_middleware:1: WARNING: py:class reference target not found: types.TracebackType /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:1: WARNING: py:class reference target not found: pathlib.Path /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:1: WARNING: py:class reference target not found: connexion.jsonifier.Jsonifier /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:1: WARNING: py:class reference target not found: connexion.uri_parsing.AbstractURIParser /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:2: WARNING: py:obj reference target not found: middleware.main.ConnexionmMiddleware.default_middlewares /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:20: WARNING: py:class reference target not found: options.ConnexionOptions /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:22: WARNING: py:mod reference target not found: uri_parsing /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:25: WARNING: py:obj reference target not found: validators.VALIDATOR_MAP /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:27: WARNING: py:obj reference target not found: security.SECURITY_HANDLERS /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware.add_api:1: WARNING: py:class reference target not found: pathlib.Path /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware.add_api:1: WARNING: py:class reference target not found: connexion.jsonifier.Jsonifier /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware.add_api:1: WARNING: py:class reference target not found: connexion.uri_parsing.AbstractURIParser /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:18: WARNING: py:class reference target not found: options.ConnexionOptions /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:20: WARNING: py:mod reference target not found: uri_parsing /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:23: WARNING: py:obj reference target not found: validators.VALIDATOR_MAP /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware:25: WARNING: py:obj reference target not found: security.SECURITY_HANDLERS /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware.add_error_handler:1: WARNING: py:class reference target not found: connexion.lifecycle.ConnexionResponse /Users/julian/Development/connexion/connexion/middleware/main.py:docstring of connexion.middleware.main.ConnexionMiddleware.add_error_handler:1: WARNING: py:class reference target not found: connexion.lifecycle.ConnexionResponse /Users/julian/Development/connexion/connexion/lifecycle.py:docstring of connexion.lifecycle.ConnexionRequest.from_starlette_request:1: WARNING: py:class reference target not found: starlette.requests.Request /Users/julian/Development/connexion/connexion/resolver.py:docstring of connexion.resolver.RelativeResolver:1: WARNING: py:class reference target not found: types.ModuleType /Users/julian/Development/connexion/connexion/resolver.py:docstring of connexion.resolver.RelativeResolver:1: WARNING: py:class reference target not found: types.FunctionType /Users/julian/Development/connexion/docs/testing.rst:29: WARNING: py:class reference target not found: TestContext /Users/julian/Development/connexion/connexion/problem.py:docstring of connexion.problem.problem:14: WARNING: py:class reference target not found: type: str /Users/julian/Development/connexion/connexion/problem.py:docstring of connexion.problem.problem:1: WARNING: py:class reference target not found: ConnexionResponse /Users/julian/Development/connexion/docs/exceptions.rst:1: WARNING: broken link: about:blank () /Users/julian/Development/connexion/docs/context.rst:1: WARNING: broken link: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#componentsObject (Anchor 'componentsObject' not found) /Users/julian/Development/connexion/docs/v3.rst:105: WARNING: broken link: https://github.com/abersheeran/a2wsgi#convert-asgi-app-to-wsgi-app (Anchor 'convert-asgi-app-to-wsgi-app' not found) /Users/julian/Development/connexion/docs/context.rst:1: WARNING: broken link: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#security-definitions-object (Anchor 'security-definitions-object' not found) /Users/julian/Development/connexion/docs/context.rst:1: WARNING: broken link: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#definitionsObject (Anchor 'definitionsObject' not found) docs: exit 1 (5.40 seconds) /Users/julian/Development/connexion> .tox/docs/bin/python -m sphinx -n -T -q -b linkcheck docs /Users/julian/Development/connexion/.tox/docs/tmp/build pid=35935 .pkg: _exit> python /Users/julian/.dotfiles/.local/share/virtualenvs/tox/lib/python3.12/site-packages/pyproject_api/_backend.py True poetry.core.masonry.api docs: FAIL code 1 (7.91=setup[1.96]+cmd[0.55,5.40] seconds) evaluation failed :( (7.95 seconds) ``` </details> I'm trying to actually use connexion for the first time, but if the above sounds reasonable to y'all maintainers I can try to come back to it and send a PR later.
323 lines
11 KiB
ReStructuredText
323 lines
11 KiB
ReStructuredText
Connexion 3.0: API-first for all
|
|
================================
|
|
|
|
**We are excited to announce the release of Connexion 3.0!** 🎉
|
|
|
|
Connexion 3 fundamentally changes how Connexion is designed and implemented, and how it
|
|
fits into the wider Python API ecosystem. We adopted the ASGI interface, which makes Connexion both
|
|
modular and well-integrated with most modern Python API tooling.
|
|
|
|
**It brings some major changes compared to 2.X:**
|
|
|
|
* The improved ``App`` and new ``AsyncApp`` allow you to use Connexion as a stand-alone framework
|
|
|
|
* The ``App`` interface was extended so you no longer have to care about the framework used
|
|
underneath
|
|
|
|
* Connexion can now be used as middleware to supercharge any ASGI or WSGI-compatible framework
|
|
with its spec-based functionality
|
|
* Connexion is now pluggable in many dimensions:
|
|
|
|
* All Connexion functionality is pluggable by adding or removing middleware from its stack
|
|
* Validation is now pluggable by content type, solving longstanding issues regarding endpoints
|
|
with multiple content types and making it easy to add validation for additional content types
|
|
* Authentication is now pluggable by security scheme, making it easy to customize the behavior or
|
|
add support for additional security schemes.
|
|
|
|
* Aiohttp support has been dropped due to lack of ASGI support
|
|
* We spent a lot of effort on extending and improving `our documentation`_
|
|
|
|
**Read on below to discover more changes.** 👇
|
|
|
|
Or read our `in-depth blog post`_ on the redesign.
|
|
|
|
.. _in-depth blog post: https://medium.com/@robbe.sneyders/a5dc17e81ff8?source=friends_link&sk=de5a7a67ccae8a03752f5e8e1dc68d48
|
|
.. _our documentation: https://connexion.readthedocs.io/en/stable/
|
|
|
|
Getting started with Connexion 3
|
|
--------------------------------
|
|
|
|
If you're getting started with Connexion 3 for a new project, follow the
|
|
:doc:`quickstart <quickstart>`. All documentation has been updated for Connexion 3.
|
|
|
|
Migrating from Connexion 2
|
|
--------------------------
|
|
|
|
The rest of this page will focus on how to migrate from Connexion 2 to Connexion 3.
|
|
|
|
This page will show examples migrating the ``connexion.FlaskApp``. However all Connexion 3 examples
|
|
should work for ``connexion.AsyncApp`` as well. If you are not relying on the underlying
|
|
Flask application, or you are coming from the old ``AiohttpApp``, we recommend migrating to the
|
|
``connexion.AsyncApp`` instead.
|
|
|
|
Running the application
|
|
'''''''''''''''''''''''
|
|
|
|
There have been 2 changes related to running the application:
|
|
|
|
- You now MUST run the Connexion application instead of the underlying Flask application.
|
|
- You should use an ASGI server instead of a WSGI server.
|
|
|
|
While the following would work on Connexion 2, it no longer works on Connexion 3:
|
|
|
|
.. code-block:: python
|
|
:caption: **hello.py**
|
|
|
|
import connexion
|
|
|
|
app = connexion.App(__name__)
|
|
flask_app = app.app
|
|
|
|
if __name__ == "__main__":
|
|
flask_app.run()
|
|
|
|
.. code-block:: bash
|
|
|
|
$ flask --app hello:flask_app
|
|
|
|
.. code-block:: bash
|
|
|
|
$ gunicorn hello:flask_app
|
|
|
|
|
|
Instead, you need to run the Connexion application using an ASGI server:
|
|
|
|
.. code-block:: python
|
|
:caption: **hello.py**
|
|
|
|
import connexion
|
|
|
|
app = connexion.App(__name__)
|
|
|
|
if __name__ == "__main__":
|
|
app.run()
|
|
|
|
.. code-block:: bash
|
|
|
|
$ uvicorn run:app
|
|
|
|
.. code-block:: bash
|
|
|
|
$ gunicorn -k uvicorn.workers.UvicornWorker run:app
|
|
|
|
.. warning::
|
|
|
|
You can wrap Connexion with the `ASGIMiddleware`_ offered by `a2wsgi`_ to run it with a WSGI
|
|
server. You will however lose the benefits offered by ASGI, and performance might be
|
|
impacted. You should only use this as a temporary workaround until you can switch to an ASGI
|
|
server.
|
|
|
|
For more information, check :ref:`Running your application <quickstart:Running your application>`.
|
|
|
|
.. _ASGIMiddleware: https://github.com/abersheeran/a2wsgi#convert-asgi-app-to-wsgi-app
|
|
.. _a2wsgi: https://github.com/abersheeran/a2wsgi
|
|
|
|
**Workers and threads**
|
|
|
|
You can still use workers as before, however you should not use threads with ASGI, since it
|
|
handles concurrency using an async event loop instead.
|
|
|
|
In the ``AsyncApp``, concurrency is completely handled by the async event loop.
|
|
|
|
The ``FlaskApp`` is more complex, since the underlying Flask app is WSGI instead of ASGI.
|
|
Concurrency in the middleware stack is handled by the async event loop, but once a request is
|
|
passed to the underlying Flask app, it is executed in a thread pool (of 10 workers) automatically.
|
|
|
|
Error handlers
|
|
``````````````
|
|
|
|
There have been 2 changes related to running the application:
|
|
|
|
- The interface of the error handlers changed, with a request now being injected as well
|
|
- The error handlers now should be registered on the Connexion App, not the underlying Flask App
|
|
|
|
Connexion 2:
|
|
|
|
.. code-block:: python
|
|
:caption: **hello.py**
|
|
|
|
import connexion
|
|
|
|
def not_found_handler(exc: Exception) -> flask.Response:
|
|
...
|
|
|
|
app = connexion.App(__name__)
|
|
flask_app = app.app
|
|
|
|
app.add_error_handler(404, not_found_handler) # either
|
|
flask_app.register_error_handler(404, not_found_handler) # or
|
|
|
|
Connexion 3:
|
|
|
|
.. code-block:: python
|
|
:caption: **hello.py**
|
|
|
|
import connexion
|
|
from connexion.lifecycle import ConnexionRequest, ConnexionResponse
|
|
|
|
def not_found_handler(request: ConnexionRequest, exc: Exception) -> ConnexionResponse:
|
|
...
|
|
|
|
app = connexion.App(__name__)
|
|
app.add_error_handler(404, not_found_handler)
|
|
|
|
You can easily generate Connexion responses adhering to the `Problem Details for HTTP APIs`_
|
|
standard by using the ``connexion.problem.problem`` module:
|
|
|
|
.. code-block:: python
|
|
|
|
from connexion.problem import problem
|
|
|
|
def not_found_handler(request: ConnexionRequest, exc: Exception) -> ConnexionResponse:
|
|
return problem(
|
|
title=http_facts.HTTP_STATUS_CODES.get(404),
|
|
detail="The resource was not found",
|
|
status=404,
|
|
)
|
|
|
|
|
|
.. dropdown:: View a detailed reference of the ``connexion.problem.problem`` function
|
|
:icon: eye
|
|
|
|
.. autofunction:: connexion.problem.problem
|
|
:noindex:
|
|
|
|
For more information, check the :doc:`exceptions` documentation.
|
|
|
|
.. _Problem Details for HTTP APIs: https://datatracker.ietf.org/doc/html/rfc7807
|
|
|
|
Flask extensions and WSGI middleware
|
|
````````````````````````````````````
|
|
|
|
Certain Flask extensions and WSGI middleware might no longer work, since some functionaity was
|
|
moved outside the scope of the Flask application. Extensions and middleware impacting the
|
|
following functionality should now be implemented as ASGI middleware instead:
|
|
|
|
- Exception handling
|
|
- Swagger UI
|
|
- Routing
|
|
- Security
|
|
- Validation
|
|
|
|
One such example is CORS support, since it impacts routing. It can no longer be added via the
|
|
``Flask-Cors`` extension. See :ref:`Connexion Cookbook: CORS <cookbook:CORS>` on how to use a
|
|
``CORSMiddleware`` instead.
|
|
|
|
See :doc:`middleware` for general documentation on ASGI middleware.
|
|
|
|
Custom validators
|
|
`````````````````
|
|
|
|
Validation is now pluggable by content type, which means that the `VALIDATOR_MAP` has been updated
|
|
to accommodate this.
|
|
|
|
You can use the ``connexion.datastructures.MediaTypeDict`` to support content type ranges.
|
|
|
|
.. code-block:: python
|
|
|
|
VALIDATOR_MAP = {
|
|
"parameter": ParameterValidator,
|
|
"body": MediaTypeDict(
|
|
{
|
|
"*/*json": JSONRequestBodyValidator,
|
|
"application/x-www-form-urlencoded": FormDataValidator,
|
|
"multipart/form-data": MultiPartFormDataValidator,
|
|
}
|
|
),
|
|
"response": MediaTypeDict(
|
|
{
|
|
"*/*json": JSONResponseBodyValidator,
|
|
"text/plain": TextResponseBodyValidator,
|
|
}
|
|
),
|
|
}
|
|
|
|
You can pass it either to the app, or when registering an API.
|
|
|
|
.. code-block:: python
|
|
|
|
app = connexion.App(__name__, validator_map=VALIDATOR_MAP)
|
|
app.add_api("openapi.yaml", validator_map=VALIDATOR_MAP)
|
|
|
|
An ``AbstractRequestBodyValidator`` and ``AbstractResponseBodyValidator`` class are available to
|
|
support the creation of custom validators.
|
|
|
|
Swagger UI Options
|
|
------------------
|
|
|
|
The ``options`` argument has been renamed to ``swagger_ui_options`` and now takes an instance
|
|
of the :class:`.SwaggerUIOptions`. The naming of the options themselves have been changed to
|
|
better represent their meaning.
|
|
|
|
.. code-block:: python
|
|
|
|
import connexion
|
|
from connexion.options import SwaggerUIOptions
|
|
|
|
swagger_ui_options = SwaggerUIOptions(
|
|
swagger_ui=True,
|
|
swagger_ui_path="docs",
|
|
)
|
|
|
|
app = connexion.FlaskApp(__name__, swagger_ui_options=swagger_ui_options) # either
|
|
app.add_api("openapi.yaml", swagger_ui_options=swagger_ui_options) # or
|
|
|
|
See :doc:`swagger_ui` for more information.
|
|
|
|
Smaller breaking changes
|
|
------------------------
|
|
|
|
* The ``uri_parser_class`` is now passed to the ``App`` or its ``add_api()`` method directly
|
|
instead of via the ``options`` argument.
|
|
* The ``jsonifier`` is now passed to the ``App`` or its ``add_api()`` method instead of setting it
|
|
as an attribute on the Api.
|
|
* Drop Flask 1.X support and support Flask 2.X async routes
|
|
* Drop Python 3.6 (and add Python 3.10) support
|
|
* ``connexion.request`` is now a Starlette ``Request`` instead of a Flask ``Request``
|
|
* Route priority changed. The most specific route should now be defined first in the specification.
|
|
* We no longer guess a content type for response serialization if multiple are defined in the spec.
|
|
We do take into account returned headers.
|
|
* Don't return 400 when read-only property is received
|
|
* Content type is now validated for requests and responses if defined in the spec
|
|
* The deprecated positions for ``x-body-name`` are no longer supported
|
|
* The parameter ``pass_context_arg_name`` has been removed. Context is now available as global
|
|
request-level context, or can be passed in by defining a ``context_`` parameter in your view function.
|
|
* The ``MethodViewResolver`` has been renamed to ``MethodResolver``, and a new ``MethodViewResolver``
|
|
has been added to work with Flask's ``MethodView`` specifically.
|
|
* Built-in support for uWSGI has been removed. You can re-add this functionality using a custom middleware.
|
|
* The request body is now passed through for ``GET``, ``HEAD``, ``DELETE``, ``CONNECT`` and ``OPTIONS`` methods as well.
|
|
* The signature of error handlers has changed and default Flask error handlers are now replaced
|
|
with default Connexion error handlers which work the same for ``AsyncApp`` and
|
|
``ConnexionMiddleware``.
|
|
|
|
|
|
Non-breaking changes
|
|
--------------------
|
|
|
|
* Relative and nested refs are now supported in OpenAPI / Swagger specifications
|
|
* The ``required`` keyword is now supported for requestBodies
|
|
* HTTP exceptions are now implemented as a hierarchy
|
|
* Connexion now exposes ``context``, ``operation``, ``receive``, ``scope`` as global request-level context
|
|
* Connexion now provides a ``DefaultsJSONRequestBodyValidator`` to fill in default values in received
|
|
request bodies.
|
|
|
|
Full changelog
|
|
--------------
|
|
|
|
Consult our `Github release page`_ for an overview of all changes.
|
|
|
|
.. _Github release page: https://github.com/spec-first/connexion/releases/tag/3.0.0
|
|
|
|
Feedback
|
|
--------
|
|
|
|
We would really love to hear from you, so let us know if you have any feedback or questions. We'd
|
|
like to make the migration for our users as easy and possible.
|
|
|
|
* For questions, comments, and feedback, please comment on the `discussion`_ which will be
|
|
created and pinned after the release.
|
|
* For issues, please open an issue on our `Github tracker`_
|
|
|
|
.. _discussion: https://github.com/spec-first/connexion/discussions
|
|
.. _Github tracker: https://github.com/spec-first/connexion/issues
|