test_markupsafe.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. # -*- coding: utf-8 -*-
  2. import pytest
  3. from markupsafe import escape
  4. from markupsafe import escape_silent
  5. from markupsafe import Markup
  6. from markupsafe._compat import PY2
  7. from markupsafe._compat import text_type
  8. def test_adding():
  9. unsafe = '<script type="application/x-some-script">alert("foo");</script>'
  10. safe = Markup("<em>username</em>")
  11. assert unsafe + safe == text_type(escape(unsafe)) + text_type(safe)
  12. @pytest.mark.parametrize(
  13. ("template", "data", "expect"),
  14. (
  15. ("<em>%s</em>", "<bad user>", "<em>&lt;bad user&gt;</em>"),
  16. (
  17. "<em>%(username)s</em>",
  18. {"username": "<bad user>"},
  19. "<em>&lt;bad user&gt;</em>",
  20. ),
  21. ("%i", 3.14, "3"),
  22. ("%.2f", 3.14, "3.14"),
  23. ),
  24. )
  25. def test_string_interpolation(template, data, expect):
  26. assert Markup(template) % data == expect
  27. def test_type_behavior():
  28. assert type(Markup("foo") + "bar") is Markup
  29. x = Markup("foo")
  30. assert x.__html__() is x
  31. def test_html_interop():
  32. class Foo(object):
  33. def __html__(self):
  34. return "<em>awesome</em>"
  35. def __unicode__(self):
  36. return "awesome"
  37. __str__ = __unicode__
  38. assert Markup(Foo()) == "<em>awesome</em>"
  39. result = Markup("<strong>%s</strong>") % Foo()
  40. assert result == "<strong><em>awesome</em></strong>"
  41. def test_tuple_interpol():
  42. result = Markup("<em>%s:%s</em>") % ("<foo>", "<bar>")
  43. expect = Markup(u"<em>&lt;foo&gt;:&lt;bar&gt;</em>")
  44. assert result == expect
  45. def test_dict_interpol():
  46. result = Markup("<em>%(foo)s</em>") % {"foo": "<foo>"}
  47. expect = Markup(u"<em>&lt;foo&gt;</em>")
  48. assert result == expect
  49. result = Markup("<em>%(foo)s:%(bar)s</em>") % {"foo": "<foo>", "bar": "<bar>"}
  50. expect = Markup(u"<em>&lt;foo&gt;:&lt;bar&gt;</em>")
  51. assert result == expect
  52. def test_escaping():
  53. assert escape("\"<>&'") == "&#34;&lt;&gt;&amp;&#39;"
  54. assert Markup("<em>Foo &amp; Bar</em>").striptags() == "Foo & Bar"
  55. def test_unescape():
  56. assert Markup("&lt;test&gt;").unescape() == "<test>"
  57. result = Markup("jack & tavi are cooler than mike &amp; russ").unescape()
  58. expect = "jack & tavi are cooler than mike & russ"
  59. assert result == expect
  60. original = "&foo&#x3b;"
  61. once = Markup(original).unescape()
  62. twice = Markup(once).unescape()
  63. expect = "&foo;"
  64. assert once == expect
  65. assert twice == expect
  66. def test_format():
  67. result = Markup("<em>{awesome}</em>").format(awesome="<awesome>")
  68. assert result == "<em>&lt;awesome&gt;</em>"
  69. result = Markup("{0[1][bar]}").format([0, {"bar": "<bar/>"}])
  70. assert result == "&lt;bar/&gt;"
  71. result = Markup("{0[1][bar]}").format([0, {"bar": Markup("<bar/>")}])
  72. assert result == "<bar/>"
  73. def test_formatting_empty():
  74. formatted = Markup("{}").format(0)
  75. assert formatted == Markup("0")
  76. def test_custom_formatting():
  77. class HasHTMLOnly(object):
  78. def __html__(self):
  79. return Markup("<foo>")
  80. class HasHTMLAndFormat(object):
  81. def __html__(self):
  82. return Markup("<foo>")
  83. def __html_format__(self, spec):
  84. return Markup("<FORMAT>")
  85. assert Markup("{0}").format(HasHTMLOnly()) == Markup("<foo>")
  86. assert Markup("{0}").format(HasHTMLAndFormat()) == Markup("<FORMAT>")
  87. def test_complex_custom_formatting():
  88. class User(object):
  89. def __init__(self, id, username):
  90. self.id = id
  91. self.username = username
  92. def __html_format__(self, format_spec):
  93. if format_spec == "link":
  94. return Markup('<a href="/user/{0}">{1}</a>').format(
  95. self.id, self.__html__()
  96. )
  97. elif format_spec:
  98. raise ValueError("Invalid format spec")
  99. return self.__html__()
  100. def __html__(self):
  101. return Markup("<span class=user>{0}</span>").format(self.username)
  102. user = User(1, "foo")
  103. result = Markup("<p>User: {0:link}").format(user)
  104. expect = Markup('<p>User: <a href="/user/1"><span class=user>foo</span></a>')
  105. assert result == expect
  106. def test_formatting_with_objects():
  107. class Stringable(object):
  108. def __unicode__(self):
  109. return u"строка"
  110. if PY2:
  111. def __str__(self):
  112. return "some other value"
  113. else:
  114. __str__ = __unicode__
  115. assert Markup("{s}").format(s=Stringable()) == Markup(u"строка")
  116. def test_all_set():
  117. import markupsafe as markup
  118. for item in markup.__all__:
  119. getattr(markup, item)
  120. def test_escape_silent():
  121. assert escape_silent(None) == Markup()
  122. assert escape(None) == Markup(None)
  123. assert escape_silent("<foo>") == Markup(u"&lt;foo&gt;")
  124. def test_splitting():
  125. expect = [Markup("a"), Markup("b")]
  126. assert Markup("a b").split() == expect
  127. assert Markup("a b").rsplit() == expect
  128. assert Markup("a\nb").splitlines() == expect
  129. def test_mul():
  130. assert Markup("a") * 3 == Markup("aaa")
  131. def test_escape_return_type():
  132. assert isinstance(escape("a"), Markup)
  133. assert isinstance(escape(Markup("a")), Markup)
  134. class Foo:
  135. def __html__(self):
  136. return "<strong>Foo</strong>"
  137. assert isinstance(escape(Foo()), Markup)