fix(plex): plain text survives a decimal reference too long to parse
int() refuses a decimal run past 4300 digits, so one such reference in a summary raised out of the sync and the text migration. Any number past seven significant digits is beyond U+10FFFF, so it becomes U+FFFD like any out-of-range reference; leading zeros are dropped first. The rails test's comment now says what it guards: both rails agree with the rollup.
This commit is contained in:
@@ -27,7 +27,14 @@ _REF = re.compile(r"&(?:#[0-9]+|#[xX][0-9a-fA-F]+|[A-Za-z][A-Za-z0-9]*);")
|
|||||||
|
|
||||||
def _decode(m: re.Match[str]) -> str:
|
def _decode(m: re.Match[str]) -> str:
|
||||||
ref = m.group()
|
ref = m.group()
|
||||||
return html.unescape(ref) if ref[1] == "#" or ref[1:] in html5 else ref
|
if ref[1] != "#":
|
||||||
|
return html.unescape(ref) if ref[1:] in html5 else ref
|
||||||
|
if ref[2] in "xX":
|
||||||
|
return html.unescape(ref)
|
||||||
|
# `int()` refuses a decimal run past 4300 digits, and any number past seven significant digits is
|
||||||
|
# beyond U+10FFFF, which the parser turns into U+FFFD anyway.
|
||||||
|
digits = ref[2:-1].lstrip("0") or "0"
|
||||||
|
return "�" if len(digits) > 7 else html.unescape(f"&#{digits};")
|
||||||
|
|
||||||
|
|
||||||
def plain_text(value: str | None) -> str | None:
|
def plain_text(value: str | None) -> str | None:
|
||||||
|
|||||||
@@ -168,8 +168,8 @@ def test_continue_watching_movies_and_shows(db, monkeypatch, override_dep):
|
|||||||
def test_a_continue_watching_show_says_whether_it_has_an_episode_to_resume(
|
def test_a_continue_watching_show_says_whether_it_has_an_episode_to_resume(
|
||||||
db, monkeypatch, override_dep
|
db, monkeypatch, override_dep
|
||||||
):
|
):
|
||||||
# Both in-progress rails (Discover's and Home's) take a show's card state from the one rollup:
|
# Both in-progress rails (Discover's and Home's) agree with the one rollup: a show part watched
|
||||||
# a show part watched with nothing to resume offers Play alone, not Continue + Restart.
|
# with nothing to resume offers Play alone, not Continue + Restart.
|
||||||
from app.discover.queries import plex_in_progress
|
from app.discover.queries import plex_in_progress
|
||||||
|
|
||||||
user = _seed(db)
|
user = _seed(db)
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ HU_SUMMARY = "<p>A műsorban minden párosnak stoppal kell eljutnia.</p>"
|
|||||||
# ...and only a whole entity name: a legacy one at its start ("¬", "&") is not.
|
# ...and only a whole entity name: a legacy one at its start ("¬", "&") is not.
|
||||||
("AT¬ice; and &x;", "AT¬ice; and &x;"),
|
("AT¬ice; and &x;", "AT¬ice; and &x;"),
|
||||||
("été ©", "été ©"),
|
("été ©", "été ©"),
|
||||||
|
# A decimal reference too long for int() to parse is out of range, like �.
|
||||||
|
("a &#" + "9" * 5000 + "; b", "a � b"),
|
||||||
|
("&#" + "0" * 5000 + "65;", "A"),
|
||||||
("Plain summary.", "Plain summary."),
|
("Plain summary.", "Plain summary."),
|
||||||
(" padded ", "padded"),
|
(" padded ", "padded"),
|
||||||
("<p></p>", None),
|
("<p></p>", None),
|
||||||
|
|||||||
Reference in New Issue
Block a user