diff --git a/.gitattributes b/.gitattributes
deleted file mode 100644
index 2125666..0000000
--- a/.gitattributes
+++ /dev/null
@@ -1 +0,0 @@
-* text=auto
\ No newline at end of file
diff --git a/pyzen/_colorama/README.txt b/pyzen/_colorama/README.txt
index 15b4701..55fe171 100644
--- a/pyzen/_colorama/README.txt
+++ b/pyzen/_colorama/README.txt
@@ -1,307 +1,307 @@
-Download and docs:
- http://pypi.python.org/pypi/colorama
-Development:
- http://code.google.com/p/colorama
-
-Description
-===========
-
-Makes ANSI escape character sequences for producing colored terminal text work
-under MS Windows.
-
-ANSI escape character sequences have long been used to produce colored terminal
-text on Unix and Macs. Colorama makes this work on Windows, too. It also
-provides some shortcuts to help generate ANSI sequences, and works fine in
-conjunction with any other ANSI sequence generation library, such as Termcolor
-(http://pypi.python.org/pypi/termcolor.)
-
-This has the upshot of providing a simple cross-platform API for printing
-colored terminal text from Python, and has the happy side-effect that existing
-applications or libraries which use ANSI sequences to produce colored output on
-Linux or Macs can now also work on Windows, simply by calling
-``colorama.init()``.
-
-A demo script in the source code repository prints some colored text using
-ANSI sequences. Compare its output under Gnome-terminal's built in ANSI
-handling, versus on Windows Command-Prompt using Colorama:
-
-.. image:: http://colorama.googlecode.com/hg/screenshots/ubuntu-demo.png
- :width: 661
- :height: 357
- :alt: ANSI sequences on Ubuntu under gnome-terminal.
-
-.. image:: http://colorama.googlecode.com/hg/screenshots/windows-demo.png
- :width: 668
- :height: 325
- :alt: Same ANSI sequences on Windows, using Colorama.
-
-These screengrabs make it clear that Colorama on Windows does not support
-ANSI 'dim text': it looks the same as 'normal text'.
-
-
-Dependencies
-============
-
-None, other than Python. Tested on Python 2.5.5, 2.6.5, 2.7 & 3.1.2.
-
-
-Usage
-=====
-
-Initialisation
---------------
-
-Applications should initialise Colorama using::
-
- from colorama import init
- init()
-
-If you are on Windows, the call to ``init()`` will start filtering ANSI escape
-sequences out of any text sent to stdout or stderr, and will replace them with
-equivalent Win32 calls.
-
-Calling ``init()`` has no effect on other platforms (unless you request other
-optional functionality, see keyword args below.) The intention is that
-applications can call ``init()`` unconditionally on all platforms, after which
-ANSI output should just work.
-
-
-Colored Output
---------------
-
-Cross-platform printing of colored text can then be done using Colorama's
-constant shorthand for ANSI escape sequences::
-
- from colorama import Fore, Back, Style
- print Fore.RED + 'some red text'
- print Back.GREEN + and with a green background'
- print Style.DIM + 'and in dim text'
- print + Fore.RESET + Back.RESET + Style.RESET_ALL
- print 'back to normal now'
-
-or simply by manually printing ANSI sequences from your own code::
-
- print '/033[31m' + 'some red text'
- print '/033[30m' # and reset to default color
-
-or Colorama can be used happily in conjunction with existing ANSI libraries
-such as Termcolor::
-
- from colorama import init
- from termcolor import colored
-
- # use Colorama to make Termcolor work on Windows too
- init()
-
- # then use Termcolor for all colored text output
- print colored('Hello, World!', 'green', 'on_red')
-
-Available formatting constants are::
-
- Fore: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET.
- Back: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET.
- Style: DIM, NORMAL, BRIGHT, RESET_ALL
-
-Style.RESET_ALL resets foreground, background and brightness. Colorama will
-perform this reset automatically on program exit.
-
-
-Init Keyword Args
------------------
-
-``init()`` accepts some kwargs to override default behaviour.
-
-init(autoreset=False):
- If you find yourself repeatedly sending reset sequences to turn off color
- changes at the end of every print, then ``init(autoreset=True)`` will
- automate that::
-
- from colorama import init
- init(autoreset=True)
- print Fore.RED + 'some red text'
- print 'automatically back to default color again'
-
-init(strip=None):
- Pass ``True`` or ``False`` to override whether ansi codes should be
- stripped from the output. The default behaviour is to strip if on Windows.
-
-init(convert=None):
- Pass ``True`` or ``False`` to override whether to convert ansi codes in the
- output into win32 calls. The default behaviour is to convert if on Windows
- and output is to a tty (terminal).
-
-init(wrap=True):
- On Windows, colorama works by replacing ``sys.stdout`` and ``sys.stderr``
- with proxy objects, which override the .write() method to do their work. If
- this wrapping causes you problems, then this can be disabled by passing
- ``init(wrap=False)``. The default behaviour is to wrap if autoreset or
- strip or convert are True.
-
- When wrapping is disabled, colored printing on non-Windows platforms will
- continue to work as normal. To do cross-platform colored output, you can
- use Colorama's ``AnsiToWin32`` proxy directly::
-
- from colorama import init, AnsiToWin32
- init(wrap=False)
- stream = AnsiToWin32(sys.stderr).stream
- print >>stream, Fore.BLUE + 'blue text on stderr'
-
-
-Status & Known Problems
-=======================
-
-Feature complete as far as colored text goes, but still finding bugs and
-occasionally making small changes to the API (such as new keyword arguments
-to ``init()``).
-
-Only tested on WinXP (CMD, Console2) and Ubuntu (gnome-terminal, xterm). Much
-obliged if anyone can let me know how it fares elsewhere, in particular on
-Macs.
-
-I'd like to add the ability to handle ANSI codes which position the text cursor
-and clear the terminal.
-
-See outstanding issues and wishlist at:
-http://code.google.com/p/colorama/issues/list
-
-If anything doesn't work for you, or doesn't do what you expected or hoped for,
-I'd *love* to hear about it on that issues list.
-
-
-Recognised ANSI Sequences
-=========================
-
-ANSI sequences generally take the form:
-
- ESC [ ; ...
-
-Where is an integer, and is a single letter. Zero or more
-params are passed to a . If no params are passed, it is generally
-synonymous with passing a single zero. No spaces exist in the sequence, they
-have just been inserted here to make it easy to read.
-
-The only ANSI sequences that colorama converts into win32 calls are::
-
- ESC [ 0 m # reset all (colors and brightness)
- ESC [ 1 m # bright
- ESC [ 2 m # dim (looks same as normal brightness)
- ESC [ 22 m # normal brightness
-
- # FOREGROUND:
- ESC [ 30 m # black
- ESC [ 31 m # red
- ESC [ 32 m # green
- ESC [ 33 m # yellow
- ESC [ 34 m # blue
- ESC [ 35 m # magenta
- ESC [ 36 m # cyan
- ESC [ 37 m # white
- ESC [ 39 m # reset
-
- # BACKGROUND
- ESC [ 40 m # black
- ESC [ 41 m # red
- ESC [ 42 m # green
- ESC [ 43 m # yellow
- ESC [ 44 m # blue
- ESC [ 45 m # magenta
- ESC [ 46 m # cyan
- ESC [ 47 m # white
- ESC [ 49 m # reset
-
-Multiple numeric params to the 'm' command can be combined into a single
-sequence, eg::
-
- ESC [ 36 ; 45 ; 1 m # bright cyan text on magenta background
-
-All other ANSI sequences of the form ``ESC [ ; ... ``
-are silently stripped from the output on Windows.
-
-Any other form of ANSI sequence, such as single-character codes or alternative
-initial characters, are not recognised nor stripped.
-
-
-Development
-===========
-
-Running tests requires:
-
-- Michael Foord's 'mock' module to be installed.
-- Either to be run under Python2.7 or 3.1 stdlib unittest, or to have Michael
- Foord's 'unittest2' module to be installed.
-
-unittest2 test discovery doesn't work for colorama, so I use 'nose'::
-
- nosetests -s
-
-The -s is required because 'nosetests' otherwise applies a proxy of its own to
-stdout, which confuses the unit tests.
-
-
-Thanks
-======
-Roger Binns, for many suggestions, valuable feedback, & bug reports.
-Tim Golden for thought and much appreciated feedback on the initial idea.
-
-
-Changes
-=======
-
-0.1.17
- Prevent printing of garbage ANSI codes upon installing with pip
-0.1.16
- Re-upload to fix previous error. Make clean now removes old MANIFEST.
-0.1.15
- Completely broken. Distribution was empty due to leftover invalid MANIFEST
- file from building on a different platform.
- Fix python3 incompatibility kindly reported by G |uumlaut| nter Kolousek
-0.1.14
- Fix hard-coded reset to white-on-black colors. Fore.RESET, Back.RESET
- and Style.RESET_ALL now revert to the colors as they were when init()
- was called. Some lessons hopefully learned about testing prior to release.
-0.1.13
- Completely broken: barfed when installed using pip.
-0.1.12
- Completely broken: contained no source code. double oops.
-0.1.11
- Completely broken: fatal import errors on Ubuntu. oops.
-0.1.10
- Stop emulating 'bright' text with bright backgrounds.
- Display 'normal' text using win32 normal foreground instead of bright.
- Drop support for 'dim' text.
-0.1.9
- Fix incompatibility with Python 2.5 and earlier.
- Remove setup.py dependency on setuptools, now uses stdlib distutils.
-0.1.8
- Fix ghastly errors all over the place on Ubuntu.
- Add init kwargs 'convert' and 'strip', which supercede the old 'wrap'.
-0.1.7
- Python 3 compatible.
- Fix: Now strips ansi on windows without necessarily converting it to
- win32 calls (eg. if output is not a tty.)
- Fix: Flaky interaction of interleaved ansi sent to stdout and stderr.
- Improved demo.sh (hg checkout only.)
-0.1.6
- Fix ansi sequences with no params now default to parmlist of [0].
- Fix flaky behaviour of autoreset and reset_all atexit.
- Fix stacking of repeated atexit calls - now just called once.
- Fix ghastly import problems while running tests.
- 'demo.py' (hg checkout only) now demonstrates autoreset and reset atexit.
- Provide colorama.VERSION, used by setup.py.
- Tests defanged so they no longer actually change terminal color when run.
-0.1.5
- Now works on Ubuntu.
-0.1.4
- Implemented RESET_ALL on application exit
-0.1.3
- Implemented init(wrap=False)
-0.1.2
- Implemented init(autoreset=True)
-0.1.1
- Minor tidy
-0.1
- Works on Windows for foreground color, background color, bright or dim
-
-.. |uumlaut| unicode:: U+00FC .. u with umlaut
- :trim:
-
+Download and docs:
+ http://pypi.python.org/pypi/colorama
+Development:
+ http://code.google.com/p/colorama
+
+Description
+===========
+
+Makes ANSI escape character sequences for producing colored terminal text work
+under MS Windows.
+
+ANSI escape character sequences have long been used to produce colored terminal
+text on Unix and Macs. Colorama makes this work on Windows, too. It also
+provides some shortcuts to help generate ANSI sequences, and works fine in
+conjunction with any other ANSI sequence generation library, such as Termcolor
+(http://pypi.python.org/pypi/termcolor.)
+
+This has the upshot of providing a simple cross-platform API for printing
+colored terminal text from Python, and has the happy side-effect that existing
+applications or libraries which use ANSI sequences to produce colored output on
+Linux or Macs can now also work on Windows, simply by calling
+``colorama.init()``.
+
+A demo script in the source code repository prints some colored text using
+ANSI sequences. Compare its output under Gnome-terminal's built in ANSI
+handling, versus on Windows Command-Prompt using Colorama:
+
+.. image:: http://colorama.googlecode.com/hg/screenshots/ubuntu-demo.png
+ :width: 661
+ :height: 357
+ :alt: ANSI sequences on Ubuntu under gnome-terminal.
+
+.. image:: http://colorama.googlecode.com/hg/screenshots/windows-demo.png
+ :width: 668
+ :height: 325
+ :alt: Same ANSI sequences on Windows, using Colorama.
+
+These screengrabs make it clear that Colorama on Windows does not support
+ANSI 'dim text': it looks the same as 'normal text'.
+
+
+Dependencies
+============
+
+None, other than Python. Tested on Python 2.5.5, 2.6.5, 2.7 & 3.1.2.
+
+
+Usage
+=====
+
+Initialisation
+--------------
+
+Applications should initialise Colorama using::
+
+ from colorama import init
+ init()
+
+If you are on Windows, the call to ``init()`` will start filtering ANSI escape
+sequences out of any text sent to stdout or stderr, and will replace them with
+equivalent Win32 calls.
+
+Calling ``init()`` has no effect on other platforms (unless you request other
+optional functionality, see keyword args below.) The intention is that
+applications can call ``init()`` unconditionally on all platforms, after which
+ANSI output should just work.
+
+
+Colored Output
+--------------
+
+Cross-platform printing of colored text can then be done using Colorama's
+constant shorthand for ANSI escape sequences::
+
+ from colorama import Fore, Back, Style
+ print Fore.RED + 'some red text'
+ print Back.GREEN + and with a green background'
+ print Style.DIM + 'and in dim text'
+ print + Fore.RESET + Back.RESET + Style.RESET_ALL
+ print 'back to normal now'
+
+or simply by manually printing ANSI sequences from your own code::
+
+ print '/033[31m' + 'some red text'
+ print '/033[30m' # and reset to default color
+
+or Colorama can be used happily in conjunction with existing ANSI libraries
+such as Termcolor::
+
+ from colorama import init
+ from termcolor import colored
+
+ # use Colorama to make Termcolor work on Windows too
+ init()
+
+ # then use Termcolor for all colored text output
+ print colored('Hello, World!', 'green', 'on_red')
+
+Available formatting constants are::
+
+ Fore: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET.
+ Back: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET.
+ Style: DIM, NORMAL, BRIGHT, RESET_ALL
+
+Style.RESET_ALL resets foreground, background and brightness. Colorama will
+perform this reset automatically on program exit.
+
+
+Init Keyword Args
+-----------------
+
+``init()`` accepts some kwargs to override default behaviour.
+
+init(autoreset=False):
+ If you find yourself repeatedly sending reset sequences to turn off color
+ changes at the end of every print, then ``init(autoreset=True)`` will
+ automate that::
+
+ from colorama import init
+ init(autoreset=True)
+ print Fore.RED + 'some red text'
+ print 'automatically back to default color again'
+
+init(strip=None):
+ Pass ``True`` or ``False`` to override whether ansi codes should be
+ stripped from the output. The default behaviour is to strip if on Windows.
+
+init(convert=None):
+ Pass ``True`` or ``False`` to override whether to convert ansi codes in the
+ output into win32 calls. The default behaviour is to convert if on Windows
+ and output is to a tty (terminal).
+
+init(wrap=True):
+ On Windows, colorama works by replacing ``sys.stdout`` and ``sys.stderr``
+ with proxy objects, which override the .write() method to do their work. If
+ this wrapping causes you problems, then this can be disabled by passing
+ ``init(wrap=False)``. The default behaviour is to wrap if autoreset or
+ strip or convert are True.
+
+ When wrapping is disabled, colored printing on non-Windows platforms will
+ continue to work as normal. To do cross-platform colored output, you can
+ use Colorama's ``AnsiToWin32`` proxy directly::
+
+ from colorama import init, AnsiToWin32
+ init(wrap=False)
+ stream = AnsiToWin32(sys.stderr).stream
+ print >>stream, Fore.BLUE + 'blue text on stderr'
+
+
+Status & Known Problems
+=======================
+
+Feature complete as far as colored text goes, but still finding bugs and
+occasionally making small changes to the API (such as new keyword arguments
+to ``init()``).
+
+Only tested on WinXP (CMD, Console2) and Ubuntu (gnome-terminal, xterm). Much
+obliged if anyone can let me know how it fares elsewhere, in particular on
+Macs.
+
+I'd like to add the ability to handle ANSI codes which position the text cursor
+and clear the terminal.
+
+See outstanding issues and wishlist at:
+http://code.google.com/p/colorama/issues/list
+
+If anything doesn't work for you, or doesn't do what you expected or hoped for,
+I'd *love* to hear about it on that issues list.
+
+
+Recognised ANSI Sequences
+=========================
+
+ANSI sequences generally take the form:
+
+ ESC [ ; ...
+
+Where is an integer, and is a single letter. Zero or more
+params are passed to a . If no params are passed, it is generally
+synonymous with passing a single zero. No spaces exist in the sequence, they
+have just been inserted here to make it easy to read.
+
+The only ANSI sequences that colorama converts into win32 calls are::
+
+ ESC [ 0 m # reset all (colors and brightness)
+ ESC [ 1 m # bright
+ ESC [ 2 m # dim (looks same as normal brightness)
+ ESC [ 22 m # normal brightness
+
+ # FOREGROUND:
+ ESC [ 30 m # black
+ ESC [ 31 m # red
+ ESC [ 32 m # green
+ ESC [ 33 m # yellow
+ ESC [ 34 m # blue
+ ESC [ 35 m # magenta
+ ESC [ 36 m # cyan
+ ESC [ 37 m # white
+ ESC [ 39 m # reset
+
+ # BACKGROUND
+ ESC [ 40 m # black
+ ESC [ 41 m # red
+ ESC [ 42 m # green
+ ESC [ 43 m # yellow
+ ESC [ 44 m # blue
+ ESC [ 45 m # magenta
+ ESC [ 46 m # cyan
+ ESC [ 47 m # white
+ ESC [ 49 m # reset
+
+Multiple numeric params to the 'm' command can be combined into a single
+sequence, eg::
+
+ ESC [ 36 ; 45 ; 1 m # bright cyan text on magenta background
+
+All other ANSI sequences of the form ``ESC [ ; ... ``
+are silently stripped from the output on Windows.
+
+Any other form of ANSI sequence, such as single-character codes or alternative
+initial characters, are not recognised nor stripped.
+
+
+Development
+===========
+
+Running tests requires:
+
+- Michael Foord's 'mock' module to be installed.
+- Either to be run under Python2.7 or 3.1 stdlib unittest, or to have Michael
+ Foord's 'unittest2' module to be installed.
+
+unittest2 test discovery doesn't work for colorama, so I use 'nose'::
+
+ nosetests -s
+
+The -s is required because 'nosetests' otherwise applies a proxy of its own to
+stdout, which confuses the unit tests.
+
+
+Thanks
+======
+Roger Binns, for many suggestions, valuable feedback, & bug reports.
+Tim Golden for thought and much appreciated feedback on the initial idea.
+
+
+Changes
+=======
+
+0.1.17
+ Prevent printing of garbage ANSI codes upon installing with pip
+0.1.16
+ Re-upload to fix previous error. Make clean now removes old MANIFEST.
+0.1.15
+ Completely broken. Distribution was empty due to leftover invalid MANIFEST
+ file from building on a different platform.
+ Fix python3 incompatibility kindly reported by G |uumlaut| nter Kolousek
+0.1.14
+ Fix hard-coded reset to white-on-black colors. Fore.RESET, Back.RESET
+ and Style.RESET_ALL now revert to the colors as they were when init()
+ was called. Some lessons hopefully learned about testing prior to release.
+0.1.13
+ Completely broken: barfed when installed using pip.
+0.1.12
+ Completely broken: contained no source code. double oops.
+0.1.11
+ Completely broken: fatal import errors on Ubuntu. oops.
+0.1.10
+ Stop emulating 'bright' text with bright backgrounds.
+ Display 'normal' text using win32 normal foreground instead of bright.
+ Drop support for 'dim' text.
+0.1.9
+ Fix incompatibility with Python 2.5 and earlier.
+ Remove setup.py dependency on setuptools, now uses stdlib distutils.
+0.1.8
+ Fix ghastly errors all over the place on Ubuntu.
+ Add init kwargs 'convert' and 'strip', which supercede the old 'wrap'.
+0.1.7
+ Python 3 compatible.
+ Fix: Now strips ansi on windows without necessarily converting it to
+ win32 calls (eg. if output is not a tty.)
+ Fix: Flaky interaction of interleaved ansi sent to stdout and stderr.
+ Improved demo.sh (hg checkout only.)
+0.1.6
+ Fix ansi sequences with no params now default to parmlist of [0].
+ Fix flaky behaviour of autoreset and reset_all atexit.
+ Fix stacking of repeated atexit calls - now just called once.
+ Fix ghastly import problems while running tests.
+ 'demo.py' (hg checkout only) now demonstrates autoreset and reset atexit.
+ Provide colorama.VERSION, used by setup.py.
+ Tests defanged so they no longer actually change terminal color when run.
+0.1.5
+ Now works on Ubuntu.
+0.1.4
+ Implemented RESET_ALL on application exit
+0.1.3
+ Implemented init(wrap=False)
+0.1.2
+ Implemented init(autoreset=True)
+0.1.1
+ Minor tidy
+0.1
+ Works on Windows for foreground color, background color, bright or dim
+
+.. |uumlaut| unicode:: U+00FC .. u with umlaut
+ :trim:
+
diff --git a/pyzen/_colorama/ansi.py b/pyzen/_colorama/ansi.py
index 7c45983..7b818e1 100644
--- a/pyzen/_colorama/ansi.py
+++ b/pyzen/_colorama/ansi.py
@@ -1,49 +1,49 @@
-'''
-This module generates ANSI character codes to printing colors to terminals.
-See: http://en.wikipedia.org/wiki/ANSI_escape_code
-'''
-
-CSI = '\033['
-
-def code_to_chars(code):
- return CSI + str(code) + 'm'
-
-class AnsiCodes(object):
- def __init__(self, codes):
- for name in dir(codes):
- if not name.startswith('_'):
- value = getattr(codes, name)
- setattr(self, name, code_to_chars(value))
-
-class AnsiFore:
- BLACK = 30
- RED = 31
- GREEN = 32
- YELLOW = 33
- BLUE = 34
- MAGENTA = 35
- CYAN = 36
- WHITE = 37
- RESET = 39
-
-class AnsiBack:
- BLACK = 40
- RED = 41
- GREEN = 42
- YELLOW = 43
- BLUE = 44
- MAGENTA = 45
- CYAN = 46
- WHITE = 47
- RESET = 49
-
-class AnsiStyle:
- BRIGHT = 1
- DIM = 2
- NORMAL = 22
- RESET_ALL = 0
-
-Fore = AnsiCodes( AnsiFore )
-Back = AnsiCodes( AnsiBack )
-Style = AnsiCodes( AnsiStyle )
-
+'''
+This module generates ANSI character codes to printing colors to terminals.
+See: http://en.wikipedia.org/wiki/ANSI_escape_code
+'''
+
+CSI = '\033['
+
+def code_to_chars(code):
+ return CSI + str(code) + 'm'
+
+class AnsiCodes(object):
+ def __init__(self, codes):
+ for name in dir(codes):
+ if not name.startswith('_'):
+ value = getattr(codes, name)
+ setattr(self, name, code_to_chars(value))
+
+class AnsiFore:
+ BLACK = 30
+ RED = 31
+ GREEN = 32
+ YELLOW = 33
+ BLUE = 34
+ MAGENTA = 35
+ CYAN = 36
+ WHITE = 37
+ RESET = 39
+
+class AnsiBack:
+ BLACK = 40
+ RED = 41
+ GREEN = 42
+ YELLOW = 43
+ BLUE = 44
+ MAGENTA = 45
+ CYAN = 46
+ WHITE = 47
+ RESET = 49
+
+class AnsiStyle:
+ BRIGHT = 1
+ DIM = 2
+ NORMAL = 22
+ RESET_ALL = 0
+
+Fore = AnsiCodes( AnsiFore )
+Back = AnsiCodes( AnsiBack )
+Style = AnsiCodes( AnsiStyle )
+
diff --git a/pyzen/_colorama/ansitowin32.py b/pyzen/_colorama/ansitowin32.py
index 363061d..9ce77dd 100644
--- a/pyzen/_colorama/ansitowin32.py
+++ b/pyzen/_colorama/ansitowin32.py
@@ -1,176 +1,176 @@
-
-import re
-import sys
-
-from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style
-from .winterm import WinTerm, WinColor, WinStyle
-from .win32 import windll
-
-
-if windll is not None:
- winterm = WinTerm()
-
-
-def is_a_tty(stream):
- return hasattr(stream, 'isatty') and stream.isatty()
-
-
-class StreamWrapper(object):
- '''
- Wraps a stream (such as stdout), acting as a transparent proxy for all
- attribute access apart from method 'write()', which is delegated to our
- Converter instance.
- '''
- def __init__(self, wrapped, converter):
- # double-underscore everything to prevent clashes with names of
- # attributes on the wrapped stream object.
- self.__wrapped = wrapped
- self.__convertor = converter
-
- def __getattr__(self, name):
- return getattr(self.__wrapped, name)
-
- def write(self, text):
- self.__convertor.write(text)
-
-
-class AnsiToWin32(object):
- '''
- Implements a 'write()' method which, on Windows, will strip ANSI character
- sequences from the text, and if outputting to a tty, will convert them into
- win32 function calls.
- '''
- ANSI_RE = re.compile('\033\[((?:\d|;)*)([a-zA-Z])')
-
- def __init__(self, wrapped, convert=None, strip=None, autoreset=False):
- # The wrapped stream (normally sys.stdout or sys.stderr)
- self.wrapped = wrapped
-
- # should we reset colors to defaults after every .write()
- self.autoreset = autoreset
-
- # create the proxy wrapping our output stream
- self.stream = StreamWrapper(wrapped, self)
-
- on_windows = sys.platform.startswith('win')
-
- # should we strip ANSI sequences from our output?
- if strip is None:
- strip = on_windows
- self.strip = strip
-
- # should we should convert ANSI sequences into win32 calls?
- if convert is None:
- convert = on_windows and is_a_tty(wrapped)
- self.convert = convert
-
- # dict of ansi codes to win32 functions and parameters
- self.win32_calls = self.get_win32_calls()
-
- # are we wrapping stderr?
- self.on_stderr = self.wrapped is sys.stderr
-
-
- def should_wrap(self):
- '''
- True if this class is actually needed. If false, then the output
- stream will not be affected, nor will win32 calls be issued, so
- wrapping stdout is not actually required. This will generally be
- False on non-Windows platforms, unless optional functionality like
- autoreset has been requested using kwargs to init()
- '''
- return self.convert or self.strip or self.autoreset
-
-
- def get_win32_calls(self):
- if self.convert and winterm:
- return {
- AnsiStyle.RESET_ALL: (winterm.reset_all, ),
- AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT),
- AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL),
- AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL),
- AnsiFore.BLACK: (winterm.fore, WinColor.BLACK),
- AnsiFore.RED: (winterm.fore, WinColor.RED),
- AnsiFore.GREEN: (winterm.fore, WinColor.GREEN),
- AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW),
- AnsiFore.BLUE: (winterm.fore, WinColor.BLUE),
- AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA),
- AnsiFore.CYAN: (winterm.fore, WinColor.CYAN),
- AnsiFore.WHITE: (winterm.fore, WinColor.GREY),
- AnsiFore.RESET: (winterm.fore, ),
- AnsiBack.BLACK: (winterm.back, WinColor.BLACK),
- AnsiBack.RED: (winterm.back, WinColor.RED),
- AnsiBack.GREEN: (winterm.back, WinColor.GREEN),
- AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW),
- AnsiBack.BLUE: (winterm.back, WinColor.BLUE),
- AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA),
- AnsiBack.CYAN: (winterm.back, WinColor.CYAN),
- AnsiBack.WHITE: (winterm.back, WinColor.GREY),
- AnsiBack.RESET: (winterm.back, ),
- }
-
-
- def write(self, text):
- if self.strip or self.convert:
- self.write_and_convert(text)
- else:
- self.wrapped.write(text)
- self.wrapped.flush()
- if self.autoreset:
- self.reset_all()
-
-
- def reset_all(self):
- if self.convert:
- self.call_win32('m', (0,))
- else:
- self.wrapped.write(Style.RESET_ALL)
-
-
- def write_and_convert(self, text):
- '''
- Write the given text to our wrapped stream, stripping any ANSI
- sequences from the text, and optionally converting them into win32
- calls.
- '''
- cursor = 0
- for match in self.ANSI_RE.finditer(text):
- start, end = match.span()
- self.write_plain_text(text, cursor, start)
- self.convert_ansi(*match.groups())
- cursor = end
- self.write_plain_text(text, cursor, len(text))
-
-
- def write_plain_text(self, text, start, end):
- if start < end:
- self.wrapped.write(text[start:end])
- self.wrapped.flush()
-
-
- def convert_ansi(self, paramstring, command):
- if self.convert:
- params = self.extract_params(paramstring)
- self.call_win32(command, params)
-
-
- def extract_params(self, paramstring):
- def split(paramstring):
- for p in paramstring.split(';'):
- if p != '':
- yield int(p)
- return tuple(split(paramstring))
-
-
- def call_win32(self, command, params):
- if params == []:
- params = [0]
- if command == 'm':
- for param in params:
- if param in self.win32_calls:
- func_args = self.win32_calls[param]
- func = func_args[0]
- args = func_args[1:]
- kwargs = dict(on_stderr=self.on_stderr)
- func(*args, **kwargs)
-
+
+import re
+import sys
+
+from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style
+from .winterm import WinTerm, WinColor, WinStyle
+from .win32 import windll
+
+
+if windll is not None:
+ winterm = WinTerm()
+
+
+def is_a_tty(stream):
+ return hasattr(stream, 'isatty') and stream.isatty()
+
+
+class StreamWrapper(object):
+ '''
+ Wraps a stream (such as stdout), acting as a transparent proxy for all
+ attribute access apart from method 'write()', which is delegated to our
+ Converter instance.
+ '''
+ def __init__(self, wrapped, converter):
+ # double-underscore everything to prevent clashes with names of
+ # attributes on the wrapped stream object.
+ self.__wrapped = wrapped
+ self.__convertor = converter
+
+ def __getattr__(self, name):
+ return getattr(self.__wrapped, name)
+
+ def write(self, text):
+ self.__convertor.write(text)
+
+
+class AnsiToWin32(object):
+ '''
+ Implements a 'write()' method which, on Windows, will strip ANSI character
+ sequences from the text, and if outputting to a tty, will convert them into
+ win32 function calls.
+ '''
+ ANSI_RE = re.compile('\033\[((?:\d|;)*)([a-zA-Z])')
+
+ def __init__(self, wrapped, convert=None, strip=None, autoreset=False):
+ # The wrapped stream (normally sys.stdout or sys.stderr)
+ self.wrapped = wrapped
+
+ # should we reset colors to defaults after every .write()
+ self.autoreset = autoreset
+
+ # create the proxy wrapping our output stream
+ self.stream = StreamWrapper(wrapped, self)
+
+ on_windows = sys.platform.startswith('win')
+
+ # should we strip ANSI sequences from our output?
+ if strip is None:
+ strip = on_windows
+ self.strip = strip
+
+ # should we should convert ANSI sequences into win32 calls?
+ if convert is None:
+ convert = on_windows and is_a_tty(wrapped)
+ self.convert = convert
+
+ # dict of ansi codes to win32 functions and parameters
+ self.win32_calls = self.get_win32_calls()
+
+ # are we wrapping stderr?
+ self.on_stderr = self.wrapped is sys.stderr
+
+
+ def should_wrap(self):
+ '''
+ True if this class is actually needed. If false, then the output
+ stream will not be affected, nor will win32 calls be issued, so
+ wrapping stdout is not actually required. This will generally be
+ False on non-Windows platforms, unless optional functionality like
+ autoreset has been requested using kwargs to init()
+ '''
+ return self.convert or self.strip or self.autoreset
+
+
+ def get_win32_calls(self):
+ if self.convert and winterm:
+ return {
+ AnsiStyle.RESET_ALL: (winterm.reset_all, ),
+ AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT),
+ AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL),
+ AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL),
+ AnsiFore.BLACK: (winterm.fore, WinColor.BLACK),
+ AnsiFore.RED: (winterm.fore, WinColor.RED),
+ AnsiFore.GREEN: (winterm.fore, WinColor.GREEN),
+ AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW),
+ AnsiFore.BLUE: (winterm.fore, WinColor.BLUE),
+ AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA),
+ AnsiFore.CYAN: (winterm.fore, WinColor.CYAN),
+ AnsiFore.WHITE: (winterm.fore, WinColor.GREY),
+ AnsiFore.RESET: (winterm.fore, ),
+ AnsiBack.BLACK: (winterm.back, WinColor.BLACK),
+ AnsiBack.RED: (winterm.back, WinColor.RED),
+ AnsiBack.GREEN: (winterm.back, WinColor.GREEN),
+ AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW),
+ AnsiBack.BLUE: (winterm.back, WinColor.BLUE),
+ AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA),
+ AnsiBack.CYAN: (winterm.back, WinColor.CYAN),
+ AnsiBack.WHITE: (winterm.back, WinColor.GREY),
+ AnsiBack.RESET: (winterm.back, ),
+ }
+
+
+ def write(self, text):
+ if self.strip or self.convert:
+ self.write_and_convert(text)
+ else:
+ self.wrapped.write(text)
+ self.wrapped.flush()
+ if self.autoreset:
+ self.reset_all()
+
+
+ def reset_all(self):
+ if self.convert:
+ self.call_win32('m', (0,))
+ else:
+ self.wrapped.write(Style.RESET_ALL)
+
+
+ def write_and_convert(self, text):
+ '''
+ Write the given text to our wrapped stream, stripping any ANSI
+ sequences from the text, and optionally converting them into win32
+ calls.
+ '''
+ cursor = 0
+ for match in self.ANSI_RE.finditer(text):
+ start, end = match.span()
+ self.write_plain_text(text, cursor, start)
+ self.convert_ansi(*match.groups())
+ cursor = end
+ self.write_plain_text(text, cursor, len(text))
+
+
+ def write_plain_text(self, text, start, end):
+ if start < end:
+ self.wrapped.write(text[start:end])
+ self.wrapped.flush()
+
+
+ def convert_ansi(self, paramstring, command):
+ if self.convert:
+ params = self.extract_params(paramstring)
+ self.call_win32(command, params)
+
+
+ def extract_params(self, paramstring):
+ def split(paramstring):
+ for p in paramstring.split(';'):
+ if p != '':
+ yield int(p)
+ return tuple(split(paramstring))
+
+
+ def call_win32(self, command, params):
+ if params == []:
+ params = [0]
+ if command == 'm':
+ for param in params:
+ if param in self.win32_calls:
+ func_args = self.win32_calls[param]
+ func = func_args[0]
+ args = func_args[1:]
+ kwargs = dict(on_stderr=self.on_stderr)
+ func(*args, **kwargs)
+
diff --git a/pyzen/_colorama/initialise.py b/pyzen/_colorama/initialise.py
index 4df5c3e..eca2bea 100644
--- a/pyzen/_colorama/initialise.py
+++ b/pyzen/_colorama/initialise.py
@@ -1,38 +1,38 @@
-import atexit
-import sys
-
-from .ansitowin32 import AnsiToWin32
-
-
-orig_stdout = sys.stdout
-orig_stderr = sys.stderr
-
-atexit_done = False
-
-
-def reset_all():
- AnsiToWin32(orig_stdout).reset_all()
-
-
-def init(autoreset=False, convert=None, strip=None, wrap=True):
-
- if wrap==False and (autoreset==True or convert==True or strip==True):
- raise ValueError('wrap=False conflicts with any other arg=True')
-
- sys.stdout = wrap_stream(orig_stdout, convert, strip, autoreset, wrap)
- sys.stderr = wrap_stream(orig_stderr, convert, strip, autoreset, wrap)
-
- global atexit_done
- if not atexit_done:
- atexit.register(reset_all)
- atexit_done = True
-
-
-def wrap_stream(stream, convert, strip, autoreset, wrap):
- if wrap:
- wrapper = AnsiToWin32(stream,
- convert=convert, strip=strip, autoreset=autoreset)
- if wrapper.should_wrap():
- stream = wrapper.stream
- return stream
-
+import atexit
+import sys
+
+from .ansitowin32 import AnsiToWin32
+
+
+orig_stdout = sys.stdout
+orig_stderr = sys.stderr
+
+atexit_done = False
+
+
+def reset_all():
+ AnsiToWin32(orig_stdout).reset_all()
+
+
+def init(autoreset=False, convert=None, strip=None, wrap=True):
+
+ if wrap==False and (autoreset==True or convert==True or strip==True):
+ raise ValueError('wrap=False conflicts with any other arg=True')
+
+ sys.stdout = wrap_stream(orig_stdout, convert, strip, autoreset, wrap)
+ sys.stderr = wrap_stream(orig_stderr, convert, strip, autoreset, wrap)
+
+ global atexit_done
+ if not atexit_done:
+ atexit.register(reset_all)
+ atexit_done = True
+
+
+def wrap_stream(stream, convert, strip, autoreset, wrap):
+ if wrap:
+ wrapper = AnsiToWin32(stream,
+ convert=convert, strip=strip, autoreset=autoreset)
+ if wrapper.should_wrap():
+ stream = wrapper.stream
+ return stream
+
diff --git a/pyzen/_colorama/win32.py b/pyzen/_colorama/win32.py
index 2a6fc94..5f49e6c 100644
--- a/pyzen/_colorama/win32.py
+++ b/pyzen/_colorama/win32.py
@@ -1,95 +1,95 @@
-
-# from winbase.h
-STDOUT = -11
-STDERR = -12
-
-try:
- from ctypes import windll
-except ImportError:
- windll = None
- SetConsoleTextAttribute = lambda *_: None
-else:
- from ctypes import (
- byref, Structure, c_char, c_short, c_uint32, c_ushort
- )
-
- handles = {
- STDOUT: windll.kernel32.GetStdHandle(STDOUT),
- STDERR: windll.kernel32.GetStdHandle(STDERR),
- }
-
- SHORT = c_short
- WORD = c_ushort
- DWORD = c_uint32
- TCHAR = c_char
-
- class COORD(Structure):
- """struct in wincon.h"""
- _fields_ = [
- ('X', SHORT),
- ('Y', SHORT),
- ]
-
- class SMALL_RECT(Structure):
- """struct in wincon.h."""
- _fields_ = [
- ("Left", SHORT),
- ("Top", SHORT),
- ("Right", SHORT),
- ("Bottom", SHORT),
- ]
-
- class CONSOLE_SCREEN_BUFFER_INFO(Structure):
- """struct in wincon.h."""
- _fields_ = [
- ("dwSize", COORD),
- ("dwCursorPosition", COORD),
- ("wAttributes", WORD),
- ("srWindow", SMALL_RECT),
- ("dwMaximumWindowSize", COORD),
- ]
-
- def GetConsoleScreenBufferInfo(stream_id):
- handle = handles[stream_id]
- csbi = CONSOLE_SCREEN_BUFFER_INFO()
- success = windll.kernel32.GetConsoleScreenBufferInfo(
- handle, byref(csbi))
- # This fails when imported via setup.py when installing using 'pip'
- # presumably the fix is that running setup.py should not trigger all
- # this activity.
- # assert success
- return csbi
-
- def SetConsoleTextAttribute(stream_id, attrs):
- handle = handles[stream_id]
- success = windll.kernel32.SetConsoleTextAttribute(handle, attrs)
- assert success
-
- def SetConsoleCursorPosition(stream_id, position):
- handle = handles[stream_id]
- position = COORD(*position)
- success = windll.kernel32.SetConsoleCursorPosition(handle, position)
- assert success
-
- def FillConsoleOutputCharacter(stream_id, char, length, start):
- handle = handles[stream_id]
- char = TCHAR(char)
- length = DWORD(length)
- start = COORD(*start)
- num_written = DWORD(0)
- # AttributeError: function 'FillConsoleOutputCharacter' not found
- # could it just be that my types are wrong?
- success = windll.kernel32.FillConsoleOutputCharacter(
- handle, char, length, start, byref(num_written))
- assert success
- return num_written.value
-
-
-if __name__=='__main__':
- x = GetConsoleScreenBufferInfo(STDOUT)
- print(x.dwSize)
- print(x.dwCursorPosition)
- print(x.wAttributes)
- print(x.srWindow)
- print(x.dwMaximumWindowSize)
-
+
+# from winbase.h
+STDOUT = -11
+STDERR = -12
+
+try:
+ from ctypes import windll
+except ImportError:
+ windll = None
+ SetConsoleTextAttribute = lambda *_: None
+else:
+ from ctypes import (
+ byref, Structure, c_char, c_short, c_uint32, c_ushort
+ )
+
+ handles = {
+ STDOUT: windll.kernel32.GetStdHandle(STDOUT),
+ STDERR: windll.kernel32.GetStdHandle(STDERR),
+ }
+
+ SHORT = c_short
+ WORD = c_ushort
+ DWORD = c_uint32
+ TCHAR = c_char
+
+ class COORD(Structure):
+ """struct in wincon.h"""
+ _fields_ = [
+ ('X', SHORT),
+ ('Y', SHORT),
+ ]
+
+ class SMALL_RECT(Structure):
+ """struct in wincon.h."""
+ _fields_ = [
+ ("Left", SHORT),
+ ("Top", SHORT),
+ ("Right", SHORT),
+ ("Bottom", SHORT),
+ ]
+
+ class CONSOLE_SCREEN_BUFFER_INFO(Structure):
+ """struct in wincon.h."""
+ _fields_ = [
+ ("dwSize", COORD),
+ ("dwCursorPosition", COORD),
+ ("wAttributes", WORD),
+ ("srWindow", SMALL_RECT),
+ ("dwMaximumWindowSize", COORD),
+ ]
+
+ def GetConsoleScreenBufferInfo(stream_id):
+ handle = handles[stream_id]
+ csbi = CONSOLE_SCREEN_BUFFER_INFO()
+ success = windll.kernel32.GetConsoleScreenBufferInfo(
+ handle, byref(csbi))
+ # This fails when imported via setup.py when installing using 'pip'
+ # presumably the fix is that running setup.py should not trigger all
+ # this activity.
+ # assert success
+ return csbi
+
+ def SetConsoleTextAttribute(stream_id, attrs):
+ handle = handles[stream_id]
+ success = windll.kernel32.SetConsoleTextAttribute(handle, attrs)
+ assert success
+
+ def SetConsoleCursorPosition(stream_id, position):
+ handle = handles[stream_id]
+ position = COORD(*position)
+ success = windll.kernel32.SetConsoleCursorPosition(handle, position)
+ assert success
+
+ def FillConsoleOutputCharacter(stream_id, char, length, start):
+ handle = handles[stream_id]
+ char = TCHAR(char)
+ length = DWORD(length)
+ start = COORD(*start)
+ num_written = DWORD(0)
+ # AttributeError: function 'FillConsoleOutputCharacter' not found
+ # could it just be that my types are wrong?
+ success = windll.kernel32.FillConsoleOutputCharacter(
+ handle, char, length, start, byref(num_written))
+ assert success
+ return num_written.value
+
+
+if __name__=='__main__':
+ x = GetConsoleScreenBufferInfo(STDOUT)
+ print(x.dwSize)
+ print(x.dwCursorPosition)
+ print(x.wAttributes)
+ print(x.srWindow)
+ print(x.dwMaximumWindowSize)
+
diff --git a/pyzen/_colorama/winterm.py b/pyzen/_colorama/winterm.py
index 4326c21..63f4469 100644
--- a/pyzen/_colorama/winterm.py
+++ b/pyzen/_colorama/winterm.py
@@ -1,69 +1,69 @@
-
-from . import win32
-
-
-# from wincon.h
-class WinColor(object):
- BLACK = 0
- BLUE = 1
- GREEN = 2
- CYAN = 3
- RED = 4
- MAGENTA = 5
- YELLOW = 6
- GREY = 7
-
-# from wincon.h
-class WinStyle(object):
- NORMAL = 0x00 # dim text, dim background
- BRIGHT = 0x08 # bright text, dim background
-
-
-class WinTerm(object):
-
- def __init__(self):
- self._default = \
- win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes
- self.set_attrs(self._default)
- self._default_fore = self._fore
- self._default_back = self._back
- self._default_style = self._style
-
- def get_attrs(self):
- return self._fore + self._back * 16 + self._style
-
- def set_attrs(self, value):
- self._fore = value & 7
- self._back = (value >> 4) & 7
- self._style = value & WinStyle.BRIGHT
-
- def reset_all(self, on_stderr=None):
- self.set_attrs(self._default)
- self.set_console(attrs=self._default)
-
- def fore(self, fore=None, on_stderr=False):
- if fore is None:
- fore = self._default_fore
- self._fore = fore
- self.set_console(on_stderr=on_stderr)
-
- def back(self, back=None, on_stderr=False):
- if back is None:
- back = self._default_back
- self._back = back
- self.set_console(on_stderr=on_stderr)
-
- def style(self, style=None, on_stderr=False):
- if style is None:
- style = self._default_style
- self._style = style
- self.set_console(on_stderr=on_stderr)
-
- def set_console(self, attrs=None, on_stderr=False):
- if attrs is None:
- attrs = self.get_attrs()
- handle = win32.STDOUT
- if on_stderr:
- handle = win32.STDERR
- win32.SetConsoleTextAttribute(handle, attrs)
-
+
+from . import win32
+
+
+# from wincon.h
+class WinColor(object):
+ BLACK = 0
+ BLUE = 1
+ GREEN = 2
+ CYAN = 3
+ RED = 4
+ MAGENTA = 5
+ YELLOW = 6
+ GREY = 7
+
+# from wincon.h
+class WinStyle(object):
+ NORMAL = 0x00 # dim text, dim background
+ BRIGHT = 0x08 # bright text, dim background
+
+
+class WinTerm(object):
+
+ def __init__(self):
+ self._default = \
+ win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes
+ self.set_attrs(self._default)
+ self._default_fore = self._fore
+ self._default_back = self._back
+ self._default_style = self._style
+
+ def get_attrs(self):
+ return self._fore + self._back * 16 + self._style
+
+ def set_attrs(self, value):
+ self._fore = value & 7
+ self._back = (value >> 4) & 7
+ self._style = value & WinStyle.BRIGHT
+
+ def reset_all(self, on_stderr=None):
+ self.set_attrs(self._default)
+ self.set_console(attrs=self._default)
+
+ def fore(self, fore=None, on_stderr=False):
+ if fore is None:
+ fore = self._default_fore
+ self._fore = fore
+ self.set_console(on_stderr=on_stderr)
+
+ def back(self, back=None, on_stderr=False):
+ if back is None:
+ back = self._default_back
+ self._back = back
+ self.set_console(on_stderr=on_stderr)
+
+ def style(self, style=None, on_stderr=False):
+ if style is None:
+ style = self._default_style
+ self._style = style
+ self.set_console(on_stderr=on_stderr)
+
+ def set_console(self, attrs=None, on_stderr=False):
+ if attrs is None:
+ attrs = self.get_attrs()
+ handle = win32.STDOUT
+ if on_stderr:
+ handle = win32.STDERR
+ win32.SetConsoleTextAttribute(handle, attrs)
+
diff --git a/pyzen/ui/osx.py b/pyzen/ui/osx.py
index cd2ad81..64a40ae 100644
--- a/pyzen/ui/osx.py
+++ b/pyzen/ui/osx.py
@@ -1,16 +1,43 @@
import subprocess
+import os
from pyzen.ui.base import img_path, PyZenUI
+
class AppleScriptError(Exception):
pass
+class TerminalNotifierError(Exception):
+ pass
+
+
def run_script(script):
proc = subprocess.Popen(['osascript', '-'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = proc.communicate(script)
if proc.returncode != 0:
- raise AppleScriptError('osascript failure: %s'%err)
+ raise AppleScriptError('osascript failure: %s' % err)
+ out = out.strip()
+ if out == 'true':
+ return True
+ elif out == 'false':
+ return False
+ elif out.isdigit():
+ return int(out)
+ else:
+ return out
+
+
+def run_notifier(**kwargs):
+ args = list()
+ for (k, v) in kwargs.iteritems():
+ if (k in ['message', 'title', 'subtitle', 'sound', 'group', 'list', 'activate', 'sender', 'open', 'execute']):
+ args += ['-' + k, v]
+ proc = subprocess.Popen(['terminal-notifier'] + args,
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = proc.communicate()
+ if proc.returncode != 0:
+ raise TerminalNotifierError('terminal-notifier failure: %s' % err)
out = out.strip()
if out == 'true':
return True
@@ -21,6 +48,7 @@ def run_script(script):
else:
return out
+
def is_growl_running():
"""Check if Growl is running. Run this before any other Growl functions."""
script = """
@@ -30,46 +58,62 @@ def is_growl_running():
"""
return run_script(script)
+
+def is_notifier_installed():
+ """Check if terminal-notifier is installed. Run this before any other functions."""
+ return os.system("which terminal-notifier") == 0
+
+
def register_app():
- script= """
+ script = """
tell application "GrowlHelperApp"
- -- Make a list of all the notification types
+ -- Make a list of all the notification types
-- that this script will ever send:
set the notificationsList to {"Test Successful" , "Test Failure"}
-- Register our script with growl.
- -- You can optionally (as here) set a default icon
+ -- You can optionally (as here) set a default icon
-- for this script's notifications.
register as application "ZenTest" all notifications notificationsList default notifications notificationsList
end tell"""
run_script(script)
+
def notify(type, title, msg, img='logo.png'):
- script= """
+ script = """
tell application "GrowlHelperApp"
notify with name "%s" title "%s" description "%s" application name "ZenTest" image from location "file://%s"
- end tell"""%(type, title, msg, img_path(img))
+ end tell""" % (type, title, msg, img_path(img))
run_script(script)
-class GrowlUI(PyZenUI):
+
+class OSXUI(PyZenUI):
+
"""A PyZen UI that uses Growl. Only supported on OS X."""
-
+
name = 'osx'
platform = 'darwin'
-
+
def __init__(self):
+ self.has_notifier = is_notifier_installed()
self.has_growl = is_growl_running()
if self.has_growl:
register_app()
-
+ elif self.has_notifier:
+ pass
+
def notify(self, failure, title, msg, icon):
+ type = failure and 'Test Failure' or 'Test Successful'
if self.has_growl:
- type = failure and 'Test Failure' or 'Test Successful'
- notify(type, title, msg, icon+'.png')
+ notify(type, title, msg, icon + '.png')
+ elif self.has_notifier:
+ run_notifier(message=msg, title=title, subtitle=type)
# Random test stuff
if __name__ == '__main__':
+ if is_notifier_installed():
+ run_notifier(subtitle='Test Successful', title='Test Successful', message='Run 1 test(s) in 0.001 seconds')
if is_growl_running():
register_app()
- notify('Test Successful', 'Test Successful', 'Run 1 test(s) in 0.001 seconds', 'red.png')
\ No newline at end of file
+ notify('Test Successful', 'Test Successful', 'Run 1 test(s) in 0.001 seconds', 'red.png')