Classes and Functions

Inform

The Inform class controls the active informants.

class inform.Inform(mute=False, quiet=False, verbose=False, narrate=False, logfile=False, prev_logfile_suffix=None, error_status=1, prog_name=True, argv=None, version=None, termination_callback=None, colorscheme='dark', flush=False, stdout=None, stderr=None, length_thresh=80, culprit_sep=', ', stream_policy='termination', notify_if_no_tty=False, notifier='notify-send', **kwargs)[source]

Manages all informants, which in turn handle user messaging. Generally informants copy messages to the logfile while most also send to the standard output as well, however all is controllable.

Parameters:
  • mute (bool) –

    All output is suppressed (it is still logged).

    With the provided informants all output is suppressed when set (it is still logged). This is generally used when the program being run is being run by another program that is generating its own messages and does not want the user confused by additional messages. In this case, the calling program is responsible for observing and reacting to the exit status of the called program.

  • quiet (bool) –

    Normal output is suppressed (it is still logged).

    With the provided informants normal output is suppressed when set (it is still logged). This is used when the user has indicated that they are uninterested in any conversational messages and just want to see the essentials (generally error messages).

  • verbose (bool) –

    Comments are output to user, normally they are just logged.

    With the provided informants comments are output to user when set; normally they are just logged. Comments are generally used to document unusual occurrences that might warrant the user’s attention.

  • narrate (bool) –

    Narration is output to user, normally it is just logged.

    With the provided informants narration is output to user when set, normally it is just logged. Narration is generally used to inform the user as to what is going on. This can help place errors and warnings in context so that they are easier to understand.

  • logfile (path, string, stream, bool) – May be a pathlib path or a string, in which case it is taken to be the path of the logfile. May be True, in which case ./.<prog_name>.log is used. May be an open stream. Or it may be False, in which case no log file is created. It may also be an instance of LoggingCache, which caches the log messages until it is replaced with Inform.set_logfile().

  • prev_logfile_suffix (string) – If specified, the previous logfile will be moved aside before creating the new logfile.

  • error_status (int) – The default exit status to return to the shell when terminating the program due to an error. The default is 1.

  • prog_name (string) – The program name. Is appended to the message headers and used to create the default logfile name. May be a string, in which case it is used as the name of the program. May be True, in which case basename(argv[0]) is used. May be False to indicate that program name should not be added to message headers.

  • argv (list of strings) – System command line arguments (logged). By default, sys.argv is used. If False is passed in, argv is not logged and argv[0] is not available to be the program name.

  • version (string) – program version (logged if provided).

  • termination_callback (func) – A function that is called at program termination. This function is called before the logfile is closed and is only called if Inform processes the program termination. If you want to register a function to run regardless of how the program exit is processed, use the atexit module.

  • colorscheme (None, ‘light’, or ‘dark’) – Color scheme to use. None indicates that messages should not be colorized. Colors are not used if desired output stream is not a TTY.

  • flush (bool) – Flush the stream after each write. Is useful if your program is crashing, causing loss of the latest writes. Can cause programs to run considerably slower if they produce a lot of output. Not available with python2.

  • stdout (stream) – Messages are sent here by default. Generally used for testing. If not given, sys.stdout is used.

  • stderr (stream) – Exceptional messages are sent here by default. Exceptional message include termination messages and possibly error messages (depends on stream_policy). Generally used for testing. If not given, sys.stderr is used.

  • length_thresh (integer) – Split header from body if line length would be greater than this threshold.

  • culprit_sep (string) – Join string used for culprit collections. Default is ‘, ‘.

  • stream_policy (string or func) –

    The default stream policy, which determines which stream each informant uses by default (which stream is used if the stream is not specifically specified when the informant is created).

    The following named policies are available:
    ’termination’:

    stderr is used for the final termination message. stdout is used otherwise. This is generally used for programs that are not filters (the output is largely status rather than data that might be fed into another program through a pipeline).

    ’header’:

    stderr is used for all messages with headers/severities. stdout is used otherwise. This is generally used for programs that act as filters (the output is largely data that might be fed into another program through a pipeline). In this case stderr is used for error messages so they do not pollute the data stream.

    May also be a function that returns the stream and takes three arguments: the active informant, Inform’s stdout, and Inform’s stderr.

    If no stream is specified, either explicitly on the informant when it is defined, or through the stream policy, then Inform’s stdout is used.

  • notify_if_no_tty (bool) – If it appears that an error message is expecting to displayed on the console but the standard output is not a TTY send it to the notifier if this flag is True.

  • notifier (str) – Command used to run the notifier. The command will be called with two arguments, the header and the body of the message.

  • **kwargs – Any additional keyword arguments are made attributes that are ignored by Inform, but may be accessed by the informants.

add_culprit(culprit)[source]

Add to the currently saved culprit.

Similar to Inform.set_culprit() except that this method appends the given culprit to the cached culprit rather than simply replacing it.

Parameters:

culprit (string, number or tuple of strings and numbers) – A culprit or collection of culprits that are cached with the intent that they be available to be included in a message upon demand. They generally are used to indicate what a message refers to.

This function is designed to work as a context manager, meaning that it meant to be used with Python’s with statement. It temporarily replaces any existing culprit, but that culprit in reinstated upon exiting the with statement. Once a culprit is saved, inform.Inform.get_culprit() is used to access it.

See Inform.set_culprit() for an example of a closely related method.

close_logfile(status=None)[source]

Close logfile

If status is given, it is taken to be the exit message or exit status.

disconnect()[source]

Disconnect informer, returning to previous informer.

done(exit=True)[source]

Terminate the program with normal exit status.

Parameters:

exit (bool) – If False, all preparations for termination are done, but sys.exit() is not called. Instead, the exit status is returned.

Returns:

The desired exit status is returned if exit is False (the function does not return if exit is True).

errors_accrued(reset=False)[source]

Returns number of errors that have accrued.

Parameters:

reset (bool) – Reset the error count to 0 if True.

flush_logfile()[source]

Flush the logfile.

get_culprit(culprit=None)[source]

Get the current culprit.

Return the currently cached culprit as a tuple. If a culprit is specified as an argument, it is appended to the cached culprit without modifying it.

Parameters:

culprit (string, number or tuple of strings and numbers) – A culprit or collection of culprits that is appended to the return value without modifying the cached culprit.

Returns:

The culprit argument is appended to the cached culprit and the combination is returned. The return value is always in the form of a tuple even if there is only one component.

See Inform.set_culprit() for an example use of this method.

get_prog_name()[source]

Returns the program name.

join_culprit(culprit)[source]

Join the specified culprits with the current culprit separators.

Culprits are returned from the informer or for exceptions as a tuple. This function allows you to join those culprits into a string.

Parameters:

culprit (tuple of strings or numbers) –

Returns:

The culprit tuple joined into a string.

set_culprit(culprit)[source]

Set the culprit while temporarily displacing current culprit.

Squirrels away a culprit for later use. Any existing culprit is moved out of the way.

Parameters:

culprit (string, number or tuple of strings and numbers) – A culprit or collection of culprits that are cached with the intent that they be available to be included in a message upon demand. They generally are used to indicate what a message refers to.

This function is designed to work as a context manager, meaning that it meant to be used with Python’s with statement. It temporarily replaces any existing saved culprit, but that culprit in reinstated upon exiting the with statement. Once a culprit is saved, inform.Inform.get_culprit() is used to access it.

Example:

>>> from inform import get_culprit, set_culprit, warn

>>> def count_lines(lines):
...    empty = 0
...    for lineno, line in enumerate(lines):
...        if not line:
...            warn('empty line.', culprit=get_culprit(lineno+1))

>>> filename = 'pyproject.toml'
>>> with open(filename) as f, set_culprit(filename):
...    lines = f.read().splitlines()
...    num_lines = count_lines(lines)
warning: pyproject.toml, 25: empty line.
warning: pyproject.toml, 33: empty line.
warning: pyproject.toml, 39: empty line.
set_logfile(logfile, prev_logfile_suffix=None, encoding='utf-8')[source]

Allows you to change the logfile (only available as a method).

Parameters:
  • logfile

    May be a pathlib path. May be a string, in which case it is taken to be the path of the logfile. May be True, in which case ./.<prog_name>.log is used. May be an open stream. Or it may be False, in which case no log file is created.

    Directory containing the logfile must exist.

  • prev_logfile_suffix – If specified, the existing logfile will be renamed before creating the new logfile. This only occurs the first time the logfile is specified.

  • encoding (string) – The encoding to use when writing the file.

set_stream_policy(stream_policy)[source]

Allows you to change the stream policy (see inform.Inform).

suppress_output(mute=True)[source]

Allows you to change the mute flag (only available as a method).

Parameters:

mute (bool) – If mute is True all output is suppressed (it is still logged).

terminate(status=None, exit=True)[source]

Terminate the program with specified exit status.

Parameters:
  • status (int, bool, string, or None) – The desired exit status or exit message. Exit status is inform.error_status if True is passed in. When None, return inform.error_status if errors occurred and 0 otherwise. Status may also be a string, in which case it is printed to stderr without a header and the exit status is inform.error_status.

  • exit (bool) – If False, all preparations for termination are done, but sys.exit() is not called. Instead, the exit status is returned.

Returns:

The desired exit status is returned if exit is False (the function does not return if exit is True).

Recommended status codes:
0: success
1: unexpected error
2: invalid invocation
3: panic
Of, if your program naturally want to signal pass or failure using its exit status:
0: success
1: failure
2: error
3: panic
terminate_if_errors(status=None, exit=True)[source]

Terminate the program if error count is nonzero.

Parameters:
  • status (int, bool or string) – The desired exit status or exit message.

  • exit (bool) – If False, all preparations for termination are done, but sys.exit() is not called. Instead, the exit status is returned.

Returns:

None is returned if there is no errors, otherwise the desired exit status is returned if exit is False (the function does not return if there is an error and exit is True).

Direct Access Functions

Several of the above methods are also available as stand-alone functions that act on the currently active informer. This make it easy to use their functionality even if you do not have local access to the informer.

inform.done(exit=True)[source]

Terminate the program with normal exit status.

Calls inform.Inform.done() for the active informer.

inform.terminate(status=None, exit=True)[source]

Terminate the program with specified exit status.”

Calls inform.Inform.terminate() for the active informer.

inform.terminate_if_errors(status=None, exit=True)[source]

Terminate the program if error count is nonzero.”

Calls inform.Inform.terminate_if_errors() for the active informer.

inform.errors_accrued(reset=False)[source]

Returns number of errors that have accrued.”

Calls inform.Inform.errors_accrued() for the active informer.

inform.get_prog_name()[source]

Returns the program name.

Calls inform.Inform.get_prog_name() for the active informer.

inform.set_culprit(culprit)[source]

Set the culprit while displacing current culprit.

Calls inform.Inform.set_culprit() for the active informer.

inform.add_culprit(culprit)[source]

Append to the end of the current culprit.

Calls inform.Inform.add_culprit() for the active informer.

inform.get_culprit(culprit=None)[source]

Get the current culprit.

Calls inform.Inform.get_culprit() for the active informer.

You can also request the active informer:

inform.get_informer()[source]

Returns the active informer.

InformantFactory

class inform.InformantFactory(**kwargs)[source]

Create informants.

An object of InformantFactory is referred to as an informant. It is generally treated as a function that is called to produce the desired output.

