Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-more-itertools for 
openSUSE:Factory checked in at 2022-11-01 13:41:10
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-more-itertools (Old)
 and      /work/SRC/openSUSE:Factory/.python-more-itertools.new.2275 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-more-itertools"

Tue Nov  1 13:41:10 2022 rev:21 rq:1032501 version:9.0.0

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-more-itertools/python-more-itertools.changes  
    2022-09-18 17:32:12.625768784 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-more-itertools.new.2275/python-more-itertools.changes
    2022-11-01 13:41:20.055502214 +0100
@@ -1,0 +2,17 @@
+Fri Oct 28 18:32:55 UTC 2022 - Yogalakshmi Arunachalam <yarunacha...@suse.com>
+
+- Update to 9.0.0 
+  * Potentially breaking changes
+   grouper() no longer accepts an integer as its first argument. Previously 
this raised a DeprecationWarning.
+   collate() has been removed. Use the built-in heapq.merge() instead.
+   windowed() now yields nothing when its iterable is empty.
+   This library now advertises support for Python 3.7+.
+  * New functions
+   constrained_batches()
+   batched() (from the Python itertools docs)
+   polynomial_from_roots() (from the Python itertools docs)
+   sieve() (from the Python itertools docs)
+  * Other changes
+   Some documentation issues were fixed (thanks to nanouasyn)
+
+-------------------------------------------------------------------

Old:
----
  more-itertools-8.14.0.tar.gz

New:
----
  more-itertools-9.0.0.tar.gz

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

Other differences:
------------------
++++++ python-more-itertools.spec ++++++
--- /var/tmp/diff_new_pack.sQLD4j/_old  2022-11-01 13:41:20.599505108 +0100
+++ /var/tmp/diff_new_pack.sQLD4j/_new  2022-11-01 13:41:20.603505128 +0100
@@ -19,7 +19,7 @@
 %{?!python_module:%define python_module() python3-%{**}}
 %define skip_python2 1
 Name:           python-more-itertools
-Version:        8.14.0
+Version:        9.0.0
 Release:        0
 Summary:        More routines for operating on iterables, beyond itertools
 License:        MIT

++++++ more-itertools-8.14.0.tar.gz -> more-itertools-9.0.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/more-itertools-8.14.0/.github/workflows/python-app.yml 
new/more-itertools-9.0.0/.github/workflows/python-app.yml
--- old/more-itertools-8.14.0/.github/workflows/python-app.yml  2022-08-09 
16:00:34.670124000 +0200
+++ new/more-itertools-9.0.0/.github/workflows/python-app.yml   2022-10-18 
15:38:19.069835000 +0200
@@ -8,7 +8,7 @@
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        python-version: [3.6, 3.7, 3.8, 3.9.0, 3.10.0, pypy3]
+        python-version: ["3.7", "3.8", "3.9", "3.10", "3.11.0-rc.2", 
"pypy-3.8"]
 
     steps:
     - uses: actions/checkout@v2
@@ -31,28 +31,28 @@
       run: |
         flake8 .
     - name: Check formatting with black
-      if: "matrix.python-version == '3.6'"
+      if: "matrix.python-version == '3.7'"
       run: |
         pip install -U black
         black --check .
     - name: Check type stubs with mypy
-      if: "matrix.python-version != 'pypy3'"
+      if: "matrix.python-version != 'pypy-3.8'"
       run: |
         pip install -U mypy
         stubtest more_itertools.more more_itertools.recipes
     - name: Build docs with sphinx
-      if: "matrix.python-version == '3.6'"
+      if: "matrix.python-version == '3.7'"
       run: |
         pip install -U sphinx sphinx_rtd_theme
         sphinx-build -W -b html docs docs/_build/html
     - name: Build packages
