diff options
-rw-r--r-- | lib/sqlalchemy/dialects/drizzle/base.py | 7 | ||||
-rw-r--r-- | lib/sqlalchemy/dialects/mysql/base.py | 9 | ||||
-rw-r--r-- | lib/sqlalchemy/dialects/postgresql/base.py | 4 | ||||
-rw-r--r-- | lib/sqlalchemy/types.py | 49 | ||||
-rw-r--r-- | lib/sqlalchemy/util/langhelpers.py | 23 | ||||
-rw-r--r-- | test/sql/test_types.py | 29 |
6 files changed, 107 insertions, 14 deletions
diff --git a/lib/sqlalchemy/dialects/drizzle/base.py b/lib/sqlalchemy/dialects/drizzle/base.py index efad13549..3966c7dde 100644 --- a/lib/sqlalchemy/dialects/drizzle/base.py +++ b/lib/sqlalchemy/dialects/drizzle/base.py @@ -263,6 +263,13 @@ class CHAR(_StringType, sqltypes.CHAR): class ENUM(mysql_dialect.ENUM): """Drizzle ENUM type.""" + __kwargs_signature__ = ( + ('strict', False), + ('collation', None), + ('binary', False), + ('quoting', 'unquoted'), + ) + def __init__(self, *enums, **kw): """Construct an ENUM. diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py index d5e33c802..61b7c1b17 100644 --- a/lib/sqlalchemy/dialects/mysql/base.py +++ b/lib/sqlalchemy/dialects/mysql/base.py @@ -977,6 +977,15 @@ class ENUM(sqltypes.Enum, _StringType): """MySQL ENUM type.""" __visit_name__ = 'ENUM' + __kwargs_signature__ = ( + ('strict', False), + ('charset', None), + ('collation', None), + ('ascii', False), + ('unicode', False), + ('binary', False), + ('quoting', 'unquoted'), + ) def __init__(self, *enums, **kw): """Construct an ENUM. diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py index dc6e30b81..8fd5e411a 100644 --- a/lib/sqlalchemy/dialects/postgresql/base.py +++ b/lib/sqlalchemy/dialects/postgresql/base.py @@ -763,6 +763,10 @@ class ENUM(sqltypes.Enum): """ + __kwargs_signature__ = ( + ('create_type', True), + ) + def __init__(self, *enums, **kw): """Construct an :class:`~.postgresql.ENUM`. diff --git a/lib/sqlalchemy/types.py b/lib/sqlalchemy/types.py index bfff05362..a087ddae6 100644 --- a/lib/sqlalchemy/types.py +++ b/lib/sqlalchemy/types.py @@ -878,7 +878,7 @@ class Variant(TypeDecorator): """ - def __init__(self, base, mapping): + def __init__(self, base, mapping, active_dialect=None): """Construct a new :class:`.Variant`. :param base: the base 'fallback' type @@ -888,6 +888,15 @@ class Variant(TypeDecorator): """ self.impl = base self.mapping = mapping + if not active_dialect: + if len(self.mapping) > 1: + raise exc.ArgumentError( + 'If a mapping has multiple dialects, an active_dialect ' + 'must be specified.') + else: + self.active_dialect = self.mapping.keys()[0] + else: + self.active_dialect = active_dialect def load_dialect_impl(self, dialect): if dialect.name in self.mapping: @@ -914,7 +923,15 @@ class Variant(TypeDecorator): "the mapping for this Variant" % dialect_name) mapping = self.mapping.copy() mapping[dialect_name] = type_ - return Variant(self.impl, mapping) + active_dialect = dialect_name if len(mapping.keys()) > 1 else None + return Variant(self.impl, mapping, active_dialect) + + def __repr__(self): + dialect = __import__('sqlalchemy.dialects.%s' % + (self.active_dialect, ), + fromlist=['base']).dialect + obj = self.load_dialect_impl(dialect) + return util.generic_repr(obj, to_inspect=super(obj.__class__, obj)) def to_instance(typeobj, *arg, **kw): @@ -1243,6 +1260,13 @@ class Unicode(String): """ __visit_name__ = 'unicode' + __kwargs_signature__ = ( + ('length', None), + ('collation', None), + ('convert_unicode', True), + ('unicode_error', None), + ('_warn_on_bytestring', True), + ) def __init__(self, length=None, **kwargs): """ @@ -1271,6 +1295,13 @@ class UnicodeText(Text): """ __visit_name__ = 'unicode_text' + __kwargs_signature__ = ( + ('length', None), + ('collation', None), + ('convert_unicode', True), + ('unicode_error', None), + ('_warn_on_bytestring', True), + ) def __init__(self, length=None, **kwargs): """ @@ -1916,6 +1947,15 @@ class Enum(String, SchemaType): """ __visit_name__ = 'enum' + __kwargs_signature__ = ( + ('convert_unicode', None), + ('metadata', None), + ('name', None), + ('native_enum', True), + ('schema', None), + ('quote', None), + ('inherit_schema', None), + ) def __init__(self, *enums, **kw): """Construct an enum. @@ -1998,10 +2038,7 @@ class Enum(String, SchemaType): SchemaType.__init__(self, **kw) def __repr__(self): - return util.generic_repr(self, [ - ("native_enum", True), - ("name", None) - ]) + return util.generic_repr(self) def _should_create_constraint(self, compiler): return not self.native_enum or \ diff --git a/lib/sqlalchemy/util/langhelpers.py b/lib/sqlalchemy/util/langhelpers.py index 1ff868e01..191474576 100644 --- a/lib/sqlalchemy/util/langhelpers.py +++ b/lib/sqlalchemy/util/langhelpers.py @@ -342,16 +342,22 @@ def unbound_method_to_callable(func_or_cls): return func_or_cls -def generic_repr(obj, additional_kw=(), to_inspect=None): +def generic_repr(obj, to_inspect=None): """Produce a __repr__() based on direct association of the __init__() specification vs. same-named attributes present. """ - if to_inspect is None: - to_inspect = obj - missing = object() + # if a type uses **kwargs, it should give tuples of its expected + # argument names and default values in __kwargs_signature__ + additional_kw = getattr(obj, "__kwargs_signature__", ()) + if to_inspect: + if hasattr(to_inspect, "__kwargs_signature__"): + additional_kw += getattr(to_inspect, "__kwargs_signature__") + else: + to_inspect = obj + def genargs(): try: (args, vargs, vkw, defaults) = \ @@ -364,8 +370,6 @@ def generic_repr(obj, additional_kw=(), to_inspect=None): if not default_len: for arg in args[1:]: yield repr(getattr(obj, arg, None)) - if vargs is not None and hasattr(obj, vargs): - yield ', '.join(repr(val) for val in getattr(obj, vargs)) else: for arg in args[1:-default_len]: yield repr(getattr(obj, arg, None)) @@ -376,7 +380,10 @@ def generic_repr(obj, additional_kw=(), to_inspect=None): yield '%s=%r' % (arg, val) except: pass - if additional_kw: + if vargs is not None: + if hasattr(obj, vargs): + yield ', '.join(repr(val) for val in getattr(obj, vargs)) + if len(additional_kw): for arg, defval in additional_kw: try: val = getattr(obj, arg, missing) @@ -384,7 +391,7 @@ def generic_repr(obj, additional_kw=(), to_inspect=None): yield '%s=%r' % (arg, val) except: pass - + return "%s(%s)" % (obj.__class__.__name__, ", ".join(genargs())) diff --git a/test/sql/test_types.py b/test/sql/test_types.py index dbb475b98..268acd205 100644 --- a/test/sql/test_types.py +++ b/test/sql/test_types.py @@ -655,6 +655,35 @@ class VariantTest(fixtures.TestBase, AssertsCompiledSQL): 'fooUTWO' ) + def test_repr(self): + test_objects = ( + (types.String().with_variant( + dialects.mysql.VARCHAR(32, collation='foo', ascii=True), + 'mysql'), + "VARCHAR(collation='foo', ascii=True)"), + (types.Enum('red', 'green', 'blue').with_variant( + dialects.postgresql.ENUM( + 'red', 'green', 'blue', name="rgb_enum", create_type=False), + 'postgresql'), + "ENUM('red', 'green', 'blue', create_type=False, convert_unicode=" + "False, name='rgb_enum', inherit_schema=False)"), + (types.Enum('red', 'green', 'blue').with_variant( + dialects.drizzle.ENUM('red', 'green', 'blue', unicode=True), + 'drizzle'), + "ENUM('red', 'green', 'blue', unicode=True)"), + (types.Integer().with_variant( + dialects.mssql.TINYINT(), + 'mssql'), + "TINYINT()"), + (types.Numeric().with_variant( + dialects.oracle.NUMBER(precision='10', scale='4'), + 'oracle'), + "NUMBER(precision='10', scale='4')") + ) + for obj, result in test_objects: + eq_(repr(obj), result) + + class UnicodeTest(fixtures.TestBase): """Exercise the Unicode and related types. |