Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-peewee for openSUSE:Factory 
checked in at 2022-12-03 10:04:00
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-peewee (Old)
 and      /work/SRC/openSUSE:Factory/.python-peewee.new.1835 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-peewee"

Sat Dec  3 10:04:00 2022 rev:20 rq:1039750 version:3.15.4

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-peewee/python-peewee.changes      
2022-11-01 13:42:27.827862749 +0100
+++ /work/SRC/openSUSE:Factory/.python-peewee.new.1835/python-peewee.changes    
2022-12-03 10:04:14.619442717 +0100
@@ -1,0 +2,24 @@
+Fri Dec  2 21:43:51 UTC 2022 - Yogalakshmi Arunachalam <yarunacha...@suse.com>
+
+- Update to 3.15.4 
+  Raise an exception in ReconnectMixin if connection is lost while inside a 
transaction (if the transaction was interrupted presumably some changes were 
lost and explicit intervention is needed).
+  Add db.Model property to reduce boilerplate.
+  Add support for running prefetch() queries with joins instead of subqueries 
(this helps overcome a MySQL limitation about applying LIMITs to a subquery).
+  Add SQL AVG to whitelist to avoid coercing by default.
+  Allow arbitrary keywords in metaclass constructor, #2627
+  Add a pyproject.toml to silence warnings from newer pips when wheel package 
is not available.
+  This release has a small helper for reducing boilerplate in some cases by 
exposing a base model class as an attribute of the database instance.
+  # old:
+  db = SqliteDatabase('...')
+  class BaseModel(Model):
+    class Meta:
+        database = db
+  class MyModel(BaseModel):
+    pass
+
+  # new:
+  db = SqliteDatabase('...')
+  class MyModel(db.Model):
+    pass
+
+-------------------------------------------------------------------

Old:
----
  peewee-3.15.3.tar.gz

New:
----
  peewee-3.15.4.tar.gz

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

Other differences:
------------------
++++++ python-peewee.spec ++++++
--- /var/tmp/diff_new_pack.2sQj2x/_old  2022-12-03 10:04:15.015444918 +0100
+++ /var/tmp/diff_new_pack.2sQj2x/_new  2022-12-03 10:04:15.019444940 +0100
@@ -18,7 +18,7 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-peewee
-Version:        3.15.3
+Version:        3.15.4
 Release:        0
 Summary:        An expressive ORM that supports multiple SQL backends
 License:        BSD-3-Clause

++++++ peewee-3.15.3.tar.gz -> peewee-3.15.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/peewee-3.15.3/.github/workflows/tests.yaml 
new/peewee-3.15.4/.github/workflows/tests.yaml
--- old/peewee-3.15.3/.github/workflows/tests.yaml      2022-09-22 
04:55:53.000000000 +0200
+++ new/peewee-3.15.4/.github/workflows/tests.yaml      2022-11-11 
15:32:56.000000000 +0100
@@ -34,6 +34,8 @@
         include:
           - python-version: 3.6
             peewee-backend: cockroachdb
+          - python-version: "3.10"
+            peewee-backend: cockroachdb
     steps:
       - uses: actions/checkout@v2
       - uses: actions/setup-python@v2
@@ -54,9 +56,9 @@
       - name: crdb
         if: ${{ matrix.peewee-backend == 'cockroachdb' }}
         run: |
-          wget -qO- 
https://binaries.cockroachdb.com/cockroach-v20.1.1.linux-amd64.tgz | tar xz
-          ./cockroach-v20.1.1.linux-amd64/cockroach start-single-node 
--insecure --background
-          ./cockroach-v20.1.1.linux-amd64/cockroach sql --insecure -e 'create 
database peewee_test;'
+          wget -qO- 
https://binaries.cockroachdb.com/cockroach-v22.1.7.linux-amd64.tgz | tar xz
+          ./cockroach-v22.1.7.linux-amd64/cockroach start-single-node 
--insecure --background
+          ./cockroach-v22.1.7.linux-amd64/cockroach sql --insecure -e 'create 
database peewee_test;'
       - name: runtests ${{ matrix.peewee-backend }} - ${{ 
matrix.python-version }}
         env:
           PEEWEE_TEST_BACKEND: ${{ matrix.peewee-backend }}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/peewee-3.15.3/CHANGELOG.md 
new/peewee-3.15.4/CHANGELOG.md
--- old/peewee-3.15.3/CHANGELOG.md      2022-09-22 04:55:53.000000000 +0200
+++ new/peewee-3.15.4/CHANGELOG.md      2022-11-11 15:32:56.000000000 +0100
@@ -7,7 +7,43 @@
 
 ## master
 
-[View commits](https://github.com/coleifer/peewee/compare/3.15.3...master)
+[View commits](https://github.com/coleifer/peewee/compare/3.15.4...master)
+
+## 3.15.4
+
+* Raise an exception in `ReconnectMixin` if connection is lost while inside a
+  transaction (if the transaction was interrupted presumably some changes were
+  lost and explicit intervention is needed).
+* Add `db.Model` property to reduce boilerplate.
+* Add support for running `prefetch()` queries with joins instead of subqueries
+  (this helps overcome a MySQL limitation about applying LIMITs to a subquery).
+* Add SQL `AVG` to whitelist to avoid coercing by default.
+* Allow arbitrary keywords in metaclass constructor, #2627
+* Add a `pyproject.toml` to silence warnings from newer pips when `wheel`
+  package is not available.
+
+This release has a small helper for reducing boilerplate in some cases by
+exposing a base model class as an attribute of the database instance.
+
+```python
+# old:
+db = SqliteDatabase('...')
+
+class BaseModel(Model):
+    class Meta:
+        database = db
+
+class MyModel(BaseModel):
+    pass
+
+# new:
+db = SqliteDatabase('...')
+
+class MyModel(db.Model):
+    pass
+```
+
+[View commits](https://github.com/coleifer/peewee/compare/3.15.3...3.15.4)
 
 ## 3.15.3
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/peewee-3.15.3/README.rst new/peewee-3.15.4/README.rst
--- old/peewee-3.15.3/README.rst        2022-09-22 04:55:53.000000000 +0200
+++ new/peewee-3.15.4/README.rst        2022-11-11 15:32:56.000000000 +0100
@@ -104,7 +104,10 @@
              .group_by(User)
              .order_by(tweet_ct.desc()))
 
-    # Do an atomic update
+    # Do an atomic update (for illustrative purposes only, imagine a simple
+    # table for tracking a "count" associated with each URL). We don't want to
+    # naively get the save in two separate steps since this is prone to race
+    # conditions.
     Counter.update(count=Counter.count + 1).where(Counter.url == request.url)
 
 Check out the `example twitter app 
<http://docs.peewee-orm.com/en/latest/peewee/example.html>`_.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/peewee-3.15.3/bench.py new/peewee-3.15.4/bench.py
--- old/peewee-3.15.3/bench.py  2022-09-22 04:55:53.000000000 +0200
+++ new/peewee-3.15.4/bench.py  2022-11-11 15:32:56.000000000 +0100
@@ -117,6 +117,14 @@
         for i in c.items:
             pass
 
+@timed
+def select_prefetch_join(i):
+    query = prefetch(Collection.select(), Item,
+                     prefetch_type=PREFETCH_TYPE.JOIN)
+    for c in query:
+        for i in c.items:
+            pass
+
 
 if __name__ == '__main__':
     db.create_tables([Register, Collection, Item])
@@ -138,4 +146,5 @@
     select_related_dicts()
     select_related_dbapi_raw()
     select_prefetch()
+    select_prefetch_join()
     db.drop_tables([Register, Collection, Item])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/peewee-3.15.3/docs/peewee/api.rst 
new/peewee-3.15.4/docs/peewee/api.rst
--- old/peewee-3.15.3/docs/peewee/api.rst       2022-09-22 04:55:53.000000000 
+0200
+++ new/peewee-3.15.4/docs/peewee/api.rst       2022-11-11 15:32:56.000000000 
+0100
@@ -4784,14 +4784,20 @@
 
         Use Django-style filters to express a WHERE clause.
 
-    .. py:method:: prefetch(*subqueries)
+    .. py:method:: prefetch(*subqueries[, prefetch_type=PREFETCH_TYPE.WHERE])
 
         :param subqueries: A list of :py:class:`Model` classes or select
             queries to prefetch.
+        :param prefetch_type: Query type to use for the subqueries.
         :returns: a list of models with selected relations prefetched.
 
         Execute the query, prefetching the given additional resources.
 
+        Prefetch type may be one of:
+
+        * ``PREFETCH_TYPE.WHERE``
+        * ``PREFETCH_TYPE.JOIN``
+
         See also :py:func:`prefetch` standalone function.
 
         Example:
@@ -4812,15 +4818,23 @@
             mapped correctly.
 
 
-.. py:function:: prefetch(sq, *subqueries)
+.. py:function:: prefetch(sq, *subqueries[, prefetch_type=PREFETCH_TYPE.WHERE])
 
     :param sq: Query to use as starting-point.
     :param subqueries: One or more models or :py:class:`ModelSelect` queries
         to eagerly fetch.
+    :param prefetch_type: Query type to use for the subqueries.
     :returns: a list of models with selected relations prefetched.
 
     Eagerly fetch related objects, allowing efficient querying of multiple
-    tables when a 1-to-many relationship exists.
+    tables when a 1-to-many relationship exists. The prefetch type changes how
+    the subqueries are constructed which may be desirable dependending on the
+    database engine in use.
+
+        Prefetch type may be one of:
+
+        * ``PREFETCH_TYPE.WHERE``
+        * ``PREFETCH_TYPE.JOIN``
 
     For example, it is simple to query a many-to-1 relationship efficiently::
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/peewee-3.15.3/docs/peewee/playhouse.rst 
new/peewee-3.15.4/docs/peewee/playhouse.rst
--- old/peewee-3.15.3/docs/peewee/playhouse.rst 2022-09-22 04:55:53.000000000 
+0200
+++ new/peewee-3.15.4/docs/peewee/playhouse.rst 2022-11-11 15:32:56.000000000 
+0100
@@ -2997,6 +2997,26 @@
         migrator.add_column('comment_tbl', 'comment', comment_field),
     )
 
+.. note::
+    Peewee follows the Django convention of, by default, appending ``_id`` to
+    the column name for a given :py:class:`ForeignKeyField`. When adding a
+    foreign-key, you will want to ensure you give it the proper column name. 
For
+    example, if I want to add a ``user`` foreign-key to a ``Tweet`` model:
+
+    .. code-block:: python
+
+        # Our desired model will look like this:
+        class Tweet(BaseModel):
+            user = ForeignKeyField(User)  # I want to add this field.
+            # ... other fields ...
+
+        # Migration code:
+        user = ForeignKeyField(User, field=User.id, null=True)
+        migrate(
+            # Note that the column name given is "user_id".
+            migrator.add_column(Tweet._meta.table_name, 'user_id', user),
+        )
+
 Renaming a field:
 
 .. code-block:: python
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/peewee-3.15.3/docs/peewee/relationships.rst 
new/peewee-3.15.4/docs/peewee/relationships.rst
--- old/peewee-3.15.3/docs/peewee/relationships.rst     2022-09-22 
04:55:53.000000000 +0200
+++ new/peewee-3.15.4/docs/peewee/relationships.rst     2022-11-11 
15:32:56.000000000 +0100
@@ -1005,3 +1005,5 @@
 * Foreign keys must exist between the models being prefetched.
 * `LIMIT` works as you'd expect on the outer-most query, but may be difficult
   to implement correctly if trying to limit the size of the sub-selects.
+  * The parameter `prefetch_type` may be used when `LIMIT` is not supported
+    with the default query construction (e.g. with MySQL).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/peewee-3.15.3/peewee.py new/peewee-3.15.4/peewee.py
--- old/peewee-3.15.3/peewee.py 2022-09-22 04:55:53.000000000 +0200
+++ new/peewee-3.15.4/peewee.py 2022-11-11 15:32:56.000000000 +0100
@@ -70,7 +70,7 @@
         mysql = None
 
 
-__version__ = '3.15.3'
+__version__ = '3.15.4'
 __all__ = [
     'AnyField',
     'AsIs',
@@ -129,6 +129,7 @@
     'PostgresqlDatabase',
     'PrimaryKeyField',  # XXX: Deprecated, change to AutoField.
     'prefetch',
+    'PREFETCH_TYPE',
     'ProgrammingError',
     'Proxy',
     'QualifiedNames',
@@ -346,6 +347,11 @@
     CONSTRUCTOR=4,
     MODEL=5)
 
+# Query type to use with prefetch
+PREFETCH_TYPE = attrdict(
+    WHERE=1,
+    JOIN=2)
+
 SCOPE_NORMAL = 1
 SCOPE_SOURCE = 2
 SCOPE_VALUES = 4
@@ -458,6 +464,8 @@
     """
     Proxy implementation specifically for proxying `Database` objects.
     """
+    __slots__ = ('obj', '_callbacks', '_Model')
+
     def connection_context(self):
         return ConnectionContext(self)
     def atomic(self, *args, **kwargs):
@@ -468,6 +476,12 @@
         return _transaction(self, *args, **kwargs)
     def savepoint(self):
         return _savepoint(self)
+    @property
+    def Model(self):
+        if not hasattr(self, '_Model'):
+            class Meta: database = self
+            self._Model = type('BaseModel', (Model,), {'Meta': Meta})
+        return self._Model
 
 
 class ModelDescriptor(object): pass
@@ -1563,13 +1577,15 @@
 
 
 class Function(ColumnBase):
+    no_coerce_functions = set(('sum', 'count', 'avg', 'cast', 'array_agg'))
+
     def __init__(self, name, arguments, coerce=True, python_value=None):
         self.name = name
         self.arguments = arguments
         self._filter = None
         self._order_by = None
         self._python_value = python_value
-        if name and name.lower() in ('sum', 'count', 'cast', 'array_agg'):
+        if name and name.lower() in self.no_coerce_functions:
             self._coerce = False
         else:
             self._coerce = coerce
@@ -3441,6 +3457,13 @@
     def get_noop_select(self, ctx):
         return ctx.sql(Select().columns(SQL('0')).where(SQL('0')))
 
+    @property
+    def Model(self):
+        if not hasattr(self, '_Model'):
+            class Meta: database = self
+            self._Model = type('BaseModel', (Model,), {'Meta': Meta})
+        return self._Model
+
 
 def __pragma__(name):
     def __get__(self):
@@ -6266,9 +6289,10 @@
                        'only_save_dirty', 'legacy_table_names',
                        'table_settings', 'strict_tables'])
 
