yabs package#


yabs.util module#

exception yabs.util.CheckError[source]#

Bases: ExitingYabsError

–check condition failed.


Exception.add_note(note) – add a note to the exception


Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.


exception code

exception yabs.util.ConfigError[source]#

Bases: ExitingYabsError

Invalid yabs.yaml or command line (terminates without stacktrace).


Exception.add_note(note) – add a note to the exception


Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.


exception code

exception yabs.util.ExitingYabsError[source]#

Bases: SystemExit, YabsError

YabsError the will cause sys.exit(). Raised for errors that don’t need a stack trace.


Exception.add_note(note) – add a note to the exception


Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.


exception code

exception yabs.util.YabsError[source]#

Bases: RuntimeError

Base class for all exception that we deliberatly throw.


Exception.add_note(note) – add a note to the exception


Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

class yabs.util.NO_DEFAULT[source]#

Bases: object

Used as default parameter to distinguish from None.

yabs.util.assert_always(condition, msg=None)[source]#

assert even in production code.

yabs.util.check_arg(argument, allowed_types, condition=<class 'yabs.util.NO_DEFAULT'>, *, or_none=False)[source]#

Check if argument has the expected type and value.

Note: the exception’s traceback is manipulated, so that the back frame points to the check_arg() line, instead of the actual raise.

  • argument (any) – value of the argument to check

  • allowed_types (type or tuple of types)

  • condition (bool, optional) – additional condition that must be true

  • or_none (bool, optional) – defaults to false



  • TypeError – if argument is of an unexpected type

  • ValueError – if argument does not fulfill the optional condition

  • AssertionError – if check_arg was called with a wrong syntax, i.e. allowed_types does not contain types, e.g. if 1 was passed instead of int.


def foo(name, amount, options=None):
    check_arg(name, str)
    check_arg(amount, (int, float), amount > 0)
    check_arg(options, dict, or_none=True)

Check for presence of –verbose/–quiet or -v/-q without using argparse.

yabs.util.check_dict_keys(d: dict, *, known: set, mandatory: set, prefix: str, key_prefix: str = '') List[str][source]#

Validate a dict fo missing or unknown keys.

yabs.util.datetime_to_iso(dt=None, *, microseconds: bool = False) str[source]#

Return current UTC datetime as ISO formatted string.

yabs.util.format_elap(seconds, *, count=None, unit='items', high_prec=False, short_suffix=False)[source]#

Return elapsed time as H:M:S.h string with reasonable precision.

yabs.util.format_rate(count, time, unit=None, high_prec=False)[source]#

Return count / time with reasonable precision.

yabs.util.get_dict_attr(d, key_path, default=<class 'yabs.util.NO_DEFAULT'>)[source]#

Return the value of a nested dict using dot-notation path.

  • d (dict)

  • key_path (str)

  • KeyError

  • ValueError

  • IndexError




  • k[1] instead of k.[1]

  • default arg


Return folder files names as set.

yabs.util.init_logging(verbose=3, path=None)[source]#

CLI calls this.

yabs.util.lstrip_string(s, prefix, ignore_case=False)[source]#

Remove leading string from s.

Note: This is different than s.lstrip(‘bar’) which would remove all leading ‘a’, ‘b’, and ‘r’ chars.

yabs.util.plural_s(value) str[source]#

Return ‘s’ if value is not singular.


from util import plural_s as ps

v = [1, 2] print(f”Found value{ps(v)}: {v}”)

yabs.util.resolve_path(root, path, must_exist=True, check_root=False)[source]#

Return an absolute path, assuming relative to the root file or folder.

yabs.util.run_process_streamed(process, name=None, on_output=None, log_alive=5.0, timeout=None, poll_interval=0.1, flush_min_interval=0.2, prefix_chunks=False)[source]#

Read and print output of a running process.

  • process (subprocess.Popen) – A running process instance

  • name (str) – Descriptive name of the process

  • on_output (stream) – Call this method for output (default: logger.info)

  • log_alive (float) – Print a simple message if not new output was received for X seconds (default: 5.0)

  • timeout (float) – Kill process after X seconds (default: None)

  • poll_interval (float) – Poll output buffer every X seconds (default: 0.1)

  • flush_min_interval (float) – Minimal log interval: Wait X seconds for more lines (default: 0.2)

  • prefix_chunks (bool) – Prefix output chunks with <name> (default: False)


