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