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 return the html representation of a string for interoperability this allows other template engines to understand django s safedata a str subclass that has been specifically marked as safe for html output purposes concatenating a safe string with another safe bytestring or safe string is safe otherwise the result is no longer safe explicitly mark a string as safe for html output purposes the returned object can be used everywhere a string is appropriate if used on a method as a decorator mark the returned data as safe can be called multiple times on a single string return the html representation of a string for interoperability this allows other template engines to understand django s safedata a str subclass that has been specifically marked as safe for html output purposes concatenating a safe string with another safe bytestring or safe string is safe otherwise the result is no longer safe for backwards compatibility since django 2 0 explicitly mark a string as safe for html output purposes the returned object can be used everywhere a string is appropriate if used on a method as a decorator mark the returned data as safe can be called multiple times on a single string
from functools import wraps

from django.utils.functional import keep_lazy


class SafeData:
    __slots__ = ()

    def __html__(self):
        
        return self


class SafeString(str, SafeData):
    

    __slots__ = ()

    def __add__(self, rhs):
        
        t = super().__add__(rhs)
        if isinstance(rhs, SafeData):
            return SafeString(t)
        return t

    def __str__(self):
        return self


SafeText = SafeString  


def _safety_decorator(safety_marker, func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        return safety_marker(func(*args, **kwargs))

    return wrapper


@keep_lazy(SafeString)
def mark_safe(s):
    
    if hasattr(s, "__html__"):
        return s
    if callable(s):
        return _safety_decorator(mark_safe, s)
    return SafeString(s)