Skip to content

Commit 2430d5b

Browse files
committed
updating to spec 1.0
This commit includes a number of significant changes: - updating the library to use the new spec - moving to analytics.write_key API - moving to a consumer in a separate thread - adding request retries - python 3 support - making analytics.flush() synchronous - adding full travis tests
1 parent 4e98335 commit 2430d5b

21 files changed

Lines changed: 839 additions & 992 deletions

.travis.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
language: python
2+
python:
3+
- "2.6"
4+
- "2.7"
5+
- "3.2"
6+
- "3.3"
7+
- "3.4"
8+
install:
9+
- "pip install ."
10+
- "pip install -r requirements.txt"
11+
script: make test
12+
matrix:
13+
fast_finish: true

Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2+
test:
3+
python setup.py test
4+
5+
.PHONY: test

README.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,3 @@ The above copyright notice and this permission notice shall be included in all c
3232

3333
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3434

35-
36-
[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/segmentio/analytics-python/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
37-

analytics/__init__.py

Lines changed: 35 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -1,166 +1,50 @@
11

2-
import version
2+
from analytics.version import VERSION
3+
from analytics.client import Client
34

4-
VERSION = version.VERSION
55
__version__ = VERSION
66

7-
import sys
8-
this_module = sys.modules[__name__]
7+
"""Settings."""
8+
write_key = None
9+
on_error = None
10+
debug = False
911

10-
from stats import Statistics
11-
stats = Statistics()
12+
default_client = None
1213

1314

14-
def init(secret, **kwargs):
15-
"""Create a default instance of a analytics-python client
15+
def track(*args, **kwargs):
16+
"""Send a track call."""
17+
_proxy('track', *args, **kwargs)
1618

17-
:param str secret: The Segment.io API Secret
19+
def identify(*args, **kwargs):
20+
"""Send a identify call."""
21+
_proxy('identify', *args, **kwargs)
1822

19-
Kwargs:
23+
def group(*args, **kwargs):
24+
"""Send a group call."""
25+
_proxy('group', *args, **kwargs)
2026

21-
:param logging.LOG_LEVEL log_level: The logging log level for the client
22-
talks to. Use log_level=logging.DEBUG to troubleshoot
23-
: param bool log: False to turn off logging completely, True by default
24-
: param int flush_at: Specicies after how many messages the client will flush
25-
to the server. Use flush_at=1 to disable batching
26-
: param datetime.timedelta flush_after: Specifies after how much time
27-
of no flushing that the server will flush. Used in conjunction with
28-
the flush_at size policy
29-
: param bool async: True to have the client flush to the server on another
30-
thread, therefore not blocking code (this is the default). False to
31-
enable blocking and making the request on the calling thread.
27+
def alias(*args, **kwargs):
28+
"""Send a alias call."""
29+
_proxy('alias', *args, **kwargs)
3230

33-
"""
34-
from client import Client
31+
def page(*args, **kwargs):
32+
"""Send a page call."""
33+
_proxy('page', *args, **kwargs)
3534

36-
# if we have already initialized, no-op
37-
if hasattr(this_module, 'default_client'):
38-
return
35+
def screen(*args, **kwargs):
36+
"""Send a screen call."""
37+
_proxy('screen', *args, **kwargs)
3938

40-
default_client = Client(secret=secret, stats=stats, **kwargs)
39+
def flush():
40+
"""Tell the client to flush."""
41+
_proxy('flush')
4142

42-
setattr(this_module, 'default_client', default_client)
43+
def _proxy(method, *args, **kwargs):
44+
"""Create an analytics client if one doesn't exist and send to it."""
45+
global default_client
46+
if not default_client:
47+
default_client = Client(write_key, debug=debug, on_error=on_error)
4348

44-
45-
def _get_default_client():
46-
default_client = None
47-
if hasattr(this_module, 'default_client'):
48-
default_client = getattr(this_module, 'default_client')
49-
else:
50-
sys.stderr.write('Please call analytics.init(secret) ' +
51-
'before calling analytics methods.\n')
52-
return default_client
53-
54-
55-
def identify(user_id=None, traits={}, context={}, timestamp=None):
56-
"""Identifying a user ties all of their actions to an id, and
57-
associates user traits to that id.
58-
59-
:param str user_id: the user's id after they are logged in. It's the
60-
same id as which you would recognize a signed-in user in your system.
61-
62-
: param dict traits: a dictionary with keys like subscriptionPlan or
63-
age. You only need to record a trait once, no need to send it again.
64-
Accepted value types are string, boolean, ints,, longs, and
65-
datetime.datetime.
66-
67-
: param dict context: An optional dictionary with additional
68-
information thats related to the visit. Examples are userAgent, and IP
69-
address of the visitor.
70-
71-
: param datetime.datetime timestamp: If this event happened in the
72-
past, the timestamp can be used to designate when the identification
73-
happened. Careful with this one, if it just happened, leave it None.
74-
If you do choose to provide a timestamp, make sure it has a timezone.
75-
"""
76-
default_client = _get_default_client()
77-
if default_client:
78-
default_client.identify(user_id=user_id, traits=traits,
79-
context=context, timestamp=timestamp)
80-
81-
82-
def track(user_id=None, event=None, properties={}, context={},
83-
timestamp=None):
84-
"""Whenever a user triggers an event, you'll want to track it.
85-
86-
:param str user_id: the user's id after they are logged in. It's the
87-
same id as which you would recognize a signed-in user in your system.
88-
89-
:param str event: The event name you are tracking. It is recommended
90-
that it is in human readable form. For example, "Bought T-Shirt"
91-
or "Started an exercise"
92-
93-
:param dict properties: A dictionary with items that describe the
94-
event in more detail. This argument is optional, but highly recommended
95-
- you'll find these properties extremely useful later. Accepted value
96-
types are string, boolean, ints, doubles, longs, and datetime.datetime.
97-
98-
:param dict context: An optional dictionary with additional information
99-
thats related to the visit. Examples are userAgent, and IP address
100-
of the visitor.
101-
102-
:param datetime.datetime timestamp: If this event happened in the past,
103-
the timestamp can be used to designate when the identification
104-
happened. Careful with this one, if it just happened, leave it None.
105-
If you do choose to provide a timestamp, make sure it has a timezone.
106-
107-
"""
108-
default_client = _get_default_client()
109-
if default_client:
110-
default_client.track(user_id=user_id, event=event,
111-
properties=properties, context=context,
112-
timestamp=timestamp)
113-
114-
115-
def alias(from_id, to_id, context={}, timestamp=None):
116-
"""Aliases an anonymous user into an identified user
117-
118-
:param str from_id: the anonymous user's id before they are logged in
119-
120-
:param str to_id: the identified user's id after they're logged in
121-
122-
:param dict context: An optional dictionary with additional information
123-
thats related to the visit. Examples are userAgent, and IP address
124-
of the visitor.
125-
126-
:param datetime.datetime timestamp: If this event happened in the past,
127-
the timestamp can be used to designate when the identification
128-
happened. Careful with this one, if it just happened, leave it None.
129-
If you do choose to provide a timestamp, make sure it has a timezone.
130-
"""
131-
default_client = _get_default_client()
132-
if default_client:
133-
default_client.alias(from_id=from_id, to_id=to_id, context=context,
134-
timestamp=timestamp)
135-
136-
137-
def flush(async=None):
138-
""" Forces a flush from the internal queue to the server
139-
140-
:param bool async: True to block until all messages have been flushed
141-
"""
142-
default_client = _get_default_client()
143-
if default_client:
144-
default_client.flush(async=async)
145-
146-
147-
def on_success(callback):
148-
"""
149-
Assign a callback to fire after a successful flush
150-
151-
:param func callback: A callback that will be fired on a flush success
152-
"""
153-
default_client = _get_default_client()
154-
if default_client:
155-
default_client.on_success(callback)
156-
157-
158-
def on_failure(callback):
159-
"""
160-
Assign a callback to fire after a failed flush
161-
162-
:param func callback: A callback that will be fired on a failed flush
163-
"""
164-
default_client = _get_default_client()
165-
if default_client:
166-
default_client.on_failure(callback)
49+
fn = getattr(default_client, method)
50+
fn(*args, **kwargs)

0 commit comments

Comments
 (0)