Commits

Yohann Gabory  committed 01779e0

moved the other backends (tutorial and monitoring) outside the app

  • Participants
  • Parent commits 77fb0c9

Comments (0)

Files changed (12)

   - pip install https://github.com/dcramer/pyflakes/tarball/master
   - pip install argparse
   - pip install docutils
-
+  - pip install coverage
+  - pip install django-coverage
 before_script:
   - "pep8 --exclude=migrations --ignore=E501,E225 mustachebox"
   - pyflakes -x W mustachebox

File mustachebox/backends/example_backend.py

         self.template = 'columnchart'
         return time_serie(**kwargs)
 
-    def pie_chart(self):
+    def pie_chart(self, **kwargs):
         """
         Define a generic pie chart using google chart
 
 
         return {'label': label, 'records': activities}
 
-    def line_chart(self):
+    def line_chart(self, **kwargs):
         """
         Define a generic line chart using D3js
 
                 'date': time.mktime(date.timetuple()) * 1000,
                 'value': (i * 10) + int(random.random() * 1000)})
         return response
+
+    def multiserie_linechart(self, **kwargs):
+        """
+        Define a multi-line graph using D3js
+
+        data are formated as follow ::
+
+            [
+              {'date': 1109743200000,
+              'value1': 453,
+              'value2': 543,
+              'value3': 458
+              },
+              {'date': 1107151200000,
+               'value1': 435,
+               'value2': 897,
+               'value': 123
+              },
+              ...
+            ]
+        """
+        self.template = "multiline_chart"
+        response = []
+        for a in range(3):  # we render a 3 series chart
+            date = datetime.datetime(2005, 1, 1, 0, 0, 0)
+            for i in range(200):
+                if a % 3 == 0:
+                    mult = -10
+                elif a % 2 == 0:
+                    mult = 1
+                else:
+                    mult = 10
+                date += datetime.timedelta(days=2)
+                response.append({
+                    'date': time.mktime(date.timetuple()) * 1000,
+                    'value': (i * mult) + int(random.random() * 1000),
+                    'serie': a
+                    })
+        return response

File mustachebox/backends/monitoring_backend.py

-import datetime
-import time
-import random
-from mustachebox.backends import BaseBackend
-
-
-def time_serie(**kwargs):
-    """
-    Render a time serie
-    """
-    resp = {2004: ['2004'],
-            2005: ['2005'],
-            2006: ['2006'],
-            2007: ['2007']}
-
-    for i in range(2):
-        for k, v in resp.iteritems():
-            v.append(int((random.random() * random.random()) * 10000))
-        resp['label'] = ['year', 'sales', 'expenses']
-    return resp
-
-
-class Backend(BaseBackend):
-    """
-    A backend get data formated as mustache need them.
-    - data : contain the data to be printed as graph
-    - name : the graph name
-    - template_name: the template to use for rendering
-    """
-
-    def monitoring(self, **kwargs):
-        """
-        Return a set of data to be represented as a graph
-        """
-        records = []
-        for i in range(10):
-            # 1 instances
-            instance = Instance(i)
-            date = datetime.datetime(2012, 1, 1, 0, 0, 0)
-            for i in range(300):
-                # this dataset consist of 300 metrics for 10 machines
-                date += datetime.timedelta(minutes=65)
-                record = Record(instance.name, date)
-
-                records.append(
-                    {'instance': instance.name,
-                     'cpu': record.CPU,
-                     'ram': record.RAM,
-                     'La1': record.La1,
-                     'La2': record.La2,
-                     'La3': record.La3,
-                     'date': record.date
-                     })
-        self.template = "crossfilter"
-        return records
-
-
-class Record(object):
-    """
-    Metric about an instance.
-    CPU, RAM, Load Average 1 sec 5 sec and 1 minute.
-    """
-    def __init__(self, instance, date):
-        """ instance is just a name to identify a set of data """
-        self.instance = instance
-        self.CPU = random.random() * 100
-        self.RAM = random.random() * 100
-        self.La1 = random.random() * 10
-        self.La2 = random.random() * 10
-        self.La3 = random.random() * 10
-        self.date = time.mktime(date.timetuple())
-
-
-class Instance(object):
-    """
-    An instance to identify metrics.
-    Each metric are attached to an instance
-    """
-    def __init__(self, name):
-        self.name = "instance_%i" % name

File mustachebox/backends/tutorial_backend.py

-from mustachebox.backends import BaseBackend
-import random
-
-
-class Backend(BaseBackend):
-
-    def test_method(self, **kwargs):
-        """
-          render a simple time serie suitable for javascript graphs :
-          [
-            {'year':
-                [2004, 2005, 2006, 2007]
-            },
-            {'sale':
-                [1000, 1170, 660, 1030]
-            },
-            {'expenses':
-                [400, 460, 1120, 540]
-            }
-            ]
-        """
-        self.template = "area"
-        resp = {2004: ['2004'],
-                2005: ['2005'],
-                2006: ['2006'],
-                2007: ['2007']}
-
-        for i in range(2):
-            for k, v in resp.iteritems():
-                    v.append(int((random.random() * random.random()) * 10000))
-        resp['label'] = ['year', 'sales', 'expenses']
-        return resp

File mustachebox/static/js/d3_multiline_chart.js

+data = data.map( function (d) {
+    return {
+      serie: +d.serie,   // the + sign will coerce strings to number values
+      date: new Date(d.date),
+      value: +d.value };
+});
+
+
+var x = d3.time.scale()
+        .range([0, width]);
+
+var y = d3.scale.linear()
+    .range([height, 0]);
+
+x.domain(d3.extent(data, function(d) {return d.date; }));
+
+data = d3.nest().key(function(d) { return d.serie; }).entries(data);
+
+
+
+
+
+var line = d3.svg.line()
+    .interpolate("basis")
+    .x(function(d) {return x(d.date); })
+    .y(function(d) {return y(d.value); });
+
+var color = d3.scale.category10();
+
+var xAxis = d3.svg.axis()
+    .scale(x)
+    .orient("bottom");
+
+var yAxis = d3.svg.axis()
+    .scale(y)
+    .orient("left");
+
+y.domain([
+    d3.min(data, function(c) {
+        return d3.min(c.values, function(v) { return v.value; }); }),
+    d3.max(data, function(c) {
+        return d3.max(c.values, function(v) { return v.value; }); })
+  ]);
+
+
+
+
+var svg = d3.select("body").append("svg")
+    .attr("width", width + margin.left + margin.right)
+    .attr("height", height + margin.top + margin.bottom)
+  .append("g")
+    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
+
+  svg.append("g")
+      .attr("class", "x axis")
+      .attr("transform", "translate(0," + height + ")")
+      .call(xAxis);
+
+  svg.append("g")
+      .attr("class", "y axis")
+      .call(yAxis)
+
+var serie = svg.selectAll(".serie")
+      .data(data)
+    .enter().append("g")
+      .attr("class", "serie");
+
+serie.append("path")
+      .attr("class", "line")
+      .attr("d", function(d){return line(d.values)})
+      .style("stroke", function(d) {return color(d.key); });
+

File mustachebox/templates/mustachebox/multiline_chart.html

+<html>
+  <head>
+
+<style>
+
+body {
+  font: 10px sans-serif;
+}
+
+.axis path,
+.axis line {
+  fill: none;
+  stroke: #000;
+  shape-rendering: crispEdges;
+}
+
+.x.axis path {
+  display: none;
+}
+
+.line {
+  fill: none;
+  stroke: steelblue;
+  stroke-width: 1.5px;
+}
+
+</style>
+
+    {% include "mustachebox/includes/jsheader.html" %}
+    <script type="text/javascript">
+      var data = {% autoescape off %}{{object.data}}{% endautoescape %}
+      var width = 960;
+      var height = 500;
+      var margin = {top: 20, right: 20, bottom: 30, left: 50};
+    </script>
+
+  </head>
+  <body>
+<script type="text/javascript" src="{{STATIC_URL}}js/d3_multiline_chart.js"></script>
+  </body>
+</html>

File mustachebox/templates/mustachebox/tags/multiline_chart.html

+<html>
+  <head>
+
+    <style>
+
+    </style>
+
+    {% include "mustachebox/includes/jsheader.html" %}
+    <script type="text/javascript">
+      var data = {% autoescape off %}{{object.data}}{% endautoescape %}
+      var width = 960;
+      var height = 500;
+      var margin = {top: 20, right: 20, bottom: 30, left: 50};
+    </script>
+
+  </head>
+  <body>
+<script type="text/javascript" src="{{STATIC_URL}}js/d3_multiline_chart.js"></script>
+  </body>
+</html>

File mustachebox/templatetags/graph.py

         arguments = token.contents.split()
         method = arguments[1]
         args = arguments[2:]
-    except ValueError:
+    except IndexError:
         raise template.TemplateSyntaxError, """
 %r tag requires at least 1 argument, the name of the graph you want to render
 """.format(token.contents.split()[0])
 
 @register.filter(name='parse_docstring')
 def parse_docstring(value):
-    if value is None:
-        return
+
     from docutils import core
     publish_args = {'source': value, 'writer_name': 'html4css1'}
     parts = core.publish_parts(**publish_args)

File mustachebox/tests.py

 from django.test import TestCase
 from django.test.client import Client
 from django import template
-
+from django.template import TemplateSyntaxError
 
 class TestGraphList(TestCase):
 
         response = client.get("/grapher/all/")
         self.assertEqual(response.status_code, 200)
 
