Skip to content

[bug] CLI not working with Django on master #949

@rochacbruno

Description

@rochacbruno

On master branch the CLI is not working in a Django app

Steps to Reproduce

❯ cd tests_functional/django_example
❯ DJANGO_SETTINGS_MODULE=foo.settings PYTHONPATH=. dynaconf list
Django app detected


╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮

│                                                                                                  │
│ /home/rochacbruno/Projects/dynaconf/dynaconf/cli.py:546 in _list                                 │
│                                                                                                  │
│   543 │   if env:                                                                                │
│   544 │   │   settings.setenv(env)                                                               │
│   545 │                                                                                          │
│ ❱ 546 │   cur_env = settings.current_env.lower()                                                 │
│   547 │                                                                                          │
│   548 │   if cur_env == "main":                                                                  │
│   549 │   │   flat = True                                                                        │
│                                                                                                  │
│ ╭───────────────────────────────── locals ─────────────────────────────────╮                     │
│ │     _all = False                                                         │                     │
│ │      ctx = <dynaconf.vendor.click.core.Context object at 0x7f4d5a77c130> │                     │
│ │      env = None                                                          │                     │
│ │     flat = False                                                         │                     │
│ │      key = None                                                          │                     │
│ │   loader = None                                                          │                     │
│ │     more = None                                                          │                     │
│ │   output = None                                                          │                     │
│ │ settings = <LazySettings "foo.settings">                                 │                     │
│ ╰──────────────────────────────────────────────────────────────────────────╯                     │
│                                                                                                  │
│ /home/rochacbruno/Projects/dynaconf/.venv/lib/python3.8/site-packages/django/conf/__init__.py:88 │
│ in __getattr__                                                                                   │
│                                                                                                  │
│    85 │   │   """Return the value of a setting and cache it in self.__dict__."""                 │
│    86 │   │   if self._wrapped is empty:                                                         │
│    87 │   │   │   self._setup(name)                                                              │
│ ❱  88 │   │   val = getattr(self._wrapped, name)                                                 │
│    89 │   │                                                                                      │
│    90 │   │   # Special case some settings which require further modification.                   │
│    91 │   │   # This is done here for performance reasons so the modified value is cached.       │
│                                                                                                  │
│ ╭─────────────── locals ───────────────╮                                                         │
│ │ name = 'current_env'                 │                                                         │
│ │ self = <LazySettings "foo.settings"> │                                                         │
│ ╰──────────────────────────────────────╯                                                         │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
AttributeError: 'Settings' object has no attribute 'current_env'

Same error happens with get command

❯ DJANGO_SETTINGS_MODULE=foo.settings PYTHONPATH=. dynaconf get DEBUG


│ /home/rochacbruno/Projects/dynaconf/dynaconf/cli.py:475 in get                                   │
│                                                                                                  │
│   472 │   if default is not empty:                                                               │
│   473 │   │   result = settings.get(key, default)                                                │
│   474 │   else:                                                                                  │
│ ❱ 475 │   │   result = settings[key]  # let the keyerror raises                                  │
│   476 │                                                                                          │
│   477 │   if unparse:                                                                            │
│   478 │   │   result = unparse_conf_data(result)                                                 │
│                                                                                                  │
│ ╭───────────────────────────────── locals ─────────────────────────────────╮                     │
│ │      ctx = <dynaconf.vendor.click.core.Context object at 0x7f32e513c130> │                     │
│ │  default = <dynaconf.utils.functional.Empty object at 0x7f32e4a5d0d0>    │                     │
│ │      env = None                                                          │                     │
│ │      key = 'DEBUG'                                                       │                     │
│ │ settings = <LazySettings "foo.settings">                                 │                     │
│ │  unparse = False                                                         │                     │
│ ╰──────────────────────────────────────────────────────────────────────────╯                     │
│                                                                                                  │
│ /home/rochacbruno/Projects/dynaconf/.venv/lib/python3.8/site-packages/django/utils/functional.py │
│ :259 in inner                                                                                    │
│                                                                                                  │
│   256 │   def inner(self, *args):                                                                │
│   257 │   │   if self._wrapped is empty:                                                         │
│   258 │   │   │   self._setup()                                                                  │
│ ❱ 259 │   │   return func(self._wrapped, *args)                                                  │
│   260 │                                                                                          │
│   261 │   return inner                                                                           │
│   262                                                                                            │
│                                                                                                  │
│ ╭─────────────── locals ───────────────╮                                                         │
│ │ args = ('DEBUG',)                    │                                                         │
│ │ func = <built-in function getitem>   │                                                         │
│ │ self = <LazySettings "foo.settings"> │                                                         │
│ ╰──────────────────────────────────────╯                                                         │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
TypeError: 'Settings' object is not subscriptable

