22import traceback
33from pprint import PrettyPrinter
44from threading import Lock
5+ from types import TracebackType
56from typing import *
67
78
89
910
1011__all__ = [
11- 'PRINT' , 'Print' , 'PrintLines' , 'getPPrintStr' , 'print_exception' ,
12- 'TITLE_TAG' , 'DEFAULT_TAG' , 'END_TAG' , 'pp' , 'check' , 'GetCallStackAsString' , 'GetCallStack' ,
13- 'get_func_details' , 'GetFunctionName' , 'GetFuncModule' , 'print_signature'
12+ # 'getPPrintStr', 'print_exception', 'check', 'get_func_details', 'print_signature'
13+ 'PRINT' , 'Print' ,
14+ # 'TITLE_TAG', 'DEFAULT_TAG', 'END_TAG',
15+ 'Printer' , 'pp' , 'CallStack' ,
16+ 'GetFunctionName' , 'GetFuncModule' ,
1417 ]
1518
1619class NoStringWrappingPrettyPrinter (PrettyPrinter ):
@@ -27,107 +30,152 @@ def _format(self, o, *args):
2730 width = self ._width
2831 self ._width = sys .maxsize
2932 try :
30- super ()._format (o , * args )
33+ return super ()._format (o , * args )
3134 finally :
3235 self ._width = width
33- else :
34- super ()._format (o , * args )
35- 36- DEFAULT_TAG = '\n ______________________________________________________________\n "{0}"'
37- TITLE_TAG = "\n ---------------- {0} ---------------- \n "
38- END_TAG = '\n ============================================================= \n '
39- 40- pp = NoStringWrappingPrettyPrinter .Create ()
41- debug = __debug__
42- _lock = Lock ()
43- 44- def check (DisableWhenNotDebug : bool ) -> bool :
45- """ internal method """
46- if not debug : return True
47- elif not DisableWhenNotDebug : return True
48- 49- return False
50- 51- def Print (* args , sep = ' ' , end = '\n ' , file = None , DisableWhenNotDebug : bool = True ):
52- """
53- :param sep: string to put between passed args
54- :type sep: str
55- :param end: string to append to end of passed args
56- :type end: str
57- :param file: file to write to
58- :type file: file
59- :param DisableWhenNotDebug: if __debug__ is False and DisableWhenNotDebug is True, returns and does NOT print to console.
60- :type DisableWhenNotDebug: bool
61- """
62- if check (DisableWhenNotDebug ):
63- print ('__check__' )
64- return
6536
66- with _lock :
67- return print (* args , sep = sep , end = end , file = file )
68- def PrintLines (* args , sep = '\n ' , end = '\n \n ' , file = None , DisableWhenNotDebug : bool = True ):
69- """
70- :param sep: string to put between passed args
71- :type sep: str
72- :param end: string to append to end of passed args
73- :type end: str
74- :param file: file to write to
75- :type file: file
76- :param DisableWhenNotDebug: if __debug__ is False and DisableWhenNotDebug is True, returns and does NOT print to console.
77- :type DisableWhenNotDebug: bool
78- """
79- return Print (* args , sep = sep , end = end , file = file , DisableWhenNotDebug = DisableWhenNotDebug )
80- def PRINT (title : str , * args , _pp : PrettyPrinter = None , use_double_quotes : bool = True , DisableWhenNotDebug : bool = True , sep = '\n ' , end = '\n \n ' , file = None , ** kwargs ):
81- """
82- :param title: message to start the Print, to make it easier to find it.
83- :type title: str
84- :param o: object to be serialized
85- :type o: any
86- :param _pp: any PrettyPrinter inpmentation. provide your own to customize the output.
87- :type _pp: PrettyPrinter
88- :param use_double_quotes: use double quotes (") instead of the default single quotes (')
89- :type use_double_quotes: bool
90-
91- :param sep: string to put between passed args
92- :type sep: str
93- :param end: string to append to end of passed args
94- :type end: str
95- :param file: file to write to
96- :type file: file
97- :param DisableWhenNotDebug: if __debug__ is False and DisableWhenNotDebug is True, returns and does NOT print to console.
98- :type DisableWhenNotDebug: bool
99- """
100- if check (DisableWhenNotDebug ): return
37+ elif isinstance (o , CallStack ):
38+ print ('__CallStack__' , o , * args )
39+ # super()._format(o.Lines, *args)
40+ return super ()._format (str (o ), * args )
10141
102- return PrintLines (TITLE_TAG .format (title ),
103- getPPrintStr (dict (args = args , kwargs = kwargs ), _pp = _pp , use_double_quotes = use_double_quotes ),
104- sep = sep , end = end , file = file )
105- 106- 107- 108- def getPPrintStr (o : any , * , _pp : PrettyPrinter = None , use_double_quotes : bool = True ) -> str :
109- """
110- :param o: object to be serialized
111- :type o: any
112- :param _pp: any PrettyPrinter inpmentation. provide your own to customize the output.
113- :type _pp: PrettyPrinter
114- :param use_double_quotes: use double quotes (") instead of the default single quotes (')
115- :type use_double_quotes:
116- :return: formatted string of the passed object
117- :rtype: str
118- """
119- s = (_pp or pp ).pformat (o )
120- if use_double_quotes : s = s .replace ("'" , '"' )
121- return s
42+ else :
43+ return super ()._format (o , * args )
44+ 45+ class CallStack (object ):
46+ _lines : Iterable [str ] = None
47+ def __init__ (self , indent : str = 4 * ' ' , * , once : bool = True ):
48+ self ._indent = indent
49+ self ._once = once
50+ self .Update ()
51+ 52+ def Update (self ):
53+ if self ._once and self ._lines is not None : raise RuntimeError ()
54+ 55+ self ._lines = [self ._indent + line .strip () for line in traceback .format_stack ()][:- 1 ]
56+ 57+ @property
58+ def Lines (self ) -> Iterable [str ]:
59+ if self ._lines is None : self .Update ()
60+ return self ._lines
61+ def __str__ (self ) -> str : return '\n ' .join (self .Lines )
62+ # def __repr__(self) -> str: return '\n'.join(self.Lines)
63+ 64+ 65+ 66+ class Printer (object ):
67+ DEFAULT_TAG = '\n ______________________________________________________________\n "{0}"'
68+ TITLE_TAG = "\n ---------------- {0} ---------------- \n "
69+ END_TAG = '\n ============================================================= \n '
70+ 71+ _lock = Lock ()
72+ _active : bool = False
73+ def __init__ (self , _pp : PrettyPrinter = None , * , use_double_quotes : bool , end : str , file = None ):
74+ """
75+ :param end: string to append to end of passed args
76+ :type end: str
77+ :param file: file to write to
78+ :type file: file
79+ :param _pp: any PrettyPrinter inpmentation. provide your own to customize the output.
80+ :type _pp: PrettyPrinter
81+ :param use_double_quotes: use double quotes (") instead of the default single quotes (')
82+ :type use_double_quotes: bool
83+ """
84+ self ._file = file
85+ self ._end = end
86+ self ._use_double_quotes = use_double_quotes
87+ self ._pp = _pp or NoStringWrappingPrettyPrinter .Create ()
88+ self .pprint = self ._pp .pprint
89+ 90+ @property
91+ def debug (self ) -> bool : return __debug__
92+ def check (self ) -> bool : return not self .debug
93+ 94+ def __enter__ (self ):
95+ self ._active = True
96+ self ._lock .__enter__ ()
97+ return self
98+ def __exit__ (self , exc_type : Optional [Type [BaseException ]], exc_val : Optional [BaseException ], exc_tb : Optional [TracebackType ]) -> Optional [bool ]:
99+ self ._active = False
100+ return self ._lock .__exit__ (exc_type , exc_val , exc_tb )
101+ 102+ 103+ def Print (self , * args ):
104+ if self .check (): return
105+ if self ._active :
106+ return self .print (* args )
107+ 108+ with self as p :
109+ return p .print (* args )
110+ 111+ def print (self , * args ): return print (* args , sep = '\n ' , end = self ._end , file = self ._file )
112+ 113+ def getPPrintStr (self , o : any ) -> str :
114+ """
115+ :param o: object to be serialized
116+ :type o: any
117+ :return: formatted string of the passed object
118+ :rtype: str
119+ """
120+ s = self ._pp .pformat (o )
121+ if self ._use_double_quotes : s = s .replace ("'" , '"' )
122+ return s
123+ 124+ 125+ def print_exception (self , e : Exception ):
126+ if self .check (): return
127+ 128+ with self ._lock :
129+ traceback .print_exception (type (e ), e , e .__traceback__ )
130+ 131+ def get_func_details (self , func : callable , tag : str , result : Any , args , kwargs ) -> Tuple [Any , str , str , str , str ]:
132+ """
133+ :param result: result of the passed function or method
134+ :type result: Any
135+ :param func: function or method being called
136+ :type func: callable
137+ :param tag: line to print before function/method details
138+ :type tag: str
139+ :param args: args passed to function/method
140+ :param kwargs: keyword args passed to function/method
141+ :return: result, tag, name, signature, pp_result
142+ :rtype: Tuple[Any, str, str, str, str]
143+ """
144+ assert ('{0}' in tag )
145+ 146+ name = GetFunctionName (func )
147+ tag = tag .format (name )
148+ signature = self .getPPrintStr ({ 'args' : args , 'kwargs' : kwargs })
149+ pp_result = self .getPPrintStr (result )
150+ 151+ return result , tag , name , signature , pp_result
152+ 153+ def print_signature (self , func : callable , tag : str , * args , ** kwargs ):
154+ if not self .debug : return
155+ assert ('{0}' in tag )
156+ 157+ result = func (* args , ** kwargs )
158+ result , _tag , name , signature , pp_result = self .get_func_details (func , tag , result , args , kwargs )
159+ self .Print (tag , f'{ name } (\n { signature } \n )' , name , f'returned: \n { self .getPPrintStr (result )} ' )
160+ 161+ return result
122162
163+ @classmethod
164+ def Default (cls ): return cls (use_double_quotes = True , end = '\n \n ' )
123165
166+ @staticmethod
167+ def Set (_pp ):
168+ """
169+ :param _pp: Printer class instance to be used for all printing.
170+ :type _pp: Printer
171+ """
172+ assert (isinstance (_pp , Printer ))
173+ global pp
174+ pp = _pp
124175
125- def print_exception (e : Exception , * , DisableWhenNotDebug : bool = True ):
126- if check (DisableWhenNotDebug ): return
127176
128- with _lock :
129- traceback .print_exception (type (e ), e , e .__traceback__ )
130177
178+ pp : Printer = Printer .Default ()
131179
132180
133181def GetFuncModule (func : callable ) -> str : return func .__module__
@@ -138,38 +186,19 @@ def GetFunctionName(func: callable) -> str:
138186
139187
140188
141- def GetCallStack (INDENT : str ) -> Iterable [str ]: return [INDENT + line .strip () for line in traceback .format_stack ()][:- 1 ]
142- def GetCallStackAsString (INDENT : str ) -> str : return '\n ' .join (GetCallStack (INDENT ))
143- 144- 145- 146- def get_func_details (func : callable , tag : str , result : Any , args , kwargs ) -> Tuple [Any , str , str , str , str ]:
189+ def PRINT (title : str , * args , tag : str = pp .TITLE_TAG , ** kwargs ):
147190 """
148- :param result: result of the passed function or method
149- :type result: Any
150- :param func: function or method being called
151- :type func: callable
152- :param tag: line to print before function/method details
191+ :param tag: identifer to seprate calls
153192 :type tag: str
154- :param args: args passed to function/method
155- :param kwargs: keyword args passed to function/method
156- :return: result, tag, name, signature, pp_result
157- :rtype: Tuple[Any, str, str, str, str]
193+ :param title: message to start the Print, to make it easier to find it.
194+ :type title: str
158195 """
159- assert ('{0}' in tag )
160- 161- name = GetFunctionName (func )
162- tag = tag .format (name )
163- signature = getPPrintStr ({ 'args' : args , 'kwargs' : kwargs })
164- pp_result = getPPrintStr (result )
196+ with pp as p :
197+ p .Print (tag .format (title ))
198+ return p .pprint (dict (args = args , kwargs = kwargs ))
165199
166- return result , tag , name , signature , pp_result
167- def print_signature (func : callable , tag : str , * args , ** kwargs ):
168- if not debug : return
169- assert ('{0}' in tag )
170200
171- result = func (* args , ** kwargs )
172- result , _tag , name , signature , pp_result = get_func_details (func , tag , result , args , kwargs )
173- PrintLines (tag , f'{ name } (\n { signature } \n )' , name , f'returned: \n { getPPrintStr (result )} ' )
174201
175- return result
202+ def Print (* args ):
203+ with pp :
204+ return pp .Print (* args )
0 commit comments