mirror of
https://github.com/django-components/django-components.git
synced 2025-08-11 17:57:59 +00:00
fix: thread unsafe media resolve validation by moving it to ComponentMedia __post_init (#979)
This commit is contained in:
parent
8f9d675097
commit
3cf586a974
1 changed files with 13 additions and 8 deletions
|
@ -220,6 +220,7 @@ class ComponentMediaInput(Protocol):
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class ComponentMedia:
|
class ComponentMedia:
|
||||||
|
comp_cls: Type["Component"]
|
||||||
resolved: bool = False
|
resolved: bool = False
|
||||||
Media: Optional[Type[ComponentMediaInput]] = None
|
Media: Optional[Type[ComponentMediaInput]] = None
|
||||||
template: Optional[str] = None
|
template: Optional[str] = None
|
||||||
|
@ -229,6 +230,15 @@ class ComponentMedia:
|
||||||
css: Optional[str] = None
|
css: Optional[str] = None
|
||||||
css_file: Optional[str] = None
|
css_file: Optional[str] = None
|
||||||
|
|
||||||
|
def __post_init__(self) -> None:
|
||||||
|
for inlined_attr in ("template", "js", "css"):
|
||||||
|
file_attr = f"{inlined_attr}_file"
|
||||||
|
if getattr(self, inlined_attr) is not None and getattr(self, file_attr) is not None:
|
||||||
|
raise ImproperlyConfigured(
|
||||||
|
f"Received non-null value from both '{inlined_attr}' and '{file_attr}' in"
|
||||||
|
f" Component {self.comp_cls.__name__}. Only one of the two must be set."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# This metaclass is all about one thing - lazily resolving the media files.
|
# This metaclass is all about one thing - lazily resolving the media files.
|
||||||
#
|
#
|
||||||
|
@ -301,6 +311,7 @@ class ComponentMediaMeta(type):
|
||||||
def _setup_lazy_media_resolve(comp_cls: Type["Component"], attrs: Dict[str, Any]) -> None:
|
def _setup_lazy_media_resolve(comp_cls: Type["Component"], attrs: Dict[str, Any]) -> None:
|
||||||
# Collect all the original values of the lazy attributes, so we can access them from the getter
|
# Collect all the original values of the lazy attributes, so we can access them from the getter
|
||||||
comp_cls._component_media = ComponentMedia(
|
comp_cls._component_media = ComponentMedia(
|
||||||
|
comp_cls=comp_cls,
|
||||||
resolved=False,
|
resolved=False,
|
||||||
# NOTE: We take the values from `attrs` so we consider only the values that were set on THIS class,
|
# NOTE: We take the values from `attrs` so we consider only the values that were set on THIS class,
|
||||||
# and not the values that were inherited from the parent classes.
|
# and not the values that were inherited from the parent classes.
|
||||||
|
@ -350,7 +361,7 @@ def _get_comp_cls_attr(comp_cls: Type["Component"], attr: str) -> Any:
|
||||||
value = getattr(comp_media, attr, None)
|
value = getattr(comp_media, attr, None)
|
||||||
|
|
||||||
# For each of the pairs of inlined_content + file (e.g. `js` + `js_file`), if at least one of the two
|
# For each of the pairs of inlined_content + file (e.g. `js` + `js_file`), if at least one of the two
|
||||||
# is defined, we interpret it such that this (sub)class has overriden what was set by the parent class(es),
|
# is defined, we interpret it such that this (sub)class has overridden what was set by the parent class(es),
|
||||||
# and we won't search further up the MRO.
|
# and we won't search further up the MRO.
|
||||||
def check_pair_empty(inline_attr: str, file_attr: str) -> bool:
|
def check_pair_empty(inline_attr: str, file_attr: str) -> bool:
|
||||||
inline_attr_empty = getattr(comp_media, inline_attr, None) is None
|
inline_attr_empty = getattr(comp_media, inline_attr, None) is None
|
||||||
|
@ -614,7 +625,7 @@ def _normalize_media(media: Type[ComponentMediaInput]) -> None:
|
||||||
# JS is already a list, no action needed
|
# JS is already a list, no action needed
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Now that the Media class has a predicatable shape, get all the various JS/CSS paths
|
# Now that the Media class has a predictable shape, get all the various JS/CSS paths
|
||||||
# that user has defined, and normalize them too.
|
# that user has defined, and normalize them too.
|
||||||
#
|
#
|
||||||
# Because we can accept:
|
# Because we can accept:
|
||||||
|
@ -832,12 +843,6 @@ def _get_asset(
|
||||||
asset_content = getattr(comp_media, inlined_attr, None)
|
asset_content = getattr(comp_media, inlined_attr, None)
|
||||||
asset_file = getattr(comp_media, file_attr, None)
|
asset_file = getattr(comp_media, file_attr, None)
|
||||||
|
|
||||||
if asset_file is not None and asset_content is not None:
|
|
||||||
raise ImproperlyConfigured(
|
|
||||||
f"Received non-null value from both '{inlined_attr}' and '{file_attr}' in"
|
|
||||||
f" Component {comp_cls.__name__}. Only one of the two must be set."
|
|
||||||
)
|
|
||||||
|
|
||||||
if asset_file is not None:
|
if asset_file is not None:
|
||||||
# Check if the file is in one of the components' directories
|
# Check if the file is in one of the components' directories
|
||||||
full_path = resolve_file(asset_file, comp_dirs)
|
full_path = resolve_file(asset_file, comp_dirs)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue