1
- # =============================================================================
2
- # _____ _ _ _____ _ _ _ _ ___
3
- # _ __ _ |_ _|__ ___ | (_)_ __ __ _|_ _|__ _ __ _ __ ___ (_)_ __ __ _| | | | |_ _|
4
- # | '_ \| | | || |/ _ \ / _ \| | | '_ \ / _` | | |/ _ \ '__| '_ ` _ \| | '_ \ / _` | | | | || |
5
- # | |_) | |_| || | (_) | (_) | | | | | | (_| |_| | __/ | | | | | | | | | | | (_| | | |_| || |
6
- # | .__/ \__, ||_|\___/ \___/|_|_|_| |_|\__, (_)_|\___|_| |_| |_| |_|_|_| |_|\__,_|_|\___/|___|
7
- # |_| |___/ |___/
8
- # =============================================================================
9
- # Authors: Patrick Lehmann
1
+ # ==================================================================================================================== #
2
+ # _____ _ _ _____ _ _ _ _ ___ #
3
+ # _ __ _ |_ _|__ ___ | (_)_ __ __ _|_ _|__ _ __ _ __ ___ (_)_ __ __ _| | | | |_ _| #
4
+ # | '_ \| | | || |/ _ \ / _ \| | | '_ \ / _` | | |/ _ \ '__| '_ ` _ \| | '_ \ / _` | | | | || | #
5
+ # | |_) | |_| || | (_) | (_) | | | | | | (_| |_| | __/ | | | | | | | | | | | (_| | | |_| || | #
6
+ # | .__/ \__, ||_|\___/ \___/|_|_|_| |_|\__, (_)_|\___|_| |_| |_| |_|_|_| |_|\__,_|_|\___/|___| #
7
+ # |_| |___/ |___/ #
8
+ # ==================================================================================================================== #
9
+ # Authors: #
10
+ # Patrick Lehmann #
11
+ # #
12
+ # License: #
13
+ # ==================================================================================================================== #
14
+ # Copyright 2017-2021 Patrick Lehmann - Bötzingen, Germany #
15
+ # #
16
+ # Licensed under the Apache License, Version 2.0 (the "License"); #
17
+ # you may not use this file except in compliance with the License. #
18
+ # You may obtain a copy of the License at #
19
+ # #
20
+ # http://www.apache.org/licenses/LICENSE-2.0 #
21
+ # #
22
+ # Unless required by applicable law or agreed to in writing, software #
23
+ # distributed under the License is distributed on an "AS IS" BASIS, #
24
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
25
+ # See the License for the specific language governing permissions and #
26
+ # limitations under the License. #
27
+ # #
28
+ # SPDX-License-Identifier: Apache-2.0 #
29
+ # ==================================================================================================================== #
10
30
#
11
- # Python package: A set of helpers to implement a text user interface (TUI) in a terminal.
12
- #
13
- # License:
14
- # ============================================================================
15
- # Copyright 2017-2021 Patrick Lehmann - Bötzingen, Germany
16
- #
17
- # Licensed under the Apache License, Version 2.0 (the "License");
18
- # you may not use this file except in compliance with the License.
19
- # You may obtain a copy of the License at
20
- #
21
- # http://www.apache.org/licenses/LICENSE-2.0
22
- #
23
- # Unless required by applicable law or agreed to in writing, software
24
- # distributed under the License is distributed on an "AS IS" BASIS,
25
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26
- # See the License for the specific language governing permissions and
27
- # limitations under the License.
28
- #
29
- # SPDX-License-Identifier: Apache-2.0
30
- # ============================================================================
31
- #
32
- from enum import Enum , unique
33
- from platform import system as platform_system
34
- from typing import NoReturn , Tuple
35
-
36
- from pyTooling .Decorators import export
37
- from pyTooling .MetaClasses import Singleton
38
-
31
+ """A set of helpers to implement a text user interface (TUI) in a terminal."""
39
32
__author__ = "Patrick Lehmann"
40
33
__email__ = "Paebbels@gmail.com"
41
34
__copyright__ = "2007-2021, Patrick Lehmann"
42
35
__license__ = "Apache License, Version 2.0"
43
36
__version__ = "1.5.6"
44
37
__keywords__ = ["terminal" , "shell" , "text user interface" , "TUI" , "console" , "message logging" ]
45
38
39
+ from enum import Enum , unique
40
+ from platform import system as platform_system
41
+ from typing import NoReturn , Tuple , Any
42
+
43
+ from pyTooling .Decorators import export
44
+ from pyTooling .MetaClasses import Singleton
45
+
46
46
47
47
@export
48
48
class Terminal :
@@ -163,7 +163,6 @@ def versionCheck(cls, version) -> None:
163
163
@classmethod
164
164
def printException (cls , ex ) -> NoReturn :
165
165
"""Prints an exception of type :exc:`Exception`."""
166
-
167
166
from traceback import print_tb , walk_tb
168
167
169
168
cls .initColors ()
@@ -194,7 +193,6 @@ def printException(cls, ex) -> NoReturn:
194
193
@classmethod
195
194
def printNotImplementedError (cls , ex ) -> NoReturn :
196
195
"""Prints a not-implemented exception of type :exc:`NotImplementedError`."""
197
-
198
196
from traceback import walk_tb
199
197
200
198
cls .initColors ()
@@ -238,11 +236,7 @@ def Height(self) -> int:
238
236
239
237
@staticmethod
240
238
def GetTerminalSize () -> Tuple [int , int ]:
241
- """
242
- Returns the terminal size as tuple (width, height) for Windows, Mac OS
243
- (Darwin), Linux, cygwin (Windows), MinGW32/64 (Windows).
244
- """
245
-
239
+ """Returns the terminal size as tuple (width, height) for Windows, Mac OS (Darwin), Linux, cygwin (Windows), MinGW32/64 (Windows)."""
246
240
size = None
247
241
248
242
platform = platform_system ()
@@ -261,7 +255,6 @@ def GetTerminalSize() -> Tuple[int, int]:
261
255
@staticmethod
262
256
def __GetTerminalSizeOnWindows () -> Tuple [int , int ]:
263
257
"""Returns the current terminal window's size for Windows."""
264
-
265
258
try :
266
259
from ctypes import windll , create_string_buffer
267
260
from struct import unpack as struct_unpack
@@ -294,7 +287,6 @@ def __GetTerminalSizeWithTPut() -> Tuple[int, int]:
294
287
@staticmethod
295
288
def __GetTerminalSizeOnLinux () -> Tuple [int , int ]:
296
289
"""Returns the current terminal window's size for Linux."""
297
-
298
290
import os
299
291
300
292
def ioctl_GWINSZ (fd ):
@@ -345,23 +337,41 @@ class Severity(Enum):
345
337
def __hash__ (self ):
346
338
return hash (self .name )
347
339
348
- def __eq__ (self , other ):
349
- return self .value == other .value
340
+ def __eq__ (self , other : Any ):
341
+ if isinstance (other , Severity ):
342
+ return self .value == other .value
343
+ else :
344
+ raise TypeError (f"Second operand of type '{ other .__class__ .__name__ } ' is not supported by == operator." )
350
345
351
- def __ne__ (self , other ):
352
- return self .value != other .value
346
+ def __ne__ (self , other : Any ):
347
+ if isinstance (other , Severity ):
348
+ return self .value != other .value
349
+ else :
350
+ raise TypeError (f"Second operand of type '{ other .__class__ .__name__ } ' is not supported by != operator." )
353
351
354
- def __lt__ (self , other ):
355
- return self .value < other .value
352
+ def __lt__ (self , other : Any ):
353
+ if isinstance (other , Severity ):
354
+ return self .value < other .value
355
+ else :
356
+ raise TypeError (f"Second operand of type '{ other .__class__ .__name__ } ' is not supported by < operator." )
356
357
357
- def __le__ (self , other ):
358
- return self .value <= other .value
358
+ def __le__ (self , other : Any ):
359
+ if isinstance (other , Severity ):
360
+ return self .value <= other .value
361
+ else :
362
+ raise TypeError (f"Second operand of type '{ other .__class__ .__name__ } ' is not supported by <= operator." )
359
363
360
- def __gt__ (self , other ):
361
- return self .value > other .value
364
+ def __gt__ (self , other : Any ):
365
+ if isinstance (other , Severity ):
366
+ return self .value > other .value
367
+ else :
368
+ raise TypeError (f"Second operand of type '{ other .__class__ .__name__ } ' is not supported by > operator." )
362
369
363
- def __ge__ (self , other ):
364
- return self .value >= other .value
370
+ def __ge__ (self , other : Any ):
371
+ if isinstance (other , Severity ):
372
+ return self .value >= other .value
373
+ else :
374
+ raise TypeError (f"Second operand of type '{ other .__class__ .__name__ } ' is not supported by >= operator." )
365
375
366
376
367
377
@export
@@ -382,7 +392,6 @@ class Line:
382
392
383
393
def __init__ (self , message , severity = Severity .Normal , indent = 0 , appendLinebreak = True ) -> None :
384
394
"""Constructor for a new ``Line`` object."""
385
-
386
395
self ._severity = severity
387
396
self ._message = message
388
397
self ._indent = indent
@@ -421,7 +430,6 @@ class ILineTerminal:
421
430
422
431
def __init__ (self , terminal = None ) -> None :
423
432
"""MixIn initializer."""
424
-
425
433
self ._terminal = terminal
426
434
427
435
# FIXME: Alter methods if a terminal is present or set dummy methods
@@ -433,7 +441,6 @@ def Terminal(self) -> Terminal:
433
441
434
442
def WriteLine (self , line : Line , condition = True ):
435
443
"""Write an entry to the local terminal."""
436
-
437
444
if ((self ._terminal is not None ) and condition ):
438
445
return self ._terminal .WriteLine (line )
439
446
return False
@@ -445,63 +452,54 @@ def WriteLine(self, line : Line, condition=True):
445
452
446
453
def WriteFatal (self , * args , condition = True , ** kwargs ):
447
454
"""Write a fatal message if ``condition`` is true."""
448
-
449
455
if ((self ._terminal is not None ) and condition ):
450
456
return self ._terminal .WriteFatal (* args , ** kwargs )
451
457
return False
452
458
453
459
def WriteError (self , * args , condition = True , ** kwargs ):
454
460
"""Write an error message if ``condition`` is true."""
455
-
456
461
if ((self ._terminal is not None ) and condition ):
457
462
return self ._terminal .WriteError (* args , ** kwargs )
458
463
return False
459
464
460
465
def WriteWarning (self , * args , condition = True , ** kwargs ):
461
466
"""Write a warning message if ``condition`` is true."""
462
-
463
467
if ((self ._terminal is not None ) and condition ):
464
468
return self ._terminal .WriteWarning (* args , ** kwargs )
465
469
return False
466
470
467
471
def WriteInfo (self , * args , condition = True , ** kwargs ):
468
472
"""Write a info message if ``condition`` is true."""
469
-
470
473
if ((self ._terminal is not None ) and condition ):
471
474
return self ._terminal .WriteInfo (* args , ** kwargs )
472
475
return False
473
476
474
477
def WriteQuiet (self , * args , condition = True , ** kwargs ):
475
478
"""Write a message even in quiet mode if ``condition`` is true."""
476
-
477
479
if ((self ._terminal is not None ) and condition ):
478
480
return self ._terminal .WriteQuiet (* args , ** kwargs )
479
481
return False
480
482
481
483
def WriteNormal (self , * args , condition = True , ** kwargs ):
482
484
"""Write a *normal* message if ``condition`` is true."""
483
-
484
485
if ((self ._terminal is not None ) and condition ):
485
486
return self ._terminal .WriteNormal (* args , ** kwargs )
486
487
return False
487
488
488
489
def WriteVerbose (self , * args , condition = True , ** kwargs ):
489
490
"""Write a verbose message if ``condition`` is true."""
490
-
491
491
if ((self ._terminal is not None ) and condition ):
492
492
return self ._terminal .WriteVerbose (* args , ** kwargs )
493
493
return False
494
494
495
495
def WriteDebug (self , * args , condition = True , ** kwargs ):
496
496
"""Write a debug message if ``condition`` is true."""
497
-
498
497
if ((self ._terminal is not None ) and condition ):
499
498
return self ._terminal .WriteDebug (* args , ** kwargs )
500
499
return False
501
500
502
501
def WriteDryRun (self , * args , condition = True , ** kwargs ):
503
502
"""Write a dry-run message if ``condition`` is true."""
504
-
505
503
if ((self ._terminal is not None ) and condition ):
506
504
return self ._terminal .WriteDryRun (* args , ** kwargs )
507
505
return False
@@ -511,7 +509,6 @@ def WriteDryRun(self, *args, condition=True, **kwargs):
511
509
class LineTerminal (Terminal , ILineTerminal , metaclass = Singleton ):
512
510
def __init__ (self , verbose = False , debug = False , quiet = False , writeToStdOut = True ) -> None :
513
511
"""Initializer of a line based terminal interface."""
514
-
515
512
Terminal .__init__ (self )
516
513
ILineTerminal .__init__ (self , self )
517
514
@@ -580,21 +577,18 @@ def BaseIndent(self, value: int) -> None:
580
577
581
578
def ExitOnPreviousErrors (self ) -> None :
582
579
"""Exit application if errors have been printed."""
583
-
584
580
if self ._errorCounter > 0 :
585
581
self .WriteFatal ("Too many errors in previous steps." )
586
582
self .fatalExit ()
587
583
588
584
def ExitOnPreviousWarnings (self ) -> None :
589
585
"""Exit application if warnings have been printed."""
590
-
591
586
if self ._warningCounter > 0 :
592
587
self .WriteError ("Too many warnings in previous steps." )
593
588
self .exit ()
594
589
595
590
def WriteLine (self , line : Line ):
596
591
"""Print a formatted line to the underlying terminal/console offered by the operating system."""
597
-
598
592
if (line .Severity >= self ._WriteLevel ):
599
593
self ._lines .append (line )
600
594
if self ._writeToStdOut :
0 commit comments