summaryrefslogtreecommitdiff
path: root/django/utils/choices.py
diff options
context:
space:
mode:
authorNick Pope <nick@nickpope.me.uk>2023-10-16 19:25:17 +0100
committerNatalia <124304+nessita@users.noreply.github.com>2023-10-23 14:51:27 -0300
commit711c0547224de00aee39b8720c706ac4977e89fd (patch)
tree9305adcbc912d920a431f435ba8b10b9cd169f1b /django/utils/choices.py
parent08aa336af46f30a29577a96588eeb3b440cd6dad (diff)
[5.0.x] Refs #31262 -- Added __eq__() and __getitem__() to BaseChoiceIterator.
This makes it easier to work with lazy iterators used for callables, etc. when extracting items or comparing to lists, e.g. during testing. Also added `BaseChoiceIterator.__iter__()` to make it clear that subclasses must implement this and added `__all__` to the module. Co-authored-by: Adam Johnson <me@adamj.eu> Co-authored-by: Natalia Bidart <124304+nessita@users.noreply.github.com> Backport of 07fa79ef2bb3e8cace7bd87b292c6c85230eed05 from main
Diffstat (limited to 'django/utils/choices.py')
-rw-r--r--django/utils/choices.py26
1 files changed, 26 insertions, 0 deletions
diff --git a/django/utils/choices.py b/django/utils/choices.py
index a0611d96f1..734b9331a1 100644
--- a/django/utils/choices.py
+++ b/django/utils/choices.py
@@ -1,11 +1,37 @@
from collections.abc import Callable, Iterable, Iterator, Mapping
+from itertools import islice, zip_longest
from django.utils.functional import Promise
+__all__ = [
+ "BaseChoiceIterator",
+ "CallableChoiceIterator",
+ "normalize_choices",
+]
+
class BaseChoiceIterator:
"""Base class for lazy iterators for choices."""
+ def __eq__(self, other):
+ if isinstance(other, Iterable):
+ return all(a == b for a, b in zip_longest(self, other, fillvalue=object()))
+ return super().__eq__(other)
+
+ def __getitem__(self, index):
+ if index < 0:
+ # Suboptimally consume whole iterator to handle negative index.
+ return list(self)[index]
+ try:
+ return next(islice(self, index, index + 1))
+ except StopIteration:
+ raise IndexError("index out of range") from None
+
+ def __iter__(self):
+ raise NotImplementedError(
+ "BaseChoiceIterator subclasses must implement __iter__()."
+ )
+
class CallableChoiceIterator(BaseChoiceIterator):
"""Iterator to lazily normalize choices generated by a callable."""