Skip to content

Commit 74c7dc5

Browse files
committed
Bumped the minimum Python version to 3.10
Python <=3.9 are EOL.
1 parent 636b679 commit 74c7dc5

File tree

16 files changed

+83
-83
lines changed

16 files changed

+83
-83
lines changed

.github/workflows/ci.yml

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

1414
strategy:
1515
matrix:
16-
python-version: ["3.8", "3.9", "3.10", "3.11", "pypy-3.10"]
16+
python-version: ["3.10", "3.11", "3.12", "3.13", "pypy-3.10"]
1717

1818
steps:
1919
- uses: "actions/checkout@v2"

README

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
| |_) || |_| || |_| __/
1010
| .__/ \__, | \__|\___|
1111
| | __/ |
12-
|_| |___/ 0.8.2
12+
|_| |___/ 0.8.3dev
1313

1414

1515
What is ``pyte``?

benchmark.py

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

3030

3131
def make_benchmark(path, screen_cls):
32-
with io.open(path, "rt", encoding="utf-8") as handle:
32+
with open(path, encoding="utf-8") as handle:
3333
data = handle.read()
3434

3535
stream = pyte.Stream(screen_cls(80, 24))

docs/conf.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,17 @@
4242
master_doc = 'index'
4343

4444
# General information about the project.
45-
project = u'pyte'
46-
copyright = u'2011-2012 Selectel, 2012-2017 pyte authors and contributors'
45+
project = 'pyte'
46+
copyright = '2011-2012 Selectel, 2012-2025 pyte authors and contributors'
4747

4848
# The version info for the project you're documenting, acts as replacement for
4949
# |version| and |release|, also used in various other places throughout the
5050
# built documents.
5151
#
5252
# The short X.Y version.
53-
version = '0.8.2'
53+
version = '0.8.3'
5454
# The full version, including alpha/beta/rc tags.
55-
release = '0.8.2'
55+
release = '0.8.3dev'
5656

5757
# The language for content autogenerated by Sphinx. Refer to documentation
5858
# for a list of supported languages.

examples/helloworld.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@
1717
stream.feed("Hello World!")
1818

1919
for idx, line in enumerate(screen.display, 1):
20-
print("{0:2d} {1} ¶".format(idx, line))
20+
print(f"{idx:2d} {line} ¶")

examples/history.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def print_screen(screen, text):
2121
print(pyte.control.ESC + pyte.escape.RIS)
2222

2323
for idx, line in enumerate(screen.display, 1):
24-
print("{0:2d} {1} ¶".format(idx, line))
24+
print(f"{idx:2d} {line} ¶")
2525

2626
input(os.linesep + os.linesep + text)
2727

examples/terminal_emulator.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@ def __init__(self, lines):
3333
self.lines = lines
3434

3535
def __rich_console__(self, console, options):
36-
for line in self.lines:
37-
yield line
36+
yield from self.lines
3837

3938

4039
class Terminal(Widget, can_focus=True):

pyte/__init__.py

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

3434

3535
if __debug__:
36-
def dis(chars: Union[bytes, str]) -> None:
36+
def dis(chars: bytes | str) -> None:
3737
"""A :func:`dis.dis` for terminals.
3838
3939
>>> dis(b"\x07") # doctest: +NORMALIZE_WHITESPACE

pyte/graphics.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,4 +143,4 @@
143143
v = 8 + i * 10
144144
_FG_BG_256.append((v, v, v))
145145

146-
FG_BG_256 = ["{0:02x}{1:02x}{2:02x}".format(r, g, b) for r, g, b in _FG_BG_256]
146+
FG_BG_256 = [f"{r:02x}{g:02x}{b:02x}" for r, g, b in _FG_BG_256]

pyte/screens.py

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@
3535
import warnings
3636
from collections import deque, defaultdict
3737
from functools import lru_cache
38-
from typing import Any, Callable, Dict, Generator, List, NamedTuple, Optional, Set, Sequence, TextIO, TypeVar
38+
from typing import Any, Dict, List, NamedTuple, Optional, Set, TextIO, TypeVar
39+
from collections.abc import Callable, Generator, Sequence
3940

4041
from wcwidth import wcwidth as _wcwidth # type: ignore[import-untyped]
4142

@@ -115,7 +116,7 @@ def __init__(self, x: int, y: int, attrs: Char = Char(" ")) -> None:
115116
self.hidden = False
116117

117118

118-
class StaticDefaultDict(Dict[KT, VT]):
119+
class StaticDefaultDict(dict[KT, VT]):
119120
"""A :func:`dict` with a static default value.
120121
121122
Unlike :func:`collections.defaultdict` this implementation does not
@@ -134,7 +135,7 @@ def __missing__(self, key: KT) -> VT:
134135
return self.default
135136