tuple (ret_code, output)

yabs.util.search_file_upward(root: str | Path, filename: str, *, max_level=0, or_none=False) Path[source]#


yabs.util.set_console_ctrl_handler(ctrl_handler, do_ctrl_c=True, do_ctrl_break=False, do_ctrl_close=False)[source]#

The do_ctrl_* functions could simply be sys.exit(1), which will ensure that atexit handlers get called. See https://bugs.python.org/issue35935




False if not on Windows or could not register the handler.

yabs.util.shorten_string(long_string, max_chars, min_tail_chars=0, place_holder='[...]')[source]#

Return string, shortened to max_chars characters.

long_string = “This is a long string, that will be truncated.” trunacated_string = truncate_string(long_string, max_chars=26, min_tail_chars=11, place_holder=”[…]”) print trunacated_string >> This is a […] truncated.

@param long_string: string to be truncated @param max_chars: max chars of returned string @param min_tail_chars: minimum of tailing chars @param place_holder: place holder for striped content @return: truncated string

yabs.util.timetag(seconds=True, *, ms=False)[source]#

Return a time stamp string that can be used as (part of a) filename (also sorts well).

yabs.util.to_list(obj, or_none=False)[source]#

Convert a single object to a list.

yabs.util.to_set(obj, or_none=False)[source]#

Convert a single object to a set.

yabs.task package#

yabs.task.common module#

class yabs.task.common.TaskContext(task_runner)[source]#

Bases: object

Context information that is passed by the task runner to all tasks. This instance is used by tasks to pass information to downstream tasks.

artifacts: dict#

(dict) all files that ‘pypi_release’ created, e.g. {"sdist": <path>, "bdist_msi": <path>}

dry_run: bool#

(bool) true if --dry-run was passed

gh_auth_token: str#

(str) GitHub authentication token

inc: str#

(str) value of --inc argument (‘major’, ‘minor’, ‘patch’, ‘postrelease’)

org_tag_name: str#

(str) the repo’s latest tag name (before ‘bump’)

org_version: Version#

(semantic_version.Version) latest version (before ‘bump’) E.g. str(context.org_version) == ‘1.2.3-a1’

repo: str#

(str) GitHub repo name, e.g. ‘USER/PROJECT’

repo_obj: Repo#


repo_path: Path#

(str) Root folder

repo_short: str#

(str) Short repo name, without user/ prefixe.g. ‘PROJECT’

tag_name: str#

(str) the current tag name (after ‘bump’)

task_runner: TaskRunner#


version: Version#

(semantic_version.Version) current version (after ‘bump’) E.g. str(context.version) == ‘1.2.3’

version_manager: VersionFileManager#


class yabs.task.common.WorkflowTask(task_inst: TaskInstance)[source]#

Bases: ABC

Common base class for all yabs tasks.

abstract classmethod check_task_def(task_inst: TaskInstance)[source]#

Check task definition for errors.

This allows static pre-checks before the actual workflow starts.


(str|list|bool) Error message(s)

cli_arg(key: str, default=None)[source]#

Return a value from command line args.

Tasks mus handle tha case that args is not undefined when not running as CLI or the command is “info” instead of “running” for example.

get_setup_metadata(extra_args: list = None) dict[source]#

‘Query setup.py for project name and version.

abstract classmethod register_cli_command(subparsers, parents, run_parser)[source]#

Let tasks add a sub-command and/or arguments to the ‘run’ command.

COMMON_OPTS = frozenset({'dry_run', 'verbose'})#

(frozenset) Task options shared by all task

DEFAULT_OPTS: dict = None#

(dict) define all supported arguments and their default values. This attribute must be defined by derived classes.

KNOWN_TARGETS = frozenset({'bdist_msi', 'bdist_wheel', 'sdist'})#

(frozenset) Task options shared by all task


(set) mandatory task options. ‘task’ is implicitly mandatory. This is validated by the task runner before starting the workflow.

dry_run: bool#

(bool) true if –dry-run was passed to the CLI

opts: dict#

(dict) The actual arguments, i.e. the default values merged with (dict) passed options

task_inst: TaskInstance#


verbose: int#

(int, default=3) 0..5