# Path: sacredboard/app/data/rundao.py
# class RunDAO:
#     """
#     Interface for accessing Runs.
# 
#     Issue: https://github.com/chovanecm/sacredboard/issues/69
#     """
# 
#     def get(self, run_id):
#         """
#         Return the run associated with the id.
# 
#         :raise NotFoundError when not found
#         """
#         raise NotImplementedError("RunDAO is abstract.")
# 
#     def get_runs(self, sort_by=None, sort_direction=None,
#                  start=0, limit=None, query={"type": "and", "filters": []}):
#         """Return all runs that match the query."""
#         raise NotImplementedError("RunDAO is abstract.")
# 
#     def delete(self, run_id):
#         """
#         Delete run with the given id from the backend.
# 
#         :param run_id: Id of the run to delete.
#         :raise NotImplementedError If not supported by the backend.
#         :raise DataSourceError General data source error.
#         :raise NotFoundError The run was not found. (Some backends may succeed
#         even if the run does not exist.
#         """
#         raise NotImplementedError(
#             "This database data source does not currently support this "
#             "operation.")
# 
# Path: sacredboard/app/data/errors.py
# class NotFoundError(Exception):
#     """Record not found exception."""
# 
#     def __init__(self, *args, **kwargs):
#         """Record not found exception."""
#         Exception.__init__(self, *args, **kwargs)
# 
# Path: sacredboard/app/data/filesdao.py
# class FilesDAO:
#     """Interface for accessing files."""
# 
#     def get(self, file_id) -> [typing.BinaryIO, str, datetime.datetime]:
#         """
#         Return the file associated with the id as binary stream and its filename and upload date.
# 
#         :raise NotFoundError when not found
#         """
#         raise NotImplementedError("RunDAO is abstract.")
# 
# Path: sacredboard/app/data/metricsdao.py
# class MetricsDAO:
#     """
#     Interface for accessing Sacred metrics.
# 
#     Issue: https://github.com/chovanecm/sacredboard/issues/58
# 
#     Extended because of: https://github.com/chovanecm/sacredboard/issues/66
#     """
# 
#     def get(self, run_id, metric_id):
#         """
#         Read a metric of the given id and run.
# 
#         The returned object has the following format (timestamps are datetime
#          objects).
# 
#         .. code::
# 
#             {"steps": [0,1,20,40,...],
#             "timestamps": [timestamp1,timestamp2,timestamp3,...],
#             "values": [0,1 2,3,4,5,6,...],
#             "name": "name of the metric",
#             "metric_id": "metric_id",
#             "run_id": "run_id"}
# 
#         :param run_id: ID of the Run that the metric belongs to.
#         :param metric_id: The ID fo the metric.
#         :return: The whole metric as specified.
# 
#         :raise NotFoundError
#         """
#         raise NotImplementedError("The MetricsDAO class is abstract.")
# 
#     def delete(self, run_id):
#         """
#         Delete all metrics belonging to the given run.
# 
#         :param run_id: ID of the Run that the metric belongs to.
#         """
#         raise NotImplementedError("The MetricsDAO class is abstract.")


from sacredboard.app.data.rundao import RunDAO
from .errors import NotFoundError
from .filesdao import FilesDAO
from .metricsdao import MetricsDAO
    def get_metrics_dao(self) -> MetricsDAO:
        """
        Return a data access object for metrics.

        By default, returns a dummy Data Access Object if not overridden.
        Issue: https://github.com/chovanecm/sacredboard/issues/62

        :return MetricsDAO
        """
        return DummyMetricsDAO()

    def get_run_dao(self) -> RunDAO:
        """
        Return a data access object for Runs.

        :return: RunDAO
        """
        raise NotImplementedError(
            "Run Data Access Object must be implemented.")

    def get_files_dao(self) -> FilesDAO:
        """
        Return a data access object for files.

        :return: FilesDAO
        """
        raise NotImplementedError(
            "Artifacts Data Access Object must be implemented.")



