Skip to content

Commit eed9aa0

Browse files
authored
Merge pull request #6121 from TomJGooding/build-update-supported-python-versions
build!: update supported Python versions
2 parents f1c6bec + 2ca685d commit eed9aa0

29 files changed

+1810
-1409
lines changed

.github/workflows/pythonpackage.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
strategy:
2121
matrix:
2222
os: [ubuntu-latest, windows-latest, macos-latest]
23-
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
23+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
2424
defaults:
2525
run:
2626
shell: bash
@@ -35,18 +35,18 @@ jobs:
3535
cache: "poetry"
3636
- name: Install dependencies
3737
run: poetry install --no-interaction --extras syntax
38-
if: ${{ matrix.python-version != '3.8' && matrix.python-version != '3.9' }}
39-
- name: Install dependencies for 3.8 and 3.9
38+
if: ${{ matrix.python-version != '3.9' }}
39+
- name: Install dependencies for 3.9
4040
run: poetry install --no-interaction
41-
if: ${{ matrix.python-version == '3.8' || matrix.python-version == '3.9' }}
41+
if: ${{ matrix.python-version == '3.9' }}
4242
- name: Test with pytest (Py310+ - with syntax highlighting)
4343
run: |
4444
poetry run pytest tests -v --cov=./src/textual --cov-report=xml:./coverage.xml --cov-report term-missing
45-
if: ${{ matrix.python-version != '3.8' && matrix.python-version != '3.9' }}
45+
if: ${{ matrix.python-version != '3.9' }}
4646
- name: Test with pytest (Py39 - without syntax highlighting)
4747
run: |
4848
poetry run pytest tests -v --cov=./src/textual --cov-report=xml:./coverage.xml --cov-report term-missing -m 'not syntax'
49-
if: ${{ matrix.python-version == '3.8' || matrix.python-version == '3.9' }}
49+
if: ${{ matrix.python-version == '3.9' }}
5050
- name: Upload snapshot report
5151
if: always()
5252
uses: actions/upload-artifact@v4

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](http://keepachangelog.com/)
66
and this project adheres to [Semantic Versioning](http://semver.org/).
77

8-
## Unreleased
8+
## [6.3.0] - 2025-10-11
99

1010
### Added
1111

@@ -15,6 +15,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1515

1616
- Fixed highlight not auto-detecting lexer https://github.com/Textualize/textual/pull/6167
1717

18+
### Changed
19+
20+
- Dropped support for Python3.8 https://github.com/Textualize/textual/pull/6121/
21+
- Added support for Python3.14 https://github.com/Textualize/textual/pull/6121/
22+
1823
## [6.2.1] - 2025-10-01
1924

2025
- Fix inability to copy text outside of an input/textarea when it was focused https://github.com/Textualize/textual/pull/6148
@@ -3144,6 +3149,7 @@ https://textual.textualize.io/blog/2022/11/08/version-040/#version-040
31443149
- New handler system for messages that doesn't require inheritance
31453150
- Improved traceback handling
31463151

3152+
[6.3.0]: https://github.com/Textualize/textual/compare/v6.2.1...v6.3.0
31473153
[6.2.1]: https://github.com/Textualize/textual/compare/v6.2.0...v6.2.1
31483154
[6.2.0]: https://github.com/Textualize/textual/compare/v6.1.0...v6.2.0
31493155
[6.1.0]: https://github.com/Textualize/textual/compare/v6.0.0...v6.1.0

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22

33
[![Discord](https://img.shields.io/discord/1026214085173461072)](https://discord.gg/Enf6Z3qhVr)
4-
[![Supported Python Versions](https://img.shields.io/pypi/pyversions/textual/1.0.0)](https://pypi.org/project/textual/)
4+
[![Supported Python Versions](https://img.shields.io/pypi/pyversions/textual)](https://pypi.org/project/textual/)
55
[![PyPI version](https://badge.fury.io/py/textual.svg?)](https://badge.fury.io/py/textual)
66
![OS support](https://img.shields.io/badge/OS-macOS%20Linux%20Windows-red)
77

docs/getting_started.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ All you need to get started building Textual apps.
33

44
## Requirements
55

6-
Textual requires Python 3.8 or later (if you have a choice, pick the most recent Python). Textual runs on Linux, macOS, Windows and probably any OS where Python also runs.
6+
Textual requires Python 3.9 or later (if you have a choice, pick the most recent Python). Textual runs on Linux, macOS, Windows and probably any OS where Python also runs.
77

88
!!! info "Your platform"
99

poetry.lock

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

pyproject.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "textual"
3-
version = "6.2.1"
3+
version = "6.3.0"
44
homepage = "https://github.com/Textualize/textual"
55
repository = "https://github.com/Textualize/textual"
66
documentation = "https://textual.textualize.io/"
@@ -17,12 +17,12 @@ classifiers = [
1717
"Operating System :: Microsoft :: Windows :: Windows 11",
1818
"Operating System :: MacOS",
1919
"Operating System :: POSIX :: Linux",
20-
"Programming Language :: Python :: 3.8",
2120
"Programming Language :: Python :: 3.9",
2221
"Programming Language :: Python :: 3.10",
2322
"Programming Language :: Python :: 3.11",
2423
"Programming Language :: Python :: 3.12",
2524
"Programming Language :: Python :: 3.13",
25+
"Programming Language :: Python :: 3.14",
2626
"Typing :: Typed",
2727
]
2828
include = [
@@ -41,12 +41,12 @@ include = [
4141
"Bug Tracker" = "https://github.com/Textualize/textual/issues"
4242

4343
[tool.ruff]
44-
target-version = "py38"
44+
target-version = "py39"
4545

4646
[tool.poetry.dependencies]
47-
python = "^3.8.1"
47+
python = "^3.9"
4848
markdown-it-py = { extras = ["plugins", "linkify"], version = ">=2.1.0" }
49-
rich = ">=13.3.3"
49+
rich = ">=14.2.0"
5050
#rich = {path="../rich", develop=true}
5151
typing-extensions = "^4.4.0"
5252
platformdirs = ">=3.6.0,<5"

tests/snapshot_tests/__snapshots__/test_snapshots/test_textual_dev_keys_preview.svg

Lines changed: 69 additions & 69 deletions
Loading

tests/test_arrange.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@
77
from textual.widget import Widget
88

99

10-
def test_arrange_empty():
10+
async def test_arrange_empty():
1111
container = Widget(id="container")
1212

1313
result = arrange(container, [], Size(80, 24), Size(80, 24))
1414
assert result.placements == []
1515
assert result.widgets == set()
1616

1717

18-
def test_arrange_dock_top():
18+
async def test_arrange_dock_top():
1919
container = Widget(id="container")
2020
container._parent = App()
2121
child = Widget(id="child")
@@ -36,7 +36,7 @@ def test_arrange_dock_top():
3636
assert result.widgets == {child, header}
3737

3838

39-
def test_arrange_dock_left():
39+
async def test_arrange_dock_left():
4040
container = Widget(id="container")
4141
container._parent = App()
4242
child = Widget(id="child")
@@ -61,7 +61,7 @@ def test_arrange_dock_left():
6161
assert result.widgets == {child, header}
6262

6363

64-
def test_arrange_dock_right():
64+
async def test_arrange_dock_right():
6565
container = Widget(id="container")
6666
container._parent = App()
6767
child = Widget(id="child")
@@ -86,7 +86,7 @@ def test_arrange_dock_right():
8686
assert result.widgets == {child, header}
8787

8888

89-
def test_arrange_dock_bottom():
89+
async def test_arrange_dock_bottom():
9090
container = Widget(id="container")
9191
container._parent = App()
9292
child = Widget(id="child")
@@ -111,7 +111,7 @@ def test_arrange_dock_bottom():
111111
assert result.widgets == {child, header}
112112

113113

114-
def test_arrange_dock_badly():
114+
async def test_arrange_dock_badly():
115115
child = Widget(id="child")
116116
child.styles.dock = "nowhere"
117117
with pytest.raises(AssertionError):

tests/test_border.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def test_border_render_row():
3131
]
3232

3333

34-
def test_border_title_single_line():
34+
async def test_border_title_single_line():
3535
"""The border_title gets set to a single line even when multiple lines are provided."""
3636
widget = Widget()
3737

@@ -59,7 +59,7 @@ def test_border_title_single_line():
5959
assert widget.border_title == "[bold]Hello World[/bold]"
6060

6161

62-
def test_border_subtitle_single_line():
62+
async def test_border_subtitle_single_line():
6363
"""The border_subtitle gets set to a single line even when multiple lines are provided."""
6464
widget = Widget()
6565

tests/test_box_model.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from textual.widget import Widget
88

99

10-
def test_content_box():
10+
async def test_content_box():
1111
one = Fraction(1)
1212

1313
class TestWidget(Widget):
@@ -44,7 +44,7 @@ def get_content_height(self, container: Size, parent: Size) -> int:
4444
assert box_model == BoxModel(Fraction(14), Fraction(12), Spacing(0, 0, 0, 0))
4545

4646

47-
def test_width():
47+
async def test_width():
4848
"""Test width settings."""
4949

5050
one = Fraction(1)
@@ -93,7 +93,7 @@ def get_content_height(self, container: Size, parent: Size, width: int) -> int:
9393
assert box_model == BoxModel(Fraction(27), Fraction(16), Spacing(1, 2, 3, 4))
9494

9595

96-
def test_height():
96+
async def test_height():
9797
"""Test height settings."""
9898

9999
one = Fraction(1)
@@ -143,7 +143,7 @@ def get_content_height(self, container: Size, parent: Size, width: int) -> int:
143143
assert box_model == BoxModel(Fraction(54), Fraction(8), Spacing(1, 2, 3, 4))
144144

145145

146-
def test_max():
146+
async def test_max():
147147
"""Check that max_width and max_height are respected."""
148148
one = Fraction(1)
149149

@@ -166,7 +166,7 @@ def get_content_height(self, container: Size, parent: Size, width: int) -> int:
166166
assert box_model == BoxModel(Fraction(40), Fraction(30), Spacing(0, 0, 0, 0))
167167

168168

169-
def test_min():
169+
async def test_min():
170170
"""Check that min_width and min_height are respected."""
171171

172172
one = Fraction(1)

0 commit comments

Comments
 (0)