Coverage for sources/ictr/standard/core.py: 100%
37 statements
« prev ^ index » next coverage.py v7.16.1, created at 2026-09-26 12:43 +0000
« prev ^ index » next coverage.py v7.16.1, created at 2026-09-26 12:43 +0000
1# vim: set filetype=python fileencoding=utf-8:
2# -*- coding: utf-8 -*-
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#============================================================================#
21''' Core data structures and utilities. '''
24from . import __
27class Auxiliaries( __.immut.DataclassObject ):
28 ''' Auxiliary functions used by textualizers and interpolation.
30 Typically used by unit tests to inject mock dependencies,
31 but can also be used to deeply customize output.
32 '''
34 pid_discoverer: __.typx.Annotated[
35 __.typx.Callable[ [ ], int ],
36 __.ddoc.Doc( ''' Returns ID of current process. ''' ),
37 ] = __.os.getpid
38 thread_discoverer: __.typx.Annotated[
39 __.typx.Callable[ [ ], __.threads.Thread ],
40 __.ddoc.Doc( ''' Returns current thread. ''' ),
41 ] = __.threads.current_thread
42 time_formatter: __.typx.Annotated[
43 __.typx.Callable[ [ str ], str ],
44 __.ddoc.Doc( ''' Returns current time in specified format. ''' ),
45 ] = lambda fmt: __.Datetime.now( __.Timezone.utc ).strftime( fmt )
48class ColumnsConstraints( __.enum.Enum ):
49 ''' How to constrain text which exceeds maximum columns. '''
51 Complect = __.enum.auto( ) # fold/wrap
52 Exceed = __.enum.auto( ) # overflow
53 # Truncate = __.enum.auto( ) # chop/cut
56class IncisionBoundaries( __.enum.Enum ):
57 ''' Where to constrain text which exceeds maximum columns. '''
59 Nowhere = __.enum.auto( )
60 Whitespace = __.enum.auto( ) # horizontal spaces and tabs
61 Wordsplits = __.enum.auto( ) # hyphens + whitespace
62 Anywhere = __.enum.auto( )
65class Style( __.immut.DataclassObject ):
66 ''' Style for text. Corresponds to terminal attributes. '''
68 bgcolor: __.typx.Optional[ str ] = None
69 fgcolor: __.typx.Optional[ str ] = None
70 # TODO: Int flag enum for bold, blink, etc...
73InterpolantsStylesRegistry: __.typx.TypeAlias = (
74 __.accret.Dictionary[ str, Style ] )
77class LabelPresentations( __.enum.IntFlag ):
78 ''' How introduction labels should be presented. '''
80 Nothing = 0
81 Words = __.enum.auto( )
82 Emoji = __.enum.auto( )
85class ExceptionsConfiguration( __.immut.DataclassObject ):
86 ''' Configuration pertaining to exceptions. '''
88 discoverer: __.typx.Annotated[
89 __.typx.Callable[ [ ], __.ExceptionInfo ],
90 __.ddoc.Doc( ''' Returns information on current exception. ''' ),
91 ] = __.sys.exc_info
92 enable_discovery: __.typx.Annotated[
93 bool, __.ddoc.Doc( ''' Discover active exception? ''' )
94 ] = False
95 enable_stacktraces: __.typx.Annotated[
96 bool, __.ddoc.Doc( ''' Render tracebacks? ''' )
97 ] = False
98 recursive_stacktraces: __.typx.Annotated[
99 bool, __.ddoc.Doc(
100 ''' Render traceback for each exception group member? ''' ),
101 ] = False
102 template: __.typx.Annotated[
103 str, __.ddoc.Doc( ''' Template for exception message. ''' )
104 ] = '[{name}] {message}'
106 def discover( self ) -> __.typx.Optional[ BaseException ]:
107 ''' Discovers active exception. '''
108 return self.discoverer( )[ 1 ] if self.enable_discovery else None
110 def interpolate( self, exception: BaseException ) -> tuple[ str, ... ]:
111 ''' Interpolates exception attributes into message template. '''
112 eclass = type( exception )
113 name = eclass.__name__
114 qname = eclass.__qualname__
115 mname = eclass.__module__
116 interpolants = dict(
117 name = name, qname = qname, mname = mname,
118 message = str( exception ) )
119 interpolants[ 'fqname' ] = f"{mname}.{qname}"
120 return tuple( self.template.format( **interpolants ).split( '\n' ) )