# Path: sacredboard/app/data/rundao.py
# class RunDAO:
#     """
#     Interface for accessing Runs.
# 
#     Issue: https://github.com/chovanecm/sacredboard/issues/69
#     """
# 
#     def get(self, run_id):
#         """
#         Return the run associated with the id.
# 
#         :raise NotFoundError when not found
#         """
#         raise NotImplementedError("RunDAO is abstract.")
# 
#     def get_runs(self, sort_by=None, sort_direction=None,
#                  start=0, limit=None, query={"type": "and", "filters": []}):
#         """Return all runs that match the query."""
#         raise NotImplementedError("RunDAO is abstract.")
# 
#     def delete(self, run_id):
#         """
#         Delete run with the given id from the backend.
# 
#         :param run_id: Id of the run to delete.
#         :raise NotImplementedError If not supported by the backend.
#         :raise DataSourceError General data source error.
#         :raise NotFoundError The run was not found. (Some backends may succeed
#         even if the run does not exist.
#         """
#         raise NotImplementedError(
#             "This database data source does not currently support this "
#             "operation.")
# 
# Path: sacredboard/app/data/errors.py
# class NotFoundError(Exception):
#     """Record not found exception."""
# 
#     def __init__(self, *args, **kwargs):
#         """Record not found exception."""
#         Exception.__init__(self, *args, **kwargs)
# 
# Path: sacredboard/app/data/filesdao.py
# class FilesDAO:
#     """Interface for accessing files."""
# 
#     def get(self, file_id) -> [typing.BinaryIO, str, datetime.datetime]:
#         """
#         Return the file associated with the id as binary stream and its filename and upload date.
# 
#         :raise NotFoundError when not found
#         """
#         raise NotImplementedError("RunDAO is abstract.")
# 
# Path: sacredboard/app/data/metricsdao.py
# class MetricsDAO:
#     """
#     Interface for accessing Sacred metrics.
# 
#     Issue: https://github.com/chovanecm/sacredboard/issues/58
# 
#     Extended because of: https://github.com/chovanecm/sacredboard/issues/66
#     """
# 
#     def get(self, run_id, metric_id):
#         """
#         Read a metric of the given id and run.
# 
#         The returned object has the following format (timestamps are datetime
#          objects).
# 
#         .. code::
# 
#             {"steps": [0,1,20,40,...],
#             "timestamps": [timestamp1,timestamp2,timestamp3,...],
#             "values": [0,1 2,3,4,5,6,...],
#             "name": "name of the metric",
#             "metric_id": "metric_id",
#             "run_id": "run_id"}
# 
#         :param run_id: ID of the Run that the metric belongs to.
#         :param metric_id: The ID fo the metric.
#         :return: The whole metric as specified.
# 
#         :raise NotFoundError
#         """
#         raise NotImplementedError("The MetricsDAO class is abstract.")
# 
#     def delete(self, run_id):
#         """
#         Delete all metrics belonging to the given run.
# 
#         :param run_id: ID of the Run that the metric belongs to.
#         """
#         raise NotImplementedError("The MetricsDAO class is abstract.")


# Path: sacredboard/app/data/datastorage.py
from sacredboard.app.data.rundao import RunDAO
from .errors import NotFoundError
from .filesdao import FilesDAO
from .metricsdao import MetricsDAO

    def get_metrics_dao(self) -> MetricsDAO:
        """
        Return a data access object for metrics.

        By default, returns a dummy Data Access Object if not overridden.
        Issue: https://github.com/chovanecm/sacredboard/issues/62

        :return MetricsDAO
        """
        return DummyMetricsDAO()

    def get_run_dao(self) -> RunDAO:
        """
        Return a data access object for Runs.

        :return: RunDAO
        """
        raise NotImplementedError(
            "Run Data Access Object must be implemented.")

    def get_files_dao(self) -> FilesDAO:
        """
        Return a data access object for files.

        :return: FilesDAO
        """
        raise NotImplementedError(
            "Artifacts Data Access Object must be implemented.")



class DummyMetricsDAO(MetricsDAO):