Skip to content

Reference🔗

berhoel.helper 🔗

Misc helper.

Modules:

  • check_args –

    Proccess arguments flexible.

  • machar –

    Determine machine-specific parameters affecting floating-point arithmetic.

  • set_version –

    Set lib version from pyproject.toml.

  • tests –

Classes:

Functions:

  • count_with_msg –

    Count variable with start value and message.

  • process_msg_context –

    Provide a context for calling routines and reporting entering and exit.

  • swirl –

    Retrun generator to show a swirling life indicator.

  • timed_process_msg_context –

    Provide a context for calling routines and reporting entering and exit.

Classes🔗

berhoel.helper.SwirlSelect 🔗

Selector for swirl style.

Functions🔗

berhoel.helper.count_with_msg 🔗

count_with_msg(msg: str = 'loop', start: int = 0) -> Generator

Count variable with start value and message.

>>> c = count_with_msg("msg", 5)
>>> print([i for _, i in zip(range(5), c)] == [5, 6, 7, 8, 9])
msg 1 ...msg 2 ...msg 3 ...msg 4 ...msg 5 ...True
>>>

Parameters:

  • msg 🔗
    (str, default: 'loop' ) –

    base message

  • start 🔗
    (int, default: 0 ) –

    counter start_time

Returns:

Source code in src/berhoel/helper/__init__.py
def count_with_msg(msg: str = "loop", start: int = 0) -> Generator:
    """Count variable with start value and message.

    ```python
    >>> c = count_with_msg("msg", 5)
    >>> print([i for _, i in zip(range(5), c)] == [5, 6, 7, 8, 9])
    msg 1 ...msg 2 ...msg 3 ...msg 4 ...msg 5 ...True
    >>>
    ```

    Args:
        msg: base message
        start: counter start_time

    Returns:
        counter with message.
    """
    i = 1
    _count = start
    while True:
        sys.stdout.write(f"{msg} {i} \r")
        yield _count
        _count += 1
        i += 1

berhoel.helper.process_msg_context 🔗

process_msg_context(msg: str) -> Generator

Provide a context for calling routines and reporting entering and exit.

 >>> with process_msg_context("do something"):
...     pass
do something......do something...done
>>>

Parameters:

  • msg 🔗
    (str) –

    message for bracing process.

Returns:

Source code in src/berhoel/helper/__init__.py
@contextmanager
def process_msg_context(msg: str) -> Generator:
    """Provide a context for calling routines and reporting entering and exit.

    ```python
     >>> with process_msg_context("do something"):
    ...     pass
    do something......do something...done
    >>>
    ```

    Args:
        msg: message for bracing process.

    Returns:
        bracing message.
    """
    sys.stdout.write(f"{msg}...\r")
    yield
    sys.stdout.write(f"{msg}...done\n")

berhoel.helper.swirl 🔗

swirl(style: SwirlSelect = LINES) -> Generator

Retrun generator to show a swirling life indicator.

>>> sw = swirl()
>>> a = [_ for _ in zip(range(5), sw)]
\...|.../...-...\...
>>> sw = swirl(SwirlSelect.DOTS)
>>> a = [_ for _ in zip(range(8), sw)]
⠇...⡆...⣄...⣠...⢰...⠸...⠙...⠋...

Returns:

Source code in src/berhoel/helper/__init__.py
def swirl(style: SwirlSelect = SwirlSelect.LINES) -> Generator:
    r"""Retrun generator to show a swirling life indicator.

    ```python
    >>> sw = swirl()
    >>> a = [_ for _ in zip(range(5), sw)]
    \...|.../...-...\...
    >>> sw = swirl(SwirlSelect.DOTS)
    >>> a = [_ for _ in zip(range(8), sw)]
    ⠇...⡆...⣄...⣠...⢰...⠸...⠙...⠋...
    ```

    Returns:
        printing running indicator.
    """
    sw_string = __swirl_string[style]
    while True:
        for c in sw_string:
            sys.stdout.write(f"{c}\r")
            yield

berhoel.helper.timed_process_msg_context 🔗

timed_process_msg_context(msg: str, time_form: Callable | None = None) -> Generator

Provide a context for calling routines and reporting entering and exit.

Report spent time.

 >>> with timed_process_msg_context("do something"):
...     time.sleep(1)
do something......do something...done (0:00:01)
>>> with timed_process_msg_context(
...     "do something", lambda t: "{:d}s".format(int(t))
... ):
...     time.sleep(1)
do something......do something...done (1s)
>>>

Parameters:

  • msg 🔗
    (str) –

    message for bracing process.

  • time_form 🔗
    (Callable | None, default: None ) –

    function formatting druntime.

Returns:

Source code in src/berhoel/helper/__init__.py
@contextmanager
def timed_process_msg_context(msg: str, time_form: Callable | None = None) -> Generator:
    """Provide a context for calling routines and reporting entering and exit.

    Report spent time.

    ```python
     >>> with timed_process_msg_context("do something"):
    ...     time.sleep(1)
    do something......do something...done (0:00:01)
    >>> with timed_process_msg_context(
    ...     "do something", lambda t: "{:d}s".format(int(t))
    ... ):
    ...     time.sleep(1)
    do something......do something...done (1s)
    >>>
    ```

    Args:
        msg: message for bracing process.
        time_form: function formatting druntime.

    Returns:
        bracing message.
    """
    if time_form is None:

        def time_form(t: float | str) -> timedelta:
            return timedelta(seconds=int(t))

    start_time = time.time()
    sys.stdout.write(f"{msg}...\r")
    yield
    sys.stdout.write(f"{msg}...done ({time_form(time.time() - start_time)})\n")

berhoel.helper.machar 🔗

Determine machine-specific parameters affecting floating-point arithmetic.

Function to determine machine-specific parameters affecting floating-point arithmetic.

  • This is build after “NUMERICAL RECIPES in C”, second edition, Reprinted 1996, pp. 889.

Functions:

  • machar –

    Determine and returns machine-spec. paras affecting floating-point arithmetic.

Attributes:

Attributes🔗

berhoel.helper.machar.eps module-attribute 🔗

eps = __tmp['eps']

eps (float) Is the floating-point number ibeta ** machdep, loosly referred to as the floating-point precision.

berhoel.helper.machar.epsneg module-attribute 🔗

epsneg = __tmp['epsneg']

epsneg (float) Is ibeta ** negep, another way of defining floating-point precision. Not infrequently epsneg is 0.5 times eps; occasionally eps and epsneg are equal.

berhoel.helper.machar.ibeta module-attribute 🔗

ibeta = __tmp['ibeta']

ibeta (int) The radix in which numbers are represented, almost always 2, but occasionally 16, or even 10

berhoel.helper.machar.iexp module-attribute 🔗

iexp = __tmp['iexp']

iexp (int) Is the number of bits in the exponent (including its sign or bias)

berhoel.helper.machar.irnd module-attribute 🔗

irnd = __tmp['irnd']

irnd (int) Returns a code in the range 0…5, giving information on what kind of rounding is done in addition, and on how underflow is handled.

If irnd returns 2 or 5, then your computer is compilant with the IEEE standard for rounding. If it returns 1 or 4, then it is doing some kind of rounding, but not the IEEE standard. If irnd returns 0 or 3, then it is truncating the result, not rounding it.

berhoel.helper.machar.it module-attribute 🔗

it = __tmp['it']

it (int) The number of base-ibeta digits in the floating point mantissa

berhoel.helper.machar.machdep module-attribute 🔗

machdep = __tmp['machdep']

machep (int) Is the exponent of the smallest (most negative) power if ibeta that, added to 1.0 gives something different from 1.0.

berhoel.helper.machar.maxexp module-attribute 🔗

maxexp = __tmp['maxexp']

maxexp (int) Is the smallest (positive) power of ibeta that causes overflow.

berhoel.helper.machar.minexp module-attribute 🔗

minexp = __tmp['minexp']

minexp (int) Is the smallest (most negative) power if ibeta consistent with there no leading zeros in the mantissa.

berhoel.helper.machar.negep module-attribute 🔗

negep = __tmp['negep']

negep (int) Is the exponenet of the smalles power of ibeta that, subtracted from 1.0, gives something different from 1.0.

berhoel.helper.machar.ngrd module-attribute 🔗

ngrd = __tmp['ngrd']

ngrd (int) Is the number of guard digits used when truncating the product of two mantissas to fit the representation”

berhoel.helper.machar.xmax module-attribute 🔗

xmax = __tmp['xmax']

xmax (float) Is (1 - epsneg) x ibeta ** maxexp, generally the largest (in magnitude) usable floating value.

berhoel.helper.machar.xmin module-attribute 🔗

xmin = __tmp['xmin']

xmin (float) Is the floating-point number ibeta ** minexp, generally the smallest (in magnitude) usable floating value

Functions🔗

berhoel.helper.machar.machar 🔗

machar() -> dict[str, float | int]

Determine and returns machine-spec. paras affecting floating-point arithmetic.

Returns🔗

dict: Values in result dictionary are:

  • ibeta (int): The radix in which numbers are represented, almost always 2, but occasionally 16, or even 10
  • it (int): The number of base-ibeta digits in the floating point mantissa
  • machep (int): Is the exponent of the smallest (most negative) power if ibeta that, added to 1.0 gives something different from 1.0.
  • eps (float): Is the floating-point number ibeta ** machdep, loosly referred to as the floating-point precision.
  • negep (int): Is the exponenet of the smalles power of ibeta that, subtracted from 1.0, gives something different from 1.0.
  • epsneg (float): Is ibeta ** negep, another way of defining floating-point precision. Not infrequently epsneg is 0.5 times eps; occasionally eps and epsneg are equal.
  • iexp (int): Is the number of bits in the exponent (including its sign or bias)
  • minexp (int): Is the smallest (most negative) power if ibeta consistent with there no leading zeros in the mantissa.
  • xmin (float): Is the floating-point number ibeta ** minexp, generally the smallest (in magnitude) usable floating value
  • maxexp (int): Is the smallest (positive) power of ibeta that causes overflow.
  • xmax (float): Is (1 - epsneg) x ibeta ** maxexp, generally the largest (in magnitude) usable floating value.
  • irnd (int): Returns a code in the range 0…5, giving information on what kind of rounding is done in addition, and on how underflow is handled.

    If irnd returns 2 or 5, then your computer is compilant with the IEEE standard for rounding. If it returns 1 or 4, then it is doing some kind of rounding, but not the IEEE standard. If irnd returns 0 or 3, then it is truncating the result, not rounding it. - ngrd (int): Is the number of guard digits used when truncating the product of two mantissas to fit the representation

This is taken from “NUMERICAL RECIPES in C”, second edition, Reprinted 1996.

Source code in src/berhoel/helper/machar.py
def machar() -> dict[str, float | int]:  # noqa:PLR0915,PLR0912,C901
    """Determine and returns machine-spec. paras affecting floating-point arithmetic.

    Returns
    -------
      dict: Values in result dictionary are:

      - ``ibeta`` (int): The radix in which numbers are represented, almost
        always 2, but occasionally 16, or even 10
      - ``it`` (int): The number of base-``ibeta`` digits in the floating point
         mantissa
      - ``machep`` (int): Is the exponent of the smallest (most negative) power if
        ``ibeta`` that, added to 1.0 gives something different from 1.0.
      - ``eps`` (float): Is the floating-point number ``ibeta`` ** ``machdep``, loosly
        referred to as the *floating-point precision*.
      - ``negep`` (int): Is the exponenet of the smalles power of ``ibeta`` that,
        subtracted from 1.0, gives something different from 1.0.
      - ``epsneg`` (float): Is ``ibeta`` ** ``negep``, another way of defining
        floating-point precision. Not infrequently ``epsneg`` is 0.5 times ``eps``;
        occasionally ``eps`` and ``epsneg`` are equal.
      - ``iexp`` (int): Is the number of bits in the exponent (including its sign or
        bias)
      - ``minexp`` (int): Is the smallest (most negative) power if ``ibeta`` consistent
         with there no leading zeros in the mantissa.
      - ``xmin`` (float): Is the floating-point number ``ibeta`` ** ``minexp``,
        generally the smallest (in magnitude) usable floating value
      - ``maxexp`` (int): Is the smallest (positive) power of ``ibeta`` that causes
        overflow.
      - ``xmax`` (float): Is (1 - ``epsneg``) x ``ibeta`` ** ``maxexp``, generally the
        largest (in magnitude) usable floating value.
      - ``irnd`` (int): Returns a code in the range 0...5, giving information on what
        kind of rounding is done in addition, and on how underflow is handled.

        If ``irnd`` returns 2 or 5, then your computer is compilant with the IEEE
        standard for rounding. If it returns 1 or 4, then it is doing some kind of
        rounding, but not the IEEE standard. If ``irnd`` returns 0 or 3, then it is
        truncating the result, not rounding it.
      - ``ngrd`` (int): Is the number of *guard digits* used when truncating the product
        of two mantissas to fit the representation

    This is taken from "NUMERICAL RECIPES in C", second edition,
    Reprinted 1996.
    """
    one = float(1)
    two = one + one
    zero = one - one
    # Determine ``ibeta`` and ``beta`` by the method of M. Malcom.
    a = temp1 = one
    while temp1 - one == zero:
        a += a
        temp = a + one
        temp1 = temp - a
    b = one
    itemp = 0
    while itemp == 0:
        b += b
        temp = a + b
        itemp = int(temp - a)
    ibeta = itemp
    beta = float(ibeta)
    # Determine ``it`` and ``irnd``.
    it = 0
    b = temp1 = one
    while temp1 - one == zero:
        it = it + 1
        b = beta * b
        temp = b + one
        temp1 = temp - b
    irnd = 0
    betah = beta / two
    temp = a + betah
    if temp - a != zero:
        irnd = 1
    tempa = a + beta
    temp = tempa + betah
    if irnd == 0 and temp - tempa != zero:
        irnd = 2
    # Determine ``negep`` und ``epsneg``.
    negep = it + 3
    betain = one / beta
    a = one
    i = 1
    while i <= negep:
        i = i + 1
        a = betain * a
    b = a
    while 1:
        temp = one - a
        if temp - one != zero:
            break
        a = beta * a
        negep = negep - 1
    negep = -negep
    epsneg = a
    # Determine ``machdep`` and ``eps``.
    machdep = -it - 3
    a = b
    while 1:
        temp = one + a
        if temp - one != zero:
            break
        a = a * beta
        machdep = machdep + 1
    eps = a
    # Deterrmine ``ngrd``.
    ngrd = 0
    temp = one + eps
    if irnd == 0 and temp * one - one != zero:
        ngrd = 1
    # Determine ``iexp``.
    i = 0
    k = 1
    z = betain
    t = one + eps
    nxres = 0
    while 1:  # Loop until underflow ocurs, then exit.
        y = z
        z = y * y
        a = z * one  # check for underflow
        temp = z * t
        if a + a == zero or math.fabs(z) >= y:
            break
        temp1 = temp * betain
        if temp1 * beta == z:
            break
        i = i + 1
        k = k + k
    if ibeta != 10:  # noqa:PLR2004
        iexp = i + 1
        mx = k + k
    else:  # For decimal machines only
        iexp = i + i
        iz = ibeta
        while k >= iz:
            iz = ibeta * iz
            iexp = iexp + 1
        mx = iz + iz - 1
    # To determine ``minexp`` and ``xmin``, loop until an underflow
    # occurs, then exit.
    while True:
        xmin = y
        y = betain * y
        a = y * one  # Check here for the underflow
        temp = y * t
        if a + a != zero or math.fabs(y) < xmin:
            k = k + 1
            temp1 = temp * betain
            if temp1 * beta == y and temp != y:
                nxres = 3
                xmin = y
                break
        else:
            break
    minexp = -k
    # Determine maxexp, xmax.
    if mx <= k + k + 3 and ibeta != 10:  # noqa:PLR2004
        mx = mx + mx
        iexp = iexp + 1
    maxexp = mx + minexp
    irnd = nxres + irnd  # Adjust ``irnd`` to reflect partial underflow
    if irnd >= 2:  # noqa:PLR2004
        maxexp = maxexp - 2  # Adjust for IEEE-stype machines
    i = maxexp + minexp
    # Adjust for machines with implicit leading bit in binary mantissa,
    # and machines with radix point at extreme right of mantissa.
    if ibeta == DEFAULT_RADIX and not i:
        maxexp = maxexp - 1
    if i > 20:  # noqa:PLR2004
        maxexp = maxexp - 1
    if a != y:
        maxexp = maxexp - 2
    xmax = one - epsneg
    if xmax * one != xmax:
        xmax = one - beta * epsneg
    xmax = xmax / (xmin * beta * beta * beta)
    i = maxexp + minexp + 3
    j = 1
    while j <= i:
        j = j + 1
        xmax = xmax + xmax if ibeta == DEFAULT_RADIX else xmax * beta
    return {
        "ibeta": ibeta,
        "it": it,
        "irnd": irnd,
        "ngrd": ngrd,
        "machdep": machdep,
        "negep": negep,
        "iexp": iexp,
        "minexp": minexp,
        "maxexp": maxexp,
        "eps": eps,
        "epsneg": epsneg,
        "xmin": xmin,
        "xmax": xmax,
    }

berhoel.helper.check_args 🔗

Proccess arguments flexible.

This module provides a class named CheckArgs and a function named check_args.

The class CheckArgs is ment to be used as base class for own classes. After the __init__ method is called a dictionary args is added to the local namespace.

The init mathod has four arguments.

The first is, as usual, the self handler. The second is a list or tuples holding the allowed keyword arguments as first tuple element and their default values as remaining tuple elements.

The third and forth argument are the *data and **kw arguments from the implemented class.

Example
>>> from .check_args import CheckArgs
>>> class samp(CheckArgs):
...     default = (("A", "A"), ("B", "B"), ("C", ("C", 1, 2)))
...
...     def __init__(self, *data, **kw):
...         CheckArgs.__init__(self, *data, **kw)
...         print(self.args["A"], self.args["B"], self.args["C"])
>>> A = samp(A=34)
34 B ('C', 1, 2)
>>> A = samp(34, "HALLO")
34 HALLO ('C', 1, 2)
>>>

The function check_args provides similar funtionality for functions. It also takes four arguments.

The first to third argument are simlar to the second to forth element of the class. The forth element of the function is the functions name.

Example
>>> from .check_args import check_args
>>> def tst(*data, **kw):
...     default = (("A", "A"), ("B", "B"), ("C", ("C", 1, 2)))
...     return check_args(default, data, kw, "tst")
>>> tst(A=34) == {"A": 34, "B": "B", "C": ("C", 1, 2)}
True
>>> tst(34) == {"A": 34, "B": "B", "C": ("C", 1, 2)}
True
>>>

Classes:

  • ArgError –

    Error from the argument checking.

  • CheckArgs –

    A wrapper around the check_args function.

Functions:

Classes🔗

berhoel.helper.check_args.ArgError 🔗

Error from the argument checking.

berhoel.helper.check_args.CheckArgs 🔗

CheckArgs(*data: tuple, **kw: dict)

A wrapper around the check_args function.

Parameters:

  • data 🔗
    (tuple, default: () ) –

    arguments to __init__ method.

  • kw 🔗
    (dict, default: {} ) –

    keyword arguments to __init__ method.

Returns:

  • None –

    argument name, value pairs.

Attributes:

Source code in src/berhoel/helper/check_args.py
def __init__(self, *data: tuple, **kw: dict) -> None:
    """Intialize instance.

Args:
    data: arguments to ``__init__`` method.
    kw: keyword arguments to ``__init__`` method.

Returns:
    argument name, value pairs.
"""
    self.args = check_args(self.default, data, kw, self.__class__.__name__)
Attributes🔗
default abstractmethod property 🔗
default: Iterable[tuple[str, object]]

Return default values.

Functions🔗

Functions🔗

berhoel.helper.check_args.check_args 🔗

check_args(
    default: Iterable[tuple[str, object]], data: tuple, kw: dict, name: str
) -> dict[str, object]

Check arguments for function.

Parameters:

  • default 🔗
    (tuple[tuple[str, object]]) –

    argument names and default values for function call.

  • data 🔗
    (tuple) –

    arguments to function call.

  • kw 🔗
    (dict) –

    keyword arguments to function call.

  • name 🔗
    (str) –

    name for reporting.

Returns:

Source code in src/berhoel/helper/check_args.py
def check_args(
    default: Iterable[tuple[str, object]], data: tuple, kw: dict, name: str
) -> dict[str, object]:
    """Check arguments for function.

    Args:
        default (tuple[tuple[str, object]]): argument names and default values for
              function call.
        data (tuple): arguments to function call.
        kw (dict): keyword arguments to function call.
        name (str): name for reporting.

    Returns:
        argument name, value pairs.
    """
    args = dict(default)
    arglen = len(args)
    if (len(data) + len(kw)) > arglen:
        msg = f"{name} requires at most {arglen} argument; {len(data)} given"
        raise ArgError
    arglist = []
    for default_, data_ in zip(default, data, strict=False):
        args[default_[0]] = data_
        arglist.append(default_[0])
    for k in arglist:
        if k in kw:
            msg = f"{name}: key '{k}' used in **kw argument is also set by *data."
            raise ArgError(msg)
    args.update(kw)
    if len(args) != arglen:
        out = list(args.keys())
        for key, _ in default:
            out.remove(key)
        msg = f"{name}: unexpected keyword argument: {out[0]}"
        raise ArgError(msg)
    return args

berhoel.helper.set_version 🔗

Set lib version from pyproject.toml.

Deprecated: 1.3.6

Use:

__version__ = __import__("importlib.metadata", fromlist=["version"]).version(
    <package name>
)

instead

This library allows for setting the version number for a library from the pyproject.toml file.

Add to your pyproject.toml add a new section:

  [tool.berhoel.helper.set_version]
  version_files = ["berhoel/helper/_version.py"]

Generate the version file:

  $> poetry run set_lib_version
  writing berhoel/helper/_version.py

In the library __init__.py just use:

  try:
      from ._version import __version__
  except ImportError:
      __version__ = "0.0.0.invalid0"

Functions:

  • build –

    Create version files with version number from pyproject.toml.

  • build_parser –

    Build cli parser.

Functions🔗

berhoel.helper.set_version.build 🔗

build() -> None

Create version files with version number from pyproject.toml.

Source code in src/berhoel/helper/set_version.py
def build() -> None:
    """Create version files with version number from `pyproject.toml`."""
    message = "dont use __version__"
    warnings.warn(message, DeprecationWarning, stacklevel=2)

    parser = build_parser()
    parser.parse_args()

    pyproject = (Path() / "pyproject.toml").resolve()

    with pyproject.open("rb") as conf_inp:
        config = tomli.load(conf_inp)

    version = config["tool"]["poetry"]["version"]
    ver_files = config["tool"]["berhoel"]["helper"]["set_version"]["version_files"]
    for ver_file in ver_files:
        sys.stdout.write(f"writing {ver_file!s}\n")
        with Path(ver_file).resolve().open("w") as target:
            target.write(f'__version__ = "{version}"\n')

berhoel.helper.set_version.build_parser 🔗

build_parser() -> ArgumentParser

Build cli parser.

Source code in src/berhoel/helper/set_version.py
def build_parser() -> argparse.ArgumentParser:
    """Build cli parser."""
    parser = argparse.ArgumentParser(
        prog="set_lib_version",
        description="Create version files with version number from `pyproject.toml`.",
    )
    parser.add_argument(
        "--version",
        action="version",
        version=f"%(prog)s {metadata.version('bhoelHelper')}",
    )
    return parser