Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-SQLAlchemy-Utils for openSUSE:Factory checked in at 2021-10-18 21:59:09 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-SQLAlchemy-Utils (Old) and /work/SRC/openSUSE:Factory/.python-SQLAlchemy-Utils.new.1890 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-SQLAlchemy-Utils" Mon Oct 18 21:59:09 2021 rev:31 rq:925771 version:0.37.8 Changes: -------- --- /work/SRC/openSUSE:Factory/python-SQLAlchemy-Utils/python-SQLAlchemy-Utils.changes 2021-06-19 23:03:36.139723309 +0200 +++ /work/SRC/openSUSE:Factory/.python-SQLAlchemy-Utils.new.1890/python-SQLAlchemy-Utils.changes 2021-10-18 22:02:00.230085397 +0200 @@ -1,0 +2,8 @@ +Tue Sep 7 06:43:25 UTC 2021 - Dirk M??ller <dmuel...@suse.com> + +- update to 0.37.8: + * Added 'zoneinfo' backend to TimezoneType + * Added identifier quoting for view functions and constructs + * Added literal processor for UUIDType + +------------------------------------------------------------------- Old: ---- SQLAlchemy-Utils-0.37.6.tar.gz New: ---- SQLAlchemy-Utils-0.37.8.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-SQLAlchemy-Utils.spec ++++++ --- /var/tmp/diff_new_pack.EugfLk/_old 2021-10-18 22:02:00.642085695 +0200 +++ /var/tmp/diff_new_pack.EugfLk/_new 2021-10-18 22:02:00.642085695 +0200 @@ -19,7 +19,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define skip_python2 1 Name: python-SQLAlchemy-Utils -Version: 0.37.6 +Version: 0.37.8 Release: 0 Summary: Various utility functions for SQLAlchemy License: BSD-3-Clause @@ -31,6 +31,7 @@ BuildRequires: %{python_module SQLAlchemy >= 1.0} BuildRequires: %{python_module anyjson >= 0.3.3} BuildRequires: %{python_module arrow >= 0.3.4} +BuildRequires: %{python_module backports.zoneinfo if %python-base < 3.9} BuildRequires: %{python_module colour >= 0.0.4} BuildRequires: %{python_module cryptography >= 0.6} BuildRequires: %{python_module docutils >= 0.10} @@ -52,6 +53,9 @@ BuildRequires: fdupes BuildRequires: python-rpm-macros Requires: python-SQLAlchemy >= 1.0 +%if 0%{?python_version_nodots} < 39 +Requires: python-backports.zoneinfo +%endif Requires: python-six Recommends: python-Babel >= 1.3 Recommends: python-anyjson >= 0.3.3 ++++++ SQLAlchemy-Utils-0.37.6.tar.gz -> SQLAlchemy-Utils-0.37.8.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SQLAlchemy-Utils-0.37.6/CHANGES.rst new/SQLAlchemy-Utils-0.37.8/CHANGES.rst --- old/SQLAlchemy-Utils-0.37.6/CHANGES.rst 2021-06-02 17:21:28.000000000 +0200 +++ new/SQLAlchemy-Utils-0.37.8/CHANGES.rst 2021-06-28 09:21:44.000000000 +0200 @@ -4,6 +4,19 @@ Here you can see the full list of changes between each SQLAlchemy-Utils release. +0.37.8 (2021-06-28) +^^^^^^^^^^^^^^^^^^^ + +- Added 'zoneinfo' backend to TimezoneType (#510, pull request courtesy of huonw) + + +0.37.7 (2021-06-15) +^^^^^^^^^^^^^^^^^^^ + +- Added identifier quoting for view functions and constructs +- Added literal processor for UUIDType + + 0.37.6 (2021-06-02) ^^^^^^^^^^^^^^^^^^^ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SQLAlchemy-Utils-0.37.6/PKG-INFO new/SQLAlchemy-Utils-0.37.8/PKG-INFO --- old/SQLAlchemy-Utils-0.37.6/PKG-INFO 2021-06-02 17:25:03.000000000 +0200 +++ new/SQLAlchemy-Utils-0.37.8/PKG-INFO 2021-06-28 09:22:30.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: SQLAlchemy-Utils -Version: 0.37.6 +Version: 0.37.8 Summary: Various utility functions for SQLAlchemy. Home-page: https://github.com/kvesteri/sqlalchemy-utils Author: Konsta Vesterinen, Ryan Leckey, Janne Vanhala, Vesa Uimonen diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SQLAlchemy-Utils-0.37.6/SQLAlchemy_Utils.egg-info/PKG-INFO new/SQLAlchemy-Utils-0.37.8/SQLAlchemy_Utils.egg-info/PKG-INFO --- old/SQLAlchemy-Utils-0.37.6/SQLAlchemy_Utils.egg-info/PKG-INFO 2021-06-02 17:25:03.000000000 +0200 +++ new/SQLAlchemy-Utils-0.37.8/SQLAlchemy_Utils.egg-info/PKG-INFO 2021-06-28 09:22:29.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: SQLAlchemy-Utils -Version: 0.37.6 +Version: 0.37.8 Summary: Various utility functions for SQLAlchemy. Home-page: https://github.com/kvesteri/sqlalchemy-utils Author: Konsta Vesterinen, Ryan Leckey, Janne Vanhala, Vesa Uimonen diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SQLAlchemy-Utils-0.37.6/SQLAlchemy_Utils.egg-info/requires.txt new/SQLAlchemy-Utils-0.37.8/SQLAlchemy_Utils.egg-info/requires.txt --- old/SQLAlchemy-Utils-0.37.6/SQLAlchemy_Utils.egg-info/requires.txt 2021-06-02 17:25:03.000000000 +0200 +++ new/SQLAlchemy-Utils-0.37.8/SQLAlchemy_Utils.egg-info/requires.txt 2021-06-28 09:22:29.000000000 +0200 @@ -45,6 +45,9 @@ isort>=4.2.2 pyodbc +[test:python_version < "3.9"] +backports.zoneinfo + [test_all] Babel>=1.3 Jinja2>=2.3 @@ -73,6 +76,9 @@ python-dateutil>=2.6 pytz>=2014.2 +[test_all:python_version < "3.9"] +backports.zoneinfo + [timezone] python-dateutil diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SQLAlchemy-Utils-0.37.6/setup.py new/SQLAlchemy-Utils-0.37.8/setup.py --- old/SQLAlchemy-Utils-0.37.6/setup.py 2021-05-05 08:02:36.000000000 +0200 +++ new/SQLAlchemy-Utils-0.37.8/setup.py 2021-06-28 09:19:48.000000000 +0200 @@ -33,6 +33,7 @@ 'pg8000>=1.12.4', 'pytz>=2014.2', 'python-dateutil>=2.6', + 'backports.zoneinfo;python_version<"3.9"', 'pymysql', 'flake8>=2.4.0', 'isort>=4.2.2', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SQLAlchemy-Utils-0.37.6/sqlalchemy_utils/__init__.py new/SQLAlchemy-Utils-0.37.8/sqlalchemy_utils/__init__.py --- old/SQLAlchemy-Utils-0.37.6/sqlalchemy_utils/__init__.py 2021-06-02 17:21:47.000000000 +0200 +++ new/SQLAlchemy-Utils-0.37.8/sqlalchemy_utils/__init__.py 2021-06-28 09:21:53.000000000 +0200 @@ -102,4 +102,4 @@ refresh_materialized_view ) -__version__ = '0.37.6' +__version__ = '0.37.8' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SQLAlchemy-Utils-0.37.6/sqlalchemy_utils/primitives/ltree.py new/SQLAlchemy-Utils-0.37.8/sqlalchemy_utils/primitives/ltree.py --- old/SQLAlchemy-Utils-0.37.6/sqlalchemy_utils/primitives/ltree.py 2021-05-21 12:24:40.000000000 +0200 +++ new/SQLAlchemy-Utils-0.37.8/sqlalchemy_utils/primitives/ltree.py 2021-06-02 17:26:36.000000000 +0200 @@ -173,7 +173,9 @@ parts = self.path.split('.') for index, element in enumerate(parts): if any(( - other[index] != element or len(other) <= index + 1 or len(parts) == index + 1 + other[index] != element or + len(other) <= index + 1 or + len(parts) == index + 1 for other in other_parts )): if index == 0: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SQLAlchemy-Utils-0.37.6/sqlalchemy_utils/types/scalar_list.py new/SQLAlchemy-Utils-0.37.8/sqlalchemy_utils/types/scalar_list.py --- old/SQLAlchemy-Utils-0.37.6/sqlalchemy_utils/types/scalar_list.py 2021-05-21 12:24:40.000000000 +0200 +++ new/SQLAlchemy-Utils-0.37.8/sqlalchemy_utils/types/scalar_list.py 2021-06-08 09:16:44.000000000 +0200 @@ -50,8 +50,8 @@ session.commit() - ScalarListType is always stored as text. To use an array field on PostgreSQL - database use variant construct:: + ScalarListType is always stored as text. To use an array field on + PostgreSQL database use variant construct:: from sqlalchemy_utils import ScalarListType @@ -59,7 +59,9 @@ class Player(Base): __tablename__ = 'player' id = sa.Column(sa.Integer, autoincrement=True) - points = sa.Column(ARRAY(Integer).with_variant(ScalarListType(int), 'sqlite')) + points = sa.Column( + ARRAY(Integer).with_variant(ScalarListType(int), 'sqlite') + ) """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SQLAlchemy-Utils-0.37.6/sqlalchemy_utils/types/timezone.py new/SQLAlchemy-Utils-0.37.8/sqlalchemy_utils/types/timezone.py --- old/SQLAlchemy-Utils-0.37.6/sqlalchemy_utils/types/timezone.py 2021-05-16 10:51:24.000000000 +0200 +++ new/SQLAlchemy-Utils-0.37.8/sqlalchemy_utils/types/timezone.py 2021-06-28 09:19:48.000000000 +0200 @@ -7,11 +7,9 @@ class TimezoneType(ScalarCoercible, types.TypeDecorator): """ - TimezoneType provides a way for saving timezones (from either the pytz or - the dateutil package) objects into database. TimezoneType saves timezone - objects as strings on the way in and converts them back to objects when - querying the database. - + TimezoneType provides a way for saving timezones objects into database. + TimezoneType saves timezone objects as strings on the way in and converts + them back to objects when querying the database. :: @@ -20,9 +18,15 @@ class User(Base): __tablename__ = 'user' - # Pass backend='pytz' to change it to use pytz (dateutil by - # default) + # Pass backend='pytz' to change it to use pytz. Other values: + # 'dateutil' (default), and 'zoneinfo'. timezone = sa.Column(TimezoneType(backend='pytz')) + + :param backend: Whether to use 'dateutil', 'pytz' or 'zoneinfo' for + timezones. 'zoneinfo' uses the standard library module in Python 3.9+, + but requires the external 'backports.zoneinfo' package for older + Python versions. + """ impl = types.Unicode(50) @@ -30,10 +34,6 @@ python_type = None def __init__(self, backend='dateutil'): - """ - :param backend: Whether to use 'dateutil' or 'pytz' for timezones. - """ - self.backend = backend if backend == 'dateutil': try: @@ -65,10 +65,27 @@ "for 'TimezoneType'" ) + elif backend == "zoneinfo": + try: + import zoneinfo + except ImportError: + try: + from backports import zoneinfo + except ImportError: + raise ImproperlyConfigured( + "'backports.zoneinfo' is required to use " + "the 'zoneinfo' backend for 'TimezoneType'" + "on Python version < 3.9" + ) + + self.python_type = zoneinfo.ZoneInfo + self._to = zoneinfo.ZoneInfo + self._from = six.text_type + else: raise ImproperlyConfigured( - "'pytz' or 'dateutil' are the backends supported for " - "'TimezoneType'" + "'pytz', 'dateutil' or 'zoneinfo' are the backends " + "supported for 'TimezoneType'" ) def _coerce(self, value): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SQLAlchemy-Utils-0.37.6/sqlalchemy_utils/types/uuid.py new/SQLAlchemy-Utils-0.37.8/sqlalchemy_utils/types/uuid.py --- old/SQLAlchemy-Utils-0.37.6/sqlalchemy_utils/types/uuid.py 2021-05-16 10:51:24.000000000 +0200 +++ new/SQLAlchemy-Utils-0.37.8/sqlalchemy_utils/types/uuid.py 2021-06-15 12:00:43.000000000 +0200 @@ -63,6 +63,9 @@ return value + def process_literal_param(self, value, dialect): + return "'{}'".format(value) if value else value + def process_bind_param(self, value, dialect): if value is None: return value @@ -70,7 +73,11 @@ if not isinstance(value, uuid.UUID): value = self._coerce(value) - if self.native and dialect.name in ('postgresql', 'mssql', 'cockroachdb'): + if self.native and dialect.name in ( + 'postgresql', + 'mssql', + 'cockroachdb' + ): return str(value) return value.bytes if self.binary else value.hex @@ -79,7 +86,11 @@ if value is None: return value - if self.native and dialect.name in ('postgresql', 'mssql', 'cockroachdb'): + if self.native and dialect.name in ( + 'postgresql', + 'mssql', + 'cockroachdb' + ): if isinstance(value, uuid.UUID): # Some drivers convert PostgreSQL's uuid values to # Python's uuid.UUID objects by themselves diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SQLAlchemy-Utils-0.37.6/sqlalchemy_utils/view.py new/SQLAlchemy-Utils-0.37.8/sqlalchemy_utils/view.py --- old/SQLAlchemy-Utils-0.37.6/sqlalchemy_utils/view.py 2021-04-12 14:12:57.000000000 +0200 +++ new/SQLAlchemy-Utils-0.37.8/sqlalchemy_utils/view.py 2021-06-15 11:43:50.000000000 +0200 @@ -16,7 +16,7 @@ def compile_create_materialized_view(element, compiler, **kw): return 'CREATE {}VIEW {} AS {}'.format( 'MATERIALIZED ' if element.materialized else '', - element.name, + compiler.dialect.identifier_preparer.quote(element.name), compiler.sql_compiler.process(element.selectable, literal_binds=True), ) @@ -32,7 +32,7 @@ def compile_drop_materialized_view(element, compiler, **kw): return 'DROP {}VIEW IF EXISTS {} {}'.format( 'MATERIALIZED ' if element.materialized else '', - element.name, + compiler.dialect.identifier_preparer.quote(element.name), 'CASCADE' if element.cascade else '' ) @@ -190,6 +190,6 @@ session.execute( 'REFRESH MATERIALIZED VIEW {}{}'.format( 'CONCURRENTLY ' if concurrently else '', - name + session.bind.engine.dialect.identifier_preparer.quote(name) ) ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SQLAlchemy-Utils-0.37.6/tests/test_views.py new/SQLAlchemy-Utils-0.37.8/tests/test_views.py --- old/SQLAlchemy-Utils-0.37.6/tests/test_views.py 2019-12-23 09:48:02.000000000 +0100 +++ new/SQLAlchemy-Utils-0.37.8/tests/test_views.py 2021-06-15 11:51:54.000000000 +0200 @@ -32,7 +32,7 @@ def ArticleMV(Base, Article, User): class ArticleMV(Base): __table__ = create_materialized_view( - name='article_mv', + name='article-mv', selectable=sa.select( [ Article.id, @@ -47,7 +47,7 @@ ), aliases={'name': 'article_name'}, metadata=Base.metadata, - indexes=[sa.Index('article_mv_id_idx', 'id')] + indexes=[sa.Index('article-mv_id_idx', 'id')] ) return ArticleMV @@ -56,7 +56,7 @@ def ArticleView(Base, Article, User): class ArticleView(Base): __table__ = create_view( - name='article_view', + name='article-view', selectable=sa.select( [ Article.id, @@ -94,7 +94,7 @@ ) session.add(article) session.commit() - refresh_materialized_view(session, 'article_mv') + refresh_materialized_view(session, 'article-mv') materialized = session.query(ArticleMV).first() assert materialized.article_name == 'Some article' assert materialized.author_name == 'Some user' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SQLAlchemy-Utils-0.37.6/tests/types/test_timezone.py new/SQLAlchemy-Utils-0.37.8/tests/types/test_timezone.py --- old/SQLAlchemy-Utils-0.37.6/tests/types/test_timezone.py 2021-05-16 10:51:24.000000000 +0200 +++ new/SQLAlchemy-Utils-0.37.8/tests/types/test_timezone.py 2021-06-28 09:19:48.000000000 +0200 @@ -3,6 +3,11 @@ import sqlalchemy as sa from dateutil.zoneinfo import getzoneinfofile_stream, tzfile, ZoneInfoFile +try: + import zoneinfo +except ImportError: + from backports import zoneinfo + from sqlalchemy_utils.types import timezone, TimezoneType @@ -17,6 +22,9 @@ timezone_pytz = sa.Column( timezone.TimezoneType(backend='pytz') ) + timezone_zoneinfo = sa.Column( + timezone.TimezoneType(backend='zoneinfo') + ) def __repr__(self): return 'Visitor(%r)' % self.id @@ -32,7 +40,8 @@ def test_parameter_processing(self, session, Visitor): visitor = Visitor( timezone_dateutil=u'America/Los_Angeles', - timezone_pytz=u'America/Los_Angeles' + timezone_pytz=u'America/Los_Angeles', + timezone_zoneinfo=u'America/Los_Angeles' ) session.add(visitor) @@ -44,9 +53,13 @@ visitor_pytz = session.query(Visitor).filter_by( timezone_pytz=u'America/Los_Angeles' ).first() + visitor_zoneinfo = session.query(Visitor).filter_by( + timezone_zoneinfo=u'America/Los_Angeles' + ).first() assert visitor_dateutil is not None assert visitor_pytz is not None + assert visitor_zoneinfo is not None def test_compilation(self, Visitor, session): query = sa.select([Visitor.timezone_pytz]) @@ -54,7 +67,7 @@ session.execute(query) -TIMEZONE_BACKENDS = ['dateutil', 'pytz'] +TIMEZONE_BACKENDS = ['dateutil', 'pytz', 'zoneinfo'] def test_can_coerce_pytz_DstTzInfo(): @@ -83,12 +96,23 @@ assert isinstance(tzcol._coerce(zone), tzfile) +@pytest.mark.parametrize('zone', zoneinfo.available_timezones()) +def test_can_coerce_string_for_zoneinfo_zone(zone): + tzcol = TimezoneType(backend='zoneinfo') + assert str(tzcol._coerce(zone)) == zone + + @pytest.mark.parametrize('backend', TIMEZONE_BACKENDS) def test_can_coerce_and_raise_UnknownTimeZoneError_or_ValueError(backend): tzcol = TimezoneType(backend=backend) - with pytest.raises((ValueError, pytz.exceptions.UnknownTimeZoneError)): + exceptions = ( + ValueError, + pytz.exceptions.UnknownTimeZoneError, + zoneinfo.ZoneInfoNotFoundError + ) + with pytest.raises(exceptions): tzcol._coerce('SolarSystem/Mars') - with pytest.raises((ValueError, pytz.exceptions.UnknownTimeZoneError)): + with pytest.raises(exceptions): tzcol._coerce('') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/SQLAlchemy-Utils-0.37.6/tests/types/test_uuid.py new/SQLAlchemy-Utils-0.37.8/tests/types/test_uuid.py --- old/SQLAlchemy-Utils-0.37.6/tests/types/test_uuid.py 2021-05-16 10:51:24.000000000 +0200 +++ new/SQLAlchemy-Utils-0.37.8/tests/types/test_uuid.py 2021-06-15 12:02:56.000000000 +0200 @@ -2,6 +2,7 @@ import pytest import sqlalchemy as sa +from sqlalchemy.dialects import postgresql from sqlalchemy_utils import UUIDType @@ -60,3 +61,12 @@ query = sa.select([User.id]) # the type should be cacheable and not throw exception session.execute(query) + + def test_literal_bind(self, User): + expr = (User.id == 'b4e794d6-5750-4844-958c-fa382649719d').compile( + dialect=postgresql.dialect(), + compile_kwargs={'literal_binds': True} + ) + assert str(expr) == ( + '''"user".id = \'b4e794d6-5750-4844-958c-fa382649719d\'''' + )