Skip to content
This repository has been archived by the owner on Jul 19, 2021. It is now read-only.

Add ARCHITECTURE.rst and module docstrings #6

Closed
wants to merge 1 commit into from
Closed
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
73 changes: 73 additions & 0 deletions ARCHITECTURE.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
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`_, 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/
.. _OpenAPI operation: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#operation-object
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps provide a link to both swagger 2 and OpenAPI 3 operation objects to make it clear both versions are supported?

https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.0.md#operationObject

9 changes: 9 additions & 0 deletions connexion/__init__.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down
4 changes: 4 additions & 0 deletions connexion/__main__.py
Original file line number Diff line number Diff line change
@@ -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
15 changes: 15 additions & 0 deletions connexion/apis/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,16 @@
"""
This module defines an Connexion APIs. A connexion API takes in an OpenAPI specification and
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: "an Connexion APIs."

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
4 changes: 4 additions & 0 deletions connexion/apis/abstract.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
This module defines an AbstractAPI, which defines a standardized interface for a Connexion API.
"""

import abc
import logging
import pathlib
Expand Down
5 changes: 5 additions & 0 deletions connexion/apis/aiohttp_api.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down
5 changes: 5 additions & 0 deletions connexion/apis/flask_api.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
"""
This module defines a Flask Connexion API which implements translations between Flask and
Connexion requests / responses.
"""

import logging
import warnings

Expand Down
4 changes: 4 additions & 0 deletions connexion/apis/flask_utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
This module defines utility functions related to the Flask framework.
"""

import functools
import random
import re
Expand Down
5 changes: 5 additions & 0 deletions connexion/apps/__init__.py
Original file line number Diff line number Diff line change
@@ -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
5 changes: 5 additions & 0 deletions connexion/apps/abstract.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down
4 changes: 4 additions & 0 deletions connexion/apps/aiohttp_app.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
This module defines an AioHttpApp, a Connexion application to wrap an AioHttp application.
"""

import logging
import os.path
import pkgutil
Expand Down
4 changes: 4 additions & 0 deletions connexion/apps/flask_app.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
This module defines a FlaskApp, a Connexion application to wrap an AioHttp application.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"to wrap a Flask application"

"""

import datetime
import logging
import pathlib
Expand Down
5 changes: 5 additions & 0 deletions connexion/cli.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down
3 changes: 3 additions & 0 deletions connexion/decorators/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""
This module defines decorators which Connexion uses to wrap user provided view functions.
"""
4 changes: 4 additions & 0 deletions connexion/decorators/coroutine_wrappers.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
This module defines view function decorators specifically for coroutine operations.
"""

import asyncio
import functools

Expand Down
5 changes: 5 additions & 0 deletions connexion/decorators/decorator.py
Original file line number Diff line number Diff line change
@@ -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 functools
import logging

Expand Down
5 changes: 5 additions & 0 deletions connexion/decorators/metrics.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down
4 changes: 4 additions & 0 deletions connexion/decorators/parameter.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
This module defines a decorator to convert request parameters to arguments for the view function.
"""

import functools
import inspect
import logging
Expand Down
5 changes: 4 additions & 1 deletion connexion/decorators/produces.py
Original file line number Diff line number Diff line change
@@ -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

Expand Down
5 changes: 4 additions & 1 deletion connexion/decorators/response.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# Decorators to change the return type of endpoints
"""
This module defines an view function decorator to validate its responses.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"an view function" --> "a view function"

"""

import functools
import logging

Expand Down
5 changes: 4 additions & 1 deletion connexion/decorators/uri_parsing.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down
4 changes: 4 additions & 0 deletions connexion/decorators/validation.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
This module defines view function decorators to validate request and response parameters and bodies.
"""

import collections
import copy
import functools
Expand Down
8 changes: 6 additions & 2 deletions connexion/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
This module defines Exception classes used by Connexion to generate a proper response.
"""

import warnings

from jsonschema.exceptions import ValidationError
Expand All @@ -14,8 +18,8 @@ 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
`connexion.problem` function to generate a propert response.
This exception holds arguments that are going to be passed to the
`connexion.problem` function to generate a proper response.
"""
self.status = status
self.title = title
Expand Down
4 changes: 4 additions & 0 deletions connexion/handlers.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
This module defines error handlers, operations that produce proper response problems.
"""

import logging

from .exceptions import AuthenticationProblem, ResolverProblem
Expand Down
4 changes: 4 additions & 0 deletions connexion/http_facts.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
This module contains definitions of the HTTP protocol.
"""

FORM_CONTENT_TYPES = [
'application/x-www-form-urlencoded',
'multipart/form-data'
Expand Down
4 changes: 4 additions & 0 deletions connexion/json_schema.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
Module containing all code related to json schema validation.
"""

from copy import deepcopy

from jsonschema import Draft4Validator, RefResolver, _utils
Expand Down
15 changes: 14 additions & 1 deletion connexion/jsonifier.py
Original file line number Diff line number Diff line change
@@ -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:
Expand All @@ -25,7 +38,7 @@ def default(self, o):

class Jsonifier(object):
"""
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):
"""
Expand Down
7 changes: 7 additions & 0 deletions connexion/lifecycle.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
"""
This module defines interfaces for requests and responses used in Connexion for authentication,
validation, serialization, etc.
"""


class ConnexionRequest(object):
"""Connexion interface for a request."""
def __init__(self,
url,
method,
Expand Down Expand Up @@ -28,6 +34,7 @@ def json(self):


class ConnexionResponse(object):
"""Connexion interface for a response."""
def __init__(self,
status_code=200,
mimetype=None,
Expand Down
4 changes: 4 additions & 0 deletions connexion/mock.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
This module contains a mock resolver that returns mock functions for operations it cannot resolve.
"""

import functools
import logging

Expand Down
8 changes: 8 additions & 0 deletions connexion/operations/__init__.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down
5 changes: 5 additions & 0 deletions connexion/operations/abstract.py
Original file line number Diff line number Diff line change
@@ -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

Expand Down
4 changes: 3 additions & 1 deletion connexion/operations/compat.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# This is a dummy module for backwards compatability with < v2.0
"""
This is a dummy module for backwards compatibility with < v2.0.
"""
from .secure import * # noqa
from .swagger2 import * # noqa
4 changes: 4 additions & 0 deletions connexion/operations/openapi.py
Original file line number Diff line number Diff line change
@@ -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

Expand Down
Loading