From 9289ead9967b84f5cee1ee5d22554490f39e23fc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 16 Nov 2024 14:51:58 -0800 Subject: [PATCH] Bump mako from 1.3.5 to 1.3.6 (#2423) * Bump mako from 1.3.5 to 1.3.6 Bumps [mako](https://github.com/sqlalchemy/mako) from 1.3.5 to 1.3.6. - [Release notes](https://github.com/sqlalchemy/mako/releases) - [Changelog](https://github.com/sqlalchemy/mako/blob/main/CHANGES) - [Commits](https://github.com/sqlalchemy/mako/commits) --- updated-dependencies: - dependency-name: mako dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Update mako==1.3.6 --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: JonnyWong16 <9099342+JonnyWong16@users.noreply.github.com> [skip ci] --- lib/mako/__init__.py | 2 +- lib/mako/lexer.py | 2 +- lib/markupsafe/__init__.py | 355 +++++++++++++++++++++-------------- lib/markupsafe/_native.py | 61 +----- lib/markupsafe/_speedups.c | 158 +++------------- lib/markupsafe/_speedups.pyi | 10 +- requirements.txt | 2 +- 7 files changed, 237 insertions(+), 353 deletions(-) diff --git a/lib/mako/__init__.py b/lib/mako/__init__.py index 0ac3dd68..d7223f7c 100644 --- a/lib/mako/__init__.py +++ b/lib/mako/__init__.py @@ -5,4 +5,4 @@ # the MIT License: http://www.opensource.org/licenses/mit-license.php -__version__ = "1.3.5" +__version__ = "1.3.6" diff --git a/lib/mako/lexer.py b/lib/mako/lexer.py index 9d1f5f30..b4a76a45 100644 --- a/lib/mako/lexer.py +++ b/lib/mako/lexer.py @@ -375,7 +375,7 @@ class Lexer: | (?=\${) # an expression | - (?= str: - pass - _P = te.ParamSpec("_P") +class _HasHTML(t.Protocol): + def __html__(self, /) -> str: ... -__version__ = "2.1.5" +class _TPEscape(t.Protocol): + def __call__(self, s: t.Any, /) -> Markup: ... -def _simple_escaping_wrapper(func: "t.Callable[_P, str]") -> "t.Callable[_P, Markup]": - @functools.wraps(func) - def wrapped(self: "Markup", *args: "_P.args", **kwargs: "_P.kwargs") -> "Markup": - arg_list = _escape_argspec(list(args), enumerate(args), self.escape) - _escape_argspec(kwargs, kwargs.items(), self.escape) - return self.__class__(func(self, *arg_list, **kwargs)) # type: ignore[arg-type] +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. - return wrapped # type: ignore[return-value] + 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 the object is already a plain string, skip __html__ check and string + # conversion. This is the most common use case. + # Use type(s) instead of s.__class__ because a proxy object may be reporting + # the __class__ of the proxied value. + if type(s) is str: + return Markup(_escape_inner(s)) + + if hasattr(s, "__html__"): + return Markup(s.__html__()) + + return Markup(_escape_inner(str(s))) + + +def escape_silent(s: t.Any | None, /) -> 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("") + >>> 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) + + return s class Markup(str): @@ -65,82 +120,72 @@ class Markup(str): __slots__ = () def __new__( - cls, base: t.Any = "", encoding: t.Optional[str] = None, errors: str = "strict" - ) -> "te.Self": - if hasattr(base, "__html__"): - base = base.__html__() + cls, object: t.Any = "", encoding: str | None = None, errors: str = "strict" + ) -> te.Self: + if hasattr(object, "__html__"): + object = object.__html__() if encoding is None: - return super().__new__(cls, base) + return super().__new__(cls, object) - return super().__new__(cls, base, encoding, errors) + return super().__new__(cls, object, encoding, errors) - def __html__(self) -> "te.Self": + def __html__(self, /) -> te.Self: return self - def __add__(self, other: t.Union[str, "HasHTML"]) -> "te.Self": - if isinstance(other, str) or hasattr(other, "__html__"): - return self.__class__(super().__add__(self.escape(other))) + def __add__(self, value: str | _HasHTML, /) -> te.Self: + if isinstance(value, str) or hasattr(value, "__html__"): + return self.__class__(super().__add__(self.escape(value))) return NotImplemented - def __radd__(self, other: t.Union[str, "HasHTML"]) -> "te.Self": - if isinstance(other, str) or hasattr(other, "__html__"): - return self.escape(other).__add__(self) + def __radd__(self, value: str | _HasHTML, /) -> te.Self: + if isinstance(value, str) or hasattr(value, "__html__"): + return self.escape(value).__add__(self) return NotImplemented - def __mul__(self, num: "te.SupportsIndex") -> "te.Self": - if isinstance(num, int): - return self.__class__(super().__mul__(num)) + def __mul__(self, value: t.SupportsIndex, /) -> te.Self: + return self.__class__(super().__mul__(value)) - return NotImplemented + def __rmul__(self, value: t.SupportsIndex, /) -> te.Self: + return self.__class__(super().__mul__(value)) - __rmul__ = __mul__ - - def __mod__(self, arg: t.Any) -> "te.Self": - if isinstance(arg, tuple): + def __mod__(self, value: t.Any, /) -> te.Self: + if isinstance(value, tuple): # a tuple of arguments, each wrapped - arg = tuple(_MarkupEscapeHelper(x, self.escape) for x in arg) - elif hasattr(type(arg), "__getitem__") and not isinstance(arg, str): + value = tuple(_MarkupEscapeHelper(x, self.escape) for x in value) + elif hasattr(type(value), "__getitem__") and not isinstance(value, str): # a mapping of arguments, wrapped - arg = _MarkupEscapeHelper(arg, self.escape) + value = _MarkupEscapeHelper(value, self.escape) else: # a single argument, wrapped with the helper and a tuple - arg = (_MarkupEscapeHelper(arg, self.escape),) + value = (_MarkupEscapeHelper(value, self.escape),) - return self.__class__(super().__mod__(arg)) + return self.__class__(super().__mod__(value)) - def __repr__(self) -> str: + def __repr__(self, /) -> str: return f"{self.__class__.__name__}({super().__repr__()})" - def join(self, seq: t.Iterable[t.Union[str, "HasHTML"]]) -> "te.Self": - return self.__class__(super().join(map(self.escape, seq))) - - join.__doc__ = str.join.__doc__ + def join(self, iterable: cabc.Iterable[str | _HasHTML], /) -> te.Self: + return self.__class__(super().join(map(self.escape, iterable))) def split( # type: ignore[override] - self, sep: t.Optional[str] = None, maxsplit: int = -1 - ) -> t.List["te.Self"]: + self, /, sep: str | None = None, maxsplit: t.SupportsIndex = -1 + ) -> list[te.Self]: return [self.__class__(v) for v in super().split(sep, maxsplit)] - split.__doc__ = str.split.__doc__ - def rsplit( # type: ignore[override] - self, sep: t.Optional[str] = None, maxsplit: int = -1 - ) -> t.List["te.Self"]: + self, /, sep: str | None = None, maxsplit: t.SupportsIndex = -1 + ) -> list[te.Self]: return [self.__class__(v) for v in super().rsplit(sep, maxsplit)] - rsplit.__doc__ = str.rsplit.__doc__ - def splitlines( # type: ignore[override] - self, keepends: bool = False - ) -> t.List["te.Self"]: + self, /, keepends: bool = False + ) -> list[te.Self]: return [self.__class__(v) for v in super().splitlines(keepends)] - splitlines.__doc__ = str.splitlines.__doc__ - - def unescape(self) -> str: + def unescape(self, /) -> str: """Convert escaped markup back into a text string. This replaces HTML entities with the characters they represent. @@ -151,7 +196,7 @@ class Markup(str): return unescape(str(self)) - def striptags(self) -> str: + def striptags(self, /) -> str: """:meth:`unescape` the markup, remove tags, and normalize whitespace to single spaces. @@ -163,31 +208,17 @@ class Markup(str): # Look for comments then tags separately. Otherwise, a comment that # contains a tag would end early, leaving some of the comment behind. - while True: - # keep finding comment start marks - start = value.find("", start) - - if end == -1: + if (end := value.find("-->", start)) == -1: break value = f"{value[:start]}{value[end + 3:]}" # remove tags using the same method - while True: - start = value.find("<") - - if start == -1: - break - - end = value.find(">", start) - - if end == -1: + while (start := value.find("<")) != -1: + if (end := value.find(">", start)) == -1: break value = f"{value[:start]}{value[end + 1:]}" @@ -197,7 +228,7 @@ class Markup(str): return self.__class__(value).unescape() @classmethod - def escape(cls, s: t.Any) -> "te.Self": + def escape(cls, s: t.Any, /) -> te.Self: """Escape a string. Calls :func:`escape` and ensures that for subclasses the correct type is returned. """ @@ -208,49 +239,90 @@ class Markup(str): return rv # type: ignore[return-value] - __getitem__ = _simple_escaping_wrapper(str.__getitem__) - capitalize = _simple_escaping_wrapper(str.capitalize) - title = _simple_escaping_wrapper(str.title) - lower = _simple_escaping_wrapper(str.lower) - upper = _simple_escaping_wrapper(str.upper) - replace = _simple_escaping_wrapper(str.replace) - ljust = _simple_escaping_wrapper(str.ljust) - rjust = _simple_escaping_wrapper(str.rjust) - lstrip = _simple_escaping_wrapper(str.lstrip) - rstrip = _simple_escaping_wrapper(str.rstrip) - center = _simple_escaping_wrapper(str.center) - strip = _simple_escaping_wrapper(str.strip) - translate = _simple_escaping_wrapper(str.translate) - expandtabs = _simple_escaping_wrapper(str.expandtabs) - swapcase = _simple_escaping_wrapper(str.swapcase) - zfill = _simple_escaping_wrapper(str.zfill) - casefold = _simple_escaping_wrapper(str.casefold) + def __getitem__(self, key: t.SupportsIndex | slice, /) -> te.Self: + return self.__class__(super().__getitem__(key)) - if sys.version_info >= (3, 9): - removeprefix = _simple_escaping_wrapper(str.removeprefix) - removesuffix = _simple_escaping_wrapper(str.removesuffix) + def capitalize(self, /) -> te.Self: + return self.__class__(super().capitalize()) - def partition(self, sep: str) -> t.Tuple["te.Self", "te.Self", "te.Self"]: - l, s, r = super().partition(self.escape(sep)) + def title(self, /) -> te.Self: + return self.__class__(super().title()) + + def lower(self, /) -> te.Self: + return self.__class__(super().lower()) + + def upper(self, /) -> te.Self: + return self.__class__(super().upper()) + + def replace(self, old: str, new: str, count: t.SupportsIndex = -1, /) -> te.Self: + return self.__class__(super().replace(old, self.escape(new), count)) + + def ljust(self, width: t.SupportsIndex, fillchar: str = " ", /) -> te.Self: + return self.__class__(super().ljust(width, self.escape(fillchar))) + + def rjust(self, width: t.SupportsIndex, fillchar: str = " ", /) -> te.Self: + return self.__class__(super().rjust(width, self.escape(fillchar))) + + def lstrip(self, chars: str | None = None, /) -> te.Self: + return self.__class__(super().lstrip(chars)) + + def rstrip(self, chars: str | None = None, /) -> te.Self: + return self.__class__(super().rstrip(chars)) + + def center(self, width: t.SupportsIndex, fillchar: str = " ", /) -> te.Self: + return self.__class__(super().center(width, self.escape(fillchar))) + + def strip(self, chars: str | None = None, /) -> te.Self: + return self.__class__(super().strip(chars)) + + def translate( + self, + table: cabc.Mapping[int, str | int | None], # type: ignore[override] + /, + ) -> str: + return self.__class__(super().translate(table)) + + def expandtabs(self, /, tabsize: t.SupportsIndex = 8) -> te.Self: + return self.__class__(super().expandtabs(tabsize)) + + def swapcase(self, /) -> te.Self: + return self.__class__(super().swapcase()) + + def zfill(self, width: t.SupportsIndex, /) -> te.Self: + return self.__class__(super().zfill(width)) + + def casefold(self, /) -> te.Self: + return self.__class__(super().casefold()) + + def removeprefix(self, prefix: str, /) -> te.Self: + return self.__class__(super().removeprefix(prefix)) + + def removesuffix(self, suffix: str) -> te.Self: + return self.__class__(super().removesuffix(suffix)) + + def partition(self, sep: str, /) -> tuple[te.Self, te.Self, te.Self]: + left, sep, right = super().partition(sep) cls = self.__class__ - return cls(l), cls(s), cls(r) + return cls(left), cls(sep), cls(right) - def rpartition(self, sep: str) -> t.Tuple["te.Self", "te.Self", "te.Self"]: - l, s, r = super().rpartition(self.escape(sep)) + def rpartition(self, sep: str, /) -> tuple[te.Self, te.Self, te.Self]: + left, sep, right = super().rpartition(sep) cls = self.__class__ - return cls(l), cls(s), cls(r) + return cls(left), cls(sep), cls(right) - def format(self, *args: t.Any, **kwargs: t.Any) -> "te.Self": + def format(self, *args: t.Any, **kwargs: t.Any) -> te.Self: formatter = EscapeFormatter(self.escape) return self.__class__(formatter.vformat(self, args, kwargs)) - def format_map( # type: ignore[override] - self, map: t.Mapping[str, t.Any] - ) -> "te.Self": + def format_map( + self, + mapping: cabc.Mapping[str, t.Any], # type: ignore[override] + /, + ) -> te.Self: formatter = EscapeFormatter(self.escape) - return self.__class__(formatter.vformat(self, (), map)) + return self.__class__(formatter.vformat(self, (), mapping)) - def __html_format__(self, format_spec: str) -> "te.Self": + def __html_format__(self, format_spec: str, /) -> te.Self: if format_spec: raise ValueError("Unsupported format specification for Markup.") @@ -260,8 +332,8 @@ class Markup(str): class EscapeFormatter(string.Formatter): __slots__ = ("escape",) - def __init__(self, escape: t.Callable[[t.Any], Markup]) -> None: - self.escape = escape + def __init__(self, escape: _TPEscape) -> None: + self.escape: _TPEscape = escape super().__init__() def format_field(self, value: t.Any, format_spec: str) -> str: @@ -278,55 +350,46 @@ class EscapeFormatter(string.Formatter): 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)) + rv = super().format_field(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__"): - obj[key] = escape(value) - - return obj - - class _MarkupEscapeHelper: """Helper for :meth:`Markup.__mod__`.""" __slots__ = ("obj", "escape") - def __init__(self, obj: t.Any, escape: t.Callable[[t.Any], Markup]) -> None: - self.obj = obj - self.escape = escape + def __init__(self, obj: t.Any, escape: _TPEscape) -> None: + self.obj: t.Any = obj + self.escape: _TPEscape = escape - def __getitem__(self, item: t.Any) -> "te.Self": - return self.__class__(self.obj[item], self.escape) + def __getitem__(self, key: t.Any, /) -> te.Self: + return self.__class__(self.obj[key], self.escape) - def __str__(self) -> str: + def __str__(self, /) -> str: return str(self.escape(self.obj)) - def __repr__(self) -> str: + def __repr__(self, /) -> str: return str(self.escape(repr(self.obj))) - def __int__(self) -> int: + def __int__(self, /) -> int: return int(self.obj) - def __float__(self) -> float: + 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 -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 +def __getattr__(name: str) -> t.Any: + if name == "__version__": + import importlib.metadata + import warnings + + warnings.warn( + "The '__version__' attribute is deprecated and will be removed in" + " MarkupSafe 3.1. Use feature detection, or" + ' `importlib.metadata.version("markupsafe")`, instead.', + stacklevel=2, + ) + return importlib.metadata.version("markupsafe") + + raise AttributeError(name) diff --git a/lib/markupsafe/_native.py b/lib/markupsafe/_native.py index 8117b271..088b3bca 100644 --- a/lib/markupsafe/_native.py +++ b/lib/markupsafe/_native.py @@ -1,63 +1,8 @@ -import typing as t - -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. - """ - if hasattr(s, "__html__"): - return Markup(s.__html__()) - - return Markup( - str(s) - .replace("&", "&") +def _escape_inner(s: str, /) -> str: + return ( + 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('') - """ - 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("") - >>> 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) - - return s diff --git a/lib/markupsafe/_speedups.c b/lib/markupsafe/_speedups.c index 3c463fb8..09dd57ca 100644 --- a/lib/markupsafe/_speedups.c +++ b/lib/markupsafe/_speedups.c @@ -1,22 +1,5 @@ #include -static PyObject* markup; - -static int -init_constants(void) -{ - PyObject *module; - - /* import markup type so that we can mark the return value */ - module = PyImport_ImportModule("markupsafe"); - if (!module) - return 0; - markup = PyObject_GetAttrString(module, "Markup"); - Py_DECREF(module); - - return 1; -} - #define GET_DELTA(inp, inp_end, delta) \ while (inp < inp_end) { \ switch (*inp++) { \ @@ -166,135 +149,29 @@ escape_unicode_kind4(PyUnicodeObject *in) } static PyObject* -escape_unicode(PyUnicodeObject *in) +escape_unicode(PyObject *self, PyObject *s) { - if (PyUnicode_READY(in)) + if (!PyUnicode_Check(s)) return NULL; - switch (PyUnicode_KIND(in)) { + // This check is no longer needed in Python 3.12. + if (PyUnicode_READY(s)) + return NULL; + + switch (PyUnicode_KIND(s)) { case PyUnicode_1BYTE_KIND: - return escape_unicode_kind1(in); + return escape_unicode_kind1((PyUnicodeObject*) s); case PyUnicode_2BYTE_KIND: - return escape_unicode_kind2(in); + return escape_unicode_kind2((PyUnicodeObject*) s); case PyUnicode_4BYTE_KIND: - return escape_unicode_kind4(in); + return escape_unicode_kind4((PyUnicodeObject*) s); } assert(0); /* shouldn't happen */ return NULL; } -static PyObject* -escape(PyObject *self, PyObject *text) -{ - 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; - } - } - - /* we don't have to escape integers, bools or floats */ - if (PyLong_CheckExact(text) || - 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); - if (html) { - 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); - return rv; - } - - /* otherwise make the object unicode if it isn't, then escape */ - PyErr_Clear(); - if (!PyUnicode_Check(text)) { - PyObject *unicode = PyObject_Str(text); - if (!unicode) - return NULL; - s = escape_unicode((PyUnicodeObject*)unicode); - Py_DECREF(unicode); - } - else - s = escape_unicode((PyUnicodeObject*)text); - - /* convert the unicode string into a markup object. */ - rv = PyObject_CallFunctionObjArgs(markup, (PyObject*)s, NULL); - Py_DECREF(s); - return rv; -} - - -static PyObject* -escape_silent(PyObject *self, PyObject *text) -{ - if (text != Py_None) - return escape(self, text); - return PyObject_CallFunctionObjArgs(markup, NULL); -} - - -static PyObject* -soft_str(PyObject *self, PyObject *s) -{ - if (!PyUnicode_Check(s)) - return PyObject_Str(s); - Py_INCREF(s); - return 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(\"\")\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" - }, + {"_escape_inner", (PyCFunction)escape_unicode, METH_O, NULL}, {NULL, NULL, 0, NULL} /* Sentinel */ }; @@ -313,8 +190,15 @@ static struct PyModuleDef module_definition = { PyMODINIT_FUNC PyInit__speedups(void) { - if (!init_constants()) - return NULL; + PyObject *m = PyModule_Create(&module_definition); - return PyModule_Create(&module_definition); + if (m == NULL) { + return NULL; + } + + #ifdef Py_GIL_DISABLED + PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED); + #endif + + return m; } diff --git a/lib/markupsafe/_speedups.pyi b/lib/markupsafe/_speedups.pyi index f673240f..8c888585 100644 --- a/lib/markupsafe/_speedups.pyi +++ b/lib/markupsafe/_speedups.pyi @@ -1,9 +1 @@ -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: ... +def _escape_inner(s: str, /) -> str: ... diff --git a/requirements.txt b/requirements.txt index 92f7474e..ae5649d4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -20,7 +20,7 @@ importlib-metadata==8.5.0 importlib-resources==6.4.5 git+https://github.com/Tautulli/ipwhois.git@master#egg=ipwhois IPy==1.01 -Mako==1.3.5 +Mako==1.3.6 MarkupSafe==2.1.5 musicbrainzngs==0.7.1 packaging==24.1