Scalars#

Scalars are a way to extend the schema input and output types. The basic scalars are usually enough for most projects, however adding a few extra types makes working with the requests and responses a little easier.

Cannula provides a handful of useful scalars which might be all you need. You just need to specify these in you configuration and add them to your schema. These will automatically serialize and deserialize the values from an Input type or when rendering the data.

Example schema:

scalar Datetime

type MyModel {
   id: id
   created: Datetime
}

Then in your cannula.api.CannulaAPI specify the scalars you are using with the full dotted import path:

graph = CannulaAPI(
    PARENT_DIR / 'schema.graphql',
    scalars=[
        "cannula.scalars.date.Datetime"
    ]
)

Built-in Scalars#

These scalars are available to use just add to your configuration. If you are using codegen they will also need to be set in the pyproject.toml definition so that the generated code will import them properly.

cannula.scalars.date.Date

Date seralizes to datetime.date objects

cannula.scalars.date.Datetime

Datetime seralizes to datetime.datetime objects

cannula.scalars.date.Time

Time seralizes to datetime.time objects

cannula.scalars.util.JSON

JSON seralizes to json() objects

cannula.scalars.util.UUID

UUID seralizes to uuid.UUID() objects

Custom Scalars#

If the Built-in Scalars are not quite perfect or you need something else, you can easily define your own. Simply create a subclass of the cannula.scalars.ScalarType and provide a serialize() and parse_value() methods.

class cannula.scalars.ScalarInterface(*args, **kwargs)#

This is used for type hints to assert that the Custom Scalars match this interface. For concrete implementations you should subclass the cannula.scalars.ScalarType

class cannula.scalars.ScalarType#

This class is intended to assist in generating well typed custom scalars. This class is a Generic type that expects two concrete types, Input and Output. Input is the raw python type and Output is a serializable type like str, int that is safe for JSON encoding.

To use a custom type you must first add this type definition to your schema:

scalar Datetime

Next you need to create a subclass of ScalarType like:

from datetime import datetime

class Datetime(
    ScalarType[
        datetime,     # The first type is the Input
        str,          # The second type is the Output
    ],
    name="Datetime",  # Optional scalar name, by default the class name will be used.
):

    @staticmethod
    def serialize(value: datetime) -> str:
        return value.isoformat()

    @staticmethod
    def parse_value(value: str) -> datetime:
        return datetime.datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%f")