Hello community,

here is the log from the commit of package python-humanfriendly for 
openSUSE:Factory checked in at 2018-02-09 15:51:56
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-humanfriendly (Old)
 and      /work/SRC/openSUSE:Factory/.python-humanfriendly.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-humanfriendly"

Fri Feb  9 15:51:56 2018 rev:4 rq:574413 version:4.8

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-humanfriendly/python-humanfriendly.changes    
    2017-09-11 16:18:02.428731047 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-humanfriendly.new/python-humanfriendly.changes
   2018-02-09 15:52:02.221713860 +0100
@@ -1,0 +2,103 @@
+Thu Feb  8 21:59:46 UTC 2018 - adrian.glaub...@suse.com
+
+- Update to version 4.8
+  * Add coerce_pattern() function
+  * Improve code consistency
+- From version 4.7
+  * Support background colors and 256 color mode
+  * Tests for output(), message() and warning()
+- From version 4.6
+  * Support for bright terminal colors
+- From version 4.5
+  * Extend byte ranges, add RAM output to command line
+- From version 4.4.2
+  * Reduce clock source sensitivity* (MacOS on Travis CI)
+  * Fix `Double requirement given' error
+  * Try to fix Python 2.6 tests on Travis CI
+  * Change Sphinx documentation theme
+  * Bump copyright
+  * Try to enable MacOS builds on Travis CI
+  * Fix ImportError exception on Windows
+- From version 4.4.1
+  * Include docs to sdist
+  * PEP-8 fail
+  * Change cli test from 1.05 mm to 1.05 km
+  * Another correction to test_cli
+  * Corrected CLI format_length test
+  * Aim for more CLI coverage
+  * Add CLI tests for format-byte
+  * Added size test cases
+  * Size 1z is now valid
+- From version 4.4
+  * Add touch() to __all__
+  * Make touch() create intermediate directories
+  * Add humanfriendly.testing.touch() function
+- From version 4.3
+  * Don't log duplicate output in run_cli()
+- From version 4.2
+  * Reconfigure logging in run_cli()
+- From version 4.1
+  * Always log stderr as well in run_cli()
+- From version 4.0
+  * Improve humanfriendly.testing.run_cli() (backwards incompatible)
+- From version 3.8
+  * Make it easy to mock the $HOME directory
+- From version 3.7
+  * Customizable skipping of tests
+  * Added .pyc to .gitignore
+  * Added Exa, Zetta & Yotta prefixes and tests
+  * Added -S --format-bytes option to use powers of 1024 rather than 1000 from 
command line.
+- From version 3.6.1
+  * Improve robustness of Patched{Attribute,Item}
+- From version 3.6
+  * Make retry limit configurable
+  * Refactor makefile and Travis CI configuration
+- From version 3.5
+  * Bug fix for TestCase.assertRaises()
+  * Enhance TestCase.assertRaises()
+- From version 3.4.1
+  * Bug fix for Python 3 syntax incompatibility
+- From version 3.4
+  * Promote command line test function to public API
+- From version 3.3
+  * Add humanfriendly.testing module (unittest helpers)
+  * Add humanfriendly.text.random_string() function
+  * Define humanfriendly.text.__all__
+  * Reorder functions in humanfriendly.text alphabetically
+- From version 3.2
+  * Auto-encode terminal output to avoid encoding errors
+  * Remove unused import
+- From version 3.1
+  * Improve usage message parsing and rendering
+- From version 3.0
+  * Add Python 3.6 to tested versions
+  * Silence flake8 complaints
+  * Add min, mins tests
+  * Support min, mins abbreviations for minutes
+- From version 2.4
+  * Restore Python 3 compatibility
+  * Make usage() and show_pager() more user friendly
+  * Remove redundant :py: prefixes in docstrings
+  * Improve docstrings in setup.py
+- From version 2.3.2
+  * Bug fix: Don't hard code conditional dependencies in wheels
+- From version 2.3.1
+  * Fix parse_usage() tripping up on commas in option labels
+  * Break test suite to reproduce parse_usage() bug
+- From version 2.3
+  * Switch to monotonic clock for timers
+  * Bump copyright
+  * Minor improvements to setup script
+  * Improve intersphinx references
+  * s/readthedocs.org/readthedocs.io/g
+- From version 2.2.1
+  * Fix timers being awkward as context managers
+  * Reproduce timers being awkward as context managers
+  * Minor improvements to reStructuredText in docstrings
+- From version 2.2
+  * Fix parse_date() choking on Unicode strings
+  * Reproduce parse_date() bug in test suite
+  * Fix flake8 warning
+  * Only use readline hints in prompts when stdin is tty
+
+-------------------------------------------------------------------

Old:
----
  humanfriendly-4.4.1.tar.gz

New:
----
  humanfriendly-4.8.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-humanfriendly.spec ++++++
--- /var/tmp/diff_new_pack.WvfYGp/_old  2018-02-09 15:52:03.501667888 +0100
+++ /var/tmp/diff_new_pack.WvfYGp/_new  2018-02-09 15:52:03.505667744 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-humanfriendly
 #
-# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -20,18 +20,18 @@
 # Dependency loop with colorlogs
 %bcond_with     test
 Name:           python-humanfriendly
-Version:        4.4.1
+Version:        4.8
 Release:        0
 Summary:        Human friendly input/output for text interfaces using Python
 License:        MIT
 Group:          Development/Languages/Python
 Url:            https://github.com/xolox/humanfriendly
 Source:         
https://files.pythonhosted.org/packages/source/h/humanfriendly/humanfriendly-%{version}.tar.gz
-BuildRequires:  fdupes
-BuildRequires:  python-rpm-macros
 BuildRequires:  %{python_module devel}
 BuildRequires:  %{python_module setuptools}
+BuildRequires:  fdupes
 BuildRequires:  python-monotonic
+BuildRequires:  python-rpm-macros
 %if %{with test}
 BuildRequires:  %{python_module coloredlogs >= 2}
 %endif

++++++ humanfriendly-4.4.1.tar.gz -> humanfriendly-4.8.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/humanfriendly-4.4.1/LICENSE.txt 
new/humanfriendly-4.8/LICENSE.txt
--- old/humanfriendly-4.4.1/LICENSE.txt 2017-03-01 02:42:51.000000000 +0100
+++ new/humanfriendly-4.8/LICENSE.txt   2018-01-04 13:06:45.000000000 +0100
@@ -1,4 +1,4 @@
-Copyright (c) 2017 Peter Odding
+Copyright (c) 2018 Peter Odding
 
 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/humanfriendly-4.4.1/PKG-INFO 
new/humanfriendly-4.8/PKG-INFO
--- old/humanfriendly-4.4.1/PKG-INFO    2017-08-07 22:59:43.000000000 +0200
+++ new/humanfriendly-4.8/PKG-INFO      2018-01-20 21:19:22.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: humanfriendly
-Version: 4.4.1
+Version: 4.8
 Summary: Human friendly output for text interfaces using Python
 Home-page: https://humanfriendly.readthedocs.io
 Author: Peter Odding
@@ -32,7 +32,8 @@
           size.
         
         The `humanfriendly` package is currently tested on Python 2.6, 2.7, 
3.4, 3.5,
-        3.6 and PyPy (2.7).
+        3.6 and PyPy (2.7) on Linux and Mac OS X. While the intention is to 
support
+        Windows as well, you may encounter some rough edges.
         
         .. contents::
            :local:
@@ -91,12 +92,16 @@
            formatted number to standard output."
            "``-s``, ``--format-size=BYTES``","Convert a byte count (given as 
the integer ``BYTES``) into a human readable
            string and print that string to standard output."
+           "``-b``, ``--binary``","Change the output of ``-s``, 
``--format-size`` to use binary multiples of bytes
+           (base-2) instead of the default decimal multiples of bytes 
(base-10)."
            "``-t``, ``--format-timespan=SECONDS``","Convert a number of 
seconds (given as the floating point number ``SECONDS``)
            into a human readable timespan and print that string to standard 
output."
-           ``--parse-size=VALUE``,"Parse a human readable data size (given as 
the string ``VALUE``) and print the
-           number of bytes to standard output."
            ``--parse-length=VALUE``,"Parse a human readable length (given as 
the string ``VALUE``) and print the
            number of metres to standard output."
+           ``--parse-size=VALUE``,"Parse a human readable data size (given as 
the string ``VALUE``) and print the
+           number of bytes to standard output."
+           ``--demo``,"Demonstrate changing the style and color of the 
terminal font using ANSI
+           escape sequences."
            "``-h``, ``--help``",Show this message and exit.
         
         .. [[[end]]]
@@ -139,7 +144,7 @@
         
         This software is licensed under the `MIT license`_.
         
-        © 2017 Peter Odding.
+        © 2018 Peter Odding.
         
         .. External references:
         .. _#4: https://github.com/xolox/python-humanfriendly/issues/4
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/humanfriendly-4.4.1/README.rst 
new/humanfriendly-4.8/README.rst
--- old/humanfriendly-4.4.1/README.rst  2017-06-29 00:08:23.000000000 +0200
+++ new/humanfriendly-4.8/README.rst    2018-01-04 21:39:27.000000000 +0100
@@ -24,7 +24,8 @@
   size.
 
 The `humanfriendly` package is currently tested on Python 2.6, 2.7, 3.4, 3.5,
-3.6 and PyPy (2.7).
+3.6 and PyPy (2.7) on Linux and Mac OS X. While the intention is to support
+Windows as well, you may encounter some rough edges.
 
 .. contents::
    :local:
@@ -83,12 +84,16 @@
    formatted number to standard output."
    "``-s``, ``--format-size=BYTES``","Convert a byte count (given as the 
integer ``BYTES``) into a human readable
    string and print that string to standard output."
+   "``-b``, ``--binary``","Change the output of ``-s``, ``--format-size`` to 
use binary multiples of bytes
+   (base-2) instead of the default decimal multiples of bytes (base-10)."
    "``-t``, ``--format-timespan=SECONDS``","Convert a number of seconds (given 
as the floating point number ``SECONDS``)
    into a human readable timespan and print that string to standard output."
-   ``--parse-size=VALUE``,"Parse a human readable data size (given as the 
string ``VALUE``) and print the
-   number of bytes to standard output."
    ``--parse-length=VALUE``,"Parse a human readable length (given as the 
string ``VALUE``) and print the
    number of metres to standard output."
+   ``--parse-size=VALUE``,"Parse a human readable data size (given as the 
string ``VALUE``) and print the
+   number of bytes to standard output."
+   ``--demo``,"Demonstrate changing the style and color of the terminal font 
using ANSI
+   escape sequences."
    "``-h``, ``--help``",Show this message and exit.
 
 .. [[[end]]]
@@ -131,7 +136,7 @@
 
 This software is licensed under the `MIT license`_.
 
-© 2017 Peter Odding.
+© 2018 Peter Odding.
 
 .. External references:
 .. _#4: https://github.com/xolox/python-humanfriendly/issues/4
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/humanfriendly-4.4.1/docs/conf.py 
new/humanfriendly-4.8/docs/conf.py
--- old/humanfriendly-4.4.1/docs/conf.py        2017-06-29 00:08:23.000000000 
+0200
+++ new/humanfriendly-4.8/docs/conf.py  2018-01-04 13:06:45.000000000 +0100
@@ -32,7 +32,7 @@
 
 # General information about the project.
 project = u'humanfriendly'
-copyright = u'2017, Peter Odding'
+copyright = u'2018, Peter Odding'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
@@ -73,7 +73,4 @@
 
 # The theme to use for HTML and HTML Help pages.  See the documentation for
 # a list of builtin themes.
-html_theme = 'default'
-
-# Output file base name for HTML help builder.
-htmlhelp_basename = 'humanfriendlydoc'
+html_theme = 'nature'
Binary files old/humanfriendly-4.4.1/docs/images/ansi-demo.png and 
new/humanfriendly-4.8/docs/images/ansi-demo.png differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/humanfriendly-4.4.1/humanfriendly/__init__.py 
new/humanfriendly-4.8/humanfriendly/__init__.py
--- old/humanfriendly-4.4.1/humanfriendly/__init__.py   2017-08-07 
22:59:18.000000000 +0200
+++ new/humanfriendly-4.8/humanfriendly/__init__.py     2018-01-20 
21:19:02.000000000 +0100
@@ -1,7 +1,7 @@
 # Human friendly input/output in Python.
 #
 # Author: Peter Odding <pe...@peterodding.com>
-# Last Change: August 7, 2017
+# Last Change: January 20, 2018
 # URL: https://humanfriendly.readthedocs.io
 
 """The main module of the `humanfriendly` package."""
@@ -39,7 +39,7 @@
 from humanfriendly.compat import is_string, monotonic
 
 # Semi-standard module versioning.
-__version__ = '4.4.1'
+__version__ = '4.8'
 
 # Spinners are redrawn at most this many seconds.
 minimum_spinner_interval = 0.2
@@ -52,6 +52,7 @@
 hide_cursor_code = '\x1b[?25l'
 show_cursor_code = '\x1b[?25h'
 
+# Named tuples to define units of size.
 SizeUnit = collections.namedtuple('SizeUnit', 'divider, symbol, name')
 CombinedUnit = collections.namedtuple('CombinedUnit', 'decimal, binary')
 
@@ -62,6 +63,9 @@
     CombinedUnit(SizeUnit(1000**3, 'GB', 'gigabyte'), SizeUnit(1024**3, 'GiB', 
'gibibyte')),
     CombinedUnit(SizeUnit(1000**4, 'TB', 'terabyte'), SizeUnit(1024**4, 'TiB', 
'tebibyte')),
     CombinedUnit(SizeUnit(1000**5, 'PB', 'petabyte'), SizeUnit(1024**5, 'PiB', 
'pebibyte')),
+    CombinedUnit(SizeUnit(1000**6, 'EB', 'exabyte'), SizeUnit(1024**6, 'EiB', 
'exbibyte')),
+    CombinedUnit(SizeUnit(1000**7, 'ZB', 'zettabyte'), SizeUnit(1024**7, 
'ZiB', 'zebibyte')),
+    CombinedUnit(SizeUnit(1000**8, 'YB', 'yottabyte'), SizeUnit(1024**8, 
'YiB', 'yobibyte')),
 )
 
 # Common length size units, used for formatting and parsing.
@@ -104,11 +108,33 @@
             return False
         else:
             msg = "Failed to coerce string to boolean! (%r)"
-            raise ValueError(msg % value)
+            raise ValueError(format(msg, value))
     else:
         return bool(value)
 
 
+def coerce_pattern(value, flags=0):
+    """
+    Coerce strings to compiled regular expressions.
+
+    :param value: A string containing a regular expression pattern
+                  or a compiled regular expression.
+    :param flags: The flags used to compile the pattern (an integer).
+    :returns: A compiled regular expression.
+    :raises: :exc:`~exceptions.ValueError` when `value` isn't a string
+             and also isn't a compiled regular expression.
+    """
+    if is_string(value):
+        value = re.compile(value, flags)
+    else:
+        empty_pattern = re.compile('')
+        pattern_type = type(empty_pattern)
+        if not isinstance(value, pattern_type):
+            msg = "Failed to coerce value to compiled regular expression! (%r)"
+            raise ValueError(format(msg, value))
+    return value
+
+
 def format_size(num_bytes, keep_width=False, binary=False):
     """
     Format a byte count as a human readable file size.
@@ -205,7 +231,7 @@
                     return int(tokens[0] * (unit.binary.divider if binary else 
unit.decimal.divider))
     # We failed to parse the size specification.
     msg = "Failed to parse size! (input %r was tokenized as %r)"
-    raise InvalidSize(msg % (size, tokens))
+    raise InvalidSize(format(msg, size, tokens))
 
 
 def format_length(num_metres, keep_width=False):
@@ -274,7 +300,7 @@
                     return tokens[0] * unit['divider']
     # We failed to parse the length specification.
     msg = "Failed to parse length! (input %r was tokenized as %r)"
-    raise InvalidLength(msg % (length, tokens))
+    raise InvalidLength(format(msg, length, tokens))
 
 
 def format_number(number, num_decimals=2):
@@ -461,7 +487,7 @@
                     return float(tokens[0]) * unit['divider']
     # We failed to parse the timespan specification.
     msg = "Failed to parse timespan! (input %r was tokenized as %r)"
-    raise InvalidTimespan(msg % (timespan, tokens))
+    raise InvalidTimespan(format(msg, timespan, tokens))
 
 
 def parse_date(datestring):
@@ -532,7 +558,7 @@
             return (year, month, day, 0, 0, 0)
     except Exception:
         msg = "Invalid date! (expected 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' 
but got: %r)"
-        raise InvalidDate(msg % datestring)
+        raise InvalidDate(format(msg, datestring))
 
 
 def format_path(pathname):
@@ -933,7 +959,7 @@
     >>> parse_date('2013-06-XY')
     Traceback (most recent call last):
       File "humanfriendly.py", line 206, in parse_date
-        raise InvalidDate, msg % datestring
+        raise InvalidDate(format(msg, datestring))
     humanfriendly.InvalidDate: Invalid date! (expected 'YYYY-MM-DD' or 
'YYYY-MM-DD HH:MM:SS' but got: '2013-06-XY')
     """
 
@@ -949,7 +975,7 @@
     >>> parse_size('5 Z')
     Traceback (most recent call last):
       File "humanfriendly/__init__.py", line 267, in parse_size
-        raise InvalidSize(msg % (size, tokens))
+        raise InvalidSize(format(msg, size, tokens))
     humanfriendly.InvalidSize: Failed to parse size! (input '5 Z' was 
tokenized as [5, 'Z'])
     """
 
@@ -965,7 +991,7 @@
     >>> parse_length('5 Z')
     Traceback (most recent call last):
       File "humanfriendly/__init__.py", line 267, in parse_length
-        raise InvalidLength(msg % (length, tokens))
+        raise InvalidLength(format(msg, length, tokens))
     humanfriendly.InvalidLength: Failed to parse length! (input '5 Z' was 
tokenized as [5, 'Z'])
     """
 
@@ -981,6 +1007,6 @@
     >>> parse_timespan('1 age')
     Traceback (most recent call last):
       File "humanfriendly/__init__.py", line 419, in parse_timespan
-        raise InvalidTimespan(msg % (timespan, tokens))
+        raise InvalidTimespan(format(msg, timespan, tokens))
     humanfriendly.InvalidTimespan: Failed to parse timespan! (input '1 age' 
was tokenized as [1, 'age'])
     """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/humanfriendly-4.4.1/humanfriendly/cli.py 
new/humanfriendly-4.8/humanfriendly/cli.py
--- old/humanfriendly-4.4.1/humanfriendly/cli.py        2017-06-29 
00:08:23.000000000 +0200
+++ new/humanfriendly-4.8/humanfriendly/cli.py  2018-01-14 03:27:50.000000000 
+0100
@@ -1,7 +1,7 @@
 # Human friendly input/output in Python.
 #
 # Author: Peter Odding <pe...@peterodding.com>
-# Last Change: May 18, 2017
+# Last Change: January 14, 2018
 # URL: https://humanfriendly.readthedocs.io
 
 """
@@ -46,20 +46,30 @@
     Convert a byte count (given as the integer BYTES) into a human readable
     string and print that string to standard output.
 
+  -b, --binary
+
+    Change the output of -s, --format-size to use binary multiples of bytes
+    (base-2) instead of the default decimal multiples of bytes (base-10).
+
   -t, --format-timespan=SECONDS
 
     Convert a number of seconds (given as the floating point number SECONDS)
     into a human readable timespan and print that string to standard output.
 
+  --parse-length=VALUE
+
+    Parse a human readable length (given as the string VALUE) and print the
+    number of metres to standard output.
+
   --parse-size=VALUE
 
     Parse a human readable data size (given as the string VALUE) and print the
     number of bytes to standard output.
 
-  --parse-length=VALUE
+  --demo
 
-    Parse a human readable length (given as the string VALUE) and print the
-    number of metres to standard output.
+    Demonstrate changing the style and color of the terminal font using ANSI
+    escape sequences.
 
   -h, --help
 
@@ -75,6 +85,8 @@
 
 # Modules included in our package.
 from humanfriendly import (
+    Spinner,
+    Timer,
     format_length,
     format_number,
     format_size,
@@ -82,19 +94,28 @@
     format_timespan,
     parse_length,
     parse_size,
-    Spinner,
-    Timer,
 )
-from humanfriendly.terminal import output, usage, warning
+from humanfriendly.tables import format_smart_table
+from humanfriendly.terminal import (
+    ANSI_COLOR_CODES,
+    ANSI_TEXT_STYLES,
+    HIGHLIGHT_COLOR,
+    ansi_strip,
+    ansi_wrap,
+    find_terminal_size,
+    output,
+    usage,
+    warning,
+)
 
 
 def main():
     """Command line interface for the ``humanfriendly`` program."""
     try:
-        options, arguments = getopt.getopt(sys.argv[1:], 'cd:hn:s:t:', [
-            'delimiter=', 'format-length=', 'format-number=', 'format-size=',
-            'format-table', 'format-timespan=', 'parse-length=',
-            'parse-size=', 'run-command', 'help',
+        options, arguments = getopt.getopt(sys.argv[1:], 'cd:l:n:s:bt:h', [
+            'run-command', 'format-table', 'delimiter=', 'format-length=',
+            'format-number=', 'format-size=', 'binary', 'format-timespan=',
+            'parse-length=', 'parse-size=', 'demo', 'help',
         ])
     except Exception as e:
         warning("Error: %s", e)
@@ -102,6 +123,7 @@
     actions = []
     delimiter = None
     should_format_table = False
+    binary = any(o in ('-b', '--binary') for o, v in options)
     for option, value in options:
         if option in ('-d', '--delimiter'):
             delimiter = value
@@ -116,11 +138,13 @@
         elif option in ('-n', '--format-number'):
             actions.append(functools.partial(print_formatted_number, value))
         elif option in ('-s', '--format-size'):
-            actions.append(functools.partial(print_formatted_size, value))
+            actions.append(functools.partial(print_formatted_size, value, 
binary))
         elif option == '--format-table':
             should_format_table = True
         elif option in ('-t', '--format-timespan'):
             actions.append(functools.partial(print_formatted_timespan, value))
+        elif option == '--demo':
+            actions.append(demonstrate_ansi_formatting)
         elif option in ('-h', '--help'):
             usage(__doc__)
             return
@@ -160,9 +184,9 @@
     output(format_number(float(value)))
 
 
-def print_formatted_size(value):
+def print_formatted_size(value, binary):
     """Print a human readable size."""
-    output(format_size(int(value)))
+    output(format_size(int(value), binary=binary))
 
 
 def print_formatted_table(delimiter):
@@ -187,3 +211,65 @@
 def print_parsed_size(value):
     """Parse a human readable data size and print the number of bytes."""
     output(parse_size(value))
+
+
+def demonstrate_ansi_formatting():
+    """Demonstrate the use of ANSI escape sequences."""
+    # First we demonstrate the supported text styles.
+    output('%s', ansi_wrap('Text styles:', bold=True))
+    styles = ['normal', 'bright']
+    styles.extend(ANSI_TEXT_STYLES.keys())
+    for style_name in sorted(styles):
+        options = dict(color=HIGHLIGHT_COLOR)
+        if style_name != 'normal':
+            options[style_name] = True
+        style_label = style_name.replace('_', ' ').capitalize()
+        output(' - %s', ansi_wrap(style_label, **options))
+    # Now we demonstrate named foreground and background colors.
+    for color_type, color_label in (('color', 'Foreground colors'),
+                                    ('background', 'Background colors')):
+        intensities = [
+            ('normal', dict()),
+            ('bright', dict(bright=True)),
+        ]
+        if color_type != 'background':
+            intensities.insert(0, ('faint', dict(faint=True)))
+        output('\n%s' % ansi_wrap('%s:' % color_label, bold=True))
+        output(format_smart_table([
+            [color_name] + [
+                ansi_wrap(
+                    'XXXXXX' if color_type != 'background' else (' ' * 6),
+                    **dict(kw.items() + [(color_type, color_name)])
+                ) for label, kw in intensities
+            ] for color_name in sorted(ANSI_COLOR_CODES.keys())
+        ], column_names=['Color'] + [
+            label.capitalize() for label, kw in intensities
+        ]))
+    # Demonstrate support for 256 colors as well.
+    demonstrate_256_colors(0, 7, 'standard colors')
+    demonstrate_256_colors(8, 15, 'high-intensity colors')
+    demonstrate_256_colors(16, 231, '216 colors')
+    demonstrate_256_colors(232, 255, 'gray scale colors')
+
+
+def demonstrate_256_colors(i, j, group=None):
+    """Demonstrate 256 color mode support."""
+    # Generate the label.
+    label = '256 color mode'
+    if group:
+        label += ' (%s)' % group
+    output('\n' + ansi_wrap('%s:' % label, bold=True))
+    # Generate a simple rendering of the colors in the requested range and
+    # check if it will fit on a single line (given the terminal's width).
+    single_line = ''.join(' ' + ansi_wrap(str(n), color=n) for n in range(i, j 
+ 1))
+    lines, columns = find_terminal_size()
+    if columns >= len(ansi_strip(single_line)):
+        output(single_line)
+    else:
+        # Generate a more complex rendering of the colors that will nicely wrap
+        # over multiple lines without using too many lines.
+        width = len(str(j)) + 1
+        colors_per_line = columns / width
+        colors = [ansi_wrap(str(n).rjust(width), color=n) for n in range(i, j 
+ 1)]
+        blocks = [colors[n:n + colors_per_line] for n in range(0, len(colors), 
colors_per_line)]
+        output('\n'.join(''.join(b) for b in blocks))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/humanfriendly-4.4.1/humanfriendly/terminal.py 
new/humanfriendly-4.8/humanfriendly/terminal.py
--- old/humanfriendly-4.4.1/humanfriendly/terminal.py   2017-06-29 
00:08:23.000000000 +0200
+++ new/humanfriendly-4.8/humanfriendly/terminal.py     2018-01-14 
03:27:50.000000000 +0100
@@ -1,7 +1,7 @@
 # Human friendly input/output in Python.
 #
 # Author: Peter Odding <pe...@peterodding.com>
-# Last Change: May 18, 2017
+# Last Change: January 14, 2018
 # URL: https://humanfriendly.readthedocs.io
 
 """
@@ -18,6 +18,7 @@
 
 # Standard library modules.
 import codecs
+import numbers
 import os
 import re
 import subprocess
@@ -190,10 +191,18 @@
     """
     Generate ANSI escape sequences for the given color and/or style(s).
 
-    :param color: The name of a color (one of the strings 'black', 'red',
-                  'green', 'yellow', 'blue', 'magenta', 'cyan' or 'white') or
-                  :data:`None` (the default) which means no escape sequence to
-                  switch color will be emitted.
+    :param color: The foreground color. Two types of values are supported:
+
+                  - The name of a color (one of the strings 'black', 'red',
+                    'green', 'yellow', 'blue', 'magenta', 'cyan' or 'white').
+                  - An integer that refers to the 256 color mode palette.
+
+                  The value :data:`None` (the default) means no escape
+                  sequence to switch color will be emitted.
+    :param background: The background color (see the description
+                       of the `color` argument).
+    :param bright: Use high intensity colors instead of default colors
+                   (a boolean, defaults to :data:`False`).
     :param readline_hints: If :data:`True` then :func:`readline_wrap()` is
                            applied to the generated ANSI escape sequences (the
                            default is :data:`False`).
@@ -204,19 +213,51 @@
     :returns: The ANSI escape sequences to enable the requested text styles or
               an empty string if no styles were requested.
     :raises: :exc:`~exceptions.ValueError` when an invalid color name is given.
+
+    Even though only eight named colors are supported, the use of `bright=True`
+    and `faint=True` increases the number of available colors to around 24 (it
+    may be slightly lower, for example because faint black is just black).
+
+    Starting in version 4.7 support for 256 color mode was added. While this
+    significantly increases the available colors it's not very human friendly
+    in usage because you need to look up color codes in the `256 color mode
+    palette <https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit>`_.
+
+    You can use the ``humanfriendly --demo`` command to get a demonstration of
+    the available colors, see also the screen shot below. Note that the small
+    font size in the screen shot was so that the demonstration of 256 color
+    mode support would fit into a single screen shot without scrolling :-)
+    (I wasn't feeling very creative).
+
+    .. image:: images/ansi-demo.png
     """
     # Start with sequences that change text styles.
-    sequences = [str(ANSI_TEXT_STYLES[k]) for k, v in kw.items() if k in 
ANSI_TEXT_STYLES and v]
+    sequences = [ANSI_TEXT_STYLES[k] for k, v in kw.items() if k in 
ANSI_TEXT_STYLES and v]
     # Append the color code (if any).
-    color_name = kw.get('color')
-    if color_name:
-        # Validate the color name.
-        if color_name not in ANSI_COLOR_CODES:
-            msg = "Invalid color name %r! (expected one of %s)"
-            raise ValueError(msg % (color_name, 
concatenate(sorted(ANSI_COLOR_CODES))))
-        sequences.append('3%i' % ANSI_COLOR_CODES[color_name])
+    for color_type in 'color', 'background':
+        color_value = kw.get(color_type)
+        if isinstance(color_value, numbers.Number):
+            # Numeric values are assumed to be 256 color codes.
+            sequences.extend((
+                39 if color_type == 'background' else 38,
+                5, int(color_value)
+            ))
+        elif color_value:
+            # Other values are assumed to be strings containing one of the 
known color names.
+            if color_value not in ANSI_COLOR_CODES:
+                msg = "Invalid color value %r! (expected an integer or one of 
the strings %s)"
+                raise ValueError(msg % (color_value, concatenate(map(repr, 
sorted(ANSI_COLOR_CODES)))))
+            # Pick the right offset for foreground versus background
+            # colors and regular intensity versus bright colors.
+            offset = (
+                (100 if kw.get('bright') else 40)
+                if color_type == 'background'
+                else (90 if kw.get('bright') else 30)
+            )
+            # Combine the offset and color code into a single integer.
+            sequences.append(offset + ANSI_COLOR_CODES[color_value])
     if sequences:
-        encoded = ANSI_CSI + ';'.join(sequences) + ANSI_SGR
+        encoded = ANSI_CSI + ';'.join(map(str, sequences)) + ANSI_SGR
         return readline_wrap(encoded) if kw.get('readline_hints') else encoded
     else:
         return ''
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/humanfriendly-4.4.1/humanfriendly/tests.py 
new/humanfriendly-4.8/humanfriendly/tests.py
--- old/humanfriendly-4.4.1/humanfriendly/tests.py      2017-08-07 
22:55:14.000000000 +0200
+++ new/humanfriendly-4.8/humanfriendly/tests.py        2018-01-20 
21:19:02.000000000 +0100
@@ -4,7 +4,7 @@
 # Tests for the `humanfriendly' package.
 #
 # Author: Peter Odding <peter.odd...@paylogic.eu>
-# Last Change: July 16, 2017
+# Last Change: January 20, 2018
 # URL: https://humanfriendly.readthedocs.io
 
 """Test suite for the `humanfriendly` package."""
@@ -12,6 +12,7 @@
 # Standard library modules.
 import math
 import os
+import re
 import random
 import subprocess
 import sys
@@ -21,7 +22,7 @@
 # Modules included in our package.
 import humanfriendly
 from humanfriendly import prompts
-from humanfriendly import compact, dedent, trim_empty_lines
+from humanfriendly import coerce_pattern, compact, dedent, trim_empty_lines
 from humanfriendly.cli import main
 from humanfriendly.compat import StringIO
 from humanfriendly.prompts import (
@@ -52,8 +53,11 @@
     connected_to_terminal,
     find_terminal_size,
     get_pager_command,
+    message,
+    output,
     show_pager,
     terminal_supports_colors,
+    warning,
 )
 from humanfriendly.testing import (
     CallableTimedOut,
@@ -234,6 +238,19 @@
             self.assertEqual(False, humanfriendly.coerce_boolean(value))
         self.assertRaises(ValueError, humanfriendly.coerce_boolean, 'not a 
boolean')
 
+    def test_pattern_coercion(self):
+        """Test :func:`humanfriendly.coerce_pattern()`."""
+        empty_pattern = re.compile('')
+        # Make sure strings are converted to compiled regular expressions.
+        assert isinstance(coerce_pattern('foobar'), type(empty_pattern))
+        # Make sure compiled regular expressions pass through untouched.
+        assert empty_pattern is coerce_pattern(empty_pattern)
+        # Make sure flags are respected.
+        pattern = coerce_pattern('foobar', re.IGNORECASE)
+        assert pattern.match('FOOBAR')
+        # Make sure invalid values raise the expected exception.
+        self.assertRaises(ValueError, coerce_pattern, [])
+
     def test_format_timespan(self):
         """Test :func:`humanfriendly.format_timespan()`."""
         minute = 60
@@ -313,11 +330,17 @@
         self.assertEqual('1 GB', humanfriendly.format_size(1000 ** 3))
         self.assertEqual('1 TB', humanfriendly.format_size(1000 ** 4))
         self.assertEqual('1 PB', humanfriendly.format_size(1000 ** 5))
+        self.assertEqual('1 EB', humanfriendly.format_size(1000 ** 6))
+        self.assertEqual('1 ZB', humanfriendly.format_size(1000 ** 7))
+        self.assertEqual('1 YB', humanfriendly.format_size(1000 ** 8))
         self.assertEqual('1 KiB', humanfriendly.format_size(1024 ** 1, 
binary=True))
         self.assertEqual('1 MiB', humanfriendly.format_size(1024 ** 2, 
binary=True))
         self.assertEqual('1 GiB', humanfriendly.format_size(1024 ** 3, 
binary=True))
         self.assertEqual('1 TiB', humanfriendly.format_size(1024 ** 4, 
binary=True))
         self.assertEqual('1 PiB', humanfriendly.format_size(1024 ** 5, 
binary=True))
+        self.assertEqual('1 EiB', humanfriendly.format_size(1024 ** 6, 
binary=True))
+        self.assertEqual('1 ZiB', humanfriendly.format_size(1024 ** 7, 
binary=True))
+        self.assertEqual('1 YiB', humanfriendly.format_size(1024 ** 8, 
binary=True))
         self.assertEqual('45 KB', humanfriendly.format_size(1000 * 45))
         self.assertEqual('2.9 TB', humanfriendly.format_size(1000 ** 4 * 2.9))
 
@@ -333,8 +356,14 @@
         self.assertEqual(1024, humanfriendly.parse_size('1 kilobyte', 
binary=True))
         self.assertEqual(1000 ** 2 * 69, humanfriendly.parse_size('69 MB'))
         self.assertEqual(1000 ** 3, humanfriendly.parse_size('1 GB'))
+        self.assertEqual(1000 ** 4, humanfriendly.parse_size('1 TB'))
+        self.assertEqual(1000 ** 5, humanfriendly.parse_size('1 PB'))
+        self.assertEqual(1000 ** 6, humanfriendly.parse_size('1 EB'))
+        self.assertEqual(1000 ** 7, humanfriendly.parse_size('1 ZB'))
+        self.assertEqual(1000 ** 8, humanfriendly.parse_size('1 YB'))
         self.assertEqual(1000 ** 3 * 1.5, humanfriendly.parse_size('1.5 GB'))
-        self.assertRaises(humanfriendly.InvalidSize, humanfriendly.parse_size, 
'1z')
+        self.assertEqual(1024 ** 8 * 1.5, humanfriendly.parse_size('1.5 YiB'))
+        self.assertRaises(humanfriendly.InvalidSize, humanfriendly.parse_size, 
'1q')
         self.assertRaises(humanfriendly.InvalidSize, humanfriendly.parse_size, 
'a')
 
     def test_format_length(self):
@@ -527,19 +556,17 @@
         # Test automatic timer.
         automatic_timer = humanfriendly.Timer()
         time.sleep(1)
-        self.assertEqual(normalize_timestamp(humanfriendly.round_number(
-            automatic_timer.elapsed_time,
-            keep_width=True,
-        )), '1.00')
+        # XXX The following normalize_timestamp(ndigits=0) calls are intended
+        #     to compensate for unreliable clock sources in virtual machines
+        #     like those encountered on Travis CI, see also:
+        #     https://travis-ci.org/xolox/python-humanfriendly/jobs/323944263
+        self.assertEqual(normalize_timestamp(automatic_timer.elapsed_time, 0), 
'1.00')
         # Test resumable timer.
         resumable_timer = humanfriendly.Timer(resumable=True)
         for i in range(2):
             with resumable_timer:
                 time.sleep(1)
-        self.assertEqual(normalize_timestamp(humanfriendly.round_number(
-            resumable_timer.elapsed_time,
-            keep_width=True,
-        )), '2.00')
+        self.assertEqual(normalize_timestamp(resumable_timer.elapsed_time, 0), 
'2.00')
         # Make sure Timer.__enter__() returns the timer object.
         with humanfriendly.Timer(resumable=True) as timer:
             assert timer is not None
@@ -672,6 +699,17 @@
         random_byte_count = random.randint(1024, 1024 * 1024)
         returncode, output = run_cli(main, '--format-size=%i' % 
random_byte_count)
         assert output.strip() == humanfriendly.format_size(random_byte_count)
+        # Test `humanfriendly --format-size --binary'.
+        random_byte_count = random.randint(1024, 1024 * 1024)
+        returncode, output = run_cli(main, '--format-size=%i' % 
random_byte_count, '--binary')
+        assert output.strip() == humanfriendly.format_size(random_byte_count, 
binary=True)
+        # Test `humanfriendly --format-length'.
+        random_len = random.randint(1024, 1024 * 1024)
+        returncode, output = run_cli(main, '--format-length=%i' % random_len)
+        assert output.strip() == humanfriendly.format_length(random_len)
+        random_len = float(random_len) / 12345.6
+        returncode, output = run_cli(main, '--format-length=%f' % random_len)
+        assert output.strip() == humanfriendly.format_length(random_len)
         # Test `humanfriendly --format-table'.
         returncode, output = run_cli(main, '--format-table', '--delimiter=\t', 
input='1\t2\t3\n4\t5\t6\n7\t8\t9')
         assert output.strip() == dedent('''
@@ -688,6 +726,14 @@
         # Test `humanfriendly --parse-size'.
         returncode, output = run_cli(main, '--parse-size=5 KB')
         assert int(output) == humanfriendly.parse_size('5 KB')
+        # Test `humanfriendly --parse-size'.
+        returncode, output = run_cli(main, '--parse-size=5 YiB')
+        assert int(output) == humanfriendly.parse_size('5 YB', binary=True)
+        # Test `humanfriendly --parse-length'.
+        returncode, output = run_cli(main, '--parse-length=5 km')
+        assert int(output) == humanfriendly.parse_length('5 km')
+        returncode, output = run_cli(main, '--parse-length=1.05 km')
+        assert float(output) == humanfriendly.parse_length('1.05 km')
         # Test `humanfriendly --run-command'.
         returncode, output = run_cli(main, '--run-command', 'bash', '-c', 
'sleep 2 && exit 42')
         assert returncode == 42
@@ -700,6 +746,10 @@
         assert ansi_style(inverse=True) == '%s7%s' % (ANSI_CSI, ANSI_SGR)
         assert ansi_style(strike_through=True) == '%s9%s' % (ANSI_CSI, 
ANSI_SGR)
         assert ansi_style(color='blue') == '%s34%s' % (ANSI_CSI, ANSI_SGR)
+        assert ansi_style(background='blue') == '%s44%s' % (ANSI_CSI, ANSI_SGR)
+        assert ansi_style(color='blue', bright=True) == '%s94%s' % (ANSI_CSI, 
ANSI_SGR)
+        assert ansi_style(color=214) == '%s38;5;214%s' % (ANSI_CSI, ANSI_SGR)
+        assert ansi_style(background=214) == '%s39;5;214%s' % (ANSI_CSI, 
ANSI_SGR)
         self.assertRaises(ValueError, ansi_style, color='unknown')
 
     def test_ansi_width(self):
@@ -726,6 +776,41 @@
         # Make sure ansi_wrap() ends the text by resetting the ANSI styles.
         assert ansi_wrap(text, bold=True).endswith(ANSI_RESET)
 
+    def test_generate_output(self):
+        """Test the :func:`humanfriendly.terminal.output()` function."""
+        text = "Standard output generated by output()"
+        with CaptureOutput(merged=False) as capturer:
+            output(text)
+            self.assertEqual([text], capturer.stdout.get_lines())
+            self.assertEqual([], self.ignore_coverage_warning(capturer))
+
+    def test_generate_message(self):
+        """Test the :func:`humanfriendly.terminal.message()` function."""
+        text = "Standard error generated by message()"
+        with CaptureOutput(merged=False) as capturer:
+            message(text)
+            self.assertEqual([], capturer.stdout.get_lines())
+            self.assertIn(text, self.ignore_coverage_warning(capturer))
+
+    def test_generate_warning(self):
+        """Test the output(), message() and warning() functions."""
+        text = "Standard error generated by warning()"
+        with CaptureOutput(merged=False) as capturer:
+            warning(text)
+            self.assertEqual([], capturer.stdout.get_lines())
+            self.assertEqual([ansi_wrap(text, color='red')], 
self.ignore_coverage_warning(capturer))
+
+    def ignore_coverage_warning(self, capturer):
+        """
+        Filter out coverage.py warning from standard error.
+
+        This is intended to remove the following line from the lines captured
+        on the standard error stream:
+
+        Coverage.py warning: No data was collected. (no-data-collected)
+        """
+        return [line for line in capturer.stderr.get_lines() if 
'no-data-collected' not in line]
+
     def test_clean_output(self):
         """Test :func:`humanfriendly.terminal.clean_terminal_output()`."""
         # Simple output should pass through unharmed (single line).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/humanfriendly-4.4.1/humanfriendly.egg-info/PKG-INFO 
new/humanfriendly-4.8/humanfriendly.egg-info/PKG-INFO
--- old/humanfriendly-4.4.1/humanfriendly.egg-info/PKG-INFO     2017-08-07 
22:59:43.000000000 +0200
+++ new/humanfriendly-4.8/humanfriendly.egg-info/PKG-INFO       2018-01-20 
21:19:21.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: humanfriendly
-Version: 4.4.1
+Version: 4.8
 Summary: Human friendly output for text interfaces using Python
 Home-page: https://humanfriendly.readthedocs.io
 Author: Peter Odding
@@ -32,7 +32,8 @@
           size.
         
         The `humanfriendly` package is currently tested on Python 2.6, 2.7, 
3.4, 3.5,
-        3.6 and PyPy (2.7).
+        3.6 and PyPy (2.7) on Linux and Mac OS X. While the intention is to 
support
+        Windows as well, you may encounter some rough edges.
         
         .. contents::
            :local:
@@ -91,12 +92,16 @@
            formatted number to standard output."
            "``-s``, ``--format-size=BYTES``","Convert a byte count (given as 
the integer ``BYTES``) into a human readable
            string and print that string to standard output."
+           "``-b``, ``--binary``","Change the output of ``-s``, 
``--format-size`` to use binary multiples of bytes
+           (base-2) instead of the default decimal multiples of bytes 
(base-10)."
            "``-t``, ``--format-timespan=SECONDS``","Convert a number of 
seconds (given as the floating point number ``SECONDS``)
            into a human readable timespan and print that string to standard 
output."
-           ``--parse-size=VALUE``,"Parse a human readable data size (given as 
the string ``VALUE``) and print the
-           number of bytes to standard output."
            ``--parse-length=VALUE``,"Parse a human readable length (given as 
the string ``VALUE``) and print the
            number of metres to standard output."
+           ``--parse-size=VALUE``,"Parse a human readable data size (given as 
the string ``VALUE``) and print the
+           number of bytes to standard output."
+           ``--demo``,"Demonstrate changing the style and color of the 
terminal font using ANSI
+           escape sequences."
            "``-h``, ``--help``",Show this message and exit.
         
         .. [[[end]]]
@@ -139,7 +144,7 @@
         
         This software is licensed under the `MIT license`_.
         
-        © 2017 Peter Odding.
+        © 2018 Peter Odding.
         
         .. External references:
         .. _#4: https://github.com/xolox/python-humanfriendly/issues/4
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/humanfriendly-4.4.1/humanfriendly.egg-info/SOURCES.txt 
new/humanfriendly-4.8/humanfriendly.egg-info/SOURCES.txt
--- old/humanfriendly-4.4.1/humanfriendly.egg-info/SOURCES.txt  2017-08-07 
22:59:43.000000000 +0200
+++ new/humanfriendly-4.8/humanfriendly.egg-info/SOURCES.txt    2018-01-20 
21:19:21.000000000 +0100
@@ -7,6 +7,7 @@
 setup.py
 docs/conf.py
 docs/index.rst
+docs/images/ansi-demo.png
 docs/images/pretty-table.png
 docs/images/spinner-basic.gif
 docs/images/spinner-with-progress.gif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/humanfriendly-4.4.1/humanfriendly.egg-info/requires.txt 
new/humanfriendly-4.8/humanfriendly.egg-info/requires.txt
--- old/humanfriendly-4.4.1/humanfriendly.egg-info/requires.txt 2017-08-07 
22:59:43.000000000 +0200
+++ new/humanfriendly-4.8/humanfriendly.egg-info/requires.txt   2018-01-20 
21:19:21.000000000 +0100
@@ -5,3 +5,6 @@
 [:python_version == "2.6" or python_version == "3.0"]
 importlib
 unittest2
+
+[:sys_platform == "win32"]
+pyreadline
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/humanfriendly-4.4.1/requirements-tests.txt 
new/humanfriendly-4.8/requirements-tests.txt
--- old/humanfriendly-4.4.1/requirements-tests.txt      2017-06-29 
00:08:23.000000000 +0200
+++ new/humanfriendly-4.8/requirements-tests.txt        2018-01-04 
13:06:45.000000000 +0100
@@ -1,5 +1,9 @@
 # Test suite requirements.
 capturer >= 2.1
 coloredlogs >= 2.0
-pytest >= 3.0.7
+pytest >= 3.0.7 ; python_version > '2.6'
 pytest-cov >= 2.4.0
+
+# pytest release 3.3 drops Python 2.6 compatibility:
+# https://docs.pytest.org/en/latest/changelog.html#pytest-3-3-0-2017-11-23
+pytest < 3.3 ; python_version < '2.7'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/humanfriendly-4.4.1/setup.py 
new/humanfriendly-4.8/setup.py
--- old/humanfriendly-4.4.1/setup.py    2017-07-01 22:45:42.000000000 +0200
+++ new/humanfriendly-4.8/setup.py      2018-01-04 13:06:45.000000000 +0100
@@ -3,7 +3,7 @@
 # Setup script for the `humanfriendly' package.
 #
 # Author: Peter Odding <pe...@peterodding.com>
-# Last Change: July 1, 2017
+# Last Change: January 1, 2018
 # URL: https://humanfriendly.readthedocs.io
 
 """
@@ -50,6 +50,8 @@
             install_requires.extend(('importlib', 'unittest2'))
         if sys.version_info[:2] < (3, 3):
             install_requires.append('monotonic')
+        if sys.platform == 'win32':
+            install_requires.append('pyreadline')
     return sorted(install_requires)
 
 
@@ -57,7 +59,7 @@
     """Get the conditional dependencies for wheel distributions."""
     extras_require = {}
     if have_environment_marker_support():
-        # Conditional `importlib' dependency.
+        # Conditional `importlib' and `unittest2' dependencies.
         expression = ':%s' % ' or '.join([
             'python_version == "2.6"',
             'python_version == "3.0"',
@@ -72,6 +74,9 @@
             'python_version == "3.2"',
         ])
         extras_require[expression] = ['monotonic']
+        # Conditional `pyreadline' dependency.
+        expression = ':sys_platform == "win32"'
+        extras_require[expression] = 'pyreadline'
     return extras_require
 
 


Reply via email to