def parse_range(spec):
    """
    Return minimum, maximum, and stepping value for a range.

    Argument `spec` must be a string of the form `LOW:HIGH:STEP`,
    where LOW, HIGH and STEP are (integer or floating-point) numbers.
    Example::

      >>> parse_range('1:10:2')
      (1, 10, 2)

      >>> parse_range('1.0:3.5:0.5')
      (1.0, 3.5, 0.5)

    Note that, as soon as *any* one of LOW, HIGH, STEP is not an
    integer, *all* of them are parsed as Python floats::

      >>> parse_range('1:3:0.5')
      (1.0, 3.0, 0.5)

      >>> parse_range('1.0:3:1')
      (1.0, 3.0, 1.0)

      >>> parse_range('1:3.0:1')
      (1.0, 3.0, 1.0)

    The final part `:STEP` can be omitted if the step is `1`::

      >>> parse_range('2:5')
      (2, 5, 1)

      >>> parse_range('1.0:3.0')
      (1.0, 3.0, 1.0)

    Finally, note that `parse_range` does not perform any kind of
    check on the validity of the resulting range; so it is possible to
    parse a string into an empty range or range specification with
    stepping 0::

      >>> parse_range('1:-5:10')
      (1, -5, 10)

      >>> parse_range('1:2:0')
      (1, 2, 0)

    As a special case to simplify user interfaces, a single number is
    accepted as a *degenerate* range: it will be parsed as a range
    whose content is just the given number::

      >>> parse_range('42')
      (42, 43, 1)
    """
    colons = spec.count(':')
    if colons == 2:
        low, high, step = spec.split(':')
    elif colons == 1:
        low, high = spec.split(':')
        step = '1'
    elif colons == 0:
        low = spec
        if '.' in low:
            high = str(float(low) + 1)
        else:
            high = str(int(low) + 1)
        step = '1'
    else:
        raise ValueError(
            "Argument `spec` must have the form 'LOW:HIGH:STEP', where LOW, HIGH and STEP are (integer or floating-point) numbers."
            )
    if '.' in low or '.' in high or '.' in step:
        low = float(low)
        high = float(high)
        step = float(step)
    else:
        low = int(low)
        high = int(high)
        step = int(step)
    return low, high, step
