Basic Tutorial (Python)

This tutorial introduces how CBOT can be used in Python for both untyped and Typed Model which is the intended use case for the protocol.

Installation

pip install sisujs-cbot

Untyped Example: Library

CBOT can be used as a simple replacement for json.dumps() and json.loads() and this example will demonstrate typical JSON-like behavior that you may be accustomed to. The example consists of a library with three concepts: Author, Book and Catalog.

Let's define some values:

isaac = {
  "name": "Isaac Asimov",
  "birthdate": date(1902, 1, 2)
}

foundation = {
  "title": "Foundation",
  "isbn": "978-0-394-51330-7",
  "publication_year": 1951,
  "author": isaac
}

i_robot = {
  "title": "I, Robot",
  "isbn": "978-0-394-51331-4",
  "publication_year": 1950,
  "author": isaac
}

catalog = [
  {
    "genre": "Science Fiction",
    "books": [
      foundation,
      i_robot
    ],
    "authors": [isaac]
  }
]

In order to serialize something, one needs an instance of CBOT in some static variable. You should always create just one instance for each model and use it globally.

from sisujs_cbot import Cbot, CbotOptions

cbot = Cbot(CbotOptions())

Now we can actually serialize an object to a message and vice versa:

msg = cbot.serialize(foundation)
deserialized = cbot.deserialize(msg)

This example demonstrated how serialization and deserialization are used in a JSON-like way.

Typed Example: Library

This example employs the same concepts as the untyped one but with actual types. Cbot-implementation relies on Pydantic-models to create proper class-model

Namespace

The first step is to create a namespace which is an important tool for categorizing Pydantic models into usable groups.

Namespace is created as follows:

from sisujs_cbot import Cbot, CbotNamespace, CbotOptions

ns = CbotNamespace("library")

Typed Model

Then model is created as follows:

@ns.model()
class Author(BaseModel):
  name: str = string_type()
  birthdate: date = local_date_type()

@ns.model()
class Book(BaseModel):
  title: str = string_type()
  isbn: str = string_type()
  author: Author = model_object_type()
  publication_year: int = int32_type("publicationYear")
  rating: float = float64_type()

@ns.model()
class Catalog(BaseModel):
  genre: str = string_type()
  books: list[Book] = model_object_type()
  authors: list[Author] = model_object_type()

ns.seal()

What can be observed here is that classes and all their properties require a corresponding type-information for the model to be constructed correctly. For instance Python has a int-type which is in practice arbitrary long integer. In this case it must indentified as int32(), int64() or big_integer().

It is also possible to have (transient) properties without adding the indentifier at all, and these will not be included in the model.

Also, note that publication_year property has additional name in the indentifier. The publicationYear is a public name so that property names do not have be in camelcase.

The last thing is to call seal() function for all declared types, which prevents adding further declarations.

Creating Objects

After this object creation happens as expected:


isaac = Author(name="Isaac Asimov", birthdate=date(1902, 1, 2))

foundation = Book(
  title="Foundation",
  isbn="978-0-394-51330-7",
  publication_year=1951,
  author=isaac,
  rating=7.0)

i_robot = Book(
  title="I, Robot",
  isbn="978-0-394-51331-4",
  publication_year=1950,
  author=isaac,
  rating=10.0)

catalog = Catalog(
  genre="Science Fiction",
  books=[foundation, i_robot],
  authors= [isaac])

Cbot instance

Next a proper Cbot-instance is created as follows:

cbot = Cbot(CbotOptions(namespaces=[ns]))

Usage

Next we can serialize and deserialize a catalog as expected:

msg = cbot.serialize(catalog);
deserialized:Catalog = cbot.deserialize(msg);