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