Skip to content

Commit cd5074f

Browse files
authored
Merge pull request #3861 from Textualize/python314
bump for Python3.14
2 parents ea9d4db + 041406c commit cd5074f

File tree

8 files changed

+262
-168
lines changed

8 files changed

+262
-168
lines changed

.github/workflows/pythonpackage.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ jobs:
99
fail-fast: false
1010
matrix:
1111
os: [windows-latest, ubuntu-latest, macos-latest]
12-
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
12+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
1313
exclude:
1414
- { os: windows-latest, python-version: "3.13" }
1515
defaults:

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [14.2.0] - 2025-10-09
9+
10+
### Changed
11+
12+
- Python3.14 compatibility https://github.com/Textualize/rich/pull/3861
813

914
## [14.1.0] - 2025-06-25
1015

poetry.lock

Lines changed: 226 additions & 153 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "rich"
33
homepage = "https://github.com/Textualize/rich"
44
documentation = "https://rich.readthedocs.io/en/latest/"
5-
version = "14.1.0"
5+
version = "14.2.0"
66
description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
77
authors = ["Will McGugan <[email protected]>"]
88
license = "MIT"
@@ -21,6 +21,7 @@ classifiers = [
2121
"Programming Language :: Python :: 3.11",
2222
"Programming Language :: Python :: 3.12",
2323
"Programming Language :: Python :: 3.13",
24+
"Programming Language :: Python :: 3.14",
2425
"Typing :: Typed",
2526
]
2627
include = ["rich/py.typed"]
@@ -42,7 +43,6 @@ mypy = "^1.11"
4243
pytest-cov = "^3.0.0"
4344
attrs = "^21.4.0"
4445
pre-commit = "^2.17.0"
45-
asv = "^0.5.1"
4646
typing-extensions = ">=4.0.0, <5.0"
4747

4848
[build-system]

rich/style.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import sys
22
from functools import lru_cache
3-
from marshal import dumps, loads
3+
from operator import attrgetter
4+
from pickle import dumps, loads
45
from random import randint
56
from typing import Any, Dict, Iterable, List, Optional, Type, Union, cast
67

@@ -9,6 +10,10 @@
910
from .repr import Result, rich_repr
1011
from .terminal_theme import DEFAULT_TERMINAL_THEME, TerminalTheme
1112

13+
_hash_getter = attrgetter(
14+
"_color", "_bgcolor", "_attributes", "_set_attributes", "_link", "_meta"
15+
)
16+
1217
# Style instances and style definitions are often interchangeable
1318
StyleType = Union[str, "Style"]
1419

@@ -432,16 +437,7 @@ def __ne__(self, other: Any) -> bool:
432437
def __hash__(self) -> int:
433438
if self._hash is not None:
434439
return self._hash
435-
self._hash = hash(
436-
(
437-
self._color,
438-
self._bgcolor,
439-
self._attributes,
440-
self._set_attributes,
441-
self._link,
442-
self._meta,
443-
)
444-
)
440+
self._hash = hash(_hash_getter(self))
445441
return self._hash
446442

447443
@property

tests/test_inspect.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@
4343
reason="rendered differently on py3.13",
4444
)
4545

46+
skip_py314 = pytest.mark.skipif(
47+
sys.version_info.minor == 14 and sys.version_info.major == 3,
48+
reason="rendered differently on py3.14",
49+
)
50+
51+
4652
skip_pypy3 = pytest.mark.skipif(
4753
hasattr(sys, "pypy_version_info"),
4854
reason="rendered differently on pypy3",
@@ -139,6 +145,7 @@ def test_inspect_empty_dict():
139145
assert render({}).startswith(expected)
140146

141147

148+
@skip_py314
142149
@skip_py313
143150
@skip_py312
144151
@skip_py311
@@ -219,6 +226,7 @@ def test_inspect_integer_with_value():
219226
@skip_py311
220227
@skip_py312
221228
@skip_py313
229+
@skip_py314
222230
def test_inspect_integer_with_methods_python38_and_python39():
223231
expected = (
224232
"╭──────────────── <class 'int'> ─────────────────╮\n"
@@ -257,6 +265,7 @@ def test_inspect_integer_with_methods_python38_and_python39():
257265
@skip_py311
258266
@skip_py312
259267
@skip_py313
268+
@skip_py314
260269
def test_inspect_integer_with_methods_python310only():
261270
expected = (
262271
"╭──────────────── <class 'int'> ─────────────────╮\n"
@@ -299,6 +308,7 @@ def test_inspect_integer_with_methods_python310only():
299308
@skip_py310
300309
@skip_py312
301310
@skip_py313
311+
@skip_py314
302312
def test_inspect_integer_with_methods_python311():
303313
# to_bytes and from_bytes methods on int had minor signature change -
304314
# they now, as of 3.11, have default values for all of their parameters

tests/test_pretty.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@
3838
sys.version_info.minor == 13 and sys.version_info.major == 3,
3939
reason="rendered differently on py3.13",
4040
)
41+
skip_py314 = pytest.mark.skipif(
42+
sys.version_info.minor == 14 and sys.version_info.major == 3,
43+
reason="rendered differently on py3.14",
44+
)
4145

4246

4347
def test_install() -> None:
@@ -639,6 +643,7 @@ class Nada:
639643
@skip_py311
640644
@skip_py312
641645
@skip_py313
646+
@skip_py314
642647
def test_attrs_broken() -> None:
643648
@attr.define
644649
class Foo:

tests/test_text.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -843,7 +843,12 @@ def test_assemble():
843843
def test_assemble_meta():
844844
text = Text.assemble("foo", ("bar", "bold"), meta={"foo": "bar"})
845845
assert str(text) == "foobar"
846-
assert text._spans == [Span(3, 6, "bold"), Span(0, 6, Style(meta={"foo": "bar"}))]
846+
847+
spans = text._spans
848+
expected = [Span(3, 6, "bold"), Span(0, 6, Style(meta={"foo": "bar"}))]
849+
850+
assert spans == expected
851+
847852
console = Console()
848853
assert text.get_style_at_offset(console, 0).meta == {"foo": "bar"}
849854

0 commit comments

Comments
 (0)