Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
from __future__ import annotations
from typing import Any, Dict, Mapping, Tuple
from common.orm.fields.PrimaryKeyField import PrimaryKeyField
from common.type_checkers.Checkers import chk_none
from ..backend._Backend import _Backend
from ..fields.Field import Field
from .Tools import NoDupOrderedDict
class MetaModel(type):
@classmethod
def __prepare__(metacls, name : str, bases : Tuple[type, ...], **attrs : Any) -> Mapping[str, Any]:
return NoDupOrderedDict()
def __new__(metacls, name : str, bases : Tuple[type, ...], attrs : NoDupOrderedDict[str, Any]):
field_names = list()
primary_key_field = None
for key, value in attrs.items():
if not isinstance(value, Field): continue
attrs[key].name = key
field_names.append(key)
if isinstance(value, PrimaryKeyField):
if primary_key_field is None:
primary_key_field = value
continue
raise AttributeError('PrimaryKey for Model({:s}) already set to attribute({:s})'.format(
str(name), str(primary_key_field.name)))
cls_obj = super().__new__(metacls, name, bases, dict(attrs))
setattr(cls_obj, '_primary_key_field', primary_key_field)
setattr(cls_obj, '_field_names_list', field_names)
setattr(cls_obj, '_field_names_set', set(field_names))
return cls_obj
class Model(metaclass=MetaModel):
def __init__(self, parent : 'Model', primary_key : Any = None) -> None:
if not isinstance(parent, Model):
str_class_path = '{}.{}'.format(Model.__module__, Model.__name__)
raise AttributeError('parent must inherit from {}'.format(str_class_path))
self._parent = parent
self._backend = self._parent.backend
self._class_name = type(self).__name__
self._backend_key = '{:s}/{:s}'.format(self.parent.backend_key, self._class_name)
if self._primary_key_field is not None: # pylint: disable=no-member
primary_key_field_name = self._primary_key_field.name # pylint: disable=no-member
print('primary_key_field_name', primary_key_field_name)
setattr(self, primary_key_field_name, primary_key)
self._backend_key += '[{:s}]'.format(getattr(self, primary_key_field_name))
else:
try:
chk_none('primary_key', primary_key)
except:
msg = 'Unable to set primary_key({:s}) since no PrimaryKeyField is defined in the model'
raise AttributeError(msg.format(str(primary_key)))
@property
def parent(self) -> 'Model': return self._parent
@property
def backend(self) -> _Backend: return self._parent.backend
@property
def backend_key(self) -> str: return self._backend_key
def load(self) -> None:
attributes = self._backend.dict_get(self._backend_key).items()
for name in self._field_names_list: # pylint: disable=no-member
if name not in attributes: continue
setattr(self, name, attributes[name])
def save(self) -> None:
attributes : Dict[str, Any] = {
name:repr(getattr(self, name))
for name in self._field_names_list # pylint: disable=no-member
}
self._backend.dict_update(self._backend_key, attributes)
def delete(self) -> None:
self._backend.dict_delete(self._backend_key)
def dump_id(self) -> Dict:
raise NotImplementedError()
def dump(self) -> Dict:
raise NotImplementedError()
def __repr__(self) -> str:
pk_field = self._primary_key_field # pylint: disable=no-member
pk_field_name = None if pk_field is None else pk_field.name # pylint: disable=no-member
arguments = ', '.join(
'{:s}={:s}{:s}'.format(
name, repr(getattr(self, name)), '(PK)' if name == pk_field_name else '')
for name in self._field_names_list # pylint: disable=no-member
)
return '{:s}({:s})'.format(self._class_name, arguments)