2828
2929from collections .abc import Callable
3030from types import FunctionType , NoneType
31- from typing import Any , NamedTuple
31+ from typing import Any , NamedTuple , NoReturn , Literal , overload
3232
3333# TODO:
3434#
5959}
6060
6161class Unspecified :
62- def __repr__ (self ):
62+ def __repr__ (self ) -> str :
6363 return '<Unspecified>'
6464
6565unspecified = Unspecified ()
6666
6767
6868class Null :
69- def __repr__ (self ):
69+ def __repr__ (self ) -> str :
7070 return '<Null>'
7171
7272NULL = Null ()
7373
7474
7575class Unknown :
76- def __repr__ (self ):
76+ def __repr__ (self ) -> str :
7777 return '<Unknown>'
7878
7979unknown = Unknown ()
8080
8181sig_end_marker = '--'
8282
8383Appender = Callable [[str ], None ]
84- Outputter = Callable [[None ], str ]
84+ Outputter = Callable [[], str ]
8585
8686class _TextAccumulator (NamedTuple ):
8787 text : list [str ]
8888 append : Appender
8989 output : Outputter
9090
91- def _text_accumulator ():
92- text = []
91+ def _text_accumulator () -> _TextAccumulator :
92+ text : list [ str ] = []
9393 def output ():
9494 s = '' .join (text )
9595 text .clear ()
@@ -98,10 +98,10 @@ def output():
9898
9999
100100class TextAccumulator (NamedTuple ):
101- text : list [str ]
102101 append : Appender
102+ output : Outputter
103103
104- def text_accumulator ():
104+ def text_accumulator () -> TextAccumulator :
105105 """
106106 Creates a simple text accumulator / joiner.
107107
@@ -115,8 +115,28 @@ def text_accumulator():
115115 text , append , output = _text_accumulator ()
116116 return TextAccumulator (append , output )
117117
118-
119- def warn_or_fail (fail = False , * args , filename = None , line_number = None ):
118+ @overload
119+ def warn_or_fail (
120+ * args : object ,
121+ fail : Literal [True ],
122+ filename : str | None = None ,
123+ line_number : int | None = None ,
124+ ) -> NoReturn : ...
125+
126+ @overload
127+ def warn_or_fail (
128+ * args : object ,
129+ fail : Literal [False ] = False ,
130+ filename : str | None = None ,
131+ line_number : int | None = None ,
132+ ) -> None : ...
133+
134+ def warn_or_fail (
135+ * args : object ,
136+ fail : bool = False ,
137+ filename : str | None = None ,
138+ line_number : int | None = None ,
139+ ) -> None :
120140 joined = " " .join ([str (a ) for a in args ])
121141 add , output = text_accumulator ()
122142 if fail :
@@ -139,14 +159,22 @@ def warn_or_fail(fail=False, *args, filename=None, line_number=None):
139159 sys .exit (- 1 )
140160
141161
142- def warn (* args , filename = None , line_number = None ):
143- return warn_or_fail (False , * args , filename = filename , line_number = line_number )
162+ def warn (
163+ * args : object ,
164+ filename : str | None = None ,
165+ line_number : int | None = None ,
166+ ) -> None :
167+ return warn_or_fail (* args , filename = filename , line_number = line_number , fail = False )
144168
145- def fail (* args , filename = None , line_number = None ):
146- return warn_or_fail (True , * args , filename = filename , line_number = line_number )
169+ def fail (
170+ * args : object ,
171+ filename : str | None = None ,
172+ line_number : int | None = None ,
173+ ) -> NoReturn :
174+ warn_or_fail (* args , filename = filename , line_number = line_number , fail = True )
147175
148176
149- def quoted_for_c_string (s ) :
177+ def quoted_for_c_string (s : str ) -> str :
150178 for old , new in (
151179 ('\\ ' , '\\ \\ ' ), # must be first!
152180 ('"' , '\\ "' ),
@@ -155,13 +183,13 @@ def quoted_for_c_string(s):
155183 s = s .replace (old , new )
156184 return s
157185
158- def c_repr (s ) :
186+ def c_repr (s : str ) -> str :
159187 return '"' + s + '"'
160188
161189
162190is_legal_c_identifier = re .compile ('^[A-Za-z_][A-Za-z0-9_]*$' ).match
163191
164- def is_legal_py_identifier (s ) :
192+ def is_legal_py_identifier (s : str ) -> bool :
165193 return all (is_legal_c_identifier (field ) for field in s .split ('.' ))
166194
167195# identifiers that are okay in Python but aren't a good idea in C.
@@ -174,7 +202,7 @@ def is_legal_py_identifier(s):
174202typedef typeof union unsigned void volatile while
175203""" .strip ().split ())
176204
177- def ensure_legal_c_identifier (s ) :
205+ def ensure_legal_c_identifier (s : str ) -> str :
178206 # for now, just complain if what we're given isn't legal
179207 if not is_legal_c_identifier (s ):
180208 fail ("Illegal C identifier: {}" .format (s ))
@@ -183,22 +211,22 @@ def ensure_legal_c_identifier(s):
183211 return s + "_value"
184212 return s
185213
186- def rstrip_lines (s ) :
214+ def rstrip_lines (s : str ) -> str :
187215 text , add , output = _text_accumulator ()
188216 for line in s .split ('\n ' ):
189217 add (line .rstrip ())
190218 add ('\n ' )
191219 text .pop ()
192220 return output ()
193221
194- def format_escape (s ) :
222+ def format_escape (s : str ) -> str :
195223 # double up curly-braces, this string will be used
196224 # as part of a format_map() template later
197225 s = s .replace ('{' , '{{' )
198226 s = s .replace ('}' , '}}' )
199227 return s
200228
201- def linear_format (s , ** kwargs ) :
229+ def linear_format (s : str , ** kwargs : str ) -> str :
202230 """
203231 Perform str.format-like substitution, except:
204232 * The strings substituted must be on lines by
@@ -242,7 +270,7 @@ def linear_format(s, **kwargs):
242270
243271 return output ()[:- 1 ]
244272
245- def indent_all_lines (s , prefix ) :
273+ def indent_all_lines (s : str , prefix : str ) -> str :
246274 """
247275 Returns 's', with 'prefix' prepended to all lines.
248276
@@ -263,7 +291,7 @@ def indent_all_lines(s, prefix):
263291 final .append (last )
264292 return '' .join (final )
265293
266- def suffix_all_lines (s , suffix ) :
294+ def suffix_all_lines (s : str , suffix : str ) -> str :
267295 """
268296 Returns 's', with 'suffix' appended to all lines.
269297
@@ -283,7 +311,7 @@ def suffix_all_lines(s, suffix):
283311 return '' .join (final )
284312
285313
286- def version_splitter (s ) :
314+ def version_splitter (s : str ) -> tuple [ int , ...] :
287315 """Splits a version string into a tuple of integers.
288316
289317 The following ASCII characters are allowed, and employ
@@ -294,7 +322,7 @@ def version_splitter(s):
294322 (This permits Python-style version strings such as "1.4b3".)
295323 """
296324 version = []
297- accumulator = []
325+ accumulator : list [ str ] = []
298326 def flush ():
299327 if not accumulator :
300328 raise ValueError ('Unsupported version string: ' + repr (s ))
@@ -314,7 +342,7 @@ def flush():
314342 flush ()
315343 return tuple (version )
316344
317- def version_comparitor (version1 , version2 ) :
345+ def version_comparitor (version1 : str , version2 : str ) -> Literal [ - 1 , 0 , 1 ] :
318346 iterator = itertools .zip_longest (version_splitter (version1 ), version_splitter (version2 ), fillvalue = 0 )
319347 for i , (a , b ) in enumerate (iterator ):
320348 if a < b :
0 commit comments