Coverage for sources/ictruck/printers.py: 100%

23 statements  

« prev     ^ index     » next       coverage.py v7.9.2, created at 2025-07-05 05:21 +0000

1# vim: set filetype=python fileencoding=utf-8: 

2# -*- coding: utf-8 -*- 

3 

4#============================================================================# 

5# # 

6# Licensed under the Apache License, Version 2.0 (the "License"); # 

7# you may not use this file except in compliance with the License. # 

8# You may obtain a copy of the License at # 

9# # 

10# http://www.apache.org/licenses/LICENSE-2.0 # 

11# # 

12# Unless required by applicable law or agreed to in writing, software # 

13# distributed under the License is distributed on an "AS IS" BASIS, # 

14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 

15# See the License for the specific language governing permissions and # 

16# limitations under the License. # 

17# # 

18#============================================================================# 

19 

20 

21''' Printers, printer factories, and auxiliary functions and types. ''' 

22 

23 

24 

25import colorama as _colorama 

26 

27from . import __ 

28from . import configuration as _cfg 

29from . import exceptions as _exceptions 

30 

31 

32_validate_arguments = ( 

33 __.validate_arguments( 

34 globalvars = globals( ), 

35 errorclass = _exceptions.ArgumentClassInvalidity ) ) 

36 

37 

38Printer: __.typx.TypeAlias = __.cabc.Callable[ [ str ], None ] 

39PrinterFactory: __.typx.TypeAlias = ( 

40 __.cabc.Callable[ [ str, _cfg.Flavor ], Printer ] ) 

41PrinterFactoryUnion: __.typx.TypeAlias = __.io.TextIOBase | PrinterFactory 

42 

43 

44@_validate_arguments 

45def produce_simple_printer( 

46 target: __.io.TextIOBase, 

47 mname: str, 

48 flavor: _cfg.Flavor, 

49 force_color: bool = False, 

50) -> Printer: 

51 ''' Produces printer which uses standard Python 'print'. ''' 

52 match __.sys.platform: 

53 case 'win32': 

54 winansi = _colorama.AnsiToWin32( target ) # pyright: ignore 

55 target_ = ( # pragma: no cover 

56 winansi.stream if winansi.convert else target ) 

57 case _: target_ = target 

58 return __.funct.partial( 

59 _simple_print, 

60 target = target_, # pyright: ignore 

61 force_color = force_color ) 

62 

63 

64def _remove_ansi_c1_sequences( text: str ) -> str: 

65 # https://stackoverflow.com/a/14693789/14833542 

66 regex = __.re.compile( r'''\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])''' ) 

67 return regex.sub( '', text ) 

68 

69 

70def _simple_print( 

71 text: str, target: __.io.TextIOBase, force_color = False 

72) -> None: 

73 if not force_color and not target.isatty( ): 

74 print( _remove_ansi_c1_sequences( text ), file = target ) 

75 return 

76 print( text, file = target )