Codebase list humanfriendly / 4eafa22
Update upstream source from tag 'upstream/9.1' Update to upstream version '9.1' with Debian dir 04914890f75b54b6317c2c21720bd98fd0b2289c Sandro Tosi 3 years ago
20 changed file(s) with 317 addition(s) and 484 deletion(s). Raw diff Collapse all Expand all
0 [run]
1 branch = true
2 parallel = True
3 concurrency = multiprocessing
4 source = humanfriendly
5 omit = humanfriendly/tests.py
0 *.egg-info/
1 *.pyc
2 .coverage
3 .coverage.*
4 __pycache__/
5 dist/*.tar.gz
6 dist/*.zip
7 docs/_build/
8 docs/_static/
9 docs/_templates/
10 docs/build/
11 htmlcov/
0 language: python
1 cache: pip
2 matrix:
3 include:
4 - os: osx
5 language: generic
6 - python: pypy
7 - python: 2.7
8 - python: 3.5
9 - python: 3.6
10 - python: 3.7
11 - python: 3.8
12 - python: 3.9-dev
13 install:
14 - scripts/travis.sh pip install --upgrade setuptools
15 - scripts/travis.sh pip install --upgrade --requirement=requirements-travis.txt
16 - scripts/travis.sh LC_ALL=C pip install .
17 script:
18 - scripts/travis.sh make check
19 - scripts/travis.sh make test
20 after_success:
21 - scripts/travis.sh coveralls
22 branches:
23 except:
24 - /^[0-9]/
99
1010 .. _Keep a Changelog: http://keepachangelog.com/
1111 .. _semantic versioning: http://semver.org/
12
13 `Release 9.1`_ (2020-12-10)
14 ---------------------------
15
16 Added :func:`~humanfriendly.compat.on_macos()` function to detect Apple MacOS
17 (I need this in an upcoming :pypi:`coloredlogs` release and don't want to have
18 to think about how to detect MacOS again in the future 😇).
19
20 .. _Release 9.1: https://github.com/xolox/python-humanfriendly/compare/9.0...9.1
21
22 `Release 9.0`_ (2020-12-01)
23 ---------------------------
24
25 The major version number was bumped because the bug fix for
26 :func:`~humanfriendly.text.pluralize()` is backwards incompatible
27 and (even though this seems like very "cosmetic" functionality)
28 version numbers are cheap, so who cares 😉.
29
30 **Bug fixes:**
31
32 - Changed :func:`~humanfriendly.format_number()` to properly support negative
33 numbers (as suggested in `issue #40`_).
34
35 - Changed :func:`~humanfriendly.text.pluralize()` to generate "1.5 seconds"
36 instead of "1.5 second" (as suggested in `issue #43`_).
37
38 **Enhancements:**
39
40 - Enhanced :func:`~humanfriendly.text.concatenate()` to support ``conjunction``
41 and ``serial_comma`` keyword arguments (as suggested in `issue #30`_).
42
43 - Added :func:`~humanfriendly.text.pluralize_raw()` to select singular or
44 plural form without prefixing the count to the text that is returned.
45
46 .. _Release 9.0: https://github.com/xolox/python-humanfriendly/compare/8.2...9.0
47 .. _issue #30: https://github.com/xolox/python-humanfriendly/issues/30
48 .. _issue #40: https://github.com/xolox/python-humanfriendly/issues/40
49 .. _issue #43: https://github.com/xolox/python-humanfriendly/issues/43
1250
1351 `Release 8.2`_ (2020-04-19)
1452 ---------------------------
0 # Makefile for the 'humanfriendly' package.
1 #
2 # Author: Peter Odding <peter@peterodding.com>
3 # Last Change: March 1, 2020
4 # URL: https://humanfriendly.readthedocs.io
5
6 PACKAGE_NAME = humanfriendly
7 WORKON_HOME ?= $(HOME)/.virtualenvs
8 VIRTUAL_ENV ?= $(WORKON_HOME)/$(PACKAGE_NAME)
9 PYTHON ?= python3
10 PATH := $(VIRTUAL_ENV)/bin:$(PATH)
11 MAKE := $(MAKE) --no-print-directory
12 SHELL = bash
13
14 default:
15 @echo "Makefile for $(PACKAGE_NAME)"
16 @echo
17 @echo 'Usage:'
18 @echo
19 @echo ' make install install the package in a virtual environment'
20 @echo ' make reset recreate the virtual environment'
21 @echo ' make check check coding style (PEP-8, PEP-257)'
22 @echo ' make test run the test suite, report coverage'
23 @echo ' make tox run the tests on all Python versions'
24 @echo ' make readme update usage in readme'
25 @echo ' make docs update documentation using Sphinx'
26 @echo ' make publish publish changes to GitHub/PyPI'
27 @echo ' make clean cleanup all temporary files'
28 @echo
29
30 install:
31 @test -d "$(VIRTUAL_ENV)" || mkdir -p "$(VIRTUAL_ENV)"
32 @test -x "$(VIRTUAL_ENV)/bin/python" || virtualenv --python=$(PYTHON) --quiet "$(VIRTUAL_ENV)"
33 @pip uninstall --yes $(PACKAGE_NAME) &>/dev/null || true
34 @pip install --quiet --no-deps --ignore-installed .
35
36 reset:
37 @$(MAKE) clean
38 @rm -Rf "$(VIRTUAL_ENV)"
39 @$(MAKE) install
40
41 check: install
42 @pip install --upgrade --quiet --requirement=requirements-checks.txt
43 @flake8
44
45 test: install
46 @pip install --quiet --requirement=requirements-tests.txt
47 @py.test --cov
48 @coverage combine || true
49 @coverage html
50
51 tox: install
52 @pip install --quiet tox
53 @tox
54
55 readme: install
56 @pip install --quiet cogapp
57 @cog.py -r README.rst
58
59 docs: readme
60 @pip install --quiet sphinx
61 @cd docs && sphinx-build -nWb html -d build/doctrees . build/html
62
63 publish: install
64 @git push origin && git push --tags origin
65 @$(MAKE) clean
66 @pip install --quiet twine wheel
67 @python setup.py sdist bdist_wheel
68 @twine upload dist/*
69 @$(MAKE) clean
70
71 clean:
72 @rm -Rf *.egg .cache .coverage .tox build dist docs/build htmlcov
73 @find -depth -type d -name __pycache__ -exec rm -Rf {} \;
74 @find -type f -name '*.pyc' -delete
75
76 .PHONY: default install reset check test tox readme docs publish clean
+0
-201
PKG-INFO less more
0 Metadata-Version: 1.2
1 Name: humanfriendly
2 Version: 8.2
3 Summary: Human friendly output for text interfaces using Python
4 Home-page: https://humanfriendly.readthedocs.io
5 Author: Peter Odding
6 Author-email: peter@peterodding.com
7 License: MIT
8 Description: humanfriendly: Human friendly input/output in Python
9 ====================================================
10
11 .. image:: https://travis-ci.org/xolox/python-humanfriendly.svg?branch=master
12 :target: https://travis-ci.org/xolox/python-humanfriendly
13
14 .. image:: https://coveralls.io/repos/github/xolox/python-humanfriendly/badge.svg?branch=master
15 :target: https://coveralls.io/github/xolox/python-humanfriendly?branch=master
16
17 The functions and classes in the `humanfriendly` package can be used to make
18 text interfaces more user friendly. Some example features:
19
20 - Parsing and formatting numbers, file sizes, pathnames and timespans in
21 simple, human friendly formats.
22
23 - Easy to use timers for long running operations, with human friendly
24 formatting of the resulting timespans.
25
26 - Prompting the user to select a choice from a list of options by typing the
27 option's number or a unique substring of the option.
28
29 - Terminal interaction including text styling (ANSI escape sequences), user
30 friendly rendering of usage messages and querying the terminal for its
31 size.
32
33 The `humanfriendly` package is currently tested on Python 2.7, 3.5+ and PyPy
34 (2.7) on Linux and macOS. While the intention is to support Windows as well,
35 you may encounter some rough edges.
36
37 .. contents::
38 :local:
39
40 Getting started
41 ---------------
42
43 It's very simple to start using the `humanfriendly` package::
44
45 >>> import humanfriendly
46 >>> user_input = raw_input("Enter a readable file size: ")
47 Enter a readable file size: 16G
48 >>> num_bytes = humanfriendly.parse_size(user_input)
49 >>> print num_bytes
50 16000000000
51 >>> print "You entered:", humanfriendly.format_size(num_bytes)
52 You entered: 16 GB
53 >>> print "You entered:", humanfriendly.format_size(num_bytes, binary=True)
54 You entered: 14.9 GiB
55
56 Command line
57 ------------
58
59 .. A DRY solution to avoid duplication of the `humanfriendly --help' text:
60 ..
61 .. [[[cog
62 .. from humanfriendly.usage import inject_usage
63 .. inject_usage('humanfriendly.cli')
64 .. ]]]
65
66 **Usage:** `humanfriendly [OPTIONS]`
67
68 Human friendly input/output (text formatting) on the command
69 line based on the Python package with the same name.
70
71 **Supported options:**
72
73 .. csv-table::
74 :header: Option, Description
75 :widths: 30, 70
76
77
78 "``-c``, ``--run-command``","Execute an external command (given as the positional arguments) and render
79 a spinner and timer while the command is running. The exit status of the
80 command is propagated."
81 ``--format-table``,"Read tabular data from standard input (each line is a row and each
82 whitespace separated field is a column), format the data as a table and
83 print the resulting table to standard output. See also the ``--delimiter``
84 option."
85 "``-d``, ``--delimiter=VALUE``","Change the delimiter used by ``--format-table`` to ``VALUE`` (a string). By default
86 all whitespace is treated as a delimiter."
87 "``-l``, ``--format-length=LENGTH``","Convert a length count (given as the integer or float ``LENGTH``) into a human
88 readable string and print that string to standard output."
89 "``-n``, ``--format-number=VALUE``","Format a number (given as the integer or floating point number ``VALUE``) with
90 thousands separators and two decimal places (if needed) and print the
91 formatted number to standard output."
92 "``-s``, ``--format-size=BYTES``","Convert a byte count (given as the integer ``BYTES``) into a human readable
93 string and print that string to standard output."
94 "``-b``, ``--binary``","Change the output of ``-s``, ``--format-size`` to use binary multiples of bytes
95 (base-2) instead of the default decimal multiples of bytes (base-10)."
96 "``-t``, ``--format-timespan=SECONDS``","Convert a number of seconds (given as the floating point number ``SECONDS``)
97 into a human readable timespan and print that string to standard output."
98 ``--parse-length=VALUE``,"Parse a human readable length (given as the string ``VALUE``) and print the
99 number of metres to standard output."
100 ``--parse-size=VALUE``,"Parse a human readable data size (given as the string ``VALUE``) and print the
101 number of bytes to standard output."
102 ``--demo``,"Demonstrate changing the style and color of the terminal font using ANSI
103 escape sequences."
104 "``-h``, ``--help``",Show this message and exit.
105
106 .. [[[end]]]
107
108 A note about size units
109 -----------------------
110
111 When I originally published the `humanfriendly` package I went with binary
112 multiples of bytes (powers of two). It was pointed out several times that this
113 was a poor choice (see issue `#4`_ and pull requests `#8`_ and `#9`_) and thus
114 the new default became decimal multiples of bytes (powers of ten):
115
116 +------+---------------+---------------+
117 | Unit | Binary value | Decimal value |
118 +------+---------------+---------------+
119 | KB | 1024 | 1000 +
120 +------+---------------+---------------+
121 | MB | 1048576 | 1000000 |
122 +------+---------------+---------------+
123 | GB | 1073741824 | 1000000000 |
124 +------+---------------+---------------+
125 | TB | 1099511627776 | 1000000000000 |
126 +------+---------------+---------------+
127 | etc | | |
128 +------+---------------+---------------+
129
130 The option to use binary multiples of bytes remains by passing the keyword
131 argument `binary=True` to the `format_size()`_ and `parse_size()`_ functions.
132
133 Windows support
134 ---------------
135
136 Windows 10 gained native support for ANSI escape sequences which means commands
137 like ``humanfriendly --demo`` should work out of the box (if your system is
138 up-to-date enough). If this doesn't work then you can install the colorama_
139 package, it will be used automatically once installed.
140
141 Contact
142 -------
143
144 The latest version of `humanfriendly` is available on PyPI_ and GitHub_. The
145 documentation is hosted on `Read the Docs`_ and includes a changelog_. For bug
146 reports please create an issue on GitHub_. If you have questions, suggestions,
147 etc. feel free to send me an e-mail at `peter@peterodding.com`_.
148
149 License
150 -------
151
152 This software is licensed under the `MIT license`_.
153
154 © 2020 Peter Odding.
155
156 .. External references:
157 .. _#4: https://github.com/xolox/python-humanfriendly/issues/4
158 .. _#8: https://github.com/xolox/python-humanfriendly/pull/8
159 .. _#9: https://github.com/xolox/python-humanfriendly/pull/9
160 .. _changelog: https://humanfriendly.readthedocs.io/en/latest/changelog.html
161 .. _colorama: https://pypi.org/project/colorama
162 .. _format_size(): https://humanfriendly.readthedocs.io/en/latest/#humanfriendly.format_size
163 .. _GitHub: https://github.com/xolox/python-humanfriendly
164 .. _MIT license: https://en.wikipedia.org/wiki/MIT_License
165 .. _parse_size(): https://humanfriendly.readthedocs.io/en/latest/#humanfriendly.parse_size
166 .. _peter@peterodding.com: peter@peterodding.com
167 .. _PyPI: https://pypi.org/project/humanfriendly
168 .. _Read the Docs: https://humanfriendly.readthedocs.io
169
170 Platform: UNKNOWN
171 Classifier: Development Status :: 6 - Mature
172 Classifier: Environment :: Console
173 Classifier: Framework :: Sphinx :: Extension
174 Classifier: Intended Audience :: Developers
175 Classifier: Intended Audience :: System Administrators
176 Classifier: License :: OSI Approved :: MIT License
177 Classifier: Natural Language :: English
178 Classifier: Programming Language :: Python
179 Classifier: Programming Language :: Python :: 2
180 Classifier: Programming Language :: Python :: 2.7
181 Classifier: Programming Language :: Python :: 3
182 Classifier: Programming Language :: Python :: 3.5
183 Classifier: Programming Language :: Python :: 3.6
184 Classifier: Programming Language :: Python :: 3.7
185 Classifier: Programming Language :: Python :: 3.8
186 Classifier: Programming Language :: Python :: Implementation :: CPython
187 Classifier: Programming Language :: Python :: Implementation :: PyPy
188 Classifier: Topic :: Communications
189 Classifier: Topic :: Scientific/Engineering :: Human Machine Interfaces
190 Classifier: Topic :: Software Development
191 Classifier: Topic :: Software Development :: Libraries :: Python Modules
192 Classifier: Topic :: Software Development :: User Interfaces
193 Classifier: Topic :: System :: Shells
194 Classifier: Topic :: System :: System Shells
195 Classifier: Topic :: System :: Systems Administration
196 Classifier: Topic :: Terminals
197 Classifier: Topic :: Text Processing :: General
198 Classifier: Topic :: Text Processing :: Linguistic
199 Classifier: Topic :: Utilities
200 Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*
00 # Human friendly input/output in Python.
11 #
22 # Author: Peter Odding <peter@peterodding.com>
3 # Last Change: April 19, 2020
3 # Last Change: December 10, 2020
44 # URL: https://humanfriendly.readthedocs.io
55
66 """The main module of the `humanfriendly` package."""
5050 )
5151
5252 # Semi-standard module versioning.
53 __version__ = '8.2'
53 __version__ = '9.1'
5454
5555 # Named tuples to define units of size.
5656 SizeUnit = collections.namedtuple('SizeUnit', 'divider, symbol, name')
352352 6,000,000,000
353353 """
354354 integer_part, _, decimal_part = str(float(number)).partition('.')
355 reversed_digits = ''.join(reversed(integer_part))
355 negative_sign = integer_part.startswith('-')
356 reversed_digits = ''.join(reversed(integer_part.lstrip('-')))
356357 parts = []
357358 while reversed_digits:
358359 parts.append(reversed_digits[:3])
361362 decimals_to_add = decimal_part[:num_decimals].rstrip('0')
362363 if decimals_to_add:
363364 formatted_number += '.' + decimals_to_add
365 if negative_sign:
366 formatted_number = '-' + formatted_number
364367 return formatted_number
365368
366369
00 # Human friendly input/output in Python.
11 #
22 # Author: Peter Odding <peter@peterodding.com>
3 # Last Change: March 1, 2020
3 # Last Change: December 10, 2020
44 # URL: https://humanfriendly.readthedocs.io
55
66 """
5151 'is_unicode',
5252 'monotonic',
5353 'name2codepoint',
54 'on_macos',
5455 'on_windows',
5556 'unichr',
5657 'unicode',
131132 return isinstance(value, unicode)
132133
133134
135 def on_macos():
136 """
137 Check if we're running on Apple MacOS.
138
139 :returns: :data:`True` if running MacOS, :data:`False` otherwise.
140 """
141 return sys.platform.startswith('darwin')
142
143
134144 def on_windows():
135145 """
136146 Check if we're running on the Microsoft Windows OS.
33 # Tests for the `humanfriendly' package.
44 #
55 # Author: Peter Odding <peter.odding@paylogic.eu>
6 # Last Change: April 19, 2020
6 # Last Change: December 1, 2020
77 # URL: https://humanfriendly.readthedocs.io
88
99 """Test suite for the `humanfriendly` package."""
440440 # Make sure milliseconds are never shown separately when detailed=False.
441441 # https://github.com/xolox/python-humanfriendly/issues/10
442442 assert '1 minute, 1 second and 100 milliseconds' == format_timespan(61.10, detailed=True)
443 assert '1 minute and 1.1 second' == format_timespan(61.10, detailed=False)
443 assert '1 minute and 1.1 seconds' == format_timespan(61.10, detailed=False)
444444 # Test for loss of precision as reported in issue 11:
445445 # https://github.com/xolox/python-humanfriendly/issues/11
446446 assert '1 minute and 0.3 seconds' == format_timespan(60.300)
574574 self.assertEqual('1,000', format_number(1000.12, 0))
575575 self.assertEqual('1,000,000', format_number(1000000))
576576 self.assertEqual('1,000,000.42', format_number(1000000.42))
577 # Regression test for https://github.com/xolox/python-humanfriendly/issues/40.
578 self.assertEqual('-285.67', format_number(-285.67))
577579
578580 def test_round_number(self):
579581 """Test :func:`humanfriendly.round_number()`."""
727729 assert concatenate(['one']) == 'one'
728730 assert concatenate(['one', 'two']) == 'one and two'
729731 assert concatenate(['one', 'two', 'three']) == 'one, two and three'
732 # Test the 'conjunction' option.
733 assert concatenate(['one', 'two', 'three'], conjunction='or') == 'one, two or three'
734 # Test the 'serial_comma' option.
735 assert concatenate(['one', 'two', 'three'], serial_comma=True) == 'one, two, and three'
730736
731737 def test_split(self):
732738 """Test :func:`humanfriendly.text.split()`."""
786792 .replace(ANSI_HIDE_CURSOR, ''))
787793 lines = [line for line in output.split(ANSI_ERASE_LINE) if line]
788794 self.assertTrue(len(lines) > 0)
789 self.assertTrue(all('test spinner' in l for l in lines))
790 self.assertTrue(all('%' in l for l in lines))
795 self.assertTrue(all('test spinner' in ln for ln in lines))
796 self.assertTrue(all('%' in ln for ln in lines))
791797 self.assertEqual(sorted(set(lines)), sorted(lines))
792798
793799 def test_automatic_spinner(self):
951957 # https://github.com/xolox/python-humanfriendly/issues/28
952958 returncode, output = run_cli(main, '--demo')
953959 assert returncode == 0
954 lines = [ansi_strip(l) for l in output.splitlines()]
960 lines = [ansi_strip(ln) for ln in output.splitlines()]
955961 assert "Text styles:" in lines
956962 assert "Foreground colors:" in lines
957963 assert "Background colors:" in lines
00 # Human friendly input/output in Python.
11 #
22 # Author: Peter Odding <peter@peterodding.com>
3 # Last Change: March 1, 2020
3 # Last Change: December 1, 2020
44 # URL: https://humanfriendly.readthedocs.io
55
66 """
1919 """
2020
2121 # Standard library modules.
22 import math
2322 import numbers
2423 import random
2524 import re
3736 'is_empty_line',
3837 'join_lines',
3938 'pluralize',
39 'pluralize_raw',
4040 'random_string',
4141 'split',
4242 'split_paragraphs',
9393 return ''.join(lines)
9494
9595
96 def concatenate(items):
96 def concatenate(items, conjunction='and', serial_comma=False):
9797 """
9898 Concatenate a list of items in a human friendly way.
9999
100 :param items: A sequence of strings.
101 :returns: A single string.
100 :param items:
101
102 A sequence of strings.
103
104 :param conjunction:
105
106 The word to use before the last item (a string, defaults to "and").
107
108 :param serial_comma:
109
110 :data:`True` to use a `serial comma`_, :data:`False` otherwise
111 (defaults to :data:`False`).
112
113 :returns:
114
115 A single string.
102116
103117 >>> from humanfriendly.text import concatenate
104118 >>> concatenate(["eggs", "milk", "bread"])
105119 'eggs, milk and bread'
120
121 .. _serial comma: https://en.wikipedia.org/wiki/Serial_comma
106122 """
107123 items = list(items)
108124 if len(items) > 1:
109 return ', '.join(items[:-1]) + ' and ' + items[-1]
125 final_item = items.pop()
126 formatted = ', '.join(items)
127 if serial_comma:
128 formatted += ','
129 return ' '.join([formatted, conjunction, final_item])
110130 elif items:
111131 return items[0]
112132 else:
275295 """
276296 Combine a count with the singular or plural form of a word.
277297
298 :param count: The count (a number).
299 :param singular: The singular form of the word (a string).
300 :param plural: The plural form of the word (a string or :data:`None`).
301 :returns: The count and singular or plural word concatenated (a string).
302
303 See :func:`pluralize_raw()` for the logic underneath :func:`pluralize()`.
304 """
305 return '%s %s' % (count, pluralize_raw(count, singular, plural))
306
307
308 def pluralize_raw(count, singular, plural=None):
309 """
310 Select the singular or plural form of a word based on a count.
311
312 :param count: The count (a number).
313 :param singular: The singular form of the word (a string).
314 :param plural: The plural form of the word (a string or :data:`None`).
315 :returns: The singular or plural form of the word (a string).
316
317 When the given count is exactly 1.0 the singular form of the word is
318 selected, in all other cases the plural form of the word is selected.
319
278320 If the plural form of the word is not provided it is obtained by
279321 concatenating the singular form of the word with the letter "s". Of course
280322 this will not always be correct, which is why you have the option to
281323 specify both forms.
282
283 :param count: The count (a number).
284 :param singular: The singular form of the word (a string).
285 :param plural: The plural form of the word (a string or :data:`None`).
286 :returns: The count and singular/plural word concatenated (a string).
287324 """
288325 if not plural:
289326 plural = singular + 's'
290 return '%s %s' % (count, singular if math.floor(float(count)) == 1 else plural)
327 return singular if float(count) == 1.0 else plural
291328
292329
293330 def random_string(length=(25, 100), characters=string.ascii_letters):
00 # Human friendly input/output in Python.
11 #
22 # Author: Peter Odding <peter@peterodding.com>
3 # Last Change: June 24, 2017
3 # Last Change: December 1, 2020
44 # URL: https://humanfriendly.readthedocs.io
55
66 """
257257 ('\n\n'.join(render_paragraph(p, meta_variables) for p in split_paragraphs(description))).rstrip(),
258258 ])
259259 csv_lines = csv_buffer.getvalue().splitlines()
260 output.append('\n'.join(' %s' % l for l in csv_lines))
260 output.append('\n'.join(' %s' % ln for ln in csv_lines))
261261 logger.debug("Rendered output: %s", output)
262262 return '\n\n'.join(trim_empty_lines(o) for o in output)
263263
+0
-201
humanfriendly.egg-info/PKG-INFO less more
0 Metadata-Version: 1.2
1 Name: humanfriendly
2 Version: 8.2
3 Summary: Human friendly output for text interfaces using Python
4 Home-page: https://humanfriendly.readthedocs.io
5 Author: Peter Odding
6 Author-email: peter@peterodding.com
7 License: MIT
8 Description: humanfriendly: Human friendly input/output in Python
9 ====================================================
10
11 .. image:: https://travis-ci.org/xolox/python-humanfriendly.svg?branch=master
12 :target: https://travis-ci.org/xolox/python-humanfriendly
13
14 .. image:: https://coveralls.io/repos/github/xolox/python-humanfriendly/badge.svg?branch=master
15 :target: https://coveralls.io/github/xolox/python-humanfriendly?branch=master
16
17 The functions and classes in the `humanfriendly` package can be used to make
18 text interfaces more user friendly. Some example features:
19
20 - Parsing and formatting numbers, file sizes, pathnames and timespans in
21 simple, human friendly formats.
22
23 - Easy to use timers for long running operations, with human friendly
24 formatting of the resulting timespans.
25
26 - Prompting the user to select a choice from a list of options by typing the
27 option's number or a unique substring of the option.
28
29 - Terminal interaction including text styling (ANSI escape sequences), user
30 friendly rendering of usage messages and querying the terminal for its
31 size.
32
33 The `humanfriendly` package is currently tested on Python 2.7, 3.5+ and PyPy
34 (2.7) on Linux and macOS. While the intention is to support Windows as well,
35 you may encounter some rough edges.
36
37 .. contents::
38 :local:
39
40 Getting started
41 ---------------
42
43 It's very simple to start using the `humanfriendly` package::
44
45 >>> import humanfriendly
46 >>> user_input = raw_input("Enter a readable file size: ")
47 Enter a readable file size: 16G
48 >>> num_bytes = humanfriendly.parse_size(user_input)
49 >>> print num_bytes
50 16000000000
51 >>> print "You entered:", humanfriendly.format_size(num_bytes)
52 You entered: 16 GB
53 >>> print "You entered:", humanfriendly.format_size(num_bytes, binary=True)
54 You entered: 14.9 GiB
55
56 Command line
57 ------------
58
59 .. A DRY solution to avoid duplication of the `humanfriendly --help' text:
60 ..
61 .. [[[cog
62 .. from humanfriendly.usage import inject_usage
63 .. inject_usage('humanfriendly.cli')
64 .. ]]]
65
66 **Usage:** `humanfriendly [OPTIONS]`
67
68 Human friendly input/output (text formatting) on the command
69 line based on the Python package with the same name.
70
71 **Supported options:**
72
73 .. csv-table::
74 :header: Option, Description
75 :widths: 30, 70
76
77
78 "``-c``, ``--run-command``","Execute an external command (given as the positional arguments) and render
79 a spinner and timer while the command is running. The exit status of the
80 command is propagated."
81 ``--format-table``,"Read tabular data from standard input (each line is a row and each
82 whitespace separated field is a column), format the data as a table and
83 print the resulting table to standard output. See also the ``--delimiter``
84 option."
85 "``-d``, ``--delimiter=VALUE``","Change the delimiter used by ``--format-table`` to ``VALUE`` (a string). By default
86 all whitespace is treated as a delimiter."
87 "``-l``, ``--format-length=LENGTH``","Convert a length count (given as the integer or float ``LENGTH``) into a human
88 readable string and print that string to standard output."
89 "``-n``, ``--format-number=VALUE``","Format a number (given as the integer or floating point number ``VALUE``) with
90 thousands separators and two decimal places (if needed) and print the
91 formatted number to standard output."
92 "``-s``, ``--format-size=BYTES``","Convert a byte count (given as the integer ``BYTES``) into a human readable
93 string and print that string to standard output."
94 "``-b``, ``--binary``","Change the output of ``-s``, ``--format-size`` to use binary multiples of bytes
95 (base-2) instead of the default decimal multiples of bytes (base-10)."
96 "``-t``, ``--format-timespan=SECONDS``","Convert a number of seconds (given as the floating point number ``SECONDS``)
97 into a human readable timespan and print that string to standard output."
98 ``--parse-length=VALUE``,"Parse a human readable length (given as the string ``VALUE``) and print the
99 number of metres to standard output."
100 ``--parse-size=VALUE``,"Parse a human readable data size (given as the string ``VALUE``) and print the
101 number of bytes to standard output."
102 ``--demo``,"Demonstrate changing the style and color of the terminal font using ANSI
103 escape sequences."
104 "``-h``, ``--help``",Show this message and exit.
105
106 .. [[[end]]]
107
108 A note about size units
109 -----------------------
110
111 When I originally published the `humanfriendly` package I went with binary
112 multiples of bytes (powers of two). It was pointed out several times that this
113 was a poor choice (see issue `#4`_ and pull requests `#8`_ and `#9`_) and thus
114 the new default became decimal multiples of bytes (powers of ten):
115
116 +------+---------------+---------------+
117 | Unit | Binary value | Decimal value |
118 +------+---------------+---------------+
119 | KB | 1024 | 1000 +
120 +------+---------------+---------------+
121 | MB | 1048576 | 1000000 |
122 +------+---------------+---------------+
123 | GB | 1073741824 | 1000000000 |
124 +------+---------------+---------------+
125 | TB | 1099511627776 | 1000000000000 |
126 +------+---------------+---------------+
127 | etc | | |
128 +------+---------------+---------------+
129
130 The option to use binary multiples of bytes remains by passing the keyword
131 argument `binary=True` to the `format_size()`_ and `parse_size()`_ functions.
132
133 Windows support
134 ---------------
135
136 Windows 10 gained native support for ANSI escape sequences which means commands
137 like ``humanfriendly --demo`` should work out of the box (if your system is
138 up-to-date enough). If this doesn't work then you can install the colorama_
139 package, it will be used automatically once installed.
140
141 Contact
142 -------
143
144 The latest version of `humanfriendly` is available on PyPI_ and GitHub_. The
145 documentation is hosted on `Read the Docs`_ and includes a changelog_. For bug
146 reports please create an issue on GitHub_. If you have questions, suggestions,
147 etc. feel free to send me an e-mail at `peter@peterodding.com`_.
148
149 License
150 -------
151
152 This software is licensed under the `MIT license`_.
153
154 © 2020 Peter Odding.
155
156 .. External references:
157 .. _#4: https://github.com/xolox/python-humanfriendly/issues/4
158 .. _#8: https://github.com/xolox/python-humanfriendly/pull/8
159 .. _#9: https://github.com/xolox/python-humanfriendly/pull/9
160 .. _changelog: https://humanfriendly.readthedocs.io/en/latest/changelog.html
161 .. _colorama: https://pypi.org/project/colorama
162 .. _format_size(): https://humanfriendly.readthedocs.io/en/latest/#humanfriendly.format_size
163 .. _GitHub: https://github.com/xolox/python-humanfriendly
164 .. _MIT license: https://en.wikipedia.org/wiki/MIT_License
165 .. _parse_size(): https://humanfriendly.readthedocs.io/en/latest/#humanfriendly.parse_size
166 .. _peter@peterodding.com: peter@peterodding.com
167 .. _PyPI: https://pypi.org/project/humanfriendly
168 .. _Read the Docs: https://humanfriendly.readthedocs.io
169
170 Platform: UNKNOWN
171 Classifier: Development Status :: 6 - Mature
172 Classifier: Environment :: Console
173 Classifier: Framework :: Sphinx :: Extension
174 Classifier: Intended Audience :: Developers
175 Classifier: Intended Audience :: System Administrators
176 Classifier: License :: OSI Approved :: MIT License
177 Classifier: Natural Language :: English
178 Classifier: Programming Language :: Python
179 Classifier: Programming Language :: Python :: 2
180 Classifier: Programming Language :: Python :: 2.7
181 Classifier: Programming Language :: Python :: 3
182 Classifier: Programming Language :: Python :: 3.5
183 Classifier: Programming Language :: Python :: 3.6
184 Classifier: Programming Language :: Python :: 3.7
185 Classifier: Programming Language :: Python :: 3.8
186 Classifier: Programming Language :: Python :: Implementation :: CPython
187 Classifier: Programming Language :: Python :: Implementation :: PyPy
188 Classifier: Topic :: Communications
189 Classifier: Topic :: Scientific/Engineering :: Human Machine Interfaces
190 Classifier: Topic :: Software Development
191 Classifier: Topic :: Software Development :: Libraries :: Python Modules
192 Classifier: Topic :: Software Development :: User Interfaces
193 Classifier: Topic :: System :: Shells
194 Classifier: Topic :: System :: System Shells
195 Classifier: Topic :: System :: Systems Administration
196 Classifier: Topic :: Terminals
197 Classifier: Topic :: Text Processing :: General
198 Classifier: Topic :: Text Processing :: Linguistic
199 Classifier: Topic :: Utilities
200 Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*
+0
-42
humanfriendly.egg-info/SOURCES.txt less more
0 CHANGELOG.rst
1 LICENSE.txt
2 MANIFEST.in
3 README.rst
4 requirements-checks.txt
5 requirements-tests.txt
6 requirements-travis.txt
7 setup.cfg
8 setup.py
9 docs/api.rst
10 docs/changelog.rst
11 docs/conf.py
12 docs/index.rst
13 docs/readme.rst
14 docs/images/ansi-demo.png
15 docs/images/html-to-ansi.png
16 docs/images/pretty-table.png
17 docs/images/spinner-basic.gif
18 docs/images/spinner-with-progress.gif
19 docs/images/spinner-with-timer.gif
20 humanfriendly/__init__.py
21 humanfriendly/case.py
22 humanfriendly/cli.py
23 humanfriendly/compat.py
24 humanfriendly/decorators.py
25 humanfriendly/deprecation.py
26 humanfriendly/prompts.py
27 humanfriendly/sphinx.py
28 humanfriendly/tables.py
29 humanfriendly/testing.py
30 humanfriendly/tests.py
31 humanfriendly/text.py
32 humanfriendly/usage.py
33 humanfriendly.egg-info/PKG-INFO
34 humanfriendly.egg-info/SOURCES.txt
35 humanfriendly.egg-info/dependency_links.txt
36 humanfriendly.egg-info/entry_points.txt
37 humanfriendly.egg-info/requires.txt
38 humanfriendly.egg-info/top_level.txt
39 humanfriendly/terminal/__init__.py
40 humanfriendly/terminal/html.py
41 humanfriendly/terminal/spinners.py
+0
-1
humanfriendly.egg-info/dependency_links.txt less more
0
+0
-3
humanfriendly.egg-info/entry_points.txt less more
0 [console_scripts]
1 humanfriendly = humanfriendly.cli:main
2
+0
-6
humanfriendly.egg-info/requires.txt less more
0
1 [:python_version == "2.7"]
2 monotonic
3
4 [:sys_platform == "win32"]
5 pyreadline
+0
-1
humanfriendly.egg-info/top_level.txt less more
0 humanfriendly
0 #!/bin/bash -e
1
2 # Even though Travis CI supports Mac OS X [1] and several Python interpreters
3 # are installed out of the box, the Python environment cannot be configured in
4 # the Travis CI build configuration [2].
5 #
6 # As a workaround the build configuration file specifies a single Mac OS X job
7 # with `language: generic' that runs this script to create and activate a
8 # Python virtual environment.
9 #
10 # Recently the `virtualenv' command seems to no longer come pre-installed on
11 # the MacOS workers of Travis CI [3] so when this situation is detected we
12 # install it ourselves.
13 #
14 # [1] https://github.com/travis-ci/travis-ci/issues/216
15 # [2] https://github.com/travis-ci/travis-ci/issues/2312
16 # [3] https://travis-ci.org/xolox/python-humanfriendly/jobs/411396506
17
18 main () {
19 if [ "$TRAVIS_OS_NAME" = osx ]; then
20 local environment="$HOME/virtualenv/python2.7"
21 if [ -x "$environment/bin/python" ]; then
22 msg "Activating virtual environment ($environment) .."
23 source "$environment/bin/activate"
24 else
25 if ! which virtualenv &>/dev/null; then
26 msg "Installing 'virtualenv' in per-user site-packages .."
27 pip install --user virtualenv
28 msg "Figuring out 'bin' directory of per-user site-packages .."
29 LOCAL_BINARIES=$(python -c 'import os, site; print(os.path.join(site.USER_BASE, "bin"))')
30 msg "Prefixing '$LOCAL_BINARIES' to PATH .."
31 export PATH="$LOCAL_BINARIES:$PATH"
32 fi
33 msg "Creating virtual environment ($environment) .."
34 virtualenv "$environment"
35 msg "Activating virtual environment ($environment) .."
36 source "$environment/bin/activate"
37 msg "Checking if 'pip' executable works .."
38 if ! pip --version; then
39 msg "Bootstrapping working 'pip' installation using get-pip.py .."
40 curl -s https://bootstrap.pypa.io/get-pip.py | python -
41 fi
42 fi
43 fi
44 msg "Running command: $*"
45 eval "$@"
46 }
47
48 msg () {
49 echo "[travis.sh] $*" >&2
50 }
51
52 main "$@"
0 # Enable building of universal wheels so we can publish wheel
1 # distribution archives to PyPI (the Python package index)
2 # that are compatible with Python 2 as well as Python 3.
3
04 [wheel]
1 universal = 1
2
3 [egg_info]
4 tag_build =
5 tag_date = 0
6
5 universal=1
0 # Tox (http://tox.testrun.org/) is a tool for running tests in multiple
1 # virtualenvs. This configuration file will run the test suite on all supported
2 # python versions. To use it, "pip install tox" and then run "tox" from this
3 # directory.
4
5 [tox]
6 envlist = py27, py35, py36, py37, py38, py39, pypy
7
8 [testenv]
9 deps = -rrequirements-tests.txt
10 commands = py.test {posargs}
11 passenv = HOME
12
13 [pytest]
14 addopts = --verbose
15 norecursedirs = .tox
16 python_files = humanfriendly/tests.py
17
18 [flake8]
19 exclude = .tox
20 extend-ignore = D200,D205,D211,D400,D401,D402,D412,D413,W504
21 max-line-length = 120