-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathmodel_base.py
More file actions
142 lines (116 loc) · 4.2 KB
/
model_base.py
File metadata and controls
142 lines (116 loc) · 4.2 KB
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# Copyright 2012 Hewlett-Packard Development Company, L.P.
#
# Author: Patrick Galbraith <patg@hp.com>
# Author: Endre Karlson <endre.karlson@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# Copied: Moniker
from sqlalchemy import Column, DateTime, Unicode, UnicodeText
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import object_mapper
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.ext.declarative import declared_attr
from billingstack import exceptions, utils
from billingstack.sqlalchemy.types import UUID
from billingstack.openstack.common.uuidutils import generate_uuid
from billingstack.openstack.common import timeutils
class ModelBase(object):
__abstract__ = True
__table_initialized__ = False
@declared_attr
def __tablename__(cls):
return utils.capital_to_underscore(cls.__name__)
def save(self, session):
""" Save this object """
session.add(self)
try:
session.flush()
except IntegrityError, e:
non_unique_strings = (
'duplicate entry',
'not unique'
)
for non_unique_string in non_unique_strings:
if non_unique_string in str(e).lower():
raise exceptions.Duplicate(str(e))
# Not a Duplicate error.. Re-raise.
raise
def delete(self, session):
""" Delete this object """
session.delete(self)
session.flush()
def __setitem__(self, key, value):
setattr(self, key, value)
def __getitem__(self, key):
return getattr(self, key)
def __iter__(self):
columns = dict(object_mapper(self).columns).keys()
# NOTE(russellb): Allow models to specify other keys that can be looked
# up, beyond the actual db columns. An example would be the 'name'
# property for an Instance.
if hasattr(self, '_extra_keys'):
columns.extend(self._extra_keys())
self._i = iter(columns)
return self
def next(self):
n = self._i.next()
return n, getattr(self, n)
def update(self, values):
""" Make the model object behave like a dict """
for k, v in values.iteritems():
setattr(self, k, v)
def iteritems(self):
"""
Make the model object behave like a dict.
Includes attributes from joins.
"""
local = dict(self)
joined = dict([(k, v) for k, v in self.__dict__.iteritems()
if not k[0] == '_'])
local.update(joined)
return local.iteritems()
class BaseMixin(object):
"""
A mixin that provides id, and some dates.
"""
id = Column(UUID, default=generate_uuid, primary_key=True)
created_at = Column(DateTime, default=timeutils.utcnow)
updated_at = Column(DateTime, onupdate=timeutils.utcnow)
TYPES = {
"float": float,
"str": unicode,
"unicode": unicode,
"int": int,
"bool": bool
}
class PropertyMixin(object):
"""
Helper mixin for Property classes.
Store the type of the value using type() or the pre-defined data_type
and cast it on value when returning the value.
Supported types are in the TYPES dict.
"""
id = Column(UUID, default=generate_uuid, primary_key=True)
data_type = Column(Unicode(20), nullable=False, default=u'str')
name = Column(Unicode(60), index=True, nullable=False)
_value = Column('value', UnicodeText)
@hybrid_property
def value(self):
data_type = TYPES.get(self.data_type, str)
return data_type(self._value)
@value.setter
def value(self, value):
data_type = type(value).__name__
self.data_type = data_type
self._value = value