Skip to main content

Business validation diagnostics (errors) collection library. With FastAPI support.

Project description

GCM Diagnostics

Library for collecting errors from validation logic and presenting them to user.

Mainly intended to be used with FastAPI endpoints for doing business validation which Pydantic is not intended for. Errors generated by this library are compatible with Pydantic validation response, so it appears the same to the consumer of API.

Installation

pip install gcm_diagnostics

# or

poetry add gcm_diagnostics

Usage

from gcm_diagnostics import DiagnosticCollector
from gcm_diagnostics.errors import EntityNotFound, EntityAlreadyExists

with DiagnosticCollector(prefix=["body"]) as diag:
    diag.append(EntityNotFound(loc=[1, "id"], id=1))
    diag.append(EntityAlreadyExists(loc=[2, "name"], entity="Hello"))

# Here, DiagnosticException is raised, containing both errors.

print(diag.errors)
# [
#     {
#         "loc": ["body", 1, "id"],
#         "msg": "Entity with id 1 not found",
#         "type": "entity_not_found",
#         "id": 1
#     },
#     {
#         "loc": ["body", 2, "name"],
#         "msg": "Entity already exists",
#         "type": "entity_already_exists",
#         "entity": "Hello"
#     }
# ]

Usage with FastAPI

from fastapi import FastAPI
from gcm_diagnostics import install_exception_handler, DiagnosticCollector, diagnostic_schema
from gcm_diagnostics.errors import EntityNotFound
from starlette.testclient import TestClient

app = FastAPI()

# Install exception handler for the DiagnosticError exception.  
install_exception_handler(app)

@app.get(
    "/",
    # This builds responses structure containing documentation for the specified
    # error types this endpoint produces instead of generic error description.
    # Usage of diagnostic_schema() is not required, it is just a convenient
    # helper to build better documentation even for error states.
    responses=diagnostic_schema([EntityNotFound])
)
def diagnostics(id: int) -> None:
    # Instantiate DiagnosticCollector(), that will collect all diagnostic data from
    # validation logic.
    # In this case, all errors will be prefixed with "query" prefix.
    with DiagnosticCollector(prefix=["query"]) as diag:
        # Append new error to the collector. This does not raise exception immediately,
        # it allows to collect multiple errors at one shot, and present it all to the user.
        # Resulting loc for this error will be ["query", "id"].
        diag.append(EntityNotFound(loc=["id"], id=id))
        
        # If you want to raise exception in the middle of validation logic, you can
        # use raise_if_errors() as follows:
        #diag.raise_if_errors()


with TestClient(app, raise_server_exceptions=False) as client:
    response = client.get("/", params={"id": 123})
    
    # Error code is gathered from diagnostics. If there are only diagnostics of one
    # type (with one status code), this status code is returned.
    # If there are multiple different status codes, generic 422 is returned.
    assert response.status_code == 404
    
    # Response is generated from collected diagnostics. All errors are present in the detail array.
    assert response.json() == {
        "detail": [
            {
                "loc": ["query", "id"],
                "msg": "Entity does not exists.",
                "type": "entity_not_found",
                "id": 123
            }
        ]
    }

For more usage details, please consult the documentation in the code, mainly the documentation of class DiagnosticCollector.

Maturity

This library is currently used in various production applications and is considered stable.

Contributing

Contributions are always welcome. Just open an issue or a merge request.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gcm_diagnostics-1.4.2.tar.gz (19.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gcm_diagnostics-1.4.2-py3-none-any.whl (19.3 kB view details)

Uploaded Python 3

File details

Details for the file gcm_diagnostics-1.4.2.tar.gz.

File metadata

  • Download URL: gcm_diagnostics-1.4.2.tar.gz
  • Upload date:
  • Size: 19.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.3.0 CPython/3.11.14 Linux/6.8.0-90-generic

File hashes

Hashes for gcm_diagnostics-1.4.2.tar.gz
Algorithm Hash digest
SHA256 28b44be65789dbbcd15c8bfef0b9a588eff382b8c5b3987d61acdc875d0c4874
MD5 8e0139d4b61e9e28d104113f750ce6e4
BLAKE2b-256 8ee2ed400f5d48d8b30b4fe9580e6b7099269e6f134c41cfc0f98b356e0fc92a

See more details on using hashes here.

File details

Details for the file gcm_diagnostics-1.4.2-py3-none-any.whl.

File metadata

  • Download URL: gcm_diagnostics-1.4.2-py3-none-any.whl
  • Upload date:
  • Size: 19.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.3.0 CPython/3.11.14 Linux/6.8.0-90-generic

File hashes

Hashes for gcm_diagnostics-1.4.2-py3-none-any.whl
Algorithm Hash digest
SHA256 ab476c8975f30ebb67ad37c15c32b0eb698ce55018abe80a08b467db0c97ba3e
MD5 fb4261d12fb2ee6b3a7e105a910a74b0
BLAKE2b-256 9396e76c1257e4393d855ca23504e8e609c36482989701f8cf7c74fd54f15524

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page