136137

137-
_DEFAULT_MODE = set([mo.DECAWM, mo.DECTCEM])
138+
_DEFAULT_MODE = {mo.DECAWM, mo.DECTCEM}
138139

139140

140141
class Screen:
@@ -214,23 +215,23 @@ def default_char(self) -> Char:
214215
return Char(data=" ", fg="default", bg="default", reverse=reverse)
215216

216217
def __init__(self, columns: int, lines: int) -> None:
217-
self.savepoints: List[Savepoint] = []
218+
self.savepoints: list[Savepoint] = []
218219
self.columns = columns
219220
self.lines = lines
220-
self.buffer: Dict[int, StaticDefaultDict[int, Char]] = defaultdict(lambda: StaticDefaultDict[int, Char](self.default_char))
221-
self.dirty: Set[int] = set()
221+
self.buffer: dict[int, StaticDefaultDict[int, Char]] = defaultdict(lambda: StaticDefaultDict[int, Char](self.default_char))
222+
self.dirty: set[int] = set()
222223
self.reset()
223224
self.mode = _DEFAULT_MODE.copy()
224-
self.margins: Optional[Margins] = None
225+
self.margins: Margins | None = None
225226

226227
def __repr__(self) -> str:
227-
return ("{0}({1}, {2})".format(self.__class__.__name__,
228+
return ("{}({}, {})".format(self.__class__.__name__,
228229
self.columns, self.lines))
229230

230231
@property
231-
def display(self) -> List[str]:
232+
def display(self) -> list[str]:
232233
"""A :func:`list` of screen lines as unicode strings."""
233-
def render(line: StaticDefaultDict[int, Char]) -> Generator[str, None, None]:
234+
def render(line: StaticDefaultDict[int, Char]) -> Generator[str]:
234235
is_wide_char = False
235236
for x in range(self.columns):
236237
if is_wide_char: # Skip stub
@@ -281,9 +282,9 @@ def reset(self) -> None:
281282
self.cursor = Cursor(0, 0)
282283
self.cursor_position()
283284

284-
self.saved_columns: Optional[int] = None
285+
self.saved_columns: int | None = None
285286

286-
def resize(self, lines: Optional[int] = None, columns: Optional[int] = None) -> None:
287+
def resize(self, lines: int | None = None, columns: int | None = None) -> None:
287288
"""Resize the screen to the given size.
288289
289290
If the requested screen size has more lines than the existing
@@ -324,7 +325,7 @@ def resize(self, lines: Optional[int] = None, columns: Optional[int] = None) ->
324325
self.lines, self.columns = lines, columns
325326
self.set_margins()
326327

327-
def set_margins(self, top: Optional[int] = None, bottom: Optional[int] = None) -> None:
328+
def set_margins(self, top: int | None = None, bottom: int | None = None) -> None:
328329
"""Select top and bottom margins for the scrolling region.
329330
330331
:param int top: the smallest line number that is scrolled.
@@ -638,7 +639,7 @@ def restore_cursor(self) -> None:
638639
self.reset_mode(mo.DECOM)
639640
self.cursor_position()
640641

641-
def insert_lines(self, count: Optional[int] = None) -> None:
642+
def insert_lines(self, count: int | None = None) -> None:
642643
"""Insert the indicated # of lines at line with cursor. Lines
643644
displayed **at** and below the cursor move down. Lines moved
644645
past the bottom margin are lost.
@@ -658,7 +659,7 @@ def insert_lines(self, count: Optional[int] = None) -> None:
658659

659660
self.carriage_return()
660661

661-
def delete_lines(self, count: Optional[int] = None) -> None:
662+
def delete_lines(self, count: int | None = None) -> None:
662663
"""Delete the indicated # of lines, starting at line with
663664
cursor. As lines are deleted, lines displayed below cursor
664665
move up. Lines added to bottom of screen have spaces with same
@@ -681,7 +682,7 @@ def delete_lines(self, count: Optional[int] = None) -> None:
681682

682683
self.carriage_return()
683684

684-
def insert_characters(self, count: Optional[int] = None) -> None:
685+
def insert_characters(self, count: int | None = None) -> None:
685686
"""Insert the indicated # of blank characters at the cursor
686687
position. The cursor does not move and remains at the beginning
687688
of the inserted blank characters. Data on the line is shifted
@@ -698,7 +699,7 @@ def insert_characters(self, count: Optional[int] = None) -> None:
698699
line[x + count] = line[x]
699700
line.pop(x, None)
700701

701-
def delete_characters(self, count: Optional[int] = None) -> None:
702+
def delete_characters(self, count: int | None = None) -> None:
702703
"""Delete the indicated # of characters, starting with the
703704
character at cursor position. When a character is deleted, all
704705
characters to the right of cursor move left. Character attributes
@@ -716,7 +717,7 @@ def delete_characters(self, count: Optional[int] = None) -> None:
716717
else:
717718
line.pop(x, None)
718719

719-
def erase_characters(self, count: Optional[int] = None) -> None:
720+
def erase_characters(self, count: int | None = None) -> None:
720721
"""Erase the indicated # of characters, starting with the
721722
character at cursor position. Character attributes are set
722723
cursor attributes. The cursor remains in the same position.
@@ -828,7 +829,7 @@ def ensure_hbounds(self) -> None:
828829
"""Ensure the cursor is within horizontal screen bounds."""
829830
self.cursor.x = min(max(0, self.cursor.x), self.columns - 1)
830831

831-
def ensure_vbounds(self, use_margins: Optional[bool] = None) -> None:
832+
def ensure_vbounds(self, use_margins: bool | None = None) -> None:
832833
"""Ensure the cursor is within vertical screen bounds.
833834
834835
:param bool use_margins: when ``True`` or when
@@ -843,7 +844,7 @@ def ensure_vbounds(self, use_margins: Optional[bool] = None) -> None:
843844

844845
self.cursor.y = min(max(top, self.cursor.y), bottom)
845846

846-
def cursor_up(self, count: Optional[int] = None) -> None:
847+
def cursor_up(self, count: int | None = None) -> None:
847848
"""Move cursor up the indicated # of lines in same column.
848849
Cursor stops at top margin.
849850
@@ -852,7 +853,7 @@ def cursor_up(self, count: Optional[int] = None) -> None:
852853
top, _bottom = self.margins or Margins(0, self.lines - 1)
853854
self.cursor.y = max(self.cursor.y - (count or 1), top)
854855

855-
def cursor_up1(self, count: Optional[int] = None) -> None:
856+
def cursor_up1(self, count: int | None = None) -> None:
856857
"""Move cursor up the indicated # of lines to column 1. Cursor
857858
stops at bottom margin.
858859
@@ -861,7 +862,7 @@ def cursor_up1(self, count: Optional[int] = None) -> None:
861862
self.cursor_up(count)
862863
self.carriage_return()
863864

864-
def cursor_down(self, count: Optional[int] = None) -> None:
865+
def cursor_down(self, count: int | None = None) -> None:
865866
"""Move cursor down the indicated # of lines in same column.
866867
Cursor stops at bottom margin.
867868
@@ -870,7 +871,7 @@ def cursor_down(self, count: Optional[int] = None) -> None:
870871
_top, bottom = self.margins or Margins(0, self.lines - 1)
871872
self.cursor.y = min(self.cursor.y + (count or 1), bottom)
872873

873-
def cursor_down1(self, count: Optional[int] = None) -> None:
874+
def cursor_down1(self, count: int | None = None) -> None:
874875
"""Move cursor down the indicated # of lines to column 1.
875876
Cursor stops at bottom margin.
876877
@@ -879,7 +880,7 @@ def cursor_down1(self, count: Optional[int] = None) -> None:
879880
self.cursor_down(count)
880881
self.carriage_return()
881882

882-
def cursor_back(self, count: Optional[int] = None) -> None:
883+
def cursor_back(self, count: int | None = None) -> None:
883884
"""Move cursor left the indicated # of columns. Cursor stops
884885
at left margin.
885886
@@ -893,7 +894,7 @@ def cursor_back(self, count: Optional[int] = None) -> None:
893894
self.cursor.x -= count or 1
894895
self.ensure_hbounds()
895896

896-
def cursor_forward(self, count: Optional[int] = None) -> None:
897+
def cursor_forward(self, count: int | None = None) -> None:
897898
"""Move cursor right the indicated # of columns. Cursor stops
898899
at right margin.
899900
@@ -902,7 +903,7 @@ def cursor_forward(self, count: Optional[int] = None) -> None:
902903
self.cursor.x += count or 1
903904
self.ensure_hbounds()
904905

905-
def cursor_position(self, line: Optional[int] = None, column: Optional[int] = None) -> None:
906+
def cursor_position(self, line: int | None = None, column: int | None = None) -> None:
906907
"""Set the cursor to a specific `line` and `column`.
907908
908909
Cursor is allowed to move out of the scrolling region only when
@@ -929,15 +930,15 @@ def cursor_position(self, line: Optional[int] = None, column: Optional[int] = No
929930
self.ensure_hbounds()
930931
self.ensure_vbounds()
931932

932-
def cursor_to_column(self, column: Optional[int] = None) -> None:
933+
def cursor_to_column(self, column: int | None = None) -> None:
933934
"""Move cursor to a specific column in the current line.
934935
935936
:param int column: column number to move the cursor to.
936937
"""
937938
self.cursor.x = (column or 1) - 1
938939
self.ensure_hbounds()
939940

940-
def cursor_to_line(self, line: Optional[int] = None) -> None:
941+
def cursor_to_line(self, line: int | None = None) -> None:
941942
"""Move cursor to a specific line in the current column.
942943
943944
:param int line: line number to move the cursor to.
@@ -1008,7 +1009,7 @@ def select_graphic_rendition(self, *attrs: int) -> None:
10081009
# This is somewhat non-standard but is nonetheless
10091010
# supported in quite a few terminals. See discussion
10101011
# here https://gist.github.com/XVilka/8346728.
1011-
replace[key] = "{0:02x}{1:02x}{2:02x}".format(
1012+
replace[key] = "{:02x}{:02x}{:02x}".format(
10121013
attrs_list.pop(), attrs_list.pop(), attrs_list.pop())
10131014
except IndexError:
10141015
pass
@@ -1048,7 +1049,7 @@ def report_device_status(self, mode: int) -> None:
10481049
if mo.DECOM in self.mode:
10491050
assert self.margins is not None
10501051
y -= self.margins.top
1051-
self.write_process_input(ctrl.CSI + "{0};{1}R".format(y, x))
1052+
self.write_process_input(ctrl.CSI + f"{y};{x}R")
10521053

10531054
def write_process_input(self, data: str) -> None:
10541055
"""Write data to the process running inside the terminal.
@@ -1085,7 +1086,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:
10851086
"``Screen`` and will be removed in 0.8.0. Please update "
10861087
"your code accordingly.", DeprecationWarning)
10871088

1088-
super(DiffScreen, self).__init__(*args, **kwargs)
1089+
super().__init__(*args, **kwargs)
10891090

10901091

10911092
class History(NamedTuple):
@@ -1145,7 +1146,7 @@ def __init__(self, columns: int, lines: int, history: int = 100, ratio: float =
11451146
history,
11461147
history)
11471148

1148-
super(HistoryScreen, self).__init__(columns, lines)
1149+
super().__init__(columns, lines)
11491150

11501151
def _make_wrapper(self, event: str, handler: Callable[..., Any]) -> Callable[..., Any]:
11511152
def inner(*args: Any, **kwargs: Any) -> Any:
@@ -1156,7 +1157,7 @@ def inner(*args: Any, **kwargs: Any) -> Any:
11561157
return inner
11571158

11581159
def __getattribute__(self, attr: str) -> Callable[..., Any]:
1159-
value = super(HistoryScreen, self).__getattribute__(attr)
1160+
value = super().__getattribute__(attr)
11601161
if attr in HistoryScreen._wrapped:
11611162
return HistoryScreen._make_wrapper(self, attr, value)
11621163
else:
@@ -1202,12 +1203,12 @@ def reset(self) -> None:
12021203
is reset to bottom of both queues; queues themselves are
12031204
emptied.
12041205
"""
1205-
super(HistoryScreen, self).reset()
1206+
super().reset()
12061207
self._reset_history()
12071208

12081209
def erase_in_display(self, how: int = 0, *args: Any, **kwargs: Any) -> None:
12091210
"""Overloaded to reset history state."""
1210-
super(HistoryScreen, self).erase_in_display(how, *args, **kwargs)
1211+
super().erase_in_display(how, *args, **kwargs)
12111212

12121213
if how == 3:
12131214
self._reset_history()
@@ -1219,7 +1220,7 @@ def index(self) -> None:
12191220
if self.cursor.y == bottom:
12201221
self.history.top.append(self.buffer[top])
12211222

1222-
super(HistoryScreen, self).index()
1223+
super().index()
12231224

12241225
def reverse_index(self) -> None:
12251226
"""Overloaded to update bottom history with the removed lines."""
@@ -1228,7 +1229,7 @@ def reverse_index(self) -> None:
12281229
if self.cursor.y == top:
12291230
self.history.bottom.append(self.buffer[bottom])
12301231

1231-
super(HistoryScreen, self).reverse_index()
1232+
super().reverse_index()
12321233

12331234
def prev_page(self) -> None:
12341235
"""Move the screen page up through the history buffer. Page
@@ -1332,7 +1333,7 @@ def wrapper(*args: Any, **kwargs: Any) -> None:
13321333

13331334
def __getattribute__(self, attr: str) -> Callable[..., None]:
13341335
if attr not in Stream.events:
1335-
return super(DebugScreen, self).__getattribute__(attr) # type: ignore[no-any-return]
1336+
return super().__getattribute__(attr) # type: ignore[no-any-return]
13361337
elif not self.only or attr in self.only:
13371338
return self.only_wrapper(attr)
13381339
else:

0 commit comments

Comments
 (0)