.. _blueprints:
==========
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:
.. code:: python
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:
.. code:: python
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
.. code:: python
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`
.. code:: python
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.
.. code:: python
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.
.. code:: python
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
^^^^
.. code:: python
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.
.. code:: python
invalid_d = qalx.item.add(data={'a': 30, 'b': 5})
dim_bp.validate(invalid_d)
The code above raises the following error:
.. code-block::
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.
.. code:: python
d = qalx.item.add(data={'height': 30, 'width': 5})
valid_set = qalx.set.add(items={"dimensions": d},
blueprint_name="ASetBlueprint")
# Make some changes to our valid set
# 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