MetaBaseModel   A
last analyzed

Complexity

Total Complexity 3

Size/Duplication

Total Lines 15
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 3
c 1
b 0
f 0
dl 0
loc 15
rs 10

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __init__() 0 3 1
A __getitem__() 0 7 2
1
"""
2
Define an Abstract Base Class (ABC) for models
3
"""
4
from datetime import datetime
5
from weakref import WeakValueDictionary
6
from sqlalchemy import inspect
7
from sqlalchemy.orm import aliased
8
9
from . import db
10
11
12
class MetaBaseModel(db.Model.__class__):
13
    """ Define a metaclass for the BaseModel
14
        Implement `__getitem__` for managing aliases """
15
16
    def __init__(cls, *args):
17
        super().__init__(*args)
18
        cls.aliases = WeakValueDictionary()
19
20
    def __getitem__(cls, key):
21
        try:
22
            alias = cls.aliases[key]
23
        except KeyError:
24
            alias = aliased(cls)
25
            cls.aliases[key] = alias
26
        return alias
27
28
29
class BaseModel():
30
    """ Generalize __init__, __repr__ and to_json
31
        Based on the models columns """
32
33
    print_filter = ()
34
    to_json_filter = ()
35
36
    def __repr__(self):
37
        """ Define a base way to print models
38
            Columns inside `print_filter` are excluded """
39
        return '%s(%s)' % (self.__class__.__name__, {
40
            column: value
41
            for column, value in self._to_dict().items()
42
            if column not in self.print_filter
43
        })
44
45
    @property
46
    def json(self):
47
        """ Define a base way to jsonify models
48
            Columns inside `to_json_filter` are excluded """
49
        return {
50
            column: value
51
            if not isinstance(value, datetime) else value.strftime('%Y-%m-%d')
52
            for column, value in self._to_dict().items()
53
            if column not in self.to_json_filter
54
        }
55
56
    def _to_dict(self):
57
        """ This would more or less be the same as a `to_json`
58
            But putting it in a "private" function
59
            Allows to_json to be overriden without impacting __repr__
60
            Or the other way around
61
            And to add filter lists """
62
        return {
63
            column.key: getattr(self, column.key)
64
            for column in inspect(self.__class__).attrs
65
        }
66
67
    def save(self):
68
        db.session.add(self)
69
        db.session.commit()
70
        return self
71
72
    def delete(self):
73
        db.session.delete(self)
74
        db.session.commit()
75