12
12
# See the License for the specific language governing permissions and
13
13
# limitations under the License.
14
14
15
+ from __future__ import annotations
16
+ import enum
15
17
import os
16
18
import io
17
19
import sys
27
29
if T .TYPE_CHECKING :
28
30
from ._typing import StringProtocol , SizedStringProtocol
29
31
32
+ from .mparser import BaseNode
33
+
34
+
30
35
"""This is (mostly) a standalone module used to write logging
31
36
information about Meson runs. Some output goes to screen,
32
37
some to logging dir and some goes to both."""
@@ -218,12 +223,12 @@ def process_markup(args: T.Sequence[TV_Loggable], keep: bool) -> T.List[str]:
218
223
arr .append (str (arg ))
219
224
return arr
220
225
221
- def force_print (* args : str , nested : bool , ** kwargs : T .Any ) -> None :
226
+ def force_print (* args : str , nested : bool , sep : T .Optional [str ] = None ,
227
+ end : T .Optional [str ] = None ) -> None :
222
228
if log_disable_stdout :
223
229
return
224
230
iostr = io .StringIO ()
225
- kwargs ['file' ] = iostr
226
- print (* args , ** kwargs )
231
+ print (* args , sep = sep , end = end , file = iostr )
227
232
228
233
raw = iostr .getvalue ()
229
234
if log_depth :
@@ -242,11 +247,11 @@ def force_print(*args: str, nested: bool, **kwargs: T.Any) -> None:
242
247
cleaned = raw .encode ('ascii' , 'replace' ).decode ('ascii' )
243
248
print (cleaned , end = '' )
244
249
245
- # We really want a heterogeneous dict for this, but that's in typing_extensions
246
- def debug ( * args : TV_Loggable , ** kwargs : T .Any ) -> None :
250
+ def debug ( * args : TV_Loggable , sep : T . Optional [ str ] = None ,
251
+ end : T .Optional [ str ] = None ) -> None :
247
252
arr = process_markup (args , False )
248
253
if log_file is not None :
249
- print (* arr , file = log_file , ** kwargs )
254
+ print (* arr , file = log_file , sep = sep , end = end )
250
255
log_file .flush ()
251
256
252
257
def _debug_log_cmd (cmd : str , args : T .List [str ]) -> None :
@@ -260,27 +265,30 @@ def cmd_ci_include(file: str) -> None:
260
265
261
266
262
267
def log (* args : TV_Loggable , is_error : bool = False ,
263
- once : bool = False , ** kwargs : T .Any ) -> None :
268
+ once : bool = False , nested : bool = True ,
269
+ sep : T .Optional [str ] = None ,
270
+ end : T .Optional [str ] = None ) -> None :
264
271
if once :
265
- log_once (* args , is_error = is_error , ** kwargs )
272
+ log_once (* args , is_error = is_error , nested = nested , sep = sep , end = end )
266
273
else :
267
- _log (* args , is_error = is_error , ** kwargs )
274
+ _log (* args , is_error = is_error , nested = nested , sep = sep , end = end )
268
275
269
276
270
277
def _log (* args : TV_Loggable , is_error : bool = False ,
271
- ** kwargs : T . Any ) -> None :
272
- nested = kwargs . pop ( 'nested' , True )
278
+ nested : bool = True , sep : T . Optional [ str ] = None ,
279
+ end : T . Optional [ str ] = None ) -> None :
273
280
arr = process_markup (args , False )
274
281
if log_file is not None :
275
- print (* arr , file = log_file , ** kwargs )
282
+ print (* arr , file = log_file , sep = sep , end = end )
276
283
log_file .flush ()
277
284
if colorize_console ():
278
285
arr = process_markup (args , True )
279
286
if not log_errors_only or is_error :
280
- force_print (* arr , nested = nested , ** kwargs )
287
+ force_print (* arr , nested = nested , sep = sep , end = end )
281
288
282
289
def log_once (* args : TV_Loggable , is_error : bool = False ,
283
- ** kwargs : T .Any ) -> None :
290
+ nested : bool = True , sep : T .Optional [str ] = None ,
291
+ end : T .Optional [str ] = None ) -> None :
284
292
"""Log variant that only prints a given message one time per meson invocation.
285
293
286
294
This considers ansi decorated values by the values they wrap without
@@ -296,7 +304,7 @@ def to_str(x: TV_Loggable) -> str:
296
304
if t in _logged_once :
297
305
return
298
306
_logged_once .add (t )
299
- _log (* args , is_error = is_error , ** kwargs )
307
+ _log (* args , is_error = is_error , nested = nested , sep = sep , end = end )
300
308
301
309
# This isn't strictly correct. What we really want here is something like:
302
310
# class StringProtocol(typing_extensions.Protocol):
@@ -308,26 +316,36 @@ def to_str(x: TV_Loggable) -> str:
308
316
def get_error_location_string (fname : str , lineno : int ) -> str :
309
317
return f'{ fname } :{ lineno } :'
310
318
311
- def _log_error (severity : str , * rargs : TV_Loggable ,
312
- once : bool = False , fatal : bool = True , ** kwargs : T .Any ) -> None :
319
+
320
+ class _Severity (enum .Enum ):
321
+
322
+ NOTICE = enum .auto ()
323
+ WARNING = enum .auto ()
324
+ ERROR = enum .auto ()
325
+ DEPRECATION = enum .auto ()
326
+
327
+
328
+ def _log_error (severity : _Severity , * rargs : TV_Loggable ,
329
+ once : bool = False , fatal : bool = True ,
330
+ location : T .Optional [BaseNode ] = None ,
331
+ nested : bool = True , sep : T .Optional [str ] = None ,
332
+ end : T .Optional [str ] = None ,
333
+ is_error : bool = True ) -> None :
313
334
from .mesonlib import MesonException , relpath
314
335
315
336
# The typing requirements here are non-obvious. Lists are invariant,
316
337
# therefore T.List[A] and T.List[T.Union[A, B]] are not able to be joined
317
- if severity == 'notice' :
338
+ if severity is _Severity . NOTICE :
318
339
label = [bold ('NOTICE:' )] # type: TV_LoggableList
319
- elif severity == 'warning' :
340
+ elif severity is _Severity . WARNING :
320
341
label = [yellow ('WARNING:' )]
321
- elif severity == 'error' :
342
+ elif severity is _Severity . ERROR :
322
343
label = [red ('ERROR:' )]
323
- elif severity == 'deprecation' :
344
+ elif severity is _Severity . DEPRECATION :
324
345
label = [red ('DEPRECATION:' )]
325
- else :
326
- raise MesonException ('Invalid severity ' + severity )
327
346
# rargs is a tuple, not a list
328
347
args = label + list (rargs )
329
348
330
- location = kwargs .pop ('location' , None )
331
349
if location is not None :
332
350
location_file = relpath (location .filename , os .getcwd ())
333
351
location_str = get_error_location_string (location_file , location .lineno )
@@ -336,25 +354,45 @@ def _log_error(severity: str, *rargs: TV_Loggable,
336
354
location_list = T .cast ('TV_LoggableList' , [location_str ])
337
355
args = location_list + args
338
356
339
- log (* args , once = once , ** kwargs )
357
+ log (* args , once = once , nested = nested , sep = sep , end = end , is_error = is_error )
340
358
341
359
global log_warnings_counter # pylint: disable=global-statement
342
360
log_warnings_counter += 1
343
361
344
362
if log_fatal_warnings and fatal :
345
363
raise MesonException ("Fatal warnings enabled, aborting" )
346
364
347
- def error (* args : TV_Loggable , ** kwargs : T .Any ) -> None :
348
- return _log_error ('error' , * args , ** kwargs , is_error = True )
349
-
350
- def warning (* args : TV_Loggable , ** kwargs : T .Any ) -> None :
351
- return _log_error ('warning' , * args , ** kwargs , is_error = True )
352
-
353
- def deprecation (* args : TV_Loggable , ** kwargs : T .Any ) -> None :
354
- return _log_error ('deprecation' , * args , ** kwargs , is_error = True )
355
-
356
- def notice (* args : TV_Loggable , ** kwargs : T .Any ) -> None :
357
- return _log_error ('notice' , * args , ** kwargs , is_error = False )
365
+ def error (* args : TV_Loggable ,
366
+ once : bool = False , fatal : bool = True ,
367
+ location : T .Optional [BaseNode ] = None ,
368
+ nested : bool = True , sep : T .Optional [str ] = None ,
369
+ end : T .Optional [str ] = None ) -> None :
370
+ return _log_error (_Severity .ERROR , * args , once = once , fatal = fatal , location = location ,
371
+ nested = nested , sep = sep , end = end , is_error = True )
372
+
373
+ def warning (* args : TV_Loggable ,
374
+ once : bool = False , fatal : bool = True ,
375
+ location : T .Optional [BaseNode ] = None ,
376
+ nested : bool = True , sep : T .Optional [str ] = None ,
377
+ end : T .Optional [str ] = None ) -> None :
378
+ return _log_error (_Severity .WARNING , * args , once = once , fatal = fatal , location = location ,
379
+ nested = nested , sep = sep , end = end , is_error = True )
380
+
381
+ def deprecation (* args : TV_Loggable ,
382
+ once : bool = False , fatal : bool = True ,
383
+ location : T .Optional [BaseNode ] = None ,
384
+ nested : bool = True , sep : T .Optional [str ] = None ,
385
+ end : T .Optional [str ] = None ) -> None :
386
+ return _log_error (_Severity .DEPRECATION , * args , once = once , fatal = fatal , location = location ,
387
+ nested = nested , sep = sep , end = end , is_error = True )
388
+
389
+ def notice (* args : TV_Loggable ,
390
+ once : bool = False , fatal : bool = True ,
391
+ location : T .Optional [BaseNode ] = None ,
392
+ nested : bool = True , sep : T .Optional [str ] = None ,
393
+ end : T .Optional [str ] = None ) -> None :
394
+ return _log_error (_Severity .NOTICE , * args , once = once , fatal = fatal , location = location ,
395
+ nested = nested , sep = sep , end = end , is_error = False )
358
396
359
397
def get_relative_path (target : Path , current : Path ) -> Path :
360
398
"""Get the path to target from current"""
@@ -457,3 +495,14 @@ def stop_pager() -> None:
457
495
pass
458
496
log_pager .wait ()
459
497
log_pager = None
498
+
499
+
500
+ def code_line (text : str , line : str , colno : int ) -> str :
501
+ """Print a line with a caret pointing the colno
502
+
503
+ :param text: A message to display before the line
504
+ :param line: The line of code to be pointed to
505
+ :param colno: The column number to point at
506
+ :return: A formatted string of the text, line, and a caret
507
+ """
508
+ return f'{ text } \n { line } \n { " " * colno } ^'
0 commit comments