h2o-bindings/bin/bindings.py
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"), ("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())
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"), ("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())
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)