refactor: fix wrongly initiated settings (#1250)

* refactor: fix wrongly initiated settings

* refacttor: remove `_load_settings()` from apps.py

* refactor: fix building of docs + update titles in API reference

* refactor: fix docs build error

* refactor: use EXTENSIONS_DEFAULTS

* refactor: update titles
This commit is contained in:
Juro Oravec 2025-06-10 10:12:48 +02:00 committed by GitHub
parent 2350a6b6c4
commit 458e1894db
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 65 additions and 41 deletions

View file

@ -34,6 +34,10 @@
Now, each subclass has it's own `Template` instance, and changes to the template of the subclass do not affect the template of the parent class.
- Fix Django failing to restart due to "TypeError: 'Dynamic' object is not iterable" ([#1232](https://github.com/django-components/django-components/issues/1232))
- Fix bug when error formatting failed when error value was not a string.
## v0.140.1
#### Fix

View file

@ -1,16 +1,16 @@
# `.nav.yml` is provided by https://lukasgeiter.github.io/mkdocs-awesome-nav
nav:
- API: api.md
- Commands: commands.md
- CLI commands: commands.md
- Components: components.md
- Exceptions: exceptions.md
- Extension commands: extension_commands.md
- Extension hooks: extension_hooks.md
- Extension URLs: extension_urls.md
- Extension commands API: extension_commands.md
- Extension URLs API: extension_urls.md
- Settings: settings.md
- Signals: signals.md
- Tag formatters: tag_formatters.md
- Template tags: template_tags.md
- Template vars: template_vars.md
- Template variables: template_vars.md
- URLs: urls.md
- Testing API: testing_api.md

View file

@ -1,6 +1,6 @@
<!-- Autogenerated by reference.py -->
# Extension commands
# Extension commands API
Overview of all classes, functions, and other objects related to defining extension commands.

View file

@ -1,6 +1,6 @@
<!-- Autogenerated by reference.py -->
# Extension URLs
# Extension URLs API
Overview of all classes, functions, and other objects related to defining extension URLs.

View file

@ -67,7 +67,7 @@ If you insert this tag multiple times, ALL JS scripts will be duplicately insert
<a href="https://github.com/django-components/django-components/tree/master/src/django_components/templatetags/component_tags.py#L3796" target="_blank">See source code</a>
<a href="https://github.com/django-components/django-components/tree/master/src/django_components/templatetags/component_tags.py#L3799" target="_blank">See source code</a>

View file

@ -44,6 +44,7 @@ from pathlib import Path
from textwrap import dedent
from typing import Any, Dict, List, NamedTuple, Optional, Sequence, Tuple, Type, Union
from django.conf import settings
from django.core.management.base import BaseCommand
from django.urls import URLPattern, URLResolver
@ -465,7 +466,13 @@ def gen_reference_commands():
# Add link to source code
module_abs_path = import_module(cmd_def_cls.__module__).__file__
module_rel_path = Path(module_abs_path).relative_to(Path.cwd()).as_posix() # type: ignore[arg-type]
obj_lineno = inspect.findsource(cmd_def_cls)[1]
# NOTE: Raises `OSError` if the file is not found.
try:
obj_lineno = inspect.findsource(cmd_def_cls)[1]
except Exception:
obj_lineno = None
source_code_link = _format_source_code_html(module_rel_path, obj_lineno)
# NOTE: For the commands we have to generate the markdown entries ourselves,
@ -524,7 +531,7 @@ def gen_reference_commands():
)
def gen_reference_templatetags():
def gen_reference_template_tags():
"""
Generate documentation for all Django template tags defined by django-components,
like `{% slot %}`, `{% component %}`, etc.
@ -537,7 +544,7 @@ def gen_reference_templatetags():
]
preface = "<!-- Autogenerated by reference.py -->\n\n"
preface += (root / "docs/templates/reference_templatetags.md").read_text()
preface += (root / "docs/templates/reference_template_tags.md").read_text()
out_file = root / "docs/reference/template_tags.md"
out_file.parent.mkdir(parents=True, exist_ok=True)
@ -585,14 +592,14 @@ def gen_reference_templatetags():
)
def gen_reference_templatevars():
def gen_reference_template_variables():
"""
Generate documentation for all variables that are available inside the component templates
under the `{{ component_vars }}` variable, as defined by `ComponentVars`.
"""
preface = "<!-- Autogenerated by reference.py -->\n\n"
preface += (root / "docs/templates/reference_templatevars.md").read_text()
out_file = root / "docs/reference/template_vars.md"
preface += (root / "docs/templates/reference_template_variables.md").read_text()
out_file = root / "docs/reference/template_variables.md"
out_file.parent.mkdir(parents=True, exist_ok=True)
with out_file.open("w", encoding="utf-8") as f:
@ -1099,6 +1106,13 @@ def _is_extension_url_api(obj: Any) -> bool:
def gen_reference():
"""The entrypoint to generate all the reference documentation."""
# Set up Django settings so we can import `extensions`
if not settings.configured:
settings.configure(
BASE_DIR=Path(__file__).parent.parent.parent,
)
gen_reference_api()
gen_reference_exceptions()
gen_reference_components()
@ -1106,8 +1120,8 @@ def gen_reference():
gen_reference_tagformatters()
gen_reference_urls()
gen_reference_commands()
gen_reference_templatetags()
gen_reference_templatevars()
gen_reference_template_tags()
gen_reference_template_variables()
gen_reference_signals()
gen_reference_testing_api()
gen_reference_extension_hooks()

View file

@ -1,4 +1,4 @@
# Extension commands
# Extension commands API
Overview of all classes, functions, and other objects related to defining extension commands.

View file

@ -1,4 +1,4 @@
# Extension URLs
# Extension URLs API
Overview of all classes, functions, and other objects related to defining extension URLs.

View file

@ -746,8 +746,8 @@ defaults = ComponentsSettings(
#
# Settings are loaded from Django settings only once, at `apps.py` in `ready()`.
class InternalSettings:
def __init__(self, settings: Optional[Dict[str, Any]] = None):
self._settings = ComponentsSettings(**settings) if settings else defaults
def __init__(self) -> None:
self._settings: Optional[ComponentsSettings] = None
def _load_settings(self) -> None:
data = getattr(settings, "COMPONENTS", {})
@ -786,6 +786,11 @@ class InternalSettings:
tag_formatter=default(components_settings.tag_formatter, defaults.tag_formatter), # type: ignore[arg-type]
)
def _get_settings(self) -> ComponentsSettings:
if self._settings is None:
self._load_settings()
return cast(ComponentsSettings, self._settings)
def _prepare_extensions(self, new_settings: ComponentsSettings) -> List["ComponentExtension"]:
extensions: Sequence[Union[Type["ComponentExtension"], str]] = default(
new_settings.extensions, cast(List[str], defaults.extensions)
@ -853,70 +858,73 @@ class InternalSettings:
return raw_value
# TODO REMOVE THE PROPERTIES BELOW? THEY NO LONGER SERVE ANY PURPOSE
@property
def AUTODISCOVER(self) -> bool:
return self._settings.autodiscover # type: ignore[return-value]
return self._get_settings().autodiscover # type: ignore[return-value]
@property
def CACHE(self) -> Optional[str]:
return self._settings.cache
return self._get_settings().cache
@property
def DIRS(self) -> Sequence[Union[str, PathLike, Tuple[str, str], Tuple[str, PathLike]]]:
return self._settings.dirs # type: ignore[return-value]
return self._get_settings().dirs # type: ignore[return-value]
@property
def APP_DIRS(self) -> Sequence[str]:
return self._settings.app_dirs # type: ignore[return-value]
return self._get_settings().app_dirs # type: ignore[return-value]
@property
def DEBUG_HIGHLIGHT_COMPONENTS(self) -> bool:
return self._settings.debug_highlight_components # type: ignore[return-value]
return self._get_settings().debug_highlight_components # type: ignore[return-value]
@property
def DEBUG_HIGHLIGHT_SLOTS(self) -> bool:
return self._settings.debug_highlight_slots # type: ignore[return-value]
return self._get_settings().debug_highlight_slots # type: ignore[return-value]
@property
def DYNAMIC_COMPONENT_NAME(self) -> str:
return self._settings.dynamic_component_name # type: ignore[return-value]
return self._get_settings().dynamic_component_name # type: ignore[return-value]
@property
def LIBRARIES(self) -> List[str]:
return self._settings.libraries # type: ignore[return-value]
return self._get_settings().libraries # type: ignore[return-value]
@property
def EXTENSIONS(self) -> List["ComponentExtension"]:
return self._settings.extensions # type: ignore[return-value]
return self._get_settings().extensions # type: ignore[return-value]
@property
def EXTENSIONS_DEFAULTS(self) -> Dict[str, Any]:
return self._get_settings().extensions_defaults # type: ignore[return-value]
@property
def MULTILINE_TAGS(self) -> bool:
return self._settings.multiline_tags # type: ignore[return-value]
return self._get_settings().multiline_tags # type: ignore[return-value]
@property
def RELOAD_ON_FILE_CHANGE(self) -> bool:
return self._settings.reload_on_file_change # type: ignore[return-value]
return self._get_settings().reload_on_file_change # type: ignore[return-value]
@property
def TEMPLATE_CACHE_SIZE(self) -> int:
return self._settings.template_cache_size # type: ignore[return-value]
return self._get_settings().template_cache_size # type: ignore[return-value]
@property
def STATIC_FILES_ALLOWED(self) -> Sequence[Union[str, re.Pattern]]:
return self._settings.static_files_allowed # type: ignore[return-value]
return self._get_settings().static_files_allowed # type: ignore[return-value]
@property
def STATIC_FILES_FORBIDDEN(self) -> Sequence[Union[str, re.Pattern]]:
return self._settings.static_files_forbidden # type: ignore[return-value]
return self._get_settings().static_files_forbidden # type: ignore[return-value]
@property
def CONTEXT_BEHAVIOR(self) -> ContextBehavior:
return ContextBehavior(self._settings.context_behavior)
return ContextBehavior(self._get_settings().context_behavior)
@property
def TAG_FORMATTER(self) -> Union["TagFormatterABC", str]:
return self._settings.tag_formatter # type: ignore[return-value]
return self._get_settings().tag_formatter # type: ignore[return-value]
app_settings = InternalSettings()

View file

@ -20,8 +20,6 @@ class ComponentsConfig(AppConfig):
from django_components.extension import extensions
from django_components.util.django_monkeypatch import monkeypatch_template_cls
app_settings._load_settings()
# NOTE: This monkeypatch is applied here, before Django processes any requests.
# To make django-components work with django-debug-toolbar-template-profiler
# See https://github.com/django-components/django-components/discussions/819

View file

@ -20,7 +20,7 @@ def _gen_subcommands() -> List[Type[ComponentCommand]]:
commands: List[Type[ComponentCommand]] = []
for extension in extensions.extensions:
ExtCommand = type(
"ExtCommand",
"ExtRunSubcommand_" + extension.name,
(ComponentCommand,),
{
"name": extension.name,

View file

@ -1047,7 +1047,7 @@ class ExtensionManager:
# - `MyExtensionBase` is the base class that the extension class inherits from.
bases_list = [ext_base_class]
all_extensions_defaults = app_settings._settings.extensions_defaults or {}
all_extensions_defaults = app_settings.EXTENSIONS_DEFAULTS or {}
extension_defaults = all_extensions_defaults.get(extension.name, None)
if extension_defaults:
# Create dummy class that holds the extension defaults

View file

@ -25,7 +25,7 @@ def component_error_message(component_path: List[str]) -> Generator[None, None,
if not components:
orig_msg = str(err.args[0])
else:
orig_msg = err.args[0].split("\n", 1)[-1]
orig_msg = str(err.args[0]).split("\n", 1)[-1]
else:
orig_msg = str(err)