Base classes

Base classes are intended to provide data modeling, validation and configuration management by utilizing normal python classes. For example, given the following simple class

class Person:
    name = fields.String(default="ahmed")

The user should be able to create/store multiple instances of Person with valid data.

To achieve this, we implemented base classes using meta classes and property descriptors. (a small note, after python 3.7 data classes seems a better option that can be used later).

At first, to explain why we need to implement custom base class/model, we will illustrate the following examples:

If we have the same class called Person, with the following definition:

class Person:
    name = fields.String(default="ahmed")

Accessing the class variable name from class or instance level will yield the same value, an instance of String field:

Person.name  #=> <jumpscale.core.base.fields.String object at 0x7efd89980c18>

p = Person()
p.name  #=> <jumpscale.core.base.fields.String object at 0x7efd89980c18>

The solution to this problem is using data descriptors (see https://docs.python.org/3/howto/descriptor.html), so the following class:

class Person(Base):
    name = fields.String(default="ahmed")

Should have different behavior when accessing name from a class or an objects, so, it will be converted by the meta class to a new class like:

class Person(Base):
    def __init__(self):
        self.__name = "ahmed"

    @property
    def get_name(self):
        return self.__name

    @property
    def set_name(self, value):
        self.__name == value

    name = property(get_name, set_name)

And accessing name from class and object levels will yield:

Person.name  #=> <property object at 0x7efd89a259f8>


p = Person()
p.name  #=> "ahmed"

Parent relationship is supported too, every instance can have a parent object (which must be a Base type too)

BaseMeta

This metaclass will convert normal classes to a new class with "injected" properties.

Also, this metaclass adds all field information inside _fields class variable.

    def __new__(cls, name: str, based: tuple, attrs: dict) -> type:
        """
        get a new class with all field attributes replaced by property data descriptors.

        Args:
            name (str): class name
            based (tuple): super class types (classes)
            attrs (dict): current attributes

        Returns:
            type: a new class
        """
        # will collect class fields
        cls_fields = {}
        ...
        ...

See complete implementation at meta.py

Base

This base class uses BaseMeta as its meta class, hence we have all information about defined fields/properties.

Then it implements - Serialization: to_dict/from_dict methods - Hierarchy: using an optional parent_

See full implementation at meta.py

Any one who uses this class as base class/model for his type, he will be able to define custom fields as class variables, then set/get a serializable and validated data.