Repository: ManiacalLabs/BiblioPixel
Pull request #1007 (2018-10-12 11:12:43)

util.int_names has memorable names for int indexes
Last in the "get it out of client".

This is a bit silly, but actually pretty useful.  

There are various things like MathFunc where we select an abstract rule using an integer index - and I can never remember which number corresponds to which pattern after experimenting.

With this change, you can use memorable names from some famous series:

* days of the week
* months
* planets
* chemical elements

which means you will be able to say:

    animation:
      typename: $bpa.matrix.MathFunc
      func: uranium

which is much more memorable, and a little entertaining to boot...

Of course, `func: 92` will still work, but is a lot less fun.  :-D





Patch:
diff --git a/bibliopixel/project/fields.py b/bibliopixel/project/fields.py
index 2bb1f67..22bd21f 100644
--- a/bibliopixel/project/fields.py
+++ b/bibliopixel/project/fields.py
@@ -1,5 +1,6 @@
 from . types import (
-    channel_order, color, colors, duration, gamma, ledtype, spi_interface)
+    channel_order, color, colors, duration, gamma, int_name, ledtype,
+    spi_interface)
 
 
 FIELD_TYPES = {
@@ -8,12 +9,16 @@ FIELD_TYPES = {
     'channel_order': channel_order,
     'color': color,
     'colors': colors,
+    'count': int_name,
     'duration': duration,
+    'func': int_name,
     'gamma': gamma,
+    'i': int_name,
     'ledtype': ledtype,
+    'num': int_name,
     'palette': colors,
-    'time': duration,
     'spi_interface': spi_interface,
+    'time': duration,
 }
 
 
diff --git a/bibliopixel/project/types/int_name.py b/bibliopixel/project/types/int_name.py
new file mode 100644
index 0000000..c54fe60
--- /dev/null
+++ b/bibliopixel/project/types/int_name.py
@@ -0,0 +1,14 @@
+from ... util import int_names
+
+USAGE = """
+An int_name is either an integer, a string representing an integer, or a
+fanciful name that's either a day of week, a month, a planet, or a chemical
+element.
+"""
+
+
+def make(c):
+    try:
+        return int_names.to_index(c)
+    except:
+        raise ValueError('Don\'t understand "%s"\n%s' % (c, USAGE))
diff --git a/bibliopixel/util/int_names.py b/bibliopixel/util/int_names.py
new file mode 100644
index 0000000..3ce38d5
--- /dev/null
+++ b/bibliopixel/util/int_names.py
@@ -0,0 +1,185 @@
+"""
+Fanciful names for integer indexes into lists - either a day of week,
+a month, a planet, or a chemical element.
+
+
+"""
+
+import calendar
+
+
+def to_index(name):
+    if isinstance(name, float):
+        raise KeyError('Indexes cannot be floating point')
+    try:
+        return int(name)
+    except:
+        pass
+    try:
+        return NAME_TO_INDEX[name.lower()]
+    except:
+        raise KeyError('Can\'t understand index "%s"' % name)
+
+
+def to_names(index):
+    return INDEX_TO_NAME[index]
+
+
+def _combine(*name_lists):
+    name_to_index = {}
+    index_to_name = {}
+
+    def add(i, name):
+        nl = name.lower()
+        if nl not in name_to_index:
+            name_to_index[nl] = i
+            index_to_name.setdefault(i, []).append(name)
+        elif nl not in DUPES:
+            raise ValueError(name + ' duplicated')
+
+    for z in ZEROES:
+        add(0, z)
+
+    for name_list in name_lists:
+        for i, names in enumerate(name_list):
+            if isinstance(names, str):
+                names = names,
+
+            for name in names:
+                add(i + 1, name)
+
+    return name_to_index, index_to_name
+
+
+DUPES = 'may', 'mercury'
+ZEROES = 'none', 'nothing', 'zero', 'zip'
+
+DAYS = tuple(zip(calendar.day_abbr, calendar.day_name))
+MONTHS = tuple(zip(calendar.month_abbr, calendar.month_name))[1:]
+COLORS = 'red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'
+PLANETS = ('Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn', 'Uranus',
+           'Neptune', 'Pluto')
+
+ELEMENTS = (
+    ('H', 'hydrogen'),
+    ('He', 'helium'),
+    ('Li', 'lithium'),
+    ('Be', 'beryllium'),
+    ('B', 'boron'),
+    ('C', 'carbon'),
+    ('N', 'nitrogen'),
+    ('O', 'oxygen'),
+    ('F', 'fluorine'),
+    ('Ne', 'neon'),
+    ('Na', 'sodium'),
+    ('Mg', 'magnesium'),
+    ('Al', 'aluminum'),
+    ('Si', 'silicon'),
+    ('P', 'phosphorus'),
+    ('S', 'sulfur'),
+    ('Cl', 'chlorine'),
+    ('Ar', 'argon'),
+    ('K', 'potassium'),
+    ('Ca', 'calcium'),
+    ('Sc', 'scandium'),
+    ('Ti', 'titanium'),
+    ('V', 'vanadium'),
+    ('Cr', 'chromium'),
+    ('Mn', 'manganese'),
+    ('Fe', 'iron'),
+    ('Co', 'cobalt'),
+    ('Ni', 'nickel'),
+    ('Cu', 'copper'),
+    ('Zn', 'zinc'),
+    ('Ga', 'gallium'),
+    ('Ge', 'germanium'),
+    ('As', 'arsenic'),
+    ('Se', 'selenium'),
+    ('Br', 'bromine'),
+    ('Kr', 'krypton'),
+    ('Rb', 'rubidium'),
+    ('Sr', 'strontium'),
+    ('Y', 'yttrium'),
+    ('Zr', 'zirconium'),
+    ('Nb', 'niobium'),
+    ('Mo', 'molybdenum'),
+    ('Tc', 'technetium'),
+    ('Ru', 'ruthenium'),
+    ('Rh', 'rhodium'),
+    ('Pd', 'palladium'),
+    ('Ag', 'silver'),
+    ('Cd', 'cadmium'),
+    ('In', 'indium'),
+    ('Sn', 'tin'),
+    ('Sb', 'antimony'),
+    ('Te', 'tellurium'),
+    ('I', 'iodine'),
+    ('Xe', 'xenon'),
+    ('Cs', 'cesium'),
+    ('Ba', 'barium'),
+    ('La', 'lanthanum'),
+    ('Ce', 'cerium'),
+    ('Pr', 'praseodymium'),
+    ('Nd', 'neodymium'),
+    ('Pm', 'promethium'),
+    ('Sm', 'samarium'),
+    ('Eu', 'europium'),
+    ('Gd', 'gadolinium'),
+    ('Tb', 'terbium'),
+    ('Dy', 'dysprosium'),
+    ('Ho', 'holmium'),
+    ('Er', 'erbium'),
+    ('Tm', 'thulium'),
+    ('Yb', 'ytterbium'),
+    ('Lu', 'lutetium'),
+    ('Hf', 'hafnium'),
+    ('Ta', 'tantalum'),
+    ('W', 'tungsten'),
+    ('Re', 'rhenium'),
+    ('Os', 'osmium'),
+    ('Ir', 'iridium'),
+    ('Pt', 'platinum'),
+    ('Au', 'gold'),
+    ('Hg', 'mercury'),
+    ('Tl', 'thallium'),
+    ('Pb', 'lead'),
+    ('Bi', 'bismuth'),
+    ('Po', 'polonium'),
+    ('At', 'astatine'),
+    ('Rn', 'radon'),
+    ('Fr', 'francium'),
+    ('Ra', 'radium'),
+    ('Ac', 'actinium'),
+    ('Th', 'thorium'),
+    ('Pa', 'protactinium'),
+    ('U', 'uranium'),
+    ('Np', 'neptunium'),
+    ('Pu', 'plutonium'),
+    ('Am', 'americium'),
+    ('Cm', 'curium'),
+    ('Bk', 'berkelium'),
+    ('Cf', 'californium'),
+    ('Es', 'einsteinium'),
+    ('Fm', 'fermium'),
+    ('Md', 'mendelevium'),
+    ('No', 'nobelium'),
+    ('Lr', 'lawrencium'),
+    ('Rf', 'rutherfordium'),
+    ('Db', 'dubnium'),
+    ('Sg', 'seaborgium'),
+    ('Bh', 'bohrium'),
+    ('Hs', 'hassium'),
+    ('Mt', 'meitnerium'),
+    ('Ds', 'darmstadtium'),
+    ('Rg', 'roentgenium'),
+    ('Cn', 'copernicium'),
+    ('Nh', 'nihonium'),
+    ('Fl', 'flerovium'),
+    ('Mc', 'moscovium'),
+    ('Lv', 'livermorium'),
+    ('Ts', 'tennessine'),
+    ('Og', 'oganesson'),
+)
+
+
+NAME_TO_INDEX, INDEX_TO_NAME = _combine(DAYS, MONTHS, COLORS, PLANETS, ELEMENTS)


Test patch:
diff --git a/test/bibliopixel/util/int_names_test.py b/test/bibliopixel/util/int_names_test.py
new file mode 100644
index 0000000..bb69d22
--- /dev/null
+++ b/test/bibliopixel/util/int_names_test.py
@@ -0,0 +1,25 @@
+import unittest
+from bibliopixel.util import int_names
+
+
+class NamesTest(unittest.TestCase):
+    def test_to_index(self):
+        self.assertEqual(int_names.to_index('H'), 1)
+        self.assertEqual(int_names.to_index('hydrogen'), 1)
+        self.assertEqual(int_names.to_index('wed'), 3)
+        self.assertEqual(int_names.to_index('wednesday'), 3)
+        self.assertEqual(int_names.to_index('Pluto'), 9)
+        with self.assertRaises(KeyError):
+            int_names.to_index('Ploto')
+        with self.assertRaises(KeyError):
+            int_names.to_index('12.5')
+        with self.assertRaises(KeyError):
+            int_names.to_index(12.5)
+
+    def test_to_names(self):
+        expected = ['Mon', 'Monday', 'Jan', 'January', 'red', 'Mercury', 'H',
+                    'hydrogen']
+        self.assertEqual(int_names.to_names(1), expected)
+        self.assertEqual(int_names.to_names(98), ['Cf', 'californium'])
+        with self.assertRaises(KeyError):
+            int_names.to_names(126)