Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
P
pydevutils
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Deploy
Releases
Container registry
Model registry
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Art
pydevutils
Commits
d2878063
Commit
d2878063
authored
7 years ago
by
Art
Browse files
Options
Downloads
Patches
Plain Diff
Colored logger from hshdev
parents
No related branches found
No related tags found
No related merge requests found
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
colored_logger.py
+98
-0
98 additions, 0 deletions
colored_logger.py
with
98 additions
and
0 deletions
colored_logger.py
0 → 100644
+
98
−
0
View file @
d2878063
"""
This module decorates methods of Logger class.
It
'
s quite harmless, unless you use some weird non-tty stdout/stderr while DEBUG-ing.
This hack should be auto-loaded by it
'
s app.
If you don
'
t use the app, just import this file to apply the hack.
"""
import
sys
import
logging
import
itertools
import
random
# Control sequences (just google VT52 to see the compatibility burden straight from 1975)
color_set
=
"
\x1b
[{}m{}
"
color_reset
=
"
\x1b
[0m
"
# useless stuff displayed before applying patches... yes, I felt very bored
intro_words
=
[
"
magic
"
,
"
MaGiC
"
,
"
voodoo
"
,
"
sorcery
"
,
"
wizardry
"
,
"
witchery
"
,
"
foobar
"
,
"
rainbow
"
]
intro_adjectives
=
[
"
colourful
"
,
"
evil
"
,
"
fairy
"
,
"
random
"
]
intro_colors
=
[
34
,
36
,
32
,
33
,
35
]
decorate_info
=
{
# method names and their desired highlight colors
"
debug
"
:
"
1;90
"
,
"
info
"
:
"
1;32
"
,
"
warning
"
:
"
1;33
"
,
"
error
"
:
"
1;91
"
,
"
critical
"
:
"
1;95
"
,
"
exception
"
:
"
1;95
"
,
}
if
settings
.
DEBUG
:
# probably PyCharm or some other IDE with own stream handling
# useless foo
intro_seq
=
zip
(
itertools
.
cycle
(
intro_colors
),
random
.
choice
(
intro_words
))
print
(
"
{adj} {word}{reset}:
"
.
format
(
adj
=
random
.
choice
(
intro_adjectives
).
capitalize
(),
word
=
str
().
join
(
color_set
.
format
(
*
symbol
)
for
symbol
in
intro_seq
),
reset
=
color_reset
,
),
end
=
"
"
)
# Patching handlers: Python logging.StreamHandler targets stderr by default,
# therefore Django example config does, therefore our logging config also does,
# so PyCharm believes every line of log is error. Well... Fixing it now.
# Existing loggers first.
patched
=
list
()
for
logger
in
logging
.
Logger
.
manager
.
loggerDict
.
values
():
for
handler
in
getattr
(
logger
,
"
handlers
"
,
list
()):
if
isinstance
(
handler
,
logging
.
StreamHandler
):
if
handler
.
stream
==
sys
.
stderr
:
handler
.
stream
=
sys
.
stdout
patched
.
append
(
handler
)
# Future loggers (they should be initially created with the proper stream).
original_constructor
=
logging
.
StreamHandler
.
__init__
# must grab a reference outside of the lambda
logging
.
StreamHandler
.
__init__
=
lambda
zelf
,
stream
=
None
:
original_constructor
(
zelf
,
stream
or
sys
.
stdout
)
# the isatty() stuff below solved some problems in the past, I'm not sure anymore which exactly
try
:
stdout_tty
=
sys
.
stdout
.
isatty
()
except
Exception
:
stdout_tty
=
False
if
not
stdout_tty
:
patched
.
append
(
sys
.
stdout
.
isatty
)
sys
.
stdout
.
isatty
=
lambda
:
True
# stdout is now a TTY no matter what
# reporting
print
(
"
applied {n} logging patches.
"
.
format
(
n
=
len
(
patched
)))
logging
.
getLogger
().
debug
(
"
Logging patches: {}.
"
.
format
(
"
,
"
.
join
(
str
(
e
)
for
e
in
patched
)
or
"
none
"
))
def
_apply_color_to_msg
(
msg
,
color
,
extras
):
return
""
.
join
([
color_set
.
format
(
color
,
extras
),
str
(
msg
),
color_reset
])
def
decorate_for_tty
(
method
,
color
=
"
1;39
"
,
extras
=
""
):
"""
it also knows how to decorate bound methods, but it is not used anymore
"""
method_is_bound
=
bool
(
getattr
(
method
,
"
__self__
"
,
None
))
# existing loggers cause bound methods
msg_index
=
0
if
method_is_bound
else
1
# message argument is located there
def
wrapper
(
*
args
,
**
kwargs
):
args
=
list
(
args
)
# it's an immutable tuple when received
args
[
msg_index
]
=
_apply_color_to_msg
(
args
[
msg_index
],
color
,
extras
)
return
method
(
*
args
,
**
kwargs
)
return
wrapper
for
entity
in
[
logging
.
Logger
]:
for
method_name
,
color_str
in
decorate_info
.
items
():
if
isinstance
(
entity
,
logging
.
Logger
)
or
entity
is
logging
.
Logger
:
new_method
=
decorate_for_tty
(
getattr
(
entity
,
method_name
),
color_str
)
setattr
(
entity
,
method_name
,
new_method
)
else
:
pass
# that should be a placeholder object (non-public API), ignoring it
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment