2525from itertools import chain
2626from typing import (
2727 Any ,
28- Callable ,
2928 Dict ,
3029 List ,
3130 Optional ,
3433 cast ,
3534 no_type_check ,
3635)
37- from collections .abc import Iterable , Iterator , Mapping , MutableMapping
36+ from collections .abc import Callable , Iterable , Iterator , Mapping , MutableMapping
3837
3938from .escseqparse import parse , remove_ansi
4039from .termformatconstants import (
5958}
6059
6160two_arg_xforms : Mapping [str , Callable [[str , int ], str ]] = {
62- "fg" : lambda s , v : "{}{}{}" . format ( seq (v ), s , seq (RESET_FG )) ,
61+ "fg" : lambda s , v : f" { seq (v )} { s } { seq (RESET_FG )} " ,
6362 "bg" : lambda s , v : seq (v ) + s + seq (RESET_BG ),
6463}
6564
6665
6766class FrozenAttributes (dict [str , Union [int , bool ]]):
6867 """Immutable dictionary class for format string attributes"""
6968
70- def __setitem__ (self , key : str , value : Union [ int , bool ] ) -> None :
69+ def __setitem__ (self , key : str , value : int | bool ) -> None :
7170 raise Exception ("Cannot change value." )
7271
7372 def update (self , * args : Any , ** kwds : Any ) -> None :
7473 raise Exception ("Cannot change value." )
7574
76- def extend (self , dictlike : Mapping [str , Union [ int , bool ] ]) -> "FrozenAttributes" :
75+ def extend (self , dictlike : Mapping [str , int | bool ]) -> "FrozenAttributes" :
7776 return FrozenAttributes (chain (self .items (), dictlike .items ()))
7877
7978 def remove (self , * keys : str ) -> "FrozenAttributes" :
@@ -103,9 +102,7 @@ class Chunk:
103102
104103 Subject to change, not part of the API"""
105104
106- def __init__ (
107- self , string : str , atts : Optional [Mapping [str , Union [int , bool ]]] = None
108- ):
105+ def __init__ (self , string : str , atts : Mapping [str , int | bool ] | None = None ):
109106 if not isinstance (string , str ):
110107 raise ValueError ("unicode string required, got %r" % string )
111108 self ._s = string
@@ -212,7 +209,7 @@ def reinit(self, chunk: Chunk) -> None:
212209 divides .append (divides [- 1 ] + wcwidth (c ))
213210 self .divides = divides
214211
215- def request (self , max_width : int ) -> Optional [ tuple [int , Chunk ]] :
212+ def request (self , max_width : int ) -> tuple [int , Chunk ] | None :
216213 """Requests a sub-chunk of max_width or shorter. Returns None if no chunks left."""
217214 if max_width < 1 :
218215 raise ValueError ("requires positive integer max_width" )
@@ -279,10 +276,10 @@ def __init__(self, *components: Chunk) -> None:
279276 self .chunks = list (components )
280277
281278 # caching these leads to a significant speedup
282- self ._unicode : Optional [ str ] = None
283- self ._len : Optional [ int ] = None
284- self ._s : Optional [ str ] = None
285- self ._width : Optional [ int ] = None
279+ self ._unicode : str | None = None
280+ self ._len : int | None = None
281+ self ._s : str | None = None
282+ self ._width : int | None = None
286283
287284 @staticmethod
288285 def from_str (s : str ) -> "FmtStr" :
@@ -349,7 +346,7 @@ def setslice_with_length(
349346 return result
350347
351348 def splice (
352- self , new_str : Union [str , "FmtStr" ], start : int , end : Optional [ int ] = None
349+ self , new_str : Union [str , "FmtStr" ], start : int , end : int | None = None
353350 ) -> "FmtStr" :
354351 """Returns a new FmtStr with the input string spliced into the
355352 the original FmtStr at start and end.
@@ -401,7 +398,7 @@ def splice(
401398 def append (self , string : Union [str , "FmtStr" ]) -> "FmtStr" :
402399 return self .splice (string , len (self .s ))
403400
404- def copy_with_new_atts (self , ** attributes : Union [ bool , int ] ) -> "FmtStr" :
401+ def copy_with_new_atts (self , ** attributes : bool | int ) -> "FmtStr" :
405402 """Returns a new FmtStr with the same content but new formatting"""
406403
407404 return FmtStr (
@@ -426,8 +423,8 @@ def join(self, iterable: Iterable[Union[str, "FmtStr"]]) -> "FmtStr":
426423 # TODO make this split work like str.split
427424 def split (
428425 self ,
429- sep : Optional [ str ] = None ,
430- maxsplit : Optional [ int ] = None ,
426+ sep : str | None = None ,
427+ maxsplit : int | None = None ,
431428 regex : bool = False ,
432429 ) -> list ["FmtStr" ]:
433430 """Split based on separator, optionally using a regex.
@@ -462,7 +459,7 @@ def splitlines(self, keepends: bool = False) -> list["FmtStr"]:
462459
463460 # proxying to the string via __getattr__ is insufficient
464461 # because we shouldn't drop foreground or formatting info
465- def ljust (self , width : int , fillchar : Optional [ str ] = None ) -> "FmtStr" :
462+ def ljust (self , width : int , fillchar : str | None = None ) -> "FmtStr" :
466463 """S.ljust(width[, fillchar]) -> string
467464
468465 If a fillchar is provided, less formatting information will be preserved
@@ -477,7 +474,7 @@ def ljust(self, width: int, fillchar: Optional[str] = None) -> "FmtStr":
477474 uniform = self .new_with_atts_removed ("bg" )
478475 return uniform + fmtstr (to_add , ** self .shared_atts ) if to_add else uniform
479476
480- def rjust (self , width : int , fillchar : Optional [ str ] = None ) -> "FmtStr" :
477+ def rjust (self , width : int , fillchar : str | None = None ) -> "FmtStr" :
481478 """S.rjust(width[, fillchar]) -> string
482479
483480 If a fillchar is provided, less formatting information will be preserved
@@ -557,7 +554,7 @@ def __mul__(self, other: int) -> "FmtStr":
557554 # TODO ensure empty FmtStr isn't a problem
558555
559556 @property
560- def shared_atts (self ) -> dict [str , Union [ int , bool ] ]:
557+ def shared_atts (self ) -> dict [str , int | bool ]:
561558 """Gets atts shared among all nonzero length component Chunks"""
562559 # TODO cache this, could get ugly for large FmtStrs
563560 atts = {}
@@ -611,7 +608,7 @@ def s(self) -> str:
611608 self ._s = "" .join (fs .s for fs in self .chunks )
612609 return self ._s
613610
614- def __getitem__ (self , index : Union [ int , slice ] ) -> "FmtStr" :
611+ def __getitem__ (self , index : int | slice ) -> "FmtStr" :
615612 index = normalize_slice (len (self ), index )
616613 counter = 0
617614 parts = []
@@ -631,7 +628,7 @@ def __getitem__(self, index: Union[int, slice]) -> "FmtStr":
631628 break
632629 return FmtStr (* parts ) if parts else fmtstr ("" )
633630
634- def width_aware_slice (self , index : Union [ int , slice ] ) -> "FmtStr" :
631+ def width_aware_slice (self , index : int | slice ) -> "FmtStr" :
635632 """Slice based on the number of columns it would take to display the substring."""
636633 if wcswidth (self .s , None ) == - 1 :
637634 raise ValueError ("bad values for width aware slicing" )
@@ -687,7 +684,7 @@ def _width_aware_splitlines(self, columns: int) -> Iterator["FmtStr"]:
687684 if chunks_of_line :
688685 yield FmtStr (* chunks_of_line )
689686
690- def _getitem_normalized (self , index : Union [ int , slice ] ) -> "FmtStr" :
687+ def _getitem_normalized (self , index : int | slice ) -> "FmtStr" :
691688 """Builds the more compact fmtstrs by using fromstr( of the control sequences)"""
692689 index = normalize_slice (len (self ), index )
693690 counter = 0
@@ -749,7 +746,7 @@ def width_aware_slice(s: str, start: int, end: int, replacement_char: str = " ")
749746 return "" .join (new_chunk_chars )
750747
751748
752- def linesplit (string : Union [ str , FmtStr ] , columns : int ) -> list [FmtStr ]:
749+ def linesplit (string : str | FmtStr , columns : int ) -> list [FmtStr ]:
753750 """Returns a list of lines, split on the last possible space of each line.
754751
755752 Split spaces will be removed. Whitespaces will be normalized to one space.
@@ -794,7 +791,7 @@ def linesplit(string: Union[str, FmtStr], columns: int) -> list[FmtStr]:
794791 return lines
795792
796793
797- def normalize_slice (length : int , index : Union [ int , slice ] ) -> slice :
794+ def normalize_slice (length : int , index : int | slice ) -> slice :
798795 "Fill in the Nones in a slice."
799796 is_int = False
800797 if isinstance (index , int ):
@@ -818,8 +815,8 @@ def normalize_slice(length: int, index: Union[int, slice]) -> slice:
818815
819816def parse_args (
820817 args : tuple [str , ...],
821- kwargs : MutableMapping [str , Union [ int , bool , str ] ],
822- ) -> MutableMapping [str , Union [ int , bool ] ]:
818+ kwargs : MutableMapping [str , int | bool | str ],
819+ ) -> MutableMapping [str , int | bool ]:
823820 """Returns a kwargs dictionary by turning args into kwargs"""
824821 if "style" in kwargs :
825822 args += (cast (str , kwargs ["style" ]),)
@@ -855,7 +852,7 @@ def parse_args(
855852 return cast (MutableMapping [str , Union [int , bool ]], kwargs )
856853
857854
858- def fmtstr (string : Union [ str , FmtStr ] , * args : Any , ** kwargs : Any ) -> FmtStr :
855+ def fmtstr (string : str | FmtStr , * args : Any , ** kwargs : Any ) -> FmtStr :
859856 """
860857 Convenience function for creating a FmtStr
861858
0 commit comments