-    def __new__(cls, name, bases, attrs):
+    def __new__(cls, name, bases, attrs, **kwargs):
         if name == MODEL_BASE or bases[0].__name__ == MODEL_BASE:
-            return super(ModelBase, cls).__new__(cls, name, bases, attrs)
+            return super(ModelBase, cls).__new__(cls, name, bases, attrs,
+                                                 **kwargs)
 
         meta_options = {}
         meta = attrs.pop('Meta', None)
@@ -6308,7 +6332,7 @@
         Schema = meta_options.get('schema_manager_class', SchemaManager)
 
         # Construct the new class.
-        cls = super(ModelBase, cls).__new__(cls, name, bases, attrs)
+        cls = super(ModelBase, cls).__new__(cls, name, bases, attrs, **kwargs)
         cls.__data__ = cls.__rel__ = None
 
         cls._meta = Meta(cls, **meta_options)
@@ -7038,8 +7062,8 @@
             self.execute()
         return iter(self._cursor_wrapper)
 
-    def prefetch(self, *subqueries):
-        return prefetch(self, *subqueries)
+    def prefetch(self, *subqueries, **kwargs):
+        return prefetch(self, *subqueries, **kwargs)
 
     def get(self, database=None):
         clone = self.paginate(1, 1)
@@ -7864,7 +7888,7 @@
                 id_map[key].append(instance)
 
 
-def prefetch_add_subquery(sq, subqueries):
+def prefetch_add_subquery(sq, subqueries, prefetch_type):
     fixed_queries = [PrefetchQuery(sq)]
     for i, subquery in enumerate(subqueries):
         if isinstance(subquery, tuple):
@@ -7900,28 +7924,55 @@
         dest = (target_model,) if target_model else None
 
         if fks:
-            expr = reduce(operator.or_, [
-                (fk << last_query.select(pk))
-                for (fk, pk) in zip(fks, pks)])
-            subquery = subquery.where(expr)
+            if prefetch_type == PREFETCH_TYPE.WHERE:
+                expr = reduce(operator.or_, [
+                    (fk << last_query.select(pk))
+                    for (fk, pk) in zip(fks, pks)])
+                subquery = subquery.where(expr)
+            elif prefetch_type == PREFETCH_TYPE.JOIN:
+                expr = []
+                select_pks = []
+                for fk, pk in zip(fks, pks):
+                    expr.append(getattr(last_query.c, pk.column_name) == fk)
+                    select_pks.append(pk)
+                subquery = subquery.distinct().join(
+                    last_query.select(*select_pks),
+                    on=reduce(operator.or_, expr))
             fixed_queries.append(PrefetchQuery(subquery, fks, False, dest))
         elif backrefs:
-            expressions = []
+            expr = []
+            fields = []
             for backref in backrefs:
                 rel_field = getattr(subquery_model, backref.rel_field.name)
                 fk_field = getattr(last_obj, backref.name)
-                expressions.append(rel_field << last_query.select(fk_field))
-            subquery = subquery.where(reduce(operator.or_, expressions))
+                fields.append((rel_field, fk_field))
+
+            if prefetch_type == PREFETCH_TYPE.WHERE:
+                for rel_field, fk_field in fields:
+                    expr.append(rel_field << last_query.select(fk_field))
+                subquery = subquery.where(reduce(operator.or_, expr))
+            elif prefetch_type == PREFETCH_TYPE.JOIN:
+                select_fks = []
+                for rel_field, fk_field in fields:
+                    select_fks.append(fk_field)
+                    target = getattr(last_query.c, fk_field.column_name)
+                    expr.append(rel_field == target)
+                subquery = subquery.distinct().join(
+                    last_query.select(*select_fks),
+                    on=reduce(operator.or_, expr))
             fixed_queries.append(PrefetchQuery(subquery, backrefs, True, dest))
 
     return fixed_queries
 
 
-def prefetch(sq, *subqueries):
+def prefetch(sq, *subqueries, **kwargs):
     if not subqueries:
         return sq
+    prefetch_type = kwargs.pop('prefetch_type', PREFETCH_TYPE.WHERE)
+    if kwargs:
+        raise ValueError('Unrecognized arguments: %s' % kwargs)
 
-    fixed_queries = prefetch_add_subquery(sq, subqueries)
+    fixed_queries = prefetch_add_subquery(sq, subqueries, prefetch_type)
     deps = {}
     rel_map = {}
     for pq in reversed(fixed_queries):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/peewee-3.15.3/playhouse/shortcuts.py 
new/peewee-3.15.4/playhouse/shortcuts.py
--- old/peewee-3.15.3/playhouse/shortcuts.py    2022-09-22 04:55:53.000000000 
+0200
+++ new/peewee-3.15.4/playhouse/shortcuts.py    2022-11-11 15:32:56.000000000 
+0100
@@ -249,6 +249,11 @@
         try:
             return super(ReconnectMixin, self).execute_sql(sql, params, commit)
         except Exception as exc:
