You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Describe the bug
The load_enum_name_overrides function uses a decorator to cache function execution. However, the function internally uses the global variable spectacular_settings.ENUM_NAME_OVERRIDES, which is actually not constant. So whichever set of settings are loaded during the first execution of this function are implicitly baked into the cached result.
Specifically, if you are serving multiple schemas, each one can have its own custom settings. The way this works is that a context manager wraps the core view logic, patching the global settings object:
To Reproduce
Suppose your drf project has multiple installed applications. Each app can serve its own schema, with potentially unique drf-specatcular settings:
# in foo/urls.pypath("schema/", SpectacularAPIView.as_view(custom_settings=FOO_SPECTACULAR_SETTINGS), name="schema"),
# in bar/urls.pypath("schema/", SpectacularAPIView.as_view(custom_settings=BAR_SPECTACULAR_SETTINGS), name="schema"),
# in project_name/urls.pypath("foo/", include("foo.urls", namespace="foo")),
path("bar/", include("bar.urls", namespace="bar")),
Assuming that foo and bar have different enum overrides, loading foo first will break bar until the server restarts, and visa-versa.
Proposed fix
Make enum_name_overrides_setting an explicit argument to _load_enum_name_overrides, so it is cached properly:
defload_enum_name_overrides():
return_load_enum_name_overrides(
language=get_language(),
enum_name_overrides_setting=spectacular_settings.ENUM_NAME_OVERRIDES,
)
@functools.lru_cache()def_load_enum_name_overrides(language: str, enum_name_overrides_setting: dict[str, Any]):
overrides= {}
forname, choicesinenum_name_overrides_setting.items():
...
# there is one more usage of the setting at the bottom of the function that also needs to be swapped
Note that using the full settings object itself as a cached function argument will NOT work, since its hash function is not impacted by the patching process.
The text was updated successfully, but these errors were encountered:
Describe the bug
The
load_enum_name_overrides
function uses a decorator to cache function execution. However, the function internally uses the global variablespectacular_settings.ENUM_NAME_OVERRIDES
, which is actually not constant. So whichever set of settings are loaded during the first execution of this function are implicitly baked into the cached result.Specifically, if you are serving multiple schemas, each one can have its own custom settings. The way this works is that a context manager wraps the core view logic, patching the global settings object:
drf-spectacular/drf_spectacular/views.py
Lines 79 to 84 in 2501bfd
drf-spectacular/drf_spectacular/settings.py
Lines 279 to 283 in 2501bfd
The end result is that your expected enum overrides are not consistently applied, leading to unpredictable schema generation.
This bug is not new. It impacts both the historical implementation:
drf-spectacular/drf_spectacular/plumbing.py
Lines 862 to 865 in 9268276
as well as the recent changes to fix translation:
drf-spectacular/drf_spectacular/plumbing.py
Lines 863 to 870 in 2501bfd
To Reproduce
Suppose your drf project has multiple installed applications. Each app can serve its own schema, with potentially unique drf-specatcular settings:
Assuming that foo and bar have different enum overrides, loading foo first will break bar until the server restarts, and visa-versa.
Proposed fix
Make
enum_name_overrides_setting
an explicit argument to_load_enum_name_overrides
, so it is cached properly:Note that using the full settings object itself as a cached function argument will NOT work, since its hash function is not impacted by the patching process.
The text was updated successfully, but these errors were encountered: