Sanic-validation 0.3 brings support for data normalization

Sanic-validation 0.3.0 was just released.
A big new feature is support for data normalization. You can have cleaned and normalized data provided directly to your handler method. Renaming of fields, assigning default values and converting types could be done as part of the validation step. This is especially useful for working with query arguments, as they are provided as strings by default.

How to use it?

Let’s say we want to write a service that returns the first count words of Lorem Ipsum. Let’s also assume that we have a list lorem_ipsum_words containing the text split into single words.
Our endpoint could look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
schema = {
'count': {
'type': 'integer',
'min': 1,
'required': True,
'coerce': int,
}
}


@app.get('/lorem-provider')
@validate_args(schema, clean=True)
async def lorem_ipsum_provider(request, valid_args):
words = lorem_ipsum_words[:valid_args['count']]
result = ' '.join(words)
return text(result)

Because of the coerce rule, count will be parsed with int before validation begins. If conversion fails, an appropriate validation error will be returned. Enabling the clean flag signals that we want cleaned arguments to be passed to our handler function as valid_args. This dictionary will contain count as a number, so we don’t have to manually convert it.

For more information, check out the documentation.

Validation library for sanic

I’ve recently discovered sanic - a fast, async web server framework.
I couldn’t find a good validation library for it, so I wrote my own.
Under the hood it uses cerberus to validate data against the supplied schema.
Generated error messages provide full path to the offending parameter, and the constraint that was broken.

Installation

1
pip install sanic-validation

Usage

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from sanic import Sanic
from sanic.response import json
from sanic_validation import validate_json


app = Sanic()

schema = {'name': {'type': 'string', 'required': True}}


@app.route('/')
@validate_json(schema)
async def _simple_endpoint(request):
return json({'message': 'Hello ' + request.json['name']})

app.run('0.0.0.0')

Example error

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"error": {
"invalid": [
{
"constraint": true,
"entry": "name",
"entry_type": "json_data_property",
"rule": "required"
}
],
"message": "Validation failed.",
"type": "validation_failed"
}
}

New blog site

Welcome to my new blog site.
It’s based on the Hexo static page generator.
I decided to drop ComfyMS. It was a fun experiment, but it lacked features.

Cinnabar released

The academic year is officially over.
This means I can share a project I’ve been working on for the Programming Languages and Paradigms course.
It’s an original programming language and its interpreter, written in Haskell.

The name Cinnabar references a toxic, but also beautiful mineral.
The language draws inspiration from JavaScript and Python.

Notable features include:

  • All variables are references
  • Dynamic typing with built-in types: char, bool, int, object, list, dictionary, function
  • Char, bool, int and list values are immutable
  • Tuple unpacking
  • List and dictionary literals, list comprehension
  • Runtime assertions
  • String literals (implemented as character lists)
  • Built-in str function - converts values to string representation
  • Writing to stdout and reading from stdio
  • Anonymous functions with arguments passed by reference
  • Objects with instance fields and methods.
  • Classless prototype inheritance

A simple Hello World program:

1
print "Hello World!\n";

You can get the interpreter, documentation and sample programs here.