diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..f08bfa89 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,14 @@ +language: python +python: + - "2.6" + - "2.7" + - "3.2" + - "3.3" +install: + - pip install analytics-python + +before_script: python -c "import analytics" +script: python test.py + +matrix: + fast_finish: true diff --git a/README.md b/README.md index ad6ee7c5..6e463694 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,3 @@ The above copyright notice and this permission notice shall be included in all c 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. - -[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/segmentio/analytics-python/trend.png)](https://bitdeli.com/free "Bitdeli Badge") - diff --git a/analytics/__init__.py b/analytics/__init__.py index df4306bc..5580de59 100644 --- a/analytics/__init__.py +++ b/analytics/__init__.py @@ -1,5 +1,4 @@ - -import version +import analytics.version VERSION = version.VERSION __version__ = VERSION @@ -7,7 +6,7 @@ import sys this_module = sys.modules[__name__] -from stats import Statistics +from analytics.stats import Statistics stats = Statistics() @@ -31,7 +30,7 @@ def init(secret, **kwargs): enable blocking and making the request on the calling thread. """ - from client import Client + from analytics.client import Client # if we have already initialized, no-op if hasattr(this_module, 'default_client'): diff --git a/analytics/client.py b/analytics/client.py index 9e791573..c64fe65f 100644 --- a/analytics/client.py +++ b/analytics/client.py @@ -5,14 +5,16 @@ import numbers import threading +import six + from dateutil.tz import tzutc import requests -from stats import Statistics -from errors import ApiError -from utils import guess_timezone, DatetimeSerializer +from analytics.stats import Statistics +from analytics.errors import ApiError +from analytics.utils import guess_timezone, DatetimeSerializer -import options +import analytics.options as options logging_enabled = True @@ -26,7 +28,7 @@ def log(level, *args, **kwargs): def package_exception(client, data, e): - log('warn', 'Segment.io request error', exc_info=True) + log('warning', 'Segment.io request error', exc_info=True) client._on_failed_flush(data, e) @@ -175,24 +177,31 @@ def _check_for_secret(self): 'identify or track.') def _coerce_unicode(self, cmplx): - return unicode(cmplx) + try: + item = cmplx.decode("utf-8", "strict") + except AttributeError as exception: + item = ":".join(exception) + item.decode("utf-8", "strict") + except: + raise + return item def _clean_list(self, l): return [self._clean(item) for item in l] def _clean_dict(self, d): data = {} - for k, v in d.iteritems(): + for k, v in six.iteritems(d): try: data[k] = self._clean(v) except TypeError: - log('warn', 'Dictionary values must be serializeable to ' + + log('warning', 'Dictionary values must be serializeable to ' + 'JSON "%s" value %s of type %s is unsupported.' % (k, v, type(v))) return data def _clean(self, item): - if isinstance(item, (str, unicode, int, long, float, bool, + if isinstance(item, (str, six.text_type, int, six.integer_types, float, bool, numbers.Number, datetime)): return item elif isinstance(item, (set, list, tuple)): diff --git a/test.py b/test.py index 7d56d464..5402ea40 100755 --- a/test.py +++ b/test.py @@ -4,6 +4,8 @@ import unittest import json +import six + from datetime import datetime, timedelta from random import randint @@ -22,11 +24,11 @@ def on_success(data, response): - print 'Success', response + print('Success', response) def on_failure(data, error): - print 'Failure', error + print('Failure', error) class AnalyticsBasicTests(unittest.TestCase): @@ -61,7 +63,7 @@ def test_clean(self): 'long': 200000000, 'bool': True, 'str': 'woo', - 'unicode': u'woo', + 'unicode': six.u('woo'), 'decimal': Decimal('0.142857'), 'date': datetime.now(), } @@ -72,7 +74,8 @@ def test_clean(self): 'list': [1, 2, 3] } - combined = dict(simple.items() + complicated.items()) + combined = dict(simple.items()) + combined.update(complicated.items()) pre_clean_keys = combined.keys() @@ -294,7 +297,7 @@ def test_performance(self): "Song": "Eleanor Rigby" }) - print 'Finished submitting into the queue' + print('Finished submitting into the queue') start = time() while analytics.stats.successful < target: