Skip to content

Commit

Permalink
announce: make _chunks() helper safe against more input types
Browse files Browse the repository at this point in the history
Especially `dict_keys` objects, which is how py3 handles `dict.keys()`
(vs. being a subscriptable iterable in py2).

Added a test, too, because let's not have this plugin bite us again.

NOTE:
Replaced the new test file's `__future__` imports with those appropriate
for py2, and added the magic "coding" comment expected by our 7.x style
checker rules. Backported from d915136.
  • Loading branch information
dgw committed Jul 22, 2021
1 parent 6ac11da commit 5aa9f67
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 1 deletion.
10 changes: 9 additions & 1 deletion sopel/modules/announce.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,18 @@ def _chunks(items, size):
:param items: the collection of items to chunk
:type items: :term:`iterable`
:param int size: the size of each chunk
:return: a :term:`generator` of chunks
:rtype: :term:`generator` of :class:`tuple`
"""
# Need to convert non-subscriptable types like `dict_keys` objects
try:
items[0]
except TypeError:
items = tuple(items)

# from https://stackoverflow.com/a/312464/5991 with modified names for readability
for delim in range(0, len(items), size):
yield items[delim:delim + size]
yield tuple(items[delim:delim + size])


@plugin.command('announce')
Expand Down
33 changes: 33 additions & 0 deletions test/modules/test_modules_announce.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# coding=utf-8
"""Tests for Sopel's ``announce`` plugin"""
from __future__ import absolute_import, division, print_function, unicode_literals

from sopel.modules import announce


def test_chunks():
"""Test the `_chunks` helper for functionality and compatibility."""
# list input
items = ['list', 'of', 'items', 'to', 'chunk']
r = list(announce._chunks(items, 2))

assert len(r) == 3
assert r[0] == tuple(items[:2])
assert r[1] == tuple(items[2:4])
assert r[2] == tuple(items[4:])

# tuple input
items = ('tuple', 'of', 'items')
r = list(announce._chunks(items, 3))

assert len(r) == 1
assert r[0] == items

# dict keys input
keys = {'one': True, 'two': True, 'three': True}.keys()
items = list(keys)
r = list(announce._chunks(keys, 1))

assert len(r) == 3
for idx in range(len(items)):
assert r[idx] == (items[idx],)

0 comments on commit 5aa9f67

Please sign in to comment.