Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't specify anchor in Thumbnail template tag #494

Closed
tim-schilling opened this issue Jan 10, 2020 · 0 comments · Fixed by #562
Closed

Can't specify anchor in Thumbnail template tag #494

tim-schilling opened this issue Jan 10, 2020 · 0 comments · Fixed by #562

Comments

@tim-schilling
Copy link
Contributor

I've only tested this with Django 2.2 and python 3.7.5.

When attempting to use the thumbnail templatetag, specifying anchor='c' causes the template to render and cause an infinite recursion error. I've traced this down to the pickling logic to come up with the hash for the cache filename. The pickler includes the anchor value which is a SafeString instance which apparently has fits when pickled. It has to do with SafeString being a subclass of str, but I don't know enough to know why.

One fix would be to check if the kwarg to the templatetag includes the anchor, if it does, convert it to a regular string. However, that looks to be a really ugly hack.

The core problem of SafeString not being able to be pickled properly can be verified with:

from copy import copy
from hashlib import md5
from pickle import Pickler
from io import BytesIO

def pickle(obj):
    file = BytesIO()
    Pickler(file, 0).dump(obj)
    return md5(file.getvalue()).hexdigest()

# Copied from Django's source
class SafeData:
    def __html__(self):
        """
        Return the html representation of a string for interoperability.

        This allows other template engines to understand Django's SafeData.
        """
        return self

class SafeText(str, SafeData):
    """
    A str subclass that has been specifically marked as "safe" for HTML output
    purposes.
    """
    def __add__(self, rhs):
        """
        Concatenating a safe string with another safe bytestring or
        safe string is safe. Otherwise, the result is no longer safe.
        """
        t = super().__add__(rhs)
        if isinstance(rhs, SafeData):
            return SafeText(t)
        return t

    def __str__(self):
        return self
SafeString = SafeText

x = 'hello'
safe = SafeString(x)

pickle(x)
pickle(safe)

Changing the protocol on the pickler to 3 (the default for python3) does seem to resolve the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant