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("&", "&amp;")
23        .replace(">", "&gt;")
24        .replace("<", "&lt;")
25        .replace("'", "&#39;")
26        .replace('"', "&#34;")
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('&lt;User 1&gt;')
55    >>> escape(str(value))
56    Markup('&amp;lt;User 1&amp;gt;')
57    >>> escape(soft_str(value))
58    Markup('&lt;User 1&gt;')
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