Hello community, here is the log from the commit of package python-python-sql for openSUSE:Factory checked in at 2020-10-07 14:18:15 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-python-sql (Old) and /work/SRC/openSUSE:Factory/.python-python-sql.new.4249 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-python-sql" Wed Oct 7 14:18:15 2020 rev:5 rq:839885 version:1.2.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-python-sql/python-python-sql.changes 2020-01-27 20:16:59.320506081 +0100 +++ /work/SRC/openSUSE:Factory/.python-python-sql.new.4249/python-python-sql.changes 2020-10-07 14:18:23.049480805 +0200 @@ -1,0 +2,7 @@ +Tue Oct 6 08:20:02 UTC 2020 - Axel Braun <axel.br...@gmx.de> + +- Version 1.2.0 + * Add explicit Windows to Select + * Fix missing Windows definitions in nested expressions + +------------------------------------------------------------------- Old: ---- python-sql-1.1.0.tar.gz New: ---- python-sql-1.2.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-python-sql.spec ++++++ --- /var/tmp/diff_new_pack.EkEC8t/_old 2020-10-07 14:18:23.609481250 +0200 +++ /var/tmp/diff_new_pack.EkEC8t/_new 2020-10-07 14:18:23.613481253 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-python-sql # -# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2020 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,7 +19,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define base_name python-sql Name: python-%{base_name} -Version: 1.1.0 +Version: 1.2.0 Release: 0 Summary: Library to write SQL queries License: BSD-3-Clause ++++++ python-sql-1.1.0.tar.gz -> python-sql-1.2.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-sql-1.1.0/.drone.yml new/python-sql-1.2.0/.drone.yml --- old/python-sql-1.1.0/.drone.yml 2019-12-26 10:47:34.000000000 +0100 +++ new/python-sql-1.2.0/.drone.yml 2020-10-02 21:26:48.000000000 +0200 @@ -19,8 +19,6 @@ include: - IMAGE: python:2.7 TOXENV: py27 - - IMAGE: python:3.4 - TOXENV: py34 - IMAGE: python:3.5 TOXENV: py35 - IMAGE: python:3.6 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-sql-1.1.0/.flake8 new/python-sql-1.2.0/.flake8 --- old/python-sql-1.1.0/.flake8 1970-01-01 01:00:00.000000000 +0100 +++ new/python-sql-1.2.0/.flake8 2020-03-01 00:00:32.000000000 +0100 @@ -0,0 +1,2 @@ +[flake8] +ignore=E123,E124,E126,E128,W503 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-sql-1.1.0/.hgtags new/python-sql-1.2.0/.hgtags --- old/python-sql-1.1.0/.hgtags 2020-01-25 11:11:52.000000000 +0100 +++ new/python-sql-1.2.0/.hgtags 2020-10-05 18:37:13.000000000 +0200 @@ -9,3 +9,4 @@ e3bdeb99dd975024e30d8af18c324a0a7f860e63 0.9 7459778aa23150aa6ac39356621c29d368ae1f36 1.0.0 194182e5b0e2dc6486a32778860f29c80c0672f9 1.1.0 +de68c850bc6a809b0c88ddbe2fa99b02df07bee3 1.2.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-sql-1.1.0/CHANGELOG new/python-sql-1.2.0/CHANGELOG --- old/python-sql-1.1.0/CHANGELOG 2020-01-25 11:04:49.000000000 +0100 +++ new/python-sql-1.2.0/CHANGELOG 2020-10-05 18:33:14.000000000 +0200 @@ -1,3 +1,7 @@ +Version 1.2.0 - 2020-10-05 +* Add explicit Windows to Select +* Fix missing Windows definitions in nested expressions + Version 1.1.0 - 2020-01-25 * Add ORDER BY clause to aggregate functions * Add support for Python 3.8 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-sql-1.1.0/PKG-INFO new/python-sql-1.2.0/PKG-INFO --- old/python-sql-1.1.0/PKG-INFO 2020-01-25 11:12:36.000000000 +0100 +++ new/python-sql-1.2.0/PKG-INFO 2020-10-05 18:37:51.000000000 +0200 @@ -1,11 +1,15 @@ -Metadata-Version: 1.1 +Metadata-Version: 1.2 Name: python-sql -Version: 1.1.0 +Version: 1.2.0 Summary: Library to write SQL queries -Home-page: http://python-sql.tryton.org/ +Home-page: https://pypi.org/project/python-sql/ Author: Tryton Author-email: python-...@tryton.org License: BSD +Download-URL: https://downloads.tryton.org/python-sql/ +Project-URL: Bug Tracker, https://python-sql.tryton.org/ +Project-URL: Forum, https://discuss.tryton.org/tags/python-sql +Project-URL: Source Code, https://hg.tryton.org/python-sql/ Description: python-sql ========== @@ -211,6 +215,7 @@ >>> format2numeric(*select) ('SELECT * FROM "user" AS "a" WHERE ("a"."name" = :0)', ('foo',)) +Keywords: SQL database query Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers @@ -219,5 +224,11 @@ Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 +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: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 Classifier: Topic :: Database Classifier: Topic :: Software Development :: Libraries :: Python Modules diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-sql-1.1.0/python_sql.egg-info/PKG-INFO new/python-sql-1.2.0/python_sql.egg-info/PKG-INFO --- old/python-sql-1.1.0/python_sql.egg-info/PKG-INFO 2020-01-25 11:12:35.000000000 +0100 +++ new/python-sql-1.2.0/python_sql.egg-info/PKG-INFO 2020-10-05 18:37:50.000000000 +0200 @@ -1,11 +1,15 @@ -Metadata-Version: 1.1 +Metadata-Version: 1.2 Name: python-sql -Version: 1.1.0 +Version: 1.2.0 Summary: Library to write SQL queries -Home-page: http://python-sql.tryton.org/ +Home-page: https://pypi.org/project/python-sql/ Author: Tryton Author-email: python-...@tryton.org License: BSD +Download-URL: https://downloads.tryton.org/python-sql/ +Project-URL: Bug Tracker, https://python-sql.tryton.org/ +Project-URL: Forum, https://discuss.tryton.org/tags/python-sql +Project-URL: Source Code, https://hg.tryton.org/python-sql/ Description: python-sql ========== @@ -211,6 +215,7 @@ >>> format2numeric(*select) ('SELECT * FROM "user" AS "a" WHERE ("a"."name" = :0)', ('foo',)) +Keywords: SQL database query Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers @@ -219,5 +224,11 @@ Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 +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: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 Classifier: Topic :: Database Classifier: Topic :: Software Development :: Libraries :: Python Modules diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-sql-1.1.0/python_sql.egg-info/SOURCES.txt new/python-sql-1.2.0/python_sql.egg-info/SOURCES.txt --- old/python-sql-1.1.0/python_sql.egg-info/SOURCES.txt 2020-01-25 11:12:36.000000000 +0100 +++ new/python-sql-1.2.0/python_sql.egg-info/SOURCES.txt 2020-10-05 18:37:50.000000000 +0200 @@ -1,4 +1,5 @@ .drone.yml +.flake8 .hgtags CHANGELOG MANIFEST.in diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-sql-1.1.0/setup.py new/python-sql-1.2.0/setup.py --- old/python-sql-1.1.0/setup.py 2019-11-25 21:20:07.000000000 +0100 +++ new/python-sql-1.2.0/setup.py 2020-05-11 00:47:40.000000000 +0200 @@ -49,7 +49,14 @@ long_description=read('README'), author='Tryton', author_email='python-...@tryton.org', - url='http://python-sql.tryton.org/', + url='https://pypi.org/project/python-sql/', + download_url='https://downloads.tryton.org/python-sql/', + project_urls={ + "Bug Tracker": 'https://python-sql.tryton.org/', + "Forum": 'https://discuss.tryton.org/tags/python-sql', + "Source Code": 'https://hg.tryton.org/python-sql/', + }, + keywords='SQL database query', packages=find_packages(), classifiers=[ 'Development Status :: 5 - Production/Stable', @@ -59,6 +66,12 @@ 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', 'Topic :: Database', 'Topic :: Software Development :: Libraries :: Python Modules', ], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-sql-1.1.0/sql/__init__.py new/python-sql-1.2.0/sql/__init__.py --- old/python-sql-1.1.0/sql/__init__.py 2020-01-25 11:03:48.000000000 +0100 +++ new/python-sql-1.2.0/sql/__init__.py 2020-10-05 18:33:38.000000000 +0200 @@ -30,12 +30,13 @@ from __future__ import division import string +import numbers import warnings from threading import local, currentThread from collections import defaultdict from itertools import chain -__version__ = '1.1.0' +__version__ = '1.2.0' __all__ = ['Flavor', 'Table', 'Values', 'Literal', 'Column', 'Join', 'Asc', 'Desc', 'NullsFirst', 'NullsLast', 'format2numeric'] @@ -160,6 +161,14 @@ return cls.local.alias[id(from_)] @classmethod + def contains(cls, from_): + if getattr(cls.local, 'alias', None) is None: + return False + if from_ in cls.local.exclude: + return False + return id(from_) in cls.local.alias + + @classmethod def set(cls, from_, alias): assert cls.local.alias.get(from_) is None cls.local.alias[id(from_)] = alias @@ -250,6 +259,10 @@ def alias(self): return AliasManager.get(self) + @property + def has_alias(self): + return AliasManager.contains(self) + def __getattr__(self, name): if name.startswith('__'): raise AttributeError @@ -348,7 +361,7 @@ @limit.setter def limit(self, value): if value is not None: - assert isinstance(value, (int, long)) + assert isinstance(value, numbers.Integral) self._limit = value @property @@ -358,7 +371,7 @@ @offset.setter def offset(self, value): if value is not None: - assert isinstance(value, (int, long)) + assert isinstance(value, numbers.Integral) self._offset = value @property @@ -390,11 +403,11 @@ class Select(FromItem, SelectQuery): __slots__ = ('_columns', '_where', '_group_by', '_having', '_for_', - 'from_', '_distinct', '_distinct_on') + 'from_', '_distinct', '_distinct_on', '_windows') def __init__(self, columns, from_=None, where=None, group_by=None, having=None, for_=None, distinct=False, distinct_on=None, - **kwargs): + windows=None, **kwargs): self._distinct = False self._distinct_on = [] self._columns = None @@ -402,6 +415,7 @@ self._group_by = None self._having = None self._for_ = None + self._windows = [] super(Select, self).__init__(**kwargs) self.distinct = distinct self.distinct_on = distinct_on @@ -411,6 +425,7 @@ self.group_by = group_by self.having = having self.for_ = for_ + self.windows = windows @property def distinct(self): @@ -487,6 +502,34 @@ assert all(isinstance(f, For) for f in value) self._for_ = value + @property + def windows(self): + from sql.functions import WindowFunction + from sql.aggregate import Aggregate + windows = set() + if self._windows is not None: + for window in self._windows: + windows.add(window) + yield window + for column in self.columns: + window_function = None + if isinstance(column, (WindowFunction, Aggregate)): + window_function = column + elif (isinstance(column, As) + and isinstance(column.expression, + (WindowFunction, Aggregate))): + window_function = column.expression + if (window_function and window_function.window + and window_function.window not in windows): + windows.add(window_function.window) + yield window_function.window + + @windows.setter + def windows(self, value): + if value is not None: + assert all(isinstance(w, Window) for w in value) + self._windows = value + @staticmethod def _format_column(column): if isinstance(column, As): @@ -504,23 +547,6 @@ else: return str(column) - def _window_functions(self): - from sql.functions import WindowFunction - from sql.aggregate import Aggregate - windows = set() - for column in self.columns: - window_function = None - if isinstance(column, (WindowFunction, Aggregate)): - window_function = column - elif (isinstance(column, As) - and isinstance(column.expression, - (WindowFunction, Aggregate))): - window_function = column.expression - if (window_function and window_function.window - and window_function.window not in windows): - windows.add(window_function.window) - yield window_function - def _rownum(self, func): aliases = [c.output_name if isinstance(c, As) else None for c in self.columns] @@ -568,6 +594,13 @@ from_ = ' FROM %s' % self.from_ else: from_ = '' + + # format window before expressions to set alias + window = ', '.join( + '"%s" AS (%s)' % (w.alias, w) for w in self.windows) + if window: + window = ' WINDOW ' + window + if self.distinct: distinct = 'DISTINCT ' if self.distinct_on: @@ -588,11 +621,6 @@ having = '' if self.having: having = ' HAVING ' + str(self.having) - window = '' - windows = [f.window for f in self._window_functions()] - if windows: - window = ' WINDOW ' + ', '.join( - '"%s" AS (%s)' % (w.alias, w) for w in windows) for_ = '' if self.for_ is not None: for_ = ' ' + ' '.join(map(str, self.for_)) @@ -607,25 +635,30 @@ and (self.limit is not None or self.offset is not None)): return self._rownum(lambda q: q.params) p = [] - p.extend(self._with_params()) - for column in chain(self.distinct_on or (), self.columns): - if isinstance(column, As): - p.extend(column.expression.params) - p.extend(column.params) - if self.from_ is not None: - p.extend(self.from_.params) - if self.where: - p.extend(self.where.params) - if self.group_by: - for expression in self.group_by: - p.extend(expression.params) - if self.order_by: - for expression in self.order_by: - p.extend(expression.params) - if self.having: - p.extend(self.having.params) - for window_function in self._window_functions(): - p.extend(window_function.window.params) + with AliasManager(): + # Set alias to window function to skip their params + for window_function in self.windows: + window_function.alias + + p.extend(self._with_params()) + for column in chain(self.distinct_on or (), self.columns): + if isinstance(column, As): + p.extend(column.expression.params) + p.extend(column.params) + if self.from_ is not None: + p.extend(self.from_.params) + if self.where: + p.extend(self.where.params) + if self.group_by: + for expression in self.group_by: + p.extend(expression.params) + if self.order_by: + for expression in self.order_by: + p.extend(expression.params) + if self.having: + p.extend(self.having.params) + for window_function in self.windows: + p.extend(window_function.window.params) return tuple(p) @@ -1040,6 +1073,10 @@ def alias(self): raise AttributeError + @property + def has_alias(self): + raise AttributeError + def __getattr__(self, name): raise AttributeError @@ -1452,7 +1489,7 @@ @start.setter def start(self, value): if value: - assert isinstance(value, (int, long)) + assert isinstance(value, numbers.Integral) self._start = value @property @@ -1462,13 +1499,17 @@ @end.setter def end(self, value): if value: - assert isinstance(value, (int, long)) + assert isinstance(value, numbers.Integral) self._end = value @property def alias(self): return AliasManager.get(self) + @property + def has_alias(self): + return AliasManager.contains(self) + def __str__(self): partition = '' if self.partition: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-sql-1.1.0/sql/aggregate.py new/python-sql-1.2.0/sql/aggregate.py --- old/python-sql-1.1.0/sql/aggregate.py 2020-01-18 00:21:28.000000000 +0100 +++ new/python-sql-1.2.0/sql/aggregate.py 2020-09-29 12:39:19.000000000 +0200 @@ -127,7 +127,10 @@ filter_ = ' FILTER (WHERE %s)' % self.filter_ window = '' if self.window: - window = ' OVER "%s"' % self.window.alias + if self.window.has_alias: + window = ' OVER "%s"' % self.window.alias + else: + window = ' OVER (%s)' % self.window return aggregate + within + filter_ + window @property @@ -147,6 +150,8 @@ p.extend(expression.params) if self.filter_ and has_filter: p.extend(self.filter_.params) + if self.window and not self.window.has_alias: + p.extend(self.window.params) return tuple(p) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-sql-1.1.0/sql/functions.py new/python-sql-1.2.0/sql/functions.py --- old/python-sql-1.1.0/sql/functions.py 2019-11-07 13:48:36.000000000 +0100 +++ new/python-sql-1.2.0/sql/functions.py 2020-09-29 12:40:42.000000000 +0200 @@ -30,6 +30,11 @@ from sql import Expression, Flavor, FromItem, Window +try: + basestring +except NameError: + basestring = str + __all__ = ['Abs', 'Cbrt', 'Ceil', 'Degrees', 'Div', 'Exp', 'Floor', 'Ln', 'Log', 'Mod', 'Pi', 'Power', 'Radians', 'Random', 'Round', 'SetSeed', 'Sign', 'Sqrt', 'Trunc', 'WidthBucket', @@ -523,7 +528,10 @@ filter_ = '' if self.filter_: filter_ = ' FILTER (WHERE %s)' % self.filter_ - over = ' OVER "%s"' % self.window.alias + if self.window.has_alias: + over = ' OVER "%s"' % self.window.alias + else: + over = ' OVER (%s)' % self.window return function + filter_ + over @property @@ -531,6 +539,8 @@ p = list(super(WindowFunction, self).params) if self.filter_: p.extend(self.filter_.params) + if not self.window.has_alias: + p.extend(self.window.params) return tuple(p) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-sql-1.1.0/sql/operators.py new/python-sql-1.2.0/sql/operators.py --- old/python-sql-1.1.0/sql/operators.py 2018-09-30 14:17:53.000000000 +0200 +++ new/python-sql-1.2.0/sql/operators.py 2020-03-01 00:00:56.000000000 +0100 @@ -86,7 +86,7 @@ return param def __str__(self): - raise NotImplemented + raise NotImplementedError def __and__(self, other): if isinstance(other, And): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-sql-1.1.0/sql/tests/test_aggregate.py new/python-sql-1.2.0/sql/tests/test_aggregate.py --- old/python-sql-1.1.0/sql/tests/test_aggregate.py 2020-01-18 00:21:28.000000000 +0100 +++ new/python-sql-1.2.0/sql/tests/test_aggregate.py 2020-09-29 12:28:01.000000000 +0200 @@ -84,7 +84,7 @@ def test_window(self): avg = Avg(self.table.c, window=Window([])) with AliasManager(): - self.assertEqual(str(avg), 'AVG("a"."c") OVER "b"') + self.assertEqual(str(avg), 'AVG("a"."c") OVER ()') self.assertEqual(avg.params, ()) def test_distinct(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-sql-1.1.0/sql/tests/test_functions.py new/python-sql-1.2.0/sql/tests/test_functions.py --- old/python-sql-1.1.0/sql/tests/test_functions.py 2018-08-18 13:25:33.000000000 +0200 +++ new/python-sql-1.2.0/sql/tests/test_functions.py 2020-09-29 12:30:11.000000000 +0200 @@ -149,7 +149,7 @@ function = Rank(t.c, window=Window([])) with AliasManager(): - self.assertEqual(str(function), 'RANK("a"."c") OVER "b"') + self.assertEqual(str(function), 'RANK("a"."c") OVER ()') self.assertEqual(function.params, ()) def test_filter(self): @@ -158,5 +158,5 @@ with AliasManager(): self.assertEqual(str(function), - 'RANK("a"."c") FILTER (WHERE ("a"."c" > %s)) OVER "b"') + 'RANK("a"."c") FILTER (WHERE ("a"."c" > %s)) OVER ()') self.assertEqual(function.params, (0,)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-sql-1.1.0/sql/tests/test_select.py new/python-sql-1.2.0/sql/tests/test_select.py --- old/python-sql-1.1.0/sql/tests/test_select.py 2019-11-07 13:56:08.000000000 +0100 +++ new/python-sql-1.2.0/sql/tests/test_select.py 2020-09-29 12:59:59.000000000 +0200 @@ -33,7 +33,7 @@ from sql import Table, Join, Union, Literal, Flavor, For, With, Window, Select from sql.functions import Now, Function, Rank, DatePart -from sql.aggregate import Min +from sql.aggregate import Min, Max class TestSelect(unittest.TestCase): @@ -420,6 +420,39 @@ 'WINDOW "b" AS (PARTITION BY DATE_PART(%s, "a"."date_col"))') self.assertEqual(query.params, ('year',)) + window = Window([self.table.c2]) + query = self.table.select( + Max(self.table.c1, window=window) + / Min(self.table.c1, window=window)) + self.assertEqual(str(query), + 'SELECT (MAX("a"."c1") OVER (PARTITION BY "a"."c2") ' + '/ MIN("a"."c1") OVER (PARTITION BY "a"."c2")) ' + 'FROM "t" AS "a"') + self.assertEqual(query.params, ()) + + window = Window([Literal(1)]) + query = self.table.select( + Max(self.table.c1, window=window) + / Min(self.table.c1, window=window)) + self.assertEqual(str(query), + 'SELECT (MAX("a"."c1") OVER (PARTITION BY %s) ' + '/ MIN("a"."c1") OVER (PARTITION BY %s)) ' + 'FROM "t" AS "a"') + self.assertEqual(query.params, (1, 1)) + + window1 = Window([self.table.c2]) + window2 = Window([Literal(1)]) + query = self.table.select( + Max(self.table.c1, window=window1) + / Min(self.table.c1, window=window2), + windows=[window1]) + self.assertEqual(str(query), + 'SELECT (MAX("a"."c1") OVER "b" ' + '/ MIN("a"."c1") OVER (PARTITION BY %s)) ' + 'FROM "t" AS "a" ' + 'WINDOW "b" AS (PARTITION BY "a"."c2")') + self.assertEqual(query.params, (1,)) + def test_order_params(self): with_ = With(query=self.table.select(self.table.c, where=(self.table.c > 1)))