Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bug] @reverse_lazy doesn't get evaluated without settings.using_env #1087

Open
wgordon17 opened this issue Mar 31, 2024 · 4 comments
Open
Assignees
Labels

Comments

@wgordon17
Copy link
Contributor

wgordon17 commented Mar 31, 2024

Describe the bug
To be honest, it's not entirely clear to me where the bug is, or how I'm hitting it. But I was able to reproduce this with #1086. It appears that the custom converted (added with add_converter for reverse_lazy) doesn't end up getting evaluated until after a with settings.using_env() gets applied.

So, the tests, evaluating self.assertEqual(settings.LOGIN_URL, "/admin/login/"), works at the bottom of the test (after running with settings.using_env(), but if it's tested at the top of the test (before any with settings.using_env() statements) it fails.

I really don't know why this is, but I'm seeing the same behavior in my own repo (which is what prompted me to start digging).

Environment (please complete the following information):

  • OS: macos Sonoma 14.4.1
  • Dynaconf Version: 3.2.5 and on master
  • Frameworks in use: Django==3.2.25 (running in other repo) and Django==5.0.3 (running in master here)
@wgordon17 wgordon17 added the bug label Mar 31, 2024
@wgordon17
Copy link
Contributor Author

There appears to be a similarly related timing bug, I can't use a lazily evaluated value inside of @pytest.mark.parametrize

@pytest.mark.parametrize(
    ("expected_url"),
    [settings.LOGIN_URL)],
)
def test_url(expected_url):
    assert expected_url == "/admin/login/"

@wgordon17
Copy link
Contributor Author

There is something in this PR, #951, that introduced this change in behavior. Using my nifty new tool, git bisect that I picked up from Django, it's definitely pinpointed to that PR as the introduction in change in behavior. I'm open to any suggestions!

@pedro-psb pedro-psb self-assigned this Apr 6, 2024
@pedro-psb
Copy link
Member

Hey, thanks for the investigation and the reproduction, I'll try to have a look into this.

@pedro-psb
Copy link
Member

I have a theory.
Just some context, the #951 PR adds a post-load hook function is used there because we can't import reverse_lazy on the top_module in settings.py. But here is what I think is happening:

  1. instantiate DjangoDynaconf: register hook that loads @reverse_lazy
  2. execute_loader: here we load default, user settings etc
    1. When LOGIN_URL is loaded, its interpreted as a string, because the @reverse_lazy was not added yet (the hook is a "post" hook, its executed after loading).
  3. post-hook is called, which then effectively registers the @reverse_lazy function, but it doesn't take effect unless we do load the setting again.

Then, if somehow we make dynaconf re-execute the loaders, the @reverse_lazy will take effect because it will be present on loading time. The with_env context calls the settings reloading, but other reloads, such as using settings.get("LOGIN_URL", fresh=True) has the same effect (it also "fixes" the problem).

My first thought for approaching this is implementing a pre-hook and calling it before the loaders execution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants