django-environ
django-environ copied to clipboard
Lazily load default value of environment variable
Would you accept a pull request to enable lazy evaluation of default value ? I think there are several use cases where you want to generate the default on-demand. For example, creating a new temporary directory and use it as a default value when a env var doesn't exist in environment.
Please describe how you suggest it will work! Allowing the value to be just a plain function?
I use a pattern like this when I want to have that feature and it's not very verbose and easy to follow:
env = environ.Env(
SOMETHING=(str),
)
SOMETHING = env("SOMETHING",default=None)
if not SOMETHING:
... calculate and assign value of something
I think it's maybe not a good idea to allow lazy evaluation of values after settings.py
has been loaded, it's good to have the settings at least somewhat validated when the file is loaded..
Yeah I think being able to pass a plain function that's evaluated when env("SOMETHING", fun)
is called. This wouldn't make a difference timing-wise compared to what we're doing right now.
So something like this then.. I wonder if it clashes with other features or not, I cant think of anything from the top of my head..
def create_something():
return "SOMETHING"
env = environ.Env(
SOMETHING=(str, create_something),
)
SOMETHING = env('SOMETHING')
OTHER_THING=env('OTHER_THING', default_value=create_something, cast_to=str)
Note that the amount of code isn't shorter than the code I posted earlier, the only benifit I can see is that the type str
can be validated by django-environ after being returned from the function.. I still think that the settings file becomes harder to read and I wonder if it's worth it.
Yeah this is how I'd use it. I could submit a PR if you're okay with this.
De : Thomas Frössman [email protected] Envoyé : dimanche 1 juillet 2018 11:02:16 À : joke2k/django-environ Cc : konoufo; Author Objet : Re: [joke2k/django-environ] Lazily load default value of environment variable (#185)
So something like this then..
def create_something(): return "SOMETHING"
env = environ.Env( SOMETHING=(str, create_something), )
SOMETHING = env('SOMETHING')
OTHER_THING=env('OTHER_THING', default_value=create_something, cast_to=str)
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://github.com/joke2k/django-environ/issues/185#issuecomment-401599514, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AJMLjLkjRj9f6f-n7pqylFxKFr7sd_mfks5uCKw4gaJpZM4UVWCm.
I am not a maintainer. I just wanted to understand what you were requesting (for the benefit of everyone) , it looks clear to me now..
Oh okay! Sorry. Alright, waiting for the maintainers then...
De : Thomas Frössman [email protected] Envoyé : dimanche 1 juillet 2018 17:45:57 À : joke2k/django-environ Cc : konoufo; Author Objet : Re: [joke2k/django-environ] Lazily load default value of environment variable (#185)
I am not a maintainer. I just wanted to understand what you were requesting, it looks clear to me now..
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://github.com/joke2k/django-environ/issues/185#issuecomment-401621835, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AJMLjHAUoyFzbQDZ-tawBnfDcQZvTpBnks5uCQrVgaJpZM4UVWCm.
I haven't tested this, but would creating your own lazy class work?
def create_something():
return "SOMETHING"
class LazyString:
def __init__(self, value, fn):
self.value = value
self.fn = fn
def __str__(self):
if self.value is not None:
return self.value
return self.fn()
OTHER_THING=LazyString(env('OTHERTHING', default=None), create_something)
# someotherfile.py
from django.conf import settings
other_thing = str(settings.OTHER_THING)
Well, I'd have to edit every code that uses OTHER_THING
to replace settings.OTHER_THING
with settings.OTHER_THING.value
. I'm aware of workarounds to get the functionality I want. But for the sake of separation of concerns, I don't want to call create_something
inside the settings file. And for consistency, I want the actual value of a setting to be always directly accessible thru settings.FOO
. Moreover, I think to have the default
argument to also accept a function just make sense and this pattern is ubiquitous in Python libraries.
De : Jafnee [email protected] Envoyé : lundi 2 juillet 2018 03:29:24 À : joke2k/django-environ Cc : konoufo; Author Objet : Re: [joke2k/django-environ] Lazily load default value of environment variable (#185)
I haven't tested this, but would creating your own lazy class work?
def create_something(): return "SOMETHING"
class LazyString: def init(self, value, fn): self.value = value self.fn = fn
def __str__(self):
if self.value:
return self.value
return self.fn()
OTHER_THING=LazyString(env('OTHERTHING', default=None), create_something)
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://github.com/joke2k/django-environ/issues/185#issuecomment-401662154, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AJMLjIn_CBbk2BYfjx6illwqOByYc_1eks5uCZOUgaJpZM4UVWCm.
Shouldn't need to replace everything to settings.OTHER_THING.value
, the example above is meant to evaluated lazily whenever the setting is used.
The value will either be the string set via env var or the return value of the function provided. The function is also called each time the setting is used, e.g if it returned the timestamp now, it will always return the latest value.
Remember that if you are using it for creating a new temporary directory and use it as a default value and don't return a static value the value will probably be different for each django process in a uwsgi server. If possible you should normally always prefer a deterministic way to create the settings even if it's lazily set.
Hi, I think this feature could be useful. As @konoufo said, callable defaults are ubiquitous in Python, and we could implement it as easy. Here https://github.com/joke2k/django-environ/blob/develop/environ/environ.py#L279 we could handle this, without side effects.
@Jafnee that is if you assume that the setting will be used in some way as a string or coerced to a string. @thomasf I realize that and the temporary directory setting is just a specific use case; but yeah I'm aware that it has to be deterministic if I want a single unique directory for every process. @joke2k Right, I could submit a PR.