+            # If we are in a transaction, do not reconnect silently as
+            # any changes could be lost.
+            if self.in_transaction():
+                raise exc
+
             exc_class = type(exc)
             if exc_class not in self._reconnect_errors:
                 raise exc
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/peewee-3.15.3/pyproject.toml 
new/peewee-3.15.4/pyproject.toml
--- old/peewee-3.15.3/pyproject.toml    1970-01-01 01:00:00.000000000 +0100
+++ new/peewee-3.15.4/pyproject.toml    2022-11-11 15:32:56.000000000 +0100
@@ -0,0 +1,2 @@
+[build-system]
+requires = ["setuptools", "wheel"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/peewee-3.15.3/tests/db_tests.py 
new/peewee-3.15.4/tests/db_tests.py
--- old/peewee-3.15.3/tests/db_tests.py 2022-09-22 04:55:53.000000000 +0200
+++ new/peewee-3.15.4/tests/db_tests.py 2022-11-11 15:32:56.000000000 +0100
@@ -921,3 +921,24 @@
 
         if exc is None: raise Exception('expected integrity error not raised')
         self.assertTrue(exc.orig.__module__ != 'peewee')
+
+
+class TestModelPropertyHelper(BaseTestCase):
+    def test_model_property(self):
+        database = get_in_memory_db()
+        class M1(database.Model): pass
+        class M2(database.Model): pass
+        class CM1(M1): pass
+        for M in (M1, M2, CM1):
+            self.assertTrue(M._meta.database is database)
+
+    def test_model_property_on_proxy(self):
+        db = DatabaseProxy()
+        class M1(db.Model): pass
+        class M2(db.Model): pass
+        class CM1(M1): pass
+
+        test_db = get_in_memory_db()
+        db.initialize(test_db)
+        for M in (M1, M2, CM1):
+            self.assertEqual(M._meta.database.database, ':memory:')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/peewee-3.15.3/tests/manytomany.py 
new/peewee-3.15.4/tests/manytomany.py
--- old/peewee-3.15.3/tests/manytomany.py       2022-09-22 04:55:53.000000000 
+0200
+++ new/peewee-3.15.4/tests/manytomany.py       2022-11-11 15:32:56.000000000 
+0100
@@ -277,33 +277,37 @@
 
     def test_prefetch_notes(self):
         self._set_data()
-        with self.assertQueryCount(3):
-            gargie, huey, mickey, zaizee = prefetch(
-                User.select().order_by(User.username),
-                NoteUserThrough,
-                Note)
+        for pt in PREFETCH_TYPE.values():
+            with self.assertQueryCount(3):
+                gargie, huey, mickey, zaizee = prefetch(
+                    User.select().order_by(User.username),
+                    NoteUserThrough,
+                    Note,
+                    prefetch_type=pt)
 
-        with self.assertQueryCount(0):
-            self.assertNotes(gargie.notes, [1, 2])
-        with self.assertQueryCount(0):
-            self.assertNotes(zaizee.notes, [4, 5])
+            with self.assertQueryCount(0):
+                self.assertNotes(gargie.notes, [1, 2])
+            with self.assertQueryCount(0):
+                self.assertNotes(zaizee.notes, [4, 5])
         with self.assertQueryCount(2):
             self.assertNotes(User.create(username='x').notes, [])
 
     def test_prefetch_users(self):
         self._set_data()
-        with self.assertQueryCount(3):
-            n1, n2, n3, n4, n5 = prefetch(
-                Note.select().order_by(Note.text),
-                NoteUserThrough,
-                User)
+        for pt in PREFETCH_TYPE.values():
+            with self.assertQueryCount(3):
+                n1, n2, n3, n4, n5 = prefetch(
+                    Note.select().order_by(Note.text),
+                    NoteUserThrough,
+                    User,
+                    prefetch_type=pt)
 
-        with self.assertQueryCount(0):
-            self.assertUsers(n1.users, ['gargie'])
-        with self.assertQueryCount(0):
-            self.assertUsers(n2.users, ['gargie', 'huey'])
-        with self.assertQueryCount(0):
-            self.assertUsers(n5.users, ['zaizee'])
+            with self.assertQueryCount(0):
+                self.assertUsers(n1.users, ['gargie'])
+            with self.assertQueryCount(0):
+                self.assertUsers(n2.users, ['gargie', 'huey'])
+            with self.assertQueryCount(0):
+                self.assertUsers(n5.users, ['zaizee'])
         with self.assertQueryCount(2):
             self.assertUsers(Note.create(text='x').users, [])
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/peewee-3.15.3/tests/models.py 
new/peewee-3.15.4/tests/models.py
--- old/peewee-3.15.3/tests/models.py   2022-09-22 04:55:53.000000000 +0200
+++ new/peewee-3.15.4/tests/models.py   2022-11-11 15:32:56.000000000 +0100
@@ -1865,8 +1865,8 @@
         query = Sample.select(counter)
         self.assertEqual(query.scalar(), [0, 1, 2])
 
-    @requires_models(Category)
-    def test_no_coerce_count(self):
+    @requires_models(Category, Sample)
+    def test_no_coerce_count_avg(self):
         for i in range(10):
             Category.create(name=str(i))
 
@@ -1878,6 +1878,11 @@
         query = Category.select(fn.COUNT(Category.name).coerce(True))
         self.assertEqual(query.scalar(), '10')
 
+        # Ensure avg over an integer field is returned as a float.
+        Sample.insert_many([(1, 0), (2, 0)]).execute()
+        query = Sample.select(fn.AVG(Sample.counter).alias('a'))
+        self.assertEqual(query.get().a, 1.5)
+
 
 class TestJoinModelAlias(ModelTestCase):
     data = (
@@ -2482,6 +2487,20 @@
                  .returning(User.username.alias('new_username')))
         self.assertEqual([x.new_username for x in query.execute()], ['sipp'])
 
+        # Minimal test with insert_many.
+        query = User.insert_many([('u7',), ('u8',)])
+        self.assertEqual([r for r, in query.execute()], [7, 8])
+
+        # Test with insert / on conflict.
+        query = (User
+                 .insert_many([(7, 'u7',), (9, 'u9',)],
+                              [User.id, User.username])
+                 .on_conflict(conflict_target=[User.id],
+                              update={User.username: User.username + 'x'})
+                 .returning(User))
+        self.assertEqual([(x.id, x.username) for x in query],
+                         [(7, 'u7x'), (9, 'u9')])
+
     def test_simple_returning_insert_update_delete(self):
         res = User.insert(username='charlie').returning(User).execute()
         self.assertEqual([u.username for u in res], ['charlie'])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/peewee-3.15.3/tests/prefetch_tests.py 
new/peewee-3.15.4/tests/prefetch_tests.py
--- old/peewee-3.15.3/tests/prefetch_tests.py   2022-09-22 04:55:53.000000000 
+0200
+++ new/peewee-3.15.4/tests/prefetch_tests.py   2022-11-11 15:32:56.000000000 
+0100
@@ -100,164 +100,175 @@
         return accum
 
     def test_prefetch_simple(self):
-        with self.assertQueryCount(3):
-            people = Person.select().order_by(Person.name)
-            query = people.prefetch(Note, NoteItem)
-            accum = self.accumulate_results(query, sort_items=True)
-
-        self.assertEqual(accum, [
-            ('huey', [
-                ('hiss', ['hiss-1', 'hiss-2']),
-                ('meow', ['meow-1', 'meow-2', 'meow-3']),
-                ('purr', [])]),
-            ('mickey', [
-                ('bark', ['bark-1', 'bark-2']),
-                ('woof', [])]),
-            ('zaizee', []),
-        ])
+        for pt in PREFETCH_TYPE.values():
+            with self.assertQueryCount(3):
+                people = Person.select().order_by(Person.name)
+                query = people.prefetch(Note, NoteItem, prefetch_type=pt)
+                accum = self.accumulate_results(query, sort_items=True)
 
-    def test_prefetch_filter(self):
-        with self.assertQueryCount(3):
-            people = Person.select().order_by(Person.name)
-            notes = (Note
-                     .select()
-                     .where(Note.content.not_in(('hiss', 'meow', 'woof')))
-                     .order_by(Note.content.desc()))
-            items = NoteItem.select().where(~NoteItem.content.endswith('-2'))
-            query = prefetch(people, notes, items)
-            self.assertEqual(self.accumulate_results(query), [
-                ('huey', [('purr', [])]),
-                ('mickey', [('bark', ['bark-1'])]),
+            self.assertEqual(accum, [
+                ('huey', [
+                    ('hiss', ['hiss-1', 'hiss-2']),
+                    ('meow', ['meow-1', 'meow-2', 'meow-3']),
+                    ('purr', [])]),
+                ('mickey', [
+                    ('bark', ['bark-1', 'bark-2']),
+                    ('woof', [])]),
                 ('zaizee', []),
             ])
 
+    def test_prefetch_filter(self):
+        for pt in PREFETCH_TYPE.values():
+            with self.assertQueryCount(3):
+                people = Person.select().order_by(Person.name)
+                notes = (Note
+                         .select()
+                         .where(Note.content.not_in(('hiss', 'meow', 'woof')))
+                         .order_by(Note.content.desc()))
+                items = NoteItem.select().where(
+                    ~NoteItem.content.endswith('-2'))
+                query = prefetch(people, notes, items, prefetch_type=pt)
+                self.assertEqual(self.accumulate_results(query), [
+                    ('huey', [('purr', [])]),
+                    ('mickey', [('bark', ['bark-1'])]),
+                    ('zaizee', []),
+                ])
+
     def test_prefetch_reverse(self):
-        with self.assertQueryCount(2):
+        for pt in PREFETCH_TYPE.values():
+            with self.assertQueryCount(2):
+                people = Person.select().order_by(Person.name)
+                notes = Note.select().order_by(Note.content)
+                query = prefetch(notes, people, prefetch_type=pt)
+                accum = [(note.content, note.person.name) for note in query]
+                self.assertEqual(accum, [
+                    ('bark', 'mickey'),
+                    ('hiss', 'huey'),
+                    ('meow', 'huey'),
+                    ('purr', 'huey'),
+                    ('woof', 'mickey')])
+
+    def test_prefetch_reverse_with_parent_join(self):
+        for pt in PREFETCH_TYPE.values():
+            with self.assertQueryCount(2):
+                notes = (Note
+                         .select(Note, Person)
+                         .join(Person)
+                         .order_by(Note.content))
+                items = NoteItem.select().order_by(NoteItem.content.desc())
+                query = prefetch(notes, items, prefetch_type=pt)
+                accum = [(note.person.name,
+                          note.content,
+                          [item.content for item in note.items])
+                         for note in query]
+                self.assertEqual(accum, [
+                    ('mickey', 'bark', ['bark-2', 'bark-1']),
+                    ('huey', 'hiss', ['hiss-2', 'hiss-1']),
+                    ('huey', 'meow', ['meow-3', 'meow-2', 'meow-1']),
+                    ('huey', 'purr', []),
+                    ('mickey', 'woof', []),
+                ])
+
+    def test_prefetch_multi_depth(self):
+        for pt in PREFETCH_TYPE.values():
             people = Person.select().order_by(Person.name)
             notes = Note.select().order_by(Note.content)
-            query = prefetch(notes, people)
-            accum = [(note.content, note.person.name) for note in query]
-            self.assertEqual(accum, [
-                ('bark', 'mickey'),
-                ('hiss', 'huey'),
-                ('meow', 'huey'),
-                ('purr', 'huey'),
-                ('woof', 'mickey')])
+            items = NoteItem.select().order_by(NoteItem.content)
+            flags = Flag.select().order_by(Flag.id)
+
+            LikePerson = Person.alias('lp')
+            likes = (Like
+                     .select(Like, LikePerson.name)
+                     .join(LikePerson, on=(Like.person == LikePerson.id)))
+
+            # Five queries:
+            # - person (outermost query)
+            # - notes for people
+            # - items for notes
+            # - flags for notes
+            # - likes for notes (includes join to person)
+            with self.assertQueryCount(5):
+                query = prefetch(people, notes, items, flags, likes,
+                                 prefetch_type=pt)
+                accum = []
+                for person in query:
+                    notes = []
+                    for note in person.notes:
+                        items = [item.content for item in note.items]
+                        likes = [like.person.name for like in note.likes]
+                        flags = [flag.is_spam for flag in note.flags]
+                        notes.append((note.content, items, likes, flags))
+                    accum.append((person.name, notes))
 
-    def test_prefetch_reverse_with_parent_join(self):
-        with self.assertQueryCount(2):
-            notes = (Note
-                     .select(Note, Person)
-                     .join(Person)
-                     .order_by(Note.content))
-            items = NoteItem.select().order_by(NoteItem.content.desc())
-            query = prefetch(notes, items)
-            accum = [(note.person.name,
-                      note.content,
-                      [item.content for item in note.items]) for note in query]
             self.assertEqual(accum, [
-                ('mickey', 'bark', ['bark-2', 'bark-1']),
-                ('huey', 'hiss', ['hiss-2', 'hiss-1']),
-                ('huey', 'meow', ['meow-3', 'meow-2', 'meow-1']),
-                ('huey', 'purr', []),
-                ('mickey', 'woof', []),
+                ('huey', [
+                    ('hiss', ['hiss-1', 'hiss-2'], [], []),
+                    ('meow', ['meow-1', 'meow-2', 'meow-3'], ['mickey'], []),
+                    ('purr', [], [], [True])]),
+                ('mickey', [
+                    ('bark', ['bark-1', 'bark-2'], [], []),
+                    ('woof', [], ['huey'], [True])]),
+                (u'zaizee', []),
             ])
 
-    def test_prefetch_multi_depth(self):
-        people = Person.select().order_by(Person.name)
-        notes = Note.select().order_by(Note.content)
-        items = NoteItem.select().order_by(NoteItem.content)
-        flags = Flag.select().order_by(Flag.id)
-
-        LikePerson = Person.alias('lp')
-        likes = (Like
-                 .select(Like, LikePerson.name)
-                 .join(LikePerson, on=(Like.person == LikePerson.id)))
-
-        # Five queries:
-        # - person (outermost query)
-        # - notes for people
-        # - items for notes
-        # - flags for notes
-        # - likes for notes (includes join to person)
-        with self.assertQueryCount(5):
-            query = prefetch(people, notes, items, flags, likes)
-            accum = []
-            for person in query:
-                notes = []
-                for note in person.notes:
-                    items = [item.content for item in note.items]
-                    likes = [like.person.name for like in note.likes]
-                    flags = [flag.is_spam for flag in note.flags]
-                    notes.append((note.content, items, likes, flags))
-                accum.append((person.name, notes))
-
-        self.assertEqual(accum, [
-            ('huey', [
-                ('hiss', ['hiss-1', 'hiss-2'], [], []),
-                ('meow', ['meow-1', 'meow-2', 'meow-3'], ['mickey'], []),
-                ('purr', [], [], [True])]),
-            ('mickey', [
-                ('bark', ['bark-1', 'bark-2'], [], []),
-                ('woof', [], ['huey'], [True])]),
-            (u'zaizee', []),
-        ])
-
     def test_prefetch_multi_depth_no_join(self):
-        LikePerson = Person.alias()
-        people = Person.select().order_by(Person.name)
-        notes = Note.select().order_by(Note.content)
-        items = NoteItem.select().order_by(NoteItem.content)
-        flags = Flag.select().order_by(Flag.id)
-
-        with self.assertQueryCount(6):
-            query = prefetch(people, notes, items, flags, Like, LikePerson)
-            accum = []
-            for person in query:
-                notes = []
-                for note in person.notes:
-                    items = [item.content for item in note.items]
-                    likes = [like.person.name for like in note.likes]
-                    flags = [flag.is_spam for flag in note.flags]
-                    notes.append((note.content, items, likes, flags))
-                accum.append((person.name, notes))
-
-        self.assertEqual(accum, [
-            ('huey', [
-                ('hiss', ['hiss-1', 'hiss-2'], [], []),
-                ('meow', ['meow-1', 'meow-2', 'meow-3'], ['mickey'], []),
-                ('purr', [], [], [True])]),
-            ('mickey', [
-                ('bark', ['bark-1', 'bark-2'], [], []),
-                ('woof', [], ['huey'], [True])]),
-            (u'zaizee', []),
-        ])
+        for pt in PREFETCH_TYPE.values():
+            LikePerson = Person.alias()
+            people = Person.select().order_by(Person.name)
+            notes = Note.select().order_by(Note.content)
+            items = NoteItem.select().order_by(NoteItem.content)
+            flags = Flag.select().order_by(Flag.id)
 
-    def test_prefetch_with_group_by(self):
-        people = (Person
-                  .select(Person, fn.COUNT(Note.id).alias('note_count'))
-                  .join(Note, JOIN.LEFT_OUTER)
-                  .group_by(Person)
-                  .order_by(Person.name))
-        notes = Note.select().order_by(Note.content)
-        items = NoteItem.select().order_by(NoteItem.content)
-        with self.assertQueryCount(3):
-            query = prefetch(people, notes, items)
-            self.assertEqual(self.accumulate_results(query), [
+            with self.assertQueryCount(6):
+                query = prefetch(people, notes, items, flags, Like, LikePerson,
+                                 prefetch_type=pt)
+                accum = []
+                for person in query:
+                    notes = []
+                    for note in person.notes:
+                        items = [item.content for item in note.items]
+                        likes = [like.person.name for like in note.likes]
+                        flags = [flag.is_spam for flag in note.flags]
+                        notes.append((note.content, items, likes, flags))
+                    accum.append((person.name, notes))
+
+            self.assertEqual(accum, [
                 ('huey', [
-                    ('hiss', ['hiss-1', 'hiss-2']),
-                    ('meow', ['meow-1', 'meow-2', 'meow-3']),
-                    ('purr', [])]),
+                    ('hiss', ['hiss-1', 'hiss-2'], [], []),
+                    ('meow', ['meow-1', 'meow-2', 'meow-3'], ['mickey'], []),
+                    ('purr', [], [], [True])]),
                 ('mickey', [
-                    ('bark', ['bark-1', 'bark-2']),
-                    ('woof', [])]),
-                ('zaizee', []),
+                    ('bark', ['bark-1', 'bark-2'], [], []),
+                    ('woof', [], ['huey'], [True])]),
+                (u'zaizee', []),
             ])
 
-            huey, mickey, zaizee = query
-            self.assertEqual(huey.note_count, 3)
-            self.assertEqual(mickey.note_count, 2)
-            self.assertEqual(zaizee.note_count, 0)
+    def test_prefetch_with_group_by(self):
+        for pt in PREFETCH_TYPE.values():
+            people = (Person
+                      .select(Person, fn.COUNT(Note.id).alias('note_count'))
+                      .join(Note, JOIN.LEFT_OUTER)
+                      .group_by(Person)
+                      .order_by(Person.name))
+            notes = Note.select().order_by(Note.content)
+            items = NoteItem.select().order_by(NoteItem.content)
+            with self.assertQueryCount(3):
+                query = prefetch(people, notes, items, prefetch_type=pt)
+                self.assertEqual(self.accumulate_results(query), [
+                    ('huey', [
+                        ('hiss', ['hiss-1', 'hiss-2']),
+                        ('meow', ['meow-1', 'meow-2', 'meow-3']),
+                        ('purr', [])]),
+                    ('mickey', [
+                        ('bark', ['bark-1', 'bark-2']),
+                        ('woof', [])]),
+                    ('zaizee', []),
+                ])
+
+                huey, mickey, zaizee = query
+                self.assertEqual(huey.note_count, 3)
+                self.assertEqual(mickey.note_count, 2)
+                self.assertEqual(zaizee.note_count, 0)
 
     @requires_models(Category)
     def test_prefetch_self_join(self):
@@ -270,22 +281,24 @@
             for i in range(2):
                 cc('%s-%s' % (p.name, i + 1), p)
 
-        Child = Category.alias('child')
-        with self.assertQueryCount(2):
-            query = prefetch(Category.select().order_by(Category.id), Child)
-            names_and_children = [
-                (cat.name, [child.name for child in cat.children])
-                for cat in query]
-
-        self.assertEqual(names_and_children, [
-            ('root', ['p1', 'p2']),
-            ('p1', ['p1-1', 'p1-2']),
-            ('p2', ['p2-1', 'p2-2']),
-            ('p1-1', []),
-            ('p1-2', []),
-            ('p2-1', []),
-            ('p2-2', []),
-        ])
+        for pt in PREFETCH_TYPE.values():
+            Child = Category.alias('child')
+            with self.assertQueryCount(2):
+                query = prefetch(Category.select().order_by(Category.id),
+                                 Child, prefetch_type=pt)
+                names_and_children = [
+                    (cat.name, [child.name for child in cat.children])
+                    for cat in query]
+
+            self.assertEqual(names_and_children, [
+                ('root', ['p1', 'p2']),
+                ('p1', ['p1-1', 'p1-2']),
+                ('p2', ['p2-1', 'p2-2']),
+                ('p1-1', []),
+                ('p1-2', []),
+                ('p2-1', []),
+                ('p2-2', []),
+            ])
 
     @requires_models(Category)
     def test_prefetch_adjacency_list(self):
@@ -313,21 +326,23 @@
             for child_tree in children:
                 stack.insert(0, (node, child_tree))
 
-        C = Category.alias('c')
-        G = Category.alias('g')
-        GG = Category.alias('gg')
-        GGG = Category.alias('ggg')
-        query = Category.select().where(Category.name == 'root')
-        with self.assertQueryCount(5):
-            pf = prefetch(query, C, (G, C), (GG, G), (GGG, GG))
-            def gather(c):
-                children = sorted([gather(ch) for ch in c.children])
-                return (c.name, tuple(children))
-            nodes = list(pf)
-            self.assertEqual(len(nodes), 1)
-            pf_tree = gather(nodes[0])
+        for pt in PREFETCH_TYPE.values():
+            C = Category.alias('c')
+            G = Category.alias('g')
+            GG = Category.alias('gg')
+            GGG = Category.alias('ggg')
+            query = Category.select().where(Category.name == 'root')
+            with self.assertQueryCount(5):
+                pf = prefetch(query, C, (G, C), (GG, G), (GGG, GG),
+                              prefetch_type=pt)
+                def gather(c):
+                    children = sorted([gather(ch) for ch in c.children])
+                    return (c.name, tuple(children))
+                nodes = list(pf)
+                self.assertEqual(len(nodes), 1)
+                pf_tree = gather(nodes[0])
 
-        self.assertEqual(tree, pf_tree)
+            self.assertEqual(tree, pf_tree)
 
     def test_prefetch_specific_model(self):
         # Person -> Note
@@ -336,29 +351,31 @@
                     person=Person.get(Person.name == 'zaizee'))
         NoteAlias = Note.alias('na')
 
