docs: def numpy_type(type_id):
      '''
      numpy_type(type) yields a tuple of valid numpy types that can represent the type specified in
        the given type argument. The type argument may be a numpy type such as numpy.signedinteger, in
        which case a tuple containing only it is returned. Alternately, it may be a string that labels
        a numpy type or a builtin type that should be translated to a numpy type (see below).
  
      Note that numpy_types() does note intend to reproduce the numpy type hierarchy! If you want to
      perform comparisons on the numpy hierarchy, use numpy's functions. Rather, numpy_type()
      represents types in a mathematical hierarchy, so, for example, numpy_type('real') yields the
      tuple (numpy.floating, numpy.integer, numpy.bool_) because all of these are valid real numbers.
  
      Valid numpy type strings include:
        * 'bool'
        * 'int' / 'integer' (integers and booleans)
        * 'float' / 'real' (integers, booleans, or floating-point)
        * 'complex' / 'number' (integers, booleans, reals, or complex numbers)
        * 'string' ('unicode' in Python 3, 'bytes' in Python 2)
        * 'unicode'
        * 'bytes'
        * 'chars' (numpy.character)
        * 'object'
        * 'any'
      Valid builtin types include:
        * int (also long in Python 2), like 'int'
        * float, like 'float'
        * complex, like 'complex'
        * str, like 'string'
        * bytes, like 'bytes',
        * unicode, like 'unicode'
        * object, like 'object'
        * None, like 'any'
      '''
      if is_str(type_id):
          return _numpy_type_names[type_id.lower()]
      elif isinstance(type_id, (list, tuple)):
          return tuple([dt for s in type_id for dt in numpy_type(s)])
      elif type_id is None:
          return _numpy_type_names['any']
      elif type_id in six.integer_types:       return _numpy_type_names['int']
      elif type_id is float:                   return _numpy_type_names['float']
      elif type_id is numbers.Real:            return _numpy_type_names['real']
      elif type_id is complex:                 return _numpy_type_names['complex']
      elif type_id is numbers.Complex:         return _numpy_type_names['complex']
      elif type_id is bool:                    return _numpy_type_names['bool']
      elif type_id is str:                     return _numpy_type_names['string']
      elif type_id is unicode:                 return _numpy_type_names['unicode']
      elif type_id is bytes:                   return _numpy_type_names['bytes']
      elif type_id is object:                  return _numpy_type_names['object']
      elif np.issubdtype(type_id, np.generic): return (type_id,)
      else: raise ValueError('Could not deduce numpy type for %s' % type_id)