def str_to_credentials(s):
    '''
    str_to_credentials(s) yields (key, secret) if the given string is a valid representation of a
      set of credentials. Valid representations include '<key>:<secret>' and '<key>\n<secret>'. All
      initial and trailing whitespace is always stripped from both key and scret. If a newline
      appears in the string, then this character always takes precedense as the separator over a
      colon character. The given string may also be a json object, in which case it is parsed and
      considered valid if it is either a 
    '''
    if not pimms.is_str(s): raise ValueError('str_to_credentials requires a string argument')
    s = s.strip()
    # First try a json object:
    try:
        js = json.loads(s)
        return to_credentials(s)
    except Exception: pass
    # must be '<key>\n<secret>' or '<key>:<secret>'
    dat = s.split('\n')
    if len(dat) == 1: dat = s.split(':')
    if len(dat) != 2: raise ValueError('String "%s" does not appear to be a credentials file' % s)
    return tuple([q.strip() for q in dat])
str_to_credentials(s) yields (key, secret) if the given string is a valid representation of a
      set of credentials. Valid representations include '<key>:<secret>' and '<key>\n<secret>'. All
      initial and trailing whitespace is always stripped from both key and scret. If a newline
      appears in the string, then this character always takes precedense as the separator over a
      colon character. The given string may also be a json object, in which case it is parsed and
      considered valid if it is either a