Code Monkey home page Code Monkey logo

python-humanfriendly's Introduction

humanfriendly: Human friendly input/output in Python

image

image

The functions and classes in the humanfriendly package can be used to make text interfaces more user friendly. Some example features:

  • Parsing and formatting numbers, file sizes, pathnames and timespans in simple, human friendly formats.
  • Easy to use timers for long running operations, with human friendly formatting of the resulting timespans.
  • Prompting the user to select a choice from a list of options by typing the option's number or a unique substring of the option.
  • Terminal interaction including text styling (ANSI escape sequences), user friendly rendering of usage messages and querying the terminal for its size.

The humanfriendly package is currently tested on Python 2.7, 3.5+ and PyPy (2.7) on Linux and macOS. While the intention is to support Windows as well, you may encounter some rough edges.

Getting started

It's very simple to start using the humanfriendly package:

>>> from humanfriendly import format_size, parse_size
>>> from humanfriendly.prompts import prompt_for_input
>>> user_input = prompt_for_input("Enter a readable file size: ")

  Enter a readable file size: 16G

>>> num_bytes = parse_size(user_input)
>>> print(num_bytes)
16000000000
>>> print("You entered:", format_size(num_bytes))
You entered: 16 GB
>>> print("You entered:", format_size(num_bytes, binary=True))
You entered: 14.9 GiB

To get a demonstration of supported terminal text styles (based on ANSI escape sequences) you can run the following command:

$ humanfriendly --demo

Command line

Usage: humanfriendly [OPTIONS]

Human friendly input/output (text formatting) on the command line based on the Python package with the same name.

Supported options:

Option Description
-c, --run-command Execute an external command (given as the positional arguments) and render a spinner and timer while the command is running. The exit status of the command is propagated.
--format-table Read tabular data from standard input (each line is a row and each whitespace separated field is a column), format the data as a table and print the resulting table to standard output. See also the --delimiter option.
-d, --delimiter=VALUE Change the delimiter used by --format-table to VALUE (a string). By default all whitespace is treated as a delimiter.
-l, --format-length=LENGTH Convert a length count (given as the integer or float LENGTH) into a human readable string and print that string to standard output.
-n, --format-number=VALUE Format a number (given as the integer or floating point number VALUE) with thousands separators and two decimal places (if needed) and print the 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-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.

A note about size units

When I originally published the humanfriendly package I went with binary multiples of bytes (powers of two). It was pointed out several times that this was a poor choice (see issue #4 and pull requests #8 and #9) and thus the new default became decimal multiples of bytes (powers of ten):

Unit Binary value Decimal value
KB

1024

1000 +

MB

1048576

1000000

GB

1073741824

1000000000

TB 1099511627776 1000000000000
etc

The option to use binary multiples of bytes remains by passing the keyword argument binary=True to the format_size() and parse_size() functions.

Windows support

Windows 10 gained native support for ANSI escape sequences which means commands like humanfriendly --demo should work out of the box (if your system is up-to-date enough). If this doesn't work then you can install the colorama package, it will be used automatically once installed.

Contact

The latest version of humanfriendly is available on PyPI and GitHub. The documentation is hosted on Read the Docs and includes a changelog. For bug reports please create an issue on GitHub. If you have questions, suggestions, etc. feel free to send me an e-mail at [email protected].

License

This software is licensed under the MIT license.

© 2021 Peter Odding.

python-humanfriendly's People

Contributors

blaise-io avatar brandonio21 avatar dirk-thomas avatar flimm avatar fsaintjacques avatar gadgetsteve avatar ghisvail avatar ghostofgoes avatar hugovk avatar icook avatar jasonin2d avatar korylprince avatar mitalashok avatar ppinard avatar sobolevn avatar standage avatar xolox avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-humanfriendly's Issues

erase_line_code does not work in Windows cmd.exe

image
Was trying to use the spinner in your library but spinner.clear() is not behaving as expected in Windows cmd.exe. It's probably because Windows cmd cannot decode erase_line_code. Is there any way I can resolve this? Thanks!

Dependency on pyreadline may cause breaking incompatibility in Python 3.9

We've been noticing a deprecation warning in our python stack due to pyreadline, which is a dependency of this package. Unfortunately, pyreadline has not been updated in quite a bit and is likely abandoned at this point, which yields little hope the deprecation will be resolved by the release date of Python 3.9. It might make sense to remove the dependency on pyreadline for Windows with Python >= 3.9

Upstream issue for collections deprecation
pyreadline/pyreadline#65

parse_timespan: add support for an "abbreviated" output

In [52]: humanfriendly.format_timespan(2576)
Out[52]: '42 minutes and 56 seconds'

it would be great if an abbreviated=True argument was present to produce:

In [52]: humanfriendly.format_timespan(2576, abbreviated=True)
Out[52]: '42m 56s'

parse_timespan accepts that shortened version already.

thanks!

Loss of precision when formatting timespans

Hi,

Some test cases:

>>> import humanfriendly as hf

>>> hf.format_timespan(60.300)
'1 minute and 299 milliseconds'

>>> hf.format_timespan(300.300)
'5 minutes and 300 milliseconds'

>>> hf.format_timespan(1.015, True)
'1 second and 14 milliseconds'

>>> hf.format_timespan(10.015, True)
'10 seconds and 15 milliseconds'

parse_timespan with multiple values

It would be if parse_timespan could parse multiple values.

>>> import humanfriendly
>>> humanfriendly.parse_timespan("3h")
10800.0
>>> humanfriendly.parse_timespan("4m")
240.0
>>> humanfriendly.parse_timespan("3h 4m")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/frafra/.local/share/fades/756b567c-07d9-445e-8f98-642cf7ac909e/lib64/python3.6/site-packages/humanfriendly/__init__.py", line 516, in parse_timespan
    raise InvalidTimespan(format(msg, timespan, tokens))
humanfriendly.InvalidTimespan: Failed to parse timespan! (input '3h 4m' was tokenized as [3, 'h', 4, 'm'])
>>> import copy
>>> parse_timespan = copy.copy(humanfriendly.parse_timespan)
>>> humanfriendly.parse_timespan = lambda s: sum(map(parse_timespan, s.split()))
>>> humanfriendly.parse_timespan("3h 4m")
11040.0

Formatting large negative numbers minor issue

Noticed that the function format_number returns a a leading comma after the minus sign for negative numbers with a set of digits that is a multiple of 3. Just wanted to flag here in case it was unknown :)

Current behaviour:

difference = -285.671623847
humanfriendly.format_number(difference)
Out[118]: '-,285.67'

Expected behaviour:

difference = -285.671623847
humanfriendly.format_number(difference)
Out[118]: '-285.67'

Support months in parse_timespan / Case-sensitive suffixes

Sorry if this question was raise before.

Is there any reason for humanfriendly doesn't support months (with M suffix) in parse_timespan?

Looking into the code I can see that suffixes are lowercased and therefore the 'M' suffix cant' be used but this can be easily achieved removing the .lower() call or choosing another suffix like 'mo'.

Anyway, it's possible to get month suffix in parse_timespan?

sizes incorrectly parsed as powers of two by default, ignoring IEEE 1541

i believe this is incorrect:

    >>> parse_size('42')
    42
    >>> parse_size('1 KB')
    1024
    >>> parse_size('5 kilobyte')
    5120

It should rather be:

    >>> parse_size('1 KiB')
    1024
    >>> parse_size('5 kibibyte')
    5120
    >>> parse_size('1.5 GiB')
    1610612736
    >>> parse_size('1 KB')
    1000
    >>> parse_size('5 kilobyte')
    5000
    >>> parse_size('1.5 GB')
    1000000000

i know it will complicate parsing because you can't assume that the first letter is enough to tell them apart, but maybe check the two first letters? :)

see https://en.wikipedia.org/wiki/Kibibyte for more details.

concatenate - serial comma incorrectly used with two items

Per Wikipedia, a serial comma is

a comma placed immediately after the penultimate term... in a series of three or more terms

We would therefore expect that a serial comma would not be placed by concatenate() when given a sequence of two items, but this is not the case.

Expected:

>>> humanfriendly.text.concatenate(items=["foo", "bar"], serial_comma=True)
'foo and bar'

Actual:

>>> humanfriendly.text.concatenate(items=["foo", "bar"], serial_comma=True)
'foo, and bar'

Workaround:

>>> items = ["foo", "bar"]
>>> humanfriendly.text.concatenate(items=items, serial_comma=len(items) > 2)
'foo and bar'

test failures with pytest7: AttributeError: module 'humanfriendly.tests' has no attribute 'connect'

Hello,
in debian we recently started the upgrade to pytest7, and now humanfriendly tests are failing with the error below:

# python3 -m pytest humanfriendly/tests.py::HumanFriendlyTestCase::test_touch --verbose
============================================================================================================================= test session starts ==============================================================================================================================
platform linux -- Python 3.10.5, pytest-7.1.2, pluggy-1.0.0 -- /usr/bin/python3
cachedir: .pytest_cache
rootdir: /build/humanfriendly-10.0, configfile: tox.ini
collected 1 item                                                                                                                                                                                                                                                               

humanfriendly/tests.py::HumanFriendlyTestCase::test_touch ERROR                                                                                                                                                                                                          [100%]

======= ERRORS =======
_______ ERROR at setup of HumanFriendlyTestCase.test_touch _______

app = <module 'humanfriendly.tests' from '/build/humanfriendly-10.0/humanfriendly/tests.py'>

    def setup(app):
        """
        Enable all of the provided Sphinx_ customizations.
    
        :param app: The Sphinx application object.
    
        The :func:`setup()` function makes it easy to enable all of the Sphinx
        customizations provided by the :mod:`humanfriendly.sphinx` module with the
        least amount of code. All you need to do is to add the module name to the
        ``extensions`` variable in your ``conf.py`` file:
    
        .. code-block:: python
    
           # Sphinx extension module names.
           extensions = [
               'sphinx.ext.autodoc',
               'sphinx.ext.doctest',
               'sphinx.ext.intersphinx',
               'humanfriendly.sphinx',
           ]
    
        When Sphinx sees the :mod:`humanfriendly.sphinx` name it will import the
        module and call its :func:`setup()` function. This function will then call
        the following:
    
        - :func:`enable_deprecation_notes()`
        - :func:`enable_man_role()`
        - :func:`enable_pypi_role()`
        - :func:`enable_special_methods()`
        - :func:`enable_usage_formatting()`
    
        Of course more functionality may be added at a later stage. If you don't
        like that idea you may be better of calling the individual functions from
        your own ``setup()`` function.
        """
        from humanfriendly import __version__
    
>       enable_deprecation_notes(app)

humanfriendly/sphinx.py:250: 
_ _ _ _ _

app = <module 'humanfriendly.tests' from '/build/humanfriendly-10.0/humanfriendly/tests.py'>

    def enable_deprecation_notes(app):
        """
        Enable documenting backwards compatibility aliases using the autodoc_ extension.
    
        :param app: The Sphinx application object.
    
        This function connects the :func:`deprecation_note_callback()` function to
        ``autodoc-process-docstring`` events.
    
        .. _autodoc: http://www.sphinx-doc.org/en/stable/ext/autodoc.html
        """
>       app.connect("autodoc-process-docstring", deprecation_note_callback)
E       AttributeError: module 'humanfriendly.tests' has no attribute 'connect'

humanfriendly/sphinx.py:112: AttributeError
======= short test summary info =======
ERROR humanfriendly/tests.py::HumanFriendlyTestCase::test_touch - AttributeError: module 'humanfriendly.tests' has no attribute 'connect'
======= 1 error in 0.12s =======

i tried for a while to figure out what's going on but i didnt manage to find the reason: can you help me out? thanks!

please note that running the test suite with pytest 6.2.5, it passes just fine, so it has to be something specific to python 7 (we're using 7.1.2 ftr)

File sizes with thousand separators

I'm trying to parse file sizes with thousands separators, but having no luck. With humanfriendly==9.0, I get the following:

$ python -i
Python 3.8.5 (default, Oct  6 2020, 07:21:17) 
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import humanfriendly
>>> humanfriendly.parse_size("1,067.6 KB")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "vendor/lib/python3.8/site-packages/humanfriendly/__init__.py", line 259, in parse_size
    raise InvalidSize(format(msg, size, tokens))
humanfriendly.InvalidSize: Failed to parse size! (input '1,067.6 KB' was tokenized as [1, ',', 67.6, 'KB'])

Can humanfriendly handle this? I can't seem to find a way to tell humanfriendly to expect a thousands separator (my data is fairly uniform, the separator is always the same).

Support miliseconds or any other "minimum" unit in format_timespan

If i have a duration small that 1 second, it is displayed as '0 seconds'. Should be able to display at least something like 0.3 second (without the 's'). Maybe with an additional option minimum_unit='milisecond' so it will dispay for example 301 miliseconds.

Thanks

humanfriendly is not pipenv friendly using Python 3.6

Apparently I can't add humanfriendly as a dependency of my pipenv based project that uses Python 3.

To confirm I tried on an empty folder and these are the results:

➜  mkdir t
➜  cd t
➜  pipenv install humanfriendly --three --python /Users/rhymes/.pyenv/shims/python3
Creating a virtualenv for this project…
Using /Users/rhymes/.pyenv/shims/python3 to create virtualenv…
⠋Running virtualenv with interpreter /Users/rhymes/.pyenv/shims/python3
Using base prefix '/Users/rhymes/.pyenv/versions/3.6.4'
New python executable in /Users/rhymes/.local/share/virtualenvs/t-fxF068Zy/bin/python3
Also creating executable in /Users/rhymes/.local/share/virtualenvs/t-fxF068Zy/bin/python
Installing setuptools, pip, wheel...done.

Virtualenv location: /Users/rhymes/.local/share/virtualenvs/t-fxF068Zy
Creating a Pipfile for this project…
Installing humanfriendly…
Collecting humanfriendly
  Downloading humanfriendly-4.8-py2.py3-none-any.whl (68kB)
Installing collected packages: humanfriendly
Successfully installed humanfriendly-4.8

Adding humanfriendly to Pipfile's [packages]…
Pipfile.lock not found, creating…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
tched/piptools/resolver.py", line 279, in _iter_dependencies
    for dependency in self.repository.get_dependencies(ireq):
  File "/Users/rhymes/.pyenv/versions/3.6.4/lib/python3.6/site-packages/pipenv/patched/piptools/repositories/pypi.py", line 162, in get_dependencies
    legacy_results = self.get_legacy_dependencies(ireq)
  File "/Users/rhymes/.pyenv/versions/3.6.4/lib/python3.6/site-packages/pipenv/patched/piptools/repositories/pypi.py", line 199, in get_legacy_dependencies
    result = reqset._prepare_file(self.finder, ireq)
  File "/Users/rhymes/.pyenv/versions/3.6.4/lib/python3.6/site-packages/pipenv/patched/pip/req/req_set.py", line 639, in _prepare_file
    abstract_dist.prep_for_dist()
  File "/Users/rhymes/.pyenv/versions/3.6.4/lib/python3.6/site-packages/pipenv/patched/pip/req/req_set.py", line 134, in prep_for_dist
    self.req_to_install.run_egg_info()
  File "/Users/rhymes/.pyenv/versions/3.6.4/lib/python3.6/site-packages/pipenv/patched/pip/req/req_install.py", line 438, in run_egg_info
    command_desc='python setup.py egg_info')
  File "/Users/rhymes/.pyenv/versions/3.6.4/lib/python3.6/site-packages/pipenv/patched/pip/utils/__init__.py", line 707, in call_subprocess
    % (command_desc, proc.returncode, cwd))
pip.exceptions.InstallationError: Command "python setup.py egg_info" failed with error code 1 in /var/folders/qc/c_sksnns54q13ympksl8x4h00000gp/T/tmpr9106y6sbuild/importlib/

➜  pipenv install humanfriendly --two
Creating a virtualenv for this project…
Using /Users/rhymes/.pyenv/versions/2.7.14/bin/python2 to create virtualenv…
⠋Running virtualenv with interpreter /Users/rhymes/.pyenv/versions/2.7.14/bin/python2
New python executable in /Users/rhymes/.local/share/virtualenvs/t-fxF068Zy/bin/python2
Also creating executable in /Users/rhymes/.local/share/virtualenvs/t-fxF068Zy/bin/python
Installing setuptools, pip, wheel...done.

Virtualenv location: /Users/rhymes/.local/share/virtualenvs/t-fxF068Zy
Creating a Pipfile for this project…
Installing humanfriendly…
Collecting humanfriendly
  Downloading humanfriendly-4.8-py2.py3-none-any.whl (68kB)
Collecting monotonic; python_version == "2.6" or python_version == "2.7" or python_version == "3.0" or python_version == "3.1" or python_version == "3.2" (from humanfriendly)
  Downloading monotonic-1.4-py2.py3-none-any.whl
Installing collected packages: monotonic, humanfriendly
Successfully installed humanfriendly-4.8 monotonic-1.4

Adding humanfriendly to Pipfile's [packages]…
Pipfile.lock (e41dbe) out of date, updating to (4737be)…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Updated Pipfile.lock (4737be)!
Installing dependencies from Pipfile.lock (4737be)…
  🐍   ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 2/2 — 00:00:00
To activate this project's virtualenv, run the following:
 $ pipenv shell

As you can see it works with Python 2.7 but not with Python 3.6. I have tried with different Python 3.6 minor versions but same error.

I am using pipenv 11.0.2.

Thanks

Milliseconds are represented separately even when "detailed" is set to False

Hi,

The documentation says:

detailed – If True milliseconds are represented separately instead of being represented as fractional seconds (defaults to False).

But in some cases milliseconds are displayed anyway:

>>> import humanfriendly as hf

>>> hf.format_timespan(59.99)
'59.99 seconds'

>>> hf.format_timespan(61.10)
'1 minute, 1 second and 100 milliseconds'

>>> hf.format_timespan(61.10, False)
'1 minute, 1 second and 100 milliseconds'

>>> hf.format_timespan(3600 * 123 + .456)
'5 days, 3 hours and 456 milliseconds'

humanfriendly.Timer won't work properly if the system clock changes

If the system clock changes while the Timer class is busy timing something, it won't track the elapsed time correctly. This could happen if daylight saving kicks in, or if someone travels across a border and their timezone changes, or for any number of other reasons, such as a NTP client kicking in and changing the time. A great example of this can be found in this video by Tom Scott: https://www.youtube.com/watch?v=QCwpVtqcqNE

The solution is to use a monotonic clock to track the time. Fortunately, python has built-in support for monotonic clocks: https://docs.python.org/3/library/time.html?highlight=time.monotonic#time.monotonic
There is also a polyfill available for when time.monotonic isn't available: https://pypi.python.org/pypi/monotonic

It would be great if Timer could be adjusted to use a monotonic clock so that it can properly track the elapsed time regardless of its conditions of use.

hide seconds

Hi there,

I was wondering how I can hide seconds with humanfriendly? Im just interested in Years, Days, Hours, Minutes.

Thanks for your help!

Cache prevents re-enabling ANSI support when a subprocess has disabled it

Problem description

Using subprocess on Windows can break the colored output of coloredlogs if the new process modifies the console mode. Unfortunately, this seems to happen quite a lot, and the caching applied to enable_ansi_support() prevents the end-user from turning it back on using this function. The cache is effectively invalid after every subprocess.Popen because of this.

Reproduction program given below.

Possible fix

Python 3.8 adds audit hooks that would allow this cache to be invalidated whenever subprocess is being used on Windows. If the relevant ANSI functionality in humanfriendly called enable_ansi_support() before producing output, the reenable_ansi() function defined in the program below could be installed as an audit hook to automatically resolve the problem. Whether or not that's something humanfriendly would want to do is up to the maintainer(s), but if so I would be happy to submit a PR to do this. If not, hopefully this trick helps out any users who stub their toe on the same bug 🙂

import sys

if sys.version_info > (3, 8):
    def reenable_ansi_hook(event, args):
        if event == "subprocess.Popen":
            reenable_ansi()  # defined below

    sys.addaudithook(reenable_ansi_hook)

Reproduction program

import logging
import subprocess

import coloredlogs


logger = logging.getLogger(__name__)
coloredlogs.install()

logger.info(f"This line should have working ANSI")
subprocess.check_output(["echo"])  # changes the console mode on Windows 10

logger.info(f"This line should have broken ANSI")
subprocess.check_output(["echo"])

coloredlogs.enable_ansi_support()  # does NOT enable ANSI support because the cache is now invalid
logger.info(f"This line should have working ANSI again")


def reenable_ansi():
    try:
        # invalidate the cache, if necessary
        del coloredlogs.enable_ansi_support.cached_results
    except NameError:
        pass
    coloredlogs.enable_ansi_support()


subprocess.check_output(["echo"])
reenable_ansi()
logger.info(f"This line should have working ANSI again")

Screenshot of Win10 output

--demo fails under python3

A couple of tiny python3 incompatibilities running humanfriendly --demo::

Traceback (most recent call last):
  File "./bin/humanfriendly", line 11, in <module>
    sys.exit(main())
  File "/b/lib/python3.6/site-packages/humanfriendly/cli.py", line 157, in main
    partial()
  File "/b/lib/python3.6/site-packages/humanfriendly/cli.py", line 244, in demonstrate_ansi_formatting
    ] for color_name in sorted(ANSI_COLOR_CODES.keys())
  File "/b/lib/python3.6/site-packages/humanfriendly/cli.py", line 244, in <listcomp>
    ] for color_name in sorted(ANSI_COLOR_CODES.keys())
  File "/b/lib/python3.6/site-packages/humanfriendly/cli.py", line 243, in <listcomp>
    ) for label, kw in intensities
TypeError: unsupported operand type(s) for +: 'dict_items' and 'list'

Fixing that then produces::

Traceback (most recent call last):
  File "./bin/humanfriendly", line 11, in <module>
    sys.exit(main())
  File "/b/lib/python3.6/site-packages/humanfriendly/cli.py", line 157, in main
    partial()
  File "/b/lib/python3.6/site-packages/humanfriendly/cli.py", line 251, in demonstrate_ansi_formatting
    demonstrate_256_colors(16, 231, '216 colors')
  File "/b/lib/python3.6/site-packages/humanfriendly/cli.py", line 274, in demonstrate_256_colors
    blocks = [colors[n:n + colors_per_line] for n in range(0, len(colors), colors_per_line)]
TypeError: 'float' object cannot be interpreted as an integer

A quick patch to fix::

--- /b/lib/python3.6/site-packages/humanfriendly/cli.py	2018-05-03 11:52:36.629392862 +1000
+++ ./cli.py	2018-05-03 11:51:53.161390713 +1000
@@ -242 +242 @@
-                    **dict(kw.items() + [(color_type, color_name)])
+                    **dict(list(kw.items()) + [(color_type, color_name)])
@@ -272 +272 @@
-        colors_per_line = columns / width
+        colors_per_line = int(columns / width)

Cheers.

parse_size does not distinguish between bits and bytes

humanfriendly (as of version 9.2) does not currently appear to differentiate between lower case 'b' to indicate bits and upper case 'B' to indicate bytes as per the abbreviation conventions.

For example I would expect the following comparisons to be False:

>>> humanfriendly.parse_size('10Gb') == humanfriendly.parse_size('10GB')
True

>>> humanfriendly.parse_size('10 gigabits') == humanfriendly.parse_size('10 gigabytes')
True

Furthermore, the following is just plain wrong:

>>> humanfriendly.parse_size('16 bits')  # should return the size in bytes as per docstring => 16 / 2**3 = 2 bytes
16

Is it possible to extend humanfriendly to recognise bit representations as well as bytes when supplying a size string?

error: Duplicate module named "humanfriendly.terminal.html"

Hello! Thank you very match for this package. I am using mypy for type checking in my project. Before run mypy I call stubgen for generate stubs for my deps. When I run: stubgen --ignore-error -o /tmp/stubs/ -phumanfriendly I get error:

Critical error during semantic analysis: /home/ikrivosheev/.pyenv/versions/3.9.9/envs/ptms-3.9/lib/python3.9/site-packages/humanfriendly/terminal/html.py: error: Duplicate module named "humanfriendly.terminal.html" (also at "/home/ikrivosheev/.pyenv/versions/3.9.9/envs/ptms-3.9/lib/python3.9/site-packages/humanfriendly/terminal/html.py")

Using prompt_for_confirmation fails with ModuleNotFoundError on Windows

Using the humanfriendly.prompts.prompt_for_confirmation() function on Windows fails with a ModuleNotFoundError for 'readline'.

Python: 3.6.0 64-bit
Humanfriendly: 4.4.1 (Installed from PyPI using pip)

cmd>python
Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 08:06:12) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import humanfriendly.prompts
>>> humanfriendly.prompts.prompt_for_confirmation("Testing...", default=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Program Files\Python36\lib\site-packages\humanfriendly\prompts.py", line 86, in prompt_for_confirmation
    reply = prompt_for_input(prompt_text, '', padding=padding, strip=True)
  File "C:\Program Files\Python36\lib\site-packages\humanfriendly\prompts.py", line 245, in prompt_for_input
    prepare_friendly_prompts()
  File "C:\Program Files\Python36\lib\site-packages\humanfriendly\prompts.py", line 328, in prepare_friendly_prompts
    import readline  # NOQA
ModuleNotFoundError: No module named 'readline'

This is likely due to GNU readline not being available on Windows.

The application I'm using humanfriendly with needs to work on Windows, so it would be nice if there was an option to disable readline usage when the import fails.

ModuleNotFoundError: No module named 'humanfriendly'

I installed humanfriendly so that my discord bot's mute command is usable as a tempmute command too. However, for some reason, even tho if I type humanfriendly into the console and it actually shows the help message

root@vmi476883:~/dom/JixBot# humanfriendly
Usage: humanfriendly [OPTIONS]

Human friendly input/output (text formatting) on the command
line based on the Python package with the same name.

it gives me this error: ModuleNotFoundError: No module named 'humanfriendly'. what should I do?

Requirement for unittest2

Hi. I'm curious why unittest2 is added as a required package. Since unittest2 may run into problems when built as a wheel (nix-community/pypi2nix#135), it's hard to use humanfriendly, which pulls it in. Seems unusual to put a testing package as required.

type error with Python3 in terminal.show_pager

I get a type error when calling terminal.show_pager with Python3.5

>>> from humanfriendly import terminal
>>> terminal.show_pager("1 2 3")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mib/tmp/python-humanfriendly/humanfriendly/terminal.py", line 392, in show_pager
    pager.communicate(input=formatted_text)
  File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/subprocess.py", line 1053, in communicate

    self._stdin_write(input)
  File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/subprocess.py", line 1015, in _stdin_write
    self.stdin.write(input)
TypeError: a bytes-like object is required, not 'str'

issue with raise InvalidSize(format(msg, size, tokens))

Hi Recently been getting an issue getting this error, i thought it was the version so i updated also

Name: humanfriendly
Version: 10.0
Summary: Human friendly output for text interfaces using Python
Home-page: https://humanfriendly.readthedocs.io
Author: Peter Odding
Author-email: [email protected]
License: MIT
Location: /usr/local/lib/python3.5/dist-packages
Requires:

 File "/usr/local/lib/python3.5/dist-packages/humanfriendly/__init__.py", line 258, in parse_size
    raise InvalidSize(format(msg, size, tokens))

this is part of the script

 # Extract Added Bytes
        RLOG_ADDED=$(cat $RLOG | grep 'Added to the repo' | awk '{print $5,$6}' | \
                python3 -c 'import sys; import humanfriendly; print (humanfriendly.parse_size(sys.stdin.read(), binary=True))' )
        arr+=("- rescript.backup.added[$REPO] $TIME $RLOG_ADDED")
        echo "Bytes Added:      $RLOG_ADDED"

and part of the added to the repo was

Added to the repo: 117.726 GiB

could it be its not recognizing the size?

changed the 117.726 Gib to

11.26 GiB and it worked so something odd with the reading ?

Thank you

format_timespan should accept a datetime.timedelta object

I could use to_seconds() to convert a time delta to seconds, but it would be nice if format_timespan did it for me. That way, instead of:

format_timespan((current_time - update_time).total_seconds))

I could just call:

format_timespan(current_time - update_time)

Add changelog to releases please

I could not find a changelog for this project. I looked for one in the following places:

Reason for the request: when I upgrade my projects to the latest versions of the libraries I use, I skim the changelog to see if there is any important new functionality, so I can know if there are any important refactorings of my code that I can now do, or just for future reference.

Without changelog lots of new functionality will just go unused - I only intensively read docs the first time I start using a library, not at every release.

Add a serial comma version of `humanfriendly.text.concatenate`

While the use of the serial (or Oxford) comma is a contentious issue, it is also a popular enough choice that it would be nice to have it supported. I'd certainly be very happy to see the humanfriendly.text.concatenate extended to add it:

  • final_sep="", which could be set to "," for a serial comma person, or
  • serial_comma=False, which could be set to True for the same effect, as well as
  • conjunction="and", which could be set to, for example, "or" to produce a list with that effect.

alternately, support only the conjunction, but set the default to " and", and allow ", and" to produce an serial comma list.

...er, and perhaps come up with better names than I did for keyword parameters, as that is ... not my strongest skill. :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.