#37088: path based MediaAsset equality
----------------------------------+------------------------------------
Reporter: Johannes Maron | Owner: (none)
Type: Bug | Status: new
Component: Forms | Version: 6.0
Severity: Normal | Resolution:
Keywords: Media MediaAsset | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 1 | UI/UX: 0
----------------------------------+------------------------------------
Changes (by Natalia Bidart):
* keywords: => Media MediaAsset
* stage: Unreviewed => Accepted
Old description:
> This is a spin-off from here:
> https://github.com/django/django/pull/21239#issuecomment-4396168812
>
> Currently MediaAsset.__eq__ compares only the path.
>
> This approach was deliberately chosen to benefit performance.
>
> However, in the case of `link`-elements and even `script` this approach
> can break.
> For a link, `rel=stylesheet` and `rel=refretch` can share the same path.
> Prefetching is also not too crazy a use case; someone will probably try
> to do it.
>
> A compromise could be to define an explicit list of attributes to
> compare, instead of doing a full dictionary comparison via `attributres`.
> Something like:
>
> {{{
> diff --git a/django/forms/widgets.py b/django/forms/widgets.py
> index 6972155402..70561d2c8c 100644
> --- a/django/forms/widgets.py
> +++ b/django/forms/widgets.py
> @@ -66,14 +66,20 @@ class MediaOrderConflictWarning(RuntimeWarning):
> class MediaAsset:
> element_template = "{path}"
>
> + # Only compare selected attributes to ensure performant comparison
> in Media.merge.
> + equality_attributes = ("path",)
> +
> def __init__(self, path, **attributes):
> self._path = path
> self.attributes = attributes
>
> def __eq__(self, other):
> - # Compare the path only, to ensure performant comparison in
> - # Media.merge.
> - return (self.__class__ is other.__class__ and self.path ==
> other.path) or (
> + return (
> + self.__class__ is other.__class__ and self.path ==
> other.path and all(
> + self.attributes.get(attr, None) ==
> other.attributes.get(attr, None)
> + for attr in self.equality_attributes
> + )
> + ) or (
> isinstance(other, str) and self._path == other
> )
>
> }}}
New description:
This is a spin-off from here:
https://github.com/django/django/pull/21239#issuecomment-4396168812
Currently `MediaAsset.__eq__` compares only the path.
This approach was deliberately chosen to benefit performance.
However, in the case of `link`-elements and even `script` this approach
can break.
For a link, `rel=stylesheet` and `rel=prefetch` can share the same path.
Prefetching is also not too crazy a use case; someone will probably try to
do it.
A compromise could be to define an explicit list of attributes to compare,
instead of doing a full dictionary comparison via `attributres`.
Something like:
{{{
diff --git a/django/forms/widgets.py b/django/forms/widgets.py
index 6972155402..70561d2c8c 100644
--- a/django/forms/widgets.py
+++ b/django/forms/widgets.py
@@ -66,14 +66,20 @@ class MediaOrderConflictWarning(RuntimeWarning):
class MediaAsset:
element_template = "{path}"
+ # Only compare selected attributes to ensure performant comparison in
Media.merge.
+ equality_attributes = ("path",)
+
def __init__(self, path, **attributes):
self._path = path
self.attributes = attributes
def __eq__(self, other):
- # Compare the path only, to ensure performant comparison in
- # Media.merge.
- return (self.__class__ is other.__class__ and self.path ==
other.path) or (
+ return (
+ self.__class__ is other.__class__ and self.path == other.path
and all(
+ self.attributes.get(attr, None) ==
other.attributes.get(attr, None)
+ for attr in self.equality_attributes
+ )
+ ) or (
isinstance(other, str) and self._path == other
)
}}}
--
Comment:
Thank you Johannes, this makes sense. Though implementation wise, I would
rather each class defines their own `__eq__` isolating the specific
semantic instead of defining a class attribute.
--
Ticket URL: <https://code.djangoproject.com/ticket/37088#comment:1>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/django-updates/0107019e026f7e44-0614351a-4f0c-424c-8c3b-084d790df1e1-000000%40eu-central-1.amazonses.com.