Source code for pyoko.modelmeta

# -*-  coding: utf-8 -*-
"""
"""

# Copyright (C) 2015 ZetaOps Inc.
#
# This file is licensed under the GNU General Public License v3
# (GPLv3).  See LICENSE.txt for details.
import pprint
from collections import defaultdict

from pyoko.conf import settings
from pyoko.db.queryset import QuerySet
from pyoko.lib.utils import un_camel
from pyoko.registry import Registry
from . import fields as field

model_registry = Registry()


[docs]class ModelMeta(type): """ Metaclass that process model classes. """ def __new__(mcs, name, bases, attrs): base_model_class = bases[0] class_type = getattr(base_model_class, '_TYPE', None) if class_type == 'Model': mcs.process_models(attrs, base_model_class) # if class_type == 'ListNode': # mcs.process_listnode(attrs, base_model_class) mcs.process_attributes_of_node(attrs, name, class_type) new_class = super(ModelMeta, mcs).__new__(mcs, name, bases, attrs) return new_class def __init__(mcs, name, bases, attrs): if mcs.__name__ not in ('Model', 'Node', 'ListNode'): ModelMeta.process_objects(mcs) if mcs.__base__.__name__ == 'Model': # add models to model_registry mcs.objects = QuerySet(model_class=mcs) model_registry.register_model(mcs) if 'bucket_name' not in mcs.Meta.__dict__: mcs.Meta.bucket_name = un_camel(mcs.__name__)
[docs] @staticmethod def process_attributes_of_node(attrs, node_name, class_type): """ prepare the model fields, nodes and relations Args: node_name (str): name of the node we are currently processing attrs (dict): attribute dict class_type (str): Type of class. Can be one of these: 'ListNode', 'Model', 'Node' """ # print("Node: %s" % node_name) attrs['_nodes'] = {} attrs['_linked_models'] = defaultdict(list) attrs['_debug_linked_models'] = defaultdict(list) attrs['_lazy_linked_models'] = defaultdict(list) attrs['_fields'] = {} attrs['_uniques'] = [] # attrs['_many_to_models'] = [] # iterating over attributes of the soon to be created class object. for key, attr in list(attrs.items()): # if it's a class (not instance) and it's type is Node or ListNode if hasattr(attr, '__base__') and getattr(attr.__base__, '_TYPE', '') in ['Node', 'ListNode']: # converted pops to dict access to allow sphinx to # properly document the models # attrs['_nodes'][key] = attrs.pop(key) attrs['_nodes'][key] = attrs[key] else: # otherwise it should be a field or linked model attr_type = getattr(attr, '_TYPE', '') if attr_type == 'Model': attrs['%s_id' % key] = '' # lnk_mdl_ins = attrs.pop(key) lnk_mdl_ins = attrs[key] lnk = { 'null': lnk_mdl_ins.null or class_type == 'ListNode', 'link_source': True, 'mdl': lnk_mdl_ins.__class__, 'o2o': lnk_mdl_ins._is_one_to_one, 'm2m': class_type == 'ListNode', 'reverse': lnk_mdl_ins.reverse_name, 'verbose': lnk_mdl_ins.verbose_name, 'field': key, 'is_set': False, } attrs['_linked_models'][attr.__class__.__name__].append(lnk) debug_lnk = lnk.copy() debug_lnk['lnksrc']= 'process_attributes_of_node' attrs['_debug_linked_models'][attr.__class__.__name__].append(debug_lnk) elif attr_type == 'Field': attr.name = key attrs['_fields'][key] = attr if attr.unique: attrs['_uniques'].append(key) elif attr_type == 'Link': # lzy_lnk = attrs.pop(key) attrs['%s_id' % key] = '' lzy_lnk = attrs[key] attrs['_lazy_linked_models'][key].append({'from': node_name, 'to': lzy_lnk.link_to, 'o2o': lzy_lnk.one_to_one, 'verbose': lzy_lnk.verbose_name, 'reverse': lzy_lnk.reverse_name, 'field': key})
[docs] @staticmethod def process_models(attrs, base_model_class): """ Attach default fields and meta options to models """ attrs.update(base_model_class._DEFAULT_BASE_FIELDS) attrs['_instance_registry'] = set() attrs['_is_unpermitted_fields_set'] = False attrs['save_meta_data'] = None attrs['_pre_save_hook_called'] = False attrs['_post_save_hook_called'] = False DEFAULT_META = {'bucket_type': settings.DEFAULT_BUCKET_TYPE, 'field_permissions': {}, 'app': 'main', 'list_fields': [], 'list_filters': [], 'search_fields': [], 'fake_model': False, } if 'Meta' not in attrs: attrs['Meta'] = type('Meta', (object,), DEFAULT_META) else: for k, v in DEFAULT_META.items(): if k not in attrs['Meta'].__dict__: setattr(attrs['Meta'], k, v)
# @staticmethod # def process_listnode(attrs, base_model): # attrs['idx'] = field.Id()
[docs] @staticmethod def process_objects(kls): """ Applies default Meta properties. """ # first add a Meta object if not exists if 'Meta' not in kls.__dict__: kls.Meta = type('Meta', (object,), {}) if 'unique_together' not in kls.Meta.__dict__: kls.Meta.unique_together = [] # set verbose_name(s) if not already set if 'verbose_name' not in kls.Meta.__dict__: kls.Meta.verbose_name = kls.__name__ if 'verbose_name_plural' not in kls.Meta.__dict__: kls.Meta.verbose_name_plural = kls.Meta.verbose_name + 's'