# Path: firefly/data_sources/graphite_http.py
# class GraphiteHTTP(firefly.data_source.DataSource):
#     """
#     Stats from graphite-web's HTTP endpoint
# 
#     :param graphite_url: Graphite-web URL
#     """
#     DESC = "GraphiteHTTP"
# 
#     def __init__(self, *args, **kwargs):
#         super(GraphiteHTTP, self).__init__(*args, **kwargs)
#         self.graphite_url = kwargs['graphite_url']
# 
#     def list_path(self, path):
#         """
#         Given a graphite metric name split up into it's segments,
#         return a list of the next possible segments.
# 
#         Sample input entry from graphite:
#         {
#             "leaf": 0,
#             "context": {},
#             "text": "activemq",
#             "expandable": 1,
#             "id": "activemq",
#             "allowChildren": 1
#         }
# 
#         Sample output entry to firely:
#         {
#             'type': 'dir',
#             'name': name,
#             'children': None
#         }
# 
#         :param path: list of path components as strings
#         :return: list of dicts containing the path entries
#         """
#         params = {
#             'query' : '.'.join(path + ['*']),
#             'format': 'treejson',
#         }
#         find_url = urljoin(self.graphite_url, 'metrics/find/?%s' % '&'.join(['%s=%s' % (k,v) for k,v in params.items()]))
#         find_json = urlopen(find_url).read()
#         find_results = json.loads(find_json)
# 
#         contents = list()
#         for result in sorted(find_results, key=lambda result: result['text']):
#             if result['leaf'] == 0:
#                 contents.extend(self._form_entries_from_dir(result['text']))
#             elif result['leaf'] == 1:
#                 contents.extend(self._form_entries_from_file(result['text']))
#             else:
#                 raise Exception('Unexpected value for leaf in result: %s' % result)
#         return contents
# 
#     def _form_entries_from_dir(self, name):
#         return [{'type': 'dir', 'name': name, 'children': None}]
# 
#     def _form_entries_from_file(self, name):
#         return [{'type': 'file', 'name': name}]
# 
#     def data(self, sources, start, end, width):
#         """
#         :param sources: list of list of path segments
#         :param start: timestamp like 1391044540
#         :param end: timestamp like 1391048200
#         :param width: ignored
#         :return: json string
#         """
#         # Unfortunately, the most granular unit of time that graphite supports via this API is minute.
#         fmt = '%H:%M_%Y%m%d'
#         from_str = datetime.fromtimestamp(start).strftime(fmt)
#         until_str = datetime.fromtimestamp(end).strftime(fmt)
# 
#         serieses = []
#         step = None
# 
#         # TODO: Minimize the number of http calls -- handle multiple sources in a single call
#         for metric_segments in sources:
#             metric_name = '.'.join(metric_segments)
#             params = {
#                 'target': metric_name,
#                 'format': 'json',
#                 'from' : from_str,
#                 'until': until_str,
#             }
#             render_url = urljoin(self.graphite_url, 'render/?%s' % '&'.join(['%s=%s' % (k,v) for k,v in params.items()]))
#             render_json = urlopen(render_url).read()
#             render_results = json.loads(render_json)
# 
#             values = []
#             for result in render_results:
#                 for datapoint in result['datapoints']:
#                     values.append(datapoint[0])
# 
#             # Compute step and make sure it is consistent across all metrics
#             current_step = (end - start) / (len(values) - 1)
#             if step is None:
#                 step = current_step
#             elif current_step != step:
#                 self.logger.error('Number of values from two different serieses does not match! %s != %s' % (step, current_step))
#             serieses.append(values)
# 
#         out = []
#         for timestamp, values in izip(xrange(start, end+step, step), izip(*serieses)):
#             out.append({'t': timestamp, 'v': [v for v in values]})
#         return json.dumps(out)
# 
#     def legend(self, sources):
#         return self._svc(sources)
# 
#     def title(self, sources):
#         return ["graphite_http"]
# 
# Path: firefly/util.py
# def last_dot_splitter(dotted_path):
# def import_module_class(dotted_path):
# def import_module(dotted_path):
# def setup_logging(config):
# def verify_access_token(token, key):
# def generate_access_token(key, duration=60):
# def generate_ds_key(ds):
# def b58encode(value):
# def b58decode(encoded):


from contextlib import contextmanager
from cStringIO import StringIO
from mock import Mock
from firefly.data_sources.graphite_http import GraphiteHTTP
from firefly import util
from hamcrest import starts_with
from hamcrest import contains_string
import json
import hamcrest
import mock
import urllib2
import urlparse
import testify as T

@contextmanager
def patch_urlopen():
    with mock.patch("firefly.data_sources.graphite_http.urlopen") as mock_urlopen:
        yield mock_urlopen


class match(object):
    """
    Allow use of hamcrest matchers in mock.assert_*(..) methods.

    Example:

        m = Mock()
        m('foo')
        m.assert_called_with(match(starts_with('f')))
    """
    def __init__(self, matcher):
        self.matcher = matcher

    def __eq__(self, other):
        return self.matcher.matches(other)


class GraphiteHTTPTest(T.TestCase):

    ds_url = 'http://dontcare.com:8080'

    @T.setup
    def setup_datasource(self):

