# Path: grafana_dashboards/exporter.py
# class ProjectProcessor(object):
# 
#     def __init__(self, dashboard_processors):
#         """
# 
#         :type dashboard_processors: list[grafana_dashboards.builder.DashboardExporter]
#         """
#         super(ProjectProcessor, self).__init__()
#         self._dashboard_processors = dashboard_processors
# 
#     def process_projects(self, projects, parent_context=None):
#         """
# 
#         :type projects: list[grafana_dashboards.components.projects.Project]
#         :type parent_context: dict
#         """
#         for project in projects:
#             logger.info("Processing project '%s'", project.name)
#             for context in project.get_contexts(parent_context):
#                 for dashboard in project.get_dashboards():
#                     json_obj = dashboard.gen_json(context)
#                     dashboard_name = context.expand_placeholders(dashboard.name)
#                     for processor in self._dashboard_processors:
#                         processor.process_dashboard(project.name, dashboard_name, json_obj)
# 
# class FileExporter(DashboardExporter):
# 
#     def __init__(self, output_folder):
#         super(FileExporter, self).__init__()
#         self._output_folder = output_folder
#         if not os.path.exists(self._output_folder):
#             os.makedirs(self._output_folder)
#         if not os.path.isdir(self._output_folder):
#             raise Exception("'{0}' must be a directory".format(self._output_folder))
# 
#     def process_dashboard(self, project_name, dashboard_name, dashboard_data):
#         super(FileExporter, self).process_dashboard(project_name, dashboard_name, dashboard_data)
#         dirname = os.path.join(self._output_folder, project_name)
#         try:
#             os.makedirs(dirname)
#         except OSError as e:
#             if e.errno != errno.EEXIST:
#                 raise
# 
#         dashboard_path = os.path.join(dirname, dashboard_name + '.json')
#         logger.info("Saving dashboard '%s' to '%s'", dashboard_name, os.path.abspath(dashboard_path))
#         with open(dashboard_path, 'w') as f:
#             json.dump(dashboard_data, f, sort_keys=True, indent=2, separators=(',', ': '))


import pytest
from mock import patch, MagicMock
from grafana_dashboards.exporter import ProjectProcessor, FileExporter

    # noinspection PyTypeChecker
    processor.process_projects([project], parent_context)

    project.get_contexts.assert_called_once_with(parent_context)
    dashboard.gen_json.assert_called_with(context)
    context.expand_placeholders.assert_called_with(dashboard.name)
    dashboard_processor.process_dashboard.assert_called_once_with(project.name, context.expand_placeholders(),
                                                                  dashboard.gen_json())


@patch('grafana_dashboards.exporter.open', create=True)
@patch('json.dump')
@patch('os.makedirs', return_value=True)
@patch('os.path.isdir', return_value=True)
@patch('os.path.exists', return_value=True)
def test_file_exporter(patch_exists, path_isdir, makedirs, json_dump, mock_file):
    exporter = FileExporter('output_folder')

    dashboard_data = {'some_key': 'some_value'}
    exporter.process_dashboard('project_name', 'dashboard_name', dashboard_data)

    json_dump.assert_called_once_with(dashboard_data, mock_file().__enter__(), sort_keys=True, indent=2,
                                      separators=(',', ': '))


@patch('os.makedirs', side_effect=[True, OSError('testing')])
@patch('os.path.isdir', return_value=True)
@patch('os.path.exists', return_value=False)
def test_file_exporter_path_not_exist(patch_exists, path_isdir, makedirs):

# Path: grafana_dashboards/exporter.py
# class ProjectProcessor(object):
# 
#     def __init__(self, dashboard_processors):
#         """
# 
#         :type dashboard_processors: list[grafana_dashboards.builder.DashboardExporter]
#         """
#         super(ProjectProcessor, self).__init__()
#         self._dashboard_processors = dashboard_processors
# 
#     def process_projects(self, projects, parent_context=None):
#         """
# 
#         :type projects: list[grafana_dashboards.components.projects.Project]
#         :type parent_context: dict
#         """
#         for project in projects:
#             logger.info("Processing project '%s'", project.name)
#             for context in project.get_contexts(parent_context):
#                 for dashboard in project.get_dashboards():
#                     json_obj = dashboard.gen_json(context)
#                     dashboard_name = context.expand_placeholders(dashboard.name)
#                     for processor in self._dashboard_processors:
#                         processor.process_dashboard(project.name, dashboard_name, json_obj)
# 
# class FileExporter(DashboardExporter):
# 
#     def __init__(self, output_folder):
#         super(FileExporter, self).__init__()
#         self._output_folder = output_folder
#         if not os.path.exists(self._output_folder):
#             os.makedirs(self._output_folder)
#         if not os.path.isdir(self._output_folder):
#             raise Exception("'{0}' must be a directory".format(self._output_folder))
# 
#     def process_dashboard(self, project_name, dashboard_name, dashboard_data):
#         super(FileExporter, self).process_dashboard(project_name, dashboard_name, dashboard_data)
#         dirname = os.path.join(self._output_folder, project_name)
#         try:
#             os.makedirs(dirname)
#         except OSError as e:
#             if e.errno != errno.EEXIST:
#                 raise
# 
#         dashboard_path = os.path.join(dirname, dashboard_name + '.json')
#         logger.info("Saving dashboard '%s' to '%s'", dashboard_name, os.path.abspath(dashboard_path))
#         with open(dashboard_path, 'w') as f:
#             json.dump(dashboard_data, f, sort_keys=True, indent=2, separators=(',', ': '))


# Path: tests/grafana_dashboards/test_exporter.py
import pytest
from mock import patch, MagicMock
from grafana_dashboards.exporter import ProjectProcessor, FileExporter


    # noinspection PyTypeChecker
    processor.process_projects([project], parent_context)

    project.get_contexts.assert_called_once_with(parent_context)
    dashboard.gen_json.assert_called_with(context)
    context.expand_placeholders.assert_called_with(dashboard.name)
    dashboard_processor.process_dashboard.assert_called_once_with(project.name, context.expand_placeholders(),
                                                                  dashboard.gen_json())


@patch('grafana_dashboards.exporter.open', create=True)
@patch('json.dump')
@patch('os.makedirs', return_value=True)
@patch('os.path.isdir', return_value=True)
@patch('os.path.exists', return_value=True)
def test_file_exporter(patch_exists, path_isdir, makedirs, json_dump, mock_file):
    exporter = FileExporter('output_folder')

    dashboard_data = {'some_key': 'some_value'}
    exporter.process_dashboard('project_name', 'dashboard_name', dashboard_data)

    json_dump.assert_called_once_with(dashboard_data, mock_file().__enter__(), sort_keys=True, indent=2,
                                      separators=(',', ': '))


@patch('os.makedirs', side_effect=[True, OSError('testing')])
@patch('os.path.isdir', return_value=True)
@patch('os.path.exists', return_value=False)
def test_file_exporter_path_not_exist(patch_exists, path_isdir, makedirs):

    exporter = FileExporter('output_folder')