And also the new inspect command

│ /home/rochacbruno/Projects/dynaconf/dynaconf/utils/inspect.py:79 in inspect_settings             │
│                                                                                                  │
│    76 │   original_settings = settings                                                           │
│    77 │   settings = settings if not env else settings.from_env(env)                             │
│    78 │                                                                                          │
│ ❱  79 │   setting_envs = {_env.env for _env in settings._loaded_by_loaders.keys()}               │
│    80 │   if env and env.lower() not in setting_envs:                                            │
│    81 │   │   raise EnvNotFoundError(f"The requested env is not valid: {env!r}")                 │
│    82                                                                                            │
│                                                                                                  │
│ ╭───────────────────── locals ──────────────────────╮                                            │
│ │   ascending_order = True                          │                                            │
│ │     custom_dumper = None                          │                                            │
│ │               env = ''                            │                                            │
│ │   key_dotted_path = 'DEBUG'                       │                                            │
│ │ original_settings = <LazySettings "foo.settings"> │                                            │
│ │     output_format = 'json'                        │                                            │
│ │          settings = <LazySettings "foo.settings"> │                                            │
│ │           to_file = ''                            │                                            │
│ ╰───────────────────────────────────────────────────╯                                            │
│                                                                                                  │
│ /home/rochacbruno/Projects/dynaconf/.venv/lib/python3.8/site-packages/django/conf/__init__.py:88 │
│ in __getattr__                                                                                   │
│                                                                                                  │
│    85 │   │   """Return the value of a setting and cache it in self.__dict__."""                 │
│    86 │   │   if self._wrapped is empty:                                                         │
│    87 │   │   │   self._setup(name)                                                              │
│ ❱  88 │   │   val = getattr(self._wrapped, name)                                                 │
│    89 │   │                                                                                      │
│    90 │   │   # Special case some settings which require further modification.                   │
│    91 │   │   # This is done here for performance reasons so the modified value is cached.       │
│                                                                                                  │
│ ╭─────────────── locals ───────────────╮                                                         │
│ │ name = '_loaded_by_loaders'          │                                                         │
│ │ self = <LazySettings "foo.settings"> │                                                         │
│ ╰──────────────────────────────────────╯                                                         │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
AttributeError: 'Settings' object has no attribute '_loaded_by_loaders'

Investigation

In the django context the settings is being applied correctly

❯ DJANGO_SETTINGS_MODULE=foo.settings PYTHONPATH=. django-admin shell
In [1]: from django.conf import settings

In [2]: settings.__class__
Out[2]: dynaconf.base.Settings

However I added a breakpoint on line 545 of cli.py and figured out that settings there is a bare Django.conf.settings not a dynaconf.base.Settings instance, for some reason the dynaconf plugin is not being loaded at that point.

Expected

At the same directory, checking out to 3.2.12 branch everything works as expected.

❯ git checkout 3.1.12

❯ DJANGO_SETTINGS_MODULE=foo.settings PYTHONPATH=. dynaconf list            
Django app detected
Working in production environment 
BASE_DIR<str> '/home/rochacbruno/Projects/dynaconf/tests_functional/django_example'
STATIC_URL<str> '/static/'
...


❯ DJANGO_SETTINGS_MODULE=foo.settings PYTHONPATH=. dynaconf get DEBUG
True%    

## Inspect command does not exist on that version.

❯ DJANGO_SETTINGS_MODULE=foo.settings PYTHONPATH=. django-admin shell
In [1]: from django.conf import settings

In [2]: settings.__class__
Out[2]: dynaconf.base.Settings

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions