docs: def _hash_internal(method, salt, password):
      """Internal password hash helper.  Supports plaintext without salt,
      unsalted and salted passwords.  In case salted passwords are used
      hmac is used.
      """
      if method == "plain":
          return password, method
  
      if isinstance(password, text_type):
          password = password.encode("utf-8")
  
      if method.startswith("pbkdf2:"):
          args = method[7:].split(":")
          if len(args) not in (1, 2):
              raise ValueError("Invalid number of arguments for PBKDF2")
          method = args.pop(0)
          iterations = args and int(args[0] or 0) or DEFAULT_PBKDF2_ITERATIONS
          is_pbkdf2 = True
          actual_method = "pbkdf2:%s:%d" % (method, iterations)
      else:
          is_pbkdf2 = False
          actual_method = method
  
      if is_pbkdf2:
          if not salt:
              raise ValueError("Salt is required for PBKDF2")
          rv = pbkdf2_hex(password, salt, iterations, hashfunc=method)
      elif salt:
          if isinstance(salt, text_type):
              salt = salt.encode("utf-8")
          mac = _create_mac(salt, password, method)
          rv = mac.hexdigest()
      else:
          rv = hashlib.new(method, password).hexdigest()
      return rv, actual_method