Skip to content

Commit 64a4edd

Browse files
committed
Upgrade code to Python 3.9
1 parent 415d79c commit 64a4edd

15 files changed

+84
-89
lines changed

curtsies/configfile_keynames.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
class KeyMap:
1616
"""Maps config file key syntax to Curtsies names"""
1717

18-
def __getitem__(self, key: str) -> Tuple[str, ...]:
18+
def __getitem__(self, key: str) -> tuple[str, ...]:
1919
if not key: # Unbound key
2020
return ()
2121
elif key in SPECIALS:

curtsies/escseqparse.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@
1111

1212
from typing import (
1313
List,
14-
Mapping,
1514
Union,
1615
Tuple,
17-
Match,
1816
cast,
1917
Dict,
2018
Any,
2119
Optional,
2220
)
21+
from collections.abc import Mapping
22+
from re import Match
2323

2424
import re
2525

@@ -34,14 +34,14 @@
3434
)
3535

3636

37-
Token = Dict[str, Union[str, List[int]]]
37+
Token = dict[str, Union[str, list[int]]]
3838

3939

4040
def remove_ansi(s: str) -> str:
4141
return re.sub(r"(\x9B|\x1B\[)[0-?]*[ -\/]*[@-~]", "", s)
4242

4343

44-
def parse(s: str) -> List[Union[str, Dict[str, Union[str, bool, None]]]]:
44+
def parse(s: str) -> list[Union[str, dict[str, Union[str, bool, None]]]]:
4545
r"""
4646
Returns a list of strings or format dictionaries to describe the strings.
4747
@@ -52,7 +52,7 @@ def parse(s: str) -> List[Union[str, Dict[str, Union[str, bool, None]]]]:
5252
>>> parse("\x1b[33m[\x1b[39m\x1b[33m]\x1b[39m\x1b[33m[\x1b[39m\x1b[33m]\x1b[39m\x1b[33m[\x1b[39m\x1b[33m]\x1b[39m\x1b[33m[\x1b[39m")
5353
[{'fg': 'yellow'}, '[', {'fg': None}, {'fg': 'yellow'}, ']', {'fg': None}, {'fg': 'yellow'}, '[', {'fg': None}, {'fg': 'yellow'}, ']', {'fg': None}, {'fg': 'yellow'}, '[', {'fg': None}, {'fg': 'yellow'}, ']', {'fg': None}, {'fg': 'yellow'}, '[', {'fg': None}]
5454
"""
55-
stuff: List[Union[str, Dict[str, Union[str, bool, None]]]] = []
55+
stuff: list[Union[str, dict[str, Union[str, bool, None]]]] = []
5656
rest = s
5757
while True:
5858
front, token, rest = peel_off_esc_code(rest)
@@ -73,7 +73,7 @@ def parse(s: str) -> List[Union[str, Dict[str, Union[str, bool, None]]]]:
7373
return stuff
7474

7575

76-
def peel_off_esc_code(s: str) -> Tuple[str, Optional[Token], str]:
76+
def peel_off_esc_code(s: str) -> tuple[str, Optional[Token], str]:
7777
r"""Returns processed text, the next token, and unprocessed text
7878
7979
>>> front, d, rest = peel_off_esc_code('somestuff')
@@ -114,7 +114,7 @@ def peel_off_esc_code(s: str) -> Tuple[str, Optional[Token], str]:
114114
m = None
115115

116116
if m:
117-
d: Dict[str, Any] = m.groupdict()
117+
d: dict[str, Any] = m.groupdict()
118118
del d["front"]
119119
del d["rest"]
120120
if "numbers" in d and all(d["numbers"].split(";")):
@@ -125,12 +125,12 @@ def peel_off_esc_code(s: str) -> Tuple[str, Optional[Token], str]:
125125
return s, None, ""
126126

127127

128-
def token_type(info: Token) -> Optional[List[Dict[str, Union[str, bool, None]]]]:
128+
def token_type(info: Token) -> Optional[list[dict[str, Union[str, bool, None]]]]:
129129
if info["command"] == "m":
130130
# The default action for ESC[m is to act like ESC[0m
131131
# Ref: https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_codes
132-
values = cast(List[int], info["numbers"]) if len(info["numbers"]) else [0]
133-
tokens: List[Dict[str, Union[str, bool, None]]] = []
132+
values = cast(list[int], info["numbers"]) if len(info["numbers"]) else [0]
133+
tokens: list[dict[str, Union[str, bool, None]]] = []
134134
for value in values:
135135
if value in FG_NUMBER_TO_COLOR:
136136
tokens.append({"fg": FG_NUMBER_TO_COLOR[value]})

curtsies/events.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
import itertools
55
import sys
66
from enum import Enum, auto
7-
from typing import Optional, List, Sequence, Union
7+
from typing import Optional, List, Union
8+
from collections.abc import Sequence
89

910
from .termhelpers import Termmode
1011
from .curtsieskeys import CURTSIES_NAMES as special_curtsies_names
@@ -144,7 +145,7 @@ class PasteEvent(Event):
144145
"""
145146

146147
def __init__(self) -> None:
147-
self.events: List[str] = []
148+
self.events: list[str] = []
148149

149150
def __repr__(self) -> str:
150151
return "<Paste Event with data: %r>" % self.events

curtsies/formatstring.py

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,14 @@
2727
Any,
2828
Callable,
2929
Dict,
30-
Iterable,
31-
Iterator,
3230
List,
33-
Mapping,
34-
MutableMapping,
3531
Optional,
3632
Tuple,
3733
Union,
3834
cast,
3935
no_type_check,
4036
)
37+
from collections.abc import Iterable, Iterator, Mapping, MutableMapping
4138

4239
from .escseqparse import parse, remove_ansi
4340
from .termformatconstants import (
@@ -67,7 +64,7 @@
6764
}
6865

6966

70-
class FrozenAttributes(Dict[str, Union[int, bool]]):
67+
class FrozenAttributes(dict[str, Union[int, bool]]):
7168
"""Immutable dictionary class for format string attributes"""
7269

7370
def __setitem__(self, key: str, value: Union[int, bool]) -> None:
@@ -215,7 +212,7 @@ def reinit(self, chunk: Chunk) -> None:
215212
divides.append(divides[-1] + wcwidth(c))
216213
self.divides = divides
217214

218-
def request(self, max_width: int) -> Optional[Tuple[int, Chunk]]:
215+
def request(self, max_width: int) -> Optional[tuple[int, Chunk]]:
219216
"""Requests a sub-chunk of max_width or shorter. Returns None if no chunks left."""
220217
if max_width < 1:
221218
raise ValueError("requires positive integer max_width")
@@ -413,8 +410,8 @@ def copy_with_new_atts(self, **attributes: Union[bool, int]) -> "FmtStr":
413410

414411
def join(self, iterable: Iterable[Union[str, "FmtStr"]]) -> "FmtStr":
415412
"""Joins an iterable yielding strings or FmtStrs with self as separator"""
416-
before: List[Chunk] = []
417-
chunks: List[Chunk] = []
413+
before: list[Chunk] = []
414+
chunks: list[Chunk] = []
418415
for s in iterable:
419416
chunks.extend(before)
420417
before = self.chunks
@@ -432,7 +429,7 @@ def split(
432429
sep: Optional[str] = None,
433430
maxsplit: Optional[int] = None,
434431
regex: bool = False,
435-
) -> List["FmtStr"]:
432+
) -> list["FmtStr"]:
436433
"""Split based on separator, optionally using a regex.
437434
438435
Capture groups are ignored in regex, the whole pattern is matched
@@ -453,7 +450,7 @@ def split(
453450
)
454451
]
455452

456-
def splitlines(self, keepends: bool = False) -> List["FmtStr"]:
453+
def splitlines(self, keepends: bool = False) -> list["FmtStr"]:
457454
"""Return a list of lines, split on newline characters,
458455
include line boundaries, if keepends is true."""
459456
lines = self.split("\n")
@@ -560,7 +557,7 @@ def __mul__(self, other: int) -> "FmtStr":
560557
# TODO ensure empty FmtStr isn't a problem
561558

562559
@property
563-
def shared_atts(self) -> Dict[str, Union[int, bool]]:
560+
def shared_atts(self) -> dict[str, Union[int, bool]]:
564561
"""Gets atts shared among all nonzero length component Chunks"""
565562
# TODO cache this, could get ugly for large FmtStrs
566563
atts = {}
@@ -582,7 +579,7 @@ def new_with_atts_removed(self, *attributes: str) -> "FmtStr":
582579
return result
583580

584581
@no_type_check
585-
def __getattr__(self, att):
582+
def __getattr__(self, att: str):
586583
# thanks to @aerenchyma/@jczett
587584
if not hasattr(self.s, att):
588585
raise AttributeError(f"No attribute {att!r}")
@@ -600,7 +597,7 @@ def func_help(*args, **kwargs):
600597
return func_help
601598

602599
@property
603-
def divides(self) -> List[int]:
600+
def divides(self) -> list[int]:
604601
"""List of indices of divisions between the constituent chunks."""
605602
acc = [0]
606603
for s in self.chunks:
@@ -752,7 +749,7 @@ def width_aware_slice(s: str, start: int, end: int, replacement_char: str = " ")
752749
return "".join(new_chunk_chars)
753750

754751

755-
def linesplit(string: Union[str, FmtStr], columns: int) -> List[FmtStr]:
752+
def linesplit(string: Union[str, FmtStr], columns: int) -> list[FmtStr]:
756753
"""Returns a list of lines, split on the last possible space of each line.
757754
758755
Split spaces will be removed. Whitespaces will be normalized to one space.
@@ -820,9 +817,9 @@ def normalize_slice(length: int, index: Union[int, slice]) -> slice:
820817

