Hello community,

here is the log from the commit of package python-SQLAlchemy-Utils for 
openSUSE:Factory checked in at 2017-09-05 15:14:46
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-SQLAlchemy-Utils (Old)
 and      /work/SRC/openSUSE:Factory/.python-SQLAlchemy-Utils.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-SQLAlchemy-Utils"

Tue Sep  5 15:14:46 2017 rev:3 rq:518322 version:0.32.14

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-SQLAlchemy-Utils/python-SQLAlchemy-Utils.changes
  2016-11-24 21:22:41.000000000 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-SQLAlchemy-Utils.new/python-SQLAlchemy-Utils.changes
     2017-09-05 15:14:46.644971447 +0200
@@ -1,0 +2,14 @@
+Wed Aug 23 05:02:53 UTC 2017 - [email protected]
+
+- update to 0.32.14:
+  - Fixed drop_database version comparison
+  - Fixed a DeprecationWarning by using LargeBinary instead of Binary
+  - Added generic_repr decorator
+  - TimeZoneType support for static timezones
+  - Added SQLite support for PasswordType
+  - Added PhoneNumber as the python_type for PhoneNumberType
+  - Made auto_delete_orphans support backref tuples
+  - Added support for multi-column observers
+- convert to singlespec
+
+-------------------------------------------------------------------

Old:
----
  SQLAlchemy-Utils-0.32.9.tar.gz

New:
----
  SQLAlchemy-Utils-0.32.14.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-SQLAlchemy-Utils.spec ++++++
--- /var/tmp/diff_new_pack.xekbdk/_old  2017-09-05 15:14:47.284881499 +0200
+++ /var/tmp/diff_new_pack.xekbdk/_new  2017-09-05 15:14:47.288880936 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-SQLAlchemy-Utils
 #
-# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -16,24 +16,24 @@
 #
 
 
