Use built-in oslo_db types for Columns serialized as dicts
This commit makes the following changes: * removes unncessary code (timeutils, oslo_utils.timeutils can be used instead) * oslo_db.types.JsonEncodedDict can be used instead of a custom JSONEncodedDict (forces Deckhand to save an actual dict in the DB as well) * oslo_db.types.JsonEncodedList used for new `results` Column in Revisions table
This commit is contained in:
parent
8e43f91751
commit
3bc589e7fc
@ -1,88 +0,0 @@
|
||||
# Copyright 2017 AT&T Intellectual Property. All other 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.
|
||||
|
||||
"""
|
||||
Time related utilities and helper functions.
|
||||
"""
|
||||
|
||||
import datetime
|
||||
|
||||
import iso8601
|
||||
from monotonic import monotonic as now # noqa
|
||||
from oslo_utils import encodeutils
|
||||
|
||||
# ISO 8601 extended time format with microseconds
|
||||
_ISO8601_TIME_FORMAT_SUBSECOND = '%Y-%m-%dT%H:%M:%S.%f'
|
||||
_ISO8601_TIME_FORMAT = '%Y-%m-%dT%H:%M:%S'
|
||||
PERFECT_TIME_FORMAT = _ISO8601_TIME_FORMAT_SUBSECOND
|
||||
|
||||
|
||||
def isotime(at=None, subsecond=False):
|
||||
"""Stringify time in ISO 8601 format."""
|
||||
if not at:
|
||||
at = utcnow()
|
||||
st = at.strftime(_ISO8601_TIME_FORMAT
|
||||
if not subsecond
|
||||
else _ISO8601_TIME_FORMAT_SUBSECOND)
|
||||
tz = at.tzinfo.tzname(None) if at.tzinfo else 'UTC'
|
||||
st += ('Z' if tz == 'UTC' else tz)
|
||||
return st
|
||||
|
||||
|
||||
def parse_isotime(timestr):
|
||||
"""Parse time from ISO 8601 format."""
|
||||
try:
|
||||
return iso8601.parse_date(timestr)
|
||||
except iso8601.ParseError as e:
|
||||
raise ValueError(encodeutils.exception_to_unicode(e))
|
||||
except TypeError as e:
|
||||
raise ValueError(encodeutils.exception_to_unicode(e))
|
||||
|
||||
|
||||
def utcnow(with_timezone=False):
|
||||
"""Overridable version of utils.utcnow that can return a TZ-aware datetime.
|
||||
"""
|
||||
if utcnow.override_time:
|
||||
try:
|
||||
return utcnow.override_time.pop(0)
|
||||
except AttributeError:
|
||||
return utcnow.override_time
|
||||
if with_timezone:
|
||||
return datetime.datetime.now(tz=iso8601.iso8601.UTC)
|
||||
return datetime.datetime.utcnow()
|
||||
|
||||
|
||||
def normalize_time(timestamp):
|
||||
"""Normalize time in arbitrary timezone to UTC naive object."""
|
||||
offset = timestamp.utcoffset()
|
||||
if offset is None:
|
||||
return timestamp
|
||||
return timestamp.replace(tzinfo=None) - offset
|
||||
|
||||
|
||||
def iso8601_from_timestamp(timestamp, microsecond=False):
|
||||
"""Returns an iso8601 formatted date from timestamp."""
|
||||
return isotime(datetime.datetime.utcfromtimestamp(timestamp), microsecond)
|
||||
|
||||
utcnow.override_time = None
|
||||
|
||||
|
||||
def delta_seconds(before, after):
|
||||
"""Return the difference between two timing objects.
|
||||
|
||||
Compute the difference in seconds between two date, time, or
|
||||
datetime objects (as a float, to microsecond resolution).
|
||||
"""
|
||||
delta = after - before
|
||||
return datetime.timedelta.total_seconds(delta)
|
@ -15,8 +15,7 @@
|
||||
import uuid
|
||||
|
||||
from oslo_db.sqlalchemy import models
|
||||
from oslo_log import log as logging
|
||||
from oslo_serialization import jsonutils as json
|
||||
from oslo_db.sqlalchemy import types as oslo_types
|
||||
from oslo_utils import timeutils
|
||||
from sqlalchemy import Boolean
|
||||
from sqlalchemy import Column
|
||||
@ -31,38 +30,12 @@ from sqlalchemy import String
|
||||
from sqlalchemy import Text
|
||||
from sqlalchemy.types import TypeDecorator
|
||||
|
||||
from deckhand.common import timeutils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
# Declarative base class which maintains a catalog of classes and tables
|
||||
# relative to that base.
|
||||
BASE = declarative.declarative_base()
|
||||
|
||||
|
||||
class JSONEncodedDict(TypeDecorator):
|
||||
"""Represents an immutable structure as a json-encoded string.
|
||||
|
||||
Usage::
|
||||
|
||||
JSONEncodedDict(255)
|
||||
|
||||
"""
|
||||
|
||||
impl = Text
|
||||
|
||||
def process_bind_param(self, value, dialect):
|
||||
if value is not None:
|
||||
value = json.dumps(value)
|
||||
|
||||
return value
|
||||
|
||||
def process_result_value(self, value, dialect):
|
||||
if value is not None:
|
||||
value = json.loads(value)
|
||||
return value
|
||||
|
||||
|
||||
class DeckhandBase(models.ModelBase, models.TimestampMixin):
|
||||
"""Base class for Deckhand Models."""
|
||||
|
||||
@ -133,6 +106,7 @@ class Revision(BASE, DeckhandBase):
|
||||
default=lambda: str(uuid.uuid4()))
|
||||
parent_id = Column(Integer, ForeignKey('revisions.id'), nullable=True)
|
||||
child_id = Column(Integer, ForeignKey('revisions.id'), nullable=True)
|
||||
results = Column(oslo_types.JsonEncodedList(), nullable=True)
|
||||
|
||||
documents = relationship("Document")
|
||||
|
||||
@ -154,8 +128,8 @@ class Document(BASE, DeckhandBase):
|
||||
# NOTE: Do not define a maximum length for these JSON data below. However,
|
||||
# this approach is not compatible with all database types.
|
||||
# "metadata" is reserved, so use "doc_metadata" instead.
|
||||
_metadata = Column(JSONEncodedDict(), nullable=False)
|
||||
data = Column(JSONEncodedDict(), nullable=False)
|
||||
_metadata = Column(oslo_types.JsonEncodedDict(), nullable=False)
|
||||
data = Column(oslo_types.JsonEncodedDict(), nullable=False)
|
||||
revision_id = Column(Integer, ForeignKey('revisions.id'), nullable=False)
|
||||
|
||||
def to_dict(self, raw_dict=False):
|
||||
|
@ -31,7 +31,9 @@ class DocumentFixture(object):
|
||||
@staticmethod
|
||||
def get_minimal_fixture(**kwargs):
|
||||
fixture = {
|
||||
'data': test_utils.rand_name('data'),
|
||||
'data': {
|
||||
test_utils.rand_name('key'): test_utils.rand_name('value')
|
||||
},
|
||||
'metadata': {
|
||||
'name': test_utils.rand_name('metadata_data'),
|
||||
'label': test_utils.rand_name('metadata_label'),
|
||||
|
Loading…
Reference in New Issue
Block a user