# Path: craft_ai/errors.py
# class CraftAiError(Exception):
# class CraftAiUnknownError(CraftAiError):
# class CraftAiNetworkError(CraftAiError):
# class CraftAiCredentialsError(CraftAiError):
# class CraftAiInternalError(CraftAiError):
# class CraftAiBadRequestError(CraftAiError):
# class CraftAiNotFoundError(CraftAiError):
# class CraftAiDecisionError(CraftAiError):
# class CraftAiNullDecisionError(CraftAiDecisionError):
# class CraftAiTimeError(CraftAiError):
# class CraftAiTokenError(CraftAiError):
# class CraftAiLongRequestTimeOutError(CraftAiError):
#     def __init__(self, message=None, metadata=None):
#     def __str__(self):
# 
# Path: craft_ai/tree_utils.py
# def extract_decision_paths_from_tree(tree):
#     """
#     Retrieve all the decision paths from a tree.
# 
#     This function accepts trees as retrieved from `craft_ai.Client.get_generator_decision_tree`.
# 
#     Parameters:
#         tree: A tree.
#     Returns: e.g. ['0', '0-0', '0-1']
#     """
#     return _get_paths(extract_output_tree(tree))
# 
# def extract_decision_path_neighbors(
#     tree, decision_path, max_depth=None, include_self=False
# ):
#     """
#     Retrieve neighbor of a decision path in a tree.
# 
#     This function accepts trees as retrieved from `craft_ai.Client.get_generator_decision_tree`.
# 
#     Parameters:
#         tree: A tree.
#         decision_path: string tree path eg. "0-2-1".
#         max_depth (int, optional): positive int filter neighbours on their depth,
#             default is None.
#         include_self (bool, optional): include the given decision_path to the neighbours,
#             default is False.
#     """
#     paths = _get_paths(extract_output_tree(tree))
#     if decision_path not in paths:
#         raise CraftAiError(
#             """Invalid decision path given. """
#             """{} not found in tree""".format(decision_path)
#         )
# 
#     dp_depth = len(decision_path.split("-"))
#     neighbours = _get_neighbours(paths, decision_path)
#     if max_depth is None:
#         max_depth = dp_depth
#     if max_depth < 0:
#         raise CraftAiError(
#             """Invalid max depth given: {} should be None or a positive integer """.format(
#                 max_depth
#             )
#         )
#     filtered = [n for n in neighbours if len(n.split("-")) <= max_depth]
#     if include_self:
#         filtered.append(decision_path)
#     return filtered
# 
# def extract_output_tree(tree, output_property=None):
#     """
#     Extract the output decision tree specific for a given output property from a full decision tree.
# 
#     This function accepts trees as retrieved from `craft_ai.Client.get_generator_decision_tree`.
# 
#     Parameters:
#         tree: A tree.
#         output_property (optional): If provided, the output property for which the tree predicts
#             values, otherwise the first defined tree is retrieved.
#     """
#     if not isinstance(tree, dict):
#         raise CraftAiError(
#             """Unable to retrieve the output tree, """
#             """the given decision tree format is not a valid, expected a 'dict' got a {}.""".format(
#                 type(tree)
#             )
#         )
#     if "trees" not in tree:
#         raise CraftAiError(
#             """Unable to retrieve the output tree, """
#             """the given decision tree format is not a valid, no 'trees' property defined."""
#         )
#     trees = tree["trees"]
#     if not output_property:
#         output_property = list(trees)[0]
#     if output_property not in trees:
#         raise CraftAiError(
#             """'{}' output tree can't be found in the given decision tree.""".format(
#                 output_property
#             )
#         )
#         tree = tree["trees"][output_property]
#     return trees[output_property]


import unittest
import json
import os
from craft_ai import (
    errors,
    extract_decision_paths_from_tree,
    extract_decision_path_neighbors,
    extract_output_tree,
)



HERE = os.path.abspath(os.path.dirname(__file__))
DATA_DIR = os.path.join(HERE, "data", "interpreter")

TREES_DIR = os.path.join(DATA_DIR, "decide", "trees")
PATH_DIR = os.path.join(DATA_DIR, "tree_computations_expectations", "get_paths")
NEIGHBOURS_DIR = os.path.join(
    DATA_DIR, "tree_computations_expectations", "get_neighbours"
)


class TestTreeUtils(unittest.TestCase):
    def test_extract_output_tree_invalid_tree_1(self):
        path = os.path.join(DATA_DIR, "decide", "trees", "v1", "emptyArray.json")
        tree = None
        with open(path) as f:
            tree = json.load(f)
        self.assertRaises(errors.CraftAiError, extract_output_tree, tree)

    def test_extract_output_tree_invalid_tree_2(self):
        path = os.path.join(DATA_DIR, "decide", "trees", "v1", "emptyObject.json")
        tree = None
        with open(path) as f:
            tree = json.load(f)

