aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/MarkupSafe/py3/tests
diff options
context:
space:
mode:
authorAlexander Smirnov <alex@ydb.tech>2024-10-28 20:34:11 +0000
committerAlexander Smirnov <alex@ydb.tech>2024-10-28 20:34:11 +0000
commitef9875b11a33dbd25e92bc6b4cf692c18c9ba0ce (patch)
tree1f2fd4e4d9e585da35937b42fbda5f854af04728 /contrib/python/MarkupSafe/py3/tests
parent37ae9cc90160b53eb0e22021c47b3996a01cd656 (diff)
parente3c8507a3d1cb090278f211232ddfde3bedc54d4 (diff)
downloadydb-ef9875b11a33dbd25e92bc6b4cf692c18c9ba0ce.tar.gz
Merge branch 'rightlib' into mergelibs-241028-2033
Diffstat (limited to 'contrib/python/MarkupSafe/py3/tests')
-rw-r--r--contrib/python/MarkupSafe/py3/tests/__init__.py0
-rw-r--r--contrib/python/MarkupSafe/py3/tests/conftest.py36
-rw-r--r--contrib/python/MarkupSafe/py3/tests/test_escape.py13
-rw-r--r--contrib/python/MarkupSafe/py3/tests/test_exception_custom_html.py9
-rw-r--r--contrib/python/MarkupSafe/py3/tests/test_leak.py25
-rw-r--r--contrib/python/MarkupSafe/py3/tests/test_markupsafe.py75
6 files changed, 86 insertions, 72 deletions
diff --git a/contrib/python/MarkupSafe/py3/tests/__init__.py b/contrib/python/MarkupSafe/py3/tests/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/contrib/python/MarkupSafe/py3/tests/__init__.py
diff --git a/contrib/python/MarkupSafe/py3/tests/conftest.py b/contrib/python/MarkupSafe/py3/tests/conftest.py
index d040ea8b1c..d941970b8e 100644
--- a/contrib/python/MarkupSafe/py3/tests/conftest.py
+++ b/contrib/python/MarkupSafe/py3/tests/conftest.py
@@ -1,5 +1,12 @@
+from __future__ import annotations
+
+import sys
+import typing as t
+from types import ModuleType
+
import pytest
+import markupsafe
from markupsafe import _native
try:
@@ -8,8 +15,17 @@ except ImportError:
_speedups = None # type: ignore
+def pytest_report_header() -> list[str]:
+ """Return a list of strings to be displayed in the header of the report."""
+ if sys.version_info >= (3, 13):
+ return [f"Free-threaded: {not sys._is_gil_enabled()}"]
+
+ return []
+
+
@pytest.fixture(
scope="session",
+ autouse=True,
params=(
_native,
pytest.param(
@@ -18,20 +34,6 @@ except ImportError:
),
),
)
-def _mod(request):
- return request.param
-
-
-@pytest.fixture(scope="session")
-def escape(_mod):
- return _mod.escape
-
-
-@pytest.fixture(scope="session")
-def escape_silent(_mod):
- return _mod.escape_silent
-
-
-@pytest.fixture(scope="session")
-def soft_str(_mod):
- return _mod.soft_str
+def _mod(request: pytest.FixtureRequest) -> None:
+ mod = t.cast(ModuleType, request.param)
+ markupsafe._escape_inner = mod._escape_inner # type: ignore[attr-defined]
diff --git a/contrib/python/MarkupSafe/py3/tests/test_escape.py b/contrib/python/MarkupSafe/py3/tests/test_escape.py
index bf53facedd..03e0b64892 100644
--- a/contrib/python/MarkupSafe/py3/tests/test_escape.py
+++ b/contrib/python/MarkupSafe/py3/tests/test_escape.py
@@ -1,5 +1,8 @@
+from __future__ import annotations
+
import pytest
+from markupsafe import escape
from markupsafe import Markup
@@ -18,12 +21,12 @@ from markupsafe import Markup
("こんにちは&><'\"", "こんにちは&amp;&gt;&lt;&#39;&#34;"),
# 4 byte
(
- "\U0001F363\U0001F362&><'\"\U0001F37A xyz",
- "\U0001F363\U0001F362&amp;&gt;&lt;&#39;&#34;\U0001F37A xyz",
+ "\U0001f363\U0001f362&><'\"\U0001f37a xyz",
+ "\U0001f363\U0001f362&amp;&gt;&lt;&#39;&#34;\U0001f37a xyz",
),
- ("&><'\"\U0001F37A xyz", "&amp;&gt;&lt;&#39;&#34;\U0001F37A xyz"),
- ("\U0001F363\U0001F362&><'\"", "\U0001F363\U0001F362&amp;&gt;&lt;&#39;&#34;"),
+ ("&><'\"\U0001f37a xyz", "&amp;&gt;&lt;&#39;&#34;\U0001f37a xyz"),
+ ("\U0001f363\U0001f362&><'\"", "\U0001f363\U0001f362&amp;&gt;&lt;&#39;&#34;"),
),
)
-def test_escape(escape, value, expect):
+def test_escape(value: str, expect: str) -> None:
assert escape(value) == Markup(expect)
diff --git a/contrib/python/MarkupSafe/py3/tests/test_exception_custom_html.py b/contrib/python/MarkupSafe/py3/tests/test_exception_custom_html.py
index ec2f10b1d1..582c749136 100644
--- a/contrib/python/MarkupSafe/py3/tests/test_exception_custom_html.py
+++ b/contrib/python/MarkupSafe/py3/tests/test_exception_custom_html.py
@@ -1,12 +1,16 @@
+from __future__ import annotations
+
import pytest
+from markupsafe import escape
+
class CustomHtmlThatRaises:
- def __html__(self):
+ def __html__(self) -> str:
raise ValueError(123)
-def test_exception_custom_html(escape):
+def test_exception_custom_html() -> None:
"""Checks whether exceptions in custom __html__ implementations are
propagated correctly.
@@ -14,5 +18,6 @@ def test_exception_custom_html(escape):
https://github.com/pallets/markupsafe/issues/108
"""
obj = CustomHtmlThatRaises()
+
with pytest.raises(ValueError):
escape(obj)
diff --git a/contrib/python/MarkupSafe/py3/tests/test_leak.py b/contrib/python/MarkupSafe/py3/tests/test_leak.py
index 55b10b98a4..b786e0725d 100644
--- a/contrib/python/MarkupSafe/py3/tests/test_leak.py
+++ b/contrib/python/MarkupSafe/py3/tests/test_leak.py
@@ -1,28 +1,25 @@
-import gc
-import platform
+from __future__ import annotations
-import pytest
+import gc
from markupsafe import escape
-@pytest.mark.skipif(
- escape.__module__ == "markupsafe._native",
- reason="only test memory leak with speedups",
-)
-def test_markup_leaks():
+def test_markup_leaks() -> None:
counts = set()
+ # Try to start with a "clean" count. Works for PyPy but not 3.13 JIT.
+ gc.collect()
- for _i in range(20):
- for _j in range(1000):
+ for _ in range(20):
+ for _ in range(1000):
escape("foo")
escape("<foo>")
escape("foo")
escape("<foo>")
- if platform.python_implementation() == "PyPy":
- gc.collect()
-
counts.add(len(gc.get_objects()))
- assert len(counts) == 1
+ # Some implementations, such as PyPy and Python 3.13 JIT, end up with 2
+ # counts rather than one. Presumably this is internals stabilizing. A leak
+ # would presumably have a different count every loop.
+ assert len(counts) < 3
diff --git a/contrib/python/MarkupSafe/py3/tests/test_markupsafe.py b/contrib/python/MarkupSafe/py3/tests/test_markupsafe.py
index 94bea38795..85d9ea16be 100644
--- a/contrib/python/MarkupSafe/py3/tests/test_markupsafe.py
+++ b/contrib/python/MarkupSafe/py3/tests/test_markupsafe.py
@@ -1,9 +1,16 @@
+from __future__ import annotations
+
+import typing as t
+
import pytest
+from markupsafe import escape
+from markupsafe import escape_silent
from markupsafe import Markup
+from markupsafe import soft_str
-def test_adding(escape):
+def test_adding() -> None:
unsafe = '<script type="application/x-some-script">alert("foo");</script>'
safe = Markup("<em>username</em>")
assert unsafe + safe == str(escape(unsafe)) + str(safe)
@@ -22,22 +29,22 @@ def test_adding(escape):
("%.2f", 3.14, "3.14"),
),
)
-def test_string_interpolation(template, data, expect):
+def test_string_interpolation(template: str, data: t.Any, expect: str) -> None:
assert Markup(template) % data == expect
-def test_type_behavior():
+def test_type_behavior() -> None:
assert type(Markup("foo") + "bar") is Markup
x = Markup("foo")
assert x.__html__() is x
-def test_html_interop():
+def test_html_interop() -> None:
class Foo:
- def __html__(self):
+ def __html__(self) -> str:
return "<em>awesome</em>"
- def __str__(self):
+ def __str__(self) -> str:
return "awesome"
assert Markup(Foo()) == "<em>awesome</em>"
@@ -46,18 +53,18 @@ def test_html_interop():
@pytest.mark.parametrize("args", ["foo", 42, ("foo", 42)])
-def test_missing_interpol(args):
+def test_missing_interpol(args: t.Any) -> None:
with pytest.raises(TypeError):
- Markup("<em></em>") % args
+ assert Markup("<em></em>") % args
-def test_tuple_interpol():
+def test_tuple_interpol() -> None:
result = Markup("<em>%s:%s</em>") % ("<foo>", "<bar>")
expect = Markup("<em>&lt;foo&gt;:&lt;bar&gt;</em>")
assert result == expect
-def test_dict_interpol():
+def test_dict_interpol() -> None:
result = Markup("<em>%(foo)s</em>") % {"foo": "<foo>"}
expect = Markup("<em>&lt;foo&gt;</em>")
assert result == expect
@@ -67,7 +74,7 @@ def test_dict_interpol():
assert result == expect
-def test_escaping(escape):
+def test_escaping() -> None:
assert escape("\"<>&'") == "&#34;&lt;&gt;&amp;&#39;"
assert (
Markup(
@@ -82,7 +89,7 @@ def test_escaping(escape):
)
-def test_unescape():
+def test_unescape() -> None:
assert Markup("&lt;test&gt;").unescape() == "<test>"
result = Markup("jack & tavi are cooler than mike &amp; russ").unescape()
@@ -97,7 +104,7 @@ def test_unescape():
assert twice == expect
-def test_format():
+def test_format() -> None:
result = Markup("<em>{awesome}</em>").format(awesome="<awesome>")
assert result == "<em>&lt;awesome&gt;</em>"
@@ -108,39 +115,39 @@ def test_format():
assert result == "<bar/>"
-def test_format_map():
+def test_format_map() -> None:
result = Markup("<em>{value}</em>").format_map({"value": "<value>"})
assert result == "<em>&lt;value&gt;</em>"
-def test_formatting_empty():
+def test_formatting_empty() -> None:
formatted = Markup("{}").format(0)
assert formatted == Markup("0")
-def test_custom_formatting():
+def test_custom_formatting() -> None:
class HasHTMLOnly:
- def __html__(self):
+ def __html__(self) -> Markup:
return Markup("<foo>")
class HasHTMLAndFormat:
- def __html__(self):
+ def __html__(self) -> Markup:
return Markup("<foo>")
- def __html_format__(self, spec):
+ def __html_format__(self, spec: str) -> Markup:
return Markup("<FORMAT>")
assert Markup("{0}").format(HasHTMLOnly()) == Markup("<foo>")
assert Markup("{0}").format(HasHTMLAndFormat()) == Markup("<FORMAT>")
-def test_complex_custom_formatting():
+def test_complex_custom_formatting() -> None:
class User:
- def __init__(self, id, username):
+ def __init__(self, id: int, username: str) -> None:
self.id = id
self.username = username
- def __html_format__(self, format_spec):
+ def __html_format__(self, format_spec: str) -> Markup:
if format_spec == "link":
return Markup('<a href="/user/{0}">{1}</a>').format(
self.id, self.__html__()
@@ -150,7 +157,7 @@ def test_complex_custom_formatting():
return self.__html__()
- def __html__(self):
+ def __html__(self) -> Markup:
return Markup("<span class=user>{0}</span>").format(self.username)
user = User(1, "foo")
@@ -159,43 +166,43 @@ def test_complex_custom_formatting():
assert result == expect
-def test_formatting_with_objects():
+def test_formatting_with_objects() -> None:
class Stringable:
- def __str__(self):
+ def __str__(self) -> str:
return "строка"
assert Markup("{s}").format(s=Stringable()) == Markup("строка")
-def test_escape_silent(escape, escape_silent):
+def test_escape_silent() -> None:
assert escape_silent(None) == Markup()
assert escape(None) == Markup(None)
assert escape_silent("<foo>") == Markup("&lt;foo&gt;")
-def test_splitting():
+def test_splitting() -> None:
expect = [Markup("a"), Markup("b")]
assert Markup("a b").split() == expect
assert Markup("a b").rsplit() == expect
assert Markup("a\nb").splitlines() == expect
-def test_mul():
+def test_mul() -> None:
assert Markup("a") * 3 == Markup("aaa")
-def test_escape_return_type(escape):
+def test_escape_return_type() -> None:
assert isinstance(escape("a"), Markup)
assert isinstance(escape(Markup("a")), Markup)
class Foo:
- def __html__(self):
+ def __html__(self) -> str:
return "<strong>Foo</strong>"
assert isinstance(escape(Foo()), Markup)
-def test_soft_str(soft_str):
- assert type(soft_str("")) is str
- assert type(soft_str(Markup())) is Markup
- assert type(soft_str(15)) is str
+def test_soft_str() -> None:
+ assert type(soft_str("")) is str # noqa: E721
+ assert type(soft_str(Markup())) is Markup # noqa: E721
+ assert type(soft_str(15)) is str # noqa: E721