1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
|
From: Will McGugan <willmcgugan@gmail.com>
Date: Thu, 9 Oct 2025 09:35:09 +0100
Subject: Fix tests for Python 3.14
Origin: upstream, https://github.com/Textualize/rich/pull/3861/commits/655b5210cb1403100a646d167cf027eec760dd9f
Bug-Debian: https://bugs.debian.org/1123335
Last-Update: 2026-01-07
---
rich/style.py | 18 +++++++-----------
tests/test_inspect.py | 10 ++++++++++
tests/test_pretty.py | 5 +++++
tests/test_text.py | 7 ++++++-
4 files changed, 28 insertions(+), 12 deletions(-)
diff --git a/rich/style.py b/rich/style.py
index 262fd6e..0912542 100644
--- a/rich/style.py
+++ b/rich/style.py
@@ -1,6 +1,7 @@
import sys
from functools import lru_cache
-from marshal import dumps, loads
+from operator import attrgetter
+from pickle import dumps, loads
from random import randint
from typing import Any, Dict, Iterable, List, Optional, Type, Union, cast
@@ -9,6 +10,10 @@ from .color import Color, ColorParseError, ColorSystem, blend_rgb
from .repr import Result, rich_repr
from .terminal_theme import DEFAULT_TERMINAL_THEME, TerminalTheme
+_hash_getter = attrgetter(
+ "_color", "_bgcolor", "_attributes", "_set_attributes", "_link", "_meta"
+)
+
# Style instances and style definitions are often interchangeable
StyleType = Union[str, "Style"]
@@ -432,16 +437,7 @@ class Style:
def __hash__(self) -> int:
if self._hash is not None:
return self._hash
- self._hash = hash(
- (
- self._color,
- self._bgcolor,
- self._attributes,
- self._set_attributes,
- self._link,
- self._meta,
- )
- )
+ self._hash = hash(_hash_getter(self))
return self._hash
@property
diff --git a/tests/test_inspect.py b/tests/test_inspect.py
index 130e8df..3f6e5b9 100644
--- a/tests/test_inspect.py
+++ b/tests/test_inspect.py
@@ -43,6 +43,12 @@ skip_py313 = pytest.mark.skipif(
reason="rendered differently on py3.13",
)
+skip_py314 = pytest.mark.skipif(
+ sys.version_info.minor == 14 and sys.version_info.major == 3,
+ reason="rendered differently on py3.14",
+)
+
+
skip_pypy3 = pytest.mark.skipif(
hasattr(sys, "pypy_version_info"),
reason="rendered differently on pypy3",
@@ -139,6 +145,7 @@ def test_inspect_empty_dict():
assert render({}).startswith(expected)
+@skip_py314
@skip_py313
@skip_py312
@skip_py311
@@ -219,6 +226,7 @@ def test_inspect_integer_with_value():
@skip_py311
@skip_py312
@skip_py313
+@skip_py314
def test_inspect_integer_with_methods_python38_and_python39():
expected = (
"╭──────────────── <class 'int'> ─────────────────╮\n"
@@ -257,6 +265,7 @@ def test_inspect_integer_with_methods_python38_and_python39():
@skip_py311
@skip_py312
@skip_py313
+@skip_py314
def test_inspect_integer_with_methods_python310only():
expected = (
"╭──────────────── <class 'int'> ─────────────────╮\n"
@@ -299,6 +308,7 @@ def test_inspect_integer_with_methods_python310only():
@skip_py310
@skip_py312
@skip_py313
+@skip_py314
def test_inspect_integer_with_methods_python311():
# to_bytes and from_bytes methods on int had minor signature change -
# they now, as of 3.11, have default values for all of their parameters
diff --git a/tests/test_pretty.py b/tests/test_pretty.py
index 90be42f..29331d9 100644
--- a/tests/test_pretty.py
+++ b/tests/test_pretty.py
@@ -38,6 +38,10 @@ skip_py313 = pytest.mark.skipif(
sys.version_info.minor == 13 and sys.version_info.major == 3,
reason="rendered differently on py3.13",
)
+skip_py314 = pytest.mark.skipif(
+ sys.version_info.minor == 14 and sys.version_info.major == 3,
+ reason="rendered differently on py3.14",
+)
def test_install() -> None:
@@ -639,6 +643,7 @@ def test_attrs_empty() -> None:
@skip_py311
@skip_py312
@skip_py313
+@skip_py314
def test_attrs_broken() -> None:
@attr.define
class Foo:
diff --git a/tests/test_text.py b/tests/test_text.py
index fee7302..9258033 100644
--- a/tests/test_text.py
+++ b/tests/test_text.py
@@ -843,7 +843,12 @@ def test_assemble():
def test_assemble_meta():
text = Text.assemble("foo", ("bar", "bold"), meta={"foo": "bar"})
assert str(text) == "foobar"
- assert text._spans == [Span(3, 6, "bold"), Span(0, 6, Style(meta={"foo": "bar"}))]
+
+ spans = text._spans
+ expected = [Span(3, 6, "bold"), Span(0, 6, Style(meta={"foo": "bar"}))]
+
+ assert spans == expected
+
console = Console()
assert text.get_style_at_offset(console, 0).meta == {"foo": "bar"}
|