Repository: ManiacalLabs/BiblioPixel
Pull request #770 (2018-04-19 10:38:16)

Catch and report tracebacks in threads

adammhaile: +1

On Thu, Apr 19, 2018 at 6:38 AM, Tom Swirly <notifications@github.com>
wrote:

> ------------------------------
> You can view, comment on, or merge this pull request online at:
>
>   https://github.com/ManiacalLabs/BiblioPixel/pull/770
> Commit Summary
>
>    - Catch and report tracebacks in threads
>
> File Changes
>
>    - *M* bibliopixel/util/threads/runnable.py
>    <https://github.com/ManiacalLabs/BiblioPixel/pull/770/files#diff-0>
>    (2)
>
> Patch Links:
>
>    - https://github.com/ManiacalLabs/BiblioPixel/pull/770.patch
>    - https://github.com/ManiacalLabs/BiblioPixel/pull/770.diff
>
> —
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/ManiacalLabs/BiblioPixel/pull/770>, or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AA6a6rjtU59f7yV8O8HQ5Gb1_NW6Pxtxks5tqGkYgaJpZM4TbjX0>
> .
>


Patch:
diff --git a/bibliopixel/layout/layout.py b/bibliopixel/layout/layout.py
index 96fb4b3..06486af 100644
--- a/bibliopixel/layout/layout.py
+++ b/bibliopixel/layout/layout.py
@@ -2,6 +2,7 @@ import copy, time
 from .. import util
 from .. project import attributes, data_maker, fields
 from .. util.threads.update_threading import UpdateThreading
+from .. util.color_list import to_triplets
 
 
 class Layout(object):
@@ -129,14 +130,7 @@ class Layout(object):
         """
         if not len(color_list):
             return
-        try:
-            color_list[0][0]
-        except TypeError:
-            # It's a 1-dimensional list
-            extra = len(color_list) % 3
-            if extra:
-                color_list = color_list[:-extra]
-            color_list = list(zip(*[iter(color_list)] * 3))
+        color_list = to_triplets(color_list)
 
         size = len(self._colors) - offset
         if len(color_list) > size:
diff --git a/bibliopixel/project/types/colors.py b/bibliopixel/project/types/colors.py
index 0c795d9..63d99c1 100644
--- a/bibliopixel/project/types/colors.py
+++ b/bibliopixel/project/types/colors.py
@@ -1,5 +1,6 @@
 import functools
 from . import color
+from ... util import color_list
 
 USAGE = """
 Colors is a list of colors.  Each color can be:
@@ -19,4 +20,9 @@ def make(c):
 @make.register(tuple)
 @make.register(list)
 def _(c):
-    return [color.make(i) for i in c]
+    return [color.make(i) for i in color_list.to_triplets(c)]
+
+
+@make.register(str)
+def _(s):
+    return make([s])
diff --git a/bibliopixel/util/color_list.py b/bibliopixel/util/color_list.py
index 1ec6969..bfdbb45 100644
--- a/bibliopixel/util/color_list.py
+++ b/bibliopixel/util/color_list.py
@@ -91,3 +91,25 @@ class Mixer:
         for source, level in zip(self.sources, self.levels):
             self.buffer = self.math.add(
                 self.color_list, source, level * master, self.buffer)
+
+
+def to_triplets(colors):
+    """
+    Coerce a list into a list of triplets.
+
+    If `colors` is a list of lists or strings, return it as is.  Otherwise,
+    divide it into tuplets of length three, silently discarding any extra
+    elements beyond a multiple of three.
+    """
+    try:
+        colors and colors[0][0]
+    except TypeError:
+        pass
+    else:
+        return colors
+
+    # It's a 1-dimensional list
+    extra = len(colors) % 3
+    if extra:
+        colors = colors[:-extra]
+    return list(zip(*[iter(colors)] * 3))
diff --git a/bibliopixel/util/threads/runnable.py b/bibliopixel/util/threads/runnable.py
index 464c947..492c872 100644
--- a/bibliopixel/util/threads/runnable.py
+++ b/bibliopixel/util/threads/runnable.py
@@ -1,5 +1,5 @@
 from .. import log
-import contextlib, functools, threading, queue
+import contextlib, functools, threading, traceback, queue
 
 
 class Runnable:
@@ -53,6 +53,8 @@ class RunnableTarget(Runnable):
     def run(self):
         try:
             self.target()
+        except:
+            log.error('Exception at %s: \n%s', str(self), traceback.format_tb())
         finally:
             self.cleanup()
 


Test patch:
diff --git a/test/bibliopixel/project/types/colors_test.py b/test/bibliopixel/project/types/colors_test.py
index 893ce37..4ad63e9 100644
--- a/test/bibliopixel/project/types/colors_test.py
+++ b/test/bibliopixel/project/types/colors_test.py
@@ -8,7 +8,12 @@ class ColorTypesTest(TypesBaseTest):
 
     def test_single(self):
         self.make('colors', ['red'], [(255, 0, 0)])
+        self.make('colors', 'red', [(255, 0, 0)])
 
     def test_many(self):
         self.make('colors', ['red', [0, 255, 0], 127],
                   [(255, 0, 0), (0, 255, 0), (127, 127, 127)])
+
+    def test_1d_list(self):
+        self.make('colors', [0, 255, 0, 255, 0, 0, 23, 17],
+                  [(0, 255, 0), (255, 0, 0)])