1import typing as t 2 3from . import Markup 4 5 6def escape(s: t.Any) -> Markup: 7 """Replace the characters ``&``, ``<``, ``>``, ``'``, and ``"`` in 8 the string with HTML-safe sequences. Use this if you need to display 9 text that might contain such characters in HTML. 10 11 If the object has an ``__html__`` method, it is called and the 12 return value is assumed to already be safe for HTML. 13 14 :param s: An object to be converted to a string and escaped. 15 :return: A :class:`Markup` string with the escaped text. 16 """ 17 if hasattr(s, "__html__"): 18 return Markup(s.__html__()) 19 20 return Markup( 21 str(s) 22 .replace("&", "&") 23 .replace(">", ">") 24 .replace("<", "<") 25 .replace("'", "'") 26 .replace('"', """) 27 ) 28 29 30def escape_silent(s: t.Optional[t.Any]) -> Markup: 31 """Like :func:`escape` but treats ``None`` as the empty string. 32 Useful with optional values, as otherwise you get the string 33 ``'None'`` when the value is ``None``. 34 35 >>> escape(None) 36 Markup('None') 37 >>> escape_silent(None) 38 Markup('') 39 """ 40 if s is None: 41 return Markup() 42 43 return escape(s) 44 45 46def soft_str(s: t.Any) -> str: 47 """Convert an object to a string if it isn't already. This preserves 48 a :class:`Markup` string rather than converting it back to a basic 49 string, so it will still be marked as safe and won't be escaped 50 again. 51 52 >>> value = escape("<User 1>") 53 >>> value 54 Markup('<User 1>') 55 >>> escape(str(value)) 56 Markup('&lt;User 1&gt;') 57 >>> escape(soft_str(value)) 58 Markup('<User 1>') 59 """ 60 if not isinstance(s, str): 61 return str(s) 62 63 return s 64 65 66def soft_unicode(s: t.Any) -> str: 67 import warnings 68 69 warnings.warn( 70 "'soft_unicode' has been renamed to 'soft_str'. The old name" 71 " will be removed in MarkupSafe 2.1.", 72 DeprecationWarning, 73 stacklevel=2, 74 ) 75 return soft_str(s) 76