Compare commits
12
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8977c4e3ab | ||
|
|
710ac05862 | ||
|
|
678e4ac97b | ||
|
|
6508aa6994 | ||
|
|
3b7f37aa39 | ||
|
|
ac74ee9a5c | ||
|
|
b9e323bf47 | ||
|
|
8fee12f004 | ||
|
|
3c23f0159f | ||
|
|
c944d7df2c | ||
|
|
611e01f9eb | ||
|
|
1840bb8f57 |
@@ -0,0 +1,27 @@
|
||||
name: Backend CI
|
||||
|
||||
on:
|
||||
- pull_request
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
name: Python tests
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Set up Python 3.7
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: 3.7
|
||||
|
||||
- name: Install requirements.txt dependencies with pip
|
||||
run: |
|
||||
python -m pip install -e .
|
||||
|
||||
- name: Run posthog tests
|
||||
run: |
|
||||
python setup.py test
|
||||
@@ -1,7 +1,5 @@
|
||||
# PostHog Python
|
||||
|
||||
Official PostHog Python library to capture and send events to any PostHog instance (including PostHog.com).
|
||||
Please see the main [PostHog docs](https://posthog.com/docs).
|
||||
|
||||
This library uses an internal queue to make calls non-blocking and fast. It also batches requests and flushes asynchronously, making it perfect to use in any part of your web app or other server side application that needs performance.
|
||||
|
||||
See [PostHog docs](https://docs.posthog.com) for all documentation, including our [Python docs](https://docs.posthog.com/#/integrations/python-integration).
|
||||
Specifically, the [Python integration](https://posthog.com/docs/integrations/python-integration) details.
|
||||
|
||||
+5
-5
@@ -8,13 +8,13 @@ posthog.api_key = '<your key>'
|
||||
|
||||
# Where you host PostHog, with no trailing /.
|
||||
# You can remove this line if you're using posthog.com
|
||||
posthog.host = 'http://127.0.0.1:8000'
|
||||
# posthog.host = 'http://127.0.0.1:8000'
|
||||
|
||||
# Capture an event
|
||||
posthog.capture('distinct_id', 'event', {'property1': 'value', 'property2': 'value'})
|
||||
|
||||
# Alias a previous distinct id with a new one
|
||||
posthog.alias('distinct_id', 'new_distinct_id')
|
||||
# # Alias a previous distinct id with a new one
|
||||
# posthog.alias('distinct_id', 'new_distinct_id')
|
||||
|
||||
# Add properties to the person
|
||||
posthog.identify('distinct_id', {'email': 'something@something.com'})
|
||||
# # Add properties to the person
|
||||
# posthog.identify('distinct_id', {'email': 'something@something.com'})
|
||||
+6
-62
@@ -78,7 +78,6 @@ class Client(object):
|
||||
msg = {
|
||||
'timestamp': timestamp,
|
||||
'context': context,
|
||||
'type': 'identify',
|
||||
'distinct_id': distinct_id,
|
||||
'$set': properties,
|
||||
'event': '$identify',
|
||||
@@ -100,7 +99,6 @@ class Client(object):
|
||||
'timestamp': timestamp,
|
||||
'context': context,
|
||||
'distinct_id': distinct_id,
|
||||
'type': 'capture',
|
||||
'event': event,
|
||||
'messageId': message_id,
|
||||
}
|
||||
@@ -121,34 +119,12 @@ class Client(object):
|
||||
},
|
||||
'timestamp': timestamp,
|
||||
'context': context,
|
||||
'type': 'alias',
|
||||
'event': '$create_alias'
|
||||
}
|
||||
|
||||
return self._enqueue(msg)
|
||||
|
||||
def group(self, distinct_id=None, group_id=None, traits=None, context=None,
|
||||
timestamp=None, message_id=None):
|
||||
traits = traits or {}
|
||||
context = context or {}
|
||||
|
||||
require('distinct_id', distinct_id, ID_TYPES)
|
||||
require('group_id', group_id, ID_TYPES)
|
||||
require('traits', traits, dict)
|
||||
|
||||
msg = {
|
||||
'timestamp': timestamp,
|
||||
'groupId': group_id,
|
||||
'context': context,
|
||||
'distinct_id': distinct_id,
|
||||
'traits': traits,
|
||||
'type': 'group',
|
||||
'messageId': message_id,
|
||||
}
|
||||
|
||||
return self._enqueue(msg)
|
||||
|
||||
def page(self, distinct_id=None, category=None, name=None, properties=None,
|
||||
def page(self, distinct_id=None, url=None, properties=None,
|
||||
context=None, timestamp=None, message_id=None):
|
||||
properties = properties or {}
|
||||
context = context or {}
|
||||
@@ -156,46 +132,15 @@ class Client(object):
|
||||
require('distinct_id', distinct_id, ID_TYPES)
|
||||
require('properties', properties, dict)
|
||||
|
||||
if name:
|
||||
require('name', name, string_types)
|
||||
if category:
|
||||
require('category', category, string_types)
|
||||
require('url', url, string_types)
|
||||
properties['$current_url'] = url
|
||||
|
||||
msg = {
|
||||
'event': '$pageview',
|
||||
'properties': properties,
|
||||
'timestamp': timestamp,
|
||||
'category': category,
|
||||
'context': context,
|
||||
'distinct_id': distinct_id,
|
||||
'type': 'page',
|
||||
'name': name,
|
||||
'messageId': message_id,
|
||||
}
|
||||
|
||||
return self._enqueue(msg)
|
||||
|
||||
def screen(self, distinct_id=None, category=None, name=None, properties=None,
|
||||
context=None, timestamp=None, message_id=None):
|
||||
properties = properties or {}
|
||||
context = context or {}
|
||||
|
||||
require('distinct_id', distinct_id, ID_TYPES)
|
||||
require('properties', properties, dict)
|
||||
|
||||
if name:
|
||||
require('name', name, string_types)
|
||||
if category:
|
||||
require('category', category, string_types)
|
||||
|
||||
msg = {
|
||||
|
||||
'properties': properties,
|
||||
'timestamp': timestamp,
|
||||
'category': category,
|
||||
'context': context,
|
||||
'distinct_id': distinct_id,
|
||||
'type': 'screen',
|
||||
'name': name,
|
||||
'messageId': message_id,
|
||||
}
|
||||
|
||||
@@ -210,7 +155,6 @@ class Client(object):
|
||||
if message_id is None:
|
||||
message_id = uuid4()
|
||||
|
||||
require('type', msg['type'], string_types)
|
||||
require('timestamp', timestamp, datetime)
|
||||
require('context', msg['context'], dict)
|
||||
|
||||
@@ -233,7 +177,7 @@ class Client(object):
|
||||
return True, msg
|
||||
|
||||
if self.sync_mode:
|
||||
self.log.debug('enqueued with blocking %s.', msg['type'])
|
||||
self.log.debug('enqueued with blocking %s.', msg['event'])
|
||||
post(self.api_key, self.host, gzip=self.gzip,
|
||||
timeout=self.timeout, batch=[msg])
|
||||
|
||||
@@ -241,7 +185,7 @@ class Client(object):
|
||||
|
||||
try:
|
||||
self.queue.put(msg, block=False)
|
||||
self.log.debug('enqueued %s.', msg['type'])
|
||||
self.log.debug('enqueued %s.', msg['event'])
|
||||
return True, msg
|
||||
except queue.Full:
|
||||
self.log.warning('analytics-python queue is full')
|
||||
|
||||
@@ -6,7 +6,7 @@ import sys
|
||||
|
||||
def all_names():
|
||||
for _, modname, _ in pkgutil.iter_modules(__path__):
|
||||
yield 'analytics.test.' + modname
|
||||
yield 'posthog.test.' + modname
|
||||
|
||||
|
||||
def all():
|
||||
|
||||
+32
-123
@@ -6,17 +6,18 @@ import time
|
||||
|
||||
from posthog.version import VERSION
|
||||
from posthog.client import Client
|
||||
|
||||
from posthog.test.utils import TEST_API_KEY
|
||||
|
||||
class TestClient(unittest.TestCase):
|
||||
|
||||
def fail(self, e, batch):
|
||||
"""Mark the failure handler"""
|
||||
print('FAIL', e, batch)
|
||||
self.failed = True
|
||||
|
||||
def setUp(self):
|
||||
self.failed = False
|
||||
self.client = Client('testsecret', on_error=self.fail)
|
||||
self.client = Client(TEST_API_KEY, on_error=self.fail)
|
||||
|
||||
def test_requires_api_key(self):
|
||||
self.assertRaises(AssertionError, Client)
|
||||
@@ -24,9 +25,9 @@ class TestClient(unittest.TestCase):
|
||||
def test_empty_flush(self):
|
||||
self.client.flush()
|
||||
|
||||
def test_basic_track(self):
|
||||
def test_basic_capture(self):
|
||||
client = self.client
|
||||
success, msg = client.track('distinct_id', 'python test event')
|
||||
success, msg = client.capture('distinct_id', 'python test event')
|
||||
client.flush()
|
||||
self.assertTrue(success)
|
||||
self.assertFalse(self.failed)
|
||||
@@ -35,14 +36,14 @@ class TestClient(unittest.TestCase):
|
||||
self.assertTrue(isinstance(msg['timestamp'], str))
|
||||
self.assertTrue(isinstance(msg['messageId'], str))
|
||||
self.assertEqual(msg['distinct_id'], 'distinct_id')
|
||||
self.assertEqual(msg['properties'], {})
|
||||
self.assertEqual(msg['type'], 'track')
|
||||
self.assertEqual(msg['properties']['$lib'], 'posthog-python')
|
||||
self.assertEqual(msg['properties']['$lib_version'], VERSION)
|
||||
|
||||
def test_stringifies_distinct_id(self):
|
||||
# A large number that loses precision in node:
|
||||
# node -e "console.log(157963456373623802 + 1)" > 157963456373623800
|
||||
client = self.client
|
||||
success, msg = client.track(
|
||||
success, msg = client.capture(
|
||||
distinct_id=157963456373623802, event='python test event')
|
||||
client.flush()
|
||||
self.assertTrue(success)
|
||||
@@ -50,9 +51,9 @@ class TestClient(unittest.TestCase):
|
||||
|
||||
self.assertEqual(msg['distinct_id'], '157963456373623802')
|
||||
|
||||
def test_advanced_track(self):
|
||||
def test_advanced_capture(self):
|
||||
client = self.client
|
||||
success, msg = client.track(
|
||||
success, msg = client.capture(
|
||||
'distinct_id', 'python test event', {'property': 'value'},
|
||||
{'ip': '192.168.0.1'}, datetime(2014, 9, 3),
|
||||
'messageId')
|
||||
@@ -60,14 +61,13 @@ class TestClient(unittest.TestCase):
|
||||
self.assertTrue(success)
|
||||
|
||||
self.assertEqual(msg['timestamp'], '2014-09-03T00:00:00+00:00')
|
||||
self.assertEqual(msg['properties'], {'property': 'value'})
|
||||
self.assertEqual(msg['properties']['property'], 'value')
|
||||
self.assertEqual(msg['context']['ip'], '192.168.0.1')
|
||||
self.assertEqual(msg['event'], 'python test event')
|
||||
self.assertEqual(msg['properties']['$lib'], 'posthog-python')
|
||||
self.assertEqual(msg['properties']['$lib_version'], VERSION)
|
||||
self.assertEqual(msg['messageId'], 'messageId')
|
||||
self.assertEqual(msg['distinct_id'], 'distinct_id')
|
||||
self.assertEqual(msg['type'], 'track')
|
||||
|
||||
def test_basic_identify(self):
|
||||
client = self.client
|
||||
@@ -76,11 +76,10 @@ class TestClient(unittest.TestCase):
|
||||
self.assertTrue(success)
|
||||
self.assertFalse(self.failed)
|
||||
|
||||
self.assertEqual(msg['traits'], {'trait': 'value'})
|
||||
self.assertEqual(msg['$set']['trait'], 'value')
|
||||
self.assertTrue(isinstance(msg['timestamp'], str))
|
||||
self.assertTrue(isinstance(msg['messageId'], str))
|
||||
self.assertEqual(msg['distinct_id'], 'distinct_id')
|
||||
self.assertEqual(msg['type'], 'identify')
|
||||
|
||||
def test_advanced_identify(self):
|
||||
client = self.client
|
||||
@@ -92,46 +91,12 @@ class TestClient(unittest.TestCase):
|
||||
|
||||
self.assertEqual(msg['timestamp'], '2014-09-03T00:00:00+00:00')
|
||||
self.assertEqual(msg['context']['ip'], '192.168.0.1')
|
||||
self.assertEqual(msg['traits'], {'trait': 'value'})
|
||||
self.assertEqual(msg['context']['library'], {
|
||||
'name': 'analytics-python',
|
||||
'version': VERSION
|
||||
})
|
||||
self.assertEqual(msg['$set']['trait'], 'value')
|
||||
self.assertEqual(msg['properties']['$lib'], 'posthog-python')
|
||||
self.assertEqual(msg['properties']['$lib_version'], VERSION)
|
||||
self.assertTrue(isinstance(msg['timestamp'], str))
|
||||
self.assertEqual(msg['messageId'], 'messageId')
|
||||
self.assertEqual(msg['distinct_id'], 'distinct_id')
|
||||
self.assertEqual(msg['type'], 'identify')
|
||||
|
||||
def test_basic_group(self):
|
||||
client = self.client
|
||||
success, msg = client.group('distinct_id', 'groupId')
|
||||
client.flush()
|
||||
self.assertTrue(success)
|
||||
self.assertFalse(self.failed)
|
||||
|
||||
self.assertEqual(msg['groupId'], 'groupId')
|
||||
self.assertEqual(msg['distinct_id'], 'distinct_id')
|
||||
self.assertEqual(msg['type'], 'group')
|
||||
|
||||
def test_advanced_group(self):
|
||||
client = self.client
|
||||
success, msg = client.group(
|
||||
'distinct_id', 'groupId', {'trait': 'value'}, {'ip': '192.168.0.1'},
|
||||
datetime(2014, 9, 3), 'messageId')
|
||||
|
||||
self.assertTrue(success)
|
||||
|
||||
self.assertEqual(msg['timestamp'], '2014-09-03T00:00:00+00:00')
|
||||
self.assertEqual(msg['context']['ip'], '192.168.0.1')
|
||||
self.assertEqual(msg['traits'], {'trait': 'value'})
|
||||
self.assertEqual(msg['context']['library'], {
|
||||
'name': 'analytics-python',
|
||||
'version': VERSION
|
||||
})
|
||||
self.assertTrue(isinstance(msg['timestamp'], str))
|
||||
self.assertEqual(msg['messageId'], 'messageId')
|
||||
self.assertEqual(msg['distinct_id'], 'distinct_id')
|
||||
self.assertEqual(msg['type'], 'group')
|
||||
|
||||
def test_basic_alias(self):
|
||||
client = self.client
|
||||
@@ -139,71 +104,35 @@ class TestClient(unittest.TestCase):
|
||||
client.flush()
|
||||
self.assertTrue(success)
|
||||
self.assertFalse(self.failed)
|
||||
self.assertEqual(msg['previousId'], 'previousId')
|
||||
self.assertEqual(msg['distinct_id'], 'distinct_id')
|
||||
self.assertEqual(msg['properties']['distinct_id'], 'previousId')
|
||||
self.assertEqual(msg['properties']['alias'], 'distinct_id')
|
||||
|
||||
def test_basic_page(self):
|
||||
client = self.client
|
||||
success, msg = client.page('distinct_id', name='name')
|
||||
success, msg = client.page('distinct_id', url='https://posthog.com/contact')
|
||||
self.assertFalse(self.failed)
|
||||
client.flush()
|
||||
self.assertTrue(success)
|
||||
self.assertEqual(msg['distinct_id'], 'distinct_id')
|
||||
self.assertEqual(msg['type'], 'page')
|
||||
self.assertEqual(msg['name'], 'name')
|
||||
self.assertEqual(msg['properties']['$current_url'], 'https://posthog.com/contact')
|
||||
|
||||
def test_advanced_page(self):
|
||||
client = self.client
|
||||
success, msg = client.page(
|
||||
'distinct_id', 'category', 'name', {'property': 'value'},
|
||||
'distinct_id', 'https://posthog.com/contact', {'property': 'value'},
|
||||
{'ip': '192.168.0.1'}, datetime(2014, 9, 3), 'messageId')
|
||||
|
||||
self.assertTrue(success)
|
||||
|
||||
self.assertEqual(msg['timestamp'], '2014-09-03T00:00:00+00:00')
|
||||
self.assertEqual(msg['context']['ip'], '192.168.0.1')
|
||||
self.assertEqual(msg['properties'], {'property': 'value'})
|
||||
self.assertEqual(msg['context']['library'], {
|
||||
'name': 'analytics-python',
|
||||
'version': VERSION
|
||||
})
|
||||
self.assertEqual(msg['category'], 'category')
|
||||
self.assertEqual(msg['properties']['$current_url'], 'https://posthog.com/contact')
|
||||
self.assertEqual(msg['properties']['property'], 'value')
|
||||
self.assertEqual(msg['properties']['$lib'], 'posthog-python')
|
||||
self.assertEqual(msg['properties']['$lib_version'], VERSION)
|
||||
self.assertTrue(isinstance(msg['timestamp'], str))
|
||||
self.assertEqual(msg['messageId'], 'messageId')
|
||||
self.assertEqual(msg['distinct_id'], 'distinct_id')
|
||||
self.assertEqual(msg['type'], 'page')
|
||||
self.assertEqual(msg['name'], 'name')
|
||||
|
||||
def test_basic_screen(self):
|
||||
client = self.client
|
||||
success, msg = client.screen('distinct_id', name='name')
|
||||
client.flush()
|
||||
self.assertTrue(success)
|
||||
self.assertEqual(msg['distinct_id'], 'distinct_id')
|
||||
self.assertEqual(msg['type'], 'screen')
|
||||
self.assertEqual(msg['name'], 'name')
|
||||
|
||||
def test_advanced_screen(self):
|
||||
client = self.client
|
||||
success, msg = client.screen(
|
||||
'distinct_id', 'category', 'name', {'property': 'value'},
|
||||
{'ip': '192.168.0.1'}, datetime(2014, 9, 3), 'messageId')
|
||||
|
||||
self.assertTrue(success)
|
||||
|
||||
self.assertEqual(msg['timestamp'], '2014-09-03T00:00:00+00:00')
|
||||
self.assertEqual(msg['context']['ip'], '192.168.0.1')
|
||||
self.assertEqual(msg['properties'], {'property': 'value'})
|
||||
self.assertEqual(msg['context']['library'], {
|
||||
'name': 'analytics-python',
|
||||
'version': VERSION
|
||||
})
|
||||
self.assertTrue(isinstance(msg['timestamp'], str))
|
||||
self.assertEqual(msg['messageId'], 'messageId')
|
||||
self.assertEqual(msg['category'], 'category')
|
||||
self.assertEqual(msg['distinct_id'], 'distinct_id')
|
||||
self.assertEqual(msg['type'], 'screen')
|
||||
self.assertEqual(msg['name'], 'name')
|
||||
|
||||
def test_flush(self):
|
||||
client = self.client
|
||||
@@ -230,7 +159,7 @@ class TestClient(unittest.TestCase):
|
||||
self.assertFalse(consumer.is_alive())
|
||||
|
||||
def test_synchronous(self):
|
||||
client = Client('testsecret', sync_mode=True)
|
||||
client = Client(TEST_API_KEY, sync_mode=True)
|
||||
|
||||
success, message = client.identify('distinct_id')
|
||||
self.assertFalse(client.consumers)
|
||||
@@ -238,7 +167,7 @@ class TestClient(unittest.TestCase):
|
||||
self.assertTrue(success)
|
||||
|
||||
def test_overflow(self):
|
||||
client = Client('testsecret', max_queue_size=1)
|
||||
client = Client(TEST_API_KEY, max_queue_size=1)
|
||||
# Ensure consumer thread is no longer uploading
|
||||
client.join()
|
||||
|
||||
@@ -249,46 +178,26 @@ class TestClient(unittest.TestCase):
|
||||
# Make sure we are informed that the queue is at capacity
|
||||
self.assertFalse(success)
|
||||
|
||||
def test_success_on_invalid_api_key(self):
|
||||
client = Client('bad_key', on_error=self.fail)
|
||||
client.track('distinct_id', 'event')
|
||||
client.flush()
|
||||
self.assertFalse(self.failed)
|
||||
|
||||
def test_unicode(self):
|
||||
Client(six.u('unicode_key'))
|
||||
|
||||
def test_numeric_distinct_id(self):
|
||||
self.client.track(1234, 'python event')
|
||||
self.client.capture(1234, 'python event')
|
||||
self.client.flush()
|
||||
self.assertFalse(self.failed)
|
||||
|
||||
def test_debug(self):
|
||||
Client('bad_key', debug=True)
|
||||
|
||||
def test_identify_with_date_object(self):
|
||||
client = self.client
|
||||
success, msg = client.identify(
|
||||
'distinct_id',
|
||||
{
|
||||
'birthdate': date(1981, 2, 2),
|
||||
},
|
||||
)
|
||||
client.flush()
|
||||
self.assertTrue(success)
|
||||
self.assertFalse(self.failed)
|
||||
|
||||
self.assertEqual(msg['traits'], {'birthdate': date(1981, 2, 2)})
|
||||
|
||||
def test_gzip(self):
|
||||
client = Client('testsecret', on_error=self.fail, gzip=True)
|
||||
client = Client(TEST_API_KEY, on_error=self.fail, gzip=True)
|
||||
for _ in range(10):
|
||||
client.identify('distinct_id', {'trait': 'value'})
|
||||
client.flush()
|
||||
self.assertFalse(self.failed)
|
||||
|
||||
def test_user_defined_flush_at(self):
|
||||
client = Client('testsecret', on_error=self.fail,
|
||||
client = Client(TEST_API_KEY, on_error=self.fail,
|
||||
flush_at=10, flush_interval=3)
|
||||
|
||||
def mock_post_fn(*args, **kwargs):
|
||||
@@ -296,7 +205,7 @@ class TestClient(unittest.TestCase):
|
||||
|
||||
# the post function should be called 2 times, with a batch size of 10
|
||||
# each time.
|
||||
with mock.patch('analytics.consumer.post', side_effect=mock_post_fn) \
|
||||
with mock.patch('posthog.consumer.post', side_effect=mock_post_fn) \
|
||||
as mock_post:
|
||||
for _ in range(20):
|
||||
client.identify('distinct_id', {'trait': 'value'})
|
||||
@@ -304,11 +213,11 @@ class TestClient(unittest.TestCase):
|
||||
self.assertEquals(mock_post.call_count, 2)
|
||||
|
||||
def test_user_defined_timeout(self):
|
||||
client = Client('testsecret', timeout=10)
|
||||
client = Client(TEST_API_KEY, timeout=10)
|
||||
for consumer in client.consumers:
|
||||
self.assertEquals(consumer.timeout, 10)
|
||||
|
||||
def test_default_timeout_15(self):
|
||||
client = Client('testsecret')
|
||||
client = Client(TEST_API_KEY)
|
||||
for consumer in client.consumers:
|
||||
self.assertEquals(consumer.timeout, 15)
|
||||
|
||||
+16
-15
@@ -10,6 +10,7 @@ except ImportError:
|
||||
|
||||
from posthog.consumer import Consumer, MAX_MSG_SIZE
|
||||
from posthog.request import APIError
|
||||
from posthog.test.utils import TEST_API_KEY
|
||||
|
||||
|
||||
class TestConsumer(unittest.TestCase):
|
||||
@@ -41,7 +42,7 @@ class TestConsumer(unittest.TestCase):
|
||||
|
||||
def test_upload(self):
|
||||
q = Queue()
|
||||
consumer = Consumer(q, 'testsecret')
|
||||
consumer = Consumer(q, TEST_API_KEY)
|
||||
track = {
|
||||
'type': 'track',
|
||||
'event': 'python event',
|
||||
@@ -57,9 +58,9 @@ class TestConsumer(unittest.TestCase):
|
||||
# The consumer should upload _n_ times.
|
||||
q = Queue()
|
||||
flush_interval = 0.3
|
||||
consumer = Consumer(q, 'testsecret', flush_at=10,
|
||||
consumer = Consumer(q, TEST_API_KEY, flush_at=10,
|
||||
flush_interval=flush_interval)
|
||||
with mock.patch('analytics.consumer.post') as mock_post:
|
||||
with mock.patch('posthog.consumer.post') as mock_post:
|
||||
consumer.start()
|
||||
for i in range(0, 3):
|
||||
track = {
|
||||
@@ -77,9 +78,9 @@ class TestConsumer(unittest.TestCase):
|
||||
q = Queue()
|
||||
flush_interval = 0.5
|
||||
flush_at = 10
|
||||
consumer = Consumer(q, 'testsecret', flush_at=flush_at,
|
||||
consumer = Consumer(q, TEST_API_KEY, flush_at=flush_at,
|
||||
flush_interval=flush_interval)
|
||||
with mock.patch('analytics.consumer.post') as mock_post:
|
||||
with mock.patch('posthog.consumer.post') as mock_post:
|
||||
consumer.start()
|
||||
for i in range(0, flush_at * 2):
|
||||
track = {
|
||||
@@ -92,7 +93,7 @@ class TestConsumer(unittest.TestCase):
|
||||
self.assertEqual(mock_post.call_count, 2)
|
||||
|
||||
def test_request(self):
|
||||
consumer = Consumer(None, 'testsecret')
|
||||
consumer = Consumer(None, TEST_API_KEY)
|
||||
track = {
|
||||
'type': 'track',
|
||||
'event': 'python event',
|
||||
@@ -109,7 +110,7 @@ class TestConsumer(unittest.TestCase):
|
||||
raise expected_exception
|
||||
mock_post.call_count = 0
|
||||
|
||||
with mock.patch('analytics.consumer.post',
|
||||
with mock.patch('posthog.consumer.post',
|
||||
mock.Mock(side_effect=mock_post)):
|
||||
track = {
|
||||
'type': 'track',
|
||||
@@ -135,21 +136,21 @@ class TestConsumer(unittest.TestCase):
|
||||
|
||||
def test_request_retry(self):
|
||||
# we should retry on general errors
|
||||
consumer = Consumer(None, 'testsecret')
|
||||
consumer = Consumer(None, TEST_API_KEY)
|
||||
self._test_request_retry(consumer, Exception('generic exception'), 2)
|
||||
|
||||
# we should retry on server errors
|
||||
consumer = Consumer(None, 'testsecret')
|
||||
consumer = Consumer(None, TEST_API_KEY)
|
||||
self._test_request_retry(consumer, APIError(
|
||||
500, 'code', 'Internal Server Error'), 2)
|
||||
|
||||
# we should retry on HTTP 429 errors
|
||||
consumer = Consumer(None, 'testsecret')
|
||||
consumer = Consumer(None, TEST_API_KEY)
|
||||
self._test_request_retry(consumer, APIError(
|
||||
429, 'code', 'Too Many Requests'), 2)
|
||||
|
||||
# we should NOT retry on other client errors
|
||||
consumer = Consumer(None, 'testsecret')
|
||||
consumer = Consumer(None, TEST_API_KEY)
|
||||
api_error = APIError(400, 'code', 'Client Errors')
|
||||
try:
|
||||
self._test_request_retry(consumer, api_error, 1)
|
||||
@@ -159,19 +160,19 @@ class TestConsumer(unittest.TestCase):
|
||||
self.fail('request() should not retry on client errors')
|
||||
|
||||
# test for number of exceptions raise > retries value
|
||||
consumer = Consumer(None, 'testsecret', retries=3)
|
||||
consumer = Consumer(None, TEST_API_KEY, retries=3)
|
||||
self._test_request_retry(consumer, APIError(
|
||||
500, 'code', 'Internal Server Error'), 3)
|
||||
|
||||
def test_pause(self):
|
||||
consumer = Consumer(None, 'testsecret')
|
||||
consumer = Consumer(None, TEST_API_KEY)
|
||||
consumer.pause()
|
||||
self.assertFalse(consumer.running)
|
||||
|
||||
def test_max_batch_size(self):
|
||||
q = Queue()
|
||||
consumer = Consumer(
|
||||
q, 'testsecret', flush_at=100000, flush_interval=3)
|
||||
q, TEST_API_KEY, flush_at=100000, flush_interval=3)
|
||||
track = {
|
||||
'type': 'track',
|
||||
'event': 'python event',
|
||||
@@ -189,7 +190,7 @@ class TestConsumer(unittest.TestCase):
|
||||
% len(data.encode()))
|
||||
return res
|
||||
|
||||
with mock.patch('analytics.request._session.post',
|
||||
with mock.patch('posthog.request._session.post',
|
||||
side_effect=mock_post_fn) as mock_post:
|
||||
consumer.start()
|
||||
for _ in range(0, n_msgs + 2):
|
||||
|
||||
+16
-24
@@ -1,6 +1,6 @@
|
||||
import unittest
|
||||
|
||||
import analytics
|
||||
import posthog
|
||||
|
||||
|
||||
class TestModule(unittest.TestCase):
|
||||
@@ -10,40 +10,32 @@ class TestModule(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.failed = False
|
||||
analytics.api_key = 'testsecret'
|
||||
analytics.on_error = self.failed
|
||||
posthog.api_key = 'testsecret'
|
||||
posthog.on_error = self.failed
|
||||
|
||||
def test_no_api_key(self):
|
||||
analytics.api_key = None
|
||||
self.assertRaises(Exception, analytics.track)
|
||||
posthog.api_key = None
|
||||
self.assertRaises(Exception, posthog.capture)
|
||||
|
||||
def test_no_host(self):
|
||||
analytics.host = None
|
||||
self.assertRaises(Exception, analytics.track)
|
||||
posthog.host = None
|
||||
self.assertRaises(Exception, posthog.capture)
|
||||
|
||||
def test_track(self):
|
||||
analytics.track('distinct_id', 'python module event')
|
||||
analytics.flush()
|
||||
posthog.capture('distinct_id', 'python module event')
|
||||
posthog.flush()
|
||||
|
||||
def test_identify(self):
|
||||
analytics.identify('distinct_id', {'email': 'user@email.com'})
|
||||
analytics.flush()
|
||||
|
||||
def test_group(self):
|
||||
analytics.group('distinct_id', 'groupId')
|
||||
analytics.flush()
|
||||
posthog.identify('distinct_id', {'email': 'user@email.com'})
|
||||
posthog.flush()
|
||||
|
||||
def test_alias(self):
|
||||
analytics.alias('previousId', 'distinct_id')
|
||||
analytics.flush()
|
||||
posthog.alias('previousId', 'distinct_id')
|
||||
posthog.flush()
|
||||
|
||||
def test_page(self):
|
||||
analytics.page('distinct_id')
|
||||
analytics.flush()
|
||||
|
||||
def test_screen(self):
|
||||
analytics.screen('distinct_id')
|
||||
analytics.flush()
|
||||
posthog.page('distinct_id', 'https://posthog.com/contact')
|
||||
posthog.flush()
|
||||
|
||||
def test_flush(self):
|
||||
analytics.flush()
|
||||
posthog.flush()
|
||||
|
||||
@@ -4,12 +4,13 @@ import json
|
||||
import requests
|
||||
|
||||
from posthog.request import post, DatetimeSerializer
|
||||
from posthog.test.utils import TEST_API_KEY
|
||||
|
||||
|
||||
class TestRequests(unittest.TestCase):
|
||||
|
||||
def test_valid_request(self):
|
||||
res = post(batch=[{
|
||||
res = post(TEST_API_KEY, batch=[{
|
||||
'distinct_id': 'distinct_id',
|
||||
'event': 'python event',
|
||||
'type': 'track'
|
||||
@@ -37,7 +38,7 @@ class TestRequests(unittest.TestCase):
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_should_not_timeout(self):
|
||||
res = post(batch=[{
|
||||
res = post(TEST_API_KEY, batch=[{
|
||||
'distinct_id': 'distinct_id',
|
||||
'event': 'python event',
|
||||
'type': 'track'
|
||||
@@ -46,7 +47,7 @@ class TestRequests(unittest.TestCase):
|
||||
|
||||
def test_should_timeout(self):
|
||||
with self.assertRaises(requests.ReadTimeout):
|
||||
post(batch=[{
|
||||
post('key', batch=[{
|
||||
'distinct_id': 'distinct_id',
|
||||
'event': 'python event',
|
||||
'type': 'track'
|
||||
|
||||
@@ -7,6 +7,7 @@ import six
|
||||
|
||||
from posthog import utils
|
||||
|
||||
TEST_API_KEY = 'kOOlRy2QlMY9jHZQv0bKz0FZyazBUoY8Arj0lFVNjs4'
|
||||
|
||||
class TestUtils(unittest.TestCase):
|
||||
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
VERSION = '1.0.10'
|
||||
VERSION = '1.0.11'
|
||||
|
||||
+12
-24
@@ -1,4 +1,4 @@
|
||||
import analytics
|
||||
import posthog
|
||||
import argparse
|
||||
import json
|
||||
import logging
|
||||
@@ -12,7 +12,7 @@ def json_hash(str):
|
||||
if str:
|
||||
return json.loads(str)
|
||||
|
||||
# analytics -method=<method> -posthog-write-key=<posthogWriteKey> [options]
|
||||
# posthog -method=<method> -posthog-write-key=<posthogWriteKey> [options]
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(description='send a posthog message')
|
||||
@@ -45,38 +45,28 @@ def failed(status, msg):
|
||||
raise Exception(msg)
|
||||
|
||||
|
||||
def track():
|
||||
analytics.track(options.distinct_id, options.event, anonymous_id=options.anonymousId,
|
||||
def capture():
|
||||
posthog.capture(options.distinct_id, options.event, anonymous_id=options.anonymousId,
|
||||
properties=json_hash(options.properties), context=json_hash(options.context))
|
||||
|
||||
|
||||
def page():
|
||||
analytics.page(options.distinct_id, name=options.name, anonymous_id=options.anonymousId,
|
||||
posthog.page(options.distinct_id, name=options.name, anonymous_id=options.anonymousId,
|
||||
properties=json_hash(options.properties), context=json_hash(options.context))
|
||||
|
||||
|
||||
def screen():
|
||||
analytics.screen(options.distinct_id, name=options.name, anonymous_id=options.anonymousId,
|
||||
properties=json_hash(options.properties), context=json_hash(options.context))
|
||||
|
||||
|
||||
def identify():
|
||||
analytics.identify(options.distinct_id, anonymous_id=options.anonymousId,
|
||||
posthog.identify(options.distinct_id, anonymous_id=options.anonymousId,
|
||||
traits=json_hash(options.traits), context=json_hash(options.context))
|
||||
|
||||
|
||||
def group():
|
||||
analytics.group(options.distinct_id, options.groupId, json_hash(options.traits),
|
||||
json_hash(options.context), anonymous_id=options.anonymousId)
|
||||
|
||||
|
||||
def unknown():
|
||||
print()
|
||||
|
||||
|
||||
analytics.api_key = options.writeKey
|
||||
analytics.on_error = failed
|
||||
analytics.debug = True
|
||||
posthog.api_key = options.writeKey
|
||||
posthog.on_error = failed
|
||||
posthog.debug = True
|
||||
|
||||
log = logging.getLogger('posthog')
|
||||
ch = logging.StreamHandler()
|
||||
@@ -84,16 +74,14 @@ ch.setLevel(logging.DEBUG)
|
||||
log.addHandler(ch)
|
||||
|
||||
switcher = {
|
||||
"track": track,
|
||||
"capture": capture,
|
||||
"page": page,
|
||||
"screen": screen,
|
||||
"identify": identify,
|
||||
"group": group
|
||||
"identify": identify
|
||||
}
|
||||
|
||||
func = switcher.get(options.type)
|
||||
if func:
|
||||
func()
|
||||
analytics.shutdown()
|
||||
posthog.shutdown()
|
||||
else:
|
||||
print("Invalid Message Type " + options.type)
|
||||
|
||||
Reference in New Issue
Block a user