# Path: craft_ai/errors.py
# class CraftAiError(Exception):
# class CraftAiUnknownError(CraftAiError):
# class CraftAiNetworkError(CraftAiError):
# class CraftAiCredentialsError(CraftAiError):
# class CraftAiInternalError(CraftAiError):
# class CraftAiBadRequestError(CraftAiError):
# class CraftAiNotFoundError(CraftAiError):
# class CraftAiDecisionError(CraftAiError):
# class CraftAiNullDecisionError(CraftAiDecisionError):
# class CraftAiTimeError(CraftAiError):
# class CraftAiTokenError(CraftAiError):
# class CraftAiLongRequestTimeOutError(CraftAiError):
#     def __init__(self, message=None, metadata=None):
#     def __str__(self):
# 
# Path: craft_ai/tree_utils.py
# def extract_decision_paths_from_tree(tree):
#     """
#     Retrieve all the decision paths from a tree.
# 
#     This function accepts trees as retrieved from `craft_ai.Client.get_generator_decision_tree`.
# 
#     Parameters:
#         tree: A tree.
#     Returns: e.g. ['0', '0-0', '0-1']
#     """
#     return _get_paths(extract_output_tree(tree))
# 
# def extract_decision_path_neighbors(
#     tree, decision_path, max_depth=None, include_self=False
# ):
#     """
#     Retrieve neighbor of a decision path in a tree.
# 
#     This function accepts trees as retrieved from `craft_ai.Client.get_generator_decision_tree`.
# 
#     Parameters:
#         tree: A tree.
#         decision_path: string tree path eg. "0-2-1".
#         max_depth (int, optional): positive int filter neighbours on their depth,
#             default is None.
#         include_self (bool, optional): include the given decision_path to the neighbours,
#             default is False.
#     """
#     paths = _get_paths(extract_output_tree(tree))
#     if decision_path not in paths:
#         raise CraftAiError(
#             """Invalid decision path given. """
#             """{} not found in tree""".format(decision_path)
#         )
# 
#     dp_depth = len(decision_path.split("-"))
#     neighbours = _get_neighbours(paths, decision_path)
#     if max_depth is None:
#         max_depth = dp_depth
#     if max_depth < 0:
#         raise CraftAiError(
#             """Invalid max depth given: {} should be None or a positive integer """.format(
#                 max_depth
#             )
#         )
#     filtered = [n for n in neighbours if len(n.split("-")) <= max_depth]
#     if include_self:
#         filtered.append(decision_path)
#     return filtered
# 
# def extract_output_tree(tree, output_property=None):
#     """
#     Extract the output decision tree specific for a given output property from a full decision tree.
# 
#     This function accepts trees as retrieved from `craft_ai.Client.get_generator_decision_tree`.
# 
#     Parameters:
#         tree: A tree.
#         output_property (optional): If provided, the output property for which the tree predicts
#             values, otherwise the first defined tree is retrieved.
#     """
#     if not isinstance(tree, dict):
#         raise CraftAiError(
#             """Unable to retrieve the output tree, """
#             """the given decision tree format is not a valid, expected a 'dict' got a {}.""".format(
#                 type(tree)
#             )
#         )
#     if "trees" not in tree:
#         raise CraftAiError(
#             """Unable to retrieve the output tree, """
#             """the given decision tree format is not a valid, no 'trees' property defined."""
#         )
#     trees = tree["trees"]
#     if not output_property:
#         output_property = list(trees)[0]
#     if output_property not in trees:
#         raise CraftAiError(
#             """'{}' output tree can't be found in the given decision tree.""".format(
#                 output_property
#             )
#         )
#         tree = tree["trees"][output_property]
#     return trees[output_property]


# Path: tests/test_tree_utils.py
import unittest
import json
import os
from craft_ai import (
    errors,
    extract_decision_paths_from_tree,
    extract_decision_path_neighbors,
    extract_output_tree,
)




HERE = os.path.abspath(os.path.dirname(__file__))
DATA_DIR = os.path.join(HERE, "data", "interpreter")

TREES_DIR = os.path.join(DATA_DIR, "decide", "trees")
PATH_DIR = os.path.join(DATA_DIR, "tree_computations_expectations", "get_paths")
NEIGHBOURS_DIR = os.path.join(
    DATA_DIR, "tree_computations_expectations", "get_neighbours"
)


class TestTreeUtils(unittest.TestCase):
    def test_extract_output_tree_invalid_tree_1(self):
        path = os.path.join(DATA_DIR, "decide", "trees", "v1", "emptyArray.json")
        tree = None
        with open(path) as f:
            tree = json.load(f)
        self.assertRaises(errors.CraftAiError, extract_output_tree, tree)

    def test_extract_output_tree_invalid_tree_2(self):
        path = os.path.join(DATA_DIR, "decide", "trees", "v1", "emptyObject.json")
        tree = None
        with open(path) as f:
            tree = json.load(f)

        self.assertRaises(errors.CraftAiError, extract_output_tree, tree)