Repository: jquast/blessed

Issue:
add new properties, pixel_height and pixel_width
- We have ``term.height`` and ``term.width``, we should add ``term.pixel_height`` and ``term.pixel_width``. We simply document the possibility of value 0, meaning non-support. This is what is "packed" by glibc or other non-supporting libraries or emulators.

references,

https://bugzilla.gnome.org/show_bug.cgi?id=782576
https://bugzilla.gnome.org/show_bug.cgi?id=729204

anyway this the most basic property needed to generally support libsixel.

Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/jquast/blessed/pull/157?src=pr&el=h1) Report
> Merging [#157](https://codecov.io/gh/jquast/blessed/pull/157?src=pr&el=desc) into [master](https://codecov.io/gh/jquast/blessed/commit/22eec83109d03056f84ba220e255afb800f889d3?src=pr&el=desc) will **decrease** coverage by `0.46%`.
> The diff coverage is `81.81%`.

[![Impacted file tree graph](https://codecov.io/gh/jquast/blessed/pull/157/graphs/tree.svg?width=650&token=tIujGCtGmp&height=150&src=pr)](https://codecov.io/gh/jquast/blessed/pull/157?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #157      +/-   ##
==========================================
- Coverage   95.64%   95.18%   -0.47%     
==========================================
  Files           8        8              
  Lines         987      996       +9     
  Branches      157      158       +1     
==========================================
+ Hits          944      948       +4     
- Misses         40       45       +5     
  Partials        3        3
```


| [Impacted Files](https://codecov.io/gh/jquast/blessed/pull/157?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [blessed/keyboard.py](https://codecov.io/gh/jquast/blessed/pull/157/diff?src=pr&el=tree#diff-Ymxlc3NlZC9rZXlib2FyZC5weQ==) | `100% <ø> (ø)` | :arrow_up: |
| [blessed/formatters.py](https://codecov.io/gh/jquast/blessed/pull/157/diff?src=pr&el=tree#diff-Ymxlc3NlZC9mb3JtYXR0ZXJzLnB5) | `100% <100%> (ø)` | :arrow_up: |
| [blessed/terminal.py](https://codecov.io/gh/jquast/blessed/pull/157/diff?src=pr&el=tree#diff-Ymxlc3NlZC90ZXJtaW5hbC5weQ==) | `97.97% <71.42%> (-0.43%)` | :arrow_down: |
| [blessed/win\_terminal.py](https://codecov.io/gh/jquast/blessed/pull/157/diff?src=pr&el=tree#diff-Ymxlc3NlZC93aW5fdGVybWluYWwucHk=) | `27.77% <0%> (-5.56%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/jquast/blessed/pull/157?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/jquast/blessed/pull/157?src=pr&el=footer). Last update [22eec83...de8d879](https://codecov.io/gh/jquast/blessed/pull/157?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/.landscape.yml b/.landscape.yml
deleted file mode 100644
index 578295e..0000000
--- a/.landscape.yml
+++ /dev/null
@@ -1,100 +0,0 @@
-inherits:
-    - strictness_veryhigh
-
-ignore-patterns:
-    - (^|/)\..+
-    - ^docs/
-    - ^build/
-    # ignore these, their quality does not so much matter.
-    - ^blessed/tests/
-    - ^tools/
-
-test-warnings: true
-
-output-format: grouped
-
-dodgy:
-    # Looks at Python code to search for things which look "dodgy"
-    # such as passwords or git conflict artifacts
-    run: true
-
-pyflakes:
-    # preferring 'frosted' instead (a fork of)
-    run: true
-    disable:
-        # Terminal imported but unused (false)
-        - 'E101'
-
-frosted:
-    run: false
-
-mccabe:
-    # complexity checking.  We know of only one offense of the
-    # default of 10, which is Terminal.inkey() at exactly 10.
-    # It is not easily avoided, likely removing deprecation
-    # warnings in a future release will help reduce it.
-    run: false
-    options:
-        max-complexity: 11
-
-pep257:
-    # docstring checking
-    run: true
-    disable:
-        # 1 blank line required before class docstring
-        - 'D203'
-        # 1 blank line required after class docstring
-        - 'D204'
-        # Multi-line docstring summary should start at the first line
-        - 'D212'
-        # First line should be in imperative mood
-        - 'D401'
-
-pep8:
-    # style checking
-    run: true
-
-pylint:
-    # static analysis and then some
-    run: true
-    options:
-        # pytest module has dynamically assigned functions,
-        # raising errors such as: E1101: Module 'pytest' has
-        # no 'mark' member
-        ignored-classes: pytest
-        # List of builtins function names that should not be used, separated by a comma
-        # bad-functions=map,filter,input
-        bad-functions: input
-        persistent: no
-        # 'ks' is often-cited variable representing Keystroke instance.
-        # 'fd' is a common shorthand term for file descriptor (as int).
-        good-names: _,ks,fd
-
-
-    disable:
-        - protected-access
-        - too-few-public-methods
-        - star-args
-        - wrong-import-order
-        - wrong-import-position
-        - ungrouped-imports
-        - useless-object-inheritance
-
-pyroma:
-    # checks setup.py
-    run: true
-    disable:
-        # > Setuptools and Distribute support running tests. By specifying a test
-        # > suite, it's easy to find and run tests both for automated tools and humans.
-        #
-        # https://pytest.org/latest/goodpractises.html#integration-with-setuptools-test-commands
-        # > Most often it is better to use tox instead
-        #
-        # we agree.
-        - 'PYR15'
-
-vulture:
-    # this tool does a good job of finding unused code.
-    run: false
-
-# vim: noai:ts=4:sw=4
diff --git a/blessed/formatters.py b/blessed/formatters.py
index 44735a7..535a8fe 100644
--- a/blessed/formatters.py
+++ b/blessed/formatters.py
@@ -53,6 +53,7 @@ class ParameterizingString(six.text_type):
 
     For example::
 
+        >>> from blessed import Terminal
         >>> term = Terminal()
         >>> color = ParameterizingString(term.color, term.normal, 'color')
         >>> color(9)('color #9')
@@ -97,10 +98,8 @@ class ParameterizingString(six.text_type):
             # something intelligent:
             if args and isinstance(args[0], six.string_types):
                 raise TypeError(
-                    "A native or nonexistent capability template, %r received"
-                    " invalid argument %r: %s. You probably misspelled a"
-                    " formatting call like `bright_red'" % (
-                        self._name, args, err))
+                    "Unknown terminal capability, %r, or, TypeError "
+                    "for arguments %r: %s" % (self._name, args, err))
             # Somebody passed a non-string; I don't feel confident
             # guessing what they were trying to do.
             raise
@@ -182,6 +181,8 @@ class FormattingString(six.text_type):
     given (string) argument with the 2nd argument used by the class
     constructor::
 
+        >>> from blessed import Terminal
+        >>> term = Terminal()
         >>> style = FormattingString(term.bright_blue, term.normal)
         >>> print(repr(style))
         u'\x1b[94m'
@@ -216,13 +217,13 @@ class FormattingString(six.text_type):
         # >>> t.red('This is ', t.bold('extremely'), ' dangerous!')
         for idx, ucs_part in enumerate(args):
             if not isinstance(ucs_part, six.string_types):
-                raise TypeError("Positional argument #{idx} is {is_type} "
-                                "expected any of {expected_types}: "
-                                "{ucs_part!r}".format(
-                                    idx=idx, ucs_part=ucs_part,
-                                    is_type=type(ucs_part),
-                                    expected_types=six.string_types,
-                                ))
+                expected_types = ', '.join([
+                    _type.__name__ for _type in six.string_types])
+                raise TypeError(
+                    "TypeError for FormattingString argument, "
+                    "%r, at position %s: expected type %s, "
+                    "got %s" % (ucs_part, idx, expected_types,
+                                type(ucs_part).__name__))
         postfix = u''
         if self and self._normal:
             postfix = self._normal
@@ -240,6 +241,8 @@ class FormattingOtherString(six.text_type):
     This is used for the :meth:`~.Terminal.move_up`, ``down``, ``left``, and ``right()``
     family of functions::
 
+        >>> from blessed import Terminal
+        >>> term = Terminal()
         >>> move_right = FormattingOtherString(term.cuf1, term.cuf)
         >>> print(repr(move_right))
         u'\x1b[C'
@@ -261,6 +264,10 @@ class FormattingOtherString(six.text_type):
         new._callable = target
         return new
 
+    def __getnewargs__(self):
+        # return arguments used for the __new__ method upon unpickling.
+        return six.text_type.__new__(six.text_type, self), self._callable
+
     def __call__(self, *args):
         """Return ``text`` by ``target``."""
         if args:
@@ -382,11 +389,11 @@ def resolve_capability(term, attr):
        given :attr:`~.Terminal.kind`.
     :rtype: str
     """
-    # Decode sequences as latin1, as they are always 8-bit bytes, so when
-    # b'\xff' is returned, this must be decoded to u'\xff'.
     if not term.does_styling:
         return u''
     val = curses.tigetstr(term._sugar.get(attr, attr))  # pylint: disable=protected-access
+    # Decode sequences as latin1, as they are always 8-bit bytes, so when
+    # b'\xff' is returned, this is decoded as u'\xff'.
     return u'' if val is None else val.decode('latin1')
 
 
diff --git a/blessed/keyboard.py b/blessed/keyboard.py
index f5c4fab..c7aa604 100644
--- a/blessed/keyboard.py
+++ b/blessed/keyboard.py
@@ -218,7 +218,7 @@ def get_leading_prefixes(sequences):
 
 def resolve_sequence(text, mapper, codes):
     r"""
-    Return :class:`Keystroke` instance for given sequence ``text``.
+    Return a single :class:`Keystroke` instance for given sequence ``text``.
 
     :arg str text: string of characters received from terminal input stream.
     :arg OrderedDict mapper: unicode multibyte sequences, such as ``u'\x1b[D'``
@@ -231,7 +231,7 @@ def resolve_sequence(text, mapper, codes):
     The given ``text`` may extend beyond a matching sequence, such as
     ``u\x1b[Dxxx`` returns a :class:`Keystroke` instance of attribute
     :attr:`Keystroke.sequence` valued only ``u\x1b[D``.  It is up to
-    determine that ``xxx`` remains unresolved.
+    calls to determine that ``xxx`` remains unresolved.
     """
     for sequence, code in mapper.items():
         if text.startswith(sequence):
diff --git a/blessed/terminal.py b/blessed/terminal.py
index 5b71fe9..a666e55 100644
--- a/blessed/terminal.py
+++ b/blessed/terminal.py
@@ -371,7 +371,7 @@ class Terminal(object):
         <https://invisible-island.net/ncurses/man/terminfo.5.html>`_ for a
         complete list of capabilities and their arguments.
         """
-        if not self.does_styling:
+        if not self._does_styling:
             return NullCallableString()
         # Fetch the missing 'attribute' into some kind of curses-resolved
         # capability, and cache by attaching to this Terminal class instance.
@@ -427,6 +427,24 @@ class Terminal(object):
         """
         return self._height_and_width().ws_col
 
+    @property
+    def pixel_height(self):
+        """
+        Read-only property: Height ofthe terminal (in pixels).
+
+        :rtype: int
+        """
+        return self._height_and_width().ws_ypixel
+
+    @property
+    def pixel_width(self):
+        """
+        Read-only property: Width of terminal (in pixels).
+
+        :rtype: int
+        """
+        return self._height_and_width().ws_xpixel
+
     @staticmethod
     def _winsize(fd):
         """
@@ -473,10 +491,13 @@ class Terminal(object):
         directly maps to the return value of the :const:`termios.TIOCGWINSZ`
         ioctl return value. The return parameters are:
 
-            - ``ws_row``: width of terminal by its number of character cells.
-            - ``ws_col``: height of terminal by its number of character cells.
+            - ``ws_row``: height of terminal by its number of cell rows.
+            - ``ws_col``: width of terminal by its number of cell columns.
             - ``ws_xpixel``: width of terminal by pixels (not accurate).
             - ``ws_ypixel``: height of terminal by pixels (not accurate).
+
+            .. note:: the peculiar (height, width, width, height) order, which
+               matches the return order of TIOCGWINSZ!
         """
         for fd in (self._init_descriptor, sys.__stdout__):
             try:
@@ -495,14 +516,22 @@ class Terminal(object):
         """
         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::
+        :arg int x: horizontal position, from left, *0*, to right edge of screen, *self.width - 1*.
+        :arg int y: vertical position, from top, *0*, to bottom of screen, *self.height - 1*.
+        :return: a context manager.
+        :rtype: Iterator
+
+        Move the cursor to a certain position on entry, do any kind of I/O, and upon exit
+        let you print stuff there, then return the cursor to its original position:
+
+
+        .. code-block:: python
 
             term = Terminal()
-            with term.location(2, 5):
-                for x in xrange(10):
-                    print('I can do it %i times!' % x)
-            print('We're back to the original location.')
+            with term.location(y=0, x=0):
+                for row_num in range(term.height-1):
+                    print('Row #{row_num}')
+            print(term.clear_eol + 'Back to original location.')
 
         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
@@ -510,9 +539,11 @@ class Terminal(object):
         simply want to restore your place after doing some manual cursor
         movement.
 
-        .. note:: The store- and restore-cursor capabilities used internally
-            provide no stack. This means that :meth:`location` calls cannot be
-            nested: only one should be entered at a time.
+        Calls cannot be nested: only one should be entered at a time.
+
+        .. note:: The argument order *(x, y)* differs from the return value order *(y, x)*
+            of :meth:`get_location`, or argument order *(y, x)* of :meth:`move`. This is
+            for API Compaibility with the blessings library, sorry for the trouble!
         """
         # pylint: disable=invalid-name
         #         Invalid argument name "x"
@@ -537,29 +568,33 @@ class Terminal(object):
         r"""
         Return tuple (row, column) of cursor position.
 
-        :arg float timeout: Return after time elapsed in seconds with value
-            ``(-1, -1)`` indicating that the remote end did not respond.
+        :arg float timeout: Return after time elapsed in seconds with value ``(-1, -1)`` indicating
+            that the remote end did not respond.
         :rtype: tuple
-        :returns: cursor position as tuple in form of ``(x, y)``.
+        :returns: cursor position as tuple in form of ``(y, x)``.  When a timeout is specified,
+            always ensure the return value is checked for ``(-1, -1)``.
+
+        The location of the cursor is determined by emitting the ``u7`` terminal capability, or
+        VT100 `Query Cursor Position <http://www.termsys.demon.co.uk/vtansi.htm#status>`_ when such
+        capability is undefined, which elicits a response from a reply string described by
+        capability ``u6``, or again VT100's definition of ``\x1b[%i%d;%dR`` when undefined.
 
-        The location of the cursor is determined by emitting the ``u7``
-        terminal capability, or VT100 `Query Cursor Position
-        <http://www.termsys.demon.co.uk/vtansi.htm#status>`_ when such
-        capability is undefined, which elicits a response from a reply string
-        described by capability ``u6``, or again VT100's definition of
-        ``\x1b[%i%d;%dR`` when undefined.
+        The ``(y, x)`` return value matches the parameter order of the :meth:`move_xy` capability.
+        The following sequence should cause the cursor to not move at all::
+
+            >>> term = Terminal()
+            >>> term.move_yx(*term.get_location()))
 
-        The ``(row, col)`` return value matches the parameter order of the
-        ``move`` capability, so that the following sequence should cause the
-        cursor to not move at all::
+        And the following should assert True with a terminal:
 
             >>> term = Terminal()
-            >>> term.move(*term.get_location()))
+            >>> given_y, given_x = 10, 20
+            >>> with term.location(y=given_y, x=given_x):
+            ...     result_y, result_x = term.get_location()
+            ...
+            >>> assert given_x == result_x, (given_x, result_x)
+            >>> assert given_y == result_y, (given_y, result_y)
 
-        .. warning:: You might first test that a terminal is capable of
-           informing you of its location, while using a timeout, before
-           later calling.  When a timeout is specified, always ensure the
-           return value is conditionally checked for ``(-1, -1)``.
         """
         # Local lines attached by termios and remote login protocols such as
         # ssh and telnet both provide a means to determine the window
@@ -684,8 +719,8 @@ class Terminal(object):
         """
         A callable string that moves the cursor to the given ``(x, y)`` screen coordinates.
 
-        :arg int x: horizontal position.
-        :arg int y: vertical position.
+        :arg int x: horizontal position, from left, *0*, to right edge of screen, *self.width - 1*.
+        :arg int y: vertical position, from top, *0*, to bottom of screen, *self.height - 1*.
         :rtype: ParameterizingString
         :returns: Callable string that moves the cursor to the given coordinates
         """
@@ -699,8 +734,8 @@ class Terminal(object):
         """
         A callable string that moves the cursor to the given ``(y, x)`` screen coordinates.
 
-        :arg int x: horizontal position.
-        :arg int y: vertical position.
+        :arg int y: vertical position, from top, *0*, to bottom of screen, *self.height - 1*.
+        :arg int x: horizontal position, from left, *0*, to right edge of screen, *self.width - 1*.
         :rtype: ParameterizingString
         :returns: Callable string that moves the cursor to the given coordinates
         """
@@ -849,7 +884,7 @@ class Terminal(object):
 
         Optional ``url_id`` may be specified, so that non-adjacent cells can reference a single
         target, all cells painted with the same "id" will highlight on hover, rather than any
-        individual one, as described in "Hovering and underlining the id parameter of gist
+        individual one, as described in "Hovering and underlining the id parameter" of gist
         https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda.
 
         :param str url: Hyperlink URL.
diff --git a/docs/history.rst b/docs/history.rst
index e253b59..5aba060 100644
--- a/docs/history.rst
+++ b/docs/history.rst
@@ -13,6 +13,8 @@ Version History
     :meth:`~Terminal.move_right` which are strings that move the cursor one cell in the respective
     direction, are now **also** callables for moving *n* cells to the given direction, such as
     ``term.move_right(9)``.
+  * introduced: :attr:`~Terminal.pixel_width` and :attr:`~Terminal.pixel_height` for libsixel
+    support or general curiosity.
   * bugfix: prevent ``ValueError: I/O operation on closed file`` on ``sys.stdin`` in multiprocessing
     environments, where the keyboard wouldn't work, anyway.
   * bugfix: prevent error condition, ``ValueError: underlying buffer has been detached`` in rare
@@ -25,6 +27,7 @@ Version History
     :meth:`~Terminal.keypad` now flush the stream after writing their sequences.
   * bugfix: ``chr(127)``, ``\x7f`` has changed from keycode ``term.DELETE`` to the more common
     match, ``term.BACKSPACE``, :ghissue:115` by :ghuser:`jwezel`.
+  * bugfix: ensure :class:`~.FormattingOtherString` may be pickled.
   * deprecated: the curses ``move()`` capability is no longer recommended, suggest to use
     :meth:`~.Terminal.move_xy()`, which matches the return value of :meth:`~.Terminal.get_location`.
   * deprecated: ``superscript``, ``subscript``, ``shadow``, and ``dim`` are no longer "compoundable"
diff --git a/docs/location.rst b/docs/location.rst
index e532371..85e78dc 100644
--- a/docs/location.rst
+++ b/docs/location.rst
@@ -23,18 +23,21 @@ There are four direct movement capabilities:
 And four relative capabilities:
 
 ``move_up`` or ``move_up(y)``
-  Position cursor 1 or **y** cells above the current position.
-``move_down`` or ``move_down(y)``
-  Position cursor 1 or **y** cells below the current position.
+  Position cursor 1 or **y** row cells above the current position.
+``move_down(y)``
+  Position cursor 1 or **y** row cells below the current position.
+
+  .. note:: ``move_down`` or is often valued as *\\n*, which additionally returns the carriage to
+     column 0, and, depending on your terminal emulator, may also destroy any characters to end of
+     line.
+
+    ``move_down(1)`` is always a safe non-destructive one-notch movement in the downward direction.
+
 ``move_left`` or ``move_left(x)``
-  Position cursor 1 or **x** cells left of the current position.
+  Position cursor 1 or **x** column cells left of the current position.
 ``move_right`` or ``move_right(x)``
-  Position cursor 1 or **x** cells right of the current position.
+  Position cursor 1 or **x** column cells right of the current position.
 
-.. note:: ``move_down``, if printed directly, is often valued as *\\n*, which additionally returns
-    the carriage to column 0, and, depending on your terminal emulator, may also destroy any
-    characters to end of line. ``move_down(1)`` is always a safe non-destructive one-notch movement
-    in the downward direction.
 
 Example
 -------
diff --git a/version.json b/version.json
index 8d63673..c29d060 100644
--- a/version.json
+++ b/version.json
@@ -1,1 +1,1 @@
-{"version": "1.17.2"}
+{"version": "1.17.3"}


Test patch:
diff --git a/tests/test_formatters.py b/tests/test_formatters.py
index 15c0251..35ac3c8 100644
--- a/tests/test_formatters.py
+++ b/tests/test_formatters.py
@@ -99,16 +99,12 @@ def test_parameterizing_string_type_error(monkeypatch):
         pstr('XYZ')
         assert False, "previous call should have raised TypeError"
     except TypeError as err:
-        assert (err.args[0] == (  # py3x
-            "A native or nonexistent capability template, "
-            "'cap-name' received invalid argument ('XYZ',): "
-            "custom_err. You probably misspelled a "
-            "formatting call like `bright_red'") or
-            err.args[0] == (
-                "A native or nonexistent capability template, "
-                "u'cap-name' received invalid argument ('XYZ',): "
-                "custom_err. You probably misspelled a "
-                "formatting call like `bright_red'"))
+        assert err.args[0] in ((
+            "Unknown terminal capability, 'cap-name', or, TypeError "
+            "for arguments ('XYZ',): custom_err"  # py3x
+        ), (
+            "Unknown terminal capability, u'cap-name', or, TypeError "
+            "for arguments ('XYZ',): custom_err"))  # py2
 
     # ensure TypeError when given an integer raises its natural exception
     try:
@@ -153,16 +149,19 @@ def test_nested_formattingstring_type_error(monkeypatch):
 
     # given,
     pstr = FormattingString(u'a-', u'n-')
-    expected_msg = (
-        "Positional argument #1 is {0} expected any of "
-        .format(type(1)))
+    expected_msgs = ((
+        "TypeError for FormattingString argument, 291, at position 1: "
+        "expected type str, got int"  # py3x
+    ), ("TypeError for FormattingString argument, 291, at position 1: "
+        "expected type basestring, got int"
+        ))  # py2
 
     # exercise,
     with pytest.raises(TypeError) as err:
-        pstr('text', 1, '...')
+        pstr('text', 0x123, '...')
 
     # verify,
-    assert expected_msg in str(err.value)
+    assert str(err.value) in expected_msgs
 
 
 def test_nullcallablestring(monkeypatch):
@@ -370,7 +369,7 @@ def test_resolve_attribute_recursive_compoundables(monkeypatch):
     assert pstr('text') == 'seq-6808seq-6502textseq-normal'
 
 
-def test_basic_pickling():
+def test_formattingstring_picklability():
     """Test pickle-ability of a FormattingString."""
     @as_subprocess
     def child():
@@ -378,10 +377,57 @@ def test_basic_pickling():
         # basic pickle
         pickle.loads(pickle.dumps(t.red))('orange') == t.red('orange')
         pickle.loads(pickle.dumps(t.normal)) == t.normal
-        # pickle through multiprocessing
+
+        # and, pickle through multiprocessing
         r, w = multiprocessing.Pipe()
         w.send(t.normal)
         assert r.recv() == t.normal
+
+    child()
+
+
+def test_formattingotherstring_picklability():
+    """Test pickle-ability of a FormattingOtherString."""
+    @as_subprocess
+    def child():
+        from blessed.formatters import ParameterizingString
+        t = TestTerminal(force_styling=True)
+        # basic pickle
+        pickle.loads(pickle.dumps(t.move_left)) == t.move_left
+        pickle.loads(pickle.dumps(t.move_left(3))) == t.move_left(3)
+        pickle.loads(pickle.dumps(t.move_left))(3) == t.move_left(3)
+
+        # and, pickle through multiprocessing
+        r, w = multiprocessing.Pipe()
+        w.send(t.move_left)
+        assert r.recv()(3) == t.move_left(3)
+        w.send(t.move_left(3))
+        assert r.recv() == t.move_left(3)
+
+    child()
+
+
+def test_paramterizingstring_picklability():
+    """Test pickle-ability of ParameterizingString."""
+    @as_subprocess
+    def child():
+        from blessed.formatters import ParameterizingString
+        t = TestTerminal(force_styling=True)
+
+        color = ParameterizingString(t.color, t.normal, 'color')
+        pickle.loads(pickle.dumps(color)) == color
+        pickle.loads(pickle.dumps(color(3))) == color(3)
+        pickle.loads(pickle.dumps(color))(3) == color(3)
+
+        # and, pickle through multiprocessing
+        r, w = multiprocessing.Pipe()
+        w.send(color)
+        assert r.recv() == color
+        w.send(color(3))
+        assert r.recv() == color(3)
+        w.send(t.color)
+        assert r.recv()(3) == t.color(3)
+
     child()
 
 
diff --git a/tests/test_length_sequence.py b/tests/test_length_sequence.py
index 680e144..214f51e 100644
--- a/tests/test_length_sequence.py
+++ b/tests/test_length_sequence.py
@@ -324,10 +324,11 @@ def test_env_winsize():
 @pytest.mark.skipif(platform.system() == 'Windows', reason="requires fcntl")
 def test_winsize(many_lines, many_columns):
     """Test height and width is appropriately queried in a pty."""
+    pixel_width, pixel_height = 1024, 768
     @as_subprocess
     def child(lines=25, cols=80):
         # set the pty's virtual window size
-        val = struct.pack('HHHH', lines, cols, 0, 0)
+        val = struct.pack('HHHH', lines, cols, pixel_width, pixel_height)
         fcntl.ioctl(sys.__stdout__.fileno(), termios.TIOCSWINSZ, val)
         term = TestTerminal()
         winsize = term._height_and_width()
@@ -335,6 +336,8 @@ def test_winsize(many_lines, many_columns):
         assert term.height == lines
         assert winsize.ws_col == cols
         assert winsize.ws_row == lines
+        assert term.pixel_width == pixel_width
+        assert term.pixel_height == pixel_height
 
     child(lines=many_lines, cols=many_columns)
 
diff --git a/tests/test_sequences.py b/tests/test_sequences.py
index 268d767..a0d5eae 100644
--- a/tests/test_sequences.py
+++ b/tests/test_sequences.py
@@ -473,20 +473,20 @@ def test_nice_formatting_errors(all_terms):
             assert not t.is_a_tty or False, 'Should have thrown exception'
         except TypeError:
             e = sys.exc_info()[1]
-            assert 'probably misspelled' in e.args[0]
+            assert 'Unknown terminal capability,' in e.args[0]
         try:
             t.bold_misspelled(u'hey')  # unicode
             assert not t.is_a_tty or False, 'Should have thrown exception'
         except TypeError:
             e = sys.exc_info()[1]
-            assert 'probably misspelled' in e.args[0]
+            assert 'Unknown terminal capability,' in e.args[0]
 
         try:
             t.bold_misspelled(None)  # an arbitrary non-string
             assert not t.is_a_tty or False, 'Should have thrown exception'
         except TypeError:
             e = sys.exc_info()[1]
-            assert 'probably misspelled' not in e.args[0]
+            assert 'Unknown terminal capability,' not in e.args[0]
 
         if platform.python_implementation() != 'PyPy':
             # PyPy fails to toss an exception, Why?!
@@ -495,7 +495,7 @@ def test_nice_formatting_errors(all_terms):
                 assert not t.is_a_tty or False, 'Should have thrown exception'
             except TypeError:
                 e = sys.exc_info()[1]
-                assert 'probably misspelled' in e.args[0], e.args
+                assert 'Unknown terminal capability,' in e.args[0], e.args
 
     child(all_terms)