diff options
| author | Eric Windisch <eric@cloudscaling.com> | 2012-12-04 10:40:10 -0500 |
|---|---|---|
| committer | Mark McLoughlin <markmc@redhat.com> | 2013-02-05 10:50:12 +0000 |
| commit | 13a9e6dca7742493253d5b9b4bedb01d07fb242d (patch) | |
| tree | 08455b67bf0e13593ad34260eb7fd7dd71ff36f9 /openstack/common/db/sqlalchemy/models.py | |
| parent | bd5d9f08ecc3c1fade6dce809ee9edef1c226e54 (diff) | |
| download | oslo-13a9e6dca7742493253d5b9b4bedb01d07fb242d.tar.gz oslo-13a9e6dca7742493253d5b9b4bedb01d07fb242d.tar.xz oslo-13a9e6dca7742493253d5b9b4bedb01d07fb242d.zip | |
Import sqlalchemy session/models/utils
Bring in session, base model, utilities, and tests for sqlalchemy
from Nova.
Add sqlalchemy to pip-requires and and python-mysql to test-requires.
Partially implements blueprint common-db
Change-Id: I3e0065cdac87e10c4e0742d66c293c72bb3acbb2
Diffstat (limited to 'openstack/common/db/sqlalchemy/models.py')
| -rw-r--r-- | openstack/common/db/sqlalchemy/models.py | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/openstack/common/db/sqlalchemy/models.py b/openstack/common/db/sqlalchemy/models.py new file mode 100644 index 0000000..e2eee28 --- /dev/null +++ b/openstack/common/db/sqlalchemy/models.py @@ -0,0 +1,103 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright (c) 2011 X.commerce, a business unit of eBay Inc. +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# Copyright 2011 Piston Cloud Computing, Inc. +# Copyright 2012 Cloudscaling Group, Inc. +# All Rights Reserved. +# +# 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. +""" +SQLAlchemy models. +""" + +from sqlalchemy import Column, Boolean +from sqlalchemy import DateTime +from sqlalchemy.orm import object_mapper + +from openstack.common.db.sqlalchemy.session import get_session +from openstack.common import timeutils + + +class ModelBase(object): + """Base class for models.""" + __table_initialized__ = False + created_at = Column(DateTime, default=timeutils.utcnow) + updated_at = Column(DateTime, onupdate=timeutils.utcnow) + metadata = None + + def save(self, session=None): + """Save this object.""" + if not session: + session = get_session() + # NOTE(boris-42): This part of code should be look like: + # sesssion.add(self) + # session.flush() + # But there is a bug in sqlalchemy and eventlet that + # raises NoneType exception if there is no running + # transaction and rollback is called. As long as + # sqlalchemy has this bug we have to create transaction + # explicity. + with session.begin(subtransactions=True): + session.add(self) + session.flush() + + def __setitem__(self, key, value): + setattr(self, key, value) + + def __getitem__(self, key): + return getattr(self, key) + + def get(self, key, default=None): + return getattr(self, key, default) + + 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 SoftDeleteMixin(object): + deleted_at = Column(DateTime) + deleted = Column(Boolean, default=False) + + def soft_delete(self, session=None): + """Mark this object as deleted.""" + self.deleted = True + self.deleted_at = timeutils.utcnow() + self.save(session=session) |
