From c4843bcf1479f1a4b1438af5a4a314ce1aaaae72 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Thu, 10 Aug 2017 17:21:46 -0400 Subject: Workaround non-compatible type.adapt() for SQLAlchemy < 1.1 The ndb change that makes use of String.adapt() to produce a new object breaks on SQLAlchemy < 1.1 because adapt() there does not allow for kwargs to override those already present in the type. Change-Id: I8cc79dc9bebcb3cb3accf76559bc969c2dae7ed9 --- oslo_db/sqlalchemy/compat/utils.py | 24 ++++++++++++++++++++++++ oslo_db/sqlalchemy/ndb.py | 5 +++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/oslo_db/sqlalchemy/compat/utils.py b/oslo_db/sqlalchemy/compat/utils.py index e34e70f..1d27a56 100644 --- a/oslo_db/sqlalchemy/compat/utils.py +++ b/oslo_db/sqlalchemy/compat/utils.py @@ -43,3 +43,27 @@ def get_postgresql_enums(conn): return [e['name'] for e in sqlalchemy.inspect(conn).get_enums()] else: return conn.dialect._load_enums(conn).keys() + + +def adapt_type_object(type_object, target_class, *args, **kw): + """Call the adapt() method on a type. + + For SQLAlchemy 1.0, runs a local version of constructor_copy() that + allows keyword arguments to be overridden. + + See https://github.com/zzzeek/sqlalchemy/commit/\ + ceeb033054f09db3eccbde3fad1941ec42919a54 + + """ + if sqla_110: + return type_object.adapt(target_class, *args, **kw) + else: + # NOTE(zzzeek): this only works for basic types, won't work for + # schema types like Enum, Boolean + # NOTE(zzzeek): this code can be removed once requirements + # are at SQLAlchemy >= 1.1 + names = sqlalchemy.util.get_cls_kwargs(target_class) + kw.update( + (k, type_object.__dict__[k]) for k in names.difference(kw) + if k in type_object.__dict__) + return target_class(*args, **kw) diff --git a/oslo_db/sqlalchemy/ndb.py b/oslo_db/sqlalchemy/ndb.py index e48c569..a3927cc 100644 --- a/oslo_db/sqlalchemy/ndb.py +++ b/oslo_db/sqlalchemy/ndb.py @@ -17,6 +17,7 @@ import re import debtcollector.removals +from oslo_db.sqlalchemy.compat import utils as compat_utils from oslo_db.sqlalchemy.types import String from sqlalchemy import event, schema @@ -103,8 +104,8 @@ def _compile_ndb_string(element, compiler, **kw): return compiler.visit_string(element, **kw) if element.mysql_ndb_length: - effective_type = element.adapt( - _String, length=element.mysql_ndb_length) + effective_type = compat_utils.adapt_type_object( + element, _String, length=element.mysql_ndb_length) return compiler.visit_string(effective_type, **kw) elif element.mysql_ndb_type: effective_type = to_instance(element.mysql_ndb_type) -- cgit v1.2.1