Opened 3 years ago

Closed 3 years ago

Last modified 2 years ago

#32894 closed Cleanup/optimization (needsinfo)

isinstance() checks with non-configured LazySettings raise an exception.

Reported by: simon klemenc Owned by: nobody
Component: Utilities Version: 3.2
Severity: Normal Keywords: lazyobject lazysettings
Cc: Keryn Knight Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: yes UI/UX: no

Description

steps to reproduce:

import django.conf

settings = django.conf.LazySettings()
isinstance(settings, dict)

---------------------------------------------------------------------------
ImproperlyConfigured                      Traceback (most recent call last)
<ipython-input-36-201b302c2983> in <module>
      2 
      3 settings = django.conf.LazySettings()
----> 4 isinstance(settings, str)

~/.local/lib/python3.9/site-packages/django/utils/functional.py in inner(self, *args)
    244     def inner(self, *args):
    245         if self._wrapped is empty:
--> 246             self._setup()
    247         return func(self._wrapped, *args)
    248     return inner

~/.local/lib/python3.9/site-packages/django/conf/__init__.py in _setup(self, name)
     61         if not settings_module:
     62             desc = ("setting %s" % name) if name else "settings"
---> 63             raise ImproperlyConfigured(
     64                 "Requested %s, but settings are not configured. "
     65                 "You must either define the environment variable %s "

ImproperlyConfigured: Requested settings, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.

isinstance is accessing class which wants to setup the lazyobject
maybe class should fall back to returning the "LazyObject"

Change History (6)

comment:1 by Mariusz Felisiak, 3 years ago

Component: Core (Other)Utilities
Resolution: needsinfo
Status: newclosed
Type: UncategorizedCleanup/optimization

Thanks for this report, however I don't see any practical issue here 🤔 Moreover LazySettings is an internal undocumented tool and the error message sounds good.

Can you describe your use case?

comment:2 by Mariusz Felisiak, 3 years ago

Summary: isinstance(LazyConfig, str) raises Excepionisinstance() checks with non-configured LazySettings raise an exception.

comment:3 by simon klemenc, 3 years ago

Thanks for the response,

the use case is a quite specific problem i encountered:

https://github.com/pyqtgraph/pyqtgraph/blob/4a921ddf7137c529ed033de6f933cf840f184776/pyqtgraph/__init__.py#L327

here some kind of garbage-cleanup fails because isinstance(LazyConfig, XX) fails...

To fix the tests, in the class method the setup could be catched in a try/except.
My personal feeling is that a type check should work always...?

comment:4 by Nick Pope, 3 years ago

I was baffled by you mentioning pyqtgraph here which doesn't use Django.

I did some digging which came up with this issue, however.

Are you using PyCharm? (Just wondering if it is the same problem.)

comment:5 by Keryn Knight, 3 years ago

Cc: Keryn Knight added

Adding a note to say that whilst I understand why it's closed, I think I have just been bitten by this in a similarly niche scenario: trying to use pympler's tracking module threw an error when I tried to run it over the test suite:

File "/path/to/django/tests/runtests.py", line 679, in <module>
    mem.print_diff()
  File "/path/to/python3.10/site-packages/pympler/tracker.py", line 138, in print_diff
    summary.print_(self.diff(summary1=summary1, summary2=summary2))
  File "/path/to/python3.10/site-packages/pympler/tracker.py", line 116, in diff
    self.s1 = self.create_summary()
  File "/path/to/python3.10/site-packages/pympler/tracker.py", line 91, in create_summary
    res = summary.summarize(muppy.get_objects())
  File "/path/to/python3.10/site-packages/pympler/muppy.py", line 42, in get_objects
    tmp = [o for o in tmp if not ignore_object(o)]
  File "/path/to/python3.10/site-packages/pympler/muppy.py", line 42, in <listcomp>
    tmp = [o for o in tmp if not ignore_object(o)]
  File "/path/to/python3.10/site-packages/pympler/muppy.py", line 17, in ignore_object
    return isframe(obj)
  File "/path/to/python3.10/inspect.py", line 377, in isframe
    return isinstance(object, types.FrameType)
  File "/path/to/django/utils/functional.py", line 256, in inner
    self._setup()
  File "/path/to/django/contrib/staticfiles/storage.py", line 469, in _setup
    self._wrapped = get_storage_class(settings.STATICFILES_STORAGE)()

I don't have a proposed solution as such, but it looks like it's attempting to access __class__ when it fails, which would appear (back of the napkin) to be happening before any custom __instancecheck__(...) call could be implemented, based on a quick bit of pdb usage :/

comment:6 by Keryn Knight, 2 years ago

Continuing to document new ways in which I come across this (always niche, naturally) in case there ever comes a tipping point where it's potentially worth investigating options further.

Running:

monkeytype run -m runtests --parallel=1

against the Django test suite generates a lot of log noise like so:

Failed collecting trace
Traceback (most recent call last):
  File "/path/to/python3.10/site-packages/monkeytype/tracing.py", line 259, in __call__
    self.handle_call(frame)
  File "/path/to/python3.10/site-packages/monkeytype/tracing.py", line 213, in handle_call
    func = self._get_func(frame)
  File "/path/to/python3.10/site-packages/monkeytype/tracing.py", line 207, in _get_func
    self.cache[code] = get_func(frame)
  File "/path/to/python3.10/site-packages/monkeytype/tracing.py", line 156, in get_func
    if not isinstance(v, type):
  File "/path/to/django/utils/functional.py", line 294, in __getattribute__
    value = super().__getattribute__(name)
  File "/path/to/django/utils/functional.py", line 266, in inner
    self._setup()
  File "/path/to/django/conf/__init__.py", line 72, in _setup
    raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: Requested settings, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.

They all seem to be log messages which may not actually present as an error/problem in practice, though (that is, the test suite looks to continue running ... but I gave up on it as it was taking forever)

Note: See TracTickets for help on using tickets.
Back to Top