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