+%{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-SQLAlchemy-Utils
-Version:        0.32.9
+Version:        0.32.14
 Release:        0
 Summary:        Various utility functions for SQLAlchemy
 License:        BSD-3-Clause
 Group:          Development/Languages/Python
 Url:            https://github.com/kvesteri/sqlalchemy-utils
-Source:         
https://pypi.io/packages/source/S/SQLAlchemy-Utils/SQLAlchemy-Utils-%{version}.tar.gz
-BuildRequires:  python-SQLAlchemy
-BuildRequires:  python-devel
-BuildRequires:  python-setuptools
+Source:         
https://files.pythonhosted.org/packages/source/S/SQLAlchemy-Utils/SQLAlchemy-Utils-%{version}.tar.gz
+BuildRequires:  %{python_module SQLAlchemy}
+BuildRequires:  %{python_module devel}
+BuildRequires:  %{python_module setuptools}
+BuildRequires:  python-rpm-macros
 Requires:       python-SQLAlchemy
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
-%if 0%{?suse_version} && 0%{?suse_version} <= 1110
-%{!?python_sitelib: %global python_sitelib %(python -c "from 
distutils.sysconfig import get_python_lib; print get_python_lib()")}
-%else
 BuildArch:      noarch
-%endif
+
+%python_subpackages
 
 %description
 Various utility functions and custom data types for SQLAlchemy.
@@ -42,12 +42,12 @@
 %setup -q -n SQLAlchemy-Utils-%{version}
 
 %build
-python setup.py build
+%python_build
 
 %install
-python setup.py install --prefix=%{_prefix} --root=%{buildroot}
+%python_install
 
-%files
+%files %{python_files}
 %defattr(-,root,root,-)
 %doc LICENSE README.rst
 %{python_sitelib}/*

++++++ SQLAlchemy-Utils-0.32.9.tar.gz -> SQLAlchemy-Utils-0.32.14.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SQLAlchemy-Utils-0.32.9/CHANGES.rst 
new/SQLAlchemy-Utils-0.32.14/CHANGES.rst
--- old/SQLAlchemy-Utils-0.32.9/CHANGES.rst     2016-07-17 22:00:14.000000000 
+0200
+++ new/SQLAlchemy-Utils-0.32.14/CHANGES.rst    2017-03-27 15:48:21.000000000 
+0200
@@ -4,6 +4,38 @@
 Here you can see the full list of changes between each SQLAlchemy-Utils 
release.
 
 
+0.32.14 (2017-03-27)
+^^^^^^^^^^^^^^^^^^^^
+
+- Fixed drop_database version comparison
+
+
+0.32.13 (2017-03-12)
+^^^^^^^^^^^^^^^^^^^^
+
+- Fixed a DeprecationWarning by using LargeBinary instead of Binary (#263, 
pull request courtesy of jacquerie)
+
+
+0.32.12 (2016-12-18)
+^^^^^^^^^^^^^^^^^^^^
+
+- Added generic_repr decorator
+
+
+0.32.11 (2016-11-19)
+^^^^^^^^^^^^^^^^^^^^
+
+- TimeZoneType support for static timezones (#244, pull request courtesy of 
fuhrysteve)
+- Added SQLite support for PasswordType (#254, pull request courtesy of frol)
+
+
+0.32.10 (2016-10-20)
+^^^^^^^^^^^^^^^^^^^^
+
+- Added PhoneNumber as the python_type for PhoneNumberType (#248)
+- Made auto_delete_orphans support backref tuples (#234, pull request courtesy 
of vToMy)
+
+
 0.32.9 (2016-07-17)
 ^^^^^^^^^^^^^^^^^^^
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SQLAlchemy-Utils-0.32.9/PKG-INFO 
new/SQLAlchemy-Utils-0.32.14/PKG-INFO
--- old/SQLAlchemy-Utils-0.32.9/PKG-INFO        2016-07-17 22:02:35.000000000 
+0200
+++ new/SQLAlchemy-Utils-0.32.14/PKG-INFO       2017-03-27 15:57:06.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: SQLAlchemy-Utils
-Version: 0.32.9
+Version: 0.32.14
 Summary: Various utility functions for SQLAlchemy.
 Home-page: https://github.com/kvesteri/sqlalchemy-utils
 Author: Konsta Vesterinen, Ryan Leckey, Janne Vanhala, Vesa Uimonen
@@ -24,5 +24,6 @@
 Classifier: Programming Language :: Python :: 3.3
 Classifier: Programming Language :: Python :: 3.4
 Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
 Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
 Classifier: Topic :: Software Development :: Libraries :: Python Modules
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/SQLAlchemy-Utils-0.32.9/SQLAlchemy_Utils.egg-info/PKG-INFO 
new/SQLAlchemy-Utils-0.32.14/SQLAlchemy_Utils.egg-info/PKG-INFO
--- old/SQLAlchemy-Utils-0.32.9/SQLAlchemy_Utils.egg-info/PKG-INFO      
2016-07-17 22:02:34.000000000 +0200
+++ new/SQLAlchemy-Utils-0.32.14/SQLAlchemy_Utils.egg-info/PKG-INFO     
2017-03-27 15:57:05.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: SQLAlchemy-Utils
-Version: 0.32.9
+Version: 0.32.14
 Summary: Various utility functions for SQLAlchemy.
 Home-page: https://github.com/kvesteri/sqlalchemy-utils
 Author: Konsta Vesterinen, Ryan Leckey, Janne Vanhala, Vesa Uimonen
@@ -24,5 +24,6 @@
 Classifier: Programming Language :: Python :: 3.3
 Classifier: Programming Language :: Python :: 3.4
 Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
 Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
 Classifier: Topic :: Software Development :: Libraries :: Python Modules
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/SQLAlchemy-Utils-0.32.9/SQLAlchemy_Utils.egg-info/requires.txt 
new/SQLAlchemy-Utils-0.32.14/SQLAlchemy_Utils.egg-info/requires.txt
--- old/SQLAlchemy-Utils-0.32.9/SQLAlchemy_Utils.egg-info/requires.txt  
2016-07-17 22:02:34.000000000 +0200
+++ new/SQLAlchemy-Utils-0.32.14/SQLAlchemy_Utils.egg-info/requires.txt 
2017-03-27 15:57:05.000000000 +0200
@@ -17,11 +17,13 @@
 cryptography>=0.6
 
 [enum]
+enum34
 
 [intervals]
 intervals>=0.7.1
 
 [ipaddress]
+ipaddr
 
 [password]
 passlib >= 1.6, < 2.0
@@ -49,7 +51,9 @@
 Babel>=1.3
 colour>=0.0.4
 cryptography>=0.6
+enum34
 intervals>=0.7.1
+ipaddr
 passlib >= 1.6, < 2.0
 phonenumbers>=5.9.2
 pytest>=2.7.1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SQLAlchemy-Utils-0.32.9/docs/data_types.rst 
new/SQLAlchemy-Utils-0.32.14/docs/data_types.rst
--- old/SQLAlchemy-Utils-0.32.9/docs/data_types.rst     2016-04-25 
20:10:56.000000000 +0200
+++ new/SQLAlchemy-Utils-0.32.14/docs/data_types.rst    2016-10-20 
08:55:26.000000000 +0200
@@ -63,6 +63,14 @@
 .. autoclass:: Currency
 
 
+EmailType
+---------
+
+.. automodule:: sqlalchemy_utils.types.email
+
+.. autoclass:: EmailType
+
+
 EncryptedType
 -------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SQLAlchemy-Utils-0.32.9/docs/models.rst 
new/SQLAlchemy-Utils-0.32.14/docs/models.rst
--- old/SQLAlchemy-Utils-0.32.9/docs/models.rst 2015-08-16 10:02:59.000000000 
+0200
+++ new/SQLAlchemy-Utils-0.32.14/docs/models.rst        2016-12-18 
10:08:56.000000000 +0100
@@ -8,3 +8,11 @@
 .. module:: sqlalchemy_utils.models
 
 .. autoclass:: Timestamp
+
+
+generic_repr
+------------
+
+.. module:: sqlalchemy_utils.models
+
+.. autofunction:: generic_repr
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SQLAlchemy-Utils-0.32.9/setup.cfg 
new/SQLAlchemy-Utils-0.32.14/setup.cfg
--- old/SQLAlchemy-Utils-0.32.9/setup.cfg       2016-07-17 22:02:35.000000000 
+0200
+++ new/SQLAlchemy-Utils-0.32.14/setup.cfg      2017-03-27 15:57:06.000000000 
+0200
@@ -1,5 +1,5 @@
 [egg_info]
-tag_date = 0
 tag_build = 
+tag_date = 0
 tag_svn_revision = 0
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SQLAlchemy-Utils-0.32.9/setup.py 
new/SQLAlchemy-Utils-0.32.14/setup.py
--- old/SQLAlchemy-Utils-0.32.9/setup.py        2016-04-20 14:29:57.000000000 
+0200
+++ new/SQLAlchemy-Utils-0.32.14/setup.py       2017-03-27 15:50:45.000000000 
+0200
@@ -91,6 +91,7 @@
         'Programming Language :: Python :: 3.3',
         'Programming Language :: Python :: 3.4',
         'Programming Language :: Python :: 3.5',
+        'Programming Language :: Python :: 3.6',
         'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
         'Topic :: Software Development :: Libraries :: Python Modules'
     ]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SQLAlchemy-Utils-0.32.9/sqlalchemy_utils/__init__.py 
new/SQLAlchemy-Utils-0.32.14/sqlalchemy_utils/__init__.py
--- old/SQLAlchemy-Utils-0.32.9/sqlalchemy_utils/__init__.py    2016-07-17 
22:00:12.000000000 +0200
+++ new/SQLAlchemy-Utils-0.32.14/sqlalchemy_utils/__init__.py   2017-03-27 
15:48:47.000000000 +0200
@@ -53,7 +53,7 @@
     force_auto_coercion,
     force_instant_defaults
 )
-from .models import Timestamp  # noqa
+from .models import generic_repr, Timestamp  # noqa
 from .observer import observes  # noqa
 from .primitives import Country, Currency, Ltree, WeekDay, WeekDays  # noqa
 from .proxy_dict import proxy_dict, ProxyDict  # noqa
@@ -95,4 +95,4 @@
     WeekDaysType
 )
 
-__version__ = '0.32.9'
+__version__ = '0.32.14'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/SQLAlchemy-Utils-0.32.9/sqlalchemy_utils/functions/database.py 
new/SQLAlchemy-Utils-0.32.14/sqlalchemy_utils/functions/database.py
--- old/SQLAlchemy-Utils-0.32.9/sqlalchemy_utils/functions/database.py  
2016-04-25 20:10:50.000000000 +0200
+++ new/SQLAlchemy-Utils-0.32.14/sqlalchemy_utils/functions/database.py 
2017-03-27 15:46:49.000000000 +0200
@@ -585,17 +585,14 @@
 
     elif engine.dialect.name == 'postgresql' and engine.driver == 'psycopg2':
         from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT
-        engine.raw_connection().set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)
+
+        connection = engine.connect()
+        connection.connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)
 
         # Disconnect all users from the database we are dropping.
-        version = list(
-            map(
-                int,
-                engine.execute('SHOW server_version').first()[0].split('.')
-            )
-        )
+        version = connection.dialect.server_version_info
         pid_column = (
-            'pid' if (version[0] >= 9 and version[1] >= 2) else 'procpid'
+            'pid' if (version >= (9, 2)) else 'procpid'
         )
         text = '''
         SELECT pg_terminate_backend(pg_stat_activity.%(pid_column)s)
@@ -603,12 +600,11 @@
         WHERE pg_stat_activity.datname = '%(database)s'
           AND %(pid_column)s <> pg_backend_pid();
         ''' % {'pid_column': pid_column, 'database': database}
-        engine.execute(text)
+        connection.execute(text)
 
         # Drop the database.
-        text = 'DROP DATABASE {0}'.format(quote(engine, database))
-        engine.execute(text)
-
+        text = 'DROP DATABASE {0}'.format(quote(connection, database))
+        connection.execute(text)
     else:
         text = 'DROP DATABASE {0}'.format(quote(engine, database))
         engine.execute(text)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/SQLAlchemy-Utils-0.32.9/sqlalchemy_utils/functions/sort_query.py 
new/SQLAlchemy-Utils-0.32.14/sqlalchemy_utils/functions/sort_query.py
--- old/SQLAlchemy-Utils-0.32.9/sqlalchemy_utils/functions/sort_query.py        
2016-04-25 16:20:06.000000000 +0200
+++ new/SQLAlchemy-Utils-0.32.14/sqlalchemy_utils/functions/sort_query.py       
2017-03-27 15:49:24.000000000 +0200
@@ -100,7 +100,7 @@
         query = sort_query(query, 'name')
 
 
-    2. Appying descending sort
+    2. Applying descending sort
     ::
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/SQLAlchemy-Utils-0.32.9/sqlalchemy_utils/listeners.py 
new/SQLAlchemy-Utils-0.32.14/sqlalchemy_utils/listeners.py
--- old/SQLAlchemy-Utils-0.32.9/sqlalchemy_utils/listeners.py   2016-05-09 
12:53:42.000000000 +0200
+++ new/SQLAlchemy-Utils-0.32.14/sqlalchemy_utils/listeners.py  2016-10-20 
09:13:31.000000000 +0200
@@ -235,6 +235,8 @@
             'The relationship argument given for auto_delete_orphans needs to '
             'have a backref relationship set.'
         )
+    if isinstance(backref, tuple):
+        backref = backref[0]
 
     @sa.event.listens_for(sa.orm.Session, 'after_flush')
     def delete_orphan_listener(session, ctx):
@@ -257,7 +259,7 @@
             (
                 session.query(target_class)
                 .filter(
-                    ~getattr(target_class, attr.property.backref).any()
+                    ~getattr(target_class, backref).any()
                 )
                 .delete(synchronize_session=False)
             )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SQLAlchemy-Utils-0.32.9/sqlalchemy_utils/models.py 
new/SQLAlchemy-Utils-0.32.14/sqlalchemy_utils/models.py
--- old/SQLAlchemy-Utils-0.32.9/sqlalchemy_utils/models.py      2016-04-25 
16:20:06.000000000 +0200
+++ new/SQLAlchemy-Utils-0.32.14/sqlalchemy_utils/models.py     2016-12-18 
10:08:56.000000000 +0100
@@ -1,6 +1,7 @@
 from datetime import datetime
 
 import sqlalchemy as sa
+from sqlalchemy.util.langhelpers import symbol
 
 
 class Timestamp(object):
@@ -31,3 +32,67 @@
     # When a model with a timestamp is updated; force update the updated
     # timestamp.
     target.updated = datetime.utcnow()
+
+
+NO_VALUE = symbol('NO_VALUE')
+NOT_LOADED_REPR = '<not loaded>'
+
+
+def _generic_repr_method(self, fields):
+    state = sa.inspect(self)
+    field_reprs = []
+    if not fields:
+        fields = state.mapper.columns.keys()
+    for key in fields:
+        value = state.attrs[key].loaded_value
+        if value == NO_VALUE:
+            value = NOT_LOADED_REPR
+        else:
+            value = repr(value)
+        field_reprs.append('='.join((key, value)))
+
+    return '%s(%s)' % (self.__class__.__name__, ', '.join(field_reprs))
+
+
+def generic_repr(*fields):
+    """Adds generic ``__repr__()`` method to a decalrative SQLAlchemy model.
+
+    In case if some fields are not loaded from a database, it doesn't
+    force their loading and instead repesents them as ``<not loaded>``.
+
+    In addition, user can provide field names as arguments to the decorator
+    to specify what fields should present in the string representation
+    and in what order.
+
+    Example::
+
+
+        import sqlalchemy as sa
+        from sqlalchemy_utils import generic_repr
+
+
+        @generic_repr
+        class MyModel(Base):
+            __tablename__ = 'mymodel'
+            id = sa.Column(sa.Integer, primary_key=True)
+            name = sa.Column(sa.String)
+            category = sa.Column(sa.String)
+
+        session.add(MyModel(name='Foo', category='Bar'))
+        session.commit()
+        foo = session.query(MyModel).options(sa.orm.defer('category')).one(s)
+
+        assert repr(foo) == 'MyModel(id=1, name='Foo', category=<not loaded>)'
+    """
+    if len(fields) == 1 and callable(fields[0]):
+        target = fields[0]
+        target.__repr__ = lambda self: _generic_repr_method(self, fields=None)
+        return target
+    else:
+        def decorator(cls):
+            cls.__repr__ = lambda self: _generic_repr_method(
+                self,
+                fields=fields
+            )
+            return cls
+        return decorator
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SQLAlchemy-Utils-0.32.9/sqlalchemy_utils/observer.py 
new/SQLAlchemy-Utils-0.32.14/sqlalchemy_utils/observer.py
--- old/SQLAlchemy-Utils-0.32.9/sqlalchemy_utils/observer.py    2016-07-17 
22:00:22.000000000 +0200
+++ new/SQLAlchemy-Utils-0.32.14/sqlalchemy_utils/observer.py   2016-12-18 
10:08:56.000000000 +0100
@@ -152,7 +152,7 @@
 Observing multiple columns
 -----------------------
 
-You can also observe multiple columns by spesifying all the observable columns
+You can also observe multiple columns by specifying all the observable columns
 in the decorator.
 
 
@@ -317,6 +317,7 @@
             for callback, objs in callback_objs.items():
                 callback(root_obj, *[objs[i] for i in range(len(objs))])
 
+
 observer = PropertyObserver()
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/SQLAlchemy-Utils-0.32.9/sqlalchemy_utils/types/email.py 
new/SQLAlchemy-Utils-0.32.14/sqlalchemy_utils/types/email.py
--- old/SQLAlchemy-Utils-0.32.9/sqlalchemy_utils/types/email.py 2016-07-10 
11:03:30.000000000 +0200
+++ new/SQLAlchemy-Utils-0.32.14/sqlalchemy_utils/types/email.py        
2016-10-20 08:55:26.000000000 +0200
@@ -4,6 +4,33 @@
 
 
 class EmailType(sa.types.TypeDecorator):
+    """
+    Provides a way for storing emails in a lower case.
+
+    Example::
+
+
+        from sqlalchemy_utils import EmailType
+
+
+        class User(Base):
+            __tablename__ = 'user'
+            id = sa.Column(sa.Integer, primary_key=True)
+            name = sa.Column(sa.Unicode(255))
+            email = sa.Column(EmailType)
+
+
+        user = User()
+        user.email = '[email protected]'
+        user.name = 'John Smith'
+        session.add(user)
+        session.commit()
+        # Notice - email in filter() is lowercase.
+        user = (session.query(User)
+                       .filter(User.email == '[email protected]')
+                       .one())
+        assert user.name == 'John Smith'
+    """
     impl = sa.Unicode
     comparator_factory = CaseInsensitiveComparator
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/SQLAlchemy-Utils-0.32.9/sqlalchemy_utils/types/encrypted.py 
new/SQLAlchemy-Utils-0.32.14/sqlalchemy_utils/types/encrypted.py
--- old/SQLAlchemy-Utils-0.32.9/sqlalchemy_utils/types/encrypted.py     
2016-07-10 11:03:30.000000000 +0200
+++ new/SQLAlchemy-Utils-0.32.14/sqlalchemy_utils/types/encrypted.py    
2017-03-12 11:08:09.000000000 +0100
@@ -3,7 +3,7 @@
 import datetime
 
 import six
-from sqlalchemy.types import Binary, String, TypeDecorator
+from sqlalchemy.types import LargeBinary, String, TypeDecorator
 
 from ..exceptions import ImproperlyConfigured
 from .scalar_coercible import ScalarCoercible
@@ -199,7 +199,7 @@
 
     """
 
-    impl = Binary
+    impl = LargeBinary
 
     def __init__(self, type_in=None, key=None, engine=None, **kwargs):
         """Initialization."""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/SQLAlchemy-Utils-0.32.9/sqlalchemy_utils/types/password.py 
new/SQLAlchemy-Utils-0.32.14/sqlalchemy_utils/types/password.py
--- old/SQLAlchemy-Utils-0.32.9/sqlalchemy_utils/types/password.py      
2016-07-10 11:03:30.000000000 +0200
+++ new/SQLAlchemy-Utils-0.32.14/sqlalchemy_utils/types/password.py     
2016-11-19 09:37:07.000000000 +0100
@@ -2,7 +2,7 @@
 
 import six
 from sqlalchemy import types
-from sqlalchemy.dialects import oracle, postgresql
+from sqlalchemy.dialects import oracle, postgresql, sqlite
 from sqlalchemy.ext.mutable import Mutable
 
 from ..exceptions import ImproperlyConfigured
@@ -80,7 +80,7 @@
     """
     PasswordType hashes passwords as they come into the database and allows
     verifying them using a Pythonic interface. This Pythonic interface
-    relies on setting up automatic data type coercison using the
+    relies on setting up automatic data type coercion using the
     :func:`~sqlalchemy_utils.listeners.force_auto_coercion` function.
 
     All keyword arguments (aside from max_length) are forwarded to the
@@ -192,14 +192,15 @@
         if dialect.name == 'postgresql':
             # Use a BYTEA type for postgresql.
             impl = postgresql.BYTEA(self.length)
-            return dialect.type_descriptor(impl)
-        if dialect.name == 'oracle':
+        elif dialect.name == 'oracle':
             # Use a RAW type for oracle.
             impl = oracle.RAW(self.length)
-            return dialect.type_descriptor(impl)
-
-        # Use a VARBINARY for all other dialects.
-        impl = types.VARBINARY(self.length)
+        elif dialect.name == 'sqlite':
+            # Use a BLOB type for sqlite
+            impl = sqlite.BLOB(self.length)
+        else:
+            # Use a VARBINARY for all other dialects.
+            impl = types.VARBINARY(self.length)
         return dialect.type_descriptor(impl)
 
     def process_bind_param(self, value, dialect):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/SQLAlchemy-Utils-0.32.9/sqlalchemy_utils/types/pg_composite.py 
new/SQLAlchemy-Utils-0.32.14/sqlalchemy_utils/types/pg_composite.py
--- old/SQLAlchemy-Utils-0.32.9/sqlalchemy_utils/types/pg_composite.py  
2016-04-25 16:20:06.000000000 +0200
+++ new/SQLAlchemy-Utils-0.32.14/sqlalchemy_utils/types/pg_composite.py 
2016-12-18 10:08:56.000000000 +0100
@@ -32,7 +32,7 @@
     from collections import OrderedDict
 
     import sqlalchemy as sa
-    from sqlalchemy_utils import Composite, CurrencyType
+    from sqlalchemy_utils import CompositeType, CurrencyType
 
 
     class Account(Base):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/SQLAlchemy-Utils-0.32.9/sqlalchemy_utils/types/phone_number.py 
new/SQLAlchemy-Utils-0.32.14/sqlalchemy_utils/types/phone_number.py
--- old/SQLAlchemy-Utils-0.32.9/sqlalchemy_utils/types/phone_number.py  
2016-05-20 08:58:31.000000000 +0200
+++ new/SQLAlchemy-Utils-0.32.14/sqlalchemy_utils/types/phone_number.py 
2016-10-20 08:50:43.000000000 +0200
@@ -153,9 +153,7 @@
     """
     STORE_FORMAT = 'e164'
     impl = types.Unicode(20)
-
-    def python_type(self, text):
-        return self._coerce(text)
+    python_type = PhoneNumber
 
     def __init__(self, region='US', max_length=20, *args, **kwargs):
         # Bail if phonenumbers is not found.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/SQLAlchemy-Utils-0.32.9/sqlalchemy_utils/types/timezone.py 
new/SQLAlchemy-Utils-0.32.14/sqlalchemy_utils/types/timezone.py
--- old/SQLAlchemy-Utils-0.32.9/sqlalchemy_utils/types/timezone.py      
2016-04-25 16:20:06.000000000 +0200
+++ new/SQLAlchemy-Utils-0.32.14/sqlalchemy_utils/types/timezone.py     
2016-11-19 09:35:59.000000000 +0100
@@ -52,9 +52,10 @@
 
         elif backend == 'pytz':
             try:
-                from pytz import tzfile, timezone
+                from pytz import timezone
+                from pytz.tzinfo import BaseTzInfo
 
-                self.python_type = tzfile.DstTzInfo
+                self.python_type = BaseTzInfo
                 self._to = timezone
                 self._from = six.text_type
 
@@ -71,13 +72,11 @@
             )
 
     def _coerce(self, value):
-        if value and not isinstance(value, self.python_type):
+        if value is not None and not isinstance(value, self.python_type):
             obj = self._to(value)
             if obj is None:
                 raise ValueError("unknown time zone '%s'" % value)
-
             return obj
-
         return value
 
     def process_bind_param(self, value, dialect):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/SQLAlchemy-Utils-0.32.9/tests/functions/test_make_order_by_deterministic.py 
new/SQLAlchemy-Utils-0.32.14/tests/functions/test_make_order_by_deterministic.py
--- 
old/SQLAlchemy-Utils-0.32.9/tests/functions/test_make_order_by_deterministic.py 
    2016-05-20 08:58:31.000000000 +0200
+++ 
new/SQLAlchemy-Utils-0.32.14/tests/functions/test_make_order_by_deterministic.py
    2016-10-20 10:04:40.000000000 +0200
@@ -46,58 +46,58 @@
     def test_column_property(self, session, User):
         query = session.query(User).order_by(User.email_lower)
         query = make_order_by_deterministic(query)
-        assert_contains('lower("user".name) AS lower_1', query)
-        assert_contains('lower_1, "user".id ASC', query)
+        assert_contains('lower(user.name) AS lower_1', query)
+        assert_contains('lower_1, user.id ASC', query)
 
     def test_unique_column(self, session, User):
         query = session.query(User).order_by(User.email)
         query = make_order_by_deterministic(query)
 
-        assert str(query).endswith('ORDER BY "user".email')
+        assert str(query).endswith('ORDER BY user.email')
 
     def test_non_unique_column(self, session, User):
         query = session.query(User).order_by(User.name)
         query = make_order_by_deterministic(query)
-        assert_contains('ORDER BY "user".name, "user".id ASC', query)
+        assert_contains('ORDER BY user.name, user.id ASC', query)
 
     def test_descending_order_by(self, session, User):
         query = session.query(User).order_by(
             sa.desc(User.name)
         )
         query = make_order_by_deterministic(query)
-        assert_contains('ORDER BY "user".name DESC, "user".id DESC', query)
+        assert_contains('ORDER BY user.name DESC, user.id DESC', query)
 
     def test_ascending_order_by(self, session, User):
         query = session.query(User).order_by(
             sa.asc(User.name)
         )
         query = make_order_by_deterministic(query)
-        assert_contains('ORDER BY "user".name ASC, "user".id ASC', query)
+        assert_contains('ORDER BY user.name ASC, user.id ASC', query)
 
     def test_string_order_by(self, session, User):
         query = session.query(User).order_by('name')
         query = make_order_by_deterministic(query)
-        assert_contains('ORDER BY "user".name, "user".id ASC', query)
+        assert_contains('ORDER BY user.name, user.id ASC', query)
 
     def test_annotated_label(self, session, User):
         query = session.query(User).order_by(User.article_count)
         query = make_order_by_deterministic(query)
-        assert_contains('article_count, "user".id ASC', query)
+        assert_contains('article_count, user.id ASC', query)
 
     def test_annotated_label_with_descending_order(self, session, User):
         query = session.query(User).order_by(
             sa.desc(User.article_count)
         )
         query = make_order_by_deterministic(query)
-        assert_contains('ORDER BY article_count DESC, "user".id DESC', query)
+        assert_contains('ORDER BY article_count DESC, user.id DESC', query)
 
     def test_query_without_order_by(self, session, User):
         query = session.query(User)
         query = make_order_by_deterministic(query)
-        assert 'ORDER BY "user".id' in str(query)
+        assert 'ORDER BY user.id' in str(query)
 
     def test_alias(self, session, User):
         alias = sa.orm.aliased(User.__table__)
         query = session.query(alias).order_by(alias.c.name)
         query = make_order_by_deterministic(query)
-        assert str(query).endswith('ORDER BY user_1.name, "user".id ASC')
+        assert str(query).endswith('ORDER BY user_1.name, user.id ASC')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/SQLAlchemy-Utils-0.32.9/tests/test_auto_delete_orphans.py 
new/SQLAlchemy-Utils-0.32.14/tests/test_auto_delete_orphans.py
--- old/SQLAlchemy-Utils-0.32.9/tests/test_auto_delete_orphans.py       
2016-04-25 16:20:06.000000000 +0200
+++ new/SQLAlchemy-Utils-0.32.14/tests/test_auto_delete_orphans.py      
2016-10-20 09:13:46.000000000 +0200
@@ -1,5 +1,6 @@
 import pytest
 import sqlalchemy as sa
+from sqlalchemy.orm import backref
 
 from sqlalchemy_utils import auto_delete_orphans, ImproperlyConfigured
 
@@ -36,17 +37,20 @@
     return Tag
 
 
[email protected]
-def Entry(Base, Tag, tagging_tbl):
[email protected](
+    params=['entries', backref('entries', lazy='select')],
+    ids=['backref_string', 'backref_with_keywords']
+)
+def Entry(Base, Tag, tagging_tbl, request):
     class Entry(Base):
         __tablename__ = 'entry'
 
         id = sa.Column(sa.Integer, primary_key=True)
 
         tags = sa.orm.relationship(
-            'Tag',
+            Tag,
             secondary=tagging_tbl,
-            backref='entries'
+            backref=request.param
         )
     auto_delete_orphans(Entry.tags)
     return Entry
@@ -60,7 +64,7 @@
         id = sa.Column(sa.Integer, primary_key=True)
 
         tags = sa.orm.relationship(
-            'Tag',
+            Tag,
             secondary=tagging_tbl
         )
     return EntryWithoutTagsBackref
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/SQLAlchemy-Utils-0.32.9/tests/test_case_insensitive_comparator.py 
new/SQLAlchemy-Utils-0.32.14/tests/test_case_insensitive_comparator.py
--- old/SQLAlchemy-Utils-0.32.9/tests/test_case_insensitive_comparator.py       
2016-04-25 16:20:06.000000000 +0200
+++ new/SQLAlchemy-Utils-0.32.14/tests/test_case_insensitive_comparator.py      
2016-10-20 09:47:38.000000000 +0200
@@ -29,7 +29,7 @@
             .filter(User.email == u'[email protected]')
         )
 
-        assert '"user".email = lower(:lower_1)' in str(query)
+        assert 'user.email = lower(?)' in str(query)
 
     def test_supports_in_(self, session, User):
         query = (
@@ -37,7 +37,7 @@
             .filter(User.email.in_([u'[email protected]', u'a']))
         )
         assert (
-            '"user".email IN (lower(:lower_1), lower(:lower_2))'
+            'user.email IN (lower(?), lower(?))'
             in str(query)
         )
 
@@ -47,7 +47,7 @@
             .filter(User.email.notin_([u'[email protected]', u'a']))
         )
         assert (
-            '"user".email NOT IN (lower(:lower_1), lower(:lower_2))'
+            'user.email NOT IN (lower(?), lower(?))'
             in str(query)
         )
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SQLAlchemy-Utils-0.32.9/tests/test_expressions.py 
new/SQLAlchemy-Utils-0.32.14/tests/test_expressions.py
--- old/SQLAlchemy-Utils-0.32.9/tests/test_expressions.py       2016-04-25 
16:20:06.000000000 +0200
+++ new/SQLAlchemy-Utils-0.32.14/tests/test_expressions.py      2016-10-20 
09:52:40.000000000 +0200
@@ -118,8 +118,9 @@
 
 class TestRowToJson(object):
     def test_compiler_with_default_dialect(self):
-        with pytest.raises(sa.exc.CompileError):
-            str(row_to_json(sa.text('article.*')))
+        assert str(row_to_json(sa.text('article.*'))) == (
+            'row_to_json(article.*)'
+        )
 
     def test_compiler_with_postgresql(self):
         assert str(row_to_json(sa.text('article.*')).compile(
@@ -135,13 +136,14 @@
 
 class TestArrayAgg(object):
     def test_compiler_with_default_dialect(self):
-        with pytest.raises(sa.exc.CompileError):
-            str(sa.func.array_agg(sa.text('u.name')))
+        assert str(sa.func.array_agg(sa.text('u.name'))) == (
+            'array_agg(u.name)'
+        )
 
     def test_compiler_with_postgresql(self):
         assert str(sa.func.array_agg(sa.text('u.name')).compile(
             dialect=postgresql.dialect()
-        )) == "array_agg(u.name)"
+        )) == 'array_agg(u.name)'
 
     def test_type(self):
         assert isinstance(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SQLAlchemy-Utils-0.32.9/tests/test_models.py 
new/SQLAlchemy-Utils-0.32.14/tests/test_models.py
--- old/SQLAlchemy-Utils-0.32.9/tests/test_models.py    2016-04-25 
16:20:06.000000000 +0200
+++ new/SQLAlchemy-Utils-0.32.14/tests/test_models.py   2016-12-18 
10:08:56.000000000 +0100
@@ -1,21 +1,20 @@
+import sys
 from datetime import datetime
 
 import pytest
 import sqlalchemy as sa
 
-from sqlalchemy_utils import Timestamp
-
-
[email protected]
-def Article(Base):
-    class Article(Base, Timestamp):
-        __tablename__ = 'article'
-        id = sa.Column(sa.Integer, primary_key=True)
-        name = sa.Column(sa.Unicode(255), default=u'Some article')
-    return Article
+from sqlalchemy_utils import generic_repr, Timestamp
 
 
 class TestTimestamp(object):
+    @pytest.fixture
+    def Article(self, Base):
+        class Article(Base, Timestamp):
+            __tablename__ = 'article'
+            id = sa.Column(sa.Integer, primary_key=True)
+            name = sa.Column(sa.Unicode(255), default=u'Some article')
+        return Article
 
     def test_created(self, session, Article):
         then = datetime.utcnow()
@@ -38,3 +37,52 @@
         session.commit()
 
         assert article.updated >= then and article.updated <= datetime.utcnow()
+
+
+class TestGenericRepr:
+    @pytest.fixture
+    def Article(self, Base):
+        class Article(Base):
+            __tablename__ = 'article'
+            id = sa.Column(sa.Integer, primary_key=True)
+            name = sa.Column(sa.Unicode(255), default=u'Some article')
+        return Article
+
+    def test_repr(self, Article):
+        """Representation of a basic model."""
+        Article = generic_repr(Article)
+        article = Article(id=1, name=u'Foo')
+        if sys.version_info[0] == 2:
+            expected_repr = u'Article(id=1, name=u\'Foo\')'
+        elif sys.version_info[0] == 3:
+            expected_repr = u'Article(id=1, name=\'Foo\')'
+        else:
+            raise AssertionError
+        actual_repr = repr(article)
+
+        assert actual_repr == expected_repr
+
+    def test_repr_partial(self, Article):
+        """Representation of a basic model with selected fields."""
+        Article = generic_repr('id')(Article)
+        article = Article(id=1, name=u'Foo')
+        expected_repr = u'Article(id=1)'
+        actual_repr = repr(article)
+
+        assert actual_repr == expected_repr
+
+    def test_not_loaded(self, session, Article):
+        """:py:func:`~sqlalchemy_utils.models.generic_repr` doesn't force
+        execution of additional queries if some fields are not loaded and
+        instead represents them as "<not loaded>".
+        """
+        Article = generic_repr(Article)
+        article = Article(name=u'Foo')
+        session.add(article)
+        session.commit()
+
+        article = session.query(Article).options(sa.orm.defer('name')).one()
+        actual_repr = repr(article)
+
+        expected_repr = u'Article(id={}, name=<not loaded>)'.format(article.id)
+        assert actual_repr == expected_repr
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SQLAlchemy-Utils-0.32.9/tests/test_proxy_dict.py 
new/SQLAlchemy-Utils-0.32.14/tests/test_proxy_dict.py
--- old/SQLAlchemy-Utils-0.32.9/tests/test_proxy_dict.py        2016-04-25 
16:20:06.000000000 +0200
+++ new/SQLAlchemy-Utils-0.32.14/tests/test_proxy_dict.py       2016-10-20 
09:15:43.000000000 +0200
@@ -13,7 +13,6 @@
         id = sa.Column(
             sa.Integer,
             sa.ForeignKey('article.id'),
-            autoincrement=True,
             primary_key=True
         )
         locale = sa.Column(sa.String(10), primary_key=True)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SQLAlchemy-Utils-0.32.9/tests/test_sort_query.py 
new/SQLAlchemy-Utils-0.32.14/tests/test_sort_query.py
--- old/SQLAlchemy-Utils-0.32.9/tests/test_sort_query.py        2016-04-25 
16:20:06.000000000 +0200
+++ new/SQLAlchemy-Utils-0.32.14/tests/test_sort_query.py       2016-10-20 
09:54:03.000000000 +0200
@@ -230,7 +230,7 @@
         )
         query = sort_query(query, 'aliased-full_name')
         assert_contains(
-            'concat(aliased.title, :param_1, aliased.name)', query
+            'concat(aliased.title, %(concat_1)s, aliased.name)', query
         )
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/SQLAlchemy-Utils-0.32.9/tests/test_translation_hybrid.py 
new/SQLAlchemy-Utils-0.32.14/tests/test_translation_hybrid.py
--- old/SQLAlchemy-Utils-0.32.9/tests/test_translation_hybrid.py        
2016-04-25 16:20:06.000000000 +0200
+++ new/SQLAlchemy-Utils-0.32.14/tests/test_translation_hybrid.py       
2016-10-20 09:57:03.000000000 +0200
@@ -96,7 +96,7 @@
 
         assert (
             'coalesce(article.name_translations -> article.locale'
-            in str(Article.name)
+            in str(Article.name.expression)
         )
 
     def test_locales_casted_only_in_compilation_phase(self, Base):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SQLAlchemy-Utils-0.32.9/tests/types/test_password.py 
new/SQLAlchemy-Utils-0.32.14/tests/types/test_password.py
--- old/SQLAlchemy-Utils-0.32.9/tests/types/test_password.py    2016-04-25 
16:21:32.000000000 +0200
+++ new/SQLAlchemy-Utils-0.32.14/tests/types/test_password.py   2016-11-19 
09:37:07.000000000 +0100
@@ -1,6 +1,10 @@
 import mock
 import pytest
 import sqlalchemy as sa
+import sqlalchemy.dialects.mysql
+import sqlalchemy.dialects.oracle
+import sqlalchemy.dialects.postgresql
+import sqlalchemy.dialects.sqlite
 from sqlalchemy import inspect
 
 from sqlalchemy_utils import Password, PasswordType, types  # noqa
@@ -52,6 +56,23 @@
 @pytest.mark.skipif('types.password.passlib is None')
 class TestPasswordType(object):
 
+    @pytest.mark.parametrize('dialect_module,impl', [
+        (sqlalchemy.dialects.sqlite, sa.dialects.sqlite.BLOB),
+        (sqlalchemy.dialects.postgresql, sa.dialects.postgresql.BYTEA),
+        (sqlalchemy.dialects.oracle, sa.dialects.oracle.RAW),
+        (sqlalchemy.dialects.mysql, sa.VARBINARY),
+    ])
+    def test_load_dialect_impl(self, dialect_module, impl):
+        """
+        Should produce the same impl type as Alembic would expect after
+        inspecing a database
+        """
+        password_type = PasswordType()
+        assert isinstance(
+            password_type.load_dialect_impl(dialect_module.dialect()),
+            impl
+        )
+
     def test_encrypt(self, User):
         """Should encrypt the password on setting the attribute."""
         obj = User()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/SQLAlchemy-Utils-0.32.9/tests/types/test_phonenumber.py 
new/SQLAlchemy-Utils-0.32.14/tests/types/test_phonenumber.py
--- old/SQLAlchemy-Utils-0.32.9/tests/types/test_phonenumber.py 2016-05-30 
11:49:18.000000000 +0200
+++ new/SQLAlchemy-Utils-0.32.14/tests/types/test_phonenumber.py        
2016-10-20 08:53:21.000000000 +0200
@@ -150,6 +150,9 @@
         session.refresh(user)
         assert user.phone_number is None
 
+    def test_uses_phonenumber_class_as_python_type(self):
+        assert PhoneNumberType().python_type is PhoneNumber
+
     @pytest.mark.usefixtures('user')
     def test_phone_number_is_none(self, session, User):
         phone_number = None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/SQLAlchemy-Utils-0.32.9/tests/types/test_timezone.py 
new/SQLAlchemy-Utils-0.32.14/tests/types/test_timezone.py
--- old/SQLAlchemy-Utils-0.32.9/tests/types/test_timezone.py    2016-04-25 
16:20:07.000000000 +0200
+++ new/SQLAlchemy-Utils-0.32.14/tests/types/test_timezone.py   2016-11-19 
09:35:59.000000000 +0100
@@ -1,7 +1,9 @@
 import pytest
+import pytz
 import sqlalchemy as sa
+from dateutil.zoneinfo import getzoneinfofile_stream, tzfile, ZoneInfoFile
 
-from sqlalchemy_utils.types import timezone
+from sqlalchemy_utils.types import timezone, TimezoneType
 
 
 @pytest.fixture
@@ -46,3 +48,48 @@
 
         assert visitor_dateutil is not None
         assert visitor_pytz is not None
+
+
+TIMEZONE_BACKENDS = ['dateutil', 'pytz']
+
+
+def test_can_coerce_pytz_DstTzInfo():
+    tzcol = TimezoneType(backend='pytz')
+    tz = pytz.timezone('America/New_York')
+    assert isinstance(tz, pytz.tzfile.DstTzInfo)
+    assert tzcol._coerce(tz) is tz
+
+
+def test_can_coerce_pytz_StaticTzInfo():
+    tzcol = TimezoneType(backend='pytz')
+    tz = pytz.timezone('Pacific/Truk')
+    assert isinstance(tz, pytz.tzfile.StaticTzInfo)
+    assert tzcol._coerce(tz) is tz
+
+
[email protected]('zone', pytz.all_timezones)
+def test_can_coerce_string_for_pytz_zone(zone):
+    tzcol = TimezoneType(backend='pytz')
+    assert tzcol._coerce(zone).zone == zone
+
+
[email protected](
+    'zone', ZoneInfoFile(getzoneinfofile_stream()).zones.keys())
+def test_can_coerce_string_for_dateutil_zone(zone):
+    tzcol = TimezoneType(backend='dateutil')
+    assert isinstance(tzcol._coerce(zone), tzfile)
+
+
[email protected]('backend', TIMEZONE_BACKENDS)
+def test_can_coerce_and_raise_UnknownTimeZoneError_or_ValueError(backend):
+    tzcol = TimezoneType(backend=backend)
+    with pytest.raises((ValueError, pytz.exceptions.UnknownTimeZoneError)):
+        tzcol._coerce('SolarSystem/Mars')
+    with pytest.raises((ValueError, pytz.exceptions.UnknownTimeZoneError)):
+        tzcol._coerce('')
+
+
[email protected]('backend', TIMEZONE_BACKENDS)
+def test_can_coerce_None(backend):
+    tzcol = TimezoneType(backend=backend)
+    assert tzcol._coerce(None) is None


Reply via email to