#35046: BlankChoiceIterator causes AttributeError for some existing packages and
projects
--------------------------------------+------------------------
Reporter: hazho | Owner: nobody
Type: Bug | Status: new
Component: Utilities | Version: 5.0
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 1
UI/UX: 0 |
--------------------------------------+------------------------
The iterators should have method __len__ ...!
while this is not the case for (BlankChoiceIterator) in the current
version of Django (5.0), this is why the following error raised:
AttributeError: 'BlankChoiceIterator' object has no attribute '__len__'.
Did you mean: '__le__'?
to solve this, simply the BlankChoiceIterator class should have the method
__len__ returning 0 as indication for emptiness.
this is important because the package maintainer or project author may not
find the way to update their code accordingly, for example the projects
depend on django-countries would have the following trace raised (note
there is no obvious indication where in the project code is the main
causer that calls __len__ of BlankChoiceIterator objects:
{{{
Traceback (most recent call last):
File "C:\env_django_simple_payment_system\Lib\site-
packages\django\core\handlers\exception.py", line 55, in inner
response = get_response(request)
^^^^^^^^^^^^^^^^^^^^^
File "C:\env_django_simple_payment_system\Lib\site-
packages\django\core\handlers\base.py", line 197, in _get_response
response = wrapped_callback(request, *callback_args,
**callback_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\django_simple_payment_system\wallets\views.py", line 38, in
index
return render(request, template_path, context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\env_django_simple_payment_system\Lib\site-
packages\django\shortcuts.py", line 24, in render
content = loader.render_to_string(template_name, context, request,
using=using)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\env_django_simple_payment_system\Lib\site-
packages\django\template\loader.py", line 62, in render_to_string
return template.render(context, request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\env_django_simple_payment_system\Lib\site-
packages\django\template\backends\django.py", line 61, in render
return self.template.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\env_django_simple_payment_system\Lib\site-
packages\django\template\base.py", line 171, in render
return self._render(context)
^^^^^^^^^^^^^^^^^^^^^
File "C:\env_django_simple_payment_system\Lib\site-
packages\django\template\base.py", line 163, in _render
return self.nodelist.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\env_django_simple_payment_system\Lib\site-
packages\django\template\base.py", line 1000, in render
return SafeString("".join([node.render_annotated(context) for node in
self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\env_django_simple_payment_system\Lib\site-
packages\django\template\base.py", line 961, in render_annotated
return self.render(context)
^^^^^^^^^^^^^^^^^^^^
File "C:\env_django_simple_payment_system\Lib\site-
packages\django\template\loader_tags.py", line 210, in render
return template.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\env_django_simple_payment_system\Lib\site-
packages\django\template\base.py", line 173, in render
return self._render(context)
^^^^^^^^^^^^^^^^^^^^^
File "C:\env_django_simple_payment_system\Lib\site-
packages\django\template\base.py", line 163, in _render
return self.nodelist.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\env_django_simple_payment_system\Lib\site-
packages\django\template\base.py", line 1000, in render
return SafeString("".join([node.render_annotated(context) for node in
self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\env_django_simple_payment_system\Lib\site-
packages\django\template\base.py", line 961, in render_annotated
return self.render(context)
^^^^^^^^^^^^^^^^^^^^
File "C:\env_django_simple_payment_system\Lib\site-
packages\django\template\defaulttags.py", line 241, in render
nodelist.append(node.render_annotated(context))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\env_django_simple_payment_system\Lib\site-
packages\django\template\base.py", line 961, in render_annotated
return self.render(context)
^^^^^^^^^^^^^^^^^^^^
File "C:\env_django_simple_payment_system\Lib\site-
packages\django\template\base.py", line 1065, in render
return render_value_in_context(output, context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\env_django_simple_payment_system\Lib\site-
packages\django\template\base.py", line 1042, in render_value_in_context
value = str(value)
^^^^^^^^^^
File "C:\env_django_simple_payment_system\Lib\site-
packages\django\forms\utils.py", line 79, in __str__
return self.as_widget()
^^^^^^^^^^^^^^^^
File "C:\env_django_simple_payment_system\Lib\site-
packages\django\forms\boundfield.py", line 95, in as_widget
attrs = self.build_widget_attrs(attrs, widget)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\env_django_simple_payment_system\Lib\site-
packages\django\forms\boundfield.py", line 270, in build_widget_attrs
widget.use_required_attribute(self.initial)
File "C:\env_django_simple_payment_system\Lib\site-
packages\django\forms\widgets.py", line 781, in use_required_attribute
first_choice = next(iter(self.choices), None)
^^^^^^^^^^^^
File "C:\env_django_simple_payment_system\Lib\site-
packages\django_countries\widgets.py", line 29, in get_choices
self._choices: ChoiceList = list(self._choices)
^^^^^^^^^^^^^^^^^^^
File "C:\env_django_simple_payment_system\Lib\site-
packages\django\utils\functional.py", line 188, in __wrapper__
return getattr(result, __method_name)(*args, **kw)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'BlankChoiceIterator' object has no attribute '__len__'.
Did you mean: '__le__'?
}}}
the solution can be as the following:
{{{
# django/utils/choices.py
class BlankChoiceIterator(BaseChoiceIterator):
"""Iterator to lazily inject a blank choice."""
# existing code
def __len__(self):
return 0
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/35046>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/0107018c7a30cea5-ebffe305-7941-418d-8ec5-a561360ee2c8-000000%40eu-central-1.amazonses.com.