# Buggy code
def historian(config_path, **kwargs):
    config = utils.load_config(config_path)
    connection = config.get("connection", None)
    assert connection is not None
    databaseType = connection.get("type", None)
    assert databaseType is not None
    params = connection.get("params", None)
    assert params is not None
    identity = config.get("identity", kwargs.pop("identity", None))

    if databaseType == "sqlite":
        from .db.sqlitefuncts import SqlLiteFuncts as DbFuncts
    elif databaseType == "mysql":
        from .db.mysqlfuncts import MySqlFuncts as DbFuncts
    else:
        _log.error("Unknown database type specified!")
        raise Exception("Unkown database type specified!")

    class SQLHistorian(BaseHistorian):
        """This is a simple example of a historian agent that writes stuff
        to a SQLite database. It is designed to test some of the functionality
        of the BaseHistorianAgent.
        """

        @Core.receiver("onstart")
        def starting(self, sender, **kwargs):
            print(
                "Starting address: {} identity: {}".format(
                    self.core.address, self.core.identity
                )
            )
            try:
                self.reader = DbFuncts(**connection["params"])
            except AttributeError as exc:
                _log.exception(exp)
                self.core.stop()
                return

            self.topic_map = self.reader.get_topic_map()

            if self.core.identity == "platform.historian":
                # Check to see if the platform agent is available, if it isn't then
                # subscribe to the /platform topic to be notified when the platform
                # agent becomes available.
                try:
                    ping = self.vip.ping("platform.agent", "awake?").get(timeout=3)
                    _log.debug("Ping response was? " + str(ping))
                    self.vip.rpc.call(
                        "platform.agent", "register_service", self.core.identity
                    ).get(timeout=3)
                except Unreachable:
                    _log.debug("Could not register historian service")
                finally:
                    self.vip.pubsub.subscribe("pubsub", "/platform", self.__platform)
                    _log.debug("Listening to /platform")

        def __platform(self, peer, sender, bus, topic, headers, message):
            _log.debug("Platform is now: {}".format(message))
            if message == "available" and self.core.identity == "platform.historian":
                gevent.spawn(
                    self.vip.rpc.call,
                    "platform.agent",
                    "register_service",
                    self.core.identity,
                )
                gevent.sleep(0)

        def publish_to_historian(self, to_publish_list):
            _log.debug(
                "publish_to_historian number of items: {}".format(len(to_publish_list))
            )

            # load a topic map if there isn't one yet.
            try:
                self.topic_map.items()
            except:
                self.topic_map = self.reader.get_topic_map()

            for x in to_publish_list:
                ts = x["timestamp"]
                topic = x["topic"]
                value = x["value"]
                # look at the topics that are stored in the database already
                # to see if this topic has a value
                topic_id = self.topic_map.get(topic)

                if topic_id is None:
                    row = self.writer.insert_topic(topic)
                    topic_id = row[0]
                    self.topic_map[topic] = topic_id

                self.writer.insert_data(ts, topic_id, value)

            _log.debug("published {} data values:".format(len(to_publish_list)))
            self.report_all_published()

        def query_topic_list(self):
            if len(self.topic_map) > 0:
                return self.topic_map.keys()
            else:
                # No topics present.
                return []

        def query_historian(
            self, topic, start=None, end=None, skip=0, count=None, order="FIRST_TO_LAST"
        ):
            """This function should return the results of a query in the form:
            {"values": [(timestamp1, value1), (timestamp2, value2), ...],
             "metadata": {"key1": value1, "key2": value2, ...}}

             metadata is not required (The caller will normalize this to {} for you)
            """
            return self.reader.query(
                topic, start=start, end=end, skip=skip, count=count, order=order
            )

        def historian_setup(self):
            try:
                self.writer = DbFuncts(**connection["params"])
            except AttributeError as exc:
                print(exc)
                self.core.stop()

    SQLHistorian.__name__ = "SQLHistorian"
    return SQLHistorian(identity=identity, **kwargs)


# Traceback (TypeError)
2015-08-28 08:38:59,118 (forwarderagent-3.0 6934) volttron.platform.agent.base_historian ERROR: An unhandled exception has occured while publishing to historian.
2015-08-28 08:38:59,119 (forwarderagent-3.0 6934) <stderr> ERROR: Traceback (most recent call last):
2015-08-28 08:38:59,119 (forwarderagent-3.0 6934) <stderr> ERROR:   File "/usr/lib/python2.7/logging/__init__.py", line 851, in emit
2015-08-28 08:38:59,120 (forwarderagent-3.0 6934) <stderr> ERROR:     msg = self.format(record)
2015-08-28 08:38:59,120 (forwarderagent-3.0 6934) <stderr> ERROR:   File "/usr/lib/python2.7/logging/__init__.py", line 724, in format
2015-08-28 08:38:59,120 (forwarderagent-3.0 6934) <stderr> ERROR:     return fmt.format(record)
2015-08-28 08:38:59,120 (forwarderagent-3.0 6934) <stderr> ERROR:   File "/home/volttron/volttron-3x/volttron/platform/agent/utils.py", line 228, in format
2015-08-28 08:38:59,121 (forwarderagent-3.0 6934) <stderr> ERROR:     return jsonapi.dumps(dct)
2015-08-28 08:38:59,121 (forwarderagent-3.0 6934) <stderr> ERROR:   File "/home/volttron/volttron-3x/env/local/lib/python2.7/site-packages/zmq/utils/jsonapi.py", line 40, in dumps
2015-08-28 08:38:59,121 (forwarderagent-3.0 6934) <stderr> ERROR:     s = jsonmod.dumps(o, **kwargs)
2015-08-28 08:38:59,122 (forwarderagent-3.0 6934) <stderr> ERROR:   File "/home/volttron/volttron-3x/env/local/lib/python2.7/site-packages/simplejson/__init__.py", line 397, in dumps
2015-08-28 08:38:59,122 (forwarderagent-3.0 6934) <stderr> ERROR:     **kw).encode(obj)
2015-08-28 08:38:59,122 (forwarderagent-3.0 6934) <stderr> ERROR:   File "/home/volttron/volttron-3x/env/local/lib/python2.7/site-packages/simplejson/encoder.py", line 275, in encode
2015-08-28 08:38:59,122 (forwarderagent-3.0 6934) <stderr> ERROR:     chunks = self.iterencode(o, _one_shot=True)
2015-08-28 08:38:59,123 (forwarderagent-3.0 6934) <stderr> ERROR:   File "/home/volttron/volttron-3x/env/local/lib/python2.7/site-packages/simplejson/encoder.py", line 357, in iterencode
2015-08-28 08:38:59,123 (forwarderagent-3.0 6934) <stderr> ERROR:     return _iterencode(o, 0)
2015-08-28 08:38:59,123 (forwarderagent-3.0 6934) <stderr> ERROR:   File "/home/volttron/volttron-3x/env/local/lib/python2.7/site-packages/simplejson/encoder.py", line 252, in default
2015-08-28 08:38:59,124 (forwarderagent-3.0 6934) <stderr> ERROR:     raise TypeError(repr(o) + " is not JSON serializable")
2015-08-28 08:38:59,124 (forwarderagent-3.0 6934) <stderr> ERROR: TypeError: ProtocolError('previous send operation is not complete',) is not JSON serializable
2015-08-28 08:38:59,124 (forwarderagent-3.0 6934) <stderr> ERROR: Logged from file base_historian.py, line 370

# Fixed code
def historian(config_path, **kwargs):
    config = utils.load_config(config_path)
    connection = config.get("connection", None)
    assert connection is not None
    databaseType = connection.get("type", None)
    assert databaseType is not None
    params = connection.get("params", None)
    assert params is not None
    identity = config.get("identity", kwargs.pop("identity", None))

    if databaseType == "sqlite":
        from .db.sqlitefuncts import SqlLiteFuncts as DbFuncts
    elif databaseType == "mysql":
        from .db.mysqlfuncts import MySqlFuncts as DbFuncts
    else:
        _log.error("Unknown database type specified!")
        raise Exception("Unkown database type specified!")

    class SQLHistorian(BaseHistorian):
        """This is a simple example of a historian agent that writes stuff
        to a SQLite database. It is designed to test some of the functionality
        of the BaseHistorianAgent.
        """

        @Core.receiver("onstart")
        def starting(self, sender, **kwargs):
            print(
                "Starting address: {} identity: {}".format(
                    self.core.address, self.core.identity
                )
            )
            try:
                self.reader = DbFuncts(**connection["params"])
            except AttributeError:
                _log.exception("bad connection parameters")
                self.core.stop()
                return

            self.topic_map = self.reader.get_topic_map()

            if self.core.identity == "platform.historian":
                # Check to see if the platform agent is available, if it isn't then
                # subscribe to the /platform topic to be notified when the platform
                # agent becomes available.
                try:
                    ping = self.vip.ping("platform.agent", "awake?").get(timeout=3)
                    _log.debug("Ping response was? " + str(ping))
                    self.vip.rpc.call(
                        "platform.agent", "register_service", self.core.identity
                    ).get(timeout=3)
                except Unreachable:
                    _log.debug("Could not register historian service")
                finally:
                    self.vip.pubsub.subscribe("pubsub", "/platform", self.__platform)
                    _log.debug("Listening to /platform")

        def __platform(self, peer, sender, bus, topic, headers, message):
            _log.debug("Platform is now: {}".format(message))
            if message == "available" and self.core.identity == "platform.historian":
                gevent.spawn(
                    self.vip.rpc.call,
                    "platform.agent",
                    "register_service",
                    self.core.identity,
                )
                gevent.sleep(0)

        def publish_to_historian(self, to_publish_list):
            _log.debug(
                "publish_to_historian number of items: {}".format(len(to_publish_list))
            )

            # load a topic map if there isn't one yet.
            try:
                self.topic_map.items()
            except:
                self.topic_map = self.reader.get_topic_map()

            for x in to_publish_list:
                ts = x["timestamp"]
                topic = x["topic"]
                value = x["value"]
                # look at the topics that are stored in the database already
                # to see if this topic has a value
                topic_id = self.topic_map.get(topic)

                if topic_id is None:
                    row = self.writer.insert_topic(topic)
                    topic_id = row[0]
                    self.topic_map[topic] = topic_id

                self.writer.insert_data(ts, topic_id, value)

            _log.debug("published {} data values:".format(len(to_publish_list)))
            self.report_all_published()

        def query_topic_list(self):
            if len(self.topic_map) > 0:
                return self.topic_map.keys()
            else:
                # No topics present.
                return []

        def query_historian(
            self, topic, start=None, end=None, skip=0, count=None, order="FIRST_TO_LAST"
        ):
            """This function should return the results of a query in the form:
            {"values": [(timestamp1, value1), (timestamp2, value2), ...],
             "metadata": {"key1": value1, "key2": value2, ...}}

             metadata is not required (The caller will normalize this to {} for you)
            """
            return self.reader.query(
                topic, start=start, end=end, skip=skip, count=count, order=order
            )

        def historian_setup(self):
            try:
                self.writer = DbFuncts(**connection["params"])
            except AttributeError as exc:
                print(exc)
                self.core.stop()

    SQLHistorian.__name__ = "SQLHistorian"
    return SQLHistorian(identity=identity, **kwargs)