Parameters:
  • severity (string) – Messages with severities get headers. The header consists of the severity, the program name (if desired), and the culprit (if provided). If the message text does not contain a newline it is appended to the header. Otherwise the message text is indented and placed on the next line.

  • is_error (bool) – Message is counted as an error.

  • log (bool) – Send message to the log file. May be a boolean or a function that accepts the informer as an argument and returns a boolean.

  • output (bool) – Send message to the output stream. May be a boolean or a function that accepts the informer as an argument and returns a boolean.

  • notify (bool) – Send message to the notifier. The notifier will display the message that appears temporarily in a bubble at the top of the screen. May be a boolean or a function that accepts the informer as an argument and returns a boolean.

  • terminate (bool or integer) – Terminate the program. Exit status is the value of terminate unless terminate is True, in which case 1 is returned if an error occurred and 0 otherwise.

  • is_continuation (bool) – This message is a continuation of the previous message. It will use the properties of the previous message (output, log, message color, etc) and if the previous message had a header, that header is not output and instead the message is indented.

  • message_color (string) – Color used to display the message. Choose from: black, red, green, yellow, blue, magenta, cyan or white.

  • header_color (string) – Color used to display the header, if one is produced. Choose from: black, red, green, yellow, blue, magenta, cyan or white.

  • stream (stream) – Output stream to use. Typically sys.stdout or sys.stderr. If not specified, the stream to use will be determine by stream policy of active informer.

  • clone (informant) – Clone the attributes of the given informer. Any explicitly specified arguments override those acquired through cloning.

Example:

The following generates two informants, passes, which prints its messages in green, and fails, which prints its messages in red. Output to the standard output for both is suppressed if quiet is True:

>>> from inform import InformantFactory, display

>>> success = InformantFactory(
...     clone = display,
...     severity = 'Pass',
...     header_color = 'green'
... )
>>> failure = InformantFactory(
...     clone = display,
...     severity = 'FAIL',
...     header_color = 'red'
... )

success and failure are both informants. Once created, they can be used to give messages to the user:

>>> results = [
...     (0,   0.005, 0.025),
...     (0.5, 0.512, 0.025),
...     (1,   0.875, 0.025),
... ]
>>> for expected, measured, tolerance in results:
...     if abs(expected - measured) > tolerance:
...         report = failure
...     else:
...         report = success
...     report(
...         measured, expected, measured-expected,
...         template='measured = {:.3f}V, expected = {:.3f}V, diff = {:.3f}V'
...     )
Pass: measured = 0.005V, expected = 0.000V, diff = 0.005V
Pass: measured = 0.512V, expected = 0.500V, diff = 0.012V
FAIL: measured = 0.875V, expected = 1.000V, diff = -0.125V

In the console ‘Pass’ is rendered in green and ‘FAIL’ in red.

Inform Utilities

class inform.Color(color, *, scheme=True, enable=True)[source]

Used to create colorizers, which are used to render text in a particular color.

Parameters:
  • color (string) – The desired color. Choose from: black red green yellow blue magenta cyan white.

  • scheme (string) – Use the specified colorscheme when rendering the text. Choose from None, ‘light’ or ‘dark’, default is ‘dark’.

  • enable (bool) – If set to False, the colorizer does not render the text in color.

Example:

>>> from inform import Color
>>> fail = Color('red')

In this example, fail is a colorizer. It behave just like inform.join() in that it combines its arguments into a string that it returns. The difference is that colorizers add color codes that will cause most terminals to display the string in the desired color.

Like inform.join(), colorizers take the following arguments:

unnamed arguments:

The unnamed arguments are converted to strings and joined to form the text to be colored.

sep = ‘ ‘:

The join string, used when joining the unnamed arguments.

template = None:

A template that if present interpolates the arguments to form the final message rather than simply joining the unnamed arguments with sep. The template is a string, and its format method is called with the unnamed and named arguments of the message passed as arguments.

wrap = False:

Specifies whether message should be wrapped. wrap may be True, in which case the default width of 70 is used. Alternately, you may specify the desired width. The wrapping occurs on the final message after the arguments have been joined.

scheme = False:

Use to override the colorscheme when rendering the text. Choose from None, False, ‘light’ or ‘dark’. If you specify False (the default), the colorscheme specified when creating the colorizer is used.

static isTTY(stream=<_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>)[source]

Takes a stream as an argument and returns true if it is a TTY.

Parameters:

stream (stream) – Stream to test. If not given, stdout is used as the stream.

Example:

>>> from inform import Color, display
>>> import sys, re

>>> if Color.isTTY(sys.stdout):
...     emphasize = Color('magenta')
... else:
...     emphasize = str.upper

>>> def highlight(matchobj):
...     return emphasize(matchobj.group(0))

>>> display(re.sub('your', highlight, 'Imagine your city without cars.'))
Imagine YOUR city without cars.
classmethod strip_colors(text)[source]

Takes a string as its input and return that string stripped of any color codes.

class inform.LoggingCache[source]

Use as logfile if you cannot know the desired location of the logfile until after log messages have been emitted. It holds the log messages in memory until you establish a logfile. At that point the messages are copied into the logfile.

Example:

>>> from inform import Inform, LoggingCache, log, indent
>>> with Inform(logfile=LoggingCache()) as inform:
...     log("This message is cached.")
...     inform.set_logfile(".mylog")
...     log("This message is not cached.")

>>> with open(".mylog") as f:
...     print("Contents of logfile:")
...     print(indent(f.read()), end='')  # +ELLIPSIS
Contents of logfile:
    ...: invoked as: ...
    ...: log opened on ...
    This message is cached.
    This message is not cached.
inform.cull(collection, **kwargs)[source]

Cull items of a particular value from a collection.

Parameters:
  • collection – The collection may be list-like (list, tuples, sets, etc.) or dictionary-like (dict, OrderedDict, etc.). A new collection of the same type is returned with the undesirable values removed.

  • remove

    Must be specified as keyword argument. May be a function, a collection, or a scalar. The function would take a single argument, one of the values in the collection, and return True if the value should be culled. The scalar or the collection simply specified the specific value or values to be culled.

    If remove is not specified, the value is culled if its value would be False when cast to a boolean (0, False, None, ‘’, (), [], {}, etc.)

Example:

>>> from inform import cull, display
>>> from collections import OrderedDict
>>> fruits = OrderedDict([
...    ('a','apple'), ('b','banana'), ('c','cranberry'), ('d','date'),
...    ('e',None), ('f',None), ('g','guava'),
... ])
>>> display(*cull(list(fruits.values())), sep=', ')
apple, banana, cranberry, date, guava

