Blueprints

Blueprints enable you to repeat the creation of Items or Sets in a consistent fashion.

At it’s core, a blueprint is just a jsonschema that you define, which you can then use to validate Items or Sets that you are adding to qalx.

Creating Blueprints

Create a blueprint using the Blueprint class and helper methods to add schema elements. Blueprint names are unique across an entire company.

To create a blueprint for an item you can add various rules for data keys:

from pyqalx import QalxSession, Blueprint

qalx = QalxSession()

dim_schema = Blueprint.item()
dim_schema.add_data("width",
                    {'type': 'number',
                     'minimum': 1},
                    required=True)
dim_schema.add_data("height",
                    {'type': 'number',
                     'minimum': 3,
                     'exclusiveMaximum': 100},
                    required=True)
dim_bp = qalx.blueprint.add(name='DimsBlueprint',
                            schema=dim_schema)

You could also build the schema ahead of time and update the entire blueprint at once. The below example and the above example both give the same output and each have their own pros and cons to using them:

from pyqalx import QalxSession, Blueprint

qalx = QalxSession()

dim_schema = Blueprint.item()
schema = {'data': {
            'type': 'object',
            'properties': {
                'width': {'type': 'number',
                          'minimum': 1
                          },
                'height': {'type': 'number',
                           'minimum': 3,
                           'exclusiveMaximum': 100
                           },
                },
                'required': ['width', 'height'],
                }
            }

dim_schema.add_schema(schema)

dim_bp = qalx.blueprint.add(name='DimsBlueprint',
                            schema=dim_schema)

Using Blueprints

Blueprints can be used to validate that the data that you are trying to add to an Item or Set is valid. You can use a Blueprint during the add process by providing the name to the method.

The below code would raise a jsonschema.ValidationError as the DimsBlueprint blueprint requires the width field on data to be at least 1

qalx = QalxSession()

data = {
    'width': 0.5
    'height': 10
}

qalx.item.add(data=data, blueprint_name='DimsBlueprint')

The below code would create the item as usual as the data we are providing matches the schema defined in DimsBlueprint

qalx = QalxSession()

data = {
    'width': 5
    'height': 10
}

qalx.item.add(data=data, blueprint_name='DimsBlueprint')

For sets, it is possible to specify that certain item keys are specified and that each of the items conforms to a specific blueprint. Suppose that we want a set with a dimensions item and a material item.

mat_schema = Blueprint.item()
mat_schema.add_data("density",
                    {'type': 'number'},
                    required=True)
mat_schema.add_data("E",
                    {'type': 'integer',
                     'multipleOf': 1e9},
                    required=True)
mat_bp = qalx.blueprint.add(name='MatsBlueprint',
                            schema=mat_schema)

set_schema = Blueprint.set()
set_schema.add_item("dimensions", dim_bp)
set_schema.add_item("material", mat_bp)
set_bp = qalx.blueprint.add(name='ASetBlueprint',
                            schema=set_schema)

Then, when we add items to a set we can ensure that the items are in the format we expect.

d = qalx.item.add(data={'height': 30, 'width': 5},
                  blueprint_name='DimsBlueprint')
m = qalx.item.add(data={'density': 1.4, 'E': 120e9},
                  blueprint_name='MatsBlueprint')
s = qalx.set.add(items={"dimensions": d, "material": m},
                 blueprint_name='ASetBlueprint')

Validating entities against blueprints

Blueprints also provide the functionality to validate an entity locally, without making a save request to qalx. In this way, we can check for conformity with a blueprint schema if we require this check to be done for an entity without necessarily wishing to save the entity, at least at this point in time. The following example, demonstrates this functionality.

Item

d_no_bp = qalx.item.add(data={'height': 30, 'width': 5})
dim_bp.validate(d_no_bp)

The validation in the code above works and no errors should be raised. In the same way, for items that are not structured according to a blueprint, a validation error will be raised.

invalid_d = qalx.item.add(data={'a': 30, 'b': 5})
dim_bp.validate(invalid_d)

The code above raises the following error:

ValidationError: 'width' is a required property

Failed validating 'required' in schema['properties']['data']:
    {'properties': {'height': {'exclusiveMaximum': 100,
                               'minimum': 3,
                               'type': 'number'},
                    'width': {'minimum': 1, 'type': 'number'}},
     'required': ['width', 'height'],
     'type': 'object'}

On instance['data']:
    {'a': 30, 'b': 5}

Set

The same functionality is available for Set blueprints as well.

d = qalx.item.add(data={'height': 30, 'width': 5})
valid_set = qalx.set.add(items={"dimensions": d},
                         blueprint_name="ASetBlueprint")
# <snip>Make some changes to our valid set</snip>

# Check that our set is still valid against the blueprint that we
# obtained from earlier examples.
set_bp.validate(valid_set)

Data Schema Options

Datatypes

string”: “Hello World”

number”: 1.23

integer”: 123

boolean”: true

object”: {“foo”:”bar”, “baz”:”Hello World”}

array”: [“foo”,”bar”, 5,”hello”]

null”: None

Features

string + number + integer

enum: […]

format: date-time, email, hostname, ipv4, ipv6, uri

string

minLength, maxLength

pattern: regexp

number + integer

minimum, maximum

exclusiveMinimum, exclusiveMaximum

multipleOf

array

items

minItems, maxItems

uniqueItems: enforce uniqueness

additionalItems: if true, validation always passes

object

properties

minProperties, maxProperties

patternProperties: regex base properties

additionalProperties: if true, validation always passes

required