From: Mike Bayer Date: Thu, 25 Feb 2010 22:00:58 +0000 (+0000) Subject: - The assert_unicode flag is deprecated. SQLAlchemy will raise X-Git-Tag: rel_0_6beta2~122 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=756370e0b43a20ae30ed03cb30762756c97fb258;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - The assert_unicode flag is deprecated. SQLAlchemy will raise a warning in all cases where it is asked to encode a non-unicode Python string, and will do nothing for DBAPIs that already accept Python unicode objects. --- diff --git a/CHANGES b/CHANGES index ab0c14fffa..7c33f62398 100644 --- a/CHANGES +++ b/CHANGES @@ -181,6 +181,11 @@ CHANGES Note that it is *not* built/installed by default. See README for installation instructions. + - The assert_unicode flag is deprecated. SQLAlchemy will raise + a warning in all cases where it is asked to encode a non-unicode + Python string, and will do nothing for DBAPIs that already + accept Python unicode objects. + - metadata - Added the ability to strip schema information when using "tometadata" by passing "schema=None" as an argument. If schema diff --git a/lib/sqlalchemy/dialects/mssql/base.py b/lib/sqlalchemy/dialects/mssql/base.py index facb16490a..1ce3cbde8c 100644 --- a/lib/sqlalchemy/dialects/mssql/base.py +++ b/lib/sqlalchemy/dialects/mssql/base.py @@ -489,16 +489,6 @@ class VARCHAR(_StringType, sqltypes.VARCHAR): If False, may be overridden by :attr:`sqlalchemy.engine.base.Dialect.convert_unicode`. - :param assert_unicode: - - If None (the default), no assertion will take place unless - overridden by :attr:`sqlalchemy.engine.base.Dialect.assert_unicode`. - - If 'warn', will issue a runtime warning if a ``str`` - instance is used as a bind value. - - If true, will raise an :exc:`sqlalchemy.exc.InvalidRequestError`. - :param collation: Optional, a column-level collation for this string value. Accepts a Windows Collation Name or a SQL Collation Name. @@ -546,16 +536,6 @@ class CHAR(_StringType, sqltypes.CHAR): If False, may be overridden by :attr:`sqlalchemy.engine.base.Dialect.convert_unicode`. - :param assert_unicode: - - If None (the default), no assertion will take place unless - overridden by :attr:`sqlalchemy.engine.base.Dialect.assert_unicode`. - - If 'warn', will issue a runtime warning if a ``str`` - instance is used as a bind value. - - If true, will raise an :exc:`sqlalchemy.exc.InvalidRequestError`. - :param collation: Optional, a column-level collation for this string value. Accepts a Windows Collation Name or a SQL Collation Name. diff --git a/lib/sqlalchemy/engine/__init__.py b/lib/sqlalchemy/engine/__init__.py index d04907db82..137218c2c0 100644 --- a/lib/sqlalchemy/engine/__init__.py +++ b/lib/sqlalchemy/engine/__init__.py @@ -119,12 +119,12 @@ def create_engine(*args, **kwargs): are unique to that dialect. Here, we describe the parameters that are common to most ``create_engine()`` usage. - :param assert_unicode=False: When set to ``True`` alongside - convert_unicode=``True``, asserts that incoming string bind - parameters are instances of ``unicode``, otherwise raises an - error. Only takes effect when ``convert_unicode==True``. This - flag is also available on the ``String`` type and its - descendants. New in 0.4.2. + :param assert_unicode: Deprecated. A warning is raised in all cases when a non-Unicode + object is passed when SQLAlchemy would coerce into an encoding + (note: but **not** when the DBAPI handles unicode objects natively). + To suppress or raise this warning to an + error, use the Python warnings filter documented at: + http://docs.python.org/library/warnings.html :param connect_args: a dictionary of options which will be passed directly to the DBAPI's ``connect()`` method as diff --git a/lib/sqlalchemy/engine/default.py b/lib/sqlalchemy/engine/default.py index 44c9689423..5499b34e75 100644 --- a/lib/sqlalchemy/engine/default.py +++ b/lib/sqlalchemy/engine/default.py @@ -78,7 +78,14 @@ class DefaultDialect(base.Dialect): "The %s dialect is not yet ported to SQLAlchemy 0.6" % self.name) self.convert_unicode = convert_unicode - self.assert_unicode = assert_unicode + if assert_unicode: + util.warn_deprecated("assert_unicode is deprecated. " + "SQLAlchemy emits a warning in all cases where it " + "would otherwise like to encode a Python unicode object " + "into a specific encoding but a plain bytestring is received. " + "This does *not* apply to DBAPIs that coerce Unicode natively." + ) + self.encoding = encoding self.positional = False self._ischema = None diff --git a/lib/sqlalchemy/types.py b/lib/sqlalchemy/types.py index 49ee3dbf33..aed17e67e4 100644 --- a/lib/sqlalchemy/types.py +++ b/lib/sqlalchemy/types.py @@ -500,7 +500,8 @@ class String(Concatenable, TypeEngine): __visit_name__ = 'string' - def __init__(self, length=None, convert_unicode=False, assert_unicode=None, unicode_error=None): + def __init__(self, length=None, convert_unicode=False, + assert_unicode=None, unicode_error=None): """ Create a string-holding type. @@ -511,42 +512,36 @@ class String(Concatenable, TypeEngine): the ``CREATE TABLE`` DDL is issued. Whether the value is interpreted as bytes or characters is database specific. - :param convert_unicode: defaults to False. If True, convert - ``unicode`` data sent to the database to a ``str`` - bytestring, and convert bytestrings coming back from the - database into ``unicode``. - - Bytestrings are encoded using the dialect's + :param convert_unicode: defaults to False. If True, the + type will do what is necessary in order to accept + Python Unicode objects as bind parameters, and to return + Python Unicode objects in result rows. This may + require SQLAlchemy to explicitly coerce incoming Python + unicodes into an encoding, and from an encoding + back to Unicode, or it may not require any interaction + from SQLAlchemy at all, depending on the DBAPI in use. + + When SQLAlchemy performs the encoding/decoding, + the encoding used is configured via :attr:`~sqlalchemy.engine.base.Dialect.encoding`, which defaults to `utf-8`. - If False, may be overridden by - :attr:`sqlalchemy.engine.base.Dialect.convert_unicode`. + The "convert_unicode" behavior can also be turned on + for all String types by setting + :attr:`sqlalchemy.engine.base.Dialect.convert_unicode` + on create_engine(). - If the DBAPI in use has been detected to return unicode - strings from a VARCHAR result column, the String object will - assume all subsequent results are already unicode objects, and no - type detection will be done to verify this. The - rationale here is that isinstance() calls are enormously - expensive at the level of column-fetching. To - force the check to occur regardless, set - convert_unicode='force'. This will incur significant + To instruct SQLAlchemy to perform Unicode encoding/decoding + even on a platform that already handles Unicode natively, + set convert_unicode='force'. This will incur significant performance overhead when fetching unicode result columns. - Similarly, if the dialect is known to accept bind parameters - as unicode objects, no translation from unicode to bytestring - is performed on binds. Again, encoding to a bytestring can be - forced for special circumstances by setting convert_unicode='force'. - - :param assert_unicode: - - If None (the default), no assertion will take place unless - overridden by :attr:`sqlalchemy.engine.base.Dialect.assert_unicode`. - - If 'warn', will issue a runtime warning if a ``str`` - instance is used as a bind value. - - If true, will raise an :exc:`sqlalchemy.exc.InvalidRequestError`. + :param assert_unicode: Deprecated. A warning is raised in all cases when a non-Unicode + object is passed when SQLAlchemy would coerce into an encoding + (note: but **not** when the DBAPI handles unicode objects natively). + To suppress or raise this warning to an + error, use the Python warnings filter documented at: + http://docs.python.org/library/warnings.html :param unicode_error: Optional, a method to use to handle Unicode conversion errors. Behaves like the 'errors' keyword argument to @@ -565,56 +560,37 @@ class String(Concatenable, TypeEngine): if unicode_error is not None and convert_unicode != 'force': raise exc.ArgumentError("convert_unicode must be 'force' " "when unicode_error is set.") + + if assert_unicode: + util.warn_deprecated("assert_unicode is deprecated. " + "SQLAlchemy emits a warning in all cases where it " + "would otherwise like to encode a Python unicode object " + "into a specific encoding but a plain bytestring is received. " + "This does *not* apply to DBAPIs that coerce Unicode natively." + ) self.length = length self.convert_unicode = convert_unicode - self.assert_unicode = assert_unicode self.unicode_error = unicode_error def adapt(self, impltype): return impltype( length=self.length, - convert_unicode=self.convert_unicode, - assert_unicode=self.assert_unicode) + convert_unicode=self.convert_unicode) def bind_processor(self, dialect): if self.convert_unicode or dialect.convert_unicode: - if self.assert_unicode is None: - assert_unicode = dialect.assert_unicode - else: - assert_unicode = self.assert_unicode - - if dialect.supports_unicode_binds and assert_unicode: - def process(value): - if value is None or isinstance(value, unicode): - return value - else: - if assert_unicode == 'warn': - util.warn("Unicode type received non-unicode bind " - "param value %r" % value) - return value - else: - raise exc.InvalidRequestError( - "Unicode type received non-unicode bind " - "param value %r" % value) - elif dialect.supports_unicode_binds and self.convert_unicode != 'force': + if dialect.supports_unicode_binds and self.convert_unicode != 'force': return None else: encoder = codecs.getencoder(dialect.encoding) def process(value): if isinstance(value, unicode): return encoder(value, self.unicode_error)[0] - elif assert_unicode and value is not None: - if assert_unicode == 'warn': - util.warn("Unicode type received non-unicode bind " - "param value %r" % value) - return value - else: - raise exc.InvalidRequestError( - "Unicode type received non-unicode bind " - "param value %r" % value) - else: - return value + elif value is not None: + util.warn("Unicode type received non-unicode bind " + "param value %r" % value) + return value return process else: return None @@ -669,7 +645,7 @@ class Unicode(String): database back into Python ``unicode`` objects. It's roughly equivalent to using a ``String`` object with - ``convert_unicode=True`` and ``assert_unicode='warn'``, however + ``convert_unicode=True``, however the type has other significances in that it implies the usage of a unicode-capable type being used on the backend, such as NVARCHAR. This may affect what type is emitted when issuing CREATE TABLE @@ -712,7 +688,6 @@ class Unicode(String): """ kwargs.setdefault('convert_unicode', True) - kwargs.setdefault('assert_unicode', 'warn') super(Unicode, self).__init__(length=length, **kwargs) class UnicodeText(Text): @@ -741,7 +716,6 @@ class UnicodeText(Text): """ kwargs.setdefault('convert_unicode', True) - kwargs.setdefault('assert_unicode', 'warn') super(UnicodeText, self).__init__(length=length, **kwargs) @@ -1170,9 +1144,6 @@ class Enum(String, SchemaType): :param \*enums: string or unicode enumeration labels. If unicode labels are present, the `convert_unicode` flag is auto-enabled. - :param assert_unicode: Enable unicode asserts for bind parameter values. - This flag is equivalent to that of ``String``. - :param convert_unicode: Enable unicode-aware bind parameter and result-set processing for this Enum's data. This is set automatically based on the presence of unicode label strings. @@ -1209,7 +1180,6 @@ class Enum(String, SchemaType): self.enums = enums self.native_enum = kw.pop('native_enum', True) convert_unicode= kw.pop('convert_unicode', None) - assert_unicode = kw.pop('assert_unicode', None) if convert_unicode is None: for e in enums: if isinstance(e, unicode): @@ -1225,7 +1195,6 @@ class Enum(String, SchemaType): String.__init__(self, length =length, convert_unicode=convert_unicode, - assert_unicode=assert_unicode ) SchemaType.__init__(self, **kw) @@ -1251,7 +1220,6 @@ class Enum(String, SchemaType): schema=self.schema, metadata=self.metadata, convert_unicode=self.convert_unicode, - assert_unicode=self.assert_unicode, *self.enums ) diff --git a/test/dialect/test_postgresql.py b/test/dialect/test_postgresql.py index 6ab769e513..60022e18a5 100644 --- a/test/dialect/test_postgresql.py +++ b/test/dialect/test_postgresql.py @@ -1329,7 +1329,7 @@ class ArrayTest(TestBase, AssertsExecutionResults): arrtable = Table('arrtable', metadata, Column('id', Integer, primary_key=True), Column('intarr', postgresql.PGArray(Integer)), - Column('strarr', postgresql.PGArray(Unicode(assert_unicode=False)), nullable=False) + Column('strarr', postgresql.PGArray(Unicode()), nullable=False) ) metadata.create_all() diff --git a/test/dialect/test_sqlite.py b/test/dialect/test_sqlite.py index 0012a8acb7..7b428404cb 100644 --- a/test/dialect/test_sqlite.py +++ b/test/dialect/test_sqlite.py @@ -86,10 +86,10 @@ class TestTypes(TestBase, AssertsExecutionResults): CHAR(convert_unicode=True), Unicode(), UnicodeText(), - String(assert_unicode=True, convert_unicode=True), - CHAR(assert_unicode=True, convert_unicode=True), - Unicode(assert_unicode=True), - UnicodeText(assert_unicode=True) + String(convert_unicode=True), + CHAR(convert_unicode=True), + Unicode(), + UnicodeText() ): bindproc = t.dialect_impl(dialect).bind_processor(dialect) diff --git a/test/sql/test_types.py b/test/sql/test_types.py index 27ee8709f8..fb7249ae21 100644 --- a/test/sql/test_types.py +++ b/test/sql/test_types.py @@ -384,39 +384,23 @@ class UnicodeTest(TestBase, AssertsExecutionResults): unicode_table.insert().execute(unicode_varchar=u'') assert select([unicode_table.c.unicode_varchar]).scalar() == u'' - def test_parameters(self): - """test the dialect convert_unicode parameters.""" + def test_unicode_warnings(self): + """test the warnings raised when SQLA must coerce unicode binds.""" unicodedata = u"Alors vous imaginez ma surprise, au lever du jour, quand "\ u"une drôle de petit voix m’a réveillé. "\ u"Elle disait: « S’il vous plaît… dessine-moi un mouton! »" - u = Unicode(assert_unicode=True) - uni = u.dialect_impl(testing.db.dialect).bind_processor(testing.db.dialect) - # Py3K - #assert_raises(exc.InvalidRequestError, uni, b'x') - # Py2K - assert_raises(exc.InvalidRequestError, uni, 'x') - # end Py2K - - u = Unicode() - uni = u.dialect_impl(testing.db.dialect).bind_processor(testing.db.dialect) - # Py3K - #assert_raises(exc.SAWarning, uni, b'x') - # Py2K - assert_raises(exc.SAWarning, uni, 'x') - # end Py2K - - unicode_engine = engines.utf8_engine(options={'convert_unicode':True,'assert_unicode':True}) + unicode_engine = engines.utf8_engine(options={'convert_unicode':True,}) unicode_engine.dialect.supports_unicode_binds = False s = String() uni = s.dialect_impl(unicode_engine.dialect).bind_processor(unicode_engine.dialect) # Py3K - #assert_raises(exc.InvalidRequestError, uni, b'x') + #assert_raises(exc.SAWarning, uni, b'x') #assert isinstance(uni(unicodedata), bytes) # Py2K - assert_raises(exc.InvalidRequestError, uni, 'x') + assert_raises(exc.SAWarning, uni, 'x') assert isinstance(uni(unicodedata), str) # end Py2K @@ -1169,7 +1153,7 @@ class CallableTest(TestBase): meta.drop_all() def test_callable_as_arg(self): - ucode = util.partial(Unicode, assert_unicode=None) + ucode = util.partial(Unicode) thing_table = Table('thing', meta, Column('name', ucode(20)) @@ -1178,7 +1162,7 @@ class CallableTest(TestBase): thing_table.create() def test_callable_as_kwarg(self): - ucode = util.partial(Unicode, assert_unicode=None) + ucode = util.partial(Unicode) thang_table = Table('thang', meta, Column('name', type_=ucode(20), primary_key=True)