Closed MicaelJarniac closed 4 years ago
I just realized I can probably create a custom function to give to cast
, and that might do the trick for the time being.
But I still think the feature I suggested would be nice.
Proof of concept:
from decouple import config
class Optional(object):
def __init__(self, cast=str):
self.cast = cast
def __call__(self, value):
if value is None:
return None
elif value == "None" or value == "":
return None
else:
return self.cast(value)
THRESHOLD = config("THRESHOLD", default=None, cast=Optional(float))
This way, THRESHOLD
in the config file can be missing, empty or the string None
, and all result in config
returning None
. If THRESHOLD
is set, however, it's then cast to the provided type (float
, in this case).
It's not perfect, but it does work sort of how I wanted it to.
But still, when calling config
, we have to provide a default
, otherwise it'll still throw the error if it can't find the value in the config. It'd be nice to be able to do just
from decouple import config, Optional
THRESHOLD = config("THRESHOLD", cast=Optional(float))
or even
from decouple import config
THRESHOLD = config("THRESHOLD", optional=True, cast=float)
Default must always be a string to be parsed by cast. Decouple is small and simple. Any workflow related code must be on your project's level, not the library.
In my use case, I have some configuration variables that are optional, and some of them have a specific type.
As they're optional, they can either be of some specific type, or
None
. The problem is, I usecast=type
when reading them, but if I adddefault=None
, thencast
returns an error, asNone
can't be cast totype
.Example
Say I have a project for reading a sensor, and there's an optional config var for triggering an alarm if the sensor reaches a certain level.
Such config var should be a
float
, if set, and it can be positive, zero, or negative, as the values read from the sensor can be any float.If I don't want the alarm feature, I can set its threshold to
None
, and that bypasses the checks completely.The problem is, if I have the config being cast to
float
, and the default value set toNone
, it tries to castNone
tofloat
and errors.So I have to either have no cast, so I'm able to assign
None
to it, or I have to do sometry, except
logic to handle the variable not being present, thus creating an alternative to thedefault
parameter.Having the default value be a float, like
0.0
or-1.0
, wouldn't help in this case, as the sensor can output those values, thus it'd be a valid threshold and the alarm could be triggered.My current workaround is as follows:
This way, if
THRESHOLD
is not set, it'll raise theUndefinedValueError
, that'll then be handled by theexcept
block, and setTHRESHOLD
toNone
.It seems to do the trick, but when there are multiple variables like this one, it can easily become a mess.
My suggestion is to have something like an
optional
parameter, that'sFalse
by default, but that can be set toTrue
, and if so, if the value is not present, instead of raising an exception, it returnsNone
.The same example from above would be like this:
That's considerably less code, and it's more readable IMO.
It's a bit similar to how
typing
does things:is the same as