-      if: "matrix.python-version == '3.6'"
+      if: "matrix.python-version == '3.7'"
       run: |
         pip install -U flit twine
         flit build --setup-py
         twine check dist/*
     - name: Upload packages
-      if: "matrix.python-version == '3.6'"
+      if: "matrix.python-version == '3.7'"
       uses: actions/upload-artifact@v2
       with:
         name: more-itertools-packages
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/more-itertools-8.14.0/PKG-INFO 
new/more-itertools-9.0.0/PKG-INFO
--- old/more-itertools-8.14.0/PKG-INFO  1970-01-01 01:00:00.000000000 +0100
+++ new/more-itertools-9.0.0/PKG-INFO   1970-01-01 01:00:00.000000000 +0100
@@ -1,21 +1,21 @@
 Metadata-Version: 2.1
 Name: more-itertools
-Version: 8.14.0
+Version: 9.0.0
 Summary: More routines for operating on iterables, beyond itertools
-Keywords: 
itertools,iterator,iteration,filter,peek,peekable,collate,chunk,chunked
+Keywords: itertools,iterator,iteration,filter,peek,peekable,chunk,chunked
 Author-email: Erik Rose <erikr...@grinchcentral.com>
-Requires-Python: >=3.5
+Requires-Python: >=3.7
 Description-Content-Type: text/x-rst
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Intended Audience :: Developers
 Classifier: Natural Language :: English
 Classifier: License :: OSI Approved :: MIT License
 Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.6
 Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: 3.8
 Classifier: Programming Language :: Python :: 3.9
 Classifier: Programming Language :: Python :: 3.10
+Classifier: Programming Language :: Python :: 3.11
 Classifier: Programming Language :: Python :: 3 :: Only
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
@@ -39,6 +39,7 @@
 |                        | `ichunked 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.ichunked>`_,
                                                                             |
 |                        | `chunked_even 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.chunked_even>`_,
                                                                     |
 |                        | `sliced 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.sliced>`_,
                                                                                
 |
+|                        | `constrained_batches 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.constrained_batches>`_,
                                                       |
 |                        | `distribute 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.distribute>`_,
                                                                         |
 |                        | `divide 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.divide>`_,
                                                                                
 |
 |                        | `split_at 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.split_at>`_,
                                                                             |
@@ -48,6 +49,7 @@
 |                        | `split_when 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.split_when>`_,
                                                                         |
 |                        | `bucket 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.bucket>`_,
                                                                                
 |
 |                        | `unzip 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.unzip>`_,
                                                                                
   |
+|                        | `batched 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.batched>`_,
                                                                               |
 |                        | `grouper 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.grouper>`_,
                                                                               |
 |                        | `partition 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.partition>`_
                                                                            |
 
+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
@@ -62,8 +64,8 @@
 |                        | `windowed_complete 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.windowed_complete>`_,
                                                           |
 |                        | `pairwise 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.pairwise>`_,
                                                                             |
 |                        | `triplewise 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.triplewise>`_,
                                                                         |
-|                        | `sliding_window 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.sliding_window>`_
                                                                  |
-|                        | `subslices 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.subslices>`_,
                                                                           |
+|                        | `sliding_window 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.sliding_window>`_,
                                                                 |
+|                        | `subslices 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.subslices>`_
                                                                            |
 
+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
 | Augmenting             | `count_cycle 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.count_cycle>`_,
                                                                       |
 |                        | `intersperse 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.intersperse>`_,
                                                                       |
@@ -103,7 +105,7 @@
 |                        | `all_unique 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.all_unique>`_,
                                                                         |
 |                        | `minmax 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.minmax>`_,
                                                                                
 |
 |                        | `first_true 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.first_true>`_,
                                                                         |
-|                        | `quantify 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.quantify>`_
                                                                              |
+|                        | `quantify 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.quantify>`_,
                                                                             |
 |                        | `iequals 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.iequals>`_
                                                                                
|
 
+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
 | Selecting              | `islice_extended 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.islice_extended>`_,
                                                               |
@@ -126,7 +128,7 @@
 |                        | `unique_everseen 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertoo 
ls.unique_everseen>`_,                                                          
    |
 |                        | `unique_justseen 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.unique_justseen>`_,
                                                               |
 |                        | `duplicates_everseen 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.duplicates_everseen>`_,
                                                       |
-|                        | `duplicates_justseen 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.duplicates_justseen>`_
                                                        |
+|                        | `duplicates_justseen 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.duplicates_justseen>`_,
                                                       |
 |                        | `longest_common_prefix 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.longest_common_prefix>`_
                                                    |
 
+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
 | Combinatorics          | `distinct_permutations 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.distinct_permutations>`_,
                                                   |
@@ -167,6 +169,8 @@
 |                        | `consume 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.consume>`_,
                                                                               |
 |                        | `tabulate 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.tabulate>`_,
                                                                             |
 |                        | `repeatfunc 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.repeatfunc>`_
                                                                          |
+|                        | `polynomial_from_roots 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.polynomial_from_roots>`_
                                                    |
+|                        | `sieve 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.sieve>`_
                                                                                
    |
 
+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/more-itertools-8.14.0/README.rst 
new/more-itertools-9.0.0/README.rst
--- old/more-itertools-8.14.0/README.rst        2022-08-09 15:50:39.706522700 
+0200
+++ new/more-itertools-9.0.0/README.rst 2022-10-18 15:38:19.069835000 +0200
@@ -15,6 +15,7 @@
 |                        | `ichunked 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.ichunked>`_,
                                                                             |
 |                        | `chunked_even 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.chunked_even>`_,
                                                                     |
 |                        | `sliced 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.sliced>`_,
                                                                                
 |
+|                        | `constrained_batches 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.constrained_batches>`_,
                                                       |
 |                        | `distribute 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.distribute>`_,
                                                                         |
 |                        | `divide 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.divide>`_,
                                                                                
 |
 |                        | `split_at 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.split_at>`_,
                                                                             |
@@ -24,6 +25,7 @@
 |                        | `split_when 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.split_when>`_,
                                                                         |
 |                        | `bucket 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.bucket>`_,
                                                                                
 |
 |                        | `unzip 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.unzip>`_,
                                                                                
   |
+|                        | `batched 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.batched>`_,
                                                                               |
 |                        | `grouper 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.grouper>`_,
                                                                               |
 |                        | `partition 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.partition>`_
                                                                            |
 
+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
@@ -38,8 +40,8 @@
 |                        | `windowed_complete 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.windowed_complete>`_,
                                                           |
 |                        | `pairwise 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.pairwise>`_,
                                                                             |
 |                        | `triplewise 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.triplewise>`_,
                                                                         |
-|                        | `sliding_window 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.sliding_window>`_
                                                                  |
-|                        | `subslices 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.subslices>`_,
                                                                           |
+|                        | `sliding_window 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.sliding_window>`_,
                                                                 |
+|                        | `subslices 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.subslices>`_
                                                                            |
 
+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
 | Augmenting             | `count_cycle 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.count_cycle>`_,
                                                                       |
 |                        | `intersperse 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.intersperse>`_,
                                                                       |
@@ -79,7 +81,7 @@
 |                        | `all_unique 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.all_unique>`_,
                                                                         |
 |                        | `minmax 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.minmax>`_,
                                                                                
 |
 |                        | `first_true 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.first_true>`_,
                                                                         |
-|                        | `quantify 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.quantify>`_
                                                                              |
+|                        | `quantify 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.quantify>`_,
                                                                             |
 |                        | `iequals 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.iequals>`_
                                                                                
|
 
+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
 | Selecting              | `islice_extended 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.islice_extended>`_,
                                                               |
@@ -102,7 +104,7 @@
 |                        | `unique_everseen 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertoo 
ls.unique_everseen>`_,                                                          
    |
 |                        | `unique_justseen 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.unique_justseen>`_,
                                                               |
 |                        | `duplicates_everseen 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.duplicates_everseen>`_,
                                                       |
-|                        | `duplicates_justseen 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.duplicates_justseen>`_
                                                        |
+|                        | `duplicates_justseen 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.duplicates_justseen>`_,
                                                       |
 |                        | `longest_common_prefix 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.longest_common_prefix>`_
                                                    |
 
+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
 | Combinatorics          | `distinct_permutations 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.distinct_permutations>`_,
                                                   |
@@ -143,6 +145,8 @@
 |                        | `consume 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.consume>`_,
                                                                               |
 |                        | `tabulate 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.tabulate>`_,
                                                                             |
 |                        | `repeatfunc 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.repeatfunc>`_
                                                                          |
+|                        | `polynomial_from_roots 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.polynomial_from_roots>`_
                                                    |
+|                        | `sieve 
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.sieve>`_
                                                                                
    |
 
+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/more-itertools-8.14.0/docs/api.rst 
new/more-itertools-9.0.0/docs/api.rst
--- old/more-itertools-8.14.0/docs/api.rst      2022-08-09 15:43:59.871538400 
+0200
+++ new/more-itertools-9.0.0/docs/api.rst       2022-10-18 15:37:02.101069200 
+0200
@@ -17,6 +17,7 @@
 .. autofunction:: ichunked
 .. autofunction:: chunked_even
 .. autofunction:: sliced
+.. autofunction:: constrained_batches(iterable, max_size, max_count=None, 
get_len=len, strict=True)
 .. autofunction:: distribute
 .. autofunction:: divide
 .. autofunction:: split_at
@@ -31,6 +32,7 @@
 
 **Itertools recipes**
 
+.. autofunction:: batched
 .. autofunction:: grouper
 .. autofunction:: partition
 
@@ -287,3 +289,5 @@
 .. autofunction:: consume
 .. autofunction:: tabulate
 .. autofunction:: repeatfunc
+.. autofunction:: polynomial_from_roots
+.. autofunction:: sieve
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/more-itertools-8.14.0/docs/versions.rst 
new/more-itertools-9.0.0/docs/versions.rst
--- old/more-itertools-8.14.0/docs/versions.rst 2022-08-09 15:49:41.910306700 
+0200
+++ new/more-itertools-9.0.0/docs/versions.rst  2022-10-18 15:38:19.069835000 
+0200
@@ -5,6 +5,24 @@
 .. automodule:: more_itertools
    :noindex:
 
+9.0.0
+------
+
+* Potentially breaking changes
+    * :func:`grouper` no longer accepts an integer as its first argument. 
Previously this raised a ``DeprecationWarning``.
+    * :func:`collate` has been removed. Use the built-in :func:`heapq.merge` 
instead.
+    * :func:`windowed` now yields nothing when its iterable is empty.
+    * This library now advertises support for Python 3.7+.
+
+* New functions
+    * :func:`constrained_batches`
+    * :func:`batched` (from the Python itertools docs)
+    * :func:`polynomial_from_roots` (from the Python itertools docs)
+    * :func:`sieve` (from the Python itertools docs)
+
+* Other changes
+    * Some documentation issues were fixed (thanks to nanouasyn)
+
 8.14.0
 ------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/more-itertools-8.14.0/more_itertools/__init__.py 
new/more-itertools-9.0.0/more_itertools/__init__.py
--- old/more-itertools-8.14.0/more_itertools/__init__.py        2022-08-09 
15:53:46.644506700 +0200
+++ new/more-itertools-9.0.0/more_itertools/__init__.py 2022-10-18 
15:38:19.069835000 +0200
@@ -3,4 +3,4 @@
 from .more import *  # noqa
 from .recipes import *  # noqa
 
-__version__ = '8.14.0'
+__version__ = '9.0.0'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/more-itertools-8.14.0/more_itertools/more.py 
new/more-itertools-9.0.0/more_itertools/more.py
--- old/more-itertools-8.14.0/more_itertools/more.py    2022-08-09 
15:43:59.877477000 +0200
+++ new/more-itertools-9.0.0/more_itertools/more.py     2022-10-18 
15:38:19.073834700 +0200
@@ -3,7 +3,7 @@
 from collections import Counter, defaultdict, deque, abc
 from collections.abc import Sequence
 from functools import partial, reduce, wraps
-from heapq import merge, heapify, heapreplace, heappop
+from heapq import heapify, heapreplace, heappop
 from itertools import (
     chain,
     compress,
@@ -52,9 +52,9 @@
     'chunked_even',
     'circular_shifts',
     'collapse',
-    'collate',
     'combination_index',
     'consecutive_groups',
+    'constrained_batches',
     'consumer',
     'count_cycle',
     'countable',
@@ -412,44 +412,6 @@
         return self._cache[index]
 
 
-def collate(*iterables, **kwargs):
-    """Return a sorted merge of the items from each of several already-sorted
-    *iterables*.
-
-        >>> list(collate('ACDZ', 'AZ', 'JKL'))
-        ['A', 'A', 'C', 'D', 'J', 'K', 'L', 'Z', 'Z']
-
-    Works lazily, keeping only the next value from each iterable in memory. Use
-    :func:`collate` to, for example, perform a n-way mergesort of items that
-    don't fit in memory.
-
-    If a *key* function is specified, the iterables will be sorted according
-    to its result:
-
-        >>> key = lambda s: int(s)  # Sort by numeric value, not by string
-        >>> list(collate(['1', '10'], ['2', '11'], key=key))
-        ['1', '2', '10', '11']
-
-
-    If the *iterables* are sorted in descending order, set *reverse* to
-    ``True``:
-
-        >>> list(collate([5, 3, 1], [4, 2, 0], reverse=True))
-        [5, 4, 3, 2, 1, 0]
-
-    If the elements of the passed-in iterables are out of order, you might get
-    unexpected results.
-
-    On Python 3.5+, this function is an alias for :func:`heapq.merge`.
-
-    """
-    warnings.warn(
-        "collate is no longer part of more_itertools, use heapq.merge",
-        DeprecationWarning,
-    )
-    return merge(*iterables, **kwargs)
-
-
 def consumer(func):
     """Decorator that automatically advances a PEP-342-style "reverse iterator"
     to its first yield point so you don't have to call ``next()`` on it
@@ -875,7 +837,9 @@
             yield tuple(window)
 
     size = len(window)
-    if size < n:
+    if size == 0:
+        return
+    elif size < n:
         yield tuple(chain(window, repeat(fillvalue, n - size)))
     elif 0 < i < min(step, n):
         window += (fillvalue,) * i
@@ -4331,3 +4295,53 @@
                 hi, hi_key = y, y_key
 
     return lo, hi
+
+
+def constrained_batches(
+    iterable, max_size, max_count=None, get_len=len, strict=True
+):
+    """Yield batches of items from *iterable* with a combined size limited by
+    *max_size*.
+
+    >>> iterable = [b'12345', b'123', b'12345678', b'1', b'1', b'12', b'1']
+    >>> list(constrained_batches(iterable, 10))
+    [(b'12345', b'123'), (b'12345678', b'1', b'1'), (b'12', b'1')]
+
+    If a *max_count* is supplied, the number of items per batch is also
+    limited:
+
+    >>> iterable = [b'12345', b'123', b'12345678', b'1', b'1', b'12', b'1']
+    >>> list(constrained_batches(iterable, 10, max_count = 2))
+    [(b'12345', b'123'), (b'12345678', b'1'), (b'1', b'12'), (b'1',)]
+
+    If a *get_len* function is supplied, use that instead of :func:`len` to
+    determine item size.
+
+    If *strict* is ``True``, raise ``ValueError`` if any single item is bigger
+    than *max_size*. Otherwise, allow single items to exceed *max_size*.
+    """
+    if max_size <= 0:
+        raise ValueError('maximum size must be greater than zero')
+
+    batch = []
+    batch_size = 0
+    batch_count = 0
+    for item in iterable:
+        item_len = get_len(item)
+        if strict and item_len > max_size:
+            raise ValueError('item size exceeds maximum size')
+
+        reached_count = batch_count == max_count
+        reached_size = item_len + batch_size > max_size
+        if batch_count and (reached_size or reached_count):
+            yield tuple(batch)
+            batch.clear()
+            batch_size = 0
+            batch_count = 0
+
+        batch.append(item)
+        batch_size += item_len
+        batch_count += 1
+
+    if batch:
+        yield tuple(batch)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/more-itertools-8.14.0/more_itertools/more.pyi 
new/more-itertools-9.0.0/more_itertools/more.pyi
--- old/more-itertools-8.14.0/more_itertools/more.pyi   2022-08-09 
15:43:59.881166500 +0200
+++ new/more-itertools-9.0.0/more_itertools/more.pyi    2022-10-18 
15:38:19.073834700 +0200
@@ -72,7 +72,6 @@
     @overload
     def __getitem__(self, index: slice) -> List[_T]: ...
 
-def collate(*iterables: Iterable[_T], **kwargs: Any) -> Iterable[_T]: ...
 def consumer(func: _GenFn) -> _GenFn: ...
 def ilen(iterable: Iterable[object]) -> int: ...
 def iterate(func: Callable[[_T], _T], start: _T) -> Iterator[_T]: ...
@@ -179,7 +178,7 @@
     iterable: Iterable[_T],
     *,
     n: Optional[int] = ...,
-    next_multiple: bool = ...
+    next_multiple: bool = ...,
 ) -> Iterator[Optional[_T]]: ...
 @overload
 def padded(
@@ -225,7 +224,7 @@
     __iter1: Iterable[_T],
     __iter2: Iterable[_T],
     __iter3: Iterable[_T],
-    *iterables: Iterable[_T]
+    *iterables: Iterable[_T],
 ) -> Iterator[Tuple[_T, ...]]: ...
 @overload
 def zip_offset(
@@ -233,7 +232,7 @@
     *,
     offsets: _SizedIterable[int],
     longest: bool = ...,
-    fillvalue: None = None
+    fillvalue: None = None,
 ) -> Iterator[Tuple[Optional[_T1]]]: ...
 @overload
 def zip_offset(
@@ -242,7 +241,7 @@
     *,
     offsets: _SizedIterable[int],
     longest: bool = ...,
-    fillvalue: None = None
+    fillvalue: None = None,
 ) -> Iterator[Tuple[Optional[_T1], Optional[_T2]]]: ...
 @overload
 def zip_offset(
@@ -252,7 +251,7 @@
     *iterables: Iterable[_T],
     offsets: _SizedIterable[int],
     longest: bool = ...,
-    fillvalue: None = None
+    fillvalue: None = None,
 ) -> Iterator[Tuple[Optional[_T], ...]]: ...
 @overload
 def zip_offset(
@@ -420,7 +419,7 @@
     iterable: Iterable[_T],
     func: Callable[[_T, _T], _U] = ...,
     *,
-    initial: None = ...
+    initial: None = ...,
 ) -> Iterator[Union[_T, _U]]: ...
 @overload
 def difference(
@@ -529,12 +528,12 @@
 def filter_except(
     validator: Callable[[Any], object],
     iterable: Iterable[_T],
-    *exceptions: Type[BaseException]
+    *exceptions: Type[BaseException],
 ) -> Iterator[_T]: ...
 def map_except(
     function: Callable[[Any], _U],
     iterable: Iterable[_T],
-    *exceptions: Type[BaseException]
+    *exceptions: Type[BaseException],
 ) -> Iterator[_U]: ...
 def map_if(
     iterable: Iterable[Any],
@@ -610,7 +609,7 @@
     scalar_types: Union[
         type, Tuple[Union[type, Tuple[Any, ...]], ...], None
     ] = ...,
-    strict: bool = ...
+    strict: bool = ...,
 ) -> Iterable[Tuple[_T, ...]]: ...
 def unique_in_window(
     iterable: Iterable[_T], n: int, key: Optional[Callable[[_T], _U]] = ...
@@ -640,7 +639,7 @@
     iterable_or_value: Iterable[_SupportsLessThanT],
     *,
     key: None = None,
-    default: _U
+    default: _U,
 ) -> Union[_U, Tuple[_SupportsLessThanT, _SupportsLessThanT]]: ...
 @overload
 def minmax(
@@ -653,16 +652,23 @@
 def minmax(
     iterable_or_value: _SupportsLessThanT,
     __other: _SupportsLessThanT,
-    *others: _SupportsLessThanT
+    *others: _SupportsLessThanT,
 ) -> Tuple[_SupportsLessThanT, _SupportsLessThanT]: ...
 @overload
 def minmax(
     iterable_or_value: _T,
     __other: _T,
     *others: _T,
-    key: Callable[[_T], _SupportsLessThan]
+    key: Callable[[_T], _SupportsLessThan],
 ) -> Tuple[_T, _T]: ...
 def longest_common_prefix(
     iterables: Iterable[Iterable[_T]],
 ) -> Iterator[_T]: ...
 def iequals(*iterables: Iterable[object]) -> bool: ...
+def constrained_batches(
+    iterable: Iterable[object],
+    max_size: int,
+    max_count: Optional[int] = ...,
+    get_len: Callable[[_T], object] = ...,
+    strict: bool = ...,
+) -> Iterator[Tuple[_T]]: ...
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/more-itertools-8.14.0/more_itertools/recipes.py 
new/more-itertools-9.0.0/more_itertools/recipes.py
--- old/more-itertools-8.14.0/more_itertools/recipes.py 2022-08-09 
15:43:59.884092800 +0200
+++ new/more-itertools-9.0.0/more_itertools/recipes.py  2022-10-18 
15:38:19.073834700 +0200
@@ -7,14 +7,16 @@
 .. [1] http://docs.python.org/library/itertools.html#recipes
 
 """
+import math
 import operator
-import warnings
 
 from collections import deque
 from collections.abc import Sized
+from functools import reduce
 from itertools import (
     chain,
     combinations,
+    compress,
     count,
     cycle,
     groupby,
@@ -28,6 +30,7 @@
 
 __all__ = [
     'all_equal',
+    'batched',
     'before_and_after',
     'consume',
     'convolve',
@@ -43,6 +46,7 @@
     'pad_none',
     'pairwise',
     'partition',
+    'polynomial_from_roots',
     'powerset',
     'prepend',
     'quantify',
@@ -52,6 +56,7 @@
     'random_product',
     'repeatfunc',
     'roundrobin',
+    'sieve',
     'sliding_window',
     'subslices',
     'tabulate',
@@ -364,11 +369,6 @@
     UnequalIterablesError
 
     """
-    if isinstance(iterable, int):
-        warnings.warn(
-            "grouper expects iterable as first parameter", DeprecationWarning
-        )
-        n, iterable = iterable, n
     args = [iter(iterable)] * n
     if incomplete == 'fill':
         return zip_longest(*args, fillvalue=fillvalue)
@@ -738,11 +738,12 @@
                 transition.append(elem)
                 return
 
-    def remainder_iterator():
-        yield from transition
-        yield from it
+    # Note: this is different from itertools recipes to allow nesting
+    # before_and_after remainders into before_and_after again. See tests
+    # for an example.
+    remainder_iterator = chain(transition, it)
 
-    return true_iterator(), remainder_iterator()
+    return true_iterator(), remainder_iterator
 
 
 def triplewise(iterable):
@@ -790,3 +791,51 @@
     seq = list(iterable)
     slices = starmap(slice, combinations(range(len(seq) + 1), 2))
     return map(operator.getitem, repeat(seq), slices)
+
+
+def polynomial_from_roots(roots):
+    """Compute a polynomial's coefficients from its roots.
+
+    >>> roots = [5, -4, 3]  # (x - 5) * (x + 4) * (x - 3)
+    >>> polynomial_from_roots(roots)  # x^3 - 4 * x^2 - 17 * x + 60
+    [1, -4, -17, 60]
+    """
+    # Use math.prod for Python 3.8+,
+    prod = getattr(math, 'prod', lambda x: reduce(operator.mul, x, 1))
+    roots = list(map(operator.neg, roots))
+    return [
+        sum(map(prod, combinations(roots, k))) for k in range(len(roots) + 1)
+    ]
+
+
+def sieve(n):
+    """Yield the primes less than n.
+
+    >>> list(sieve(30))
+    [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
+    """
+    isqrt = getattr(math, 'isqrt', lambda x: int(math.sqrt(x)))
+    limit = isqrt(n) + 1
+    data = bytearray([1]) * n
+    data[:2] = 0, 0
+    for p in compress(range(limit), data):
+        data[p + p : n : p] = bytearray(len(range(p + p, n, p)))
+
+    return compress(count(), data)
+
+
+def batched(iterable, n):
+    """Batch data into lists of length *n*. The last batch may be shorter.
+
+    >>> list(batched('ABCDEFG', 3))
+    [['A', 'B', 'C'], ['D', 'E', 'F'], ['G']]
+
+    This recipe is from the ``itertools`` docs. This library also provides
+    :func:`chunked`, which has a different implementation.
+    """
+    it = iter(iterable)
+    while True:
+        batch = list(islice(it, n))
+        if not batch:
+            break
+        yield batch
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/more-itertools-8.14.0/more_itertools/recipes.pyi 
new/more-itertools-9.0.0/more_itertools/recipes.pyi
--- old/more-itertools-8.14.0/more_itertools/recipes.pyi        2022-04-29 
16:09:30.648787500 +0200
+++ new/more-itertools-9.0.0/more_itertools/recipes.pyi 2022-10-18 
15:38:19.073834700 +0200
@@ -6,6 +6,7 @@
     Iterator,
     List,
     Optional,
+    Sequence,
     Tuple,
     TypeVar,
     Union,
@@ -39,20 +40,12 @@
     func: Callable[..., _U], times: Optional[int] = ..., *args: Any
 ) -> Iterator[_U]: ...
 def pairwise(iterable: Iterable[_T]) -> Iterator[Tuple[_T, _T]]: ...
-@overload
 def grouper(
     iterable: Iterable[_T],
     n: int,
     incomplete: str = ...,
     fillvalue: _U = ...,
 ) -> Iterator[Tuple[Union[_T, _U], ...]]: ...
-@overload
-def grouper(  # Deprecated interface
-    iterable: int,
-    n: Iterable[_T],
-    incomplete: str = ...,
-    fillvalue: _U = ...,
-) -> Iterator[Tuple[Union[_T, _U], ...]]: ...
 def roundrobin(*iterables: Iterable[_T]) -> Iterator[_T]: ...
 def partition(
     pred: Optional[Callable[[_T], object]], iterable: Iterable[_T]
@@ -109,3 +102,9 @@
     iterable: Iterable[_T], n: int
 ) -> Iterator[Tuple[_T, ...]]: ...
 def subslices(iterable: Iterable[_T]) -> Iterator[List[_T]]: ...
+def polynomial_from_roots(roots: Sequence[int]) -> List[int]: ...
+def sieve(n: int) -> Iterator[int]: ...
+def batched(
+    iterable: Iterable[_T],
+    n: int,
+) -> Iterator[List[_T]]: ...
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/more-itertools-8.14.0/pyproject.toml 
new/more-itertools-9.0.0/pyproject.toml
--- old/more-itertools-8.14.0/pyproject.toml    2022-08-09 15:43:59.886106300 
+0200
+++ new/more-itertools-9.0.0/pyproject.toml     2022-10-18 15:38:19.073834700 
+0200
@@ -6,7 +6,7 @@
 name = "more-itertools"
 authors = [{name = "Erik Rose", email = "erikr...@grinchcentral.com"}]
 readme = "README.rst"
-requires-python = ">=3.5"
+requires-python = ">=3.7"
 license = {file = "LICENSE"}
 keywords = [
     "itertools",
@@ -15,7 +15,6 @@
     "filter",
     "peek",
     "peekable",
-    "collate",
     "chunk",
     "chunked",
 ]
@@ -25,11 +24,11 @@
     "Natural Language :: English",
     "License :: OSI Approved :: MIT License",
     "Programming Language :: Python :: 3",
-    "Programming Language :: Python :: 3.6",
     "Programming Language :: Python :: 3.7",
     "Programming Language :: Python :: 3.8",
     "Programming Language :: Python :: 3.9",
     "Programming Language :: Python :: 3.10",
+    "Programming Language :: Python :: 3.11",
     "Programming Language :: Python :: 3 :: Only",
     "Programming Language :: Python :: Implementation :: CPython",
     "Programming Language :: Python :: Implementation :: PyPy",
@@ -45,5 +44,5 @@
 
 [tool.black]
 line-length = 79
-target-version = ['py35']
+target-version = ['py37']
 skip-string-normalization = true
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/more-itertools-8.14.0/setup.cfg 
new/more-itertools-9.0.0/setup.cfg
--- old/more-itertools-8.14.0/setup.cfg 2022-08-09 15:53:46.644978300 +0200
+++ new/more-itertools-9.0.0/setup.cfg  2022-10-18 15:38:19.073834700 +0200
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 8.14.0
+current_version = 9.0.0
 commit = True
 tag = False
 files = more_itertools/__init__.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/more-itertools-8.14.0/tests/test_more.py 
new/more-itertools-9.0.0/tests/test_more.py
--- old/more-itertools-8.14.0/tests/test_more.py        2022-08-09 
15:43:59.889434000 +0200
+++ new/more-itertools-9.0.0/tests/test_more.py 2022-10-18 15:38:19.073834700 
+0200
@@ -7,7 +7,6 @@
 from doctest import DocTestSuite
 from fractions import Fraction
 from functools import partial, reduce
-from heapq import merge
 from io import StringIO
 from itertools import (
     accumulate,
@@ -41,51 +40,6 @@
     return tests
 
 
-class CollateTests(TestCase):
-    """Unit tests for ``collate()``"""
-
-    # Also accidentally tests peekable, though that could use its own tests
-
-    def test_default(self):
-        """Test with the default `key` function."""
-        iterables = [range(4), range(7), range(3, 6)]
-        self.assertEqual(
-            sorted(reduce(list.__add__, [list(it) for it in iterables])),
-            list(mi.collate(*iterables)),
-        )
-
-    def test_key(self):
-        """Test using a custom `key` function."""
-        iterables = [range(5, 0, -1), range(4, 0, -1)]
-        actual = sorted(
-            reduce(list.__add__, [list(it) for it in iterables]), reverse=True
-        )
-        expected = list(mi.collate(*iterables, key=lambda x: -x))
-        self.assertEqual(actual, expected)
-
-    def test_empty(self):
-        """Be nice if passed an empty list of iterables."""
-        self.assertEqual([], list(mi.collate()))
-
-    def test_one(self):
-        """Work when only 1 iterable is passed."""
-        self.assertEqual([0, 1], list(mi.collate(range(2))))
-
-    def test_reverse(self):
-        """Test the `reverse` kwarg."""
-        iterables = [range(4, 0, -1), range(7, 0, -1), range(3, 6, -1)]
-
-        actual = sorted(
-            reduce(list.__add__, [list(it) for it in iterables]), reverse=True
-        )
-        expected = list(mi.collate(*iterables, reverse=True))
-        self.assertEqual(actual, expected)
-
-    def test_alias(self):
-        self.assertNotEqual(merge.__doc__, mi.collate.__doc__)
-        self.assertNotEqual(partial.__doc__, mi.collate.__doc__)
-
-
 class ChunkedTests(TestCase):
     """Tests for ``chunked()``"""
 
@@ -289,11 +243,6 @@
 
 
 class PeekableTests(PeekableMixinTests, TestCase):
-    """Tests for ``peekable()`` behavior not incidentally covered by testing
-    ``collate()``
-
-    """
-
     cls = mi.peekable
 
     def test_indexing(self):
@@ -783,64 +732,55 @@
 
 
 class WindowedTests(TestCase):
-    """Tests for ``windowed()``"""
-
     def test_basic(self):
-        actual = list(mi.windowed([1, 2, 3, 4, 5], 3))
-        expected = [(1, 2, 3), (2, 3, 4), (3, 4, 5)]
-        self.assertEqual(actual, expected)
-
-    def test_large_size(self):
-        """
-        When the window size is larger than the iterable, and no fill value is
-        given,``None`` should be filled in.
-        """
-        actual = list(mi.windowed([1, 2, 3, 4, 5], 6))
-        expected = [(1, 2, 3, 4, 5, None)]
-        self.assertEqual(actual, expected)
-
-    def test_fillvalue(self):
-        """
-        When sizes don't match evenly, the given fill value should be used.
-        """
         iterable = [1, 2, 3, 4, 5]
 
-        for n, kwargs, expected in [
-            (6, {}, [(1, 2, 3, 4, 5, '!')]),  # n > len(iterable)
-            (3, {'step': 3}, [(1, 2, 3), (4, 5, '!')]),  # using ``step``
-        ]:
-            actual = list(mi.windowed(iterable, n, fillvalue='!', **kwargs))
-            self.assertEqual(actual, expected)
+        for n, expected in (
+            (6, [(1, 2, 3, 4, 5, None)]),
+            (5, [(1, 2, 3, 4, 5)]),
+            (4, [(1, 2, 3, 4), (2, 3, 4, 5)]),
+            (3, [(1, 2, 3), (2, 3, 4), (3, 4, 5)]),
+            (2, [(1, 2), (2, 3), (3, 4), (4, 5)]),
+            (1, [(1,), (2,), (3,), (4,), (5,)]),
+            (0, [()]),
+        ):
+            with self.subTest(n=n):
+                actual = list(mi.windowed(iterable, n))
+                self.assertEqual(actual, expected)
 
-    def test_zero(self):
-        """When the window size is zero, an empty tuple should be emitted."""
-        actual = list(mi.windowed([1, 2, 3, 4, 5], 0))
-        expected = [tuple()]
+    def test_fillvalue(self):
+        actual = list(mi.windowed([1, 2, 3, 4, 5], 6, fillvalue='!'))
+        expected = [(1, 2, 3, 4, 5, '!')]
         self.assertEqual(actual, expected)
 
-    def test_negative(self):
-        """When the window size is negative, ValueError should be raised."""
-        with self.assertRaises(ValueError):
-            list(mi.windowed([1, 2, 3, 4, 5], -1))
-
     def test_step(self):
-        """The window should advance by the number of steps provided"""
         iterable = [1, 2, 3, 4, 5, 6, 7]
         for n, step, expected in [
             (3, 2, [(1, 2, 3), (3, 4, 5), (5, 6, 7)]),  # n > step
             (3, 3, [(1, 2, 3), (4, 5, 6), (7, None, None)]),  # n == step
-            (3, 4, [(1, 2, 3), (5, 6, 7)]),  # line up nicely
+            (3, 4, [(1, 2, 3), (5, 6, 7)]),  # lines up nicely
             (3, 5, [(1, 2, 3), (6, 7, None)]),  # off by one
             (3, 6, [(1, 2, 3), (7, None, None)]),  # off by two
             (3, 7, [(1, 2, 3)]),  # step past the end
             (7, 8, [(1, 2, 3, 4, 5, 6, 7)]),  # step > len(iterable)
         ]:
-            actual = list(mi.windowed(iterable, n, step=step))
-            self.assertEqual(actual, expected)
+            with self.subTest(n=n, step=step):
+                actual = list(mi.windowed(iterable, n, step=step))
+                self.assertEqual(actual, expected)
 
+    def test_invalid_step(self):
         # Step must be greater than or equal to 1
         with self.assertRaises(ValueError):
-            list(mi.windowed(iterable, 3, step=0))
+            list(mi.windowed([1, 2, 3, 4, 5], 3, step=0))
+
+    def test_fillvalue_step(self):
+        actual = list(mi.windowed([1, 2, 3, 4, 5], 3, fillvalue='!', step=3))
+        expected = [(1, 2, 3), (4, 5, '!')]
+        self.assertEqual(actual, expected)
+
+    def test_negative(self):
+        with self.assertRaises(ValueError):
+            list(mi.windowed([1, 2, 3, 4, 5], -1))
 
 
 class SubstringsTests(TestCase):
@@ -5137,3 +5077,100 @@
 
     def test_not_identical_but_equal(self):
         self.assertTrue([1, True], [1.0, complex(1, 0)])
+
+
+class ConstrainedBatchesTests(TestCase):
+    def test_basic(self):
+        zen = [
+            'Beautiful is better than ugly',
+            'Explicit is better than implicit',
+            'Simple is better than complex',
+            'Complex is better than complicated',
+            'Flat is better than nested',
+            'Sparse is better than dense',
+            'Readability counts',
+        ]
+        for size, expected in (
+            (
+                34,
+                [
+                    (zen[0],),
+                    (zen[1],),
+                    (zen[2],),
+                    (zen[3],),
+                    (zen[4],),
+                    (zen[5],),
+                    (zen[6],),
+                ],
+            ),
+            (
+                61,
+                [
+                    (zen[0], zen[1]),
+                    (zen[2],),
+                    (zen[3], zen[4]),
+                    (zen[5], zen[6]),
+                ],
+            ),
+            (
+                90,
+                [
+                    (zen[0], zen[1], zen[2]),
+                    (zen[3], zen[4], zen[5]),
+                    (zen[6],),
+                ],
+            ),
+            (
+                124,
+                [(zen[0], zen[1], zen[2], zen[3]), (zen[4], zen[5], zen[6])],
+            ),
+            (
+                150,
+                [(zen[0], zen[1], zen[2], zen[3], zen[4]), (zen[5], zen[6])],
+            ),
+            (
+                177,
+                [(zen[0], zen[1], zen[2], zen[3], zen[4], zen[5]), (zen[6],)],
+            ),
+        ):
+            with self.subTest(size=size):
+                actual = list(mi.constrained_batches(iter(zen), size))
+                self.assertEqual(actual, expected)
+
+    def test_max_count(self):
+        iterable = ['1', '1', '12345678', '12345', '12345']
+        max_size = 10
+        max_count = 2
+        actual = list(mi.constrained_batches(iterable, max_size, max_count))
+        expected = [('1', '1'), ('12345678',), ('12345', '12345')]
+        self.assertEqual(actual, expected)
+
+    def test_strict(self):
+        iterable = ['1', '123456789', '1']
+        size = 8
+        with self.assertRaises(ValueError):
+            list(mi.constrained_batches(iterable, size))
+
+        actual = list(mi.constrained_batches(iterable, size, strict=False))
+        expected = [('1',), ('123456789',), ('1',)]
+        self.assertEqual(actual, expected)
+
+    def test_get_len(self):
+        class Record(tuple):
+            def total_size(self):
+                return sum(len(x) for x in self)
+
+        record_3 = Record(('1', '23'))
+        record_5 = Record(('1234', '1'))
+        record_10 = Record(('1', '12345678', '1'))
+        record_2 = Record(('1', '1'))
+        iterable = [record_3, record_5, record_10, record_2]
+
+        self.assertEqual(
+            list(
+                mi.constrained_batches(
+                    iterable, 10, get_len=lambda x: x.total_size()
+                )
+            ),
+            [(record_3, record_5), (record_10,), (record_2,)],
+        )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/more-itertools-8.14.0/tests/test_recipes.py 
new/more-itertools-9.0.0/tests/test_recipes.py
--- old/more-itertools-8.14.0/tests/test_recipes.py     2022-08-09 
15:43:59.891580000 +0200
+++ new/more-itertools-9.0.0/tests/test_recipes.py      2022-10-18 
15:38:19.073834700 +0200
@@ -1,6 +1,5 @@
-import warnings
-
 from doctest import DocTestSuite
+from functools import reduce
 from itertools import combinations, count, permutations
 from math import factorial
 from unittest import TestCase
@@ -335,16 +334,6 @@
                 with self.assertRaises(ValueError):
                     list(mi.grouper(iter(seq), n, incomplete='strict'))
 
-    def test_legacy_order(self):
-        with warnings.catch_warnings(record=True) as caught:
-            warnings.simplefilter('always')
-            self.assertEqual(
-                list(mi.grouper(3, 'ABCDEF')),
-                [('A', 'B', 'C'), ('D', 'E', 'F')],
-            )
-
-        self.assertEqual(caught[0].category, DeprecationWarning)
-
     def test_invalid_incomplete(self):
         with self.assertRaises(ValueError):
             list(mi.grouper('ABCD', 3, incomplete='bogus'))
@@ -783,6 +772,39 @@
         self.assertEqual(list(before), [1, True])
         self.assertEqual(list(after), [0, False])
 
+    @staticmethod
+    def _group_events(events):
+        events = iter(events)
+
+        while True:
+            try:
+                operation = next(events)
+            except StopIteration:
+                break
+            assert operation in ["SUM", "MULTIPLY"]
+
+            # Here, the remainder `events` is passed into `before_and_after`
+            # again, which would be problematic if the remainder is a
+            # generator function (as in Python 3.10 itertools recipes), since
+            # that creates recursion. `itertools.chain` solves this problem.
+            numbers, events = mi.before_and_after(
+                lambda e: isinstance(e, int), events
+            )
+
+            yield (operation, numbers)
+
+    def test_nested_remainder(self):
+        events = ["SUM", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] * 1000
+        events += ["MULTIPLY", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] * 1000
+
+        for operation, numbers in self._group_events(events):
+            if operation == "SUM":
+                res = sum(numbers)
+                self.assertEqual(res, 55)
+            elif operation == "MULTIPLY":
+                res = reduce(lambda a, b: a * b, numbers)
+                self.assertEqual(res, 3628800)
+
 
 class TriplewiseTests(TestCase):
     def test_basic(self):
@@ -843,3 +865,80 @@
             with self.subTest(expected=expected):
                 actual = list(mi.subslices(iterable))
                 self.assertEqual(actual, expected)
+
+
+class PolynomialFromRootsTests(TestCase):
+    def test_basic(self):
+        for roots, expected in [
+            ((2, 1, -1), [1, -2, -1, 2]),
+            ((2, 3), [1, -5, 6]),
+            ((1, 2, 3), [1, -6, 11, -6]),
+            ((2, 4, 1), [1, -7, 14, -8]),
+        ]:
+            with self.subTest(roots=roots):
+                actual = mi.polynomial_from_roots(roots)
+                self.assertEqual(actual, expected)
+
+
+class SieveTests(TestCase):
+    def test_basic(self):
+        self.assertEqual(
+            list(mi.sieve(67)),
+            [
+                2,
+                3,
+                5,
+                7,
+                11,
+                13,
+                17,
+                19,
+                23,
+                29,
+                31,
+                37,
+                41,
+                43,
+                47,
+                53,
+                59,
+                61,
+            ],
+        )
+        self.assertEqual(list(mi.sieve(68))[-1], 67)
+
+    def test_prime_counts(self):
+        for n, expected in (
+            (100, 25),
+            (1_000, 168),
+            (10_000, 1229),
+            (100_000, 9592),
+            (1_000_000, 78498),
+        ):
+            with self.subTest(n=n):
+                self.assertEqual(mi.ilen(mi.sieve(n)), expected)
+
+    def test_small_numbers(self):
+        with self.assertRaises(ValueError):
+            list(mi.sieve(-1))
+
+        for n in (0, 1, 2):
+            with self.subTest(n=n):
+                self.assertEqual(list(mi.sieve(n)), [])
+
+
+class BatchedTests(TestCase):
+    def test_basic(self):
+        iterable = range(1, 5 + 1)
+        for n, expected in (
+            (0, []),
+            (1, [[1], [2], [3], [4], [5]]),
+            (2, [[1, 2], [3, 4], [5]]),
+            (3, [[1, 2, 3], [4, 5]]),
+            (4, [[1, 2, 3, 4], [5]]),
+            (5, [[1, 2, 3, 4, 5]]),
+            (6, [[1, 2, 3, 4, 5]]),
+        ):
+            with self.subTest(n=n):
+                actual = list(mi.batched(iterable, n))
+                self.assertEqual(actual, expected)

Reply via email to