-        with self.assertQueryCount(3):
-            people = Person.select().order_by(Person.name)
-            notes = Note.select().order_by(Note.content)
-            likes = (Like
-                     .select(Like, NoteAlias.content)
-                     .join(NoteAlias, on=(Like.note == NoteAlias.id))
-                     .order_by(NoteAlias.content))
-            query = prefetch(people, notes, (likes, Person))
-            accum = []
-            for person in query:
-                likes = []
-                notes = []
-                for note in person.notes:
-                    notes.append(note.content)
-                for like in person.likes:
-                    likes.append(like.note.content)
-                accum.append((person.name, notes, likes))
-
-        self.assertEqual(accum, [
-            ('huey', ['hiss', 'meow', 'purr'], ['woof']),
-            ('mickey', ['bark', 'woof'], ['meow']),
-            ('zaizee', [], ['woof']),
-        ])
+        for pt in PREFETCH_TYPE.values():
+            with self.assertQueryCount(3):
+                people = Person.select().order_by(Person.name)
+                notes = Note.select().order_by(Note.content)
+                likes = (Like
+                         .select(Like, NoteAlias.content)
+                         .join(NoteAlias, on=(Like.note == NoteAlias.id))
+                         .order_by(NoteAlias.content))
+                query = prefetch(people, notes, (likes, Person),
+                                 prefetch_type=pt)
+                accum = []
+                for person in query:
+                    likes = []
+                    notes = []
+                    for note in person.notes:
+                        notes.append(note.content)
+                    for like in person.likes:
+                        likes.append(like.note.content)
+                    accum.append((person.name, notes, likes))
+
+            self.assertEqual(accum, [
+                ('huey', ['hiss', 'meow', 'purr'], ['woof']),
+                ('mickey', ['bark', 'woof'], ['meow']),
+                ('zaizee', [], ['woof']),
+            ])
 
     @requires_models(Relationship)
     def test_multiple_foreign_keys(self):
