Move out to HelpersMixin
This commit is contained in:
parent
b65342c86b
commit
ff5766e398
144
billingstack/sqlalchemy/api.py
Normal file
144
billingstack/sqlalchemy/api.py
Normal 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
|
||||||
|
|
@ -11,13 +11,12 @@
|
|||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
from sqlalchemy import or_
|
|
||||||
from sqlalchemy.orm import exc
|
from sqlalchemy.orm import exc
|
||||||
from oslo.config import cfg
|
from oslo.config import cfg
|
||||||
from billingstack.openstack.common import log as logging
|
from billingstack.openstack.common import log as logging
|
||||||
from billingstack import exceptions
|
from billingstack import exceptions
|
||||||
from billingstack import utils as common_utils
|
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 import base
|
||||||
from billingstack.storage.impl_sqlalchemy import models
|
from billingstack.storage.impl_sqlalchemy import models
|
||||||
from billingstack.storage.impl_sqlalchemy.session import get_session, SQLOPTS
|
from billingstack.storage.impl_sqlalchemy.session import get_session, SQLOPTS
|
||||||
@ -39,7 +38,7 @@ class SQLAlchemyStorage(base.StorageEngine):
|
|||||||
return Connection(self.name)
|
return Connection(self.name)
|
||||||
|
|
||||||
|
|
||||||
class Connection(base.Connection):
|
class Connection(base.Connection, api.HelpersMixin):
|
||||||
"""
|
"""
|
||||||
SQLAlchemy connection
|
SQLAlchemy connection
|
||||||
"""
|
"""
|
||||||
@ -54,142 +53,6 @@ class Connection(base.Connection):
|
|||||||
""" Semi-Private Method to reset the database schema """
|
""" Semi-Private Method to reset the database schema """
|
||||||
models.BASE.metadata.drop_all(self.session.bind)
|
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):
|
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
|
Set's a dict with key values on a relation on the row
|
||||||
|
Loading…
x
Reference in New Issue
Block a user