diff --git a/conda_index/index/convert_cache.py b/conda_index/index/convert_cache.py index 9d46ccd..5e0a21c 100644 --- a/conda_index/index/convert_cache.py +++ b/conda_index/index/convert_cache.py @@ -13,8 +13,7 @@ import os.path import re import sqlite3 - -from more_itertools import ichunked +from itertools import chain, islice from . import common @@ -196,6 +195,17 @@ def db_path(match, override_channel=None): return f"{match['basename']}" +def ichunked(iterable, n): + """ + Break iterable into n-item iterables. + + Lazier than Python 3.12 batched(). + """ + source = iter(iterable) + for item in source: + yield islice(chain([item], source), n) + + def convert_cache(conn, cache_generator): """ Convert old style `conda index` cache to sqlite cache. diff --git a/news/126-less-itertools b/news/126-less-itertools new file mode 100644 index 0000000..4463ffd --- /dev/null +++ b/news/126-less-itertools @@ -0,0 +1,19 @@ +### Enhancements + +* + +### Bug fixes + +* + +### Deprecations + +* + +### Docs + +* + +### Other + +* Remove `more-itertools` dependency. (#127) diff --git a/pyproject.toml b/pyproject.toml index 4782106..297833e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,7 +17,6 @@ dependencies = [ "conda-package-streaming >=0.7.0", "filelock", "jinja2", - "more-itertools", "ruamel.yaml", "zstandard", ] diff --git a/recipe/meta.yaml b/recipe/meta.yaml index ff84e06..ebcf130 100644 --- a/recipe/meta.yaml +++ b/recipe/meta.yaml @@ -30,7 +30,6 @@ requirements: - conda-package-streaming - filelock - jinja2 - - more-itertools - ruamel.yaml test: diff --git a/tests/test_utils.py b/tests/test_utils.py index 67d6f02..cb7c7ad 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,6 +1,7 @@ import pathlib import tempfile +from conda_index.index.convert_cache import ichunked from conda_index.utils import file_contents_match @@ -25,3 +26,51 @@ def test_file_contents_match(): assert file_contents_match(c, c) assert file_contents_match(c, d) + + +def test_ichunked(): + """ + Test laziness of our version of ichunked. + """ + CHUNK_SIZE = 5 # not divisible into total + TOTAL = 32 + REMAINDER = TOTAL - (TOTAL // CHUNK_SIZE) * CHUNK_SIZE + + consumed = -1 + generated = 0 + + def counter(): + nonlocal consumed + consumed += 1 + return consumed + + def counters(): + nonlocal generated + for i in range(TOTAL): + generated = i + yield i, counter + + print("More lazy version") + for chunk in ichunked(counters(), CHUNK_SIZE): + print("Batch") + chunk_size = 0 + for i, c in chunk: + chunk_size += 1 + count = c() + print(i, generated, count) + assert i == generated == count + assert chunk_size == CHUNK_SIZE or chunk_size == REMAINDER + + try: + from itertools import batched + except ImportError: + return + + # demonstrate that generated is sometimes greater than i, c() in + # gathers-into-tuples implementation + print("Less lazy version") + consumed = -1 + for chunk in batched(counters(), CHUNK_SIZE): + print("Batch") + for i, c in chunk: + print(i, generated, c())