diff options
author | shadchin <shadchin@yandex-team.ru> | 2022-02-10 16:44:39 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:39 +0300 |
commit | e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (patch) | |
tree | 64175d5cadab313b3e7039ebaa06c5bc3295e274 /contrib/python/MarkupSafe/py3 | |
parent | 2598ef1d0aee359b4b6d5fdd1758916d5907d04f (diff) | |
download | ydb-e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0.tar.gz |
Restoring authorship annotation for <shadchin@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/python/MarkupSafe/py3')
-rw-r--r-- | contrib/python/MarkupSafe/py3/.dist-info/METADATA | 66 | ||||
-rw-r--r-- | contrib/python/MarkupSafe/py3/LICENSE.rst | 56 | ||||
-rw-r--r-- | contrib/python/MarkupSafe/py3/README.rst | 138 | ||||
-rw-r--r-- | contrib/python/MarkupSafe/py3/markupsafe/__init__.py | 478 | ||||
-rw-r--r-- | contrib/python/MarkupSafe/py3/markupsafe/_native.py | 120 | ||||
-rw-r--r-- | contrib/python/MarkupSafe/py3/markupsafe/_speedups.c | 494 | ||||
-rw-r--r-- | contrib/python/MarkupSafe/py3/markupsafe/_speedups.pyi | 18 | ||||
-rw-r--r-- | contrib/python/MarkupSafe/py3/tests/conftest.py | 84 | ||||
-rw-r--r-- | contrib/python/MarkupSafe/py3/tests/test_escape.py | 58 | ||||
-rw-r--r-- | contrib/python/MarkupSafe/py3/tests/test_exception_custom_html.py | 36 | ||||
-rw-r--r-- | contrib/python/MarkupSafe/py3/tests/test_leak.py | 56 | ||||
-rw-r--r-- | contrib/python/MarkupSafe/py3/tests/test_markupsafe.py | 370 | ||||
-rw-r--r-- | contrib/python/MarkupSafe/py3/tests/ya.make | 38 | ||||
-rw-r--r-- | contrib/python/MarkupSafe/py3/ya.make | 70 |
14 files changed, 1041 insertions, 1041 deletions
diff --git a/contrib/python/MarkupSafe/py3/.dist-info/METADATA b/contrib/python/MarkupSafe/py3/.dist-info/METADATA index ca23fb3022..e87ebb99a9 100644 --- a/contrib/python/MarkupSafe/py3/.dist-info/METADATA +++ b/contrib/python/MarkupSafe/py3/.dist-info/METADATA @@ -1,20 +1,20 @@ Metadata-Version: 2.1 Name: MarkupSafe -Version: 2.0.1 +Version: 2.0.1 Summary: Safely add untrusted strings to HTML/XML markup. Home-page: https://palletsprojects.com/p/markupsafe/ Author: Armin Ronacher Author-email: armin.ronacher@active-4.com -Maintainer: Pallets +Maintainer: Pallets Maintainer-email: contact@palletsprojects.com License: BSD-3-Clause -Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Donate, https://palletsprojects.com/donate Project-URL: Documentation, https://markupsafe.palletsprojects.com/ -Project-URL: Changes, https://markupsafe.palletsprojects.com/changes/ -Project-URL: Source Code, https://github.com/pallets/markupsafe/ -Project-URL: Issue Tracker, https://github.com/pallets/markupsafe/issues/ -Project-URL: Twitter, https://twitter.com/PalletsTeam -Project-URL: Chat, https://discord.gg/pallets +Project-URL: Changes, https://markupsafe.palletsprojects.com/changes/ +Project-URL: Source Code, https://github.com/pallets/markupsafe/ +Project-URL: Issue Tracker, https://github.com/pallets/markupsafe/issues/ +Project-URL: Twitter, https://twitter.com/PalletsTeam +Project-URL: Chat, https://discord.gg/pallets Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment @@ -24,9 +24,9 @@ Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content Classifier: Topic :: Text Processing :: Markup :: HTML -Requires-Python: >=3.6 -Description-Content-Type: text/x-rst -License-File: LICENSE.rst +Requires-Python: >=3.6 +Description-Content-Type: text/x-rst +License-File: LICENSE.rst MarkupSafe ========== @@ -56,22 +56,22 @@ Examples .. code-block:: pycon >>> from markupsafe import Markup, escape - + >>> # escape replaces special characters and wraps in Markup - >>> escape("<script>alert(document.cookie);</script>") - Markup('<script>alert(document.cookie);</script>') - + >>> escape("<script>alert(document.cookie);</script>") + Markup('<script>alert(document.cookie);</script>') + >>> # wrap in Markup to mark text "safe" and prevent escaping - >>> Markup("<strong>Hello</strong>") + >>> Markup("<strong>Hello</strong>") Markup('<strong>hello</strong>') - - >>> escape(Markup("<strong>Hello</strong>")) + + >>> escape(Markup("<strong>Hello</strong>")) Markup('<strong>hello</strong>') - - >>> # Markup is a str subclass + + >>> # Markup is a str subclass >>> # methods and operators escape their arguments - >>> template = Markup("Hello <em>{name}</em>") - >>> template.format(name='"World"') + >>> template = Markup("Hello <em>{name}</em>") + >>> template.format(name='"World"') Markup('Hello <em>"World"</em>') @@ -79,9 +79,9 @@ Donate ------ The Pallets organization develops and supports MarkupSafe and other -popular packages. In order to grow the community of contributors and -users, and allow the maintainers to devote more time to the projects, -`please donate today`_. +popular packages. In order to grow the community of contributors and +users, and allow the maintainers to devote more time to the projects, +`please donate today`_. .. _please donate today: https://palletsprojects.com/donate @@ -89,13 +89,13 @@ users, and allow the maintainers to devote more time to the projects, Links ----- -- Documentation: https://markupsafe.palletsprojects.com/ -- Changes: https://markupsafe.palletsprojects.com/changes/ -- PyPI Releases: https://pypi.org/project/MarkupSafe/ -- Source Code: https://github.com/pallets/markupsafe/ -- Issue Tracker: https://github.com/pallets/markupsafe/issues/ -- Website: https://palletsprojects.com/p/markupsafe/ -- Twitter: https://twitter.com/PalletsTeam -- Chat: https://discord.gg/pallets +- Documentation: https://markupsafe.palletsprojects.com/ +- Changes: https://markupsafe.palletsprojects.com/changes/ +- PyPI Releases: https://pypi.org/project/MarkupSafe/ +- Source Code: https://github.com/pallets/markupsafe/ +- Issue Tracker: https://github.com/pallets/markupsafe/issues/ +- Website: https://palletsprojects.com/p/markupsafe/ +- Twitter: https://twitter.com/PalletsTeam +- Chat: https://discord.gg/pallets diff --git a/contrib/python/MarkupSafe/py3/LICENSE.rst b/contrib/python/MarkupSafe/py3/LICENSE.rst index 704e0a9c5a..9d227a0cc4 100644 --- a/contrib/python/MarkupSafe/py3/LICENSE.rst +++ b/contrib/python/MarkupSafe/py3/LICENSE.rst @@ -1,28 +1,28 @@ -Copyright 2010 Pallets - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +Copyright 2010 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/contrib/python/MarkupSafe/py3/README.rst b/contrib/python/MarkupSafe/py3/README.rst index d781b9d2d4..273e1db40f 100644 --- a/contrib/python/MarkupSafe/py3/README.rst +++ b/contrib/python/MarkupSafe/py3/README.rst @@ -1,69 +1,69 @@ -MarkupSafe -========== - -MarkupSafe implements a text object that escapes characters so it is -safe to use in HTML and XML. Characters that have special meanings are -replaced so that they display as the actual characters. This mitigates -injection attacks, meaning untrusted user input can safely be displayed -on a page. - - -Installing ----------- - -Install and update using `pip`_: - -.. code-block:: text - - pip install -U MarkupSafe - -.. _pip: https://pip.pypa.io/en/stable/quickstart/ - - -Examples --------- - -.. code-block:: pycon - - >>> from markupsafe import Markup, escape - - >>> # escape replaces special characters and wraps in Markup - >>> escape("<script>alert(document.cookie);</script>") - Markup('<script>alert(document.cookie);</script>') - - >>> # wrap in Markup to mark text "safe" and prevent escaping - >>> Markup("<strong>Hello</strong>") - Markup('<strong>hello</strong>') - - >>> escape(Markup("<strong>Hello</strong>")) - Markup('<strong>hello</strong>') - - >>> # Markup is a str subclass - >>> # methods and operators escape their arguments - >>> template = Markup("Hello <em>{name}</em>") - >>> template.format(name='"World"') - Markup('Hello <em>"World"</em>') - - -Donate ------- - -The Pallets organization develops and supports MarkupSafe and other -popular packages. In order to grow the community of contributors and -users, and allow the maintainers to devote more time to the projects, -`please donate today`_. - -.. _please donate today: https://palletsprojects.com/donate - - -Links ------ - -- Documentation: https://markupsafe.palletsprojects.com/ -- Changes: https://markupsafe.palletsprojects.com/changes/ -- PyPI Releases: https://pypi.org/project/MarkupSafe/ -- Source Code: https://github.com/pallets/markupsafe/ -- Issue Tracker: https://github.com/pallets/markupsafe/issues/ -- Website: https://palletsprojects.com/p/markupsafe/ -- Twitter: https://twitter.com/PalletsTeam -- Chat: https://discord.gg/pallets +MarkupSafe +========== + +MarkupSafe implements a text object that escapes characters so it is +safe to use in HTML and XML. Characters that have special meanings are +replaced so that they display as the actual characters. This mitigates +injection attacks, meaning untrusted user input can safely be displayed +on a page. + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + pip install -U MarkupSafe + +.. _pip: https://pip.pypa.io/en/stable/quickstart/ + + +Examples +-------- + +.. code-block:: pycon + + >>> from markupsafe import Markup, escape + + >>> # escape replaces special characters and wraps in Markup + >>> escape("<script>alert(document.cookie);</script>") + Markup('<script>alert(document.cookie);</script>') + + >>> # wrap in Markup to mark text "safe" and prevent escaping + >>> Markup("<strong>Hello</strong>") + Markup('<strong>hello</strong>') + + >>> escape(Markup("<strong>Hello</strong>")) + Markup('<strong>hello</strong>') + + >>> # Markup is a str subclass + >>> # methods and operators escape their arguments + >>> template = Markup("Hello <em>{name}</em>") + >>> template.format(name='"World"') + Markup('Hello <em>"World"</em>') + + +Donate +------ + +The Pallets organization develops and supports MarkupSafe and other +popular packages. In order to grow the community of contributors and +users, and allow the maintainers to devote more time to the projects, +`please donate today`_. + +.. _please donate today: https://palletsprojects.com/donate + + +Links +----- + +- Documentation: https://markupsafe.palletsprojects.com/ +- Changes: https://markupsafe.palletsprojects.com/changes/ +- PyPI Releases: https://pypi.org/project/MarkupSafe/ +- Source Code: https://github.com/pallets/markupsafe/ +- Issue Tracker: https://github.com/pallets/markupsafe/issues/ +- Website: https://palletsprojects.com/p/markupsafe/ +- Twitter: https://twitter.com/PalletsTeam +- Chat: https://discord.gg/pallets diff --git a/contrib/python/MarkupSafe/py3/markupsafe/__init__.py b/contrib/python/MarkupSafe/py3/markupsafe/__init__.py index d1bf04fc41..d331ac3622 100644 --- a/contrib/python/MarkupSafe/py3/markupsafe/__init__.py +++ b/contrib/python/MarkupSafe/py3/markupsafe/__init__.py @@ -1,288 +1,288 @@ -import functools +import functools import re import string -import typing as t - -if t.TYPE_CHECKING: - import typing_extensions as te - - class HasHTML(te.Protocol): - def __html__(self) -> str: - pass - - -__version__ = "2.0.1" - -_striptags_re = re.compile(r"(<!--.*?-->|<[^>]*>)") - - -def _simple_escaping_wrapper(name: str) -> t.Callable[..., "Markup"]: - orig = getattr(str, name) - - @functools.wraps(orig) - def wrapped(self: "Markup", *args: t.Any, **kwargs: t.Any) -> "Markup": - args = _escape_argspec(list(args), enumerate(args), self.escape) # type: ignore - _escape_argspec(kwargs, kwargs.items(), self.escape) - return self.__class__(orig(self, *args, **kwargs)) - - return wrapped - - -class Markup(str): - """A string that is ready to be safely inserted into an HTML or XML - document, either because it was escaped or because it was marked - safe. - - Passing an object to the constructor converts it to text and wraps - it to mark it safe without escaping. To escape the text, use the - :meth:`escape` class method instead. - - >>> Markup("Hello, <em>World</em>!") - Markup('Hello, <em>World</em>!') - >>> Markup(42) - Markup('42') - >>> Markup.escape("Hello, <em>World</em>!") - Markup('Hello <em>World</em>!') - - This implements the ``__html__()`` interface that some frameworks - use. Passing an object that implements ``__html__()`` will wrap the - output of that method, marking it safe. - - >>> class Foo: - ... def __html__(self): - ... return '<a href="/foo">foo</a>' +import typing as t + +if t.TYPE_CHECKING: + import typing_extensions as te + + class HasHTML(te.Protocol): + def __html__(self) -> str: + pass + + +__version__ = "2.0.1" + +_striptags_re = re.compile(r"(<!--.*?-->|<[^>]*>)") + + +def _simple_escaping_wrapper(name: str) -> t.Callable[..., "Markup"]: + orig = getattr(str, name) + + @functools.wraps(orig) + def wrapped(self: "Markup", *args: t.Any, **kwargs: t.Any) -> "Markup": + args = _escape_argspec(list(args), enumerate(args), self.escape) # type: ignore + _escape_argspec(kwargs, kwargs.items(), self.escape) + return self.__class__(orig(self, *args, **kwargs)) + + return wrapped + + +class Markup(str): + """A string that is ready to be safely inserted into an HTML or XML + document, either because it was escaped or because it was marked + safe. + + Passing an object to the constructor converts it to text and wraps + it to mark it safe without escaping. To escape the text, use the + :meth:`escape` class method instead. + + >>> Markup("Hello, <em>World</em>!") + Markup('Hello, <em>World</em>!') + >>> Markup(42) + Markup('42') + >>> Markup.escape("Hello, <em>World</em>!") + Markup('Hello <em>World</em>!') + + This implements the ``__html__()`` interface that some frameworks + use. Passing an object that implements ``__html__()`` will wrap the + output of that method, marking it safe. + + >>> class Foo: + ... def __html__(self): + ... return '<a href="/foo">foo</a>' ... >>> Markup(Foo()) - Markup('<a href="/foo">foo</a>') + Markup('<a href="/foo">foo</a>') - This is a subclass of :class:`str`. It has the same methods, but - escapes their arguments and returns a ``Markup`` instance. + This is a subclass of :class:`str`. It has the same methods, but + escapes their arguments and returns a ``Markup`` instance. - >>> Markup("<em>%s</em>") % ("foo & bar",) - Markup('<em>foo & bar</em>') - >>> Markup("<em>Hello</em> ") + "<foo>" - Markup('<em>Hello</em> <foo>') - """ + >>> Markup("<em>%s</em>") % ("foo & bar",) + Markup('<em>foo & bar</em>') + >>> Markup("<em>Hello</em> ") + "<foo>" + Markup('<em>Hello</em> <foo>') + """ __slots__ = () - def __new__( - cls, base: t.Any = "", encoding: t.Optional[str] = None, errors: str = "strict" - ) -> "Markup": - if hasattr(base, "__html__"): + def __new__( + cls, base: t.Any = "", encoding: t.Optional[str] = None, errors: str = "strict" + ) -> "Markup": + if hasattr(base, "__html__"): base = base.__html__() - + if encoding is None: - return super().__new__(cls, base) + return super().__new__(cls, base) - return super().__new__(cls, base, encoding, errors) - - def __html__(self) -> "Markup": + return super().__new__(cls, base, encoding, errors) + + def __html__(self) -> "Markup": return self - def __add__(self, other: t.Union[str, "HasHTML"]) -> "Markup": - if isinstance(other, str) or hasattr(other, "__html__"): - return self.__class__(super().__add__(self.escape(other))) - + def __add__(self, other: t.Union[str, "HasHTML"]) -> "Markup": + if isinstance(other, str) or hasattr(other, "__html__"): + return self.__class__(super().__add__(self.escape(other))) + return NotImplemented - def __radd__(self, other: t.Union[str, "HasHTML"]) -> "Markup": - if isinstance(other, str) or hasattr(other, "__html__"): + def __radd__(self, other: t.Union[str, "HasHTML"]) -> "Markup": + if isinstance(other, str) or hasattr(other, "__html__"): return self.escape(other).__add__(self) return NotImplemented - - def __mul__(self, num: int) -> "Markup": - if isinstance(num, int): - return self.__class__(super().__mul__(num)) - - return NotImplemented # type: ignore - + + def __mul__(self, num: int) -> "Markup": + if isinstance(num, int): + return self.__class__(super().__mul__(num)) + + return NotImplemented # type: ignore + __rmul__ = __mul__ - def __mod__(self, arg: t.Any) -> "Markup": + def __mod__(self, arg: t.Any) -> "Markup": if isinstance(arg, tuple): arg = tuple(_MarkupEscapeHelper(x, self.escape) for x in arg) else: arg = _MarkupEscapeHelper(arg, self.escape) - return self.__class__(super().__mod__(arg)) - - def __repr__(self) -> str: - return f"{self.__class__.__name__}({super().__repr__()})" - - def join(self, seq: t.Iterable[t.Union[str, "HasHTML"]]) -> "Markup": - return self.__class__(super().join(map(self.escape, seq))) - - join.__doc__ = str.join.__doc__ - - def split( # type: ignore - self, sep: t.Optional[str] = None, maxsplit: int = -1 - ) -> t.List["Markup"]: - return [self.__class__(v) for v in super().split(sep, maxsplit)] - - split.__doc__ = str.split.__doc__ - - def rsplit( # type: ignore - self, sep: t.Optional[str] = None, maxsplit: int = -1 - ) -> t.List["Markup"]: - return [self.__class__(v) for v in super().rsplit(sep, maxsplit)] - - rsplit.__doc__ = str.rsplit.__doc__ - - def splitlines(self, keepends: bool = False) -> t.List["Markup"]: # type: ignore - return [self.__class__(v) for v in super().splitlines(keepends)] - - splitlines.__doc__ = str.splitlines.__doc__ - - def unescape(self) -> str: - """Convert escaped markup back into a text string. This replaces - HTML entities with the characters they represent. - - >>> Markup("Main » <em>About</em>").unescape() - 'Main » <em>About</em>' + return self.__class__(super().__mod__(arg)) + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({super().__repr__()})" + + def join(self, seq: t.Iterable[t.Union[str, "HasHTML"]]) -> "Markup": + return self.__class__(super().join(map(self.escape, seq))) + + join.__doc__ = str.join.__doc__ + + def split( # type: ignore + self, sep: t.Optional[str] = None, maxsplit: int = -1 + ) -> t.List["Markup"]: + return [self.__class__(v) for v in super().split(sep, maxsplit)] + + split.__doc__ = str.split.__doc__ + + def rsplit( # type: ignore + self, sep: t.Optional[str] = None, maxsplit: int = -1 + ) -> t.List["Markup"]: + return [self.__class__(v) for v in super().rsplit(sep, maxsplit)] + + rsplit.__doc__ = str.rsplit.__doc__ + + def splitlines(self, keepends: bool = False) -> t.List["Markup"]: # type: ignore + return [self.__class__(v) for v in super().splitlines(keepends)] + + splitlines.__doc__ = str.splitlines.__doc__ + + def unescape(self) -> str: + """Convert escaped markup back into a text string. This replaces + HTML entities with the characters they represent. + + >>> Markup("Main » <em>About</em>").unescape() + 'Main » <em>About</em>' """ - from html import unescape - - return unescape(str(self)) - - def striptags(self) -> str: - """:meth:`unescape` the markup, remove tags, and normalize - whitespace to single spaces. - - >>> Markup("Main »\t<em>About</em>").striptags() - 'Main » About' + from html import unescape + + return unescape(str(self)) + + def striptags(self) -> str: + """:meth:`unescape` the markup, remove tags, and normalize + whitespace to single spaces. + + >>> Markup("Main »\t<em>About</em>").striptags() + 'Main » About' """ - stripped = " ".join(_striptags_re.sub("", self).split()) + stripped = " ".join(_striptags_re.sub("", self).split()) return Markup(stripped).unescape() @classmethod - def escape(cls, s: t.Any) -> "Markup": - """Escape a string. Calls :func:`escape` and ensures that for - subclasses the correct type is returned. + def escape(cls, s: t.Any) -> "Markup": + """Escape a string. Calls :func:`escape` and ensures that for + subclasses the correct type is returned. """ rv = escape(s) - + if rv.__class__ is not cls: return cls(rv) - + return rv - for method in ( - "__getitem__", - "capitalize", - "title", - "lower", - "upper", - "replace", - "ljust", - "rjust", - "lstrip", - "rstrip", - "center", - "strip", - "translate", - "expandtabs", - "swapcase", - "zfill", - ): - locals()[method] = _simple_escaping_wrapper(method) - - del method - - def partition(self, sep: str) -> t.Tuple["Markup", "Markup", "Markup"]: - l, s, r = super().partition(self.escape(sep)) - cls = self.__class__ - return cls(l), cls(s), cls(r) - - def rpartition(self, sep: str) -> t.Tuple["Markup", "Markup", "Markup"]: - l, s, r = super().rpartition(self.escape(sep)) - cls = self.__class__ - return cls(l), cls(s), cls(r) - - def format(self, *args: t.Any, **kwargs: t.Any) -> "Markup": - formatter = EscapeFormatter(self.escape) - return self.__class__(formatter.vformat(self, args, kwargs)) - - def __html_format__(self, format_spec: str) -> "Markup": - if format_spec: - raise ValueError("Unsupported format specification for Markup.") - - return self - - -class EscapeFormatter(string.Formatter): - __slots__ = ("escape",) - - def __init__(self, escape: t.Callable[[t.Any], Markup]) -> None: - self.escape = escape - super().__init__() - - def format_field(self, value: t.Any, format_spec: str) -> str: - if hasattr(value, "__html_format__"): - rv = value.__html_format__(format_spec) - elif hasattr(value, "__html__"): - if format_spec: - raise ValueError( - f"Format specifier {format_spec} given, but {type(value)} does not" - " define __html_format__. A class that defines __html__ must define" - " __html_format__ to work with format specifiers." - ) - rv = value.__html__() - else: - # We need to make sure the format spec is str here as - # otherwise the wrong callback methods are invoked. - rv = string.Formatter.format_field(self, value, str(format_spec)) - return str(self.escape(rv)) - - -_ListOrDict = t.TypeVar("_ListOrDict", list, dict) - - -def _escape_argspec( - obj: _ListOrDict, iterable: t.Iterable[t.Any], escape: t.Callable[[t.Any], Markup] -) -> _ListOrDict: + for method in ( + "__getitem__", + "capitalize", + "title", + "lower", + "upper", + "replace", + "ljust", + "rjust", + "lstrip", + "rstrip", + "center", + "strip", + "translate", + "expandtabs", + "swapcase", + "zfill", + ): + locals()[method] = _simple_escaping_wrapper(method) + + del method + + def partition(self, sep: str) -> t.Tuple["Markup", "Markup", "Markup"]: + l, s, r = super().partition(self.escape(sep)) + cls = self.__class__ + return cls(l), cls(s), cls(r) + + def rpartition(self, sep: str) -> t.Tuple["Markup", "Markup", "Markup"]: + l, s, r = super().rpartition(self.escape(sep)) + cls = self.__class__ + return cls(l), cls(s), cls(r) + + def format(self, *args: t.Any, **kwargs: t.Any) -> "Markup": + formatter = EscapeFormatter(self.escape) + return self.__class__(formatter.vformat(self, args, kwargs)) + + def __html_format__(self, format_spec: str) -> "Markup": + if format_spec: + raise ValueError("Unsupported format specification for Markup.") + + return self + + +class EscapeFormatter(string.Formatter): + __slots__ = ("escape",) + + def __init__(self, escape: t.Callable[[t.Any], Markup]) -> None: + self.escape = escape + super().__init__() + + def format_field(self, value: t.Any, format_spec: str) -> str: + if hasattr(value, "__html_format__"): + rv = value.__html_format__(format_spec) + elif hasattr(value, "__html__"): + if format_spec: + raise ValueError( + f"Format specifier {format_spec} given, but {type(value)} does not" + " define __html_format__. A class that defines __html__ must define" + " __html_format__ to work with format specifiers." + ) + rv = value.__html__() + else: + # We need to make sure the format spec is str here as + # otherwise the wrong callback methods are invoked. + rv = string.Formatter.format_field(self, value, str(format_spec)) + return str(self.escape(rv)) + + +_ListOrDict = t.TypeVar("_ListOrDict", list, dict) + + +def _escape_argspec( + obj: _ListOrDict, iterable: t.Iterable[t.Any], escape: t.Callable[[t.Any], Markup] +) -> _ListOrDict: """Helper for various string-wrapped functions.""" for key, value in iterable: - if isinstance(value, str) or hasattr(value, "__html__"): + if isinstance(value, str) or hasattr(value, "__html__"): obj[key] = escape(value) - + return obj -class _MarkupEscapeHelper: - """Helper for :meth:`Markup.__mod__`.""" +class _MarkupEscapeHelper: + """Helper for :meth:`Markup.__mod__`.""" - __slots__ = ("obj", "escape") - - def __init__(self, obj: t.Any, escape: t.Callable[[t.Any], Markup]) -> None: + __slots__ = ("obj", "escape") + + def __init__(self, obj: t.Any, escape: t.Callable[[t.Any], Markup]) -> None: self.obj = obj self.escape = escape - def __getitem__(self, item: t.Any) -> "_MarkupEscapeHelper": - return _MarkupEscapeHelper(self.obj[item], self.escape) - - def __str__(self) -> str: - return str(self.escape(self.obj)) - - def __repr__(self) -> str: - return str(self.escape(repr(self.obj))) - - def __int__(self) -> int: - return int(self.obj) - - def __float__(self) -> float: - return float(self.obj) - - -# circular import + def __getitem__(self, item: t.Any) -> "_MarkupEscapeHelper": + return _MarkupEscapeHelper(self.obj[item], self.escape) + + def __str__(self) -> str: + return str(self.escape(self.obj)) + + def __repr__(self) -> str: + return str(self.escape(repr(self.obj))) + + def __int__(self) -> int: + return int(self.obj) + + def __float__(self) -> float: + return float(self.obj) + + +# circular import try: - from ._speedups import escape as escape - from ._speedups import escape_silent as escape_silent - from ._speedups import soft_str as soft_str - from ._speedups import soft_unicode + from ._speedups import escape as escape + from ._speedups import escape_silent as escape_silent + from ._speedups import soft_str as soft_str + from ._speedups import soft_unicode except ImportError: - from ._native import escape as escape - from ._native import escape_silent as escape_silent # noqa: F401 - from ._native import soft_str as soft_str # noqa: F401 - from ._native import soft_unicode # noqa: F401 + from ._native import escape as escape + from ._native import escape_silent as escape_silent # noqa: F401 + from ._native import soft_str as soft_str # noqa: F401 + from ._native import soft_unicode # noqa: F401 diff --git a/contrib/python/MarkupSafe/py3/markupsafe/_native.py b/contrib/python/MarkupSafe/py3/markupsafe/_native.py index 82504bb292..6f7eb7a8cb 100644 --- a/contrib/python/MarkupSafe/py3/markupsafe/_native.py +++ b/contrib/python/MarkupSafe/py3/markupsafe/_native.py @@ -1,75 +1,75 @@ -import typing as t +import typing as t -from . import Markup +from . import Markup -def escape(s: t.Any) -> Markup: - """Replace the characters ``&``, ``<``, ``>``, ``'``, and ``"`` in - the string with HTML-safe sequences. Use this if you need to display - text that might contain such characters in HTML. - - If the object has an ``__html__`` method, it is called and the - return value is assumed to already be safe for HTML. - - :param s: An object to be converted to a string and escaped. - :return: A :class:`Markup` string with the escaped text. +def escape(s: t.Any) -> Markup: + """Replace the characters ``&``, ``<``, ``>``, ``'``, and ``"`` in + the string with HTML-safe sequences. Use this if you need to display + text that might contain such characters in HTML. + + If the object has an ``__html__`` method, it is called and the + return value is assumed to already be safe for HTML. + + :param s: An object to be converted to a string and escaped. + :return: A :class:`Markup` string with the escaped text. """ - if hasattr(s, "__html__"): - return Markup(s.__html__()) - - return Markup( - str(s) - .replace("&", "&") - .replace(">", ">") - .replace("<", "<") - .replace("'", "'") - .replace('"', """) + if hasattr(s, "__html__"): + return Markup(s.__html__()) + + return Markup( + str(s) + .replace("&", "&") + .replace(">", ">") + .replace("<", "<") + .replace("'", "'") + .replace('"', """) ) -def escape_silent(s: t.Optional[t.Any]) -> Markup: - """Like :func:`escape` but treats ``None`` as the empty string. - Useful with optional values, as otherwise you get the string - ``'None'`` when the value is ``None``. - - >>> escape(None) - Markup('None') - >>> escape_silent(None) - Markup('') +def escape_silent(s: t.Optional[t.Any]) -> Markup: + """Like :func:`escape` but treats ``None`` as the empty string. + Useful with optional values, as otherwise you get the string + ``'None'`` when the value is ``None``. + + >>> escape(None) + Markup('None') + >>> escape_silent(None) + Markup('') """ if s is None: return Markup() - + return escape(s) -def soft_str(s: t.Any) -> str: - """Convert an object to a string if it isn't already. This preserves - a :class:`Markup` string rather than converting it back to a basic - string, so it will still be marked as safe and won't be escaped - again. - - >>> value = escape("<User 1>") - >>> value - Markup('<User 1>') - >>> escape(str(value)) - Markup('&lt;User 1&gt;') - >>> escape(soft_str(value)) - Markup('<User 1>') +def soft_str(s: t.Any) -> str: + """Convert an object to a string if it isn't already. This preserves + a :class:`Markup` string rather than converting it back to a basic + string, so it will still be marked as safe and won't be escaped + again. + + >>> value = escape("<User 1>") + >>> value + Markup('<User 1>') + >>> escape(str(value)) + Markup('&lt;User 1&gt;') + >>> escape(soft_str(value)) + Markup('<User 1>') """ - if not isinstance(s, str): - return str(s) - + if not isinstance(s, str): + return str(s) + return s - - -def soft_unicode(s: t.Any) -> str: - import warnings - - warnings.warn( - "'soft_unicode' has been renamed to 'soft_str'. The old name" - " will be removed in MarkupSafe 2.1.", - DeprecationWarning, - stacklevel=2, - ) - return soft_str(s) + + +def soft_unicode(s: t.Any) -> str: + import warnings + + warnings.warn( + "'soft_unicode' has been renamed to 'soft_str'. The old name" + " will be removed in MarkupSafe 2.1.", + DeprecationWarning, + stacklevel=2, + ) + return soft_str(s) diff --git a/contrib/python/MarkupSafe/py3/markupsafe/_speedups.c b/contrib/python/MarkupSafe/py3/markupsafe/_speedups.c index a01cfada2f..44967b1fdc 100644 --- a/contrib/python/MarkupSafe/py3/markupsafe/_speedups.c +++ b/contrib/python/MarkupSafe/py3/markupsafe/_speedups.c @@ -6,7 +6,7 @@ static int init_constants(void) { PyObject *module; - + /* import markup type so that we can mark the return value */ module = PyImport_ImportModule("markupsafe"); if (!module) @@ -17,202 +17,202 @@ init_constants(void) return 1; } -#define GET_DELTA(inp, inp_end, delta) \ - while (inp < inp_end) { \ - switch (*inp++) { \ - case '"': \ - case '\'': \ - case '&': \ - delta += 4; \ - break; \ - case '<': \ - case '>': \ - delta += 3; \ - break; \ - } \ - } - -#define DO_ESCAPE(inp, inp_end, outp) \ - { \ - Py_ssize_t ncopy = 0; \ - while (inp < inp_end) { \ - switch (*inp) { \ - case '"': \ - memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \ - outp += ncopy; ncopy = 0; \ - *outp++ = '&'; \ - *outp++ = '#'; \ - *outp++ = '3'; \ - *outp++ = '4'; \ - *outp++ = ';'; \ - break; \ - case '\'': \ - memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \ - outp += ncopy; ncopy = 0; \ - *outp++ = '&'; \ - *outp++ = '#'; \ - *outp++ = '3'; \ - *outp++ = '9'; \ - *outp++ = ';'; \ - break; \ - case '&': \ - memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \ - outp += ncopy; ncopy = 0; \ - *outp++ = '&'; \ - *outp++ = 'a'; \ - *outp++ = 'm'; \ - *outp++ = 'p'; \ - *outp++ = ';'; \ - break; \ - case '<': \ - memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \ - outp += ncopy; ncopy = 0; \ - *outp++ = '&'; \ - *outp++ = 'l'; \ - *outp++ = 't'; \ - *outp++ = ';'; \ - break; \ - case '>': \ - memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \ - outp += ncopy; ncopy = 0; \ - *outp++ = '&'; \ - *outp++ = 'g'; \ - *outp++ = 't'; \ - *outp++ = ';'; \ - break; \ - default: \ - ncopy++; \ - } \ - inp++; \ - } \ - memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \ - } - +#define GET_DELTA(inp, inp_end, delta) \ + while (inp < inp_end) { \ + switch (*inp++) { \ + case '"': \ + case '\'': \ + case '&': \ + delta += 4; \ + break; \ + case '<': \ + case '>': \ + delta += 3; \ + break; \ + } \ + } + +#define DO_ESCAPE(inp, inp_end, outp) \ + { \ + Py_ssize_t ncopy = 0; \ + while (inp < inp_end) { \ + switch (*inp) { \ + case '"': \ + memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \ + outp += ncopy; ncopy = 0; \ + *outp++ = '&'; \ + *outp++ = '#'; \ + *outp++ = '3'; \ + *outp++ = '4'; \ + *outp++ = ';'; \ + break; \ + case '\'': \ + memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \ + outp += ncopy; ncopy = 0; \ + *outp++ = '&'; \ + *outp++ = '#'; \ + *outp++ = '3'; \ + *outp++ = '9'; \ + *outp++ = ';'; \ + break; \ + case '&': \ + memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \ + outp += ncopy; ncopy = 0; \ + *outp++ = '&'; \ + *outp++ = 'a'; \ + *outp++ = 'm'; \ + *outp++ = 'p'; \ + *outp++ = ';'; \ + break; \ + case '<': \ + memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \ + outp += ncopy; ncopy = 0; \ + *outp++ = '&'; \ + *outp++ = 'l'; \ + *outp++ = 't'; \ + *outp++ = ';'; \ + break; \ + case '>': \ + memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \ + outp += ncopy; ncopy = 0; \ + *outp++ = '&'; \ + *outp++ = 'g'; \ + *outp++ = 't'; \ + *outp++ = ';'; \ + break; \ + default: \ + ncopy++; \ + } \ + inp++; \ + } \ + memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \ + } + +static PyObject* +escape_unicode_kind1(PyUnicodeObject *in) +{ + Py_UCS1 *inp = PyUnicode_1BYTE_DATA(in); + Py_UCS1 *inp_end = inp + PyUnicode_GET_LENGTH(in); + Py_UCS1 *outp; + PyObject *out; + Py_ssize_t delta = 0; + + GET_DELTA(inp, inp_end, delta); + if (!delta) { + Py_INCREF(in); + return (PyObject*)in; + } + + out = PyUnicode_New(PyUnicode_GET_LENGTH(in) + delta, + PyUnicode_IS_ASCII(in) ? 127 : 255); + if (!out) + return NULL; + + inp = PyUnicode_1BYTE_DATA(in); + outp = PyUnicode_1BYTE_DATA(out); + DO_ESCAPE(inp, inp_end, outp); + return out; +} + +static PyObject* +escape_unicode_kind2(PyUnicodeObject *in) +{ + Py_UCS2 *inp = PyUnicode_2BYTE_DATA(in); + Py_UCS2 *inp_end = inp + PyUnicode_GET_LENGTH(in); + Py_UCS2 *outp; + PyObject *out; + Py_ssize_t delta = 0; + + GET_DELTA(inp, inp_end, delta); + if (!delta) { + Py_INCREF(in); + return (PyObject*)in; + } + + out = PyUnicode_New(PyUnicode_GET_LENGTH(in) + delta, 65535); + if (!out) + return NULL; + + inp = PyUnicode_2BYTE_DATA(in); + outp = PyUnicode_2BYTE_DATA(out); + DO_ESCAPE(inp, inp_end, outp); + return out; +} + + +static PyObject* +escape_unicode_kind4(PyUnicodeObject *in) +{ + Py_UCS4 *inp = PyUnicode_4BYTE_DATA(in); + Py_UCS4 *inp_end = inp + PyUnicode_GET_LENGTH(in); + Py_UCS4 *outp; + PyObject *out; + Py_ssize_t delta = 0; + + GET_DELTA(inp, inp_end, delta); + if (!delta) { + Py_INCREF(in); + return (PyObject*)in; + } + + out = PyUnicode_New(PyUnicode_GET_LENGTH(in) + delta, 1114111); + if (!out) + return NULL; + + inp = PyUnicode_4BYTE_DATA(in); + outp = PyUnicode_4BYTE_DATA(out); + DO_ESCAPE(inp, inp_end, outp); + return out; +} + +static PyObject* +escape_unicode(PyUnicodeObject *in) +{ + if (PyUnicode_READY(in)) + return NULL; + + switch (PyUnicode_KIND(in)) { + case PyUnicode_1BYTE_KIND: + return escape_unicode_kind1(in); + case PyUnicode_2BYTE_KIND: + return escape_unicode_kind2(in); + case PyUnicode_4BYTE_KIND: + return escape_unicode_kind4(in); + } + assert(0); /* shouldn't happen */ + return NULL; +} + static PyObject* -escape_unicode_kind1(PyUnicodeObject *in) -{ - Py_UCS1 *inp = PyUnicode_1BYTE_DATA(in); - Py_UCS1 *inp_end = inp + PyUnicode_GET_LENGTH(in); - Py_UCS1 *outp; - PyObject *out; - Py_ssize_t delta = 0; - - GET_DELTA(inp, inp_end, delta); - if (!delta) { - Py_INCREF(in); - return (PyObject*)in; - } - - out = PyUnicode_New(PyUnicode_GET_LENGTH(in) + delta, - PyUnicode_IS_ASCII(in) ? 127 : 255); - if (!out) - return NULL; - - inp = PyUnicode_1BYTE_DATA(in); - outp = PyUnicode_1BYTE_DATA(out); - DO_ESCAPE(inp, inp_end, outp); - return out; -} - -static PyObject* -escape_unicode_kind2(PyUnicodeObject *in) -{ - Py_UCS2 *inp = PyUnicode_2BYTE_DATA(in); - Py_UCS2 *inp_end = inp + PyUnicode_GET_LENGTH(in); - Py_UCS2 *outp; - PyObject *out; - Py_ssize_t delta = 0; - - GET_DELTA(inp, inp_end, delta); - if (!delta) { - Py_INCREF(in); - return (PyObject*)in; - } - - out = PyUnicode_New(PyUnicode_GET_LENGTH(in) + delta, 65535); - if (!out) - return NULL; - - inp = PyUnicode_2BYTE_DATA(in); - outp = PyUnicode_2BYTE_DATA(out); - DO_ESCAPE(inp, inp_end, outp); - return out; -} - - -static PyObject* -escape_unicode_kind4(PyUnicodeObject *in) -{ - Py_UCS4 *inp = PyUnicode_4BYTE_DATA(in); - Py_UCS4 *inp_end = inp + PyUnicode_GET_LENGTH(in); - Py_UCS4 *outp; - PyObject *out; - Py_ssize_t delta = 0; - - GET_DELTA(inp, inp_end, delta); - if (!delta) { - Py_INCREF(in); - return (PyObject*)in; - } - - out = PyUnicode_New(PyUnicode_GET_LENGTH(in) + delta, 1114111); - if (!out) - return NULL; - - inp = PyUnicode_4BYTE_DATA(in); - outp = PyUnicode_4BYTE_DATA(out); - DO_ESCAPE(inp, inp_end, outp); - return out; -} - -static PyObject* -escape_unicode(PyUnicodeObject *in) -{ - if (PyUnicode_READY(in)) - return NULL; - - switch (PyUnicode_KIND(in)) { - case PyUnicode_1BYTE_KIND: - return escape_unicode_kind1(in); - case PyUnicode_2BYTE_KIND: - return escape_unicode_kind2(in); - case PyUnicode_4BYTE_KIND: - return escape_unicode_kind4(in); - } - assert(0); /* shouldn't happen */ - return NULL; -} - -static PyObject* escape(PyObject *self, PyObject *text) { - static PyObject *id_html; + static PyObject *id_html; PyObject *s = NULL, *rv = NULL, *html; - if (id_html == NULL) { - id_html = PyUnicode_InternFromString("__html__"); - if (id_html == NULL) { - return NULL; - } - } - + if (id_html == NULL) { + id_html = PyUnicode_InternFromString("__html__"); + if (id_html == NULL) { + return NULL; + } + } + /* we don't have to escape integers, bools or floats */ if (PyLong_CheckExact(text) || - PyFloat_CheckExact(text) || PyBool_Check(text) || - text == Py_None) + PyFloat_CheckExact(text) || PyBool_Check(text) || + text == Py_None) return PyObject_CallFunctionObjArgs(markup, text, NULL); /* if the object has an __html__ method that performs the escaping */ - html = PyObject_GetAttr(text ,id_html); + html = PyObject_GetAttr(text ,id_html); if (html) { - s = PyObject_CallObject(html, NULL); + s = PyObject_CallObject(html, NULL); Py_DECREF(html); - if (s == NULL) { - return NULL; - } - /* Convert to Markup object */ - rv = PyObject_CallFunctionObjArgs(markup, (PyObject*)s, NULL); - Py_DECREF(s); + if (s == NULL) { + return NULL; + } + /* Convert to Markup object */ + rv = PyObject_CallFunctionObjArgs(markup, (PyObject*)s, NULL); + Py_DECREF(s); return rv; } @@ -245,7 +245,7 @@ escape_silent(PyObject *self, PyObject *text) static PyObject* -soft_str(PyObject *self, PyObject *s) +soft_str(PyObject *self, PyObject *s) { if (!PyUnicode_Check(s)) return PyObject_Str(s); @@ -254,71 +254,71 @@ soft_str(PyObject *self, PyObject *s) } -static PyObject* -soft_unicode(PyObject *self, PyObject *s) +static PyObject* +soft_unicode(PyObject *self, PyObject *s) { - PyErr_WarnEx( - PyExc_DeprecationWarning, - "'soft_unicode' has been renamed to 'soft_str'. The old name" - " will be removed in MarkupSafe 2.1.", - 2 - ); - return soft_str(self, s); + PyErr_WarnEx( + PyExc_DeprecationWarning, + "'soft_unicode' has been renamed to 'soft_str'. The old name" + " will be removed in MarkupSafe 2.1.", + 2 + ); + return soft_str(self, s); } -static PyMethodDef module_methods[] = { - { - "escape", - (PyCFunction)escape, - METH_O, - "Replace the characters ``&``, ``<``, ``>``, ``'``, and ``\"`` in" - " the string with HTML-safe sequences. Use this if you need to display" - " text that might contain such characters in HTML.\n\n" - "If the object has an ``__html__`` method, it is called and the" - " return value is assumed to already be safe for HTML.\n\n" - ":param s: An object to be converted to a string and escaped.\n" - ":return: A :class:`Markup` string with the escaped text.\n" - }, - { - "escape_silent", - (PyCFunction)escape_silent, - METH_O, - "Like :func:`escape` but treats ``None`` as the empty string." - " Useful with optional values, as otherwise you get the string" - " ``'None'`` when the value is ``None``.\n\n" - ">>> escape(None)\n" - "Markup('None')\n" - ">>> escape_silent(None)\n" - "Markup('')\n" - }, - { - "soft_str", - (PyCFunction)soft_str, - METH_O, - "Convert an object to a string if it isn't already. This preserves" - " a :class:`Markup` string rather than converting it back to a basic" - " string, so it will still be marked as safe and won't be escaped" - " again.\n\n" - ">>> value = escape(\"<User 1>\")\n" - ">>> value\n" - "Markup('<User 1>')\n" - ">>> escape(str(value))\n" - "Markup('&lt;User 1&gt;')\n" - ">>> escape(soft_str(value))\n" - "Markup('<User 1>')\n" - }, - { - "soft_unicode", - (PyCFunction)soft_unicode, - METH_O, - "" - }, - {NULL, NULL, 0, NULL} /* Sentinel */ -}; - +static PyMethodDef module_methods[] = { + { + "escape", + (PyCFunction)escape, + METH_O, + "Replace the characters ``&``, ``<``, ``>``, ``'``, and ``\"`` in" + " the string with HTML-safe sequences. Use this if you need to display" + " text that might contain such characters in HTML.\n\n" + "If the object has an ``__html__`` method, it is called and the" + " return value is assumed to already be safe for HTML.\n\n" + ":param s: An object to be converted to a string and escaped.\n" + ":return: A :class:`Markup` string with the escaped text.\n" + }, + { + "escape_silent", + (PyCFunction)escape_silent, + METH_O, + "Like :func:`escape` but treats ``None`` as the empty string." + " Useful with optional values, as otherwise you get the string" + " ``'None'`` when the value is ``None``.\n\n" + ">>> escape(None)\n" + "Markup('None')\n" + ">>> escape_silent(None)\n" + "Markup('')\n" + }, + { + "soft_str", + (PyCFunction)soft_str, + METH_O, + "Convert an object to a string if it isn't already. This preserves" + " a :class:`Markup` string rather than converting it back to a basic" + " string, so it will still be marked as safe and won't be escaped" + " again.\n\n" + ">>> value = escape(\"<User 1>\")\n" + ">>> value\n" + "Markup('<User 1>')\n" + ">>> escape(str(value))\n" + "Markup('&lt;User 1&gt;')\n" + ">>> escape(soft_str(value))\n" + "Markup('<User 1>')\n" + }, + { + "soft_unicode", + (PyCFunction)soft_unicode, + METH_O, + "" + }, + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + static struct PyModuleDef module_definition = { - PyModuleDef_HEAD_INIT, + PyModuleDef_HEAD_INIT, "markupsafe._speedups", NULL, -1, @@ -330,7 +330,7 @@ static struct PyModuleDef module_definition = { }; PyMODINIT_FUNC -PyInit__speedups(void) +PyInit__speedups(void) { if (!init_constants()) return NULL; diff --git a/contrib/python/MarkupSafe/py3/markupsafe/_speedups.pyi b/contrib/python/MarkupSafe/py3/markupsafe/_speedups.pyi index ec61c77237..f673240f6d 100644 --- a/contrib/python/MarkupSafe/py3/markupsafe/_speedups.pyi +++ b/contrib/python/MarkupSafe/py3/markupsafe/_speedups.pyi @@ -1,9 +1,9 @@ -from typing import Any -from typing import Optional - -from . import Markup - -def escape(s: Any) -> Markup: ... -def escape_silent(s: Optional[Any]) -> Markup: ... -def soft_str(s: Any) -> str: ... -def soft_unicode(s: Any) -> str: ... +from typing import Any +from typing import Optional + +from . import Markup + +def escape(s: Any) -> Markup: ... +def escape_silent(s: Optional[Any]) -> Markup: ... +def soft_str(s: Any) -> str: ... +def soft_unicode(s: Any) -> str: ... diff --git a/contrib/python/MarkupSafe/py3/tests/conftest.py b/contrib/python/MarkupSafe/py3/tests/conftest.py index 873127f7e1..13f938ced9 100644 --- a/contrib/python/MarkupSafe/py3/tests/conftest.py +++ b/contrib/python/MarkupSafe/py3/tests/conftest.py @@ -1,42 +1,42 @@ -import pytest - -from markupsafe import _native - -try: - from markupsafe import _speedups -except ImportError: - _speedups = None # type: ignore - - -@pytest.fixture( - scope="session", - params=( - _native, - pytest.param( - _speedups, - marks=pytest.mark.skipif(_speedups is None, reason="speedups unavailable"), - ), - ), -) -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 - - -@pytest.fixture(scope="session") -def soft_unicode(_mod): - return _mod.soft_unicode +import pytest + +from markupsafe import _native + +try: + from markupsafe import _speedups +except ImportError: + _speedups = None # type: ignore + + +@pytest.fixture( + scope="session", + params=( + _native, + pytest.param( + _speedups, + marks=pytest.mark.skipif(_speedups is None, reason="speedups unavailable"), + ), + ), +) +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 + + +@pytest.fixture(scope="session") +def soft_unicode(_mod): + return _mod.soft_unicode diff --git a/contrib/python/MarkupSafe/py3/tests/test_escape.py b/contrib/python/MarkupSafe/py3/tests/test_escape.py index 4541b30ac1..bf53facedd 100644 --- a/contrib/python/MarkupSafe/py3/tests/test_escape.py +++ b/contrib/python/MarkupSafe/py3/tests/test_escape.py @@ -1,29 +1,29 @@ -import pytest - -from markupsafe import Markup - - -@pytest.mark.parametrize( - ("value", "expect"), - ( - # empty - ("", ""), - # ascii - ("abcd&><'\"efgh", "abcd&><'"efgh"), - ("&><'\"efgh", "&><'"efgh"), - ("abcd&><'\"", "abcd&><'""), - # 2 byte - ("こんにちは&><'\"こんばんは", "こんにちは&><'"こんばんは"), - ("&><'\"こんばんは", "&><'"こんばんは"), - ("こんにちは&><'\"", "こんにちは&><'""), - # 4 byte - ( - "\U0001F363\U0001F362&><'\"\U0001F37A xyz", - "\U0001F363\U0001F362&><'"\U0001F37A xyz", - ), - ("&><'\"\U0001F37A xyz", "&><'"\U0001F37A xyz"), - ("\U0001F363\U0001F362&><'\"", "\U0001F363\U0001F362&><'""), - ), -) -def test_escape(escape, value, expect): - assert escape(value) == Markup(expect) +import pytest + +from markupsafe import Markup + + +@pytest.mark.parametrize( + ("value", "expect"), + ( + # empty + ("", ""), + # ascii + ("abcd&><'\"efgh", "abcd&><'"efgh"), + ("&><'\"efgh", "&><'"efgh"), + ("abcd&><'\"", "abcd&><'""), + # 2 byte + ("こんにちは&><'\"こんばんは", "こんにちは&><'"こんばんは"), + ("&><'\"こんばんは", "&><'"こんばんは"), + ("こんにちは&><'\"", "こんにちは&><'""), + # 4 byte + ( + "\U0001F363\U0001F362&><'\"\U0001F37A xyz", + "\U0001F363\U0001F362&><'"\U0001F37A xyz", + ), + ("&><'\"\U0001F37A xyz", "&><'"\U0001F37A xyz"), + ("\U0001F363\U0001F362&><'\"", "\U0001F363\U0001F362&><'""), + ), +) +def test_escape(escape, value, expect): + 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 e1dd2dff6e..ec2f10b1d1 100644 --- a/contrib/python/MarkupSafe/py3/tests/test_exception_custom_html.py +++ b/contrib/python/MarkupSafe/py3/tests/test_exception_custom_html.py @@ -1,18 +1,18 @@ -import pytest - - -class CustomHtmlThatRaises: - def __html__(self): - raise ValueError(123) - - -def test_exception_custom_html(escape): - """Checks whether exceptions in custom __html__ implementations are - propagated correctly. - - There was a bug in the native implementation at some point: - https://github.com/pallets/markupsafe/issues/108 - """ - obj = CustomHtmlThatRaises() - with pytest.raises(ValueError): - escape(obj) +import pytest + + +class CustomHtmlThatRaises: + def __html__(self): + raise ValueError(123) + + +def test_exception_custom_html(escape): + """Checks whether exceptions in custom __html__ implementations are + propagated correctly. + + There was a bug in the native implementation at some point: + 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 b3c4042b67..55b10b98a4 100644 --- a/contrib/python/MarkupSafe/py3/tests/test_leak.py +++ b/contrib/python/MarkupSafe/py3/tests/test_leak.py @@ -1,28 +1,28 @@ -import gc -import platform - -import pytest - -from markupsafe import escape - - -@pytest.mark.skipif( - escape.__module__ == "markupsafe._native", - reason="only test memory leak with speedups", -) -def test_markup_leaks(): - counts = set() - - for _i in range(20): - for _j 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 +import gc +import platform + +import pytest + +from markupsafe import escape + + +@pytest.mark.skipif( + escape.__module__ == "markupsafe._native", + reason="only test memory leak with speedups", +) +def test_markup_leaks(): + counts = set() + + for _i in range(20): + for _j 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 diff --git a/contrib/python/MarkupSafe/py3/tests/test_markupsafe.py b/contrib/python/MarkupSafe/py3/tests/test_markupsafe.py index a4ba637fe0..fcd934702e 100644 --- a/contrib/python/MarkupSafe/py3/tests/test_markupsafe.py +++ b/contrib/python/MarkupSafe/py3/tests/test_markupsafe.py @@ -1,185 +1,185 @@ -import pytest - -from markupsafe import Markup - - -def test_adding(escape): - unsafe = '<script type="application/x-some-script">alert("foo");</script>' - safe = Markup("<em>username</em>") - assert unsafe + safe == str(escape(unsafe)) + str(safe) - - -@pytest.mark.parametrize( - ("template", "data", "expect"), - ( - ("<em>%s</em>", "<bad user>", "<em><bad user></em>"), - ( - "<em>%(username)s</em>", - {"username": "<bad user>"}, - "<em><bad user></em>", - ), - ("%i", 3.14, "3"), - ("%.2f", 3.14, "3.14"), - ), -) -def test_string_interpolation(template, data, expect): - assert Markup(template) % data == expect - - -def test_type_behavior(): - assert type(Markup("foo") + "bar") is Markup - x = Markup("foo") - assert x.__html__() is x - - -def test_html_interop(): - class Foo: - def __html__(self): - return "<em>awesome</em>" - - def __str__(self): - return "awesome" - - assert Markup(Foo()) == "<em>awesome</em>" - result = Markup("<strong>%s</strong>") % Foo() - assert result == "<strong><em>awesome</em></strong>" - - -def test_tuple_interpol(): - result = Markup("<em>%s:%s</em>") % ("<foo>", "<bar>") - expect = Markup("<em><foo>:<bar></em>") - assert result == expect - - -def test_dict_interpol(): - result = Markup("<em>%(foo)s</em>") % {"foo": "<foo>"} - expect = Markup("<em><foo></em>") - assert result == expect - - result = Markup("<em>%(foo)s:%(bar)s</em>") % {"foo": "<foo>", "bar": "<bar>"} - expect = Markup("<em><foo>:<bar></em>") - assert result == expect - - -def test_escaping(escape): - assert escape("\"<>&'") == ""<>&'" - assert Markup("<em>Foo & Bar</em>").striptags() == "Foo & Bar" - - -def test_unescape(): - assert Markup("<test>").unescape() == "<test>" - - result = Markup("jack & tavi are cooler than mike & russ").unescape() - expect = "jack & tavi are cooler than mike & russ" - assert result == expect - - original = "&foo;" - once = Markup(original).unescape() - twice = Markup(once).unescape() - expect = "&foo;" - assert once == expect - assert twice == expect - - -def test_format(): - result = Markup("<em>{awesome}</em>").format(awesome="<awesome>") - assert result == "<em><awesome></em>" - - result = Markup("{0[1][bar]}").format([0, {"bar": "<bar/>"}]) - assert result == "<bar/>" - - result = Markup("{0[1][bar]}").format([0, {"bar": Markup("<bar/>")}]) - assert result == "<bar/>" - - -def test_formatting_empty(): - formatted = Markup("{}").format(0) - assert formatted == Markup("0") - - -def test_custom_formatting(): - class HasHTMLOnly: - def __html__(self): - return Markup("<foo>") - - class HasHTMLAndFormat: - def __html__(self): - return Markup("<foo>") - - def __html_format__(self, spec): - return Markup("<FORMAT>") - - assert Markup("{0}").format(HasHTMLOnly()) == Markup("<foo>") - assert Markup("{0}").format(HasHTMLAndFormat()) == Markup("<FORMAT>") - - -def test_complex_custom_formatting(): - class User: - def __init__(self, id, username): - self.id = id - self.username = username - - def __html_format__(self, format_spec): - if format_spec == "link": - return Markup('<a href="/user/{0}">{1}</a>').format( - self.id, self.__html__() - ) - elif format_spec: - raise ValueError("Invalid format spec") - - return self.__html__() - - def __html__(self): - return Markup("<span class=user>{0}</span>").format(self.username) - - user = User(1, "foo") - result = Markup("<p>User: {0:link}").format(user) - expect = Markup('<p>User: <a href="/user/1"><span class=user>foo</span></a>') - assert result == expect - - -def test_formatting_with_objects(): - class Stringable: - def __str__(self): - return "строка" - - assert Markup("{s}").format(s=Stringable()) == Markup("строка") - - -def test_escape_silent(escape, escape_silent): - assert escape_silent(None) == Markup() - assert escape(None) == Markup(None) - assert escape_silent("<foo>") == Markup("<foo>") - - -def test_splitting(): - 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(): - assert Markup("a") * 3 == Markup("aaa") - - -def test_escape_return_type(escape): - assert isinstance(escape("a"), Markup) - assert isinstance(escape(Markup("a")), Markup) - - class Foo: - def __html__(self): - 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_unicode_deprecated(soft_unicode): - with pytest.warns(DeprecationWarning): - assert type(soft_unicode(Markup())) is Markup +import pytest + +from markupsafe import Markup + + +def test_adding(escape): + unsafe = '<script type="application/x-some-script">alert("foo");</script>' + safe = Markup("<em>username</em>") + assert unsafe + safe == str(escape(unsafe)) + str(safe) + + +@pytest.mark.parametrize( + ("template", "data", "expect"), + ( + ("<em>%s</em>", "<bad user>", "<em><bad user></em>"), + ( + "<em>%(username)s</em>", + {"username": "<bad user>"}, + "<em><bad user></em>", + ), + ("%i", 3.14, "3"), + ("%.2f", 3.14, "3.14"), + ), +) +def test_string_interpolation(template, data, expect): + assert Markup(template) % data == expect + + +def test_type_behavior(): + assert type(Markup("foo") + "bar") is Markup + x = Markup("foo") + assert x.__html__() is x + + +def test_html_interop(): + class Foo: + def __html__(self): + return "<em>awesome</em>" + + def __str__(self): + return "awesome" + + assert Markup(Foo()) == "<em>awesome</em>" + result = Markup("<strong>%s</strong>") % Foo() + assert result == "<strong><em>awesome</em></strong>" + + +def test_tuple_interpol(): + result = Markup("<em>%s:%s</em>") % ("<foo>", "<bar>") + expect = Markup("<em><foo>:<bar></em>") + assert result == expect + + +def test_dict_interpol(): + result = Markup("<em>%(foo)s</em>") % {"foo": "<foo>"} + expect = Markup("<em><foo></em>") + assert result == expect + + result = Markup("<em>%(foo)s:%(bar)s</em>") % {"foo": "<foo>", "bar": "<bar>"} + expect = Markup("<em><foo>:<bar></em>") + assert result == expect + + +def test_escaping(escape): + assert escape("\"<>&'") == ""<>&'" + assert Markup("<em>Foo & Bar</em>").striptags() == "Foo & Bar" + + +def test_unescape(): + assert Markup("<test>").unescape() == "<test>" + + result = Markup("jack & tavi are cooler than mike & russ").unescape() + expect = "jack & tavi are cooler than mike & russ" + assert result == expect + + original = "&foo;" + once = Markup(original).unescape() + twice = Markup(once).unescape() + expect = "&foo;" + assert once == expect + assert twice == expect + + +def test_format(): + result = Markup("<em>{awesome}</em>").format(awesome="<awesome>") + assert result == "<em><awesome></em>" + + result = Markup("{0[1][bar]}").format([0, {"bar": "<bar/>"}]) + assert result == "<bar/>" + + result = Markup("{0[1][bar]}").format([0, {"bar": Markup("<bar/>")}]) + assert result == "<bar/>" + + +def test_formatting_empty(): + formatted = Markup("{}").format(0) + assert formatted == Markup("0") + + +def test_custom_formatting(): + class HasHTMLOnly: + def __html__(self): + return Markup("<foo>") + + class HasHTMLAndFormat: + def __html__(self): + return Markup("<foo>") + + def __html_format__(self, spec): + return Markup("<FORMAT>") + + assert Markup("{0}").format(HasHTMLOnly()) == Markup("<foo>") + assert Markup("{0}").format(HasHTMLAndFormat()) == Markup("<FORMAT>") + + +def test_complex_custom_formatting(): + class User: + def __init__(self, id, username): + self.id = id + self.username = username + + def __html_format__(self, format_spec): + if format_spec == "link": + return Markup('<a href="/user/{0}">{1}</a>').format( + self.id, self.__html__() + ) + elif format_spec: + raise ValueError("Invalid format spec") + + return self.__html__() + + def __html__(self): + return Markup("<span class=user>{0}</span>").format(self.username) + + user = User(1, "foo") + result = Markup("<p>User: {0:link}").format(user) + expect = Markup('<p>User: <a href="/user/1"><span class=user>foo</span></a>') + assert result == expect + + +def test_formatting_with_objects(): + class Stringable: + def __str__(self): + return "строка" + + assert Markup("{s}").format(s=Stringable()) == Markup("строка") + + +def test_escape_silent(escape, escape_silent): + assert escape_silent(None) == Markup() + assert escape(None) == Markup(None) + assert escape_silent("<foo>") == Markup("<foo>") + + +def test_splitting(): + 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(): + assert Markup("a") * 3 == Markup("aaa") + + +def test_escape_return_type(escape): + assert isinstance(escape("a"), Markup) + assert isinstance(escape(Markup("a")), Markup) + + class Foo: + def __html__(self): + 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_unicode_deprecated(soft_unicode): + with pytest.warns(DeprecationWarning): + assert type(soft_unicode(Markup())) is Markup diff --git a/contrib/python/MarkupSafe/py3/tests/ya.make b/contrib/python/MarkupSafe/py3/tests/ya.make index e199fa8d89..d37516d561 100644 --- a/contrib/python/MarkupSafe/py3/tests/ya.make +++ b/contrib/python/MarkupSafe/py3/tests/ya.make @@ -1,19 +1,19 @@ -PY3TEST() - -OWNER(g:python-contrib) - -PEERDIR( - contrib/python/MarkupSafe -) - -TEST_SRCS( - conftest.py - test_escape.py - test_exception_custom_html.py - test_leak.py - test_markupsafe.py -) - -NO_LINT() - -END() +PY3TEST() + +OWNER(g:python-contrib) + +PEERDIR( + contrib/python/MarkupSafe +) + +TEST_SRCS( + conftest.py + test_escape.py + test_exception_custom_html.py + test_leak.py + test_markupsafe.py +) + +NO_LINT() + +END() diff --git a/contrib/python/MarkupSafe/py3/ya.make b/contrib/python/MarkupSafe/py3/ya.make index c3624ab35f..8c750e15d8 100644 --- a/contrib/python/MarkupSafe/py3/ya.make +++ b/contrib/python/MarkupSafe/py3/ya.make @@ -1,41 +1,41 @@ -# Generated by devtools/yamaker (pypi). - -PY3_LIBRARY() - -OWNER(g:python-contrib) - -VERSION(2.0.1) - -LICENSE(BSD-3-Clause) - -NO_COMPILER_WARNINGS() - -NO_LINT() - -SRCS( - markupsafe/_speedups.c -) - -PY_REGISTER( - markupsafe._speedups -) - -PY_SRCS( - TOP_LEVEL - markupsafe/__init__.py - markupsafe/_native.py - markupsafe/_speedups.pyi -) - +# Generated by devtools/yamaker (pypi). + +PY3_LIBRARY() + +OWNER(g:python-contrib) + +VERSION(2.0.1) + +LICENSE(BSD-3-Clause) + +NO_COMPILER_WARNINGS() + +NO_LINT() + +SRCS( + markupsafe/_speedups.c +) + +PY_REGISTER( + markupsafe._speedups +) + +PY_SRCS( + TOP_LEVEL + markupsafe/__init__.py + markupsafe/_native.py + markupsafe/_speedups.pyi +) + RESOURCE_FILES( - PREFIX contrib/python/MarkupSafe/py3/ + PREFIX contrib/python/MarkupSafe/py3/ .dist-info/METADATA .dist-info/top_level.txt - markupsafe/py.typed + markupsafe/py.typed ) END() - -RECURSE_FOR_TESTS( - tests -) + +RECURSE_FOR_TESTS( + tests +) |