app/django/utils/safestring.py
author Lennard de Rijk <ljvderijk@gmail.com>
Sat, 14 Feb 2009 21:18:12 +0000
changeset 1328 cd175dddc15c
parent 54 03e267d67478
permissions -rw-r--r--
Added bulk acceptance and progress bar in review org applications view. In the list of organization applications for reviewing, if you click the button "click here" the whole first text line will fade out and the progress bar will fade in while starting to contact the server for the list of orgs to accept and then make synchronous calls for acceptance, while updating the progress bar, the name of the organization currently accepting and the number of orgs already accepted against the total. Inside the script, what's inside the parenthesis is converted due to regexp (in this case (link_id)) and then read the json_object.applications[index].link_id. By doing this with an eval(), you can use other names as well and the script will be reading for example json_object.applications[index].attribute_name if you insert "(attribute_name)" inside the link returned by {{ bulk_accept_link }}. Notes by Lennard: -Put Done outside the for-loop so that it also shows when there are 0 pre-accepted organizations. -Made some minor style fixes Patch by: Mario Ferraro Reviewed by: Lennard de Rijk

"""
Functions for working with "safe strings": strings that can be displayed safely
without further escaping in HTML. Marking something as a "safe string" means
that the producer of the string has already turned characters that should not
be interpreted by the HTML engine (e.g. '<') into the appropriate entities.
"""
from django.utils.functional import curry, Promise

class EscapeData(object):
    pass

class EscapeString(str, EscapeData):
    """
    A string that should be HTML-escaped when output.
    """
    pass

class EscapeUnicode(unicode, EscapeData):
    """
    A unicode object that should be HTML-escaped when output.
    """
    pass

class SafeData(object):
    pass

class SafeString(str, SafeData):
    """
    A string subclass that has been specifically marked as "safe" (requires no
    further escaping) for HTML output purposes.
    """
    def __add__(self, rhs):
        """
        Concatenating a safe string with another safe string or safe unicode
        object is safe. Otherwise, the result is no longer safe.
        """
        t = super(SafeString, self).__add__(rhs)
        if isinstance(rhs, SafeUnicode):
            return SafeUnicode(t)
        elif isinstance(rhs, SafeString):
            return SafeString(t)
        return t
        
    def _proxy_method(self, *args, **kwargs):
        """
        Wrap a call to a normal unicode method up so that we return safe
        results. The method that is being wrapped is passed in the 'method'
        argument.
        """
        method = kwargs.pop('method')
        data = method(self, *args, **kwargs)
        if isinstance(data, str):
            return SafeString(data)
        else:
            return SafeUnicode(data)

    decode = curry(_proxy_method, method = str.decode)

class SafeUnicode(unicode, SafeData):
    """
    A unicode subclass that has been specifically marked as "safe" for HTML
    output purposes.
    """
    def __add__(self, rhs):
        """
        Concatenating a safe unicode object with another safe string or safe
        unicode object is safe. Otherwise, the result is no longer safe.
        """
        t = super(SafeUnicode, self).__add__(rhs)
        if isinstance(rhs, SafeData):
            return SafeUnicode(t)
        return t
    
    def _proxy_method(self, *args, **kwargs):
        """
        Wrap a call to a normal unicode method up so that we return safe
        results. The method that is being wrapped is passed in the 'method'
        argument.
        """
        method = kwargs.pop('method')
        data = method(self, *args, **kwargs)
        if isinstance(data, str):
            return SafeString(data)
        else:
            return SafeUnicode(data)

    encode = curry(_proxy_method, method = unicode.encode)

def mark_safe(s):
    """
    Explicitly mark a string as safe for (HTML) output purposes. The returned
    object can be used everywhere a string or unicode object is appropriate.

    Can be called multiple times on a single string.
    """
    if isinstance(s, SafeData):
        return s
    if isinstance(s, str) or (isinstance(s, Promise) and s._delegate_str):
        return SafeString(s)
    if isinstance(s, (unicode, Promise)):
        return SafeUnicode(s)
    return SafeString(str(s))

def mark_for_escaping(s):
    """
    Explicitly mark a string as requiring HTML escaping upon output. Has no
    effect on SafeData subclasses.

    Can be called multiple times on a single string (the resulting escaping is
    only applied once).
    """
    if isinstance(s, (SafeData, EscapeData)):
        return s
    if isinstance(s, str) or (isinstance(s, Promise) and s._delegate_str):
        return EscapeString(s)
    if isinstance(s, (unicode, Promise)):
        return EscapeUnicode(s)
    return EscapeString(str(s))