Move out to HelpersMixin

This commit is contained in:
Endre Karlson 2013-03-08 11:26:17 +00:00
parent b65342c86b
commit ff5766e398
2 changed files with 146 additions and 139 deletions

View File

@ -0,0 +1,144 @@
from sqlalchemy import or_
from sqlalchemy.orm import exc
from billingstack import exceptions
from billingstack.sqlalchemy.model_base import ModelBase
class HelpersMixin(object):
def _save(self, obj, save=True):
if not save:
return obj
try:
obj.save(self.session)
except exceptions.Duplicate:
raise
def _list(self, cls=None, query=None, criterion=None):
"""
A generic list method
:param cls: The model to try to delete
:param criterion: Criterion to match objects with
"""
if not cls and not query:
raise ValueError("Need either cls or query")
query = query or self.session.query(cls)
if criterion:
query = query.filter_by(**criterion)
try:
result = query.all()
except exc.NoResultFound:
LOG.debug('No results found querying for %s: %s' %
(cls, criterion))
return []
else:
return result
def _get(self, cls, identifier, by_name=False):
"""
Get an instance of a Model matching ID
:param cls: The model to try to get
:param identifier: The ID to get
:param by_name: Search by name as well as ID
"""
filters = [cls.id == identifier]
if by_name:
filters.append(cls.name == identifier)
query = self.session.query(cls)\
.filter(or_(*filters))
try:
obj = query.one()
except exc.NoResultFound:
raise exceptions.NotFound(identifier)
return obj
def _get_id_or_name(self, *args, **kw):
"""
Same as _get but with by_name on ass default
"""
kw['by_name'] = True
return self._get(*args, **kw)
def _update(self, cls, id_, values):
"""
Update an instance of a Model matching an ID with values
:param cls: The model to try to update
:param id_: The ID to update
:param values: The values to update the model instance with
"""
obj = self._get(cls, id_)
obj.update(values)
try:
obj.save(self.session)
except exceptions.Duplicate:
raise
return obj
def _delete(self, cls, id_):
"""
Delete an instance of a Model matching an ID
:param cls: The model to try to delete
:param id_: The ID to delete
"""
obj = self._get(cls, id_)
obj.delete(self.session)
def _get_row(self, obj, cls=None, **kw):
"""
Used to either check that passed 'obj' is a ModelBase inheriting object
and just return it
:param obj: ID or instance / ref of the object
:param cls: The class to run self._get on if obj is not a ref
"""
if isinstance(obj, ModelBase):
return obj
elif isinstance(obj, basestring) and cls:
return self._get(cls, obj)
else:
msg = 'Missing obj and/or obj and cls...'
raise exceptions.BadRequest(msg)
def _make_rel_row(self, row, rel_attr, values):
"""
Get the class of the relation attribute in 'rel_attr' and make a
row from values with it.
:param row: A instance of ModelBase
:param rel_attr: The relation attribute
:param values: The values to create the new row from
"""
cls = row.__mapper__.get_property(rel_attr).mapper.class_
return cls(**values)
def _dict(self, row, extra=[]):
data = dict(row)
for key in extra:
if isinstance(row[key], list):
data[key] = map(dict, row[key])
else:
data[key] = dict(row[key])
return data
def _kv_rows(self, rows, key='name', func=lambda i: i):
"""
Return a Key, Value dict where the "key" will be the key and the row as value
"""
data = {}
for row in rows:
if callable(key):
data_key = key(row)
else:
data_key = row[key]
data[data_key] = func(row)
return data

View File

@ -11,13 +11,12 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from sqlalchemy import or_
from sqlalchemy.orm import exc
from oslo.config import cfg
from billingstack.openstack.common import log as logging
from billingstack import exceptions
from billingstack import utils as common_utils
from billingstack.sqlalchemy import utils as db_utils
from billingstack.sqlalchemy import utils as db_utils, api
from billingstack.storage import base
from billingstack.storage.impl_sqlalchemy import models
from billingstack.storage.impl_sqlalchemy.session import get_session, SQLOPTS
@ -39,7 +38,7 @@ class SQLAlchemyStorage(base.StorageEngine):
return Connection(self.name)
class Connection(base.Connection):
class Connection(base.Connection, api.HelpersMixin):
"""
SQLAlchemy connection
"""
@ -54,142 +53,6 @@ class Connection(base.Connection):
""" Semi-Private Method to reset the database schema """
models.BASE.metadata.drop_all(self.session.bind)
def _save(self, obj, save=True):
if not save:
return obj
try:
obj.save(self.session)
except exceptions.Duplicate:
raise
def _list(self, cls=None, query=None, criterion=None):
"""
A generic list method
:param cls: The model to try to delete
:param criterion: Criterion to match objects with
"""
if not cls and not query:
raise ValueError("Need either cls or query")
query = query or self.session.query(cls)
if criterion:
query = query.filter_by(**criterion)
try:
result = query.all()
except exc.NoResultFound:
LOG.debug('No results found querying for %s: %s' %
(cls, criterion))
return []
else:
return result
def _get(self, cls, identifier, by_name=False):
"""
Get an instance of a Model matching ID
:param cls: The model to try to get
:param identifier: The ID to get
:param by_name: Search by name as well as ID
"""
filters = [cls.id == identifier]
if by_name:
filters.append(cls.name == identifier)
query = self.session.query(cls)\
.filter(or_(*filters))
try:
obj = query.one()
except exc.NoResultFound:
raise exceptions.NotFound(identifier)
return obj
def _get_id_or_name(self, *args, **kw):
"""
Same as _get but with by_name on ass default
"""
kw['by_name'] = True
return self._get(*args, **kw)
def _update(self, cls, id_, values):
"""
Update an instance of a Model matching an ID with values
:param cls: The model to try to update
:param id_: The ID to update
:param values: The values to update the model instance with
"""
obj = self._get(cls, id_)
obj.update(values)
try:
obj.save(self.session)
except exceptions.Duplicate:
raise
return obj
def _delete(self, cls, id_):
"""
Delete an instance of a Model matching an ID
:param cls: The model to try to delete
:param id_: The ID to delete
"""
obj = self._get(cls, id_)
obj.delete(self.session)
def _get_row(self, obj, cls=None, **kw):
"""
Used to either check that passed 'obj' is a ModelBase inheriting object
and just return it
:param obj: ID or instance / ref of the object
:param cls: The class to run self._get on if obj is not a ref
"""
if isinstance(obj, models.ModelBase):
return obj
elif isinstance(obj, basestring) and cls:
return self._get(cls, obj)
else:
msg = 'Missing obj and/or obj and cls...'
raise exceptions.BadRequest(msg)
def _make_rel_row(self, row, rel_attr, values):
"""
Get the class of the relation attribute in 'rel_attr' and make a
row from values with it.
:param row: A instance of ModelBase
:param rel_attr: The relation attribute
:param values: The values to create the new row from
"""
cls = row.__mapper__.get_property(rel_attr).mapper.class_
return cls(**values)
def _dict(self, row, extra=[]):
data = dict(row)
for key in extra:
if isinstance(row[key], list):
data[key] = map(dict, row[key])
else:
data[key] = dict(row[key])
return data
def _kv_rows(self, rows, key='name', func=lambda i: i):
"""
Return a Key, Value dict where the "key" will be the key and the row as value
"""
data = {}
for row in rows:
if callable(key):
data_key = key(row)
else:
data_key = row[key]
data[data_key] = func(row)
return data
def set_properties(self, obj, properties, cls=None, rel_attr='properties', purge=False):
"""
Set's a dict with key values on a relation on the row