MCPcopy
hub / github.com/django/django / normalize_choices

Function normalize_choices

django/utils/choices.py:72–116  ·  view source on GitHub ↗

Normalize choices values consistently for fields and widgets.

(value, *, depth=0)

Source from the content-addressed store, hash-verified

70
71
72def normalize_choices(value, *, depth=0):
73 """Normalize choices values consistently for fields and widgets."""
74 # Avoid circular import when importing django.forms.
75 from django.db.models.enums import ChoicesType
76
77 match value:
78 case BaseChoiceIterator() | Promise() | bytes() | str():
79 # Avoid prematurely normalizing iterators that should be lazy.
80 # Because string-like types are iterable, return early to avoid
81 # iterating over them in the guard for the Iterable case below.
82 return value
83 case ChoicesType():
84 # Choices enumeration helpers already output in canonical form.
85 return value.choices
86 case Mapping() if depth < 2:
87 value = value.items()
88 case Iterator() if depth < 2:
89 # Although Iterator would be handled by the Iterable case below,
90 # the iterator would be consumed prematurely while checking that
91 # its elements are not string-like in the guard, so we handle it
92 # separately.
93 pass
94 case Iterable() if depth < 2 and not any(
95 isinstance(x, (Promise, bytes, str)) for x in value
96 ):
97 # String-like types are iterable, so the guard above ensures that
98 # they're handled by the default case below.
99 pass
100 case Callable() if depth == 0:
101 # If at the top level, wrap callables to be evaluated lazily.
102 return CallableChoiceIterator(value)
103 case Callable() if depth < 2:
104 value = value()
105 case _:
106 return value
107
108 try:
109 # Recursive call to convert any nested values to a list of 2-tuples.
110 return [(k, normalize_choices(v, depth=depth + 1)) for k, v in value]
111 except (TypeError, ValueError):
112 # Return original value for the system check to raise if it has items
113 # that are not iterable or not 2-tuples:
114 # - TypeError: cannot unpack non-iterable <type> object
115 # - ValueError: <not enough / too many> values to unpack
116 return value

Callers 15

choicesMethod · 0.90
choicesMethod · 0.90
choicesMethod · 0.90
test_choices_iterableMethod · 0.90
test_emptyMethod · 0.90
test_choicesMethod · 0.90
test_callableMethod · 0.90
test_mappingMethod · 0.90
test_iterableMethod · 0.90
test_iteratorMethod · 0.90
test_nested_callableMethod · 0.90
test_nested_mappingMethod · 0.90

Calls 2

itemsMethod · 0.45

Tested by 15

test_choices_iterableMethod · 0.72
test_emptyMethod · 0.72
test_choicesMethod · 0.72
test_callableMethod · 0.72
test_mappingMethod · 0.72
test_iterableMethod · 0.72
test_iteratorMethod · 0.72
test_nested_callableMethod · 0.72
test_nested_mappingMethod · 0.72
test_nested_iterableMethod · 0.72
test_nested_iteratorMethod · 0.72