code: def endpoints(raw=False):
      """
      Return the list of REST API endpoints. The data is enriched with the following fields:
        class_name: which back-end class handles this endpoint (the class is derived from the URL);
        ischema: input schema object (input_schema is the schema's name)
        oschema: output schema object (output_schema is the schema's name)
        algo: for special-cased calls (ModelBuilders/train and Grid/train) -- name of the ML algo requested
        input_params: list of all input parameters (first path parameters, then all the others). The parameters are
              given as objects, not just names. There is a flag "is_path_param" on each field.
      Additionally certain buggy/deprecated endpoints are removed.
      For Grid/train and ModelBuilders/train endpoints we fix the method name and parameters info (there is some mangling
      of those on the server side).
  
        :param raw: if True, then the complete untouched response to .../endpoints is returned (including the metadata)
      """
      json = _request_or_exit("/3/Metadata/endpoints")
      if raw:
          return json
  
      schmap = schemas_map()
      apinames = {}  # Used for checking for api name duplicates
      assert (
          "routes" in json
      ), "Unexpected result from /3/Metadata/endpoints call"
      re_api_name = re.compile(r"^\w+$")
  
      def gen_rich_route():
          for e in json["routes"]:
              path = e["url_pattern"]
              method = e["handler_method"]
              apiname = e["api_name"]
              assert (
                  apiname not in apinames
              ), "Duplicate api name %s (for %s and %s)" % (
                  apiname,
                  apinames[apiname],
                  path,
              )
              assert re_api_name.match(apiname), (
                  "Bad api name %s" % apiname
              )
              apinames[apiname] = path
  
              # These redundant paths cause conflicts, remove them
              if (
                  path
                  == "/3/NodePersistentStorage/categories/{category}/exists"
              ):
                  continue
              if (
                  path
                  == "/3/ModelMetrics/frames/{frame}/models/{model}"
              ):
                  continue
              if path == "/3/ModelMetrics/frames/{frame}":
                  continue
              if path == "/3/ModelMetrics/models/{model}":
                  continue
              if path == "/3/ModelMetrics":
                  continue
              if "AutoML" in path:
                  continue  # Generation code doesn't know how to deal with defaults for complex objects yet
              if apiname.endswith("_deprecated"):
                  continue
  
              # Resolve one name conflict
              if path == "/3/DKV":
                  e["handler_method"] = "removeAll"
  
              # Find the class_name (first part of the URL after the version: "/3/About" => "About")
              mm = classname_pattern.match(path)
              assert mm, "Cannot determine class name in URL " + path
              e["class_name"] = mm.group(1)
              if e["class_name"].islower():
                  e["class_name"] = e["class_name"].capitalize()
  
              # Resolve input/output schemas into actual objects
              assert (
                  e["input_schema"] in schmap
              ), "Encountered unknown schema %s in %s" % (
                  e["input_schema"],
                  path,
              )
              assert (
                  e["output_schema"] in schmap
              ), "Encountered unknown schema %s in %s" % (
                  e["output_schema"],
                  path,
              )
              e["ischema"] = schmap[e["input_schema"]]
              e["oschema"] = schmap[e["output_schema"]]
  
              # For these special cases, the actual input schema is not the one reported by the endpoint, but the schema
              # of the 'parameters' field (which is fake).
              if (e["class_name"], method) in {
                  ("Grid", "train"),
                  ("Grid", "resume"),
                  ("ModelBuilders", "train"),
                  ("ModelBuilders", "validate_parameters"),
              }:
                  pieces = path.split("/")
                  assert len(pieces) >= 4, (
                      "Expected to see algo name in the path: " + path
                  )
                  e["algo"] = pieces[3]
                  method = (
                      method + e["algo"].capitalize()
                  )  # e.g. trainGlm()
                  e["handler_method"] = method
                  for field in e["ischema"]["fields"]:
                      if field["name"] == "parameters":
                          e["input_schema"] = field["schema_name"]
                          e["ischema"] = schmap[e["input_schema"]]
                          break
  
              # Create the list of input_params (as objects, not just names)
              e["input_params"] = []
              for parm in e["path_params"]:
                  # find the metadata for the field from the input schema:
                  fields = [
                      field
                      for field in e["ischema"]["fields"]
                      if field["name"] == parm
                  ]
                  assert len(fields) == 1, (
                      "Failed to find parameter: %s for endpoint: %s in the input schema %s"
                      % (parm, e["url_pattern"], e["ischema"]["name"])
                  )
                  field = fields[0].copy()
                  schema = (
                      field["schema_name"] or ""
                  )  # {schema} is null for primitive types
                  ftype = field["type"]
                  assert (
                      ftype == "string"
                      or ftype == "int"
                      or schema.endswith("KeyV3")
                      or schema == "ColSpecifierV3"
                  ), "Unexpected param %s of type %s (schema %s)" % (
                      field["name"],
                      ftype,
                      schema,
                  )
                  assert field["direction"] != "OUTPUT", (
                      "A path param %s cannot be of type OUTPUT"
                      % field["name"]
                  )
                  field["is_path_param"] = True
                  field["required"] = True
                  e["input_params"].append(field)
              for parm in e["ischema"]["fields"]:
                  if (
                      parm["direction"] == "OUTPUT"
                      or parm["name"] in e["path_params"]
                  ):
                      continue
                  field = parm.copy()
                  field["is_path_param"] = False
                  e["input_params"].append(field)
              yield e
  
      return list(gen_rich_route())
  
imports: import argparse
  import atexit
  import codecs
  import errno
  import os
  import platform
  import pprint
  import re
  import requests
  import shutil
  import sys
  import textwrap
  import time
  from collections import defaultdict
label_desc: Use image node_id 7 for calling a global function with example usage: endpoints(raw) and returns: list, json