-        self.assertEqual(len(response.context['object_list']), 5)
+        self.assertEqual(len(response.context['object_list']), 6)
 
 
 class TestTemplateTags(TestCase):
 
 class TestGraphPages(TestCase):
 
+    def test_ajax(self):
+        client = Client()
+        response = self.client.get("/grapher/area/",
+                                   HTTP_X_REQUESTED_WITH='XMLHttpRequest')
+        self.assertEqual(response._headers['content-type'][1],
+                         'application/json')
+
     def test_area(self):
         client = Client()
         response = client.get("/grapher/area/")

File other_backends/monitoring_backend.py

+import datetime
+import time
+import random
+from mustachebox.backends import BaseBackend
+
+
+def time_serie(**kwargs):
+    """
+    Render a time serie
+    """
+    resp = {2004: ['2004'],
+            2005: ['2005'],
+            2006: ['2006'],
+            2007: ['2007']}
+
+    for i in range(2):
+        for k, v in resp.iteritems():
+            v.append(int((random.random() * random.random()) * 10000))
+        resp['label'] = ['year', 'sales', 'expenses']
+    return resp
+
+
+class Backend(BaseBackend):
+    """
+    A backend get data formated as mustache need them.
+    - data : contain the data to be printed as graph
+    - name : the graph name
+    - template_name: the template to use for rendering
+    """
+
+    def monitoring(self, **kwargs):
+        """
+        Return a set of data to be represented as a graph
+        """
+        records = []
+        for i in range(10):
+            # 1 instances
+            instance = Instance(i)
+            date = datetime.datetime(2012, 1, 1, 0, 0, 0)
+            for i in range(300):
+                # this dataset consist of 300 metrics for 10 machines
+                date += datetime.timedelta(minutes=65)
+                record = Record(instance.name, date)
+
+                records.append(
+                    {'instance': instance.name,
+                     'cpu': record.CPU,
+                     'ram': record.RAM,
+                     'La1': record.La1,
+                     'La2': record.La2,
+                     'La3': record.La3,
+                     'date': record.date
+                     })
+        self.template = "crossfilter"
+        return records
+
+
+class Record(object):
+    """
+    Metric about an instance.
+    CPU, RAM, Load Average 1 sec 5 sec and 1 minute.
+    """
+    def __init__(self, instance, date):
+        """ instance is just a name to identify a set of data """
+        self.instance = instance
+        self.CPU = random.random() * 100
+        self.RAM = random.random() * 100
+        self.La1 = random.random() * 10
+        self.La2 = random.random() * 10
+        self.La3 = random.random() * 10
+        self.date = time.mktime(date.timetuple())
+
+
+class Instance(object):
+    """
+    An instance to identify metrics.
+    Each metric are attached to an instance
+    """
+    def __init__(self, name):
+        self.name = "instance_%i" % name

File other_backends/tutorial_backend.py

+from mustachebox.backends import BaseBackend
+import random
+
+
+class Backend(BaseBackend):
+
+    def test_method(self, **kwargs):
+        """
+          render a simple time serie suitable for javascript graphs :
+          [
+            {'year':
+                [2004, 2005, 2006, 2007]
+            },
+            {'sale':
+                [1000, 1170, 660, 1030]
+            },
+            {'expenses':
+                [400, 460, 1120, 540]
+            }
+            ]
+        """
+        self.template = "area"
+        resp = {2004: ['2004'],
+                2005: ['2005'],
+                2006: ['2006'],
+                2007: ['2007']}
+
+        for i in range(2):
+            for k, v in resp.iteritems():
+                    v.append(int((random.random() * random.random()) * 10000))
+        resp['label'] = ['year', 'sales', 'expenses']
+        return resp

File quicktest.py

 
         >>> QuickDjangoTest('app1', 'app2')
 
-    Based on a script published by Lukasz Dziedzia at: 
+    Based on a script published by Lukasz Dziedzia at:
     http://stackoverflow.com/questions/3841725/how-to-launch-tests-for-django-reusable-app
     """
     DIRNAME = os.path.dirname(__file__)
         'django.contrib.contenttypes',
         'django.contrib.sessions',
         'django.contrib.admin',
+        'django_coverage'
     )
 
     def __init__(self, *args, **kwargs):
             ROOT_URLCONF = 'test_urls',
             GRAPH_BACKEND="mustachebox.backends.example_backend"
         )
-        from django.test.simple import DjangoTestSuiteRunner
-        failures = DjangoTestSuiteRunner().run_tests(self.apps, verbosity=1)
+
+
+        from django_coverage.coverage_runner import CoverageRunner
+        failures = CoverageRunner().run_tests(self.apps, verbosity=1)
         if failures:
             sys.exit(failures)