Skip to main content

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.

Metadata

Release files for gcm-diagnostics 1.4.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for gcm-diagnostics 1.4.3
File Size Uploaded
gcm_diagnostics-1.4.3.tar.gz 19.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for gcm-diagnostics 1.4.3
File Interpreter ABI Platform
gcm_diagnostics-1.4.3-py3-none-any.whl Python 3 none any Details

Total release size: 38.9 kB

Release files / gcm_diagnostics-1.4.3.tar.gz

Download URL gcm_diagnostics-1.4.3.tar.gz
Size 19.5 kB
Tags Source
SHA-256 checksum
How to use checksums
d1282f583a28fb7743dc330f56ae3fadaab6401b00d246e30977c7ac3e7afbbb
BLAKE2b-256 checksum
How to use checksums
eb6cd2689de83cf9015ef82a12ab30b2918d35b81afa4191673af3887484b6c7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.4.1 CPython/3.11.15 Linux/6.8.0-90-generic

Release files / gcm_diagnostics-1.4.3-py3-none-any.whl

Download URL gcm_diagnostics-1.4.3-py3-none-any.whl
Size 19.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f221d9cc3b924a7e2c22452bbbcb76abb28f5378a85920fdbb46b42b755521c6
BLAKE2b-256 checksum
How to use checksums
454dbcb29cd1184b9624466ef57f661824be5de8d11206f4cc3195d0c59dadf5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.4.1 CPython/3.11.15 Linux/6.8.0-90-generic

Release history Release notifications | RSS feed

This release

1.4.3 This release

2 release files

1.4.2

2 release files

1.4.1

2 release files

1.3.3

2 release files

1.3.1

2 release files

1.2.0

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page