Commits

Éric Araujo committed 1989926

* Improve interface usage.

** Full docstrings are now on the interface class, so that we don’t
forget to update it in the future. (The diff is misleading.)

** The recent action and ip parameters are now part of the interface.

** DummyMixpanelUtility is fully compliant and 100% tested.

** Unit tests make sure the concrete classes respect the interface.

Comments (0)

Files changed (2)

pyramid_mixpanel/__init__.py

     token = Attribute("""Mixpanel token""")
 
     def track(event, properties):
-        """Track an event and its properties."""
+        """Track an event and its properties.
 
-    def people_track(distinct_id, properties, action=u"$set"):
-        """Track a user with properties."""
+        *event* is a string naming the category to use for this data.
+        *properties* is a dictionary.
 
+        Only accepts datatypes that a default JSON encoder can encode;
+        datetime and Decimal objects for example need to be converted to
+        string format by the caller.  The graphs and funnels in the
+        Mixpanel web app will do smart data type detection and detect
+        them as dates or numbers.
+        """
 
-@implementer(IMixpanelUtility)
-class MixpanelUtility(object):
-
-    def __init__(self, settings):
-        self.token = settings['mixpanel.token']
-
-    def track(self, event, properties):
-        """Logging to the mixpanel.com API.
-
-        @param event: event/category to log this data under
-        @param properties: dictionary of key-value pairs that describe event
-        See http://mixpanel.com/api/
-
-        Only accepts datatypes that a default JSON encoder can encode, i.e.,
-        datetime and Decimal objects needs to be converted to string format
-        by the client.
-        """
-        url = "https://api.mixpanel.com/track"
-        if u'token' not in properties:
-            properties[u'token'] = self.token
-
-        try:
-            params = {'event': event, 'properties': properties}
-            data = base64.b64encode(json.dumps(params))
-            # TODO POST is also accepted and better HTTP, use it
-            response = requests.get(url, params={'data': data})
-            response.raise_for_status()
-        except Exception:
-            log.exception('mixpanel track event exception: event %s; properties: %s',
-                          event, properties)
-
-    def people_track(self, distinct_id, properties, action=u'$set', ip=u'0'):
+    def people_track(distinct_id, properties, action=u'$set', ip=u'0'):
         """Create or update user in Mixpanel People.
 
         *distinct_id* must be a string and *properties* a dictionary.
         IP would be used.  This field is necessary to detect the user's
         location.
         """
+
+
+@implementer(IMixpanelUtility)
+class MixpanelUtility(object):
+
+    def __init__(self, settings):
+        self.token = settings['mixpanel.token']
+
+    def track(self, event, properties):
+        url = "https://api.mixpanel.com/track"
+        if u'token' not in properties:
+            properties[u'token'] = self.token
+
+        try:
+            params = {'event': event, 'properties': properties}
+            data = base64.b64encode(json.dumps(params))
+            # TODO POST is also accepted and better HTTP, use it
+            response = requests.get(url, params={'data': data})
+            response.raise_for_status()
+        except Exception:
+            log.exception('mixpanel track event exception: event %s; '
+                          'properties: %s', event, properties)
+
+    def people_track(self, distinct_id, properties, action=u'$set', ip=u'0'):
         try:
             data = base64.b64encode(json.dumps({
                 u'$token': self.token,
     Use it as a replacement for the regular mixpanel utility when
     running tests.
     """
+
+    token = 'dummy token'
+
     def track(self, event, properties):
         log.debug('Tracking event "%s" with properties %s', event, properties)
 
-    def people_track(self, distinct_id, properties, action=u'$set'):
+    def people_track(self, distinct_id, properties, action=u'$set', ip=u'0'):
         log.debug(
             'Tracking person "%s" with properties %s', distinct_id, properties)

pyramid_mixpanel/tests/unittests/test_pyramid_mixpanel.py

         request.registry.getUtility.assert_called_once_with(IMixpanelUtility)
         self.assertEqual(result, request.registry.getUtility.return_value)
 
+
+class TestDummyMixpanelUtility(unittest.TestCase):
+
+    def test_interface(self):
+        from zope.interface.verify import verifyObject
+        from pyramid_mixpanel import IMixpanelUtility, DummyMixpanelUtility
+        mu = DummyMixpanelUtility()
+
+        self.assertTrue(verifyObject(IMixpanelUtility, mu))
+
+    def test_track(self):
+        from pyramid_mixpanel import DummyMixpanelUtility
+        mu = DummyMixpanelUtility()
+
+        mu.track(u'test', {u'some': u'property'})
+
+    def test_people_track(self):
+        from pyramid_mixpanel import DummyMixpanelUtility
+        mu = DummyMixpanelUtility()
+
+        mu.people_track(u'some ID', {u'whatever': u'whatevs'})
+
+
+class TestMixpanelUtility(unittest.TestCase):
+
+    def test_interface(self):
+        from zope.interface.verify import verifyObject
+        from pyramid_mixpanel import IMixpanelUtility, MixpanelUtility
+        mu = MixpanelUtility({'mixpanel.token': 'token'})
+
+        self.assertTrue(verifyObject(IMixpanelUtility, mu))
+
     @mock.patch('requests.get')
     def test_track(self, m_get):
         from pyramid_mixpanel import MixpanelUtility
 
         mu = MixpanelUtility({u'mixpanel.token': u'token'})
 
-        mu.people_track(
-            u'some ID', {u'$transaction': transaction}, action='$append', ip='127.0.0.1')
+        mu.people_track(u'some ID', {u'$transaction': transaction},
+                        action='$append', ip='127.0.0.1')
 
         data = base64.b64encode(json.dumps({
             u'$token': u'token',