Patchwork [bitbake-devel,v2] bitbake: Colorize knotty interactive console output

login
register
mail settings
Submitter Seth Bollinger
Date Nov. 11, 2012, 3:17 p.m.
Message ID <CA+JN8xNzAvDdt4bgS=z536YciYVAvZGE2+Z=qQa1XP4HCE8=gg@mail.gmail.com>
Download mbox | patch
Permalink /patch/38847/
State New
Headers show

Comments

Seth Bollinger - Nov. 11, 2012, 3:17 p.m.
Add bold color output to log level name and standard color output to log msg
when bitbake is run from an iteractive console.  Color output is only
enabled
if the terminal supports color.

Signed-off-by: Seth Bollinger <seth.boll@gmail.com>
---
 bitbake/lib/bb/msg.py       |   40 ++++++++++++++++++++++++++++++++++++++++
 bitbake/lib/bb/ui/knotty.py |    6 +++++-
 2 files changed, 45 insertions(+), 1 deletions(-)
Chris Larson - Nov. 11, 2012, 10:54 p.m.
On Sun, Nov 11, 2012 at 8:17 AM, Seth Bollinger <seth.boll@gmail.com> wrote:

> @@ -67,6 +86,8 @@ class BBLogFormatter(logging.Formatter):
>          if record.levelno == self.PLAIN:
>              msg = record.getMessage()
>          else:
> +            if self.color_enabled:
> +                self.colorize(record)
>


I'm not seeing your definition of color_enabled in the constructor.
Wouldn't this attribute not exist when it's first created, before
enable_color() is called? Have you tested this with a non-interactive
terminal? I'd think you'd want a self.color_enabled = False in the
constructor for the formatter.
Seth Bollinger - Nov. 12, 2012, 2:02 a.m.
color_enabled is initialized on line 58 of msg.py.  I did this in the same
way as other class variables are initialized.

    levelnames = {
        DEBUG3   : 'DEBUG',
        DEBUG2   : 'DEBUG',
        DEBUG   : 'DEBUG',
        VERBOSE: 'NOTE',
        NOTE    : 'NOTE',
        PLAIN  : '',
        WARNING : 'WARNING',
        ERROR   : 'ERROR',
        CRITICAL: 'ERROR',
    }

    color_enabled = False
    BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(30,38)


On Sun, Nov 11, 2012 at 4:54 PM, Chris Larson <clarson@kergoth.com> wrote:

>
>
> On Sun, Nov 11, 2012 at 8:17 AM, Seth Bollinger <seth.boll@gmail.com>wrote:
>
>> @@ -67,6 +86,8 @@ class BBLogFormatter(logging.Formatter):
>>          if record.levelno == self.PLAIN:
>>              msg = record.getMessage()
>>          else:
>> +            if self.color_enabled:
>> +                self.colorize(record)
>>
>
>
> I'm not seeing your definition of color_enabled in the constructor.
> Wouldn't this attribute not exist when it's first created, before
> enable_color() is called? Have you tested this with a non-interactive
> terminal? I'd think you'd want a self.color_enabled = False in the
> constructor for the formatter.
> --
> Christopher Larson
>
Chris Larson - Nov. 12, 2012, 2:24 a.m.
On Sun, Nov 11, 2012 at 7:02 PM, Seth Bollinger <seth.boll@gmail.com> wrote:

> color_enabled is initialized on line 58 of msg.py.  I did this in the same
> way as other class variables are initialized.
>
>     levelnames = {
>         DEBUG3   : 'DEBUG',
>         DEBUG2   : 'DEBUG',
>         DEBUG   : 'DEBUG',
>         VERBOSE: 'NOTE',
>         NOTE    : 'NOTE',
>         PLAIN  : '',
>         WARNING : 'WARNING',
>         ERROR   : 'ERROR',
>         CRITICAL: 'ERROR',
>     }
>
>     color_enabled = False
>


