mirror of
https://github.com/jazzband/django-configurations.git
synced 2026-05-14 10:33:12 +00:00
Add TupleOfTuplesValue along with associated tests and updated documentation
This commit is contained in:
parent
5d1a8d7887
commit
c4ba5ca559
3 changed files with 92 additions and 11 deletions
|
|
@ -176,7 +176,16 @@ class ListValue(Value):
|
|||
self.default = []
|
||||
# initial conversion
|
||||
if self.converter is not None:
|
||||
self.default = [self.converter(value) for value in self.default]
|
||||
self.default = self._convert(self.default)
|
||||
|
||||
def _convert(self, list_):
|
||||
converted_values = []
|
||||
for value in list_:
|
||||
try:
|
||||
converted_values.append(self.converter(value))
|
||||
except (TypeError, ValueError):
|
||||
raise ValueError(self.message.format(value, value))
|
||||
return converted_values
|
||||
|
||||
def to_python(self, value):
|
||||
split_value = [v.strip() for v in value.strip().split(self.separator)]
|
||||
|
|
@ -184,14 +193,7 @@ class ListValue(Value):
|
|||
value_list = filter(None, split_value)
|
||||
if self.converter is None:
|
||||
return list(value_list)
|
||||
|
||||
converted_values = []
|
||||
for list_value in value_list:
|
||||
try:
|
||||
converted_values.append(self.converter(list_value))
|
||||
except (TypeError, ValueError):
|
||||
raise ValueError(self.message.format(list_value, value))
|
||||
return converted_values
|
||||
return self._convert(value_list)
|
||||
|
||||
|
||||
class BackendsValue(ListValue):
|
||||
|
|
@ -218,6 +220,33 @@ class TupleValue(ListValue):
|
|||
return tuple(super(TupleValue, self).to_python(value))
|
||||
|
||||
|
||||
class TupleOfTuplesValue(TupleValue):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.tuple_separator = kwargs.pop('tuple_separator', ';')
|
||||
super(TupleOfTuplesValue, self).__init__(*args, **kwargs)
|
||||
|
||||
def _convert(self, items):
|
||||
# This could receive either a bare tuple or tuple of tuples
|
||||
if items and isinstance(items[0], tuple):
|
||||
converted_tuples = []
|
||||
for inner in items:
|
||||
converted = super(TupleOfTuplesValue, self)._convert(inner)
|
||||
converted_tuples.append(tuple(converted))
|
||||
return tuple(converted_tuples)
|
||||
return tuple(super(TupleOfTuplesValue, self)._convert(items))
|
||||
|
||||
def to_python(self, value):
|
||||
split_value = [
|
||||
v.strip() for v in value.strip().split(self.tuple_separator)
|
||||
]
|
||||
# Remove empty items
|
||||
value_list = filter(None, split_value)
|
||||
tuples = [
|
||||
super(TupleOfTuplesValue, self).to_python(v) for v in value_list
|
||||
]
|
||||
return tuple(tuples)
|
||||
|
||||
|
||||
class SetValue(ListValue):
|
||||
message = 'Cannot interpret set item {0!r} in set {1!r}'
|
||||
|
||||
|
|
|
|||
|
|
@ -274,6 +274,27 @@ Type values
|
|||
|
||||
See the :class:`~ListValue` examples above.
|
||||
|
||||
.. class:: TupleOfTuplesValue(default, [tuple_separator=';', separator=',', converter=None])
|
||||
|
||||
A :class:`~TupleValue` subclass that handles tuple of tuples values.
|
||||
|
||||
:param tuple_separator: the separator to split each tuple with
|
||||
:param separator: the separator to split the inner tuple contents with
|
||||
:param converter: the optional converter callable to apply for each inner
|
||||
tuple item
|
||||
|
||||
Useful for ADMINS, MANAGERS, and the like. For example::
|
||||
|
||||
ADMINS = TupleOfTuplesValue((
|
||||
('John', 'jcleese@site.com'),
|
||||
('Eric', 'eidle@site.com'),
|
||||
))
|
||||
|
||||
Override using environment variables like this::
|
||||
|
||||
DJANGO_ADMINS=Terry,tjones@site.com;Graham,gchapman@site.com
|
||||
|
||||
|
||||
.. class:: SetValue
|
||||
|
||||
A :class:`~Value` subclass that handles set values.
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ from mock import patch
|
|||
|
||||
from configurations.values import (Value, BooleanValue, IntegerValue,
|
||||
FloatValue, DecimalValue, ListValue,
|
||||
TupleValue, SetValue, DictValue,
|
||||
URLValue, EmailValue, IPValue,
|
||||
TupleValue, TupleOfTuplesValue, SetValue,
|
||||
DictValue, URLValue, EmailValue, IPValue,
|
||||
RegexValue, PathValue, SecretValue,
|
||||
DatabaseURLValue, EmailURLValue,
|
||||
CacheURLValue, BackendsValue,
|
||||
|
|
@ -175,6 +175,37 @@ class ValueTests(TestCase):
|
|||
with env(DJANGO_TEST=''):
|
||||
self.assertEqual(value.setup('TEST'), ())
|
||||
|
||||
def test_tuple_of_tuples_values_default(self):
|
||||
value = TupleOfTuplesValue()
|
||||
with env(DJANGO_TEST='2,3;4,5'):
|
||||
expected = (('2', '3'), ('4', '5'))
|
||||
self.assertEqual(value.setup('TEST'), expected)
|
||||
with env(DJANGO_TEST='2;3;4;5'):
|
||||
expected = (('2',), ('3',), ('4',), ('5',))
|
||||
self.assertEqual(value.setup('TEST'), expected)
|
||||
with env(DJANGO_TEST='2,3,4,5'):
|
||||
expected = (('2', '3', '4', '5'),)
|
||||
self.assertEqual(value.setup('TEST'), expected)
|
||||
with env(DJANGO_TEST='2, 3 , ; 4 , 5 ; '):
|
||||
expected = (('2', '3'), ('4', '5'))
|
||||
self.assertEqual(value.setup('TEST'), expected)
|
||||
with env(DJANGO_TEST=''):
|
||||
self.assertEqual(value.setup('TEST'), ())
|
||||
|
||||
def test_tuple_of_tuples_values_separator(self):
|
||||
value = TupleOfTuplesValue(tuple_separator=':')
|
||||
with env(DJANGO_TEST='2,3:4,5'):
|
||||
self.assertEqual(value.setup('TEST'), (('2', '3'), ('4', '5')))
|
||||
|
||||
def test_tuple_of_tuples_values_converter(self):
|
||||
value = TupleOfTuplesValue(converter=int)
|
||||
with env(DJANGO_TEST='2,3;4,5'):
|
||||
self.assertEqual(value.setup('TEST'), ((2, 3), (4, 5)))
|
||||
|
||||
def test_tuple_of_tuples_values_converter_default(self):
|
||||
value = TupleOfTuplesValue((('2', '3'), ('4', '5')), converter=int)
|
||||
self.assertEqual(value.value, ((2, 3), (4, 5)))
|
||||
|
||||
def test_set_values_default(self):
|
||||
value = SetValue()
|
||||
with env(DJANGO_TEST='2,2'):
|
||||
|
|
|
|||
Loading…
Reference in a new issue