forked from mirrors/gecko-dev
Bug 1744340 - Removed the unused blessings module r=firefox-build-system-reviewers,nalexander
Differential Revision: https://phabricator.services.mozilla.com/D160450
This commit is contained in:
parent
a86cf6d1a1
commit
db6c4f0bb5
10 changed files with 0 additions and 1423 deletions
|
|
@ -61,7 +61,6 @@ vendored:third_party/python/appdirs
|
|||
vendored:third_party/python/async_timeout
|
||||
vendored:third_party/python/attrs
|
||||
vendored:third_party/python/blessed
|
||||
vendored:third_party/python/blessings
|
||||
vendored:third_party/python/cbor2
|
||||
vendored:third_party/python/certifi
|
||||
vendored:third_party/python/chardet
|
||||
|
|
|
|||
|
|
@ -1,564 +0,0 @@
|
|||
Metadata-Version: 2.1
|
||||
Name: blessings
|
||||
Version: 1.7
|
||||
Summary: A thin, practical wrapper around terminal coloring, styling, and positioning
|
||||
Home-page: https://github.com/erikrose/blessings
|
||||
Author: Erik Rose
|
||||
Author-email: erikrose@grinchcentral.com
|
||||
License: MIT
|
||||
Keywords: terminal,tty,curses,ncurses,formatting,style,color,console
|
||||
Platform: UNKNOWN
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: Natural Language :: English
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Environment :: Console
|
||||
Classifier: Environment :: Console :: Curses
|
||||
Classifier: License :: OSI Approved :: MIT License
|
||||
Classifier: Operating System :: POSIX
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.4
|
||||
Classifier: Programming Language :: Python :: 3.5
|
||||
Classifier: Programming Language :: Python :: 3.6
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||
Classifier: Topic :: Software Development :: Libraries
|
||||
Classifier: Topic :: Software Development :: User Interfaces
|
||||
Classifier: Topic :: Terminals
|
||||
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
|
||||
Requires-Dist: six
|
||||
|
||||
=========
|
||||
Blessings
|
||||
=========
|
||||
|
||||
Coding with Blessings looks like this... ::
|
||||
|
||||
from blessings import Terminal
|
||||
|
||||
t = Terminal()
|
||||
|
||||
print t.bold('Hi there!')
|
||||
print t.bold_red_on_bright_green('It hurts my eyes!')
|
||||
|
||||
with t.location(0, t.height - 1):
|
||||
print 'This is at the bottom.'
|
||||
|
||||
Or, for byte-level control, you can drop down and play with raw terminal
|
||||
capabilities::
|
||||
|
||||
print '{t.bold}All your {t.red}bold and red base{t.normal}'.format(t=t)
|
||||
print t.wingo(2)
|
||||
|
||||
`Full API Reference <https://blessings.readthedocs.io/>`_
|
||||
|
||||
The Pitch
|
||||
=========
|
||||
|
||||
Blessings lifts several of curses_' limiting assumptions, and it makes your
|
||||
code pretty, too:
|
||||
|
||||
* Use styles, color, and maybe a little positioning without necessarily
|
||||
clearing the whole
|
||||
screen first.
|
||||
* Leave more than one screenful of scrollback in the buffer after your program
|
||||
exits, like a well-behaved command-line app should.
|
||||
* Get rid of all those noisy, C-like calls to ``tigetstr`` and ``tparm``, so
|
||||
your code doesn't get crowded out by terminal bookkeeping.
|
||||
* Act intelligently when somebody redirects your output to a file, omitting the
|
||||
terminal control codes the user doesn't want to see (optional).
|
||||
|
||||
.. _curses: http://docs.python.org/library/curses.html
|
||||
|
||||
Before And After
|
||||
----------------
|
||||
|
||||
Without Blessings, this is how you'd print some underlined text at the bottom
|
||||
of the screen::
|
||||
|
||||
from curses import tigetstr, setupterm, tparm
|
||||
from fcntl import ioctl
|
||||
from os import isatty
|
||||
import struct
|
||||
import sys
|
||||
from termios import TIOCGWINSZ
|
||||
|
||||
# If we want to tolerate having our output piped to other commands or
|
||||
# files without crashing, we need to do all this branching:
|
||||
if hasattr(sys.stdout, 'fileno') and isatty(sys.stdout.fileno()):
|
||||
setupterm()
|
||||
sc = tigetstr('sc')
|
||||
cup = tigetstr('cup')
|
||||
rc = tigetstr('rc')
|
||||
underline = tigetstr('smul')
|
||||
normal = tigetstr('sgr0')
|
||||
else:
|
||||
sc = cup = rc = underline = normal = ''
|
||||
print sc # Save cursor position.
|
||||
if cup:
|
||||
# tigetnum('lines') doesn't always update promptly, hence this:
|
||||
height = struct.unpack('hhhh', ioctl(0, TIOCGWINSZ, '\000' * 8))[0]
|
||||
print tparm(cup, height - 1, 0) # Move cursor to bottom.
|
||||
print 'This is {under}underlined{normal}!'.format(under=underline,
|
||||
normal=normal)
|
||||
print rc # Restore cursor position.
|
||||
|
||||
That was long and full of incomprehensible trash! Let's try it again, this time
|
||||
with Blessings::
|
||||
|
||||
from blessings import Terminal
|
||||
|
||||
term = Terminal()
|
||||
with term.location(0, term.height - 1):
|
||||
print 'This is', term.underline('pretty!')
|
||||
|
||||
Much better.
|
||||
|
||||
What It Provides
|
||||
================
|
||||
|
||||
Blessings provides just one top-level object: ``Terminal``. Instantiating a
|
||||
``Terminal`` figures out whether you're on a terminal at all and, if so, does
|
||||
any necessary terminal setup. After that, you can proceed to ask it all sorts
|
||||
of things about the terminal. Terminal terminal terminal.
|
||||
|
||||
Simple Formatting
|
||||
-----------------
|
||||
|
||||
Lots of handy formatting codes ("capabilities" in low-level parlance) are
|
||||
available as attributes on a ``Terminal``. For example::
|
||||
|
||||
from blessings import Terminal
|
||||
|
||||
term = Terminal()
|
||||
print 'I am ' + term.bold + 'bold' + term.normal + '!'
|
||||
|
||||
Though they are strings at heart, you can also use them as callable wrappers so
|
||||
you don't have to say ``normal`` afterward::
|
||||
|
||||
print 'I am', term.bold('bold') + '!'
|
||||
|
||||
Or, if you want fine-grained control while maintaining some semblance of
|
||||
brevity, you can combine it with Python's string formatting, which makes
|
||||
attributes easy to access::
|
||||
|
||||
print 'All your {t.red}base {t.underline}are belong to us{t.normal}'.format(t=term)
|
||||
|
||||
Simple capabilities of interest include...
|
||||
|
||||
* ``bold``
|
||||
* ``reverse``
|
||||
* ``underline``
|
||||
* ``no_underline`` (which turns off underlining)
|
||||
* ``blink``
|
||||
* ``normal`` (which turns off everything, even colors)
|
||||
|
||||
Here are a few more which are less likely to work on all terminals:
|
||||
|
||||
* ``dim``
|
||||
* ``italic`` and ``no_italic``
|
||||
* ``shadow`` and ``no_shadow``
|
||||
* ``standout`` and ``no_standout``
|
||||
* ``subscript`` and ``no_subscript``
|
||||
* ``superscript`` and ``no_superscript``
|
||||
* ``flash`` (which flashes the screen once)
|
||||
|
||||
Note that, while the inverse of ``underline`` is ``no_underline``, the only way
|
||||
to turn off ``bold`` or ``reverse`` is ``normal``, which also cancels any
|
||||
custom colors. This is because there's no portable way to tell the terminal to
|
||||
undo certain pieces of formatting, even at the lowest level.
|
||||
|
||||
You might also notice that the above aren't the typical incomprehensible
|
||||
terminfo capability names; we alias a few of the harder-to-remember ones for
|
||||
readability. However, you aren't limited to these: you can reference any
|
||||
string-returning capability listed on the `terminfo man page`_ by the name
|
||||
under the "Cap-name" column: for example, ``term.rum``.
|
||||
|
||||
.. _`terminfo man page`: http://www.manpagez.com/man/5/terminfo/
|
||||
|
||||
Color
|
||||
-----
|
||||
|
||||
16 colors, both foreground and background, are available as easy-to-remember
|
||||
attributes::
|
||||
|
||||
from blessings import Terminal
|
||||
|
||||
term = Terminal()
|
||||
print term.red + term.on_green + 'Red on green? Ick!' + term.normal
|
||||
print term.bright_red + term.on_bright_blue + 'This is even worse!' + term.normal
|
||||
|
||||
You can also call them as wrappers, which sets everything back to normal at the
|
||||
end::
|
||||
|
||||
print term.red_on_green('Red on green? Ick!')
|
||||
print term.yellow('I can barely see it.')
|
||||
|
||||
The available colors are...
|
||||
|
||||
* ``black``
|
||||
* ``red``
|
||||
* ``green``
|
||||
* ``yellow``
|
||||
* ``blue``
|
||||
* ``magenta``
|
||||
* ``cyan``
|
||||
* ``white``
|
||||
|
||||
You can set the background color instead of the foreground by prepending
|
||||
``on_``, as in ``on_blue``. There is also a ``bright`` version of each color:
|
||||
for example, ``on_bright_blue``.
|
||||
|
||||
There is also a numerical interface to colors, which takes an integer from
|
||||
0-15::
|
||||
|
||||
term.color(5) + 'Hello' + term.normal
|
||||
term.on_color(3) + 'Hello' + term.normal
|
||||
|
||||
term.color(5)('Hello')
|
||||
term.on_color(3)('Hello')
|
||||
|
||||
If some color is unsupported (for instance, if only the normal colors are
|
||||
available, not the bright ones), trying to use it will, on most terminals, have
|
||||
no effect: the foreground and background colors will stay as they were. You can
|
||||
get fancy and do different things depending on the supported colors by checking
|
||||
`number_of_colors`_.
|
||||
|
||||
.. _`number_of_colors`: http://packages.python.org/blessings/#blessings.Terminal.number_of_colors
|
||||
|
||||
Compound Formatting
|
||||
-------------------
|
||||
|
||||
If you want to do lots of crazy formatting all at once, you can just mash it
|
||||
all together::
|
||||
|
||||
from blessings import Terminal
|
||||
|
||||
term = Terminal()
|
||||
print term.bold_underline_green_on_yellow + 'Woo' + term.normal
|
||||
|
||||
Or you can use your newly coined attribute as a wrapper, which implicitly sets
|
||||
everything back to normal afterward::
|
||||
|
||||
print term.bold_underline_green_on_yellow('Woo')
|
||||
|
||||
This compound notation comes in handy if you want to allow users to customize
|
||||
the formatting of your app: just have them pass in a format specifier like
|
||||
"bold_green" on the command line, and do a quick ``getattr(term,
|
||||
that_option)('Your text')`` when you do your formatting.
|
||||
|
||||
I'd be remiss if I didn't credit couleur_, where I probably got the idea for
|
||||
all this mashing.
|
||||
|
||||
.. _couleur: http://pypi.python.org/pypi/couleur
|
||||
|
||||
Moving The Cursor
|
||||
-----------------
|
||||
|
||||
When you want to move the cursor to output text at a specific spot, you have
|
||||
a few choices.
|
||||
|
||||
Moving Temporarily
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Most often, you'll need to flit to a certain location, print something, and
|
||||
then return: for example, when updating a progress bar at the bottom of the
|
||||
screen. ``Terminal`` provides a context manager for doing this concisely::
|
||||
|
||||
from blessings import Terminal
|
||||
|
||||
term = Terminal()
|
||||
with term.location(0, term.height - 1):
|
||||
print 'Here is the bottom.'
|
||||
print 'This is back where I came from.'
|
||||
|
||||
Parameters to ``location()`` are ``x`` and then ``y``, but you can also pass
|
||||
just one of them, leaving the other alone. For example... ::
|
||||
|
||||
with term.location(y=10):
|
||||
print 'We changed just the row.'
|
||||
|
||||
If you're doing a series of ``move`` calls (see below) and want to return the
|
||||
cursor to its original position afterward, call ``location()`` with no
|
||||
arguments, and it will do only the position restoring::
|
||||
|
||||
with term.location():
|
||||
print term.move(1, 1) + 'Hi'
|
||||
print term.move(9, 9) + 'Mom'
|
||||
|
||||
Note that, since ``location()`` uses the terminal's built-in
|
||||
position-remembering machinery, you can't usefully nest multiple calls. Use
|
||||
``location()`` at the outermost spot, and use simpler things like ``move``
|
||||
inside.
|
||||
|
||||
Moving Permanently
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you just want to move and aren't worried about returning, do something like
|
||||
this::
|
||||
|
||||
from blessings import Terminal
|
||||
|
||||
term = Terminal()
|
||||
print term.move(10, 1) + 'Hi, mom!'
|
||||
|
||||
``move``
|
||||
Position the cursor elsewhere. Parameters are y coordinate, then x
|
||||
coordinate.
|
||||
``move_x``
|
||||
Move the cursor to the given column.
|
||||
``move_y``
|
||||
Move the cursor to the given row.
|
||||
|
||||
How does all this work? These are simply more terminal capabilities, wrapped to
|
||||
give them nicer names. The added wrinkle--that they take parameters--is also
|
||||
given a pleasant treatment: rather than making you dig up ``tparm()`` all the
|
||||
time, we simply make these capabilities into callable strings. You'd get the
|
||||
raw capability strings if you were to just print them, but they're fully
|
||||
parametrized if you pass params to them as if they were functions.
|
||||
|
||||
Consequently, you can also reference any other string-returning capability
|
||||
listed on the `terminfo man page`_ by its name under the "Cap-name" column.
|
||||
|
||||
.. _`terminfo man page`: http://www.manpagez.com/man/5/terminfo/
|
||||
|
||||
One-Notch Movement
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Finally, there are some parameterless movement capabilities that move the
|
||||
cursor one character in various directions:
|
||||
|
||||
* ``move_left``
|
||||
* ``move_right``
|
||||
* ``move_up``
|
||||
* ``move_down``
|
||||
|
||||
For example... ::
|
||||
|
||||
print term.move_up + 'Howdy!'
|
||||
|
||||
Height And Width
|
||||
----------------
|
||||
|
||||
It's simple to get the height and width of the terminal, in characters::
|
||||
|
||||
from blessings import Terminal
|
||||
|
||||
term = Terminal()
|
||||
height = term.height
|
||||
width = term.width
|
||||
|
||||
These are newly updated each time you ask for them, so they're safe to use from
|
||||
SIGWINCH handlers.
|
||||
|
||||
Clearing The Screen
|
||||
-------------------
|
||||
|
||||
Blessings provides syntactic sugar over some screen-clearing capabilities:
|
||||
|
||||
``clear``
|
||||
Clear the whole screen.
|
||||
``clear_eol``
|
||||
Clear to the end of the line.
|
||||
``clear_bol``
|
||||
Clear backward to the beginning of the line.
|
||||
``clear_eos``
|
||||
Clear to the end of screen.
|
||||
|
||||
Full-Screen Mode
|
||||
----------------
|
||||
|
||||
Perhaps you have seen a full-screen program, such as an editor, restore the
|
||||
exact previous state of the terminal upon exiting, including, for example, the
|
||||
command-line prompt from which it was launched. Curses pretty much forces you
|
||||
into this behavior, but Blessings makes it optional. If you want to do the
|
||||
state-restoration thing, use these capabilities:
|
||||
|
||||
``enter_fullscreen``
|
||||
Switch to the terminal mode where full-screen output is sanctioned. Print
|
||||
this before you do any output.
|
||||
``exit_fullscreen``
|
||||
Switch back to normal mode, restoring the exact state from before
|
||||
``enter_fullscreen`` was used.
|
||||
|
||||
Using ``exit_fullscreen`` will wipe away any trace of your program's output, so
|
||||
reserve it for when you don't want to leave anything behind in the scrollback.
|
||||
|
||||
There's also a context manager you can use as a shortcut::
|
||||
|
||||
from blessings import Terminal
|
||||
|
||||
term = Terminal()
|
||||
with term.fullscreen():
|
||||
# Print some stuff.
|
||||
|
||||
Besides brevity, another advantage is that it switches back to normal mode even
|
||||
if an exception is raised in the ``with`` block.
|
||||
|
||||
Pipe Savvy
|
||||
----------
|
||||
|
||||
If your program isn't attached to a terminal, like if it's being piped to
|
||||
another command or redirected to a file, all the capability attributes on
|
||||
``Terminal`` will return empty strings. You'll get a nice-looking file without
|
||||
any formatting codes gumming up the works.
|
||||
|
||||
If you want to override this--like if you anticipate your program being piped
|
||||
through ``less -r``, which handles terminal escapes just fine--pass
|
||||
``force_styling=True`` to the ``Terminal`` constructor.
|
||||
|
||||
In any case, there is a ``does_styling`` attribute on ``Terminal`` that lets
|
||||
you see whether your capabilities will return actual, working formatting codes.
|
||||
If it's false, you should refrain from drawing progress bars and other frippery
|
||||
and just stick to content, since you're apparently headed into a pipe::
|
||||
|
||||
from blessings import Terminal
|
||||
|
||||
term = Terminal()
|
||||
if term.does_styling:
|
||||
with term.location(0, term.height - 1):
|
||||
print 'Progress: [=======> ]'
|
||||
print term.bold('Important stuff')
|
||||
|
||||
Shopping List
|
||||
=============
|
||||
|
||||
There are decades of legacy tied up in terminal interaction, so attention to
|
||||
detail and behavior in edge cases make a difference. Here are some ways
|
||||
Blessings has your back:
|
||||
|
||||
* Uses the terminfo database so it works with any terminal type
|
||||
* Provides up-to-the-moment terminal height and width, so you can respond to
|
||||
terminal size changes (SIGWINCH signals). (Most other libraries query the
|
||||
``COLUMNS`` and ``LINES`` environment variables or the ``cols`` or ``lines``
|
||||
terminal capabilities, which don't update promptly, if at all.)
|
||||
* Avoids making a mess if the output gets piped to a non-terminal
|
||||
* Works great with standard Python string templating
|
||||
* Provides convenient access to all terminal capabilities, not just a sugared
|
||||
few
|
||||
* Outputs to any file-like object, not just stdout
|
||||
* Keeps a minimum of internal state, so you can feel free to mix and match with
|
||||
calls to curses or whatever other terminal libraries you like
|
||||
|
||||
Blessings does not provide...
|
||||
|
||||
* Native color support on the Windows command prompt. However, it should work
|
||||
when used in concert with colorama_.
|
||||
|
||||
.. _colorama: http://pypi.python.org/pypi/colorama/0.2.4
|
||||
|
||||
Bugs
|
||||
====
|
||||
|
||||
Bugs or suggestions? Visit the `issue tracker`_.
|
||||
|
||||
.. _`issue tracker`: https://github.com/erikrose/blessings/issues/
|
||||
|
||||
Blessings tests are run automatically by `Travis CI`_.
|
||||
|
||||
.. _`Travis CI`: https://travis-ci.org/erikrose/blessings/
|
||||
|
||||
.. image:: https://travis-ci.org/erikrose/blessings.svg?branch=master
|
||||
:target: https://travis-ci.org/erikrose/blessings
|
||||
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
Blessings is under the MIT License. See the LICENSE file.
|
||||
|
||||
Version History
|
||||
===============
|
||||
|
||||
1.7
|
||||
* Drop support for Python 2.6 and 3.3, which are end-of-lifed.
|
||||
* Switch from 2to3 to the ``six`` library.
|
||||
|
||||
1.6.1
|
||||
* Don't crash if ``number_of_colors()`` is called when run in a non-terminal
|
||||
or when ``does_styling`` is otherwise false.
|
||||
|
||||
1.6
|
||||
* Add ``does_styling`` property. This takes ``force_styling`` into account
|
||||
and should replace most uses of ``is_a_tty``.
|
||||
* Make ``is_a_tty`` a read-only property, like ``does_styling``. Writing to
|
||||
it never would have done anything constructive.
|
||||
* Add ``fullscreen()`` and ``hidden_cursor()`` to the auto-generated docs.
|
||||
* Fall back to ``LINES`` and ``COLUMNS`` environment vars to find height and
|
||||
width. (jquast)
|
||||
* Support terminal types, such as kermit and avatar, that use bytes 127-255
|
||||
in their escape sequences. (jquast)
|
||||
|
||||
1.5.1
|
||||
* Clean up fabfile, removing the redundant ``test`` command.
|
||||
* Add Travis support.
|
||||
* Make ``python setup.py test`` work without spurious errors on 2.6.
|
||||
* Work around a tox parsing bug in its config file.
|
||||
* Make context managers clean up after themselves even if there's an
|
||||
exception. (Vitja Makarov)
|
||||
* Parametrizing a capability no longer crashes when there is no tty. (Vitja
|
||||
Makarov)
|
||||
|
||||
1.5
|
||||
* Add syntactic sugar and documentation for ``enter_fullscreen`` and
|
||||
``exit_fullscreen``.
|
||||
* Add context managers ``fullscreen()`` and ``hidden_cursor()``.
|
||||
* Now you can force a ``Terminal`` never to emit styles by passing
|
||||
``force_styling=None``.
|
||||
|
||||
1.4
|
||||
* Add syntactic sugar for cursor visibility control and single-space-movement
|
||||
capabilities.
|
||||
* Endorse the ``location()`` idiom for restoring cursor position after a
|
||||
series of manual movements.
|
||||
* Fix a bug in which ``location()`` wouldn't do anything when passed zeroes.
|
||||
* Allow tests to be run with ``python setup.py test``.
|
||||
|
||||
1.3
|
||||
* Added ``number_of_colors``, which tells you how many colors the terminal
|
||||
supports.
|
||||
* Made ``color(n)`` and ``on_color(n)`` callable to wrap a string, like the
|
||||
named colors can. Also, make them both fall back to the ``setf`` and
|
||||
``setb`` capabilities (like the named colors do) if the ANSI ``setaf`` and
|
||||
``setab`` aren't available.
|
||||
* Allowed ``color`` attr to act as an unparametrized string, not just a
|
||||
callable.
|
||||
* Made ``height`` and ``width`` examine any passed-in stream before falling
|
||||
back to stdout. (This rarely if ever affects actual behavior; it's mostly
|
||||
philosophical.)
|
||||
* Made caching simpler and slightly more efficient.
|
||||
* Got rid of a reference cycle between Terminals and FormattingStrings.
|
||||
* Updated docs to reflect that terminal addressing (as in ``location()``) is
|
||||
0-based.
|
||||
|
||||
1.2
|
||||
* Added support for Python 3! We need 3.2.3 or greater, because the curses
|
||||
library couldn't decide whether to accept strs or bytes before that
|
||||
(http://bugs.python.org/issue10570).
|
||||
* Everything that comes out of the library is now unicode. This lets us
|
||||
support Python 3 without making a mess of the code, and Python 2 should
|
||||
continue to work unless you were testing types (and badly). Please file a
|
||||
bug if this causes trouble for you.
|
||||
* Changed to the MIT License for better world domination.
|
||||
* Added Sphinx docs.
|
||||
|
||||
1.1
|
||||
* Added nicely named attributes for colors.
|
||||
* Introduced compound formatting.
|
||||
* Added wrapper behavior for styling and colors.
|
||||
* Let you force capabilities to be non-empty, even if the output stream is
|
||||
not a terminal.
|
||||
* Added the ``is_a_tty`` attribute for telling whether the output stream is a
|
||||
terminal.
|
||||
* Sugared the remaining interesting string capabilities.
|
||||
* Let ``location()`` operate on just an x *or* y coordinate.
|
||||
|
||||
1.0
|
||||
* Extracted Blessings from nose-progressive, my `progress-bar-having,
|
||||
traceback-shortcutting, rootin', tootin' testrunner`_. It provided the
|
||||
tootin' functionality.
|
||||
|
||||
.. _`progress-bar-having, traceback-shortcutting, rootin', tootin' testrunner`: http://pypi.python.org/pypi/nose-progressive/
|
||||
|
||||
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
blessings/__init__.py,sha256=fuk_wcBYDooRZYG7HxMBllmeg-sUlJkb1fn2PIobK-8,21885
|
||||
blessings/tests.py,sha256=YkYrnSUfgqKH1JRFYuOJDCfAJxroNNsTdkgYgPLgwp4,8506
|
||||
blessings-1.7.dist-info/METADATA,sha256=z2xOZcraJNCmzceEsxR-d3s5omjTakjQv69BRX2vJcs,19687
|
||||
blessings-1.7.dist-info/RECORD,,
|
||||
blessings-1.7.dist-info/WHEEL,sha256=NzFAKnL7g-U64xnS1s5e3mJnxKpOTeOtlXdFwS9yNXI,92
|
||||
blessings-1.7.dist-info/top_level.txt,sha256=vzAJmOe2K6vUJXLCDJIkIX05x4C-TjBDN7LcVcV-SpM,10
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.31.1)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py3-none-any
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
blessings
|
||||
556
third_party/python/blessings/blessings/__init__.py
vendored
556
third_party/python/blessings/blessings/__init__.py
vendored
|
|
@ -1,556 +0,0 @@
|
|||
"""A thin, practical wrapper around terminal coloring, styling, and
|
||||
positioning"""
|
||||
|
||||
from contextlib import contextmanager
|
||||
import curses
|
||||
from curses import setupterm, tigetnum, tigetstr, tparm
|
||||
from fcntl import ioctl
|
||||
from six import text_type, string_types
|
||||
|
||||
try:
|
||||
from io import UnsupportedOperation as IOUnsupportedOperation
|
||||
except ImportError:
|
||||
class IOUnsupportedOperation(Exception):
|
||||
"""A dummy exception to take the place of Python 3's
|
||||
``io.UnsupportedOperation`` in Python 2"""
|
||||
|
||||
from os import isatty, environ
|
||||
import struct
|
||||
import sys
|
||||
from termios import TIOCGWINSZ
|
||||
|
||||
|
||||
__all__ = ['Terminal']
|
||||
|
||||
|
||||
class Terminal(object):
|
||||
"""An abstraction around terminal capabilities
|
||||
|
||||
Unlike curses, this doesn't require clearing the screen before doing
|
||||
anything, and it's friendlier to use. It keeps the endless calls to
|
||||
``tigetstr()`` and ``tparm()`` out of your code, and it acts intelligently
|
||||
when somebody pipes your output to a non-terminal.
|
||||
|
||||
Instance attributes:
|
||||
|
||||
``stream``
|
||||
The stream the terminal outputs to. It's convenient to pass the stream
|
||||
around with the terminal; it's almost always needed when the terminal
|
||||
is and saves sticking lots of extra args on client functions in
|
||||
practice.
|
||||
|
||||
"""
|
||||
def __init__(self, kind=None, stream=None, force_styling=False):
|
||||
"""Initialize the terminal.
|
||||
|
||||
If ``stream`` is not a tty, I will default to returning an empty
|
||||
Unicode string for all capability values, so things like piping your
|
||||
output to a file won't strew escape sequences all over the place. The
|
||||
``ls`` command sets a precedent for this: it defaults to columnar
|
||||
output when being sent to a tty and one-item-per-line when not.
|
||||
|
||||
:arg kind: A terminal string as taken by ``setupterm()``. Defaults to
|
||||
the value of the ``TERM`` environment variable.
|
||||
:arg stream: A file-like object representing the terminal. Defaults to
|
||||
the original value of stdout, like ``curses.initscr()`` does.
|
||||
:arg force_styling: Whether to force the emission of capabilities, even
|
||||
if we don't seem to be in a terminal. This comes in handy if users
|
||||
are trying to pipe your output through something like ``less -r``,
|
||||
which supports terminal codes just fine but doesn't appear itself
|
||||
to be a terminal. Just expose a command-line option, and set
|
||||
``force_styling`` based on it. Terminal initialization sequences
|
||||
will be sent to ``stream`` if it has a file descriptor and to
|
||||
``sys.__stdout__`` otherwise. (``setupterm()`` demands to send them
|
||||
somewhere, and stdout is probably where the output is ultimately
|
||||
headed. If not, stderr is probably bound to the same terminal.)
|
||||
|
||||
If you want to force styling to not happen, pass
|
||||
``force_styling=None``.
|
||||
|
||||
"""
|
||||
if stream is None:
|
||||
stream = sys.__stdout__
|
||||
try:
|
||||
stream_descriptor = (stream.fileno() if hasattr(stream, 'fileno')
|
||||
and callable(stream.fileno)
|
||||
else None)
|
||||
except IOUnsupportedOperation:
|
||||
stream_descriptor = None
|
||||
|
||||
self._is_a_tty = (stream_descriptor is not None and
|
||||
isatty(stream_descriptor))
|
||||
self._does_styling = ((self.is_a_tty or force_styling) and
|
||||
force_styling is not None)
|
||||
|
||||
# The descriptor to direct terminal initialization sequences to.
|
||||
# sys.__stdout__ seems to always have a descriptor of 1, even if output
|
||||
# is redirected.
|
||||
self._init_descriptor = (sys.__stdout__.fileno()
|
||||
if stream_descriptor is None
|
||||
else stream_descriptor)
|
||||
if self.does_styling:
|
||||
# Make things like tigetstr() work. Explicit args make setupterm()
|
||||
# work even when -s is passed to nosetests. Lean toward sending
|
||||
# init sequences to the stream if it has a file descriptor, and
|
||||
# send them to stdout as a fallback, since they have to go
|
||||
# somewhere.
|
||||
setupterm(kind or environ.get('TERM', 'unknown'),
|
||||
self._init_descriptor)
|
||||
|
||||
self.stream = stream
|
||||
|
||||
# Sugary names for commonly-used capabilities, intended to help avoid trips
|
||||
# to the terminfo man page and comments in your code:
|
||||
_sugar = dict(
|
||||
# Don't use "on" or "bright" as an underscore-separated chunk in any of
|
||||
# these (e.g. on_cology or rock_on) so we don't interfere with
|
||||
# __getattr__.
|
||||
save='sc',
|
||||
restore='rc',
|
||||
|
||||
clear_eol='el',
|
||||
clear_bol='el1',
|
||||
clear_eos='ed',
|
||||
# 'clear' clears the whole screen.
|
||||
position='cup', # deprecated
|
||||
enter_fullscreen='smcup',
|
||||
exit_fullscreen='rmcup',
|
||||
move='cup',
|
||||
move_x='hpa',
|
||||
move_y='vpa',
|
||||
move_left='cub1',
|
||||
move_right='cuf1',
|
||||
move_up='cuu1',
|
||||
move_down='cud1',
|
||||
|
||||
hide_cursor='civis',
|
||||
normal_cursor='cnorm',
|
||||
|
||||
reset_colors='op', # oc doesn't work on my OS X terminal.
|
||||
|
||||
normal='sgr0',
|
||||
reverse='rev',
|
||||
# 'bold' is just 'bold'. Similarly...
|
||||
# blink
|
||||
# dim
|
||||
# flash
|
||||
italic='sitm',
|
||||
no_italic='ritm',
|
||||
shadow='sshm',
|
||||
no_shadow='rshm',
|
||||
standout='smso',
|
||||
no_standout='rmso',
|
||||
subscript='ssubm',
|
||||
no_subscript='rsubm',
|
||||
superscript='ssupm',
|
||||
no_superscript='rsupm',
|
||||
underline='smul',
|
||||
no_underline='rmul')
|
||||
|
||||
def __getattr__(self, attr):
|
||||
"""Return a terminal capability, like bold.
|
||||
|
||||
For example, you can say ``term.bold`` to get the string that turns on
|
||||
bold formatting and ``term.normal`` to get the string that turns it off
|
||||
again. Or you can take a shortcut: ``term.bold('hi')`` bolds its
|
||||
argument and sets everything to normal afterward. You can even combine
|
||||
things: ``term.bold_underline_red_on_bright_green('yowzers!')``.
|
||||
|
||||
For a parametrized capability like ``cup``, pass the parameters too:
|
||||
``some_term.cup(line, column)``.
|
||||
|
||||
``man terminfo`` for a complete list of capabilities.
|
||||
|
||||
Return values are always Unicode.
|
||||
|
||||
"""
|
||||
resolution = (self._resolve_formatter(attr) if self.does_styling
|
||||
else NullCallableString())
|
||||
setattr(self, attr, resolution) # Cache capability codes.
|
||||
return resolution
|
||||
|
||||
@property
|
||||
def does_styling(self):
|
||||
"""Whether attempt to emit capabilities
|
||||
|
||||
This is influenced by the ``is_a_tty`` property and by the
|
||||
``force_styling`` argument to the constructor. You can examine
|
||||
this value to decide whether to draw progress bars or other frippery.
|
||||
|
||||
"""
|
||||
return self._does_styling
|
||||
|
||||
@property
|
||||
def is_a_tty(self):
|
||||
"""Whether my ``stream`` appears to be associated with a terminal"""
|
||||
return self._is_a_tty
|
||||
|
||||
@property
|
||||
def height(self):
|
||||
"""The height of the terminal in characters
|
||||
|
||||
If no stream or a stream not representing a terminal was passed in at
|
||||
construction, return the dimension of the controlling terminal so
|
||||
piping to things that eventually display on the terminal (like ``less
|
||||
-R``) work. If a stream representing a terminal was passed in, return
|
||||
the dimensions of that terminal. If there somehow is no controlling
|
||||
terminal, return ``None``. (Thus, you should check that the property
|
||||
``is_a_tty`` is true before doing any math on the result.)
|
||||
|
||||
"""
|
||||
return self._height_and_width()[0]
|
||||
|
||||
@property
|
||||
def width(self):
|
||||
"""The width of the terminal in characters
|
||||
|
||||
See ``height()`` for some corner cases.
|
||||
|
||||
"""
|
||||
return self._height_and_width()[1]
|
||||
|
||||
def _height_and_width(self):
|
||||
"""Return a tuple of (terminal height, terminal width).
|
||||
|
||||
Start by trying TIOCGWINSZ (Terminal I/O-Control: Get Window Size),
|
||||
falling back to environment variables (LINES, COLUMNS), and returning
|
||||
(None, None) if those are unavailable or invalid.
|
||||
|
||||
"""
|
||||
# tigetnum('lines') and tigetnum('cols') update only if we call
|
||||
# setupterm() again.
|
||||
for descriptor in self._init_descriptor, sys.__stdout__:
|
||||
try:
|
||||
return struct.unpack(
|
||||
'hhhh', ioctl(descriptor, TIOCGWINSZ, '\000' * 8))[0:2]
|
||||
except IOError:
|
||||
# when the output stream or init descriptor is not a tty, such
|
||||
# as when when stdout is piped to another program, fe. tee(1),
|
||||
# these ioctls will raise IOError
|
||||
pass
|
||||
try:
|
||||
return int(environ.get('LINES')), int(environ.get('COLUMNS'))
|
||||
except TypeError:
|
||||
return None, None
|
||||
|
||||
@contextmanager
|
||||
def location(self, x=None, y=None):
|
||||
"""Return a context manager for temporarily moving the cursor.
|
||||
|
||||
Move the cursor to a certain position on entry, let you print stuff
|
||||
there, then return the cursor to its original position::
|
||||
|
||||
term = Terminal()
|
||||
with term.location(2, 5):
|
||||
print 'Hello, world!'
|
||||
for x in xrange(10):
|
||||
print 'I can do it %i times!' % x
|
||||
|
||||
Specify ``x`` to move to a certain column, ``y`` to move to a certain
|
||||
row, both, or neither. If you specify neither, only the saving and
|
||||
restoration of cursor position will happen. This can be useful if you
|
||||
simply want to restore your place after doing some manual cursor
|
||||
movement.
|
||||
|
||||
"""
|
||||
# Save position and move to the requested column, row, or both:
|
||||
self.stream.write(self.save)
|
||||
if x is not None and y is not None:
|
||||
self.stream.write(self.move(y, x))
|
||||
elif x is not None:
|
||||
self.stream.write(self.move_x(x))
|
||||
elif y is not None:
|
||||
self.stream.write(self.move_y(y))
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
# Restore original cursor position:
|
||||
self.stream.write(self.restore)
|
||||
|
||||
@contextmanager
|
||||
def fullscreen(self):
|
||||
"""Return a context manager that enters fullscreen mode while inside it
|
||||
and restores normal mode on leaving."""
|
||||
self.stream.write(self.enter_fullscreen)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
self.stream.write(self.exit_fullscreen)
|
||||
|
||||
@contextmanager
|
||||
def hidden_cursor(self):
|
||||
"""Return a context manager that hides the cursor while inside it and
|
||||
makes it visible on leaving."""
|
||||
self.stream.write(self.hide_cursor)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
self.stream.write(self.normal_cursor)
|
||||
|
||||
@property
|
||||
def color(self):
|
||||
"""Return a capability that sets the foreground color.
|
||||
|
||||
The capability is unparametrized until called and passed a number
|
||||
(0-15), at which point it returns another string which represents a
|
||||
specific color change. This second string can further be called to
|
||||
color a piece of text and set everything back to normal afterward.
|
||||
|
||||
:arg num: The number, 0-15, of the color
|
||||
|
||||
"""
|
||||
return ParametrizingString(self._foreground_color, self.normal)
|
||||
|
||||
@property
|
||||
def on_color(self):
|
||||
"""Return a capability that sets the background color.
|
||||
|
||||
See ``color()``.
|
||||
|
||||
"""
|
||||
return ParametrizingString(self._background_color, self.normal)
|
||||
|
||||
@property
|
||||
def number_of_colors(self):
|
||||
"""Return the number of colors the terminal supports.
|
||||
|
||||
Common values are 0, 8, 16, 88, and 256.
|
||||
|
||||
Though the underlying capability returns -1 when there is no color
|
||||
support, we return 0. This lets you test more Pythonically::
|
||||
|
||||
if term.number_of_colors:
|
||||
...
|
||||
|
||||
We also return 0 if the terminal won't tell us how many colors it
|
||||
supports, which I think is rare.
|
||||
|
||||
"""
|
||||
# This is actually the only remotely useful numeric capability. We
|
||||
# don't name it after the underlying capability, because we deviate
|
||||
# slightly from its behavior, and we might someday wish to give direct
|
||||
# access to it.
|
||||
if not self._does_styling:
|
||||
return 0
|
||||
|
||||
colors = tigetnum('colors') # Returns -1 if no color support, -2 if no
|
||||
# such cap.
|
||||
# self.__dict__['colors'] = ret # Cache it. It's not changing.
|
||||
# (Doesn't work.)
|
||||
return colors if colors >= 0 else 0
|
||||
|
||||
def _resolve_formatter(self, attr):
|
||||
"""Resolve a sugary or plain capability name, color, or compound
|
||||
formatting function name into a callable capability.
|
||||
|
||||
Return a ``ParametrizingString`` or a ``FormattingString``.
|
||||
|
||||
"""
|
||||
if attr in COLORS:
|
||||
return self._resolve_color(attr)
|
||||
elif attr in COMPOUNDABLES:
|
||||
# Bold, underline, or something that takes no parameters
|
||||
return self._formatting_string(self._resolve_capability(attr))
|
||||
else:
|
||||
formatters = split_into_formatters(attr)
|
||||
if all(f in COMPOUNDABLES for f in formatters):
|
||||
# It's a compound formatter, like "bold_green_on_red". Future
|
||||
# optimization: combine all formatting into a single escape
|
||||
# sequence.
|
||||
return self._formatting_string(
|
||||
u''.join(self._resolve_formatter(s) for s in formatters))
|
||||
else:
|
||||
return ParametrizingString(self._resolve_capability(attr))
|
||||
|
||||
def _resolve_capability(self, atom):
|
||||
"""Return a terminal code for a capname or a sugary name, or an empty
|
||||
Unicode.
|
||||
|
||||
The return value is always Unicode, because otherwise it is clumsy
|
||||
(especially in Python 3) to concatenate with real (Unicode) strings.
|
||||
|
||||
"""
|
||||
code = tigetstr(self._sugar.get(atom, atom))
|
||||
if code:
|
||||
# See the comment in ParametrizingString for why this is latin1.
|
||||
return code.decode('latin1')
|
||||
return u''
|
||||
|
||||
def _resolve_color(self, color):
|
||||
"""Resolve a color like red or on_bright_green into a callable
|
||||
capability."""
|
||||
# TODO: Does curses automatically exchange red and blue and cyan and
|
||||
# yellow when a terminal supports setf/setb rather than setaf/setab?
|
||||
# I'll be blasted if I can find any documentation. The following
|
||||
# assumes it does.
|
||||
color_cap = (self._background_color if 'on_' in color else
|
||||
self._foreground_color)
|
||||
# curses constants go up to only 7, so add an offset to get at the
|
||||
# bright colors at 8-15:
|
||||
offset = 8 if 'bright_' in color else 0
|
||||
base_color = color.rsplit('_', 1)[-1]
|
||||
return self._formatting_string(
|
||||
color_cap(getattr(curses, 'COLOR_' + base_color.upper()) + offset))
|
||||
|
||||
@property
|
||||
def _foreground_color(self):
|
||||
return self.setaf or self.setf
|
||||
|
||||
@property
|
||||
def _background_color(self):
|
||||
return self.setab or self.setb
|
||||
|
||||
def _formatting_string(self, formatting):
|
||||
"""Return a new ``FormattingString`` which implicitly receives my
|
||||
notion of "normal"."""
|
||||
return FormattingString(formatting, self.normal)
|
||||
|
||||
|
||||
def derivative_colors(colors):
|
||||
"""Return the names of valid color variants, given the base colors."""
|
||||
return set([('on_' + c) for c in colors] +
|
||||
[('bright_' + c) for c in colors] +
|
||||
[('on_bright_' + c) for c in colors])
|
||||
|
||||
|
||||
COLORS = set(['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan',
|
||||
'white'])
|
||||
COLORS.update(derivative_colors(COLORS))
|
||||
COMPOUNDABLES = (COLORS |
|
||||
set(['bold', 'underline', 'reverse', 'blink', 'dim', 'italic',
|
||||
'shadow', 'standout', 'subscript', 'superscript']))
|
||||
|
||||
|
||||
class ParametrizingString(text_type):
|
||||
"""A Unicode string which can be called to parametrize it as a terminal
|
||||
capability"""
|
||||
|
||||
def __new__(cls, formatting, normal=None):
|
||||
"""Instantiate.
|
||||
|
||||
:arg normal: If non-None, indicates that, once parametrized, this can
|
||||
be used as a ``FormattingString``. The value is used as the
|
||||
"normal" capability.
|
||||
|
||||
"""
|
||||
new = text_type.__new__(cls, formatting)
|
||||
new._normal = normal
|
||||
return new
|
||||
|
||||
def __call__(self, *args):
|
||||
try:
|
||||
# Re-encode the cap, because tparm() takes a bytestring in Python
|
||||
# 3. However, appear to be a plain Unicode string otherwise so
|
||||
# concats work.
|
||||
#
|
||||
# We use *latin1* encoding so that bytes emitted by tparm are
|
||||
# encoded to their native value: some terminal kinds, such as
|
||||
# 'avatar' or 'kermit', emit 8-bit bytes in range 0x7f to 0xff.
|
||||
# latin1 leaves these values unmodified in their conversion to
|
||||
# unicode byte values. The terminal emulator will "catch" and
|
||||
# handle these values, even if emitting utf8-encoded text, where
|
||||
# these bytes would otherwise be illegal utf8 start bytes.
|
||||
parametrized = tparm(self.encode('latin1'), *args).decode('latin1')
|
||||
return (parametrized if self._normal is None else
|
||||
FormattingString(parametrized, self._normal))
|
||||
except curses.error:
|
||||
# Catch "must call (at least) setupterm() first" errors, as when
|
||||
# running simply `nosetests` (without progressive) on nose-
|
||||
# progressive. Perhaps the terminal has gone away between calling
|
||||
# tigetstr and calling tparm.
|
||||
return u''
|
||||
except TypeError:
|
||||
# If the first non-int (i.e. incorrect) arg was a string, suggest
|
||||
# something intelligent:
|
||||
if len(args) == 1 and isinstance(args[0], string_types):
|
||||
raise TypeError(
|
||||
'A native or nonexistent capability template received '
|
||||
'%r when it was expecting ints. You probably misspelled a '
|
||||
'formatting call like bright_red_on_white(...).' % args)
|
||||
else:
|
||||
# Somebody passed a non-string; I don't feel confident
|
||||
# guessing what they were trying to do.
|
||||
raise
|
||||
|
||||
|
||||
class FormattingString(text_type):
|
||||
"""A Unicode string which can be called upon a piece of text to wrap it in
|
||||
formatting"""
|
||||
|
||||
def __new__(cls, formatting, normal):
|
||||
new = text_type.__new__(cls, formatting)
|
||||
new._normal = normal
|
||||
return new
|
||||
|
||||
def __call__(self, text):
|
||||
"""Return a new string that is ``text`` formatted with my contents.
|
||||
|
||||
At the beginning of the string, I prepend the formatting that is my
|
||||
contents. At the end, I append the "normal" sequence to set everything
|
||||
back to defaults. The return value is always a Unicode.
|
||||
|
||||
"""
|
||||
return self + text + self._normal
|
||||
|
||||
|
||||
class NullCallableString(text_type):
|
||||
"""A dummy callable Unicode to stand in for ``FormattingString`` and
|
||||
``ParametrizingString``
|
||||
|
||||
We use this when there is no tty and thus all capabilities should be blank.
|
||||
|
||||
"""
|
||||
def __new__(cls):
|
||||
new = text_type.__new__(cls, u'')
|
||||
return new
|
||||
|
||||
def __call__(self, *args):
|
||||
"""Return a Unicode or whatever you passed in as the first arg
|
||||
(hopefully a string of some kind).
|
||||
|
||||
When called with an int as the first arg, return an empty Unicode. An
|
||||
int is a good hint that I am a ``ParametrizingString``, as there are
|
||||
only about half a dozen string-returning capabilities on OS X's
|
||||
terminfo man page which take any param that's not an int, and those are
|
||||
seldom if ever used on modern terminal emulators. (Most have to do with
|
||||
programming function keys. Blessings' story for supporting
|
||||
non-string-returning caps is undeveloped.) And any parametrized
|
||||
capability in a situation where all capabilities themselves are taken
|
||||
to be blank are, of course, themselves blank.
|
||||
|
||||
When called with a non-int as the first arg (no no args at all), return
|
||||
the first arg. I am acting as a ``FormattingString``.
|
||||
|
||||
"""
|
||||
if len(args) != 1 or isinstance(args[0], int):
|
||||
# I am acting as a ParametrizingString.
|
||||
|
||||
# tparm can take not only ints but also (at least) strings as its
|
||||
# second...nth args. But we don't support callably parametrizing
|
||||
# caps that take non-ints yet, so we can cheap out here. TODO: Go
|
||||
# through enough of the motions in the capability resolvers to
|
||||
# determine which of 2 special-purpose classes,
|
||||
# NullParametrizableString or NullFormattingString, to return, and
|
||||
# retire this one.
|
||||
return u''
|
||||
return args[0] # Should we force even strs in Python 2.x to be
|
||||
# unicodes? No. How would I know what encoding to use
|
||||
# to convert it?
|
||||
|
||||
|
||||
def split_into_formatters(compound):
|
||||
"""Split a possibly compound format string into segments.
|
||||
|
||||
>>> split_into_formatters('bold_underline_bright_blue_on_red')
|
||||
['bold', 'underline', 'bright_blue', 'on_red']
|
||||
|
||||
"""
|
||||
merged_segs = []
|
||||
# These occur only as prefixes, so they can always be merged:
|
||||
mergeable_prefixes = ['on', 'bright', 'on_bright']
|
||||
for s in compound.split('_'):
|
||||
if merged_segs and merged_segs[-1] in mergeable_prefixes:
|
||||
merged_segs[-1] += '_' + s
|
||||
else:
|
||||
merged_segs.append(s)
|
||||
return merged_segs
|
||||
269
third_party/python/blessings/blessings/tests.py
vendored
269
third_party/python/blessings/blessings/tests.py
vendored
|
|
@ -1,269 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Automated tests (as opposed to human-verified test patterns)
|
||||
|
||||
It was tempting to mock out curses to get predictable output from ``tigetstr``,
|
||||
but there are concrete integration-testing benefits in not doing so. For
|
||||
instance, ``tigetstr`` changed its return type in Python 3.2.3. So instead, we
|
||||
simply create all our test ``Terminal`` instances with a known terminal type.
|
||||
All we require from the host machine is that a standard terminfo definition of
|
||||
xterm-256color exists.
|
||||
|
||||
"""
|
||||
from curses import tigetstr, tparm
|
||||
from functools import partial
|
||||
import sys
|
||||
|
||||
from nose import SkipTest
|
||||
from nose.tools import eq_
|
||||
from six import StringIO
|
||||
|
||||
# This tests that __all__ is correct, since we use below everything that should
|
||||
# be imported:
|
||||
from blessings import *
|
||||
|
||||
|
||||
TestTerminal = partial(Terminal, kind='xterm-256color')
|
||||
|
||||
|
||||
def unicode_cap(cap):
|
||||
"""Return the result of ``tigetstr`` except as Unicode."""
|
||||
return tigetstr(cap).decode('latin1')
|
||||
|
||||
|
||||
def unicode_parm(cap, *parms):
|
||||
"""Return the result of ``tparm(tigetstr())`` except as Unicode."""
|
||||
return tparm(tigetstr(cap), *parms).decode('latin1')
|
||||
|
||||
|
||||
def test_capability():
|
||||
"""Check that a capability lookup works.
|
||||
|
||||
Also test that Terminal grabs a reasonable default stream. This test
|
||||
assumes it will be run from a tty.
|
||||
|
||||
"""
|
||||
t = TestTerminal()
|
||||
sc = unicode_cap('sc')
|
||||
eq_(t.save, sc)
|
||||
eq_(t.save, sc) # Make sure caching doesn't screw it up.
|
||||
|
||||
|
||||
def test_capability_without_tty():
|
||||
"""Assert capability templates are '' when stream is not a tty."""
|
||||
t = TestTerminal(stream=StringIO())
|
||||
eq_(t.save, u'')
|
||||
eq_(t.red, u'')
|
||||
|
||||
|
||||
def test_capability_with_forced_tty():
|
||||
"""If we force styling, capabilities had better not (generally) be
|
||||
empty."""
|
||||
t = TestTerminal(stream=StringIO(), force_styling=True)
|
||||
eq_(t.save, unicode_cap('sc'))
|
||||
|
||||
|
||||
def test_parametrization():
|
||||
"""Test parametrizing a capability."""
|
||||
eq_(TestTerminal().cup(3, 4), unicode_parm('cup', 3, 4))
|
||||
|
||||
|
||||
def test_height_and_width():
|
||||
"""Assert that ``height_and_width()`` returns ints."""
|
||||
t = TestTerminal() # kind shouldn't matter.
|
||||
assert isinstance(t.height, int)
|
||||
assert isinstance(t.width, int)
|
||||
|
||||
|
||||
def test_stream_attr():
|
||||
"""Make sure Terminal exposes a ``stream`` attribute that defaults to
|
||||
something sane."""
|
||||
eq_(Terminal().stream, sys.__stdout__)
|
||||
|
||||
|
||||
def test_location():
|
||||
"""Make sure ``location()`` does what it claims."""
|
||||
t = TestTerminal(stream=StringIO(), force_styling=True)
|
||||
|
||||
with t.location(3, 4):
|
||||
t.stream.write(u'hi')
|
||||
|
||||
eq_(t.stream.getvalue(), unicode_cap('sc') +
|
||||
unicode_parm('cup', 4, 3) +
|
||||
u'hi' +
|
||||
unicode_cap('rc'))
|
||||
|
||||
|
||||
def test_horizontal_location():
|
||||
"""Make sure we can move the cursor horizontally without changing rows."""
|
||||
t = TestTerminal(stream=StringIO(), force_styling=True)
|
||||
with t.location(x=5):
|
||||
pass
|
||||
eq_(t.stream.getvalue(), unicode_cap('sc') +
|
||||
unicode_parm('hpa', 5) +
|
||||
unicode_cap('rc'))
|
||||
|
||||
|
||||
def test_null_location():
|
||||
"""Make sure ``location()`` with no args just does position restoration."""
|
||||
t = TestTerminal(stream=StringIO(), force_styling=True)
|
||||
with t.location():
|
||||
pass
|
||||
eq_(t.stream.getvalue(), unicode_cap('sc') +
|
||||
unicode_cap('rc'))
|
||||
|
||||
|
||||
def test_zero_location():
|
||||
"""Make sure ``location()`` pays attention to 0-valued args."""
|
||||
t = TestTerminal(stream=StringIO(), force_styling=True)
|
||||
with t.location(0, 0):
|
||||
pass
|
||||
eq_(t.stream.getvalue(), unicode_cap('sc') +
|
||||
unicode_parm('cup', 0, 0) +
|
||||
unicode_cap('rc'))
|
||||
|
||||
|
||||
def test_null_fileno():
|
||||
"""Make sure ``Terminal`` works when ``fileno`` is ``None``.
|
||||
|
||||
This simulates piping output to another program.
|
||||
|
||||
"""
|
||||
out = StringIO()
|
||||
out.fileno = None
|
||||
t = TestTerminal(stream=out)
|
||||
eq_(t.save, u'')
|
||||
|
||||
|
||||
def test_mnemonic_colors():
|
||||
"""Make sure color shortcuts work."""
|
||||
def color(num):
|
||||
return unicode_parm('setaf', num)
|
||||
|
||||
def on_color(num):
|
||||
return unicode_parm('setab', num)
|
||||
|
||||
# Avoid testing red, blue, yellow, and cyan, since they might someday
|
||||
# change depending on terminal type.
|
||||
t = TestTerminal()
|
||||
eq_(t.white, color(7))
|
||||
eq_(t.green, color(2)) # Make sure it's different than white.
|
||||
eq_(t.on_black, on_color(0))
|
||||
eq_(t.on_green, on_color(2))
|
||||
eq_(t.bright_black, color(8))
|
||||
eq_(t.bright_green, color(10))
|
||||
eq_(t.on_bright_black, on_color(8))
|
||||
eq_(t.on_bright_green, on_color(10))
|
||||
|
||||
|
||||
def test_callable_numeric_colors():
|
||||
"""``color(n)`` should return a formatting wrapper."""
|
||||
t = TestTerminal()
|
||||
eq_(t.color(5)('smoo'), t.magenta + 'smoo' + t.normal)
|
||||
eq_(t.color(5)('smoo'), t.color(5) + 'smoo' + t.normal)
|
||||
eq_(t.on_color(2)('smoo'), t.on_green + 'smoo' + t.normal)
|
||||
eq_(t.on_color(2)('smoo'), t.on_color(2) + 'smoo' + t.normal)
|
||||
|
||||
|
||||
def test_null_callable_numeric_colors():
|
||||
"""``color(n)`` should be a no-op on null terminals."""
|
||||
t = TestTerminal(stream=StringIO())
|
||||
eq_(t.color(5)('smoo'), 'smoo')
|
||||
eq_(t.on_color(6)('smoo'), 'smoo')
|
||||
|
||||
|
||||
def test_naked_color_cap():
|
||||
"""``term.color`` should return a stringlike capability."""
|
||||
t = TestTerminal()
|
||||
eq_(t.color + '', t.setaf + '')
|
||||
|
||||
|
||||
def test_number_of_colors_without_tty():
|
||||
"""``number_of_colors`` should return 0 when there's no tty."""
|
||||
# Hypothesis: once setupterm() has run and decided the tty supports 256
|
||||
# colors, it never changes its mind.
|
||||
raise SkipTest
|
||||
|
||||
t = TestTerminal(stream=StringIO())
|
||||
eq_(t.number_of_colors, 0)
|
||||
t = TestTerminal(stream=StringIO(), force_styling=True)
|
||||
eq_(t.number_of_colors, 0)
|
||||
|
||||
|
||||
def test_number_of_colors_with_tty():
|
||||
"""``number_of_colors`` should work."""
|
||||
t = TestTerminal()
|
||||
eq_(t.number_of_colors, 256)
|
||||
|
||||
|
||||
def test_formatting_functions():
|
||||
"""Test crazy-ass formatting wrappers, both simple and compound."""
|
||||
t = TestTerminal()
|
||||
# By now, it should be safe to use sugared attributes. Other tests test
|
||||
# those.
|
||||
eq_(t.bold(u'hi'), t.bold + u'hi' + t.normal)
|
||||
eq_(t.green('hi'), t.green + u'hi' + t.normal) # Plain strs for Python 2.x
|
||||
# Test some non-ASCII chars, probably not necessary:
|
||||
eq_(t.bold_green(u'boö'), t.bold + t.green + u'boö' + t.normal)
|
||||
eq_(t.bold_underline_green_on_red('boo'),
|
||||
t.bold + t.underline + t.green + t.on_red + u'boo' + t.normal)
|
||||
# Don't spell things like this:
|
||||
eq_(t.on_bright_red_bold_bright_green_underline('meh'),
|
||||
t.on_bright_red + t.bold + t.bright_green + t.underline + u'meh' +
|
||||
t.normal)
|
||||
|
||||
|
||||
def test_formatting_functions_without_tty():
|
||||
"""Test crazy-ass formatting wrappers when there's no tty."""
|
||||
t = TestTerminal(stream=StringIO())
|
||||
eq_(t.bold(u'hi'), u'hi')
|
||||
eq_(t.green('hi'), u'hi')
|
||||
# Test non-ASCII chars, no longer really necessary:
|
||||
eq_(t.bold_green(u'boö'), u'boö')
|
||||
eq_(t.bold_underline_green_on_red('loo'), u'loo')
|
||||
eq_(t.on_bright_red_bold_bright_green_underline('meh'), u'meh')
|
||||
|
||||
|
||||
def test_nice_formatting_errors():
|
||||
"""Make sure you get nice hints if you misspell a formatting wrapper."""
|
||||
t = TestTerminal()
|
||||
try:
|
||||
t.bold_misspelled('hey')
|
||||
except TypeError as e:
|
||||
assert 'probably misspelled' in e.args[0]
|
||||
|
||||
try:
|
||||
t.bold_misspelled(u'hey') # unicode
|
||||
except TypeError as e:
|
||||
assert 'probably misspelled' in e.args[0]
|
||||
|
||||
try:
|
||||
t.bold_misspelled(None) # an arbitrary non-string
|
||||
except TypeError as e:
|
||||
assert 'probably misspelled' not in e.args[0]
|
||||
|
||||
try:
|
||||
t.bold_misspelled('a', 'b') # >1 string arg
|
||||
except TypeError as e:
|
||||
assert 'probably misspelled' not in e.args[0]
|
||||
|
||||
|
||||
def test_init_descriptor_always_initted():
|
||||
"""We should be able to get a height and width even on no-tty Terminals."""
|
||||
t = Terminal(stream=StringIO())
|
||||
eq_(type(t.height), int)
|
||||
|
||||
|
||||
def test_force_styling_none():
|
||||
"""If ``force_styling=None`` is passed to the constructor, don't ever do
|
||||
styling."""
|
||||
t = TestTerminal(force_styling=None)
|
||||
eq_(t.save, '')
|
||||
|
||||
|
||||
def test_null_callable_string():
|
||||
"""Make sure NullCallableString tolerates all numbers and kinds of args it
|
||||
might receive."""
|
||||
t = TestTerminal(stream=StringIO())
|
||||
eq_(t.clear, '')
|
||||
eq_(t.move(1, 2), '')
|
||||
eq_(t.move_x(1), '')
|
||||
16
third_party/python/poetry.lock
generated
vendored
16
third_party/python/poetry.lock
generated
vendored
|
|
@ -69,17 +69,6 @@ jinxed = {version = ">=1.1.0", markers = "platform_system == \"Windows\""}
|
|||
six = ">=1.9.0"
|
||||
wcwidth = ">=0.1.4"
|
||||
|
||||
[[package]]
|
||||
name = "blessings"
|
||||
version = "1.7"
|
||||
description = "A thin, practical wrapper around terminal coloring, styling, and positioning"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
|
||||
[package.dependencies]
|
||||
six = "*"
|
||||
|
||||
[[package]]
|
||||
name = "cbor2"
|
||||
version = "4.0.1"
|
||||
|
|
@ -862,11 +851,6 @@ blessed = [
|
|||
{file = "blessed-1.19.1-py2.py3-none-any.whl", hash = "sha256:63b8554ae2e0e7f43749b6715c734cc8f3883010a809bf16790102563e6cf25b"},
|
||||
{file = "blessed-1.19.1.tar.gz", hash = "sha256:9a0d099695bf621d4680dd6c73f6ad547f6a3442fbdbe80c4b1daa1edbc492fc"},
|
||||
]
|
||||
blessings = [
|
||||
{file = "blessings-1.7-py2-none-any.whl", hash = "sha256:caad5211e7ba5afe04367cdd4cfc68fa886e2e08f6f35e76b7387d2109ccea6e"},
|
||||
{file = "blessings-1.7-py3-none-any.whl", hash = "sha256:b1fdd7e7a675295630f9ae71527a8ebc10bfefa236b3d6aa4932ee4462c17ba3"},
|
||||
{file = "blessings-1.7.tar.gz", hash = "sha256:98e5854d805f50a5b58ac2333411b0482516a8210f23f43308baeb58d77c157d"},
|
||||
]
|
||||
cbor2 = [
|
||||
{file = "cbor2-4.0.1-py2.py3-none-any.whl", hash = "sha256:b0eb916c9ea226aa81e9091607737475d5b0e5c314fe8d5a87179fba449cd190"},
|
||||
{file = "cbor2-4.0.1.tar.gz", hash = "sha256:cee0d01e520563b5a73c72eace5c428bb68aefb1b3f7aee5d692d3af6a1e5172"},
|
||||
|
|
|
|||
1
third_party/python/requirements.in
vendored
1
third_party/python/requirements.in
vendored
|
|
@ -1,7 +1,6 @@
|
|||
appdirs==1.4.4
|
||||
attrs==19.2.0
|
||||
blessed==1.19.1
|
||||
blessings==1.7
|
||||
cbor2==4.0.1
|
||||
colorama==0.4.5
|
||||
compare-locales==8.2.1
|
||||
|
|
|
|||
4
third_party/python/requirements.txt
vendored
4
third_party/python/requirements.txt
vendored
|
|
@ -51,10 +51,6 @@ attrs==19.2.0; (python_version >= "2.7" and python_full_version < "3.0.0") or (p
|
|||
blessed==1.19.1; python_version >= "2.7" \
|
||||
--hash=sha256:63b8554ae2e0e7f43749b6715c734cc8f3883010a809bf16790102563e6cf25b \
|
||||
--hash=sha256:9a0d099695bf621d4680dd6c73f6ad547f6a3442fbdbe80c4b1daa1edbc492fc
|
||||
blessings==1.7; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.4.0") \
|
||||
--hash=sha256:caad5211e7ba5afe04367cdd4cfc68fa886e2e08f6f35e76b7387d2109ccea6e \
|
||||
--hash=sha256:b1fdd7e7a675295630f9ae71527a8ebc10bfefa236b3d6aa4932ee4462c17ba3 \
|
||||
--hash=sha256:98e5854d805f50a5b58ac2333411b0482516a8210f23f43308baeb58d77c157d
|
||||
cbor2==4.0.1 \
|
||||
--hash=sha256:b0eb916c9ea226aa81e9091607737475d5b0e5c314fe8d5a87179fba449cd190 \
|
||||
--hash=sha256:cee0d01e520563b5a73c72eace5c428bb68aefb1b3f7aee5d692d3af6a1e5172
|
||||
|
|
|
|||
Loading…
Reference in a new issue