Skip to content

Commit 30090ba

Browse files
authored
Creating sample module for logging (#5)
1 parent d4c24b7 commit 30090ba

File tree

5 files changed

+91
-38
lines changed

5 files changed

+91
-38
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,3 +195,6 @@ cython_debug/
195195

196196
# PyCharm
197197
.idea
198+
199+
# user generated files
200+
*output.log

src/learning/decorating.py

Lines changed: 0 additions & 38 deletions
This file was deleted.

src/learning/logging/__init__.py

Whitespace-only changes.

src/learning/logging/mylog.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
"""
2+
Decorators receive a function to be executed when it is called.
3+
However, some other action can be done before or after its execution.
4+
The idea is to encapsulate some behaviour that should happen on top of
5+
some operation and can be reused everywhere it is needed.
6+
"""
7+
from functools import wraps
8+
from enum import Enum
9+
from datetime import datetime
10+
11+
class Level(Enum):
12+
NONE = 0
13+
INFO = 1
14+
DEBUG = 2
15+
16+
LOG_FILE_NAME = "output.log"
17+
18+
# If you’ve called @name without arguments, then the
19+
# decorated function will be passed in as _func. If you’ve
20+
# called it with arguments, then _func will be None, and
21+
# some of the keyword arguments may have been changed from
22+
# their default values. The asterisk in the argument list means
23+
# that you can’t call the remaining arguments as positional arguments.
24+
def logme(_func=None, *, level: Level = Level.NONE):
25+
def decorated_function(func):
26+
@wraps(func) # this ensures docstring, function name, arguments list, etc. are all copied
27+
# to the wrapped function - instead of being replaced with wrapper's info
28+
def wrapper(*args, **kwargs):
29+
if show_info():
30+
with open(LOG_FILE_NAME, "a+") as log_file:
31+
log_file.writelines("[{}] Executing function: {}\n".format(get_current_timestamp(), func.__name__))
32+
33+
result = func(*args, **kwargs)
34+
35+
if show_debug():
36+
with open(LOG_FILE_NAME, "a+") as log_file:
37+
log_file.writelines("[{}] Result of function {} is: {}\n".format(get_current_timestamp(), func.__name__, result))
38+
39+
return result
40+
41+
def get_current_timestamp():
42+
return datetime.now().strftime('%Y%m%d-%H:%M:%S')
43+
44+
def show_info():
45+
if level == Level.NONE:
46+
return False
47+
48+
# DEBUG also shows INFO
49+
return level._value_ <= Level.DEBUG._value_
50+
51+
def show_debug():
52+
# INFO does not show DEBUG
53+
return level != Level.NONE and level == Level.DEBUG
54+
55+
return wrapper
56+
57+
# In this case, you called the decorator with arguments.
58+
# Return a decorator function that takes a function as an
59+
# argument and returns a wrapper function.
60+
if _func is None:
61+
return decorated_function
62+
# In this case, you called the decorator without arguments.
63+
# Apply the decorator to the function immediately.
64+
else:
65+
return decorated_function(_func)
66+

src/learning/using_mylog.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from logging.mylog import logme, Level
2+
3+
@logme
4+
def add(a, b):
5+
return a + b
6+
7+
@logme(level=Level.INFO)
8+
def subtract(a, b):
9+
return a - b
10+
11+
@logme(level=Level.DEBUG)
12+
def multiply(a, b):
13+
return a * b
14+
15+
@logme
16+
def divide(a, b):
17+
return a / b
18+
19+
print("Adding two numbers: " + str(add(1, 2)))
20+
print("Subtracting two numbers: " + str(subtract(8, 3)))
21+
print("Multiplying two numbers: " + str(multiply(5, 6)))
22+
print("Dividing two numbers: " + str(divide(45, 5)))

0 commit comments

Comments
 (0)