From b0f289102cb2962c31b6ac3f9021f38e517b05a6 Mon Sep 17 00:00:00 2001 From: Prashant Sinha Date: Fri, 7 Oct 2016 01:09:55 +0530 Subject: [PATCH 1/8] Custom colorz --- CHANGELOG.md | 3 +++ hues/colortable.py | 15 +++++++++++---- hues/utils.py | 21 +++++++++++++++++++++ tests/test_utils.py | 21 +++++++++++++++++++++ 4 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 hues/utils.py create mode 100644 tests/test_utils.py diff --git a/CHANGELOG.md b/CHANGELOG.md index a4faff5..614699e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Added +- A `utils` submodule with `hex_to_rgb` function. Yes, custom colors coming! + ### Fixed - Fixed old reference name in a test, which was causing builds to fail. - Many many readme fixes. diff --git a/hues/colortable.py b/hues/colortable.py index 78056ca..52a5043 100644 --- a/hues/colortable.py +++ b/hues/colortable.py @@ -4,13 +4,13 @@ ''' from collections import namedtuple -ANSIColors = namedtuple('ANSIColors', [ +ANSIColors = namedtuple('ANSIColors', ( 'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', -]) -ANSIStyles = namedtuple('ANSIStyles', [ +)) +ANSIStyles = namedtuple('ANSIStyles', ( 'reset', 'bold', 'italic', 'underline', 'defaultfg', 'defaultbg', -]) +)) # Style Codes STYLE = ANSIStyles(0, 1, 3, 4, 39, 49) @@ -26,6 +26,10 @@ # Terminal sequence format SEQ = '\033[%sm' +# Extended ANSI Foreground and Background Sequence format +XFG_SEQ = '38;2;{r};{g};{b}' +XBG_SEQ = '48;2;{r};{g};{b}' + def __gen_keywords__(*args, **kwargs): '''Helper function to generate single escape sequence mapping.''' @@ -42,3 +46,6 @@ def __gen_keywords__(*args, **kwargs): return namedtuple('ANSISequences', fields)(*values) KEYWORDS = __gen_keywords__(STYLE, FG, bg=BG, bright=HI_FG, bg_bright=HI_BG) + + +__all__ = ('FG', 'BG', 'HI_FG', 'HI_BG', 'KEYWORDS', 'XFG_SEQ', 'XBG_SEQ') diff --git a/hues/utils.py b/hues/utils.py new file mode 100644 index 0000000..fd2a0ae --- /dev/null +++ b/hues/utils.py @@ -0,0 +1,21 @@ +'''Implements helper utilities.''' +from collections import namedtuple + +RGB = namedtuple('RGB', ('red', 'green', 'blue')) + + +def hex_to_rgb(color): + '''Convert hex color string to a RGB tuple + + >>> hex_to_rgb('#FFF') + RGB(red=255, green=255, blue=255) + ''' + if not color.startswith('#') or len(color) not in (4, 7): + raise ValueError('Expected a hex coded color value, got `{0}`'.format(color)) + + hexcode = color[1:] + if len(hexcode) == 3: + hexcode = ''.join([x * 2 for x in hexcode]) + + cvals = (int(hexcode[i * 2 : (i + 1) * 2], 16) for i in range(0, 3)) + return RGB(*cvals) diff --git a/tests/test_utils.py b/tests/test_utils.py new file mode 100644 index 0000000..41e6e36 --- /dev/null +++ b/tests/test_utils.py @@ -0,0 +1,21 @@ +from hues.utils import hex_to_rgb + + +def test_hex_to_rgb_usage(): + assert hex_to_rgb('#FFF') == (255, 255, 255) + assert hex_to_rgb('#FFFFFF') == (255, 255, 255) + assert hex_to_rgb('#2E2E2E') == (46, 46, 46) + assert hex_to_rgb('#AABBBB') == (170, 187, 187) + assert hex_to_rgb('#8B7E66') == (139, 126, 102) + + +def test_hex_to_rgb_exceptions(): + try: + hex_to_rgb('TROLL!') + except ValueError: + pass + + try: + hex_to_rgb('#TROLLL') + except ValueError: + pass From 10608a837d807ad1af066b855b32cdf54ea19c93 Mon Sep 17 00:00:00 2001 From: Prashant Sinha Date: Fri, 7 Oct 2016 01:28:16 +0530 Subject: [PATCH 2/8] Linter was barking.. --- hues/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hues/utils.py b/hues/utils.py index fd2a0ae..dba973c 100644 --- a/hues/utils.py +++ b/hues/utils.py @@ -17,5 +17,5 @@ def hex_to_rgb(color): if len(hexcode) == 3: hexcode = ''.join([x * 2 for x in hexcode]) - cvals = (int(hexcode[i * 2 : (i + 1) * 2], 16) for i in range(0, 3)) + cvals = (int(hexcode[i * 2:(i + 1) * 2], 16) for i in range(0, 3)) return RGB(*cvals) From fff0fcaee47855822924b414a659f5c78a702152 Mon Sep 17 00:00:00 2001 From: Prashant Sinha Date: Fri, 7 Oct 2016 14:43:08 +0530 Subject: [PATCH 3/8] Regexp annihilation --- CHANGELOG.md | 4 ++++ hues/colortable.py | 6 +++--- hues/dpda.py | 18 ++++++++++++++++-- hues/huestr.py | 8 ++++++-- tests/test_colortable.py | 2 +- tests/test_dpda.py | 23 ++++++++++++++++++++--- 6 files changed, 50 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 614699e..480c9d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] ### Added - A `utils` submodule with `hex_to_rgb` function. Yes, custom colors coming! +- Added regexp based optimization of PDA stack. + +### Changed +- Using `.format` strings. ### Fixed - Fixed old reference name in a test, which was causing builds to fail. diff --git a/hues/colortable.py b/hues/colortable.py index 52a5043..240efb0 100644 --- a/hues/colortable.py +++ b/hues/colortable.py @@ -24,11 +24,11 @@ HI_BG = ANSIColors(*range(100, 108)) # Terminal sequence format -SEQ = '\033[%sm' +SEQ = '\033[{0}m' # Extended ANSI Foreground and Background Sequence format -XFG_SEQ = '38;2;{r};{g};{b}' -XBG_SEQ = '48;2;{r};{g};{b}' +XFG_SEQ = '38;2;{0};{1};{2}' +XBG_SEQ = '48;2;{0};{1};{2}' def __gen_keywords__(*args, **kwargs): diff --git a/hues/dpda.py b/hues/dpda.py index 34794c9..bb8aab2 100644 --- a/hues/dpda.py +++ b/hues/dpda.py @@ -4,6 +4,7 @@ This module implements helper functions to allow producing deterministic representation of arbitrarily chained props. ''' +import re from functools import reduce, partial @@ -15,7 +16,7 @@ def zero_break(stack): return reduce(reducer, stack, tuple()) -def annihilate(predicate, stack): +def _annihilate(predicate, stack): '''Squash and reduce the input stack. Removes the elements of input that match predicate and only keeps the last match at the end of the stack. @@ -25,9 +26,22 @@ def annihilate(predicate, stack): return extra + (head,) if head else extra +def _annitilate_regex(pregex, stack): + '''Squash and reduce input stack with given regex predicate. + ''' + extra = tuple(filter(lambda x: re.match(pregex, str(x)) is None, stack)) + head = reduce(lambda x, y: y if re.match(pregex, str(y)) is not None else x, stack, None) + return extra + (head,) if head else extra + + def annihilator(predicate): '''Build a partial annihilator for given predicate.''' - return partial(annihilate, predicate) + return partial(_annihilate, predicate) + + +def regxannihilator(pregex): + '''Build a partial annihilator for given predicate.''' + return partial(_annitilate_regex, pregex) def dedup(stack): diff --git a/hues/huestr.py b/hues/huestr.py index edf7440..0b89dd9 100644 --- a/hues/huestr.py +++ b/hues/huestr.py @@ -22,8 +22,8 @@ def colorize(string, stack): '''Apply optimal ANSI escape sequences to the string.''' codes = optimize(stack) if len(codes): - prefix = SEQ % ';'.join(map(str, codes)) - suffix = SEQ % STYLE.reset + prefix = SEQ.format(';'.join(map(str, codes))) + suffix = SEQ.format(STYLE.reset) return prefix + string + suffix else: return string @@ -50,3 +50,7 @@ def __getattr__(self, attr): @property def colorized(self): return colorize(self.__string, self.__hue_stack) + + +def xhuestring(str, fg=None, bg=None): + pass diff --git a/tests/test_colortable.py b/tests/test_colortable.py index 99e26fc..6c7ff5b 100644 --- a/tests/test_colortable.py +++ b/tests/test_colortable.py @@ -50,7 +50,7 @@ def test_ansi_styles(): assert STYLE.defaultbg == 49 def test_sequence(): - assert SEQ % BG.black == '\033[40m' + assert SEQ.format(BG.black) == '\033[40m' def test_keywords(): assert KEYWORDS.bg_black == BG.black diff --git a/tests/test_dpda.py b/tests/test_dpda.py index 6fb559f..6896597 100644 --- a/tests/test_dpda.py +++ b/tests/test_dpda.py @@ -1,32 +1,49 @@ import hues.dpda as DPDA + def test_zero_negation(): func = DPDA.zero_break assert func((1, 2, 3, 4, 0, 10, 1)) == (10, 1) assert func((1, 2, 3, 4, 5, 0)) == tuple() + def test_order_annihilation(): - func = DPDA.annihilate + func = DPDA._annihilate assert func(range(0, 10), (1, 2, 3, 4, 4, 3)) == (3,) assert func(range(5, 12), (1, 2, 10, 11, 11, 2)) == (1, 2, 2, 11) + +def test_order_regex_annihilation(): + func = DPDA._annitilate_regex + assert func('^foo', ('foobar', 'foobaz')) == ('foobaz',) + assert func('^foo', ('foobar', 2, 3, 'foobaz')) == (2, 3, 'foobaz') + + def test_built_order_annihilation(): f1 = DPDA.annihilator(range(5, 12)) assert f1((1, 2, 10, 11, 11, 2)) == (1, 2, 2, 11) + +def test_built_order_regex_annihilation(): + f1 = DPDA.regxannihilator('^foo') + assert f1(('foobar', 2, 3, 'foobaz')) == (2, 3, 'foobaz') + + def test_dedup(): func = DPDA.dedup assert func((1, 2, 3, 3, 4, 2, 1, 3, 5)) == (1, 2, 3, 4, 5) + def test_chaining(): funcs = ( DPDA.zero_break, # Take the last non-reset subset DPDA.annihilator(range(5)), # Between 0 and 5, keep the last one DPDA.annihilator(range(10, 15)), # Between 10 and 15, keep the last one + DPDA.regxannihilator('^42;'), # Test regexp matches of type `42;..` etc. DPDA.dedup, # Finally remove duplicates ) - stack = (1, 2, 3, 2, 2, 0, 1, 2, 3, 2, 5, 5, 11, 3, 15, 14) - expected = (5, 15, 3, 14) + stack = (1, 2, 3, 2, 2, 0, 1, 2, 3, '42;30', 2, 5, 5, 11, 3, 15, '42;@', 14) + expected = (5, 15, 3, 14, '42;@') assert DPDA.apply(funcs, stack) == expected assert DPDA.apply(funcs, (1, 1, 0)) == tuple() From ba6e65ba3f8b958329d512b4b198b611a1c5ca24 Mon Sep 17 00:00:00 2001 From: Prashant Sinha Date: Fri, 7 Oct 2016 15:04:14 +0530 Subject: [PATCH 4/8] Added regex annihilators in optimization step --- hues/huestr.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/hues/huestr.py b/hues/huestr.py index 0b89dd9..efe17a5 100644 --- a/hues/huestr.py +++ b/hues/huestr.py @@ -3,17 +3,21 @@ from functools import partial from .colortable import FG, BG, HI_FG, HI_BG, SEQ, STYLE, KEYWORDS -from .dpda import zero_break, annihilator, dedup, apply +from .dpda import zero_break, annihilator, regxannihilator, dedup, apply if sys.version_info.major == 2: str = unicode # noqa +XFG_REX = r'38;2;\d{1,3};\d{1,3};\d{1,3}' +XBG_REX = r'48;2;\d{1,3};\d{1,3};\d{1,3}' OPTIMIZATION_STEPS = ( - zero_break, # Handle Resets using `reset`. - annihilator(FG + HI_FG), # Squash foreground colors to the last value. - annihilator(BG + HI_BG), # Squash background colors to the last value. - dedup, # Remove duplicates in (remaining) style values. + zero_break, # Handle Resets using `reset`. + annihilator(FG + HI_FG), # Squash foreground colors to the last value. + annihilator(BG + HI_BG), # Squash background colors to the last value. + regxannihilator(XFG_REX), # Squash extended foreground + regxannihilator(XBG_REX), # Squash extended background + dedup, # Remove duplicates in (remaining) style values. ) optimize = partial(apply, OPTIMIZATION_STEPS) From 38a8d878d5ba34e9b11a31bed62b1847c90c1d3a Mon Sep 17 00:00:00 2001 From: Prashant Sinha Date: Sat, 8 Oct 2016 17:11:44 +0530 Subject: [PATCH 5/8] Huestr is slighty less awkward. --- CHANGELOG.md | 1 + hues/console.py | 6 +-- hues/huestr.py | 98 +++++++++++++++++++++++++++++++++++++------- tests/test_huestr.py | 6 +-- 4 files changed, 91 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 480c9d2..5b17995 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added - A `utils` submodule with `hex_to_rgb` function. Yes, custom colors coming! - Added regexp based optimization of PDA stack. +- UserString instance, so the Huestr behaves more like a hue string. ### Changed - Using `.format` strings. diff --git a/hues/console.py b/hues/console.py index 0d70b4f..c3d581c 100644 --- a/hues/console.py +++ b/hues/console.py @@ -96,7 +96,7 @@ def _base_log(self, contents): def build_component(content, color=None): fg = KEYWORDS.defaultfg if color is None else color return ( - HueString(u'{}'.format(content), hue_stack=(fg,)), + HueString(u'{}'.format(content), fg), HueString(u' - '), ) @@ -161,8 +161,8 @@ def build_component(content, color=None, next_fg=None): next_bg = KEYWORDS.defaultbg if next_fg is None else (next_fg + 10) return ( - HueString(u' {} '.format(content), hue_stack=(text_bg, text_fg)), - HueString(u'', hue_stack=(fg, next_bg)), + HueString(u' {} '.format(content), text_bg, text_fg), + HueString(u'', fg, next_bg), ) nargs = () diff --git a/hues/huestr.py b/hues/huestr.py index efe17a5..4ad4124 100644 --- a/hues/huestr.py +++ b/hues/huestr.py @@ -1,9 +1,11 @@ # Unicorns import sys from functools import partial +from collections import UserString -from .colortable import FG, BG, HI_FG, HI_BG, SEQ, STYLE, KEYWORDS +from .colortable import FG, BG, HI_FG, HI_BG, SEQ, STYLE, KEYWORDS, XFG_SEQ, XBG_SEQ from .dpda import zero_break, annihilator, regxannihilator, dedup, apply +from .utils import hex_to_rgb if sys.version_info.major == 2: str = unicode # noqa @@ -33,28 +35,96 @@ def colorize(string, stack): return string -class HueString(str): +class HueString(UserString): '''Extend the string class to support hues.''' - def __new__(cls, string, hue_stack=None): - '''Return a new instance of the class.''' - return super(HueString, cls).__new__(cls, string) - - def __init__(self, string, hue_stack=tuple()): - self.__string = string - self.__hue_stack = hue_stack + def __init__(self, seq, *hues, **kwhues): + if 'fg' in kwhues: + hues += (XFG_SEQ.format(*hex_to_rgb(kwhues['fg'])),) + if 'bg' in kwhues: + hues += (XBG_SEQ.format(*hex_to_rgb(kwhues['bg'])),) + self.hues = hues + self.data = seq def __getattr__(self, attr): try: code = getattr(KEYWORDS, attr) - hues = self.__hue_stack + (code,) - return HueString(self.__string, hue_stack=hues) + hues = self.hues + (code,) + return HueString(self.data, *hues) except AttributeError as e: raise e @property def colorized(self): - return colorize(self.__string, self.__hue_stack) + return colorize(self.data, self.hues) + + def __get_wrapped__(self, dat): + return self.__class__(dat, *self.hues) + + def capitalize(self): + return self.__get_wrapped__(self.data.capitalize()) + + def casefold(self): + return self.__get_wrapped__(self.data.casefold()) + + def center(self, width, *args): + return self.__get_wrapped__(self.data.center(width, *args)) + + def expandtabs(self, tabsize=8): + return self.__get_wrapped__(self.data.expandtabs(tabsize)) + + def format(self, *args, **kwds): + return self.__get_wrapped__(self.data.format(*args, **kwds)) + + def format_map(self, mapping): + return self.__get_wrapped__(self.data.format_map(mapping)) + + def ljust(self, width, *args): + return self.__get_wrapped__(self.data.ljust(width, *args)) + + def lower(self): + return self.__get_wrapped__(self.data.lower()) + + def lstrip(self, chars=None): + return self.__get_wrapped__(self.data.lstrip(chars)) + + def partition(self, sep): + return tuple(map(self.__get_wrapped__, self.data.partition(sep))) + + def replace(self, old, new, maxsplit=-1): + return self.__get_wrapped__(self.data.replace(old, new, maxsplit)) + + def rjust(self, width, *args): + return self.__get_wrapped__(self.data.rjust(width, *args)) + + def rpartition(self, sep): + return tuple(map(self.__get_wrapped__, self.data.rpartition(sep))) + + def rstrip(self, chars=None): + return self.__get_wrapped__(self.data.rstrip(chars)) + + def split(self, sep=None, maxsplit=-1): + return tuple(map(self.__get_wrapped__, self.data.split(sep, maxsplit))) + + def rsplit(self, sep=None, maxsplit=-1): + return tuple(map(self.__get_wrapped__, self.data.rsplit(sep, maxsplit))) + + def splitlines(self, keepends=False): + return tuple(map(self.__get_wrapped__, self.data.splitlines(keepends))) + + def strip(self, chars=None): + return self.__get_wrapped__(self.data.strip(chars)) + + def swapcase(self): + return self.__get_wrapped__(self.data.swapcase()) + + def title(self): + return self.__get_wrapped__(self.data.title()) + + def translate(self, *args): + return self.__get_wrapped__(self.data.translate(*args)) + def upper(self): + return self.__get_wrapped__(self.data.upper()) -def xhuestring(str, fg=None, bg=None): - pass + def zfill(self, width): + return self.__get_wrapped__(self.data.zfill(width)) diff --git a/tests/test_huestr.py b/tests/test_huestr.py index 8077b9d..cdec318 100644 --- a/tests/test_huestr.py +++ b/tests/test_huestr.py @@ -32,14 +32,14 @@ def test_reset_chained(): def test_hues_creation(): obj = HueString('woot') - assert isinstance(obj, str) + # assert isinstance(obj, str) assert obj.colorized == 'woot' def test_hues_auto_stacking(): obj = HueString('woot').cyan.bg_green - assert isinstance(obj, str) - assert obj._HueString__hue_stack == (FG.cyan, BG.green) + # assert isinstance(obj, str) + assert obj.hues == (FG.cyan, BG.green) def test_hues_dynamic_props_exceptions(): From 2c8e6991def76ce2ab0853fd92e72500bde6d592 Mon Sep 17 00:00:00 2001 From: Prashant Sinha Date: Sat, 8 Oct 2016 17:40:36 +0530 Subject: [PATCH 6/8] Added a compatibility helper --- hues/compat.py | 13 +++++++++++++ hues/console.py | 6 ++---- hues/huestr.py | 14 +++++--------- tests/test_compat.py | 0 tests/test_huestr.py | 2 +- 5 files changed, 21 insertions(+), 14 deletions(-) create mode 100644 hues/compat.py create mode 100644 tests/test_compat.py diff --git a/hues/compat.py b/hues/compat.py new file mode 100644 index 0000000..c1e2c28 --- /dev/null +++ b/hues/compat.py @@ -0,0 +1,13 @@ +import sys + +if sys.version_info.major == 2: + string = unicode # noqa +else: + string = str + +try: + from collections import UserString +except ImportError: + class UserString(string): + def __new__(cls, seq, *args, **kwargs): + return super(UserString, cls).__new__(cls, seq) diff --git a/hues/console.py b/hues/console.py index c3d581c..ea93cc9 100644 --- a/hues/console.py +++ b/hues/console.py @@ -9,9 +9,7 @@ from .huestr import HueString from .colortable import KEYWORDS, FG - -if sys.version_info.major == 2: - str = unicode # noqa +from .compat import string CONFIG_FNAME = '.hues.yml' @@ -124,7 +122,7 @@ def log(self, *args, **kwargs): label = getattr(self.conf.labels, k) color = getattr(self.conf.hues, k) nargs.append((label, color)) - content = u' '.join([str(x) for x in args]) + content = u' '.join([string(x) for x in args]) nargs.append((content, self.conf.hues.default)) return self._base_log(nargs) diff --git a/hues/huestr.py b/hues/huestr.py index 4ad4124..768fdd8 100644 --- a/hues/huestr.py +++ b/hues/huestr.py @@ -1,15 +1,11 @@ # Unicorns -import sys from functools import partial -from collections import UserString +from .compat import string, UserString from .colortable import FG, BG, HI_FG, HI_BG, SEQ, STYLE, KEYWORDS, XFG_SEQ, XBG_SEQ from .dpda import zero_break, annihilator, regxannihilator, dedup, apply from .utils import hex_to_rgb -if sys.version_info.major == 2: - str = unicode # noqa - XFG_REX = r'38;2;\d{1,3};\d{1,3};\d{1,3}' XBG_REX = r'48;2;\d{1,3};\d{1,3};\d{1,3}' @@ -24,15 +20,15 @@ optimize = partial(apply, OPTIMIZATION_STEPS) -def colorize(string, stack): +def colorize(seq, stack): '''Apply optimal ANSI escape sequences to the string.''' codes = optimize(stack) if len(codes): - prefix = SEQ.format(';'.join(map(str, codes))) + prefix = SEQ.format(';'.join(map(string, codes))) suffix = SEQ.format(STYLE.reset) - return prefix + string + suffix + return prefix + seq + suffix else: - return string + return seq class HueString(UserString): diff --git a/tests/test_compat.py b/tests/test_compat.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_huestr.py b/tests/test_huestr.py index cdec318..fc066ea 100644 --- a/tests/test_huestr.py +++ b/tests/test_huestr.py @@ -2,8 +2,8 @@ from hues.huestr import colorize, HueString from hues.colortable import FG, BG, STYLE + if sys.version_info.major == 2: - # Python 2.7 compat. str = unicode # noqa From 9c643dd9ddd1dd1868466339c4469c56d98de03b Mon Sep 17 00:00:00 2001 From: Prashant Sinha Date: Sat, 8 Oct 2016 17:54:06 +0530 Subject: [PATCH 7/8] Added compatibility tests --- tests/test_compat.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/test_compat.py b/tests/test_compat.py index e69de29..85bd616 100644 --- a/tests/test_compat.py +++ b/tests/test_compat.py @@ -0,0 +1,18 @@ +import sys +import collections + +from hues.compat import string, UserString + + +def test_string_compat(): + if sys.version_info.major == 2: + assert string is unicode # noqa: F821 + else: + assert string is str + + +def test_user_string(): + if hasattr(collections, 'UserString'): + assert UserString is collections.UserString + else: + UserString('This is a test') From ba9ffe3ba0259ac324d0d6af05e9e9fbabafc516 Mon Sep 17 00:00:00 2001 From: Prashant Sinha Date: Tue, 11 Oct 2016 18:25:43 +0530 Subject: [PATCH 8/8] Typo fix. Ref #5 --- example.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example.py b/example.py index 22a410f..7a09094 100644 --- a/example.py +++ b/example.py @@ -15,7 +15,7 @@ def destroy_planet(planet): if __name__ == '__main__': hues.info('Destroying the planets. Please wait.') - for planet in ('Murcury', 'Venus', 'Earth', 'Mars', 'Uranus',): + for planet in ('Mercury', 'Venus', 'Earth', 'Mars', 'Uranus',): try: success = destroy_planet(planet) except ThisPlanetIsProtected: