Skip to content

Commit 158bd25

Browse files
Added the Argumentify module.
1 parent 9f4b9ad commit 158bd25

8 files changed

Lines changed: 696 additions & 60 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ Help this project by [Donation](DONATE.md)
66
Changes
77
-----------
88

9+
### 2.6.0
10+
11+
Added the `Argumentify` module. Check the examples.
12+
913
### 2.5.5
1014

1115
Fixed a bug in the `TreePrint` class.

README.md

Lines changed: 224 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -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

4144
Then you can install log21 using pip module:
4245

43-
```shell
46+
```bash
4447
python -m pip install log21 -U
4548
```
4649

4750
Or 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

5361
Changes
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

6371
Usage Examples:
6472
---------------
6573

66-
```python3
74+
### Basic Logging
75+
76+
```python
6777
import log21
6878

6979
log21.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
91103
import log21
92104
from 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
137151
import json
138152
import log21
139153

@@ -156,7 +170,9 @@ log21.tree_print(data)
156170

157171
------------------
158172

159-
```python3
173+
### Logging Window
174+
175+
```python
160176
import log21
161177

162178
window = 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
202220
import 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+
238449
About
239450
-----
240451
Author: CodeWriter21 (Mehrad Pooryoussof)

pyproject.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@ classifiers = [
2323
"Operating System :: MacOS :: MacOS X"
2424
]
2525
dependencies = [
26-
"webcolors"
26+
"webcolors",
27+
"docstring-parser"
2728
]
28-
version = "2.5.5"
29+
version = "2.6.0"
2930

3031
[tool.setuptools.packages.find]
3132
where = ["src"]

screen-shots/example-6.1.png

127 KB
Loading

screen-shots/example-6.2.png

144 KB
Loading

screen-shots/example-6.3.png

76 KB
Loading

0 commit comments

Comments
 (0)