Ah! I missed that, thanks for clarifying. Other than that question, it
looks pretty decent to me. We'll see if Richard agrees.
Richard Purdie - Nov. 13, 2012, 2:23 p.m.
On Sun, 2012-11-11 at 09:17 -0600, Seth Bollinger wrote:
> Add bold color output to log level name and standard color output to
> log msg
> when bitbake is run from an iteractive console.  Color output is only
> enabled
> if the terminal supports color.
>
> Signed-off-by: Seth Bollinger <seth.boll@gmail.com>
> ---
>  bitbake/lib/bb/msg.py       |   40
> ++++++++++++++++++++++++++++++++++++++++
>  bitbake/lib/bb/ui/knotty.py |    6 +++++-
>  2 files changed, 45 insertions(+), 1 deletions(-)

I love the idea. I tried testing it and realised that it doesn't work in
my black text on a white background terminals though, the result of the
patch was unreadable :(

Cheers,

Richard
Seth Bollinger - Nov. 13, 2012, 2:45 p.m.
I'm not sure how best to resolve this.  Would you like me to add some code
to try and detect background color?  This seems like it might be more
complex than it's worth...

Or would it be better to have a selectable light background color set?  If
you think light background is more common (I dislike staring at large
blocks of white :)) it could default to the light color set.

Thanks!

Seth


On Tue, Nov 13, 2012 at 8:23 AM, Richard Purdie <
richard.purdie@linuxfoundation.org> wrote:

> On Sun, 2012-11-11 at 09:17 -0600, Seth Bollinger wrote:
> > Add bold color output to log level name and standard color output to
> > log msg
> > when bitbake is run from an iteractive console.  Color output is only
> > enabled
> > if the terminal supports color.
> >
> > Signed-off-by: Seth Bollinger <seth.boll@gmail.com>
> > ---
> >  bitbake/lib/bb/msg.py       |   40
> > ++++++++++++++++++++++++++++++++++++++++
> >  bitbake/lib/bb/ui/knotty.py |    6 +++++-
> >  2 files changed, 45 insertions(+), 1 deletions(-)
>
> I love the idea. I tried testing it and realised that it doesn't work in
> my black text on a white background terminals though, the result of the
> patch was unreadable :(
>
> Cheers,
>
> Richard
>
>
>
Richard Purdie - Nov. 13, 2012, 3:22 p.m.
On Tue, 2012-11-13 at 08:45 -0600, Seth Bollinger wrote:
> I'm not sure how best to resolve this.  Would you like me to add some
> code to try and detect background color?  This seems like it might be
> more complex than it's worth...
>
> Or would it be better to have a selectable light background color
> set?  If you think light background is more common (I dislike staring
> at large blocks of white :)) it could default to the light color set.

I have not looked into this and am not an expert on terminals and colour
control of them. I don't know how we can solve this but the current
situation where it prints white on white on my terminal is clearly
unacceptable. This has to be a problem others have run into and solved
before though...

Cheers,

Richard
Jason Wessel - Nov. 13, 2012, 10:36 p.m.
On 11/13/2012 09:22 AM, Richard Purdie wrote:
> On Tue, 2012-11-13 at 08:45 -0600, Seth Bollinger wrote:
>> I'm not sure how best to resolve this.  Would you like me to add some
>> code to try and detect background color?  This seems like it might be
>> more complex than it's worth...
>>
>> Or would it be better to have a selectable light background color
>> set?  If you think light background is more common (I dislike staring
>> at large blocks of white :)) it could default to the light color set.
> I have not looked into this and am not an expert on terminals and colour
> control of them. I don't know how we can solve this but the current
> situation where it prints white on white on my terminal is clearly
> unacceptable. This has to be a problem others have run into and solved
> before though...


If you are planning to colorize things, my recommendation would be to take the "middle ground" and use the transparency instead of using white which should work in general on any modern terminal.

Change the patch a bit like this:
+    color_enabled = False
+    BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(30,38)

    BASECOLOR, BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(29,38)

+
+    COLORS = {
+        DEBUG3  : CYAN,
+        DEBUG2  : CYAN,
+        DEBUG   : CYAN,
+        VERBOSE : BASECOLOR,
+        NOTE    : BASECOLOR,
+        PLAIN   : BASECOLOR,
+        WARNING : YELLOW,
+        ERROR   : RED,
+        CRITICAL: RED,
+    }


