1 comment

[ 3.0 ms ] story [ 9.9 ms ] thread
My Mom does quilting, and one of her specialties is selvage quilts, so I have some idea of what good quilts look like. This collection has some very odd functions.

Take "colourcode". Why is there a 'longhex' at all? Why not have a 'destinationtype' which is "longhex" in addition to the existing "hex"? That makes it much easier to implement the code as a dispatch table, rather than a lengthy if/else chain (with multiple lower() calls!). For example:

  _colourcode_ops = {
    "hex": lambda c: c.hex,
    "longhex": lambda c: c.hex_l,
    "hsl": lambda c: c.hsl,
      ...
  }
  def colourcode(startcolourcode, destinationtype):
    ...
    c = colour.Color(str(startcolourcode))
    op = _colourcode_ops.get(destinationtype.lower())
    if op is not None:
      return op(c)
    raise ValueError(f"Unsupported destinationtype: {destinationtype}")
The 'destinationtype' docstring is confusing because the code normalizes to lowercase, so why do the examples show "HEX, HSL, RGB, red, blue, green, hue" instead of a all upper or all lower?

Oh, and I believe raising a ValueError ("Raised when an operation or function receives an argument that has the right type but an inappropriate value, and the situation is not described by a more precise exception") is better than a RuntimeWarning ("Base class for warnings about dubious runtime behavior") since 1) this isn't a warning, and 2) it doesn't deal with runtime behavior in the way Python intends.

As another example, consider:

    def posnegtoggle(number):
        if bool(number > 0):
            return number - number * 2
        elif bool(number < 0):
            return number + abs(number) * 2
        elif bool(number == 0):
            return number
There's no need for the bool() of a comparison because the reference manual says "Comparisons yield boolean values". And, what's the point? Why would someone use this instead of unary negation? Note that:

  >>> math.inf
  inf
  >>> -math.inf
  -inf
  >>> posnegtoggle(math.inf)
  nan
Furthermore, math.nan is a number, but the above returns None for posnegtoggle(math.nan) when it should return the original nan.

The isfib() also doesn't expect math.inf as an input value.

I think the following function:

  def isinfinite(variable):
    return bool(math.isfinite(variable))
should be written:

  def isinfinite(variable):
    return not math.isfinite(variable)
but again, I don't see the point of calling that function instead of just using "not math.isfinite()" directly.

As far as I can tell, "hcf()" always returns 1. Is it supposed to be the same as math.gcd()? I think the loop is supposed to be range(smaller, 0, -1).

fracsimplify() should use the fractions built-in module. Then it wouldn't have the bug that fracsimplify(6, 4) reduces to "6/4" instead of "3/2". This is Python 3 so use numerator//2 instead of int(numerator / 2).