@@ -22,9 +22,12 @@ Features
2222 structure. It's also colorized XD.
2323+ ProgressBar : log21's progress bar can be used to show progress of a process in a beautiful way.
2424+ LoggingWindow : Helps you to log messages and debug your code in a window other than the console.
25- + CrashReporter : log21's crash reporter can be used to report crashes in different ways. You can use it to log crashes
26- to console or files or use it to receive crash reports of your program through email. And you can also define your own
27- crash reporter functions and use them instead!
25+ + CrashReporter : log21's crash reporter can be used to report crashes in different
26+ ways. You can use it to log crashes to console or files or use it to receive crash
27+ reports of your program through email. And you can also define your own crash
28+ reporter functions and use them instead!
29+ + Argumentify : You can use the argumentify feature to decrease the number of lines you
30+ need to write to parse command-line arguments. It's colored by the way!
2831+ Any idea? Feel free to [ open an issue] ( https://github.com/MPCodeWriter21/log21/issues ) or submit a pull request.
2932
3033![ issues] ( https://img.shields.io/github/issues/MPCodeWriter21/log21 )
@@ -40,30 +43,37 @@ python.
4043
4144Then you can install log21 using pip module:
4245
43- ``` shell
46+ ``` bash
4447python -m pip install log21 -U
4548```
4649
4750Or you can clone [ the repository] ( https://github.com/MPCodeWriter21/log21 ) and run:
4851
49- ``` shell
50- python setup.py install
52+ ``` bash
53+ pip install .
54+ ```
55+
56+ Or let the pip get it using git:
57+ ``` bash
58+ pip install git+https://github.com/MPCodeWriter21/log21
5159```
5260
5361Changes
5462-------
5563
56- ### 2.5.5
64+ ### 2.6.0
5765
58- Fixed a bug in the ` TreePrint ` class .
66+ Added the ` Argumentify ` module. Check the examples .
5967
6068[ Full CHANGELOG] ( https://github.com/MPCodeWriter21/log21/blob/master/CHANGELOG.md )
6169
6270
6371Usage Examples:
6472---------------
6573
66- ``` python3
74+ ### Basic Logging
75+
76+ ``` python
6777import log21
6878
6979log21.print(log21.get_color(' #FF0000' ) + ' This' + log21.get_color((0 , 255 , 0 )) + ' is' + log21.get_color(' Blue' ) +
@@ -87,7 +97,9 @@ logger.error(log21.get_colors('LightRed') + "I'm still here ;1")
8797
8898----------------
8999
90- ``` python3
100+ ### Argument Parsing (See Also: [ Argumentify] ( https://github.com/MPCodeWriter21/log21#argumentify ) )
101+
102+ ``` python
91103import log21
92104from log21 import ColorizingArgumentParser, get_logger, get_colors as gc
93105
@@ -133,7 +145,9 @@ logger.info(gc('LightWhite') + 'Done!')
133145
134146------------------
135147
136- ``` python3
148+ ### Pretty-Printing and Tree-Printing
149+
150+ ``` python
137151import json
138152import log21
139153
@@ -156,7 +170,9 @@ log21.tree_print(data)
156170
157171------------------
158172
159- ``` python3
173+ ### Logging Window
174+
175+ ``` python
160176import log21
161177
162178window = log21.get_logging_window(' My Logging Window' , width = 80 )
@@ -197,7 +213,9 @@ window.error(colored_text)
197213
198214------------------
199215
200- ``` python3
216+ ### ProgressBar
217+
218+ ``` python
201219# Example 1
202220import log21, time
203221
@@ -235,6 +253,199 @@ for i in range(84):
235253![ ProgressBar - Example 1] ( https://github.com/MPCodeWriter21/log21/raw/master/screen-shots/example-5.1.gif )
236254![ ProgressBar - Example 2] ( https://github.com/MPCodeWriter21/log21/raw/master/screen-shots/example-5.2.gif )
237255
256+ ------------------
257+
258+ ### Argumentify (Check out [ the manual way] ( https://github.com/MPCodeWriter21/log21#argument-parsing ) )
259+
260+ ``` python
261+ # Common Section
262+ import log21
263+
264+
265+ class ReversedText :
266+ def __init__ (self , text : str ):
267+ self ._text = text[::- 1 ]
268+
269+ def __str__ (self ):
270+ return self ._text
271+
272+ def __repr__ (self ):
273+ return f " < { self .__class__ .__name__ } (text=' { self ._text} ') at { hex (id (self ))} > "
274+
275+
276+ # Old way
277+ def main ():
278+ """ Here is my main function"""
279+ parser = log21.ColorizingArgumentParser()
280+ parser.add_argument(' --positional-arg' , ' -p' , action = ' store' , type = int ,
281+ required = True , help = " This argument is positional!" )
282+ parser.add_argument(' --optional-arg' , ' -o' , action = ' store' , type = ReversedText,
283+ help = " Whatever you pass here will be REVERSED!" )
284+ parser.add_argument(' --arg-with-default' , ' -a' , action = ' store' , default = 21 ,
285+ help = " The default value is 21" )
286+ parser.add_argument(' --additional-arg' , ' -A' , action = ' store' ,
287+ help = " This one is extra." )
288+ parser.add_argument(' --verbose' , ' -v' , action = ' store_true' ,
289+ help = " Increase verbosity" )
290+ args = parser.parse_args()
291+
292+ if args.verbose:
293+ log21.basic_config(level = ' DEBUG' )
294+
295+ log21.info(f " positional_arg = { args.positional_arg} " )
296+ log21.info(f " optional_arg = { args.optional_arg} " )
297+ log21.debug(f " arg_with_default = { args.arg_with_default} " )
298+ log21.debug(f " additional_arg = { args.additional_arg} " )
299+
300+
301+ if __name__ == ' __main__' :
302+ main()
303+
304+
305+ # New way
306+ def main (positional_arg : int , / , optional_arg : ReversedText, arg_with_default : int = 21 ,
307+ additional_arg = None , verbose : bool = False ):
308+ """ Some description
309+
310+ :param positional_arg: This argument is positional!
311+ :param optional_arg: Whatever you pass here will be REVERSED!
312+ :param arg_with_default: The default value is 21
313+ :param additional_arg: This one is extra.
314+ :param verbose: Increase verbosity
315+ """
316+ if verbose:
317+ log21.basic_config(level = ' DEBUG' )
318+
319+ log21.info(f " { positional_arg = } " )
320+ log21.info(f " { optional_arg = !s } " )
321+ log21.debug(f " { arg_with_default = } " )
322+ log21.debug(f " { additional_arg = !s } " )
323+
324+
325+ if __name__ == ' __main__' :
326+ log21.argumentify(main)
327+ ```
328+
329+ ![ Old-Way] ( https://github.com/MPCodeWriter21/log21/raw/master/screen-shots/example-6.1.png )
330+ ![ New-Way] ( https://github.com/MPCodeWriter21/log21/raw/master/screen-shots/example-6.2.png )
331+
332+ Example with multiple functions as entry-point:
333+
334+ ``` python
335+ import ast
336+ import operator
337+ from functools import reduce
338+
339+ import log21
340+
341+ # `safe_eval` Based on https://stackoverflow.com/a/9558001/1113207
342+ # Supported Operators
343+ operators = {
344+ ast.Add: operator.add,
345+ ast.Sub: operator.sub,
346+ ast.Mult: operator.mul,
347+ ast.Div: operator.truediv,
348+ ast.FloorDiv: operator.floordiv,
349+ ast.Pow: operator.pow,
350+ ast.BitXor: operator.xor,
351+ ast.USub: operator.neg
352+ }
353+
354+
355+ def safe_eval (expr : str ):
356+ """ Safely evaluate a mathematical expression.
357+
358+ >>> eval_expr('2^6')
359+ 4
360+ >>> eval_expr('2**6')
361+ 64
362+ >>> eval_expr('1 + 2*3**(4^5) / (6 + -7)')
363+ -5.0
364+
365+ :param expr: expression to evaluate
366+ :raises SyntaxError: on invalid expression
367+ :return: result of the evaluation
368+ """
369+ try :
370+ return _eval(ast.parse(expr, mode = ' eval' ).body)
371+ except (TypeError , KeyError , SyntaxError ):
372+ log21.error(f ' Invalid expression: { expr} ' )
373+ raise
374+
375+
376+ def _eval (node : ast.AST ):
377+ """ Internal implementation of `safe_eval`.
378+
379+ :param node: AST node to evaluate
380+ :raises TypeError: on invalid node
381+ :raises KeyError: on invalid operator
382+ :raises ZeroDivisionError: on division by zero
383+ :raises ValueError: on invalid literal
384+ :raises SyntaxError: on invalid syntax
385+ :return: result of the evaluation
386+ """
387+ if isinstance (node, ast.Num): # <number>
388+ return node.n
389+ if isinstance (node, ast.BinOp): # <left> <operator> <right>
390+ return operators[type (node.op)](_eval(node.left), _eval(node.right))
391+ if isinstance (node, ast.UnaryOp): # <operator> <operand> e.g., -1
392+ return operators[type (node.op)](_eval(node.operand))
393+ raise TypeError (node)
394+
395+
396+ # Example code
397+ def addition (* numbers : float ):
398+ """ Addition of numbers.
399+
400+ Args:
401+ numbers (float): numbers to add
402+ """
403+ if len (numbers) < 2 :
404+ log21.error(' At least two numbers are required! Use `-n`.' )
405+ return
406+ log21.info(f ' Result: { sum (numbers)} ' )
407+
408+
409+ def multiplication (* numbers : float ):
410+ """ Multiplication of numbers.
411+
412+ Args:
413+ numbers (float): numbers to multiply
414+ """
415+ if len (numbers) < 2 :
416+ log21.error(' At least two numbers are required! Use `-n`.' )
417+ return
418+ log21.info(f ' Result: { reduce (lambda x , y : x * y, numbers)} ' )
419+
420+
421+ def calc (* inputs : str , verbose : bool = False ):
422+ """ Calculate numbers.
423+
424+ :param inputs: numbers and operators
425+ """
426+ expression = ' ' .join(inputs)
427+
428+ if len (expression) < 3 :
429+ log21.error(' At least two numbers and one operator are required! Use `-i`.' )
430+ return
431+
432+ if verbose:
433+ log21.basic_config(level = ' DEBUG' )
434+
435+ log21.debug(f ' Expression: { expression} ' )
436+ try :
437+ log21.info(f ' Result: { safe_eval(expression)} ' )
438+ except (TypeError , KeyError , SyntaxError ):
439+ pass
440+
441+
442+ if __name__ == " __main__" :
443+ log21.argumentify({' add' : addition, ' mul' : multiplication, ' calc' : calc})
444+ ```
445+
446+ ![ multi-entry] ( https://github.com/MPCodeWriter21/log21/raw/master/screen-shots/example-6.3.png )
447+
448+
238449About
239450-----
240451Author: CodeWriter21 (Mehrad Pooryoussof)
0 commit comments