# Path: craft_ai/pandas/constants.py
# MISSING_VALUE = MissingValue()
# 
# OPTIONAL_VALUE = OptionalValue()
# 
# Path: craft_ai/constants.py
# REACT_CRAFT_AI_DECISION_TREE_VERSION = "0.0.23"
# 
# Path: craft_ai/errors.py
# class CraftAiError(Exception):
#     """Base class for exceptions in the craft ai client."""
# 
#     def __init__(self, message=None, metadata=None):
#         self.message = message
#         self.metadata = metadata
#         super(CraftAiError, self).__init__(message, metadata)
# 
#     def __str__(self):
#         return repr(self.message)


import json
import re
import string
import importlib
import pandas as pd
from random import choice
from semver import VersionInfo
from .constants import (
    MISSING_VALUE,
    OPTIONAL_VALUE,
)
from ..constants import REACT_CRAFT_AI_DECISION_TREE_VERSION
from ..errors import CraftAiError
            or isinstance(value, str)
            or value == MISSING_VALUE
            or value == OPTIONAL_VALUE
            or value is None
        )
        and not pd.isna(value)
    )


# Helper
def create_timezone_df(df, name):
    timezone_df = pd.DataFrame(index=df.index)
    if name in df.columns:
        timezone_df[name] = df[name].fillna(method="ffill")
    else:
        timezone_df[name] = df.index.strftime("%z")
    return timezone_df


def random_string(length=20):
    return "".join(choice(string.ascii_letters) for x in range(length))


# Return a html version of the given tree
def create_tree_html(tree_object, selected_node, edge_type, folded_nodes, height=500):
    html_template = """ <html>
    <head>
        <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin defer>
        </script>
        <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin defer>

# Path: craft_ai/pandas/constants.py
# MISSING_VALUE = MissingValue()
# 
# OPTIONAL_VALUE = OptionalValue()
# 
# Path: craft_ai/constants.py
# REACT_CRAFT_AI_DECISION_TREE_VERSION = "0.0.23"
# 
# Path: craft_ai/errors.py
# class CraftAiError(Exception):
#     """Base class for exceptions in the craft ai client."""
# 
#     def __init__(self, message=None, metadata=None):
#         self.message = message
#         self.metadata = metadata
#         super(CraftAiError, self).__init__(message, metadata)
# 
#     def __str__(self):
#         return repr(self.message)


# Path: craft_ai/pandas/utils.py
import json
import re
import string
import importlib
import pandas as pd
from random import choice
from semver import VersionInfo
from .constants import (
    MISSING_VALUE,
    OPTIONAL_VALUE,
)
from ..constants import REACT_CRAFT_AI_DECISION_TREE_VERSION
from ..errors import CraftAiError

            or isinstance(value, str)
            or value == MISSING_VALUE
            or value == OPTIONAL_VALUE
            or value is None
        )
        and not pd.isna(value)
    )


# Helper
def create_timezone_df(df, name):
    timezone_df = pd.DataFrame(index=df.index)
    if name in df.columns:
        timezone_df[name] = df[name].fillna(method="ffill")
    else:
        timezone_df[name] = df.index.strftime("%z")
    return timezone_df


def random_string(length=20):
    return "".join(choice(string.ascii_letters) for x in range(length))


# Return a html version of the given tree
def create_tree_html(tree_object, selected_node, edge_type, folded_nodes, height=500):
    html_template = """ <html>
    <head>
        <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin defer>
        </script>
        <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin defer>

        </script>