-
Notifications
You must be signed in to change notification settings - Fork 5
/
logpy.py
124 lines (93 loc) · 3.19 KB
/
logpy.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
"""
LogPy
Unorthodox logging library
by Michal Hordecki
http://github.com/MHordecki/LogPy
"""
import datetime
from collections import Sequence
from threading import Lock
class Message(object):
def __init__(self, tags, args, kwargs):
self.tags = set(str(t) for t in tags)
self.args = args
self.kwargs = kwargs
self.date = datetime.datetime.now()
class LogPy(object):
"""
Logging object.
"""
def __init__(self, message_type = Message):
self.outputs = set()
self.message_type = message_type
self.lock = Lock()
def add_output(self, *args, **kwargs):
self.outputs.add(Output(*args, **kwargs))
def add_raw_output(self, output):
self.outputs.add(output)
def __call__(self, *tags, **kwargs):
"""
Log a new message with the given tags.
Returns another callable that accepts message content, instead.
Example usage: log('tag1', 'tag2')('log content')
"""
assert not kwargs or (kwargs and tuple(kwargs.keys()) == ('curry',)), 'Only \'curry\' keyword argument allowed.'
if kwargs.get('curry', False):
return self._spawn_curried(tags)
def second_step(*args, **kwargs):
msg = self.message_type(tags, args, kwargs)
for output in self.outputs:
output(msg)
return second_step
def _spawn_curried(self, tags):
def wrapped(*_tags, **kwargs):
return self(*(_tags + tags), **kwargs)
return wrapped
def log(self, *tags):
self(*tags)
class Output(object):
"""
Output manages where and in what form
your logs are saved.
"""
@staticmethod
def default_formatter(format_string):
def wrapped(message):
return format_string.format(date = message.date,
tags = ' '.join(message.tags),
args = message.args,
kwargs = message.kwargs,
message = message)
return wrapped
def __init__(self, output, formatter = None, filter = lambda x: True):
"""
Creates a new Output object.
"""
self.output = output
self.filters = filter if isinstance(filter, Sequence) else [filter]
self._formatter = None
self.formatter = formatter
@property
def formatter(self):
return self._formatter
@formatter.setter
def formatter(self, value):
if value is None:
self._formatter = self.default_formatter('{date} : {tags} : {args} {kwargs}\n')
elif isinstance(value, str):
self._formatter = self.default_formatter(value)
else:
self._formatter = value
def add_filter(self, filter):
"""
Adds a new filter. filter parameter is a callable that
returns a boolean value. Only messages for which all filters
evaluate to True will be processed by this output.
"""
self.filters.append(filter)
def __call__(self, message):
"""
Launches the process for the given message.
"""
if all(filter(message) for filter in self.filters):
self.output(self.formatter(message))