Most of the time terminals are either "dark" or "light", and default color is always set to -1 in the curses interface.  For example, the attached patch will allow the patch to work on my "lawngreen" default xterms as well as more typical defaults for gnome-terminal or rxvt.

Cheers,
Jason.
Seth Bollinger - Nov. 14, 2012, 1:18 p.m.
Thanks!  I've tested this and it works on my dark color scheme (it's better
actually :)).  I also tested on white and it looks fine.  If Richard is ok
with this solution, I'll make the changes and submit another patch.

Seth


On Tue, Nov 13, 2012 at 4:36 PM, Jason Wessel <jason.wessel@windriver.com>wrote:

> On 11/13/2012 09:22 AM, Richard Purdie wrote:
> > On Tue, 2012-11-13 at 08:45 -0600, Seth Bollinger wrote:
> >> I'm not sure how best to resolve this.  Would you like me to add some
> >> code to try and detect background color?  This seems like it might be
> >> more complex than it's worth...
> >>
> >> Or would it be better to have a selectable light background color
> >> set?  If you think light background is more common (I dislike staring
> >> at large blocks of white :)) it could default to the light color set.
> > I have not looked into this and am not an expert on terminals and colour
> > control of them. I don't know how we can solve this but the current
> > situation where it prints white on white on my terminal is clearly
> > unacceptable. This has to be a problem others have run into and solved
> > before though...
>
>
> If you are planning to colorize things, my recommendation would be to take
> the "middle ground" and use the transparency instead of using white which
> should work in general on any modern terminal.
>
> Change the patch a bit like this:
> +    color_enabled = False
> +    BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(30,38)
>
>     BASECOLOR, BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE =
> range(29,38)
>
> +
> +    COLORS = {
> +        DEBUG3  : CYAN,
> +        DEBUG2  : CYAN,
> +        DEBUG   : CYAN,
> +        VERBOSE : BASECOLOR,
> +        NOTE    : BASECOLOR,
> +        PLAIN   : BASECOLOR,
> +        WARNING : YELLOW,
> +        ERROR   : RED,
> +        CRITICAL: RED,
> +    }
>
>
> Most of the time terminals are either "dark" or "light", and default color
> is always set to -1 in the curses interface.  For example, the attached
> patch will allow the patch to work on my "lawngreen" default xterms as well
> as more typical defaults for gnome-terminal or rxvt.
>
> Cheers,
> Jason.
>
Richard Purdie - Nov. 14, 2012, 1:22 p.m.
On Wed, 2012-11-14 at 07:18 -0600, Seth Bollinger wrote:
> Thanks!  I've tested this and it works on my dark color scheme (it's
> better actually :)).  I also tested on white and it looks fine.  If
> Richard is ok with this solution, I'll make the changes and submit
> another patch.
> 
It sounds promising, I would like to try the patch...

Cheers,

Richard
Robert Yang - Nov. 22, 2012, 3:36 a.m.
I'm afraid that this patch doesn't work well, it will output chaotic message
after the "Ctrl-Z" and "fg":

On Fedora 17 64 bit
$ screen
$ bitbake xxx
$ C-Z
$ fg

then it will output like this:

(164 of 9052): 
                                                                          0: 