# Path: firefly/data_sources/graphite_http.py
# class GraphiteHTTP(firefly.data_source.DataSource):
#     """
#     Stats from graphite-web's HTTP endpoint
# 
#     :param graphite_url: Graphite-web URL
#     """
#     DESC = "GraphiteHTTP"
# 
#     def __init__(self, *args, **kwargs):
#         super(GraphiteHTTP, self).__init__(*args, **kwargs)
#         self.graphite_url = kwargs['graphite_url']
# 
#     def list_path(self, path):
#         """
#         Given a graphite metric name split up into it's segments,
#         return a list of the next possible segments.
# 
#         Sample input entry from graphite:
#         {
#             "leaf": 0,
#             "context": {},
#             "text": "activemq",
#             "expandable": 1,
#             "id": "activemq",
#             "allowChildren": 1
#         }
# 
#         Sample output entry to firely:
#         {
#             'type': 'dir',
#             'name': name,
#             'children': None
#         }
# 
#         :param path: list of path components as strings
#         :return: list of dicts containing the path entries
#         """
#         params = {
#             'query' : '.'.join(path + ['*']),
#             'format': 'treejson',
#         }
#         find_url = urljoin(self.graphite_url, 'metrics/find/?%s' % '&'.join(['%s=%s' % (k,v) for k,v in params.items()]))
#         find_json = urlopen(find_url).read()
#         find_results = json.loads(find_json)
# 
#         contents = list()
#         for result in sorted(find_results, key=lambda result: result['text']):
#             if result['leaf'] == 0:
#                 contents.extend(self._form_entries_from_dir(result['text']))
#             elif result['leaf'] == 1:
#                 contents.extend(self._form_entries_from_file(result['text']))
#             else:
#                 raise Exception('Unexpected value for leaf in result: %s' % result)
#         return contents
# 
#     def _form_entries_from_dir(self, name):
#         return [{'type': 'dir', 'name': name, 'children': None}]
# 
#     def _form_entries_from_file(self, name):
#         return [{'type': 'file', 'name': name}]
# 
#     def data(self, sources, start, end, width):
#         """
#         :param sources: list of list of path segments
#         :param start: timestamp like 1391044540
#         :param end: timestamp like 1391048200
#         :param width: ignored
#         :return: json string
#         """
#         # Unfortunately, the most granular unit of time that graphite supports via this API is minute.
#         fmt = '%H:%M_%Y%m%d'
#         from_str = datetime.fromtimestamp(start).strftime(fmt)
#         until_str = datetime.fromtimestamp(end).strftime(fmt)
# 
#         serieses = []
#         step = None
# 
#         # TODO: Minimize the number of http calls -- handle multiple sources in a single call
#         for metric_segments in sources:
#             metric_name = '.'.join(metric_segments)
#             params = {
#                 'target': metric_name,
#                 'format': 'json',
#                 'from' : from_str,
#                 'until': until_str,
#             }
#             render_url = urljoin(self.graphite_url, 'render/?%s' % '&'.join(['%s=%s' % (k,v) for k,v in params.items()]))
#             render_json = urlopen(render_url).read()
#             render_results = json.loads(render_json)
# 
#             values = []
#             for result in render_results:
#                 for datapoint in result['datapoints']:
#                     values.append(datapoint[0])
# 
#             # Compute step and make sure it is consistent across all metrics
#             current_step = (end - start) / (len(values) - 1)
#             if step is None:
#                 step = current_step
#             elif current_step != step:
#                 self.logger.error('Number of values from two different serieses does not match! %s != %s' % (step, current_step))
#             serieses.append(values)
# 
#         out = []
#         for timestamp, values in izip(xrange(start, end+step, step), izip(*serieses)):
#             out.append({'t': timestamp, 'v': [v for v in values]})
#         return json.dumps(out)
# 
#     def legend(self, sources):
#         return self._svc(sources)
# 
#     def title(self, sources):
#         return ["graphite_http"]
# 
# Path: firefly/util.py
# def last_dot_splitter(dotted_path):
# def import_module_class(dotted_path):
# def import_module(dotted_path):
# def setup_logging(config):
# def verify_access_token(token, key):
# def generate_access_token(key, duration=60):
# def generate_ds_key(ds):
# def b58encode(value):
# def b58decode(encoded):


# Path: tests/data_sources/graphite_http_test.py
from contextlib import contextmanager
from cStringIO import StringIO
from mock import Mock
from firefly.data_sources.graphite_http import GraphiteHTTP
from firefly import util
from hamcrest import starts_with
from hamcrest import contains_string
import json
import hamcrest
import mock
import urllib2
import urlparse
import testify as T


@contextmanager
def patch_urlopen():
    with mock.patch("firefly.data_sources.graphite_http.urlopen") as mock_urlopen:
        yield mock_urlopen


class match(object):
    """
    Allow use of hamcrest matchers in mock.assert_*(..) methods.

    Example:

        m = Mock()
        m('foo')
        m.assert_called_with(match(starts_with('f')))
    """
    def __init__(self, matcher):
        self.matcher = matcher

    def __eq__(self, other):
        return self.matcher.matches(other)


class GraphiteHTTPTest(T.TestCase):

    ds_url = 'http://dontcare.com:8080'

    @T.setup
    def setup_datasource(self):

        self.ds = GraphiteHTTP(graphite_url=self.ds_url)