storyboard.util module

Supporting utilities.

Classes

ProgressBar(totalsize[, interval]) Progress bar for file processing.
OptionReader([cli_args, config_files, ...]) Class for reading options from a list of fallbacks.

Routines

read_param(params, key, default) Read and return a parameter from a dict.
round_up(number[, ndigits]) Round a floating point number upward to a given precision.
evaluate_ratio(ratio_str) Evaluate ratio in the form num:den or num/den.
humansize(size) Return a human readable string of the given size in bytes.
humantime(seconds[, ndigits, one_hour_digit]) Format a duration as a human readable string.

class storyboard.util.OptionReader(cli_args=None, config_files=None, section=None, defaults=None)[source]

Bases: object

Class for reading options from a list of fallbacks.

OptionReader optionally takes command line arguments parsed by argparse, a list of possible configuration files, and a dictionary of default values. Then one can query the class for the value of an option using the opt(name) method. The value is determined in the order of CLI argument, value specified in config files, default value, and at last None if none of the above is available.

Parameters:

cli_args : argparse.Namespace, optional

CLI arguments returned by argparse.ArgumentParser.parse_args(). If None, do not consider CLI arguments. Default is None.

config_files : str or list, optional

Path(s) to the expected configuration file(s). If None, do not read from config files. Default is None.

section : str, optional

Name of the config file section to read from. Do not use DEFAULT, as it is the reserved name for a special section. If None, do not read from config files. Default is None.

defaults : dict, optional

A dict containing default values of one or more options. If None, do not consider default values. Default is None.

Raises:

configparser.Error:

If some of the supplied configuration files are malformed.

Notes

For developers: there are three private attributes, _cli_opts, _cfg_opts and _default_opts, which are dicts containing CLI, config file, and default options, respectively.

cfg_opt(name, opttype=None)[source]

Read the value of an option from config files.

Parameters:

name : str

Name of the option.

opttype : {None, str, int, float, bool}

Type of the option. The value of the option is converted to the corresponding type. If None, no conversion is done (so the return type will actually be str). If bool, the returned value will be True if the default value is 'yes', 'on', or '1', and False if the default value is 'no', 'off', or '0' (case insensitive), just like configparser.ConfigParser.getboolean.

Returns:

value

Value of the option in config files if available, and None otherwise.

Raises:

ValueError:

If the raw value of the option in config files (if available) cannot be converted to opttype, or if opttype is not one of the supported types.

cli_opt(name)[source]

Read the value of an option from the corresponding CLI argument.

Parameters:

name : str

Name of the option.

Returns:

value

Value of the corresponding CLI argument if available, and None otherwise.

default_opt(name)[source]

Read the default value of an option.

Parameters:

name : str

Name of the option.

Returns:

value

Default value of the option if available, and None otherwise.

opt(name, opttype=None)[source]

Read the value of an option.

The value is determined in the following order: CLI argument, config files, default value, and at last None.

Parameters:

name : str

Name of the option.

opttype : {None, str, int, float, bool}

Type of the option, only useful for config files. See the opttype parameter of the cfg_opt method.

Returns:

value

Value of the option.

Raises:

ValueError:

If the raw value of the option in config files (if available) cannot be converted to opttype, or if opttype is not one of the supported types.

class storyboard.util.ProgressBar(totalsize, interval=1.0)[source]

Bases: object

Progress bar for file processing.

To generate a progress bar, init a ProgressBar instance, then update frequently with the update method, passing in the size of newly processed chunk. The force_update method should only be called if you want to overwrite the processed size, which is automatically calculated incrementally. After you finish processing the file/stream, you must call the finish method to wrap it up. Any further calls after the finish method has been called lead to a RuntimeError.

Each ProgressBar instance defines several public attributes listed below. Some are available during processing, and some after processing. These attributes are meant for informational purposes, and you should not manually tamper with them (which mostly likely leads to undefined behavior).

The progress bar format is inspired by pv(1) (pipe viewer).

Parameters:

totalsize : int

Total size, in bytes, of the file/stream to be processed.

interval : float, optional

Update (refresh) interval of the progress bar, in seconds. Default is 1.0.

Notes

For developers: ProgressBar also defines three private attributes, _last, _last_processed and _barlen, during processing (deleted after the finish call). _last stores the absolute time of last update (refresh), _last_processed stores the processed size at the time of the last update (refresh), and _barlen stores the length of the progress bar (only the bar portion).

There is another private attribute __finished (bool) keeping track of whether finish has been called. (Protected with double leading underscores since no one should ever tamper with this.)

Attributes

totalsize (int) Total size of file/stream, in bytes. Available throughout.
processed (int) Process size. Available only during processing (deleted after the finish call).
start (float) Starting time (an absolute time returned by time.time()). Available throughout.
interval (float) Update (refresh) interval of the progress bar, in seconds. Available only during processing (deleted after the finish call).
elapsed (float) Total elapsed time, in seconds. Only available after the finish call.
finish()[source]

Finish file progressing and wrap up on the progress bar.

Always call this method exactly once after you finish processing. This method adds the finishing touches to the progress bar, deletes several attributes (processed, interval), and adds a new attribute (elapsed).

After finish is called on a ProgressBar attribute, it enters a read-only mode: you may read the totalsize, start, and elapsed attributes, but any method call leads to a RuntimeError.

Raises:

RuntimeError:

If finish has already been called on the ProgressBar instance before.

force_update(processed_size)[source]

Force update the progress bar with a given processed size.

The processed attribute is overwritten by the new value.

Parameters:

processed_size :

Processed size of the file/stream, in bytes. Existing value is overwritten by this value.

Raises:

RuntimeError:

If finish has been called on the ProgressBar instance.

update(chunk_size)[source]

Update the progress bar for a newly processed chunk.

The size of the processed chunk is registered. Whether the progress bar is refreshed depends on whether we have reached the refresh interval since the last refresh (handled automatically).

Parameters:

chunk_size : int

The size of the newly processed chunk (since last update), in bytes. This size will be added to the processed attribute.

Raises:

RuntimeError:

If finish has been called on the ProgressBar instance.

storyboard.util.evaluate_ratio(ratio_str)[source]

Evaluate ratio in the form num:den or num/den.

Note that numerator and denominator should both be positive integers.

Parameters:

ratio_str : str

The ratio as a string (either 'num:den' or 'num/den' where num and den, the numerator and denominator, are positive integers.

Returns:

ratio : float

The ratio as a float, or None if ratio_str is malformed.

Examples

>>> evaluate_ratio('16:9')
1.7777777777777777
>>> evaluate_ratio('16/9')
1.7777777777777777
>>> print(evaluate_ratio('0/9'))
None
storyboard.util.humansize(size)[source]

Return a human readable string of the given size in bytes.

storyboard.util.humantime(seconds, ndigits=2, one_hour_digit=False)[source]

Format a duration as a human readable string.

The duration in seconds (a nonnegative float) is formatted as HH:MM:SS.frac, where the number of fractional digits is controlled by ndigits; if ndigits is 0, the decimal point is not printed. The number of hour digits (HH) can be reduced to one with the one_hour_digits option.

Parameters:

seconds : float

Duration in seconds, must be nonnegative.

ndigits : int, optional

Number of digits after the decimal point for the seconds part. Default is 2. If 0, the decimal point is suppressed.

one_hour_digit : bool, optional

If True, only print one hour digit (e.g., nine hours is printed as 9:00:00.00). Default is False, i.e., two hour digits (nine hours is printed as 09:00:00.00).

Returns:

human_readable_duration : str

Raises:

ValueError:

If seconds is negative.

Examples

>>> humantime(10.55)
'00:00:10.55'
>>> humantime(10.55, ndigits=1)
'00:00:10.6'
>>> humantime(10.55, ndigits=0)
'00:00:11'
>>> humantime(10.55, one_hour_digit=True)
'0:00:10.55'
>>> # two hours digits for >= 10 hours, even if one_hour_digit is
>>> # set to True
>>> humantime(86400, one_hour_digit=True)
'24:00:00.00'
>>> humantime(-1)
Traceback (most recent call last):
    ...
ValueError: seconds=-1.000000 is negative, expected nonnegative value
storyboard.util.read_param(params, key, default)[source]

Read and return a parameter from a dict.

If the key key is absent from the dict params, return the default value default instead.

Parameters:

params : dict

A dict containing parameters.

key : str

Name of the parameter, i.e., its corresponding key in params.

default

Default value for the parameter, if key is absent from params.

Returns:

value

If key in params, return params[key]; otherwise, return default instead.

storyboard.util.round_up(number, ndigits=0)[source]

Round a floating point number upward to a given precision.

Unlike the builtin round, the return value round_up is always the smallest float greater than or equal to the given number matching the specified precision.

Parameters:

number : float

Number to be rounded up.

ndigits : int, optional

Number of decimal digits in the result. Default is 0.

Returns:

float

Examples

>>> round_up(math.pi)
4.0
>>> round_up(math.pi, ndigits=1)
3.2
>>> round_up(math.pi, ndigits=2)
3.15
>>> round_up(-math.pi, ndigits=4)
-3.1415