Add ARCHITECTURE.rst and module docstrings (#1368)

* Add ARCHITECTURE.rst and module docstrings

* fix flake8

Co-authored-by: Henning Jacobs <henning@zalando.de>
This commit is contained in:
Robbe Sneyders
2021-07-09 17:49:54 +02:00
committed by GitHub
parent 594ded9a05
commit 2066503c5c
48 changed files with 311 additions and 9 deletions

74
ARCHITECTURE.rst Normal file
View File

@@ -0,0 +1,74 @@
Architecture
============
This document describes the high-level architecture of Connexion.
.. image:: docs/images/architecture.png
:width: 800
:align: center
:alt: Connexion architecture
Apps
----
A Connexion ``App`` or application wraps a specific framework application (currently Flask or
AioHttp) and exposes a standardized interface for users to create and configure their Connexion
application.
While a Connexion app implements the WSGI interface, it only acts ass a pass-through and doesn't
actually intercept requests and responses. Connexion does all request and response manipulation
by wrapping the user view function in a Connexion ``Operation``. The underlying framework
application handles incoming requests and routes them to the correct Connexion ``Operation``.
Api
---
A connexion ``API`` takes in an OpenAPI specification and translates the operations defined in it to
a set of Connexion ``Operations``. This set of operations is implemented as a framework blueprint
(A `Flask blueprint`_ or framework-specific equivalent), which can be registered on the framework
application.
For each operation, the ``API`` resolves the user view function to link to the operation, wraps it
with a Connexion ``Operation`` which it configures based on the OpenAPI spec, and finally adds it as
a route on the framework blueprint.
When the ``API`` is registered on the Connexion ``APP``, the underlying framework blueprint is
registered on the framework app.
Operations
----------
A Connexion ``Operation`` implements an OpenAPI operation (`swagger 2`_, `OpenAPI 3`_), which
describes a single API operation on a path. It wraps the view function linked to the operation with
decorators to handle security, validation, serialization etc. based on the OpenAPI specification,
and exposes the result to be registered as a route on the application.
These decorators intercept incoming requests and outgoing responses of the operation and allow
Connexion to manipulate them while leaving the routing up to the underlying framework. The split
into separate decorators allows for a clean layered implementation of Connexion functionality.
The result is equivalent to the following user code, but instead Connexion implements this
automatically based on the OpenAPI spec.
.. code-block:: python
@request_response_lifecycle
@secure_endpoint
@validate_inputs
@deserialize_function_inputs
@serialize_function_outputs
@validate_outputs
def user_provided_view_function():
...
Connexion requests and responses
--------------------------------
Connexion defines a request and response interface for internal use. The outermost decorator of
the operation casts framework specific requests to ``ConnexionRequests`` and ``ConnexionResponses``
to framework specific responses.
.. _Flask blueprint: https://flask.palletsprojects.com/en/2.0.x/blueprints/
.. _swagger 2: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#operation-object
.. _OpenAPI 3: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.0.md#operationObject

View File

@@ -568,6 +568,9 @@ Contributing to Connexion/TODOs
We welcome your ideas, issues, and pull requests. Just follow the
usual/standard GitHub practices.
You can find out more about how Connexion works and where to apply your changes by having a look
at our `ARCHITECTURE.rst <ARCHITECTURE.rst>`_.
Unless you explicitly state otherwise in advance, any non trivial
contribution intentionally submitted for inclusion in this project by you
to the steward of this repository (Zalando SE, Berlin) shall be under the

View File

@@ -1,3 +1,12 @@
"""
Connexion is a framework that automagically handles HTTP requests based on OpenAPI Specification
(formerly known as Swagger Spec) of your API described in YAML format. Connexion allows you to
write an OpenAPI specification, then maps the endpoints to your Python functions; this makes it
unique, as many tools generate the specification based on your Python code. You can describe your
REST API in as much detail as you want; then Connexion guarantees that it will work as you
specified.
"""
import sys
import werkzeug.exceptions as exceptions # NOQA

View File

@@ -1,3 +1,7 @@
"""
This module provides an entrypoint for Connexion's CLI.
"""
from connexion.cli import main # pragma: no cover
main() # pragma: no cover

View File

@@ -1 +1,16 @@
"""
This module defines Connexion APIs. A connexion API takes in an OpenAPI specification and
translates the operations defined in it to a set of Connexion Operations. This set of operations
is implemented as a framework blueprint (A Flask blueprint or framework-specific equivalent),
which can be registered on the framework application.
For each operation, the API resolves the user view function to link to the operation, wraps it
with a Connexion Operation which it configures based on the OpenAPI spec, and finally adds it as
a route on the framework blueprint.
When the API is registered on the Connexion APP, the underlying framework blueprint is registered
on the framework app.
"""
from .abstract import AbstractAPI # NOQA

View File

@@ -1,3 +1,7 @@
"""
This module defines an AbstractAPI, which defines a standardized interface for a Connexion API.
"""
import abc
import logging
import pathlib

View File

@@ -1,3 +1,8 @@
"""
This module defines an AioHttp Connexion API which implements translations between AioHttp and
Connexion requests / responses.
"""
import asyncio
import logging
import re

View File

@@ -1,3 +1,8 @@
"""
This module defines a Flask Connexion API which implements translations between Flask and
Connexion requests / responses.
"""
import logging
import warnings
from typing import Any

View File

@@ -1,3 +1,7 @@
"""
This module defines utility functions related to the Flask framework.
"""
import functools
import random
import re

View File

@@ -1 +1,6 @@
"""
This module defines Connexion applications. A Connexion App wraps a specific framework application
and exposes a standardized interface for users to create and configure their Connexion application.
"""
from .abstract import AbstractApp # NOQA

View File

@@ -1,3 +1,8 @@
"""
This module defines an AbstractApp, which defines a standardized user interface for a Connexion
application.
"""
import abc
import logging
import pathlib

View File

@@ -1,3 +1,7 @@
"""
This module defines an AioHttpApp, a Connexion application to wrap an AioHttp application.
"""
import logging
import os.path
import pkgutil

View File

@@ -1,3 +1,7 @@
"""
This module defines a FlaskApp, a Connexion application to wrap a Flask application.
"""
import datetime
import logging
import pathlib

View File

@@ -1,3 +1,8 @@
"""
This module defines a command-line interface (CLI) that runs an OpenAPI specification to be a
starting point for developing your API with Connexion.
"""
import logging
import sys
from os import path

View File

@@ -0,0 +1,3 @@
"""
This module defines decorators which Connexion uses to wrap user provided view functions.
"""

View File

@@ -1,3 +1,8 @@
"""
This module defines a BaseDecorator to wrap a user view function and a RequestResponseDecorator
which manages the lifecycle of a request internally in Connexion.
"""
import asyncio
import functools
import logging

View File

@@ -1,3 +1,8 @@
"""
This module defines view function decorator to collect UWSGI metrics and expose them via an
endpoint.
"""
import functools
import os
import time

View File

@@ -1,3 +1,7 @@
"""
This module defines a decorator to convert request parameters to arguments for the view function.
"""
import builtins
import functools
import inspect

View File

@@ -1,4 +1,7 @@
# Decorators to change the return type of endpoints
"""
This module defines decorators to change the return type of a view function.
"""
import functools
import logging

View File

@@ -1,4 +1,7 @@
# Decorators to change the return type of endpoints
"""
This module defines a view function decorator to validate its responses.
"""
import asyncio
import functools
import logging

View File

@@ -1,4 +1,7 @@
# Decorators to split query and path parameters
"""
This module defines view function decorators to split query and path parameters.
"""
import abc
import functools
import json

View File

@@ -1,3 +1,7 @@
"""
This module defines view function decorators to validate request and response parameters and bodies.
"""
import collections
import copy
import functools

View File

@@ -1,3 +1,7 @@
"""
This module defines Exception classes used by Connexion to generate a proper response.
"""
import warnings
from jsonschema.exceptions import ValidationError
@@ -14,7 +18,7 @@ class ProblemException(ConnexionException):
def __init__(self, status=400, title=None, detail=None, type=None,
instance=None, headers=None, ext=None):
"""
This exception is holds arguments that are going to be passed to the
This exception holds arguments that are going to be passed to the
`connexion.problem` function to generate a proper response.
"""
self.status = status

View File

@@ -1,3 +1,7 @@
"""
This module defines error handlers, operations that produce proper response problems.
"""
import logging
from .exceptions import AuthenticationProblem, ResolverProblem

View File

@@ -1,3 +1,7 @@
"""
This module contains definitions of the HTTP protocol.
"""
FORM_CONTENT_TYPES = [
'application/x-www-form-urlencoded',
'multipart/form-data'

View File

@@ -1,3 +1,7 @@
"""
Module containing all code related to json schema validation.
"""
from collections.abc import Mapping
from copy import deepcopy

View File

@@ -1,9 +1,22 @@
"""
This module centralizes all functionality related to json encoding and decoding in Connexion.
"""
import datetime
import json
import uuid
class JSONEncoder(json.JSONEncoder):
"""The default Connexion JSON encoder. Handles extra types compared to the
built-in :class:`json.JSONEncoder`.
- :class:`datetime.datetime` and :class:`datetime.date` are
serialized to :rfc:`822` strings. This is the same as the HTTP
date format.
- :class:`uuid.UUID` is serialized to a string.
"""
def default(self, o):
if isinstance(o, datetime.datetime):
if o.tzinfo:
@@ -25,7 +38,7 @@ class JSONEncoder(json.JSONEncoder):
class Jsonifier:
"""
Used to serialized and deserialize to/from JSon
Central point to serialize and deserialize to/from JSon in Connexion.
"""
def __init__(self, json_=json, **kwargs):
"""

View File

@@ -1,4 +1,11 @@
"""
This module defines interfaces for requests and responses used in Connexion for authentication,
validation, serialization, etc.
"""
class ConnexionRequest:
"""Connexion interface for a request."""
def __init__(self,
url,
method,
@@ -27,6 +34,7 @@ class ConnexionRequest:
class ConnexionResponse:
"""Connexion interface for a response."""
def __init__(self,
status_code=200,
mimetype=None,

View File

@@ -1,3 +1,7 @@
"""
This module contains a mock resolver that returns mock functions for operations it cannot resolve.
"""
import functools
import logging

View File

@@ -1,3 +1,11 @@
"""
This module defines Connexion Operation classes. A Connexion Operation implements an OpenAPI
operation, which describes a single API operation on a path. It wraps the view function linked to
the operation with decorators to handle security, validation, serialization etc. based on the
OpenAPI specification, and exposes the result to be registered as a route on the application.
"""
from .abstract import AbstractOperation # noqa
from .openapi import OpenAPIOperation # noqa
from .secure import SecureOperation # noqa

View File

@@ -1,3 +1,8 @@
"""
This module defines an AbstractOperation class which implements an abstract Operation interface
and functionality shared between Swagger 2 and OpenAPI 3 specifications.
"""
import abc
import logging

View File

@@ -1,3 +1,5 @@
# This is a dummy module for backwards compatibility with < v2.0
"""
This is a dummy module for backwards compatibility with < v2.0.
"""
from .secure import * # noqa
from .swagger2 import * # noqa

View File

@@ -1,3 +1,7 @@
"""
This module defines an OpenAPIOperation class, a Connexion operation specific for OpenAPI 3 specs.
"""
import logging
from copy import copy, deepcopy

View File

@@ -1,3 +1,7 @@
"""
This module defines a SecureOperation class, which implements the security handler for an operation.
"""
import functools
import logging

View File

@@ -1,3 +1,7 @@
"""
This module defines a Swagger2Operation class, a Connexion operation specific for Swagger 2 specs.
"""
import logging
from copy import deepcopy

View File

@@ -1,3 +1,7 @@
"""
This module defines a Connexion specific options class to pass to the Connexion App or API.
"""
import logging
import pathlib
from typing import Optional # NOQA
@@ -19,6 +23,7 @@ logger = logging.getLogger("connexion.options")
class ConnexionOptions:
"""Class holding connexion specific options."""
def __init__(self, options=None, oas_version=(2,)):
self._options = {}

View File

@@ -1,3 +1,9 @@
"""
This module contains a Python interface for Problem Details for HTTP APIs
<https://tools.ietf.org/html/draft-ietf-appsawg-http-problem-00>, which is a standardized format
to communicate distinct "problem types" to non-human consumers.
"""
from .lifecycle import ConnexionResponse

View File

@@ -1,3 +1,8 @@
"""
This module contains resolvers, functions that resolves the user defined view functions
from the operations defined in the OpenAPI spec.
"""
import logging
import sys

View File

@@ -1,4 +1,9 @@
"""isort:skip_file"""
"""
This module defines SecurityHandlerFactories which support the creation of security
handlers for operations.
isort:skip_file
"""
# abstract
from .async_security_handler_factory import AbstractAsyncSecurityHandlerFactory # NOQA

View File

@@ -1,3 +1,7 @@
"""
This module defines an aiohttp-specific SecurityHandlerFactory.
"""
import logging
import aiohttp

View File

@@ -1,3 +1,8 @@
"""
This module defines an abstract asynchronous SecurityHandlerFactory which supports the creation of
asynchronous security handlers for coroutine operations.
"""
import abc
import asyncio
import functools

View File

@@ -1,3 +1,7 @@
"""
This module defines a Flask-specific SecurityHandlerFactory.
"""
import requests
from .security_handler_factory import AbstractSecurityHandlerFactory

View File

@@ -1,3 +1,8 @@
"""
This module defines an abstract SecurityHandlerFactory which supports the creation of security
handlers for operations.
"""
import abc
import base64
import functools
@@ -46,6 +51,12 @@ class AbstractSecurityHandlerFactory(abc.ABC):
return default
def get_tokeninfo_func(self, security_definition: dict) -> t.Optional[t.Callable]:
"""
:type security_definition: dict
>>> get_tokeninfo_url({'x-tokenInfoFunc': 'foo.bar'})
'<function foo.bar>'
"""
token_info_func = self._get_function(security_definition, "x-tokenInfoFunc", 'TOKENINFO_FUNC')
if token_info_func:
return token_info_func

View File

@@ -1,3 +1,7 @@
"""
This module defines Python interfaces for OpenAPI specifications.
"""
import abc
import copy
import pathlib
@@ -155,6 +159,8 @@ class Specification(Mapping):
class Swagger2Specification(Specification):
"""Python interface for a Swagger 2 specification."""
yaml_name = 'swagger.yaml'
operation_cls = Swagger2Operation
@@ -210,6 +216,8 @@ class Swagger2Specification(Specification):
class OpenAPISpecification(Specification):
"""Python interface for an OpenAPI 3 specification."""
yaml_name = 'openapi.yaml'
operation_cls = OpenAPIOperation

View File

@@ -1,3 +1,7 @@
"""
This module provides general utility functions used within Connexion.
"""
import asyncio
import functools
import importlib
@@ -6,7 +10,7 @@ import yaml
def boolean(s):
'''
"""
Convert JSON/Swagger boolean value to Python, raise ValueError otherwise
>>> boolean('true')
@@ -14,7 +18,7 @@ def boolean(s):
>>> boolean('false')
False
'''
"""
if isinstance(s, bool):
return s
elif not hasattr(s, 'lower'):

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 MiB

View File

@@ -1,6 +1,7 @@
[flake8]
max-line-length=170
exclude=connexion/__init__.py
rst-roles=class
[tox]
envlist =