@@ -373,43 +390,44 @@
         r4 = RC(z, c)
 
         def assertRelationships(attr, values):
+            self.assertEqual(len(attr),len(values))
             for relationship, value in zip(attr, values):
                 self.assertEqual(relationship.__data__, value)
 
-        with self.assertQueryCount(2):
-            people = Person.select().order_by(Person.name)
-            relationships = Relationship.select().order_by(Relationship.id)
-
-            query = prefetch(people, relationships)
-            cp, hp, zp = list(query)
-
-            assertRelationships(cp.relationships, [
-                {'id': r1.id, 'from_person': c.id, 'to_person': h.id},
-                {'id': r2.id, 'from_person': c.id, 'to_person': z.id}])
-            assertRelationships(cp.related_to, [
-                {'id': r3.id, 'from_person': h.id, 'to_person': c.id},
-                {'id': r4.id, 'from_person': z.id, 'to_person': c.id}])
-
-            assertRelationships(hp.relationships, [
-                {'id': r3.id, 'from_person': h.id, 'to_person': c.id}])
-            assertRelationships(hp.related_to, [
-                {'id': r1.id, 'from_person': c.id, 'to_person': h.id}])
-
-            assertRelationships(zp.relationships, [
-                {'id': r4.id, 'from_person': z.id, 'to_person': c.id}])
-            assertRelationships(zp.related_to, [
-                {'id': r2.id, 'from_person': c.id, 'to_person': z.id}])
-
-        with self.assertQueryCount(2):
-            query = prefetch(relationships, people)
-            accum = []
-            for row in query:
-                accum.append((row.from_person.name, row.to_person.name))
-            self.assertEqual(accum, [
-                ('charlie', 'huey'),
-                ('charlie', 'zaizee'),
-                ('huey', 'charlie'),
-                ('zaizee', 'charlie')])
+        for pt in PREFETCH_TYPE.values():
+            with self.assertQueryCount(2):
+                people = Person.select().order_by(Person.name)
+                relationships = Relationship.select().order_by(Relationship.id)
+                query = prefetch(people, relationships, prefetch_type=pt)
+                cp, hp, zp = list(query)
+
+                assertRelationships(cp.relationships, [
+                    {'id': r1.id, 'from_person': c.id, 'to_person': h.id},
+                    {'id': r2.id, 'from_person': c.id, 'to_person': z.id}])
+                assertRelationships(cp.related_to, [
+                    {'id': r3.id, 'from_person': h.id, 'to_person': c.id},
+                    {'id': r4.id, 'from_person': z.id, 'to_person': c.id}])
+
+                assertRelationships(hp.relationships, [
+                    {'id': r3.id, 'from_person': h.id, 'to_person': c.id}])
+                assertRelationships(hp.related_to, [
+                    {'id': r1.id, 'from_person': c.id, 'to_person': h.id}])
+
+                assertRelationships(zp.relationships, [
+                    {'id': r4.id, 'from_person': z.id, 'to_person': c.id}])
+                assertRelationships(zp.related_to, [
+                    {'id': r2.id, 'from_person': c.id, 'to_person': z.id}])
+
+            with self.assertQueryCount(2):
+                query = prefetch(relationships, people, prefetch_type=pt)
+                accum = []
+                for row in query:
+                    accum.append((row.from_person.name, row.to_person.name))
+                self.assertEqual(accum, [
+                    ('charlie', 'huey'),
+                    ('charlie', 'zaizee'),
+                    ('huey', 'charlie'),
+                    ('zaizee', 'charlie')])
 
         m = Person.create(name='mickey')
         RC(h, m)