821818

822819
def parse_args(
823-
args: Tuple[str, ...],
820+
args: tuple[str, ...],
824821
kwargs: MutableMapping[str, Union[int, bool, str]],
825-
) -> Mapping[str, Union[int, bool]]:
822+
) -> MutableMapping[str, Union[int, bool]]:
826823
"""Returns a kwargs dictionary by turning args into kwargs"""
827824
if "style" in kwargs:
828825
args += (cast(str, kwargs["style"]),)

curtsies/formatstringarray.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@
3434
Optional,
3535
Union,
3636
List,
37-
Sequence,
3837
overload,
3938
Tuple,
4039
cast,
4140
no_type_check,
4241
)
42+
from collections.abc import Sequence
4343

4444
logger = logging.getLogger(__name__)
4545

@@ -60,26 +60,26 @@ def __init__(
6060
self, num_rows: int, num_columns: int, *args: Any, **kwargs: Any
6161
) -> None:
6262
self.saved_args, self.saved_kwargs = args, kwargs
63-
self.rows: List[FmtStr] = [fmtstr("", *args, **kwargs) for _ in range(num_rows)]
63+
self.rows: list[FmtStr] = [fmtstr("", *args, **kwargs) for _ in range(num_rows)]
6464
self.num_columns = num_columns
6565

6666
@overload
6767
def __getitem__(self, slicetuple: int) -> FmtStr:
6868
pass
6969

7070
@overload
71-
def __getitem__(self, slicetuple: slice) -> List[FmtStr]:
71+
def __getitem__(self, slicetuple: slice) -> list[FmtStr]:
7272
pass
7373

7474
@overload
7575
def __getitem__(
76-
self, slicetuple: Tuple[Union[slice, int], Union[slice, int]]
77-
) -> List[FmtStr]:
76+
self, slicetuple: tuple[Union[slice, int], Union[slice, int]]
77+
) -> list[FmtStr]:
7878
pass
7979

8080
def __getitem__(
81-
self, slicetuple: Union[int, slice, Tuple[Union[int, slice], Union[int, slice]]]
82-
) -> Union[FmtStr, List[FmtStr]]:
81+
self, slicetuple: Union[int, slice, tuple[Union[int, slice], Union[int, slice]]]
82+
) -> Union[FmtStr, list[FmtStr]]:
8383
if isinstance(slicetuple, int):
8484
if slicetuple < 0:
8585
slicetuple = len(self.rows) - slicetuple
@@ -99,7 +99,7 @@ def __len__(self) -> int:
9999
return len(self.rows)
100100

101101
@property
102-
def shape(self) -> Tuple[int, int]:
102+
def shape(self) -> tuple[int, int]:
103103
"""Tuple of (len(rows, len(num_columns)) numpy-style shape"""
104104
return len(self.rows), self.num_columns
105105

@@ -301,7 +301,7 @@ def assertFSArraysEqual(a: FSArray, b: FSArray) -> None:
301301

302302
def assertFSArraysEqualIgnoringFormatting(a: FSArray, b: FSArray) -> None:
303303
"""Also accepts arrays of strings"""
304-
assert len(a) == len(b), "fsarray heights do not match: %s %s \n%s \n%s" % (
304+
assert len(a) == len(b), "fsarray heights do not match: {} {} \n{} \n{}".format(
305305
len(a),
306306
len(b),
307307
simple_format(a),
@@ -310,7 +310,7 @@ def assertFSArraysEqualIgnoringFormatting(a: FSArray, b: FSArray) -> None:
310310
for i, (a_row, b_row) in enumerate(zip(a, b)):
311311
a_row = a_row.s if isinstance(a_row, FmtStr) else a_row
312312
b_row = b_row.s if isinstance(b_row, FmtStr) else b_row
313-
assert a_row == b_row, "FSArrays differ first on line %s:\n%s" % (
313+
assert a_row == b_row, "FSArrays differ first on line {}:\n{}".format(
314314
i,
315315
FSArray.diff(a, b, ignore_formatting=True),
316316
)
@@ -319,7 +319,7 @@ def assertFSArraysEqualIgnoringFormatting(a: FSArray, b: FSArray) -> None:
319319
if __name__ == "__main__":
320320
a = FSArray(3, 14, bg="blue")
321321
a[0:2, 5:11] = cast(
322-
Tuple[FmtStr, ...],
322+
tuple[FmtStr, ...],
323323
(fmtstr("hey", "on_blue") + " " + fmtstr("yo", "on_red"), fmtstr("qwe qw")),
324324
)
325325
a.dumb_display()

0 commit comments

Comments
 (0)