Builder¶
About extension¶
Builder provides comfortable support for preparing data in database. You can declare schema for data creation and configure preparing from any runnable object who has instance of builder. Factories is an integral part of builder but can be usable separated of. Main task of the factory is product of object and its relations. Create method always gives rise to general object. Any factory method must has property as storage. If you don’t set specific storage name that storage name will as method name without “create_” prefix.
Builder is not related to specific ORM and can be used with any ORM and simple sql.
Important! Builder extension is not pluggable. You should to create instance inside runnable object for using.
Example¶
import seismograph
from seismograph.ext.builder import BaseBuilder
from seismograph.ext.builder import AliasToMethod
from seismograph.ext.builder.factory import BaseFactory
from seismograph.ext.builder.factory import factory_method
class UserFactory(BaseFactory):
def __init__(self, **user_data):
self.user = None
self.account = None
self.permissions = []
self._user_data = {} # values by default
self.build_data(**user_data)
@property
def data(self): # must be implemented
return self._user_data
def build_data(self, **user_data): # must be implemented
self._user_data.update(user_data)
@factory_method(require=['user'], only_one_creation=True)
def create_account(self, **account_data):
account_data.update(user_id=self.user.id)
self.account = AccountModel.create(**account_data)
return self._account
@factory_method(require=['user'], storage='permissions')
def create_permission(self, perm):
created_perm = UserPermissionModel.create(
perm=perm, user_id=self.user.id,
)
self.permissions.append(created_perm)
return created_perm
@factory_method(only_one_creation=True, storage='user')
def create(self): # must be implemented
self.user = UserModel.create(**self._user_data)
return self.user
class UserBlogFactory(BaseFactory):
def __init__(self, user, **blog_data):
self.user = user
self.blog = None
self.posts = []
self._blog_data = {}
self.build_data(**blog_data)
@property
def data(self): # must be implemented
return self._blog_data
def build_data(self, **blog_data): # must be implemented
self._blog_data.update(blog_data)
self._blog_data.update(user_id=self.user.id)
@factory_method(require=['blog'], storage='posts')
def create_post(self, **post_data):
post_data.update(blog_id=self.blog.id)
post = PostModel.create(**post_data)
self.posts.append(post)
return post
@factory_method(only_one_creation=True, storage='blog')
def create(self): # must be implemented
self.blog = BlogModel.create(**self._blog_data)
return self.blog
def init_blog_factory(builder, cls, sig): # for example
return cls(builder.schema.user, *sig.args, **sig.kwargs)
def create_user(factory, schema): # for example
user = factory.create()
factory.create_account()
return user
class Builder(BaseBuilder):
__build_schema__ = {
'user': {
'storage': 'users',
'factory_class': UserFactory,
'staging': {
'pre': tuple(), # for example only
'creator': create_user,
'post': (
AliasToMethod('account', 'create_account'),
AliasToMethod('permission', 'create_permission'),
),
},
'embedded': {
'blog': {
'storage': 'blogs',
'factory_class': UserBlogFactory,
'initializer': init_blog_factory,
'staging': {
'pre': tuple(), # for example only
'post': (
AliasToMethod('post', 'create_post'),
),
},
},
},
# require = ['any key from this level can be here']
},
}
suite = seismograph.Suite(__name__)
@suite.register
def simple_test(case):
builder = Builder(case)
builder.configure(
user={
'permission': {'perm': 'permission name'},
'blog': (
{
'post': {'title': 'hello', 'text': 'Hello world!'},
},
{
'post': {'title': 'hello 2', 'text': 'Hello world!'},
},
),
},
)
builder.schema.user # last created user is here
builder.schema.users # user list is here, we set it by storage key
builder.schema.user.blog # this is last created blog
builder.schema.user.blogs # all created blogs here
builder.schema.user.blog.posts # this is list from factory