linux-libc-headers-3.4.3-r0 do_fetch (pid 10632) 
           Currently 4 running tasks (164 of 9052):
          0: linux-libc-headers-3.4.3-r0 do_fetch (pid 1Currently 4 running 
tasks (165 of 9052): 
 
0: linux-libc-headers-3.4.3-r0 do_fetch (pid 1Currently 5 running tasks (165 of 
9052): 
                                                                  0: 
linux-libc-headers-3.4.3-r0 do_fetch (pid 10632)
      Currently 4 running tasks (165 of 9052): 
 
                           0: linux-libc-headers-3.4.3-r0 do_fetch (pid 
1Currently 4 running tasks (166 of 9052): 
 
                      0: linux-libc-headers-3.4.3-r0 do_fetch (pid 1Currently 5 
running tasks (166 of 9052):
 
0: linux-libc-headers-3.4.3-r0 do_fetch (pid 10632) 
                    Currently 4 running tasks (166 of 9052): 
 
                                         0: linux-libc-headers-3.4.3-r0 do_fetch 
(pid 1Currently 4 running tasks (167 of 9052): 
 
                           0: linux-libc-headers-3.4.3-r0 do_fetch (pid 
1Currently 5 running tasks (167 of 9052):


Revert this patch would be OK.

// Robert

On 11/11/2012 11:17 PM, Seth Bollinger wrote:
> Add bold color output to log level name and standard color output to log msg
> when bitbake is run from an iteractive console.  Color output is only
> enabled
> if the terminal supports color.
>
> Signed-off-by: Seth Bollinger <seth.boll@gmail.com>
> ---
>   bitbake/lib/bb/msg.py       |   40 ++++++++++++++++++++++++++++++++++++++++
>   bitbake/lib/bb/ui/knotty.py |    6 +++++-
>   2 files changed, 45 insertions(+), 1 deletions(-)
>
> diff --git a/bitbake/lib/bb/msg.py b/bitbake/lib/bb/msg.py
> index 9b39325..68b2ad7 100644
> --- a/bitbake/lib/bb/msg.py
> +++ b/bitbake/lib/bb/msg.py
> @@ -55,6 +55,25 @@ class BBLogFormatter(logging.Formatter):
>           CRITICAL: 'ERROR',
>       }
>
> +    color_enabled = False
> +    BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(30,38)
> +
> +    COLORS = {
> +        DEBUG3  : CYAN,
> +        DEBUG2  : CYAN,
> +        DEBUG   : CYAN,
> +        VERBOSE : WHITE,
> +        NOTE    : WHITE,
> +        PLAIN   : WHITE,
> +        WARNING : YELLOW,
> +        ERROR   : RED,
> +        CRITICAL: RED,
> +    }
> +
> +    BLD = '\033[1;%dm'
> +    STD = '\033[%dm'
> +    RST = '\033[0m'
> +
>       def getLevelName(self, levelno):
>           try:
>               return self.levelnames[levelno]
> @@ -67,6 +86,8 @@ class BBLogFormatter(logging.Formatter):
>           if record.levelno == self.PLAIN:
>               msg = record.getMessage()
>           else:
> +            if self.color_enabled:
> +                self.colorize(record)
>               msg = logging.Formatter.format(self, record)
>
>           if hasattr(record, 'bb_exc_info'):
> @@ -75,6 +96,25 @@ class BBLogFormatter(logging.Formatter):
>               msg += '\n' + ''.join(formatted)
>           return msg
>
> +    def colorize(self, record):
> +        color = self.COLORS[record.levelno]
> +        if self.color_enabled and color is not None:
> +            record.levelname = "".join([self.BLD % color,
> record.levelname, self.RST])
> +            record.msg = "".join([self.STD % color, record.msg, self.RST])
> +
> +    def enable_color(self):
> +        import curses
> +        try:
> +            win = None
> +            win = curses.initscr()
> +            if curses.has_colors():
> +                self.color_enabled = True
> +        except:
> +            pass
> +        finally:
> +            if win is not None:
> +                curses.endwin()
> +
>   class BBLogFilter(object):
>       def __init__(self, handler, level, debug_domains):
>           self.stdlevel = level
> diff --git a/bitbake/lib/bb/ui/knotty.py b/bitbake/lib/bb/ui/knotty.py
> index b99a121..d9aa973 100644
> --- a/bitbake/lib/bb/ui/knotty.py
> +++ b/bitbake/lib/bb/ui/knotty.py
> @@ -238,12 +238,16 @@ def main(server, eventHandler, tf = TerminalFilter):
>       helper = uihelper.BBUIHelper()
>
>       console = logging.StreamHandler(sys.stdout)
> -    format = bb.msg.BBLogFormatter("%(levelname)s: %(message)s")
> +    format_str = "%(levelname)s: %(message)s"
> +    format = bb.msg.BBLogFormatter(format_str)
> +    if interactive:
> +        format.enable_color()
>       bb.msg.addDefaultlogFilter(console)
>       console.setFormatter(format)
>       logger.addHandler(console)
>       if consolelogfile:
>           bb.utils.mkdirhier(os.path.dirname(consolelogfile))
> +        format = bb.msg.BBLogFormatter(format_str)
>           consolelog = logging.FileHandler(consolelogfile)
>           bb.msg.addDefaultlogFilter(consolelog)
>           consolelog.setFormatter(format)
>
>
>
> _______________________________________________
> bitbake-devel mailing list
> bitbake-devel@lists.openembedded.org
> http://lists.linuxtogo.org/cgi-bin/mailman/listinfo/bitbake-devel
>
Richard Purdie - Nov. 25, 2012, 9:37 p.m.
On Thu, 2012-11-22 at 11:36 +0800, Robert Yang wrote:
> I'm afraid that this patch doesn't work well, it will output chaotic message
> after the "Ctrl-Z" and "fg":

I could reproduce this and have pushed a fix for it.

Cheers,

Richard

Patch

diff --git a/bitbake/lib/bb/msg.py b/bitbake/lib/bb/msg.py
index 9b39325..68b2ad7 100644
--- a/bitbake/lib/bb/msg.py
+++ b/bitbake/lib/bb/msg.py
@@ -55,6 +55,25 @@  class BBLogFormatter(logging.Formatter):
         CRITICAL: 'ERROR',
     }

+    color_enabled = False
+    BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(30,38)
+
+    COLORS = {
+        DEBUG3  : CYAN,
+        DEBUG2  : CYAN,
+        DEBUG   : CYAN,
+        VERBOSE : WHITE,
+        NOTE    : WHITE,
+        PLAIN   : WHITE,
+        WARNING : YELLOW,
+        ERROR   : RED,
+        CRITICAL: RED,
+    }
+
+    BLD = '\033[1;%dm'
+    STD = '\033[%dm'
+    RST = '\033[0m'
+
     def getLevelName(self, levelno):
         try:
             return self.levelnames[levelno]
@@ -67,6 +86,8 @@  class BBLogFormatter(logging.Formatter):
         if record.levelno == self.PLAIN:
             msg = record.getMessage()
         else:
+            if self.color_enabled:
+                self.colorize(record)
             msg = logging.Formatter.format(self, record)

         if hasattr(record, 'bb_exc_info'):
@@ -75,6 +96,25 @@  class BBLogFormatter(logging.Formatter):
             msg += '\n' + ''.join(formatted)
         return msg

+    def colorize(self, record):
+        color = self.COLORS[record.levelno]
+        if self.color_enabled and color is not None:
+            record.levelname = "".join([self.BLD % color,
record.levelname, self.RST])
+            record.msg = "".join([self.STD % color, record.msg, self.RST])
+
+    def enable_color(self):
+        import curses
+        try:
+            win = None
+            win = curses.initscr()
+            if curses.has_colors():
+                self.color_enabled = True
+        except:
+            pass
+        finally:
+            if win is not None:
+                curses.endwin()
+
 class BBLogFilter(object):
     def __init__(self, handler, level, debug_domains):
         self.stdlevel = level
diff --git a/bitbake/lib/bb/ui/knotty.py b/bitbake/lib/bb/ui/knotty.py
index b99a121..d9aa973 100644
--- a/bitbake/lib/bb/ui/knotty.py
+++ b/bitbake/lib/bb/ui/knotty.py
@@ -238,12 +238,16 @@  def main(server, eventHandler, tf = TerminalFilter):
     helper = uihelper.BBUIHelper()

     console = logging.StreamHandler(sys.stdout)
-    format = bb.msg.BBLogFormatter("%(levelname)s: %(message)s")
+    format_str = "%(levelname)s: %(message)s"
+    format = bb.msg.BBLogFormatter(format_str)
+    if interactive:
+        format.enable_color()
     bb.msg.addDefaultlogFilter(console)
     console.setFormatter(format)
     logger.addHandler(console)
     if consolelogfile:
         bb.utils.mkdirhier(os.path.dirname(consolelogfile))
+        format = bb.msg.BBLogFormatter(format_str)
         consolelog = logging.FileHandler(consolelogfile)
         bb.msg.addDefaultlogFilter(consolelog)
         consolelog.setFormatter(format)