>>> for k, v in cull(fruits).items():
...     display('{k} is for {v}'.format(k=k, v=v))
a is for apple
b is for banana
c is for cranberry
d is for date
g is for guava
inform.indent(text, leader='    ', first=0, stops=1, sep='\n')[source]

Add indentation.

Parameters:
  • leader (string) – the string added to be beginning of a line to indent it.

  • first (integer) – number of indentations for the first line relative to others (may be negative but (first + stops) should not be).

  • stops (integer) – number of indentations (number of leaders to add to the beginning of each line).

  • sep (string) – the string used to separate the lines

Example:

>>> from inform import display, indent
>>> display(indent('And the answer is ...\n42!', first=-1))
And the answer is ...
    42!
inform.is_collection(obj)[source]

Identifies objects that can be iterated over, excluding strings.

Returns True if argument is a collection (tuple, list, set or dictionary).

Example:

>>> from inform import is_collection
>>> is_collection('')  # string
False

>>> is_collection([])  # list
True

>>> is_collection(())  # tuple
True

>>> is_collection({})  # dictionary
True
inform.is_iterable(obj)[source]

Identifies objects that can be iterated over, including strings.

Returns True if argument is a collecton or a string.

Example:

>>> from inform import is_iterable
>>> is_iterable('abc')
True

>>> is_iterable(['a', 'b', 'c'])
True
inform.is_mapping(obj)[source]

Identifies objects that are mappings (are dictionary like).

Returns True if argument is a mapping.

Example:

>>> from inform import is_mapping
>>> is_mapping('')  # string
False

>>> is_mapping([])  # list
False

>>> is_mapping(())  # tuple
False

>>> is_mapping({})  # dictionary
True
inform.is_str(arg)[source]

Identifies strings in all their various guises.

Returns True if argument is a string.

Example:

>>> from inform import is_str
>>> is_str('abc')
True

>>> is_str(['a', 'b', 'c'])
False

User Utilities

class inform.Info(**kwargs)[source]

Generic Data Structure Class

When instantiated, it converts the provided keyword arguments to attributes. Unknown attributes evaluate to None.

Example:

>>> class Orwell(Info):
...     pass

>>> george = Orwell(peace='war', freedom='slavery', ignorance='strength')
>>> print(str(george))
Orwell(
    peace='war',
    freedom='slavery',
    ignorance='strength',
)

>>> george.peace
'war'

>>> george.happiness
render(template)[source]

Render class to a string

Parameters:

template (str) – The template string is returned with any instances of {name} replaced by the value of the corresponding attribute.

Example:

>>> george.render('Peace is {peace}. Freedom is {freedom}. Ignorance is {ignorance}.')
'Peace is war. Freedom is slavery. Ignorance is strength.'
class inform.ProgressBar(stop, start=0, *, log=False, prefix=None, width=79, informant=True, markers={})[source]

Draw a progress bar.

Parameters:
  • stop (float, iterable) – The last expected value. May also be an iterable (list, tuple, iterator, etc), in which case the ProgressBar becomes an interable and start and log are ignored.

  • start (float) – The first expected value. May be greater than or less than stop, but it must not equal stop. Must be specified and must be nonzero and the same sign as stop if log is True.

  • log (bool) – Report the logarithmic progress (start and stop must be positive and nonzero).

  • prefix (str) – A string that is output before the progress bar on the same line.

  • width (int) – The maximum width of the bar, the largest factor of 10 that is less than or equal to this value is used.

  • informant (informant) – Which informant to use when outputting the progress bar. By default, inform.display() is used. Passing None or False as informant suppresses the display of the progress bar.

  • markers (dict) –

    This argument is used to associate a marker name with a pair of values, a character and a color. If a known marker name is passed to draw(), the resulting update is rendered using the matching fill character and color. The color may be specified as a string (the color name), a Color object, or None (uncolored).

    Markers should be given in order of increasing priority. If two different markers appear on non-printing updates, the one that is closer to the end of the dictionary is used on the next printing update.

There are three typical use cases. First, use to illustrate the progress through an iterator:

for item in ProgressBar(items):
    process(item)

Second, use to illustrate the progress through a fixed number of items:

for i in ProgressBar(50):
    process(i)

Lastly, to illustrate the progress through a continuous range:

stop = 1e-6
step = 1e-9
with ProgressBar(stop) as progress:
    value = 0
    while value <= stop:
        progress.draw(value)
        value += step

It produces a bar that grows in order to indicate progress. After progress is complete, it will have produced the following:

⋅⋅⋅⋅⋅⋅9⋅⋅⋅⋅⋅⋅8⋅⋅⋅⋅⋅⋅7⋅⋅⋅⋅⋅⋅6⋅⋅⋅⋅⋅⋅5⋅⋅⋅⋅⋅⋅4⋅⋅⋅⋅⋅⋅3⋅⋅⋅⋅⋅⋅2⋅⋅⋅⋅⋅⋅1⋅⋅⋅⋅⋅⋅0

It coordinates with the informants so that interruptions are handled cleanly:

⋅⋅⋅⋅⋅⋅9⋅⋅⋅⋅⋅⋅8⋅⋅⋅⋅⋅⋅7⋅⋅⋅⋅
warning: the sky is falling.
⋅⋅⋅⋅⋅⋅9⋅⋅⋅⋅⋅⋅8⋅⋅⋅⋅⋅⋅7⋅⋅⋅⋅⋅⋅6⋅⋅⋅⋅⋅⋅5⋅⋅⋅⋅⋅⋅4⋅⋅⋅⋅⋅⋅3⋅⋅⋅⋅⋅⋅2⋅⋅⋅⋅⋅⋅1⋅⋅⋅⋅⋅⋅0

This last version can be used to indicate the nature of individual updates. This is usually used to signal that there was a problem with the update. For example, the following example uses both color and fill character to distinguish four types of results: okay, warn, fail, error:

results = 'okay okay okay fail okay fail okay error warn okay'.split()

markers = dict(
    okay=('⋅', 'green'),
    warn=('−', 'yellow'),
    fail=('×', 'magenta'),
    error=('!', 'red')
)
with ProgressBar(len(results), markers=markers) as progress:
    for i in range(len(repos)):
        result = results[i]
        progress.draw(i+1, result)

It produces the following, where each of the types is rendered in the appropriate color:

⋅⋅⋅⋅⋅⋅9⋅⋅⋅⋅⋅⋅8⋅⋅⋅⋅⋅⋅7××××××6⋅⋅⋅⋅⋅⋅5××××××4⋅⋅⋅⋅⋅⋅3!!!!!!2−−−−−−1⋅⋅⋅⋅⋅⋅0
done()[source]

Complete the progress bar.

Not needed if ProgressBar is used with the Python with statement.

draw(abscissa, marker=None)[source]

Draw the progress bar.

escape()[source]

Terminate the progress bar without completing it.

inform.columns(array, pagewidth=79, alignment='<', leader='    ', min_sep_width=2, min_col_width=1)[source]

Distribute array over enough columns to fill the screen.

Returns a multiline string.

Parameters:
  • array (collection of strings) – The array to be printed.

  • pagewidth (int) – The number of characters available for each line.

  • alignment ('<', '^', or '>') – Whether to left (‘<’), center (‘^’), or right (‘>’) align the array items in their columns.

  • leader (str) – The string to prepend to each line.

  • min_sep_width (int) – The minimum number of spaces between columns. Default is 2.

  • min_col_width (int) – The minimum number of spaces between columns. Default is 1.

Example:

>>> from inform import columns, display, full_stop
>>> title = 'The NATO phonetic alphabet:'
>>> words = '''
...     Alfa Bravo Charlie Delta Echo Foxtrot Golf Hotel India Juliett
...     Kilo Lima Mike November Oscar Papa Quebec Romeo Sierra Tango
...     Uniform Victor Whiskey X-ray Yankee Zulu
... '''.split()
>>> newline = '''
... '''
>>> display(title, columns(words), sep=newline)
The NATO phonetic alphabet:
    Alfa      Echo      India     Mike      Quebec    Uniform   Yankee
    Bravo     Foxtrot   Juliett   November  Romeo     Victor    Zulu
    Charlie   Golf      Kilo      Oscar     Sierra    Whiskey
    Delta     Hotel     Lima      Papa      Tango     X-ray
inform.conjoin(iterable, conj=' and ', sep=', ', end='', fmt=None)[source]

Conjunction join.

Parameters:
  • iterable (list or generator of strings) – The collection of items to be joined. All items are converted to strings.

  • conj (string) – The separator used between the next to last and last values.

  • sep (string) – The separator to use when joining the strings in iterable.

  • end (string) – Is added to the end of the returned string.

  • fmt (string) – A format string used to convert each item in iterable to a string. May be a function, in which case it called on each member of iterable and must return a string. If fmt is not given, str() is used.

Return the items of the iterable joined into a string, where conj is used to join the last two items in the list, and sep is used to join the others.

Examples:

>>> from inform import conjoin, display, Info
>>> display(conjoin([], ' or '))


>>> display(conjoin(['a'], ' or '))
a

>>> display(conjoin(['a', 'b'], ' or '))
a or b

>>> display(conjoin(['a', 'b', 'c']))
a, b and c

>>> display(conjoin([10.1, 32.5, 16.9], fmt='${:0.2f}'))
$10.10, $32.50 and $16.90

>>> characters = dict(
...     bob = 'bob@btca.com',
...     ted = 'ted@btca.com',
...     carol = 'carol@btca.com',
...     alice = 'alice@btca.com',
... )
>>> display(conjoin(characters.items(), fmt='{0[0]:>7} : <{0[1]}>', conj='\n', sep='\n'))
    bob : <bob@btca.com>
    ted : <ted@btca.com>
  carol : <carol@btca.com>
  alice : <alice@btca.com>

>>> characters = [
...     dict(name='bob', email='bob@btca.com'),
...     dict(name='ted', email='ted@btca.com'),
...     dict(name='carol', email='carol@btca.com'),
...     dict(name='alice', email='alice@btca.com'),
... ]
>>> display(conjoin(characters, fmt="{0[name]:>7} : <{0[email]}>", conj=', or\n', sep=',\n', end='.'))
    bob : <bob@btca.com>,
    ted : <ted@btca.com>,
  carol : <carol@btca.com>, or
  alice : <alice@btca.com>.

>>> characters = [
...     Info(name='bob', email='bob@btca.com'),
...     Info(name='ted', email='ted@btca.com'),
...     Info(name='carol', email='carol@btca.com'),
...     Info(name='alice', email='alice@btca.com'),
... ]
>>> display(conjoin(characters, fmt='{0.name:>7} : <{0.email}>', conj='; &\n', sep=';\n', end='.'))
    bob : <bob@btca.com>;
    ted : <ted@btca.com>;
  carol : <carol@btca.com>; &
  alice : <alice@btca.com>.

>>> display(conjoin(characters, fmt=lambda a: f'{a.name:>7} : <{a.email}>', conj='\n', sep='\n'))
    bob : <bob@btca.com>
    ted : <ted@btca.com>
  carol : <carol@btca.com>
  alice : <alice@btca.com>
inform.dedent(text, strip_nl=None, *, bolm=None, wrap=False)[source]

Removes indentation that is common to all lines.

Without its named arguments, dedent behaves just like, and is a equivalent replacement for, textwrap.dedent.

bolm (str):

The beginning of line mark (bolm) is replaced by a space after the indent is removed. It must be the first non-space character after the initial newline. Normally bolm is a single character, often ‘|’, but it may be contain multiple characters, all of which are replaced by spaces.

strip_nl = None:

strip_nl is used to strip off a single leading or trailing newline. strip_nl may be None, ‘l’, ‘t’, or ‘b’ representing neither, leading, trailing, or both. True may also be passed, which is equivalent to ‘b’. Can also use ‘s’ (start) as synonym for ‘l’ and ‘e’ (end) as synonym for ‘t’.

wrap (bool or int):

If true the string is wrapped using a width of 70. If an integer value is passed, is used as the width of the wrap.

>>> from inform import dedent
>>> print(dedent('''
...     ◊   Diaspar
...         Lys
... ''', bolm='◊'))

    Diaspar
    Lys
>>> print(dedent('''
...     |   Diaspar
...     |   Lys
... ''', bolm='|', strip_nl='e'))

    Diaspar
|   Lys
>>> print(dedent('''
...     ||  Diaspar
...         Lys
... ''', bolm='||', strip_nl='s'))
    Diaspar
    Lys
>>> print(dedent('''
...         Diaspar
...         Lys
... ''', strip_nl='b'))
Diaspar
Lys
>>> print(dedent('''
...         Diaspar
...         Lys
... ''', strip_nl='b', wrap=True))
Diaspar Lys
inform.did_you_mean(invalid_str, valid_strs)[source]

Given an invalid string from the user, return the valid string with the most similarity.

Parameters:
  • invalid_str (string) – The invalid string given by the user.

  • valid_strs (iterable) – The set of valid strings that the user was expected to choose from.

Examples:

>>> from inform import did_you_mean
>>> did_you_mean('cat', ['cat', 'dog'])
'cat'
>>> did_you_mean('car', ['cat', 'dog'])
'cat'
>>> did_you_mean('car', {'cat': 1, 'dog': 2})
'cat'
inform.fmt(message, *args, **kwargs)[source]

Similar to ‘’.format(), but it can pull arguments from the local scope.

Convert a message with embedded attributes to a string. The values for the attributes can come from the argument list, as with ‘’.format(), or they may come from the local scope (found by introspection).

Examples:

>>> from inform import fmt
>>> s = 'str var'
>>> d = {'msg': 'dict val'}
>>> class Class:
...     a = 'cls attr'

>>> display(fmt("by order: {0}, {1[msg]}, {2.a}.", s, d, Class))
by order: str var, dict val, cls attr.

>>> display(fmt("by name: {S}, {D[msg]}, {C.a}.", S=s, D=d, C=Class))
by name: str var, dict val, cls attr.

>> display(fmt("by magic: {s}, {d[msg]}, {c.a}."))
by magic: str var, dict val, cls attr.

You can change the level at which the introspection occurs using the _lvl keyword argument.

_lvl=0 searches for variables in the scope that calls fmt(), the default
_lvl=-1 searches in the parent of the scope that calls fmt()
_lvl=-2 searches in the grandparent, etc.
_lvl=1 search root scope, etc.
inform.format_range(items, diff=<function <lambda>>, key=None, str=<class 'str'>, block_delim=', ', range_delim='-')[source]

Create a string that succinctly represents the given set of items. Groups of consecutive items are succinctly displayed as a range, and other items are listed individually.

Parameters:
  • items – An iterable containing the values to format. Any type of iterable can be given, but it will always be treated as a set (e.g. order doesn’t matter, duplicates are ignored). By default, the items in the iterable must be non-negative integers, but by customizing the other arguments, it is possible to support any discrete, ordered type.

  • key (callable or None) – A key function used to sort the given values, or None if the values can be sorted directly.

  • str (callable) – A function that can be used to convert an individual value from items into a string.

  • block_delim (str) – The character used to separate individual items and ranges in the formatted string.

  • range_delim (str) – The character used to indicate ranges in the formatted string.

Examples:

>>> from inform import format_range
>>> format_range([1, 2, 3, 5])
'1-3,5'
>>> abc_diff = lambda a, b: ord(b) - ord(a)
>>> format_range('ACDE', diff=abc_diff)
'A,C-E'
inform.full_stop(sentence, end='.', allow='.?!')[source]

Add period to end of string if it is needed.

A full stop (a period) is added if there is no terminating punctuation at the end of the string. The argument is first converted to a string, and then any white space at the end of the string is removed before looking for terminal punctuation. The return value is always a string.

Examples:

>>> from inform import full_stop
>>> full_stop('The file is out of date')
'The file is out of date.'

>>> full_stop('The file is out of date.')
'The file is out of date.'

>>> full_stop('Is the file is out of date?')
'Is the file is out of date?'

You can override the allowed and desired endings:

>>> cases = '1, 3 9, 12.'.split()
>>> print(*[full_stop(c, end=',', allow=',.') for c in cases])
1, 3, 9, 12.
inform.join(*args, **kwargs)[source]

Combines arguments into a string.

Combines the arguments in a manner very similar to an informant and returns the result as a string. Uses the sep, template and wrap keyword arguments to combine the arguments.

If template is specified it controls how the arguments are combined and the result returned. Otherwise the unnamed arguments are joined using the separator and returned.

Parameters:
  • sep (string) – Use specified string as join string rather than single space. The unnamed arguments will be joined with using this string as a separator. Default is ‘ ‘.

  • template (string or collection of strings) – A python format string. If specified, the unnamed and named arguments are combined under the control of the strings format method. This may also be a collection of strings, in which case each is tried in sequence, and the first for which all the interpolated arguments are known is used. By default, an argument is ‘known’ if it would be True if casted to a boolean.

  • remove

    Used if template is a collection.

    May be a function, a collection, or a scalar. The function would take a single argument, one of the values in the collection, and return True if the value should not be considered known. The scalar or the collection simply specified the specific value of values that should not be considered known.

    If remove is not specified, the value should not be considered known if its value would be False when cast to a boolean (0, False, None, ‘’, (), [], {}, etc.)

  • wrap (bool or int) – If true the string is wrapped using a width of 70. If an integer value is passed, is used as the width of the wrap.

Examples:

>>> from inform import join
>>> join('a', 'b', 'c', x='x', y='y', z='z')
'a b c'

>>> join('a', 'b', 'c', x='x', y='y', z='z', template='{2} {z}')
'c z'
inform.parse_range(items_str, cast=<class 'int'>, range=<function <lambda>>, block_delim=', ', range_delim='-')[source]

Parse a set of values from a string where commas can be used to separate individual items and hyphens can be used to specify ranges of items.

Parameters:
  • items_str (str) – The string to parse.

  • cast (callable) – A function that converts items from the given string to the type that will be returned. The function will be given a single argument, which will be a string, and should return that same value casted into the desired type. Note that the casted values will also be used as the inputs for the range() function.

  • range (callable) – A function that produces the values implied by a range. It will be given two arguments: the start and end of a range. Both arguments will have already been transformed by the cast() function, and the first argument is guaranteed to be less than the second. The function should return an iterable containing all the values in that range, including the start and end values.

  • block_delim (str) – The character used to separate items and ranges.

  • range_delim (str) – The character used to indicate a range.

Returns:

All of the values specified by the given string.

Return type:

set

Examples:

>>> from inform import parse_range
>>> parse_range('1-3,5')
{1, 2, 3, 5}
>>> abc_range = lambda a, b: [chr(x) for x in range(ord(a), ord(b) + 1)]
>>> parse_range('A-C,E', cast=str, range=abc_range)  
{'B', 'E', 'C', 'A'}
inform.os_error(e)[source]

Generates clean messages for operating system errors.

Parameters:

e (exception) – The value of an OSError exception.

Example:

>>> from inform import display, os_error
>>> try:
...     with open('config') as f:
...         contents = f.read()
... except OSError as e:
...     display(os_error(e))
config: no such file or directory.
class inform.plural(value, *, num='#', invert='!', slash='/')[source]

Conditionally format a phrase depending on whether it refers to a singular or plural number of things.

The format string has three sections, separated by ‘/’. The first section is always included, the last section is included if the given number is plural, and the middle section (which can be omitted) is included if the given number is singular. If there is only one section, it is used as is for the singular case and an ‘s’ is added to it for the plural case. If any of the sections contain a ‘#’, it is replaced by the number of things.

You may provide either a number (e.g. 0, 1, 2, …) or any object that implements __len__() (e.g. list, dict, set, …). In the latter case, the length of the object will be used to decide whether to use the singular of plural form. Only 1 is considered to be singular; every other number is considered plural.

If the format string starts with ‘!’ then it is removed and the sense of plurality is reversed (the plural form is used for one thing, and the singular form is used otherwise). This is useful when pluralizing verbs.

Examples:

>>> from inform import plural

>>> f"{plural(1):thing}"
'thing'
>>> f"{plural(2):thing}"
'things'

>>> f"{plural(1):thing/s}"
'thing'
>>> f"{plural(2):thing/s}"
'things'

>>> f"{plural(1):# thing/s}"
'1 thing'
>>> f"{plural(2):# thing/s}"
'2 things'

>>> f"{plural(1):/a cactus/# cacti}"
'a cactus'
>>> f"{plural(2):/a cactus/# cacti}"
'2 cacti'

>>> f"{plural(1):# /is/are}"
'1 is'
>>> f"{plural(2):# /is/are}"
'2 are'

>>> f"{plural([]):# thing/s}"
'0 things'
>>> f"{plural([0]):# thing/s}"
'1 thing'

>>> f"{plural(1):!agree}"
'agrees'
>>> f"{plural(2):!agree}"
'agree'

If ‘/’, ‘#’, or ‘!’ are inconvenient, you can change them by passing the slash, num and invert arguments to plural().

The original implementation is from Veedrac on Stack Overflow: http://stackoverflow.com/questions/21872366/plural-string-formatting

format(formatter)[source]

Expand plural to a string.

You can use this method to directly expand plural to a string without needing to use f-strings or the string format method.

Examples:

>>> plural(1).format('thing')
'thing'
>>> plural(3).format('/a cactus/# cacti')
'3 cacti'
inform.render(obj, sort=None, level=None, tab='    ')[source]

Recursively convert object to string with reasonable formatting.

Parameters:
  • obj – The object to render

  • sort (bool) – Dictionary keys and set values are sorted if sort is True. Sometimes this is not possible because the values are not comparable, in which case render reverts to using the natural order.

  • level (int) – The indent level. If not specified and render is called recursively the indent will be incremented, otherwise the indent is 0.

  • tab (string) – The string used when indenting.

render has built in support for the base Python types (None, bool, int, float, str, set, tuple, list, and dict). If you confine yourself to these types, the output of render can be read by the Python interpreter. Other types are converted to string with repr().

Example:

>>> from inform import display, render
>>> display('result =', render({'a': (0, 1), 'b': [2, 3, 4]}))
result = {'a': (0, 1), 'b': [2, 3, 4]}

In addition, you can add support for render to your classes by adding one or both of these methods:

_inform_get_args(): returns a list of argument values.

_inform_get_kwargs(): returns a dictionary of keyword arguments.

Example:

>>> class Chimera:
...     def __init__(self, *args, **kwargs):
...         self.args = args
...         self.kwargs = kwargs
...
...     def _inform_get_args(self):
...         return self.args
...
...     def _inform_get_kwargs(self):
...         return self.kwargs

>>> lycia = Chimera('Lycia', front='lion', middle='goat', tail='snake')
>>> display(render(lycia))
Chimera(
    'Lycia',
    front='lion',
    middle='goat',
    tail='snake',
)
inform.render_bar(value, width=72, full_width=False)[source]

Render graphic representation of a value in the form of a bar

Parameters:
  • value (real) – Should be normalized (fall between 0 and 1)

  • width (int) – The width of the bar in characters when value is 1.

  • full_width (bool) – Whether bar should be rendered to fill the whole width using trailing spaces,. This is useful if you plan to mark the end of the bar.

Examples:

>>> from inform import render_bar

>>> assets = {'property': 13_194, 'cash': 2846, 'equities': 19_301}
>>> total = sum(assets.values())
>>> for key, value in assets.items():
...     display(f"{key:>8}: ❭{render_bar(value/total, full_width=True)}❬")
property: ❭██████████████████████████▉                                             ❬
    cash: ❭█████▊                                                                  ❬
equities: ❭███████████████████████████████████████▎                                ❬
inform.title_case(s, exceptions=('and', 'or', 'nor', 'but', 'a', 'an', 'and', 'the', 'as', 'at', 'by', 'for', 'in', 'of', 'on', 'per', 'to'))[source]

Convert to title case

This is an attempt to provide an alternative to ‘’.title() that works with acronyms.

There are several tricky cases to worry about in typical order of importance:

  1. Upper case first letter of each word that is not an ‘minor’ word.

  2. Always upper case first word.

  3. Do not down case acronyms

  4. Quotes

  5. Hyphenated words: drive-in

  6. Titles within titles: 2001 A Space Odyssey

  7. Maintain leading spacing

  8. Maintain given spacing: This is a test. This is only a test.

The following code addresses 0-3 & 7. It was felt that addressing the others would add considerable complexity. Case 2 was handled by simply maintaining all upper case letters in the specified string.

Example:

>>> from inform import title_case
>>> cases = '''
...     CDC warns about "aggressive" rats as coronavirus shuts down restaurants
...     L.A. County opens churches, stores, pools, drive-in theaters
...     UConn senior accused of killing two men was looking for young woman
...     Giant asteroid that killed the dinosaurs slammed into Earth at ‘deadliest possible angle,’ study reveals
...     Maintain given spacing: This is a test.  This is only a test.
... '''.strip()

>>> for case in cases.splitlines():
...    print(title_case(case))
CDC Warns About "Aggressive" Rats as Coronavirus Shuts Down Restaurants
L.A. County Opens Churches, Stores, Pools, Drive-in Theaters
UConn Senior Accused of Killing Two Men Was Looking for Young Woman
Giant Asteroid That Killed the Dinosaurs Slammed Into Earth at ‘Deadliest Possible Angle,’ Study Reveals
Maintain Given Spacing: This Is a Test.  This Is Only a Test.

Debug Utilities

inform.aaa(*args, **kwargs)[source]

Print argument, then return it.

Pretty-prints its argument. Argument may be named or unnamed. Allows you to display the value that is only contained within an expression.

inform.ccc(*args, **kwargs)[source]

Print the class name for all arguments.

inform.ddd(*args, **kwargs)[source]

Print arguments function.

Pretty-prints its arguments. Arguments may be named or unnamed.

inform.ppp(*args, **kwargs)[source]

Print function.

Mimics the normal print function, but colors printed output to make it easier to see and labels it with the location of the call.

inform.sss(ignore_exceptions=True)[source]

Print a stack trace

Parameters:

ignore_exceptions – (bool) If true, the stack trace will exclude the path through exceptions.

inform.vvv(*args)[source]

Print variables function.

Pretty-prints variables from the calling scope. If no arguments are given, all variables are printed. If arguments are given, only the variables whose value match an argument are printed.

Exceptions

exception inform.Error(*args, **kwargs)[source]

A generic exception.

The exception accepts both unnamed and named arguments. All are recorded and available for later use.

template may be added to the class as an attribute, in which case it acts as the default template for the exception (used to format the exception arguments into an error message).

The idea of allowing template to be an attribute to Error was originally proposed on the Python Ideas mailing list by Ryan Fox (https://pypi.org/project/exception-template/).

get_codicil(codicil=None)[source]

Get the codicils.

A codicil is extra text attached to an error that can clarify the error message or to give extra context.

Return the codicil as a tuple. If a codicil is specified as an argument, it is appended to the exception’s codicil without modifying it.

Parameters:

codicil (string or tuple of strings) – A codicil or collection of codicils that is appended to the return value without modifying the cached codicil.

Returns:

The codicil argument is appended to the exception’s codicil and the combination is returned. The return value is always in the form of a tuple even if there is only one component.

get_culprit(culprit=None)[source]

Get the culprits.

Culprits are extra pieces of information attached to an error that help to identify the source of the error. For example, file name and line number where the error was found are often attached as culprits.

Return the culprit as a tuple. If a culprit is specified as an argument, it is appended to the exception’s culprit without modifying it.

Parameters:

culprit (string, number or tuple of strings and numbers) – A culprit or collection of culprits that is appended to the return value without modifying the cached culprit.

Returns:

The culprit argument is prepended to the exception’s culprit and the combination is returned. The return value is always in the form of a tuple even if there is only one component.

get_message(template=None)[source]

Get exception message.

Parameters:

template (str) –

This argument is treated as a format string and is passed both the unnamed and named arguments. The resulting string is treated as the message and returned.

If not specified, the template keyword argument passed to the exception is used. If there was no template argument, then the positional arguments of the exception are joined using sep and that is returned.

Returns:

The formatted message without the culprits.

render(template=None)[source]

Convert exception to a string for use in an error message.

Parameters:

template (str) –

This argument is treated as a format string and is passed both the unnamed and named arguments. The resulting string is treated as the message and returned.

If not specified, the template keyword argument passed to the exception is used. If there was no template argument, then the positional arguments of the exception are joined using sep and that is returned.

Returns:

The formatted message with any culprits.

report(**new_kwargs)[source]

Report exception to the user.

Prints the error message on the standard output.

The inform.error() function is called with the exception arguments.

Parameters:

**kwargsreport() takes any of the normal keyword arguments normally allowed on an informant (culprit, template, etc.). Any keyword argument specified here overrides those that were specified when the exception was first raised.

reraise(**new_kwargs)[source]

Re-raise the exception.

terminate(**new_kwargs)[source]

Report exception and terminate.

Prints the error message on the standard output and exits the program.

The inform.fatal() function is called with the exception arguments.

Parameters:

**kwargsreport() takes any of the normal keyword arguments normally allowed on an informant (culprit, template, etc.). Any keyword argument specified here overrides those that were specified when the exception was first raised.