Gets the actual class which can then be instantiated with its parameters

        :param tool: The tool name or id
        :type tool: str | unicode | StreamId
        :rtype: Tool | MultiOutputTool
        :return: The tool class

def get_tool_class(self, tool):
        """
        Gets the actual class which can then be instantiated with its parameters

        :param tool: The tool name or id
        :type tool: str | unicode | StreamId
        :rtype: Tool | MultiOutputTool
        :return: The tool class
        """
        if isinstance(tool, string_types):
            tool_id = StreamId(tool)
        elif isinstance(tool, StreamId):
            tool_id = tool
        else:
            raise TypeError(tool)

        tool_stream_view = None

        # Look in the main tool channel first
        if tool_id in self.tools:
            tool_stream_view = self.tools[tool_id].window((MIN_DATE, self.tools.up_to_timestamp))
        else:
            # Otherwise look through all the channels in the order they were defined
            for tool_channel in self.tool_channels:
                if tool_channel == self.tools:
                    continue
                if tool_id in tool_channel:
                    # noinspection PyTypeChecker
                    tool_stream_view = tool_channel[tool_id].window((MIN_DATE, tool_channel.up_to_timestamp))

        if tool_stream_view is None:
            raise ToolNotFoundError(tool)

        # TODO: Use tool versions - here we just take the latest one
        last = tool_stream_view.last()
        if last is None:
            raise ToolNotFoundError(tool)

        return tool_stream_view.last().value