Skip to content

Commit 312f2b7

Browse files
authored
Minor speed improvements and python 3.13 (#17)
* remove SafeString slots * remove duplicate autoplay * tuples * wip * wip * wip * wip * version
1 parent ea9bfc8 commit 312f2b7

File tree

3 files changed

+23
-16
lines changed

3 files changed

+23
-16
lines changed

.github/workflows/push.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ jobs:
66
strategy:
77
fail-fast: false
88
matrix:
9-
python-version: [3.8, 3.9, '3.10', '3.11', '3.12']
10-
poetry-version: [1.6.1]
9+
python-version: [3.8, 3.9, '3.10', '3.11', '3.12', '3.13']
10+
poetry-version: [1.8.4]
1111
os: [ubuntu-22.04, macos-latest, windows-latest]
1212
runs-on: ${{ matrix.os }}
1313
steps:

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "simple-html"
3-
version = "1.2.2"
3+
version = "1.2.3"
44
readme = "README.md"
55
description = "Template-less html rendering in Python"
66
authors = ["Keith Philpott <[email protected]>"]

simple_html/__init__.py

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
1-
from html import escape
21
from types import GeneratorType
32
from typing import Tuple, Union, Dict, List, FrozenSet, Generator, Iterable, Any, Callable
43

54

65
class SafeString:
7-
__slots__ = ("safe_str",)
8-
96
def __init__(self, safe_str: str) -> None:
107
self.safe_str = safe_str
118

@@ -19,6 +16,17 @@ def __repr__(self) -> str:
1916
return f"SafeString(safe_str='{self.safe_str}')"
2017

2118

19+
def faster_escape(s: str) -> str:
20+
"""
21+
This is nearly duplicate of html.escape in the standard lib.
22+
it's a little faster because:
23+
- we don't check if some of the replacements are desired
24+
- we don't re-assign a variable many times.
25+
"""
26+
return s.replace(
27+
"&", "&amp;" # Must be done first!
28+
).replace("<", "&lt;").replace(">", "&gt;").replace('"', "&quot;").replace('\'', "&#x27;")
29+
2230
Node = Union[
2331
str,
2432
SafeString,
@@ -31,10 +39,9 @@ def __repr__(self) -> str:
3139
TagTuple = Tuple[str, Tuple[Node, ...], str]
3240

3341
_common_safe_attribute_names: FrozenSet[str] = frozenset(
34-
{
42+
(
3543
"alt",
3644
"autoplay",
37-
"autoplay",
3845
"charset",
3946
"checked",
4047
"class",
@@ -80,13 +87,13 @@ def __repr__(self) -> str:
8087
"type",
8188
"value",
8289
"width",
83-
}
90+
)
8491
)
8592

8693

8794
def escape_attribute_key(k: str) -> str:
8895
return (
89-
escape(k, True)
96+
faster_escape(k)
9097
.replace("=", "&#x3D;")
9198
.replace("\\", "&#x5C;")
9299
.replace("`", "&#x60;")
@@ -134,7 +141,7 @@ def __call__(
134141
)
135142

136143
if isinstance(val, str):
137-
attrs += f' {key}="{escape(val, True)}"'
144+
attrs += f' {key}="{faster_escape(val)}"'
138145
elif isinstance(val, SafeString):
139146
attrs += f' {key}="{val.safe_str}"'
140147
elif val is None:
@@ -278,7 +285,7 @@ def _render(nodes: Iterable[Node], append_to_list: Callable[[str], None]) -> Non
278285
elif isinstance(node, SafeString):
279286
append_to_list(node.safe_str)
280287
elif isinstance(node, str):
281-
append_to_list(escape(node))
288+
append_to_list(faster_escape(node))
282289
elif isinstance(node, Tag):
283290
append_to_list(node.rendered)
284291
elif isinstance(node, list):
@@ -290,7 +297,7 @@ def _render(nodes: Iterable[Node], append_to_list: Callable[[str], None]) -> Non
290297

291298

292299
_common_safe_css_props = frozenset(
293-
{
300+
(
294301
"color",
295302
"border",
296303
"margin",
@@ -498,7 +505,7 @@ def _render(nodes: Iterable[Node], append_to_list: Callable[[str], None]) -> Non
498505
"word-wrap",
499506
"writing-mode",
500507
"z-index",
501-
}
508+
)
502509
)
503510

504511

@@ -511,12 +518,12 @@ def render_styles(
511518
if isinstance(k, SafeString):
512519
k = k.safe_str
513520
else:
514-
k = escape(k, True)
521+
k = faster_escape(k)
515522

516523
if isinstance(v, SafeString):
517524
v = v.safe_str
518525
elif isinstance(v, str):
519-
v = escape(v, True)
526+
v = faster_escape(v)
520527
# note that ints and floats pass through these condition checks
521528

522529
ret += f"{k}:{v};"

0 commit comments

Comments
 (0)