From: Mike Bayer Date: Thu, 29 Jan 2009 16:19:51 +0000 (+0000) Subject: - dialect.type_descriptor() becomes a classmethod X-Git-Tag: rel_0_6_6~314 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2cae5b2438867e0b56647e8522ac37a93c85f8bc;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - dialect.type_descriptor() becomes a classmethod - TypeEngine caches types in impl_dict per dialect class [ticket:1299] --- diff --git a/06CHANGES b/06CHANGES index 61637907d8..f4baaf3602 100644 --- a/06CHANGES +++ b/06CHANGES @@ -12,7 +12,8 @@ - server_version_info becomes a static attribute. - create_engine() now establishes an initial connection immediately upon creation, which is passed to the dialect to determine connection properties. - + - cached TypeEngine classes are cached per-dialect class instead of per-dialect. + - mysql - all the _detect_XXX() functions now run once underneath dialect.initialize() diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py index f0432e16db..5730563701 100644 --- a/lib/sqlalchemy/engine/base.py +++ b/lib/sqlalchemy/engine/base.py @@ -135,15 +135,17 @@ class Dialect(object): raise NotImplementedError() - def type_descriptor(self, typeobj): - """Transform a generic type to a database-specific type. + @classmethod + def type_descriptor(cls, typeobj): + """Transform a generic type to a dialect-specific type. - Transforms the given :class:`~sqlalchemy.types.TypeEngine` instance - from generic to database-specific. - - Subclasses will usually use the + Dialect classes will usually use the :func:`~sqlalchemy.types.adapt_type` method in the types module to make this job easy. + + The returned result is cached *per dialect class* so can + contain no dialect-instance state. + """ raise NotImplementedError() diff --git a/lib/sqlalchemy/engine/default.py b/lib/sqlalchemy/engine/default.py index beec145604..42608b8ac4 100644 --- a/lib/sqlalchemy/engine/default.py +++ b/lib/sqlalchemy/engine/default.py @@ -69,7 +69,8 @@ class DefaultDialect(base.Dialect): self.label_length = label_length self.description_encoding = getattr(self, 'description_encoding', encoding) - def type_descriptor(self, typeobj): + @classmethod + def type_descriptor(cls, typeobj): """Provide a database-specific ``TypeEngine`` object, given the generic object which comes from the types module. @@ -78,7 +79,7 @@ class DefaultDialect(base.Dialect): and passes on to ``types.adapt_type()``. """ - return sqltypes.adapt_type(typeobj, self.colspecs) + return sqltypes.adapt_type(typeobj, cls.colspecs) def validate_identifier(self, ident): if len(ident) > self.max_identifier_length: diff --git a/lib/sqlalchemy/types.py b/lib/sqlalchemy/types.py index 63bd8bfbab..c764feda97 100644 --- a/lib/sqlalchemy/types.py +++ b/lib/sqlalchemy/types.py @@ -108,12 +108,12 @@ class TypeEngine(AbstractType): def dialect_impl(self, dialect, **kwargs): try: - return self._impl_dict[dialect] + return self._impl_dict[dialect.__class__] except AttributeError: self._impl_dict = {} - return self._impl_dict.setdefault(dialect, dialect.type_descriptor(self)) + return self._impl_dict.setdefault(dialect.__class__, dialect.__class__.type_descriptor(self)) except KeyError: - return self._impl_dict.setdefault(dialect, dialect.type_descriptor(self)) + return self._impl_dict.setdefault(dialect.__class__, dialect.__class__.type_descriptor(self)) def __getstate__(self): d = self.__dict__.copy() @@ -232,7 +232,7 @@ class TypeDecorator(AbstractType): def dialect_impl(self, dialect): try: - return self._impl_dict[dialect] + return self._impl_dict[dialect.__class__] except AttributeError: self._impl_dict = {} except KeyError: @@ -241,7 +241,7 @@ class TypeDecorator(AbstractType): # adapt the TypeDecorator first, in # the case that the dialect maps the TD # to one of its native types (i.e. PGInterval) - adapted = dialect.type_descriptor(self) + adapted = dialect.__class__.type_descriptor(self) if adapted is not self: self._impl_dict[dialect] = adapted return adapted @@ -275,7 +275,7 @@ class TypeDecorator(AbstractType): if isinstance(self.impl, TypeDecorator): return self.impl.dialect_impl(dialect) else: - return dialect.type_descriptor(self.impl) + return dialect.__class__.type_descriptor(self.impl) def __getattr__(self, key): """Proxy all other undefined accessors to the underlying implementation.""" diff --git a/test/profiling/memusage.py b/test/profiling/memusage.py index 8bc2825db8..3cb4dfb9fa 100644 --- a/test/profiling/memusage.py +++ b/test/profiling/memusage.py @@ -7,6 +7,8 @@ import operator from testlib import testing from testlib.sa import MetaData, Table, Column, Integer, String, ForeignKey, PickleType from orm import _base +import sqlalchemy as sa +from sqlalchemy.sql import column class A(_base.ComparableEntity): @@ -386,6 +388,15 @@ class MemUsageTest(EnsureZeroed): go() finally: metadata.drop_all() + + def test_type_compile(self): + from sqlalchemy.dialects.sqlite.base import dialect as SQLiteDialect + cast = sa.cast(column('x'), sa.Integer) + @profile_memory + def go(): + dialect = SQLiteDialect() + cast.compile(dialect=dialect) + go() if __name__ == '__main__': testenv.main() diff --git a/test/sql/testtypes.py b/test/sql/testtypes.py index 40ad8814ba..97593f856b 100644 --- a/test/sql/testtypes.py +++ b/test/sql/testtypes.py @@ -12,27 +12,6 @@ from testlib import * class AdaptTest(TestBase): - def testadapt(self): - e1 = url.URL('postgres').get_dialect()() - e2 = url.URL('mysql').get_dialect()() - e3 = url.URL('sqlite').get_dialect()() - e4 = url.URL('firebird').get_dialect()() - - type = String(40) - - t1 = type.dialect_impl(e1) - t2 = type.dialect_impl(e2) - t3 = type.dialect_impl(e3) - t4 = type.dialect_impl(e4) - - impls = [t1, t2, t3, t4] - for i,ta in enumerate(impls): - for j,tb in enumerate(impls): - if i == j: - assert ta == tb # call me paranoid... :) - else: - assert ta != tb - def testmsnvarchar(self): dialect = mssql.dialect() # run the test twice to ensure the caching step works too @@ -86,12 +65,12 @@ class AdaptTest(TestBase): (postgres_dialect, Unicode(), String), (postgres_dialect, UnicodeText(), Text), (postgres_dialect, NCHAR(), String), - (firebird_dialect, String(), firebird.FBString), - (firebird_dialect, VARCHAR(), firebird.FBString), - (firebird_dialect, String(50), firebird.FBString), - (firebird_dialect, Unicode(), firebird.FBString), - (firebird_dialect, UnicodeText(), firebird.FBText), - (firebird_dialect, NCHAR(), firebird.FBString), +# (firebird_dialect, String(), firebird.FBString), +# (firebird_dialect, VARCHAR(), firebird.FBString), +# (firebird_dialect, String(50), firebird.FBString), +# (firebird_dialect, Unicode(), firebird.FBString), +# (firebird_dialect, UnicodeText(), firebird.FBText), +# (firebird_dialect, NCHAR(), firebird.FBString), ]: assert isinstance(start.dialect_impl(dialect), test), "wanted %r got %r" % (test, start.dialect_impl(dialect))