@@ -418,34 +436,35 @@
             self.assertEqual([r.to_person.name for r in p.relationships], ns)
 
         # Use prefetch to go Person -> Relationship <- Person (PA).
-        with self.assertQueryCount(3):
-            people = (Person
-                      .select()
-                      .where(Person.name != 'mickey')
-                      .order_by(Person.name))
-            relationships = Relationship.select().order_by(Relationship.id)
-            PA = Person.alias()
-            query = prefetch(people, relationships, PA)
-            cp, hp, zp = list(query)
-            assertNames(cp, ['huey', 'zaizee'])
-            assertNames(hp, ['charlie', 'mickey'])
-            assertNames(zp, ['charlie'])
-
-        # User prefetch to go Person -> Relationship+Person (PA).
-        with self.assertQueryCount(2):
-            people = (Person
-                      .select()
-                      .where(Person.name != 'mickey')
-                      .order_by(Person.name))
-            rels = (Relationship
-                    .select(Relationship, PA)
-                    .join(PA, on=(Relationship.to_person == PA.id))
-                    .order_by(Relationship.id))
-            query = prefetch(people, rels)
-            cp, hp, zp = list(query)
-            assertNames(cp, ['huey', 'zaizee'])
-            assertNames(hp, ['charlie', 'mickey'])
-            assertNames(zp, ['charlie'])
+        for pt in PREFETCH_TYPE.values():
+            with self.assertQueryCount(3):
+                people = (Person
+                          .select()
+                          .where(Person.name != 'mickey')
+                          .order_by(Person.name))
+                relationships = Relationship.select().order_by(Relationship.id)
+                PA = Person.alias()
+                query = prefetch(people, relationships, PA, prefetch_type=pt)
+                cp, hp, zp = list(query)
+                assertNames(cp, ['huey', 'zaizee'])
+                assertNames(hp, ['charlie', 'mickey'])
+                assertNames(zp, ['charlie'])
+
+            # User prefetch to go Person -> Relationship+Person (PA).
+            with self.assertQueryCount(2):
+                people = (Person
+                          .select()
+                          .where(Person.name != 'mickey')
+                          .order_by(Person.name))
+                rels = (Relationship
+                        .select(Relationship, PA)
+                        .join(PA, on=(Relationship.to_person == PA.id))
+                        .order_by(Relationship.id))
+                query = prefetch(people, rels, prefetch_type=pt)
+                cp, hp, zp = list(query)
+                assertNames(cp, ['huey', 'zaizee'])
+                assertNames(hp, ['charlie', 'mickey'])
+                assertNames(zp, ['charlie'])
 
     def test_prefetch_through_manytomany(self):
         Like.create(note=Note.get(Note.content == 'meow'),
@@ -453,23 +472,24 @@
         Like.create(note=Note.get(Note.content == 'woof'),
                     person=Person.get(Person.name == 'zaizee'))
 
-        with self.assertQueryCount(3):
-            people = Person.select().order_by(Person.name)
-            notes = Note.select().order_by(Note.content)
-            likes = Like.select().order_by(Like.id)
-            query = prefetch(people, likes, notes)
-            accum = []
-            for person in query:
-                liked_notes = []
-                for like in person.likes:
-                    liked_notes.append(like.note.content)
-                accum.append((person.name, liked_notes))
-
-        self.assertEqual(accum, [
-            ('huey', ['woof']),
-            ('mickey', ['meow']),
-            ('zaizee', ['meow', 'woof']),
-        ])
+        for pt in PREFETCH_TYPE.values():
+            with self.assertQueryCount(3):
+                people = Person.select().order_by(Person.name)
+                notes = Note.select().order_by(Note.content)
+                likes = Like.select().order_by(Like.id)
+                query = prefetch(people, likes, notes, prefetch_type=pt)
+                accum = []
+                for person in query:
+                    liked_notes = []
+                    for like in person.likes:
+                        liked_notes.append(like.note.content)
+                    accum.append((person.name, liked_notes))
+
+            self.assertEqual(accum, [
+                ('huey', ['woof']),
+                ('mickey', ['meow']),
+                ('zaizee', ['meow', 'woof']),
+            ])
 
     @requires_models(Package, PackageItem)
     def test_prefetch_non_pk_fk(self):
@@ -484,22 +504,24 @@
             for item in items:
                 PackageItem.create(package=barcode, name=item)
 
-        packages = Package.select().order_by(Package.barcode)
-        items = PackageItem.select().order_by(PackageItem.name)
-
-        with self.assertQueryCount(2):
-            query = prefetch(packages, items)
-            for package, (barcode, items) in zip(query, data):
-                self.assertEqual(package.barcode, barcode)
-                self.assertEqual([item.name for item in package.items],
-                                 list(items))
+        for pt in PREFETCH_TYPE.values():
+            packages = Package.select().order_by(Package.barcode)
+            items = PackageItem.select().order_by(PackageItem.name)
+
+            with self.assertQueryCount(2):
+                query = prefetch(packages, items, prefetch_type=pt)
+                for package, (barcode, items) in zip(query, data):
+                    self.assertEqual(package.barcode, barcode)
+                    self.assertEqual([item.name for item in package.items],
+                                     list(items))
 
     def test_prefetch_mark_dirty_regression(self):
-        people = Person.select().order_by(Person.name)
-        query = people.prefetch(Note, NoteItem)
-        for person in query:
-            self.assertEqual(person.dirty_fields, [])
-            for note in person.notes:
-                self.assertEqual(note.dirty_fields, [])
-                for item in note.items:
-                    self.assertEqual(item.dirty_fields, [])
+        for pt in PREFETCH_TYPE.values():
+            people = Person.select().order_by(Person.name)
+            query = people.prefetch(Note, NoteItem, prefetch_type=pt)
+            for person in query:
+                self.assertEqual(person.dirty_fields, [])
+                for note in person.notes:
+                    self.assertEqual(note.dirty_fields, [])
+                    for item in note.items:
+                        self.assertEqual(item.dirty_fields, [])

Reply via email to