From 09d6d192f8db0f68f6ac4dc01fb4848f04def668 Mon Sep 17 00:00:00 2001 From: Nicholas Kobald Date: Tue, 10 Oct 2017 10:42:02 -0700 Subject: [PATCH 01/13] Updates python dateutil install requirements --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index ad645f1..b193186 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ test_suite='nose.collector', install_requires=[ 'riak==2.5.4', - 'python-dateutil==1.5', + 'python-dateutil>=1.5, != 2.0', 'protobuf==2.6.1', ], options={'easy_install': {'allow_hosts': 'pypi.python.org'}}, From e666d7a0ea36478bc8f5e4e73dcb8504f73758e9 Mon Sep 17 00:00:00 2001 From: Jonas Trappenberg Date: Sun, 19 Nov 2017 16:09:11 -0800 Subject: [PATCH 02/13] Let riak handle its dependencies --- setup.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/setup.py b/setup.py index b193186..d8af902 100644 --- a/setup.py +++ b/setup.py @@ -20,9 +20,8 @@ packages=find_packages(exclude=['tests']), test_suite='nose.collector', install_requires=[ - 'riak==2.5.4', + 'riak', 'python-dateutil>=1.5, != 2.0', - 'protobuf==2.6.1', ], options={'easy_install': {'allow_hosts': 'pypi.python.org'}}, tests_require=tests_require, From f85a00e1084201bac5e5ba441333add7f34cdcc2 Mon Sep 17 00:00:00 2001 From: Jonas Trappenberg Date: Sun, 19 Nov 2017 16:52:38 -0800 Subject: [PATCH 03/13] Update exception-catching syntax to support python 3 --- sunspear/backends/riak.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sunspear/backends/riak.py b/sunspear/backends/riak.py index b3271f9..0444b92 100644 --- a/sunspear/backends/riak.py +++ b/sunspear/backends/riak.py @@ -570,7 +570,7 @@ def _dehydrate_sub_activity(self, sub_activity, obj_list, skip_sub_activities=Fa for i, item in enumerate(sub_activity[collection]['items']): try: dehydrated_sub_items.append(self._dehydrate_sub_activity(item, obj_list)) - except KeyError, e: + except KeyError as e: pass sub_activity[collection]['items'] = dehydrated_sub_items sub_activity[collection]['totalItems'] = len(dehydrated_sub_items) From eabb687918396dca121bef60a59fa5f830dafee3 Mon Sep 17 00:00:00 2001 From: Jonas Trappenberg Date: Thu, 28 Dec 2017 15:31:37 -0800 Subject: [PATCH 04/13] Pass through unrecognized keyword arguments to riak client --- sunspear/backends/riak.py | 42 +++++++++++++++++---------------------- sunspear/lib/rfc3339.py | 1 - 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/sunspear/backends/riak.py b/sunspear/backends/riak.py index 0444b92..553bb66 100644 --- a/sunspear/backends/riak.py +++ b/sunspear/backends/riak.py @@ -149,38 +149,32 @@ class RiakBackend(BaseBackend): def __init__( self, protocol="pbc", nodes=[], objects_bucket_name="objects", - activities_bucket_name="activities", **kwargs): - - self._riak_backend = RiakClient(protocol=protocol, nodes=nodes) - - r_value = kwargs.get("r") - w_value = kwargs.get("w") - dw_value = kwargs.get("dw") - pr_value = kwargs.get("pr") - pw_value = kwargs.get("pw") + activities_bucket_name="activities", r=None, w=None, dw=None, + pr=None, pw=None, **kwargs): + self._riak_backend = RiakClient(protocol=protocol, nodes=nodes, **kwargs) self._objects = self._riak_backend.bucket(objects_bucket_name) self._activities = self._riak_backend.bucket(activities_bucket_name) - if r_value: - self._objects.r = r_value - self._activities.r = r_value + if r: + self._objects.r = r + self._activities.r = r - if w_value: - self._objects.w = w_value - self._activities.w = w_value + if w: + self._objects.w = w + self._activities.w = w - if dw_value: - self._objects.dw = dw_value - self._activities.dw = dw_value + if dw: + self._objects.dw = dw + self._activities.dw = dw - if pr_value: - self._objects.pr = pr_value - self._activities.pr = pr_value + if pr: + self._objects.pr = pr + self._activities.pr = pr - if pw_value: - self._objects.pw = pw_value - self._activities.pw = pw_value + if pw: + self._objects.pw = pw + self._activities.pw = pw def clear_all(self, **kwargs): """ diff --git a/sunspear/lib/rfc3339.py b/sunspear/lib/rfc3339.py index bfca1f4..a0057e5 100644 --- a/sunspear/lib/rfc3339.py +++ b/sunspear/lib/rfc3339.py @@ -28,7 +28,6 @@ import datetime import time -import unittest def _timezone(utc_offset): From 4f3aad88cdc31894fefe9c58c9f95a18161107b4 Mon Sep 17 00:00:00 2001 From: Jonas Trappenberg Date: Sun, 19 Nov 2017 16:53:45 -0800 Subject: [PATCH 05/13] Check for string in python3-compatible way --- setup.py | 3 +- sunspear/activitystreams/models.py | 10 +++---- sunspear/backends/riak.py | 25 ++++++++-------- tests/test_activitystreams.py | 17 +++++------ tests/test_backend.py | 46 +++++++++++++++--------------- 5 files changed, 52 insertions(+), 49 deletions(-) diff --git a/setup.py b/setup.py index d8af902..df455e1 100644 --- a/setup.py +++ b/setup.py @@ -20,8 +20,9 @@ packages=find_packages(exclude=['tests']), test_suite='nose.collector', install_requires=[ - 'riak', 'python-dateutil>=1.5, != 2.0', + 'riak', + 'six', ], options={'easy_install': {'allow_hosts': 'pypi.python.org'}}, tests_require=tests_require, diff --git a/sunspear/activitystreams/models.py b/sunspear/activitystreams/models.py index 02ca5e4..213a158 100644 --- a/sunspear/activitystreams/models.py +++ b/sunspear/activitystreams/models.py @@ -1,10 +1,10 @@ -from sunspear.exceptions import SunspearValidationException - -from sunspear.lib.rfc3339 import rfc3339 +import datetime +import six from dateutil.parser import parse -import datetime +from sunspear.exceptions import SunspearValidationException +from sunspear.lib.rfc3339 import rfc3339 __all__ = ('Model', 'Activity', 'ReplyActivity', 'LikeActivity', 'Object', 'MediaLink', ) @@ -113,7 +113,7 @@ def get_dict(self): def _parse_date(self, date=None, utc=True, use_system_timezone=False): dt = None if date is None or not isinstance(date, datetime.datetime): - if isinstance(date, basestring): + if isinstance(date, six.string_types): try: dt = parse(date) except ValueError: diff --git a/sunspear/backends/riak.py b/sunspear/backends/riak.py index 553bb66..7f6e4a9 100644 --- a/sunspear/backends/riak.py +++ b/sunspear/backends/riak.py @@ -17,16 +17,17 @@ """ from __future__ import absolute_import -from sunspear.activitystreams.models import Object, Activity, Model -from sunspear.exceptions import (SunspearValidationException) -from sunspear.backends.base import BaseBackend, SUB_ACTIVITY_MAP +import calendar +import copy +import datetime +import uuid +import six from riak import RiakClient -import uuid -import copy -import datetime -import calendar +from sunspear.activitystreams.models import Activity, Model, Object +from sunspear.backends.base import SUB_ACTIVITY_MAP, BaseBackend +from sunspear.exceptions import SunspearValidationException __all__ = ('RiakBackend', ) @@ -586,9 +587,9 @@ def _extract_object_keys(self, activity, skip_sub_activities=False): for in_reply_to_obj in objects['inReplyTo']] if isinstance(objects, list): for item in objects: - if isinstance(item, basestring): + if isinstance(item, six.string_types): keys.append(item) - if isinstance(objects, basestring): + if isinstance(objects, six.string_types): keys.append(objects) if not skip_sub_activities: @@ -614,9 +615,9 @@ def _dehydrate_object_keys(self, activity, objects_dict, skip_sub_activities=Fal objects_dict, skip_sub_activities=skip_sub_activities) if isinstance(activity_objects, list): for i, obj_id in enumerate(activity_objects): - if isinstance(activity[object_key][i], basestring): + if isinstance(activity[object_key][i], six.string_types): activity[object_key][i] = objects_dict.get(obj_id, {}) - if isinstance(activity_objects, basestring): + if isinstance(activity_objects, six.string_types): activity[object_key] = objects_dict.get(activity_objects, {}) if not skip_sub_activities: @@ -678,7 +679,7 @@ def _extract_id(self, activity_or_id): Helper that returns an id if the activity has one. """ this_id = None - if isinstance(activity_or_id, basestring): + if isinstance(activity_or_id, six.string_types): this_id = activity_or_id elif isinstance(activity_or_id, dict): this_id = activity_or_id.get('id', None) diff --git a/tests/test_activitystreams.py b/tests/test_activitystreams.py index 7f492f0..0df9f24 100644 --- a/tests/test_activitystreams.py +++ b/tests/test_activitystreams.py @@ -1,12 +1,13 @@ from __future__ import absolute_import -from nose.tools import ok_, eq_, raises, set_trace -from mock import MagicMock, call, ANY +import datetime -from sunspear.activitystreams.models import Activity, MediaLink, Object, Model, ReplyActivity, LikeActivity -from sunspear.exceptions import SunspearValidationException +import six +from mock import MagicMock +from nose.tools import eq_, ok_, raises -import datetime +from sunspear.activitystreams.models import Activity, MediaLink, Model, Object +from sunspear.exceptions import SunspearValidationException class TestActivityModel(object): @@ -214,7 +215,7 @@ def test__set_defaults(self): obj = Model({}, backend=MagicMock()) obj_dict = obj._set_defaults({'id': 12}) - ok_(isinstance(obj_dict.get('id'), basestring)) + ok_(isinstance(obj_dict.get('id'), six.string_types)) def test__set_defaults_no_id_does_not_fail(self): obj = Model({}, backend=MagicMock()) @@ -229,7 +230,7 @@ def test__parse_date(self): eq_(obj._parse_date(d), d.strftime('%Y-%m-%dT%H:%M:%S') + "Z") #badly formatted string date - ok_(isinstance(obj._parse_date(date="qwerty"), basestring)) + ok_(isinstance(obj._parse_date(date="qwerty"), six.string_types)) #no date passed - ok_(isinstance(obj._parse_date(date=None), basestring)) + ok_(isinstance(obj._parse_date(date=None), six.string_types)) diff --git a/tests/test_backend.py b/tests/test_backend.py index 7b160ef..2f8ea21 100644 --- a/tests/test_backend.py +++ b/tests/test_backend.py @@ -1,13 +1,14 @@ from __future__ import absolute_import -from nose.tools import ok_, eq_, set_trace, raises -from mock import MagicMock, call, ANY +import datetime + +import six +from mock import ANY, MagicMock, call +from nose.tools import eq_, ok_, raises, set_trace -from sunspear.exceptions import SunspearValidationException from sunspear.aggregators.property import PropertyAggregator from sunspear.backends.riak import RiakBackend - -import datetime +from sunspear.exceptions import SunspearValidationException riak_connection_options = { "nodes": [ @@ -172,7 +173,7 @@ def test_create_activity_stored_as_sparse(self): riak_obj = self._backend._activities.get('5') riak_obj_data = riak_obj.data - ok_(isinstance(riak_obj_data.get("target"), basestring)) + ok_(isinstance(riak_obj_data.get("target"), six.string_types)) def test_delete_activity(self): self._backend._activities.get('5').delete() @@ -730,8 +731,8 @@ def test_create_reply_maintains_dehydrate_state(self): self._backend.create_activity({"id": 5, "title": "Stream Item", "verb": "post", "actor": actor, "object": obj}) riak_obj_data = self._backend._activities.get(key="5").data - ok_(isinstance(riak_obj_data.get("actor"), basestring)) - ok_(isinstance(riak_obj_data.get("object"), basestring)) + ok_(isinstance(riak_obj_data.get("actor"), six.string_types)) + ok_(isinstance(riak_obj_data.get("object"), six.string_types)) #now create a reply for the activity reply_activity_dict, activity_obj_dict = self._backend.sub_activity_create( @@ -739,8 +740,8 @@ def test_create_reply_maintains_dehydrate_state(self): sub_activity_verb='reply') riak_obj_data = self._backend._activities.get(key="5").data - ok_(isinstance(riak_obj_data.get("actor"), basestring)) - ok_(isinstance(riak_obj_data.get("object"), basestring)) + ok_(isinstance(riak_obj_data.get("actor"), six.string_types)) + ok_(isinstance(riak_obj_data.get("object"), six.string_types)) def test_create_reply_with_extra_data(self): self._backend._activities.get('5').delete() @@ -843,8 +844,8 @@ def test_create_like_maintains_dehydrate_state(self): self._backend.create_activity({"id": 5, "title": "Stream Item", "verb": "post", "actor": actor, "object": obj}) riak_obj_data = self._backend._activities.get(key="5").data - ok_(isinstance(riak_obj_data.get("actor"), basestring)) - ok_(isinstance(riak_obj_data.get("object"), basestring)) + ok_(isinstance(riak_obj_data.get("actor"), six.string_types)) + ok_(isinstance(riak_obj_data.get("object"), six.string_types)) #now create a reply for the activity like_activity_dict, activity_obj_dict = self._backend.sub_activity_create( @@ -852,8 +853,8 @@ def test_create_like_maintains_dehydrate_state(self): sub_activity_verb='like') riak_obj_data = self._backend._activities.get(key="5").data - ok_(isinstance(riak_obj_data.get("actor"), basestring)) - ok_(isinstance(riak_obj_data.get("object"), basestring)) + ok_(isinstance(riak_obj_data.get("actor"), six.string_types)) + ok_(isinstance(riak_obj_data.get("object"), six.string_types)) def test_create_like(self): self._backend._activities.get('5').delete() @@ -950,15 +951,15 @@ def test_delete_like_maintains_dehydrated_state(self): 5, actor2_id, "", sub_activity_verb='like') riak_obj_data = self._backend._activities.get(key="5").data - ok_(isinstance(riak_obj_data.get("actor"), basestring)) - ok_(isinstance(riak_obj_data.get("object"), basestring)) + ok_(isinstance(riak_obj_data.get("actor"), six.string_types)) + ok_(isinstance(riak_obj_data.get("object"), six.string_types)) #now delete the like and make sure everything is ok: self._backend.sub_activity_delete(like_activity_dict['id'], 'like') riak_obj_data = self._backend._activities.get(key="5").data - ok_(isinstance(riak_obj_data.get("actor"), basestring)) - ok_(isinstance(riak_obj_data.get("object"), basestring)) + ok_(isinstance(riak_obj_data.get("actor"), six.string_types)) + ok_(isinstance(riak_obj_data.get("object"), six.string_types)) def test_reply_delete_maintains_dehydrated_state(self): self._backend._activities.get('5').delete() @@ -983,16 +984,16 @@ def test_reply_delete_maintains_dehydrated_state(self): 5, actor2_id, "This is a reply.", sub_activity_verb='reply') riak_obj_data = self._backend._activities.get(key="5").data - ok_(isinstance(riak_obj_data.get("actor"), basestring)) - ok_(isinstance(riak_obj_data.get("object"), basestring)) + ok_(isinstance(riak_obj_data.get("actor"), six.string_types)) + ok_(isinstance(riak_obj_data.get("object"), six.string_types)) #now delete the reply and make sure everything is ok: self._backend.sub_activity_delete( reply_activity_dict['id'], 'reply') riak_obj_data = self._backend._activities.get(key="5").data - ok_(isinstance(riak_obj_data.get("actor"), basestring)) - ok_(isinstance(riak_obj_data.get("object"), basestring)) + ok_(isinstance(riak_obj_data.get("actor"), six.string_types)) + ok_(isinstance(riak_obj_data.get("object"), six.string_types)) def test_reply_delete(self): self._backend._activities.get('5').delete() @@ -1719,4 +1720,3 @@ def test_create_sub_activity_indexes(self): eq_(filter(lambda x: x[0] == 'actor_bin', riak_obj.indexes)[0][1], actor2_id) eq_(filter(lambda x: x[0] == 'object_bin', riak_obj.indexes)[0][1], like_activity_dict['object']['id']) eq_(filter(lambda x: x[0] == 'inreplyto_bin', riak_obj.indexes)[0][1], '5') - From db3d0f6a026332f76b3abb29e7e07bf81fe22f96 Mon Sep 17 00:00:00 2001 From: Jonas Trappenberg Date: Sun, 19 Nov 2017 16:54:36 -0800 Subject: [PATCH 06/13] long doesn't exist in python 3 --- sunspear/backends/riak.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sunspear/backends/riak.py b/sunspear/backends/riak.py index 7f6e4a9..3a7d864 100644 --- a/sunspear/backends/riak.py +++ b/sunspear/backends/riak.py @@ -699,7 +699,7 @@ def _get_timestamp(self): returns a unix timestamp representing the ``datetime`` object """ dt_obj = datetime.datetime.utcnow() - return long((calendar.timegm(dt_obj.utctimetuple()) * 1000)) + (dt_obj.microsecond / 1000) + return int((calendar.timegm(dt_obj.utctimetuple()) * 1000)) + (dt_obj.microsecond / 1000) def get_new_id(self): """ @@ -709,5 +709,3 @@ def get_new_id(self): :return: a new id """ return uuid.uuid1().hex - # now = datetime.datetime.utcnow() - # return str(long(calendar.timegm(now.utctimetuple()) - calendar.timegm(self.custom_epoch.utctimetuple())) + now.microsecond) From 3d8392d47a2157ef5c646aeca40296810734c996 Mon Sep 17 00:00:00 2001 From: Jonas Trappenberg Date: Sun, 26 Nov 2017 11:44:48 -0800 Subject: [PATCH 07/13] Add isort configuration --- setup.cfg | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/setup.cfg b/setup.cfg index ce26f6a..b6c1cfb 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,2 +1,23 @@ [nosetests] where=tests + +[isort] +line_length=120 +known_standard_library= +known_third_party= +known_first_party=sunspear +balanced_wrapping=true +combine_star=true +# 0: grid +# 1: vertical +# 2: hanging +# 3: vert-hanging +# 4: vert-grid +# 5: vert-grid-grouped +multi_line_output=4 +not_skip=__init__.py + +# Don't sort one-letter classes (like Q) first +order_by_type=false + +enforce_white_space=true From f0031ccd24ae92c7c2f98555e12ef84dcf16f6d1 Mon Sep 17 00:00:00 2001 From: Jonas Trappenberg Date: Sun, 26 Nov 2017 11:51:29 -0800 Subject: [PATCH 08/13] Add safe future imports --- docs/source/conf.py | 5 ++++- setup.py | 4 +++- sunspear/activitystreams/models.py | 2 ++ sunspear/aggregators/base.py | 3 +++ sunspear/aggregators/property.py | 9 +++++---- sunspear/backends/base.py | 10 ++++++---- sunspear/backends/riak.py | 4 ++-- sunspear/clients.py | 3 +++ sunspear/exceptions.py | 5 ++++- sunspear/lib/dotdict.py | 1 + sunspear/lib/rfc3339.py | 1 + tests/test_activitystreams.py | 2 +- tests/test_aggregators.py | 8 ++++---- tests/test_backend.py | 4 ++-- tests/test_client.py | 11 +++++------ tests/test_dotdict.py | 6 +++--- tests/test_rfc3339.py | 8 ++++---- 17 files changed, 53 insertions(+), 33 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index b435b95..48c79ac 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -11,7 +11,10 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys, os +from __future__ import absolute_import, division, print_function + +import os +import sys FILE_ROOT = os.path.abspath(os.path.dirname(__file__)) #add the apps dir to the python path. diff --git a/setup.py b/setup.py index df455e1..955390b 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,8 @@ #!/usr/bin/python -from setuptools import setup, find_packages +from __future__ import absolute_import, division, print_function + +from setuptools import find_packages, setup tests_require=[ 'nose', diff --git a/sunspear/activitystreams/models.py b/sunspear/activitystreams/models.py index 213a158..7cc434c 100644 --- a/sunspear/activitystreams/models.py +++ b/sunspear/activitystreams/models.py @@ -1,3 +1,5 @@ +from __future__ import absolute_import, division, print_function + import datetime import six diff --git a/sunspear/aggregators/base.py b/sunspear/aggregators/base.py index a2d8991..669ed48 100644 --- a/sunspear/aggregators/base.py +++ b/sunspear/aggregators/base.py @@ -1,3 +1,6 @@ +from __future__ import absolute_import, division, print_function + + class BaseAggregator(object): def __init__(self, *args, **kwargs): pass diff --git a/sunspear/aggregators/property.py b/sunspear/aggregators/property.py index 277743f..fbaaacb 100644 --- a/sunspear/aggregators/property.py +++ b/sunspear/aggregators/property.py @@ -1,10 +1,11 @@ -from sunspear.aggregators.base import BaseAggregator -from sunspear.lib.dotdict import dotdictify - -from itertools import groupby +from __future__ import absolute_import, division, print_function import copy import re +from itertools import groupby + +from sunspear.aggregators.base import BaseAggregator +from sunspear.lib.dotdict import dotdictify class PropertyAggregator(BaseAggregator): diff --git a/sunspear/backends/base.py b/sunspear/backends/base.py index 3e415f9..6f75e60 100644 --- a/sunspear/backends/base.py +++ b/sunspear/backends/base.py @@ -1,9 +1,11 @@ -from sunspear.activitystreams.models import Activity, ReplyActivity, LikeActivity -from sunspear.exceptions import (SunspearDuplicateEntryException, SunspearInvalidActivityException, - SunspearInvalidObjectException) +from __future__ import absolute_import, division, print_function -import uuid import copy +import uuid + +from sunspear.activitystreams.models import Activity, LikeActivity, ReplyActivity +from sunspear.exceptions import ( + SunspearDuplicateEntryException, SunspearInvalidActivityException, SunspearInvalidObjectException) __all__ = ('BaseBackend', 'SUB_ACTIVITY_MAP') diff --git a/sunspear/backends/riak.py b/sunspear/backends/riak.py index 3a7d864..7637373 100644 --- a/sunspear/backends/riak.py +++ b/sunspear/backends/riak.py @@ -15,7 +15,7 @@ specific language governing permissions and limitations under the License. """ -from __future__ import absolute_import +from __future__ import absolute_import, print_function import calendar import copy @@ -26,7 +26,7 @@ from riak import RiakClient from sunspear.activitystreams.models import Activity, Model, Object -from sunspear.backends.base import SUB_ACTIVITY_MAP, BaseBackend +from sunspear.backends.base import BaseBackend, SUB_ACTIVITY_MAP from sunspear.exceptions import SunspearValidationException __all__ = ('RiakBackend', ) diff --git a/sunspear/clients.py b/sunspear/clients.py index 491e4ac..3348539 100644 --- a/sunspear/clients.py +++ b/sunspear/clients.py @@ -1,3 +1,6 @@ +from __future__ import absolute_import, division, print_function + + class SunspearClient(object): """ The class is used to create, delete, remove and update activity stream items. diff --git a/sunspear/exceptions.py b/sunspear/exceptions.py index 47eb1bc..b3b2792 100644 --- a/sunspear/exceptions.py +++ b/sunspear/exceptions.py @@ -1,3 +1,6 @@ +from __future__ import absolute_import, division, print_function, unicode_literals + + class SunspearBaseException(Exception): pass @@ -26,4 +29,4 @@ class SunspearInvalidActivityException(SunspearBaseException): pass class SunspearInvalidObjectException(SunspearBaseException): - pass \ No newline at end of file + pass diff --git a/sunspear/lib/dotdict.py b/sunspear/lib/dotdict.py index 50e4ce6..a09e6fa 100644 --- a/sunspear/lib/dotdict.py +++ b/sunspear/lib/dotdict.py @@ -1,5 +1,6 @@ #Originally 'borrowed' from http://stackoverflow.com/questions/3797957/python-easily-access-deeply-nested-dict-get-and-set #Some modifications mad to suit the needs of this project +from __future__ import absolute_import, division, print_function class dotdictify(dict): diff --git a/sunspear/lib/rfc3339.py b/sunspear/lib/rfc3339.py index a0057e5..1c3c938 100644 --- a/sunspear/lib/rfc3339.py +++ b/sunspear/lib/rfc3339.py @@ -20,6 +20,7 @@ .. _BitBucket: https://bitbucket.org/henry/clan.cx/issues ''' +from __future__ import absolute_import, division, print_function __author__ = 'Henry Precheur ' __license__ = 'ISCL' diff --git a/tests/test_activitystreams.py b/tests/test_activitystreams.py index 0df9f24..20d54c6 100644 --- a/tests/test_activitystreams.py +++ b/tests/test_activitystreams.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import +from __future__ import absolute_import, division, print_function import datetime diff --git a/tests/test_aggregators.py b/tests/test_aggregators.py index d493b62..139fa77 100644 --- a/tests/test_aggregators.py +++ b/tests/test_aggregators.py @@ -1,10 +1,10 @@ -from __future__ import absolute_import +from __future__ import absolute_import, division, print_function -from nose.tools import ok_, eq_, raises, set_trace +from itertools import groupby -from sunspear.aggregators.property import PropertyAggregator +from nose.tools import eq_, ok_, raises, set_trace -from itertools import groupby +from sunspear.aggregators.property import PropertyAggregator class TestPropertyAggregator(object): diff --git a/tests/test_backend.py b/tests/test_backend.py index 2f8ea21..c826e02 100644 --- a/tests/test_backend.py +++ b/tests/test_backend.py @@ -1,9 +1,9 @@ -from __future__ import absolute_import +from __future__ import absolute_import, division, print_function import datetime import six -from mock import ANY, MagicMock, call +from mock import ANY, call, MagicMock from nose.tools import eq_, ok_, raises, set_trace from sunspear.aggregators.property import PropertyAggregator diff --git a/tests/test_client.py b/tests/test_client.py index 26ec940..ea69e8e 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -1,14 +1,14 @@ -from __future__ import absolute_import +from __future__ import absolute_import, division, print_function -from nose.tools import ok_, eq_, set_trace, raises -from mock import MagicMock, call, ANY +import datetime + +from mock import ANY, call, MagicMock +from nose.tools import eq_, ok_, raises, set_trace from sunspear.aggregators.property import PropertyAggregator from sunspear.backends.riak import RiakBackend from sunspear.clients import SunspearClient -import datetime - riak_connection_options = { "nodes": [ {'http_port': 8098, 'host': '127.0.0.1'}], @@ -615,4 +615,3 @@ def test_get_activities_with_aggregation_pipline(self): activities = self._client.get_activities(activity_ids=activity_ids, aggregation_pipeline=[PropertyAggregator(properties=['verb', 'actor'])]) eq_([{u'id': u'7779', u'verb': u'like', u'target': {u'objectType': u'something', u'id': u'31415', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'inReplyTo': [], u'objectType': u'like', u'id': u'6669', u'published': u'2012-08-05T12:00:00Z'}, u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}}, {u'id': u'8889', u'verb': u'reply', u'target': {u'objectType': u'something', u'id': u'31415', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'content': u'This is my first reply', u'inReplyTo': [], u'objectType': u'reply', u'id': u'9999', u'published': u'2012-08-05T12:00:00Z'}, u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}}, {'grouped_by_attributes': ['verb', 'actor'], u'title': [u'Stream Item', u'Stream Item'], u'object': [{u'objectType': u'something', u'id': u'4353', u'published': u'2012-07-05T12:00:00Z'}, {u'published': u'2012-07-05T12:00:00Z', u'id': u'4353', u'objectType': u'something'}], u'actor': {u'published': u'2012-07-05T12:00:00Z', u'id': u'4321', u'objectType': u'something'}, u'verb': u'post', u'replies': [{u'totalItems': 2, u'items': [{u'verb': u'reply', u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'target': {u'objectType': u'something', u'id': u'31415', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'content': u'This is my first reply', u'inReplyTo': [], u'objectType': u'reply', u'id': u'9999', u'published': u'2012-08-05T12:00:00Z'}, u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'verb': u'reply', u'id': u'8889', u'objectType': u'activity'}}, {u'verb': u'reply', u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'target': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'content': u'This is my second reply', u'inReplyTo': [], u'objectType': u'reply', u'id': u'9998', u'published': u'2012-08-05T12:05:00Z'}, u'actor': {u'objectType': u'something', u'id': u'4321', u'published': u'2012-07-05T12:00:00Z'}, u'verb': u'reply', u'id': u'8888', u'objectType': u'activity'}}]}, {u'totalItems': 2, u'items': [{u'verb': u'reply', u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'target': {u'objectType': u'something', u'id': u'31415', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'content': u'This is my first reply', u'inReplyTo': [], u'objectType': u'reply', u'id': u'9999', u'published': u'2012-08-05T12:00:00Z'}, u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'verb': u'reply', u'id': u'8889', u'objectType': u'activity'}}, {u'verb': u'reply', u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'target': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'content': u'This is my second reply', u'inReplyTo': [], u'objectType': u'reply', u'id': u'9998', u'published': u'2012-08-05T12:05:00Z'}, u'actor': {u'objectType': u'something', u'id': u'4321', u'published': u'2012-07-05T12:00:00Z'}, u'verb': u'reply', u'id': u'8888', u'objectType': u'activity'}}]}], u'id': [u'5555', u'5556'], 'grouped_by_values': [u'post', {u'published': u'2012-07-05T12:00:00Z', u'id': u'4321', u'objectType': u'something'}]}, {u'id': u'7778', u'verb': u'like', u'target': {u'objectType': u'something', u'id': u'31415', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'inReplyTo': [], u'objectType': u'like', u'id': u'6669', u'published': u'2012-08-05T12:00:00Z'}, u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}}, {u'id': u'8888', u'verb': u'reply', u'target': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'content': u'This is my second reply', u'inReplyTo': [], u'objectType': u'reply', u'id': u'9998', u'published': u'2012-08-05T12:05:00Z'}, u'actor': {u'objectType': u'something', u'id': u'4321', u'published': u'2012-07-05T12:00:00Z'}}], activities) - diff --git a/tests/test_dotdict.py b/tests/test_dotdict.py index 602704e..14c74ff 100644 --- a/tests/test_dotdict.py +++ b/tests/test_dotdict.py @@ -1,8 +1,8 @@ -from __future__ import absolute_import +from __future__ import absolute_import, division, print_function -from sunspear.lib.dotdict import dotdictify +from nose.tools import eq_, ok_, raises -from nose.tools import ok_, eq_, raises +from sunspear.lib.dotdict import dotdictify class TestDotDictify(object): diff --git a/tests/test_rfc3339.py b/tests/test_rfc3339.py index a7bc723..7bb6725 100644 --- a/tests/test_rfc3339.py +++ b/tests/test_rfc3339.py @@ -1,11 +1,11 @@ -from __future__ import absolute_import +from __future__ import absolute_import, division, print_function -from sunspear.lib.rfc3339 import rfc3339, _timezone, _utc_offset, _timedelta_to_seconds +import datetime +import time from nose.tools import eq_, ok_ -import datetime -import time +from sunspear.lib.rfc3339 import _timedelta_to_seconds, _timezone, _utc_offset, rfc3339 class TestRFC3339(object): From a28268259e597799bdf6a20559ccd1ae72efb2cd Mon Sep 17 00:00:00 2001 From: Jonas Trappenberg Date: Sun, 26 Nov 2017 11:52:24 -0800 Subject: [PATCH 09/13] Add other future imports --- docs/source/conf.py | 2 +- setup.py | 2 +- sunspear/activitystreams/models.py | 2 +- sunspear/aggregators/base.py | 2 +- sunspear/aggregators/property.py | 2 +- sunspear/backends/base.py | 2 +- sunspear/backends/riak.py | 2 +- sunspear/clients.py | 2 +- sunspear/lib/dotdict.py | 2 +- sunspear/lib/rfc3339.py | 2 +- tests/test_activitystreams.py | 2 +- tests/test_aggregators.py | 2 +- tests/test_backend.py | 2 +- tests/test_client.py | 2 +- tests/test_dotdict.py | 2 +- tests/test_rfc3339.py | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 48c79ac..c75a7ba 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -11,7 +11,7 @@ # All configuration values have a default; values that are commented out # serve to show the default. -from __future__ import absolute_import, division, print_function +from __future__ import absolute_import, division, print_function, unicode_literals import os import sys diff --git a/setup.py b/setup.py index 955390b..c38d4ac 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ #!/usr/bin/python -from __future__ import absolute_import, division, print_function +from __future__ import absolute_import, division, print_function, unicode_literals from setuptools import find_packages, setup diff --git a/sunspear/activitystreams/models.py b/sunspear/activitystreams/models.py index 7cc434c..00d4845 100644 --- a/sunspear/activitystreams/models.py +++ b/sunspear/activitystreams/models.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function +from __future__ import absolute_import, division, print_function, unicode_literals import datetime diff --git a/sunspear/aggregators/base.py b/sunspear/aggregators/base.py index 669ed48..49b9b3d 100644 --- a/sunspear/aggregators/base.py +++ b/sunspear/aggregators/base.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function +from __future__ import absolute_import, division, print_function, unicode_literals class BaseAggregator(object): diff --git a/sunspear/aggregators/property.py b/sunspear/aggregators/property.py index fbaaacb..71e3edc 100644 --- a/sunspear/aggregators/property.py +++ b/sunspear/aggregators/property.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function +from __future__ import absolute_import, division, print_function, unicode_literals import copy import re diff --git a/sunspear/backends/base.py b/sunspear/backends/base.py index 6f75e60..6ffae46 100644 --- a/sunspear/backends/base.py +++ b/sunspear/backends/base.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function +from __future__ import absolute_import, division, print_function, unicode_literals import copy import uuid diff --git a/sunspear/backends/riak.py b/sunspear/backends/riak.py index 7637373..0a51034 100644 --- a/sunspear/backends/riak.py +++ b/sunspear/backends/riak.py @@ -15,7 +15,7 @@ specific language governing permissions and limitations under the License. """ -from __future__ import absolute_import, print_function +from __future__ import absolute_import, division, print_function, unicode_literals import calendar import copy diff --git a/sunspear/clients.py b/sunspear/clients.py index 3348539..88c56ff 100644 --- a/sunspear/clients.py +++ b/sunspear/clients.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function +from __future__ import absolute_import, division, print_function, unicode_literals class SunspearClient(object): diff --git a/sunspear/lib/dotdict.py b/sunspear/lib/dotdict.py index a09e6fa..78576c1 100644 --- a/sunspear/lib/dotdict.py +++ b/sunspear/lib/dotdict.py @@ -1,6 +1,6 @@ #Originally 'borrowed' from http://stackoverflow.com/questions/3797957/python-easily-access-deeply-nested-dict-get-and-set #Some modifications mad to suit the needs of this project -from __future__ import absolute_import, division, print_function +from __future__ import absolute_import, division, print_function, unicode_literals class dotdictify(dict): diff --git a/sunspear/lib/rfc3339.py b/sunspear/lib/rfc3339.py index 1c3c938..46e525d 100644 --- a/sunspear/lib/rfc3339.py +++ b/sunspear/lib/rfc3339.py @@ -20,7 +20,7 @@ .. _BitBucket: https://bitbucket.org/henry/clan.cx/issues ''' -from __future__ import absolute_import, division, print_function +from __future__ import absolute_import, division, print_function, unicode_literals __author__ = 'Henry Precheur ' __license__ = 'ISCL' diff --git a/tests/test_activitystreams.py b/tests/test_activitystreams.py index 20d54c6..b741b2c 100644 --- a/tests/test_activitystreams.py +++ b/tests/test_activitystreams.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function +from __future__ import absolute_import, division, print_function, unicode_literals import datetime diff --git a/tests/test_aggregators.py b/tests/test_aggregators.py index 139fa77..91ece85 100644 --- a/tests/test_aggregators.py +++ b/tests/test_aggregators.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function +from __future__ import absolute_import, division, print_function, unicode_literals from itertools import groupby diff --git a/tests/test_backend.py b/tests/test_backend.py index c826e02..51968ff 100644 --- a/tests/test_backend.py +++ b/tests/test_backend.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function +from __future__ import absolute_import, division, print_function, unicode_literals import datetime diff --git a/tests/test_client.py b/tests/test_client.py index ea69e8e..ed0df43 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function +from __future__ import absolute_import, division, print_function, unicode_literals import datetime diff --git a/tests/test_dotdict.py b/tests/test_dotdict.py index 14c74ff..f387db5 100644 --- a/tests/test_dotdict.py +++ b/tests/test_dotdict.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function +from __future__ import absolute_import, division, print_function, unicode_literals from nose.tools import eq_, ok_, raises diff --git a/tests/test_rfc3339.py b/tests/test_rfc3339.py index 7bb6725..75a612b 100644 --- a/tests/test_rfc3339.py +++ b/tests/test_rfc3339.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, division, print_function +from __future__ import absolute_import, division, print_function, unicode_literals import datetime import time From e5c0df7696df09b78f77bc4fdc740b1db4eeb166 Mon Sep 17 00:00:00 2001 From: Jonas Trappenberg Date: Sun, 26 Nov 2017 11:57:00 -0800 Subject: [PATCH 10/13] Automatic 2to3 transformation --- docs/source/conf.py | 16 ++++++++-------- sunspear/activitystreams/models.py | 2 +- sunspear/aggregators/property.py | 8 ++++---- sunspear/backends/base.py | 2 +- sunspear/backends/riak.py | 10 ++++------ tests/test_backend.py | 14 +++++++------- tests/test_client.py | 2 +- tests/test_rfc3339.py | 4 ++-- 8 files changed, 28 insertions(+), 30 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index c75a7ba..96c6570 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -49,8 +49,8 @@ master_doc = 'index' # General information about the project. -project = u'Sunspear' -copyright = u'2013, Numan Sachwani' +project = 'Sunspear' +copyright = '2013, Numan Sachwani' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -192,8 +192,8 @@ # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ('index', 'Sunspear.tex', u'Sunspear Documentation', - u'Numan Sachwani', 'manual'), + ('index', 'Sunspear.tex', 'Sunspear Documentation', + 'Numan Sachwani', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -222,8 +222,8 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'sunspear', u'Sunspear Documentation', - [u'Numan Sachwani'], 1) + ('index', 'sunspear', 'Sunspear Documentation', + ['Numan Sachwani'], 1) ] # If true, show URL addresses after external links. @@ -236,8 +236,8 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'Sunspear', u'Sunspear Documentation', - u'Numan Sachwani', 'Sunspear', 'One line description of project.', + ('index', 'Sunspear', 'Sunspear Documentation', + 'Numan Sachwani', 'Sunspear', 'One line description of project.', 'Miscellaneous'), ] diff --git a/sunspear/activitystreams/models.py b/sunspear/activitystreams/models.py index 00d4845..bdec8fc 100644 --- a/sunspear/activitystreams/models.py +++ b/sunspear/activitystreams/models.py @@ -91,7 +91,7 @@ def parse_data(self, data, *args, **kwargs): _parsed_data[c] = _parsed_data[c].parse_data(_parsed_data[c].get_dict()) #parse anything that is a dictionary for things like datetime fields that are datetime objects - for k, v in _parsed_data.items(): + for k, v in list(_parsed_data.items()): if isinstance(v, dict) and k not in self._response_fields: _parsed_data[k] = self.parse_data(v) diff --git a/sunspear/aggregators/property.py b/sunspear/aggregators/property.py index 71e3edc..fcc3389 100644 --- a/sunspear/aggregators/property.py +++ b/sunspear/aggregators/property.py @@ -49,12 +49,12 @@ def _listify_attributes(self, group_by_attributes=[], activity={}): nested_root, rest = attr.split('.', 1) #store a list of nested roots. We'll have to be careful not to listify these nested_root_attributes.append(nested_root) - for nested_dict_key, nested_dict_value in activity.get(nested_dict).items(): + for nested_dict_key, nested_dict_value in list(activity.get(nested_dict).items()): if nested_dict_key != deepest_attr: listified_dict['.'.join([nested_dict, nested_dict_key])] = [nested_dict_value] #now we listify all other non nested attributes - for key, val in activity.items(): + for key, val in list(activity.items()): if key not in group_by_attributes and key not in nested_root_attributes: listified_dict[key] = [val] @@ -97,7 +97,7 @@ def _aggregate_activities(self, group_by_attributes=[], grouped_activities=[]): #aggregate the rest of the activities into lists for activity in group_list[1:]: activity = dotdictify(activity) - for key in aggregated_activity.keys(): + for key in list(aggregated_activity.keys()): if key not in group_by_attributes and key not in nested_root_attributes: aggregated_activity[key].append(activity.get(key)) @@ -108,7 +108,7 @@ def _aggregate_activities(self, group_by_attributes=[], grouped_activities=[]): if nested_val is not None: nested_dict, deepest_attr = attr.rsplit('.', 1) - for nested_dict_key, nested_dict_value in activity.get(nested_dict).items(): + for nested_dict_key, nested_dict_value in list(activity.get(nested_dict).items()): if nested_dict_key != deepest_attr: aggregated_activity['.'.join([nested_dict, nested_dict_key])].append(nested_dict_value) diff --git a/sunspear/backends/base.py b/sunspear/backends/base.py index 6ffae46..9c30e97 100644 --- a/sunspear/backends/base.py +++ b/sunspear/backends/base.py @@ -77,7 +77,7 @@ def create_activity(self, activity, **kwargs): objs_created = [] objs_modified = [] - for key, value in activity_copy.items(): + for key, value in list(activity_copy.items()): if key in Activity._object_fields and isinstance(value, dict): if self.obj_exists(value): previous_value = self.get_obj([self._extract_id(value)])[0] diff --git a/sunspear/backends/riak.py b/sunspear/backends/riak.py index 0a51034..4aad206 100644 --- a/sunspear/backends/riak.py +++ b/sunspear/backends/riak.py @@ -232,7 +232,7 @@ def set_general_indexes(self, riak_object): :type riak_object: RiakObject :param riak_object: a RiakObject representing the model of the class """ - if not filter(lambda x: x[0] == "timestamp_int", riak_object.indexes): + if not [x for x in riak_object.indexes if x[0] == "timestamp_int"]: riak_object.add_index("timestamp_int", self._get_timestamp()) riak_object.remove_index('modified_int') @@ -355,7 +355,7 @@ def activity_get( :return: list -- a list of activities matching ``activity_ids``. If the activities is not found, it is not included in the result set. Activities are returned in the order of ids provided. """ - activity_ids = map(self._extract_id, activity_ids) + activity_ids = list(map(self._extract_id, activity_ids)) if not activity_ids: return [] @@ -428,9 +428,7 @@ def sub_activity_delete(self, sub_activity, sub_activity_verb, **kwargs): activity = self._activities.get(key=in_reply_to_key) activity_data = activity.data activity_data[sub_activity_model.sub_item_key]['totalItems'] -= 1 - activity_data[sub_activity_model.sub_item_key]['items'] = filter( - lambda x: x["id"] != sub_activity_id, - activity_data[sub_activity_model.sub_item_key]['items']) + activity_data[sub_activity_model.sub_item_key]['items'] = [x for x in activity_data[sub_activity_model.sub_item_key]['items'] if x["id"] != sub_activity_id] updated_activity = self.update_activity(activity_data, **kwargs) self.delete_activity(sub_activity_id) @@ -669,7 +667,7 @@ def _get_many_activities(self, activity_ids=[], raw_filter="", filters=None, inc #riak does not return the results in any particular order (unless we sort). So, #we have to put the objects returned by riak back in order - results_map = dict(map(lambda result: (result['id'], result,), results)) + results_map = dict([(result['id'], result,) for result in results]) reordered_results = [results_map[id] for id in activity_ids if id in results_map] return reordered_results diff --git a/tests/test_backend.py b/tests/test_backend.py index 51968ff..27f3dc0 100644 --- a/tests/test_backend.py +++ b/tests/test_backend.py @@ -1577,7 +1577,7 @@ def test_get_activities_with_aggregation_pipline(self): activities = self._backend.activity_get(activity_ids, aggregation_pipeline=[PropertyAggregator(properties=['verb', 'actor'])]) - eq_([{u'id': u'7779', u'verb': u'like', u'target': {u'objectType': u'something', u'id': u'31415', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'inReplyTo': [], u'objectType': u'like', u'id': u'6669', u'published': u'2012-08-05T12:00:00Z'}, u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}}, {u'id': u'8889', u'verb': u'reply', u'target': {u'objectType': u'something', u'id': u'31415', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'content': u'This is my first reply', u'inReplyTo': [], u'objectType': u'reply', u'id': u'9999', u'published': u'2012-08-05T12:00:00Z'}, u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}}, {'grouped_by_attributes': ['verb', 'actor'], u'title': [u'Stream Item', u'Stream Item'], u'object': [{u'objectType': u'something', u'id': u'4353', u'published': u'2012-07-05T12:00:00Z'}, {u'published': u'2012-07-05T12:00:00Z', u'id': u'4353', u'objectType': u'something'}], u'actor': {u'published': u'2012-07-05T12:00:00Z', u'id': u'4321', u'objectType': u'something'}, u'verb': u'post', u'replies': [{u'totalItems': 2, u'items': [{u'verb': u'reply', u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'target': {u'objectType': u'something', u'id': u'31415', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'content': u'This is my first reply', u'inReplyTo': [], u'objectType': u'reply', u'id': u'9999', u'published': u'2012-08-05T12:00:00Z'}, u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'verb': u'reply', u'id': u'8889', u'objectType': u'activity'}}, {u'verb': u'reply', u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'target': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'content': u'This is my second reply', u'inReplyTo': [], u'objectType': u'reply', u'id': u'9998', u'published': u'2012-08-05T12:05:00Z'}, u'actor': {u'objectType': u'something', u'id': u'4321', u'published': u'2012-07-05T12:00:00Z'}, u'verb': u'reply', u'id': u'8888', u'objectType': u'activity'}}]}, {u'totalItems': 2, u'items': [{u'verb': u'reply', u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'target': {u'objectType': u'something', u'id': u'31415', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'content': u'This is my first reply', u'inReplyTo': [], u'objectType': u'reply', u'id': u'9999', u'published': u'2012-08-05T12:00:00Z'}, u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'verb': u'reply', u'id': u'8889', u'objectType': u'activity'}}, {u'verb': u'reply', u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'target': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'content': u'This is my second reply', u'inReplyTo': [], u'objectType': u'reply', u'id': u'9998', u'published': u'2012-08-05T12:05:00Z'}, u'actor': {u'objectType': u'something', u'id': u'4321', u'published': u'2012-07-05T12:00:00Z'}, u'verb': u'reply', u'id': u'8888', u'objectType': u'activity'}}]}], u'id': [u'5555', u'5556'], 'grouped_by_values': [u'post', {u'published': u'2012-07-05T12:00:00Z', u'id': u'4321', u'objectType': u'something'}]}, {u'id': u'7778', u'verb': u'like', u'target': {u'objectType': u'something', u'id': u'31415', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'inReplyTo': [], u'objectType': u'like', u'id': u'6669', u'published': u'2012-08-05T12:00:00Z'}, u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}}, {u'id': u'8888', u'verb': u'reply', u'target': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'content': u'This is my second reply', u'inReplyTo': [], u'objectType': u'reply', u'id': u'9998', u'published': u'2012-08-05T12:05:00Z'}, u'actor': {u'objectType': u'something', u'id': u'4321', u'published': u'2012-07-05T12:00:00Z'}}], activities) + eq_([{'id': '7779', 'verb': 'like', 'target': {'objectType': 'something', 'id': '31415', 'published': '2012-07-05T12:00:00Z'}, 'object': {'inReplyTo': [], 'objectType': 'like', 'id': '6669', 'published': '2012-08-05T12:00:00Z'}, 'actor': {'objectType': 'something', 'id': '1234', 'published': '2012-07-05T12:00:00Z'}}, {'id': '8889', 'verb': 'reply', 'target': {'objectType': 'something', 'id': '31415', 'published': '2012-07-05T12:00:00Z'}, 'object': {'content': 'This is my first reply', 'inReplyTo': [], 'objectType': 'reply', 'id': '9999', 'published': '2012-08-05T12:00:00Z'}, 'actor': {'objectType': 'something', 'id': '1234', 'published': '2012-07-05T12:00:00Z'}}, {'grouped_by_attributes': ['verb', 'actor'], 'title': ['Stream Item', 'Stream Item'], 'object': [{'objectType': 'something', 'id': '4353', 'published': '2012-07-05T12:00:00Z'}, {'published': '2012-07-05T12:00:00Z', 'id': '4353', 'objectType': 'something'}], 'actor': {'published': '2012-07-05T12:00:00Z', 'id': '4321', 'objectType': 'something'}, 'verb': 'post', 'replies': [{'totalItems': 2, 'items': [{'verb': 'reply', 'actor': {'objectType': 'something', 'id': '1234', 'published': '2012-07-05T12:00:00Z'}, 'object': {'target': {'objectType': 'something', 'id': '31415', 'published': '2012-07-05T12:00:00Z'}, 'object': {'content': 'This is my first reply', 'inReplyTo': [], 'objectType': 'reply', 'id': '9999', 'published': '2012-08-05T12:00:00Z'}, 'actor': {'objectType': 'something', 'id': '1234', 'published': '2012-07-05T12:00:00Z'}, 'verb': 'reply', 'id': '8889', 'objectType': 'activity'}}, {'verb': 'reply', 'actor': {'objectType': 'something', 'id': '1234', 'published': '2012-07-05T12:00:00Z'}, 'object': {'target': {'objectType': 'something', 'id': '1234', 'published': '2012-07-05T12:00:00Z'}, 'object': {'content': 'This is my second reply', 'inReplyTo': [], 'objectType': 'reply', 'id': '9998', 'published': '2012-08-05T12:05:00Z'}, 'actor': {'objectType': 'something', 'id': '4321', 'published': '2012-07-05T12:00:00Z'}, 'verb': 'reply', 'id': '8888', 'objectType': 'activity'}}]}, {'totalItems': 2, 'items': [{'verb': 'reply', 'actor': {'objectType': 'something', 'id': '1234', 'published': '2012-07-05T12:00:00Z'}, 'object': {'target': {'objectType': 'something', 'id': '31415', 'published': '2012-07-05T12:00:00Z'}, 'object': {'content': 'This is my first reply', 'inReplyTo': [], 'objectType': 'reply', 'id': '9999', 'published': '2012-08-05T12:00:00Z'}, 'actor': {'objectType': 'something', 'id': '1234', 'published': '2012-07-05T12:00:00Z'}, 'verb': 'reply', 'id': '8889', 'objectType': 'activity'}}, {'verb': 'reply', 'actor': {'objectType': 'something', 'id': '1234', 'published': '2012-07-05T12:00:00Z'}, 'object': {'target': {'objectType': 'something', 'id': '1234', 'published': '2012-07-05T12:00:00Z'}, 'object': {'content': 'This is my second reply', 'inReplyTo': [], 'objectType': 'reply', 'id': '9998', 'published': '2012-08-05T12:05:00Z'}, 'actor': {'objectType': 'something', 'id': '4321', 'published': '2012-07-05T12:00:00Z'}, 'verb': 'reply', 'id': '8888', 'objectType': 'activity'}}]}], 'id': ['5555', '5556'], 'grouped_by_values': ['post', {'published': '2012-07-05T12:00:00Z', 'id': '4321', 'objectType': 'something'}]}, {'id': '7778', 'verb': 'like', 'target': {'objectType': 'something', 'id': '31415', 'published': '2012-07-05T12:00:00Z'}, 'object': {'inReplyTo': [], 'objectType': 'like', 'id': '6669', 'published': '2012-08-05T12:00:00Z'}, 'actor': {'objectType': 'something', 'id': '1234', 'published': '2012-07-05T12:00:00Z'}}, {'id': '8888', 'verb': 'reply', 'target': {'objectType': 'something', 'id': '1234', 'published': '2012-07-05T12:00:00Z'}, 'object': {'content': 'This is my second reply', 'inReplyTo': [], 'objectType': 'reply', 'id': '9998', 'published': '2012-08-05T12:05:00Z'}, 'actor': {'objectType': 'something', 'id': '4321', 'published': '2012-07-05T12:00:00Z'}}], activities) class TestIndexes(object): @@ -1656,8 +1656,8 @@ def test_create_obj_indexes(self): riak_obj = self._backend._objects.get(key=actstream_obj['id']) riak_obj.data - ok_(filter(lambda x: x[0] == 'timestamp_int', riak_obj.indexes) != []) - ok_(filter(lambda x: x[0] == 'modified_int', riak_obj.indexes) != []) + ok_([x for x in riak_obj.indexes if x[0] == 'timestamp_int'] != []) + ok_([x for x in riak_obj.indexes if x[0] == 'modified_int'] != []) def test_create_activity_indexes(self): self._backend._activities.get('5').delete() @@ -1679,8 +1679,8 @@ def test_create_activity_indexes(self): riak_obj = self._backend._activities.get(key=act_obj_dict['id']) riak_obj.data - ok_(filter(lambda x: x[0] == 'timestamp_int', riak_obj.indexes) != []) - ok_(filter(lambda x: x[0] == 'modified_int', riak_obj.indexes) != []) + ok_([x for x in riak_obj.indexes if x[0] == 'timestamp_int'] != []) + ok_([x for x in riak_obj.indexes if x[0] == 'modified_int'] != []) eq_(filter(lambda x: x[0] == 'verb_bin', riak_obj.indexes)[0][1], 'post') eq_(filter(lambda x: x[0] == 'actor_bin', riak_obj.indexes)[0][1], actor_id) eq_(filter(lambda x: x[0] == 'object_bin', riak_obj.indexes)[0][1], object_id) @@ -1714,8 +1714,8 @@ def test_create_sub_activity_indexes(self): riak_obj = self._backend._activities.get(key=like_activity_dict['id']) riak_obj.data - ok_(filter(lambda x: x[0] == 'timestamp_int', riak_obj.indexes) != []) - ok_(filter(lambda x: x[0] == 'modified_int', riak_obj.indexes) != []) + ok_([x for x in riak_obj.indexes if x[0] == 'timestamp_int'] != []) + ok_([x for x in riak_obj.indexes if x[0] == 'modified_int'] != []) eq_(filter(lambda x: x[0] == 'verb_bin', riak_obj.indexes)[0][1], 'like') eq_(filter(lambda x: x[0] == 'actor_bin', riak_obj.indexes)[0][1], actor2_id) eq_(filter(lambda x: x[0] == 'object_bin', riak_obj.indexes)[0][1], like_activity_dict['object']['id']) diff --git a/tests/test_client.py b/tests/test_client.py index ed0df43..3da4b3a 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -614,4 +614,4 @@ def test_get_activities_with_aggregation_pipline(self): activities = self._client.get_activities(activity_ids=activity_ids, aggregation_pipeline=[PropertyAggregator(properties=['verb', 'actor'])]) - eq_([{u'id': u'7779', u'verb': u'like', u'target': {u'objectType': u'something', u'id': u'31415', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'inReplyTo': [], u'objectType': u'like', u'id': u'6669', u'published': u'2012-08-05T12:00:00Z'}, u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}}, {u'id': u'8889', u'verb': u'reply', u'target': {u'objectType': u'something', u'id': u'31415', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'content': u'This is my first reply', u'inReplyTo': [], u'objectType': u'reply', u'id': u'9999', u'published': u'2012-08-05T12:00:00Z'}, u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}}, {'grouped_by_attributes': ['verb', 'actor'], u'title': [u'Stream Item', u'Stream Item'], u'object': [{u'objectType': u'something', u'id': u'4353', u'published': u'2012-07-05T12:00:00Z'}, {u'published': u'2012-07-05T12:00:00Z', u'id': u'4353', u'objectType': u'something'}], u'actor': {u'published': u'2012-07-05T12:00:00Z', u'id': u'4321', u'objectType': u'something'}, u'verb': u'post', u'replies': [{u'totalItems': 2, u'items': [{u'verb': u'reply', u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'target': {u'objectType': u'something', u'id': u'31415', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'content': u'This is my first reply', u'inReplyTo': [], u'objectType': u'reply', u'id': u'9999', u'published': u'2012-08-05T12:00:00Z'}, u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'verb': u'reply', u'id': u'8889', u'objectType': u'activity'}}, {u'verb': u'reply', u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'target': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'content': u'This is my second reply', u'inReplyTo': [], u'objectType': u'reply', u'id': u'9998', u'published': u'2012-08-05T12:05:00Z'}, u'actor': {u'objectType': u'something', u'id': u'4321', u'published': u'2012-07-05T12:00:00Z'}, u'verb': u'reply', u'id': u'8888', u'objectType': u'activity'}}]}, {u'totalItems': 2, u'items': [{u'verb': u'reply', u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'target': {u'objectType': u'something', u'id': u'31415', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'content': u'This is my first reply', u'inReplyTo': [], u'objectType': u'reply', u'id': u'9999', u'published': u'2012-08-05T12:00:00Z'}, u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'verb': u'reply', u'id': u'8889', u'objectType': u'activity'}}, {u'verb': u'reply', u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'target': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'content': u'This is my second reply', u'inReplyTo': [], u'objectType': u'reply', u'id': u'9998', u'published': u'2012-08-05T12:05:00Z'}, u'actor': {u'objectType': u'something', u'id': u'4321', u'published': u'2012-07-05T12:00:00Z'}, u'verb': u'reply', u'id': u'8888', u'objectType': u'activity'}}]}], u'id': [u'5555', u'5556'], 'grouped_by_values': [u'post', {u'published': u'2012-07-05T12:00:00Z', u'id': u'4321', u'objectType': u'something'}]}, {u'id': u'7778', u'verb': u'like', u'target': {u'objectType': u'something', u'id': u'31415', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'inReplyTo': [], u'objectType': u'like', u'id': u'6669', u'published': u'2012-08-05T12:00:00Z'}, u'actor': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}}, {u'id': u'8888', u'verb': u'reply', u'target': {u'objectType': u'something', u'id': u'1234', u'published': u'2012-07-05T12:00:00Z'}, u'object': {u'content': u'This is my second reply', u'inReplyTo': [], u'objectType': u'reply', u'id': u'9998', u'published': u'2012-08-05T12:05:00Z'}, u'actor': {u'objectType': u'something', u'id': u'4321', u'published': u'2012-07-05T12:00:00Z'}}], activities) + eq_([{'id': '7779', 'verb': 'like', 'target': {'objectType': 'something', 'id': '31415', 'published': '2012-07-05T12:00:00Z'}, 'object': {'inReplyTo': [], 'objectType': 'like', 'id': '6669', 'published': '2012-08-05T12:00:00Z'}, 'actor': {'objectType': 'something', 'id': '1234', 'published': '2012-07-05T12:00:00Z'}}, {'id': '8889', 'verb': 'reply', 'target': {'objectType': 'something', 'id': '31415', 'published': '2012-07-05T12:00:00Z'}, 'object': {'content': 'This is my first reply', 'inReplyTo': [], 'objectType': 'reply', 'id': '9999', 'published': '2012-08-05T12:00:00Z'}, 'actor': {'objectType': 'something', 'id': '1234', 'published': '2012-07-05T12:00:00Z'}}, {'grouped_by_attributes': ['verb', 'actor'], 'title': ['Stream Item', 'Stream Item'], 'object': [{'objectType': 'something', 'id': '4353', 'published': '2012-07-05T12:00:00Z'}, {'published': '2012-07-05T12:00:00Z', 'id': '4353', 'objectType': 'something'}], 'actor': {'published': '2012-07-05T12:00:00Z', 'id': '4321', 'objectType': 'something'}, 'verb': 'post', 'replies': [{'totalItems': 2, 'items': [{'verb': 'reply', 'actor': {'objectType': 'something', 'id': '1234', 'published': '2012-07-05T12:00:00Z'}, 'object': {'target': {'objectType': 'something', 'id': '31415', 'published': '2012-07-05T12:00:00Z'}, 'object': {'content': 'This is my first reply', 'inReplyTo': [], 'objectType': 'reply', 'id': '9999', 'published': '2012-08-05T12:00:00Z'}, 'actor': {'objectType': 'something', 'id': '1234', 'published': '2012-07-05T12:00:00Z'}, 'verb': 'reply', 'id': '8889', 'objectType': 'activity'}}, {'verb': 'reply', 'actor': {'objectType': 'something', 'id': '1234', 'published': '2012-07-05T12:00:00Z'}, 'object': {'target': {'objectType': 'something', 'id': '1234', 'published': '2012-07-05T12:00:00Z'}, 'object': {'content': 'This is my second reply', 'inReplyTo': [], 'objectType': 'reply', 'id': '9998', 'published': '2012-08-05T12:05:00Z'}, 'actor': {'objectType': 'something', 'id': '4321', 'published': '2012-07-05T12:00:00Z'}, 'verb': 'reply', 'id': '8888', 'objectType': 'activity'}}]}, {'totalItems': 2, 'items': [{'verb': 'reply', 'actor': {'objectType': 'something', 'id': '1234', 'published': '2012-07-05T12:00:00Z'}, 'object': {'target': {'objectType': 'something', 'id': '31415', 'published': '2012-07-05T12:00:00Z'}, 'object': {'content': 'This is my first reply', 'inReplyTo': [], 'objectType': 'reply', 'id': '9999', 'published': '2012-08-05T12:00:00Z'}, 'actor': {'objectType': 'something', 'id': '1234', 'published': '2012-07-05T12:00:00Z'}, 'verb': 'reply', 'id': '8889', 'objectType': 'activity'}}, {'verb': 'reply', 'actor': {'objectType': 'something', 'id': '1234', 'published': '2012-07-05T12:00:00Z'}, 'object': {'target': {'objectType': 'something', 'id': '1234', 'published': '2012-07-05T12:00:00Z'}, 'object': {'content': 'This is my second reply', 'inReplyTo': [], 'objectType': 'reply', 'id': '9998', 'published': '2012-08-05T12:05:00Z'}, 'actor': {'objectType': 'something', 'id': '4321', 'published': '2012-07-05T12:00:00Z'}, 'verb': 'reply', 'id': '8888', 'objectType': 'activity'}}]}], 'id': ['5555', '5556'], 'grouped_by_values': ['post', {'published': '2012-07-05T12:00:00Z', 'id': '4321', 'objectType': 'something'}]}, {'id': '7778', 'verb': 'like', 'target': {'objectType': 'something', 'id': '31415', 'published': '2012-07-05T12:00:00Z'}, 'object': {'inReplyTo': [], 'objectType': 'like', 'id': '6669', 'published': '2012-08-05T12:00:00Z'}, 'actor': {'objectType': 'something', 'id': '1234', 'published': '2012-07-05T12:00:00Z'}}, {'id': '8888', 'verb': 'reply', 'target': {'objectType': 'something', 'id': '1234', 'published': '2012-07-05T12:00:00Z'}, 'object': {'content': 'This is my second reply', 'inReplyTo': [], 'objectType': 'reply', 'id': '9998', 'published': '2012-08-05T12:05:00Z'}, 'actor': {'objectType': 'something', 'id': '4321', 'published': '2012-07-05T12:00:00Z'}}], activities) diff --git a/tests/test_rfc3339.py b/tests/test_rfc3339.py index 75a612b..2522222 100644 --- a/tests/test_rfc3339.py +++ b/tests/test_rfc3339.py @@ -91,13 +91,13 @@ def test_timestamp_utc(self): self.local_timezone)) def test_before_1970(self): - d = datetime.date(1885, 01, 04) + d = datetime.date(1885, 0o1, 0o4) ok_(rfc3339(d).startswith('1885-01-04T00:00:00')) eq_(rfc3339(d, utc=True, use_system_timezone=False), '1885-01-04T00:00:00Z') def test_1920(self): - d = datetime.date(1920, 02, 29) + d = datetime.date(1920, 0o2, 29) x = rfc3339(d, utc=False, use_system_timezone=True) ok_(x.startswith('1920-02-29T00:00:00')) From c86563c499ff089b7edc2280601d9975b0521922 Mon Sep 17 00:00:00 2001 From: Jonas Trappenberg Date: Sun, 17 Dec 2017 20:00:48 -0800 Subject: [PATCH 11/13] Use integer division --- sunspear/backends/riak.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sunspear/backends/riak.py b/sunspear/backends/riak.py index 4aad206..30c415e 100644 --- a/sunspear/backends/riak.py +++ b/sunspear/backends/riak.py @@ -697,7 +697,7 @@ def _get_timestamp(self): returns a unix timestamp representing the ``datetime`` object """ dt_obj = datetime.datetime.utcnow() - return int((calendar.timegm(dt_obj.utctimetuple()) * 1000)) + (dt_obj.microsecond / 1000) + return int((calendar.timegm(dt_obj.utctimetuple()) * 1000)) + (dt_obj.microsecond // 1000) def get_new_id(self): """ From cf8ffedcd0568bbf5441a1a8fc139480dea84f74 Mon Sep 17 00:00:00 2001 From: Jonas Trappenberg Date: Tue, 2 Jan 2018 17:09:36 -0800 Subject: [PATCH 12/13] str in both python2 and 3 --- sunspear/backends/riak.py | 33 +++++++++++++++++---------------- sunspear/compat.py | 25 +++++++++++++++++++++++++ tests/test_backend.py | 22 +++++++++++----------- 3 files changed, 53 insertions(+), 27 deletions(-) create mode 100644 sunspear/compat.py diff --git a/sunspear/backends/riak.py b/sunspear/backends/riak.py index 30c415e..c5e8fca 100644 --- a/sunspear/backends/riak.py +++ b/sunspear/backends/riak.py @@ -27,6 +27,7 @@ from sunspear.activitystreams.models import Activity, Model, Object from sunspear.backends.base import BaseBackend, SUB_ACTIVITY_MAP +from sunspear.compat import must_be_str from sunspear.exceptions import SunspearValidationException __all__ = ('RiakBackend', ) @@ -154,8 +155,8 @@ def __init__( pr=None, pw=None, **kwargs): self._riak_backend = RiakClient(protocol=protocol, nodes=nodes, **kwargs) - self._objects = self._riak_backend.bucket(objects_bucket_name) - self._activities = self._riak_backend.bucket(activities_bucket_name) + self._objects = self._riak_backend.bucket(must_be_str(objects_bucket_name)) + self._activities = self._riak_backend.bucket(must_be_str(activities_bucket_name)) if r: self._objects.r = r @@ -232,11 +233,11 @@ def set_general_indexes(self, riak_object): :type riak_object: RiakObject :param riak_object: a RiakObject representing the model of the class """ - if not [x for x in riak_object.indexes if x[0] == "timestamp_int"]: - riak_object.add_index("timestamp_int", self._get_timestamp()) + if not any(must_be_str(name) == must_be_str('timestamp_int') for name, value in riak_object.indexes): + riak_object.add_index(must_be_str("timestamp_int"), self._get_timestamp()) - riak_object.remove_index('modified_int') - riak_object.add_index("modified_int", self._get_timestamp()) + riak_object.remove_index(must_be_str('modified_int')) + riak_object.add_index(must_be_str("modified_int"), self._get_timestamp()) return riak_object def obj_update(self, obj, **kwargs): @@ -301,15 +302,15 @@ def set_activity_indexes(self, riak_object): """ _dict = riak_object.data - riak_object.remove_index('verb_bin') - riak_object.remove_index('actor_bin') - riak_object.remove_index('object_bin') - riak_object.add_index("verb_bin", self._extract_id(_dict['verb'])) - riak_object.add_index("actor_bin", self._extract_id(_dict['actor'])) - riak_object.add_index("object_bin", self._extract_id(_dict['object'])) + riak_object.remove_index(must_be_str('verb_bin')) + riak_object.remove_index(must_be_str('actor_bin')) + riak_object.remove_index(must_be_str('object_bin')) + riak_object.add_index(must_be_str("verb_bin"), self._extract_id(_dict['verb'])) + riak_object.add_index(must_be_str("actor_bin"), self._extract_id(_dict['actor'])) + riak_object.add_index(must_be_str("object_bin"), self._extract_id(_dict['object'])) if 'target' in _dict and _dict.get("target"): - riak_object.remove_index('target_bin') - riak_object.add_index("target_bin", self._extract_id(_dict['target'])) + riak_object.remove_index(must_be_str('target_bin')) + riak_object.add_index(must_be_str("target_bin"), self._extract_id(_dict['target'])) return riak_object @@ -446,8 +447,8 @@ def set_sub_item_indexes(self, riak_object, **kwargs): original_activity_id = kwargs.get('activity_id') if not original_activity_id: raise SunspearValidationException() - riak_object.remove_index('inreplyto_bin') - riak_object.add_index("inreplyto_bin", str(original_activity_id)) + riak_object.remove_index(must_be_str('inreplyto_bin')) + riak_object.add_index(must_be_str("inreplyto_bin"), str(original_activity_id)) return riak_object diff --git a/sunspear/compat.py b/sunspear/compat.py new file mode 100644 index 0000000..61060ca --- /dev/null +++ b/sunspear/compat.py @@ -0,0 +1,25 @@ +from __future__ import absolute_import, division, print_function, unicode_literals + +import traceback +from logging import getLogger + +import six + +logger = getLogger(__name__) + + +def must_be_str(arg): + """ + Some functions require `str` in Python 2, i.e. its binary type, + but also `str` in Python 3, which is its text type... + + Accommodate both. + """ + if six.PY2: + if isinstance(arg, six.text_type): + return arg.encode('utf-8') + # The idea of this function is to simply remove all function calls once we're on python 3, so let's be sure we + # always have the right type passed in in python 2, i.e. `unicode`. + traceback.print_stack() + logger.warn('Unexpectedly got non-unicode in `must_be_str`...', extra={'stack': True}) + return arg diff --git a/tests/test_backend.py b/tests/test_backend.py index 27f3dc0..29143c4 100644 --- a/tests/test_backend.py +++ b/tests/test_backend.py @@ -4,17 +4,17 @@ import six from mock import ANY, call, MagicMock -from nose.tools import eq_, ok_, raises, set_trace +from nose.tools import eq_, ok_, raises from sunspear.aggregators.property import PropertyAggregator from sunspear.backends.riak import RiakBackend +from sunspear.compat import must_be_str from sunspear.exceptions import SunspearValidationException riak_connection_options = { "nodes": [ {'http_port': 8098, 'host': '127.0.0.1'}], 'protocol': 'http', - # "nodes": [{'host': '127.0.0.1', 'pb_port': 10017}, {'host': '127.0.0.1', 'pb_port': 10027}, {'host': '127.0.0.1', 'pb_port': 10037}], } @@ -1592,10 +1592,10 @@ def test_set_sub_item_indexes(self): self._backend.set_activity_indexes(riak_obj_mock) calls = [ - call.add_index('verb_bin', 'post'), - call.add_index('actor_bin', '1234'), - call.add_index('object_bin', '5678'), - call.add_index('target_bin', '4333'), + call.add_index(must_be_str('verb_bin'), 'post'), + call.add_index(must_be_str('actor_bin'), '1234'), + call.add_index(must_be_str('object_bin'), '5678'), + call.add_index(must_be_str('target_bin'), '4333'), ] riak_obj_mock.assert_has_calls(calls, any_order=True) @@ -1608,7 +1608,7 @@ def test_set_sub_item_indexes_reply(self): self._backend.set_sub_item_indexes(riak_obj_mock, activity_id=1234) calls = [ - call.add_index('inreplyto_bin', ANY), + call.add_index(must_be_str('inreplyto_bin'), ANY), ] riak_obj_mock.assert_has_calls(calls, any_order=True) @@ -1628,8 +1628,8 @@ def test_set_general_indexes_not_already_created_set(self): self._backend.set_general_indexes(riak_obj_mock) calls = [ - call.add_index('timestamp_int', ANY), - call.add_index('modified_int', ANY), + call.add_index(must_be_str('timestamp_int'), ANY), + call.add_index(must_be_str('modified_int'), ANY), ] riak_obj_mock.assert_has_calls(calls, any_order=True) @@ -1637,12 +1637,12 @@ def test_set_general_indexes_not_already_created_set(self): def test_set_general_indexes_already_created(self): riak_obj_mock = MagicMock() - riak_obj_mock.indexes = [('timestamp_int', 12343214,)] + riak_obj_mock.indexes = [(must_be_str('timestamp_int'), 12343214,)] self._backend.set_general_indexes(riak_obj_mock) calls = [ - call.add_index('modified_int', ANY), + call.add_index(must_be_str('modified_int'), ANY), ] riak_obj_mock.assert_has_calls(calls, any_order=True) From fa03795c1a1306140e0793451570600efbf4222f Mon Sep 17 00:00:00 2001 From: Tony Angerilli Date: Fri, 16 Aug 2019 07:45:11 -0700 Subject: [PATCH 13/13] filter in python 3 does not return a list --- sunspear/backends/riak.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sunspear/backends/riak.py b/sunspear/backends/riak.py index c5e8fca..bda720b 100644 --- a/sunspear/backends/riak.py +++ b/sunspear/backends/riak.py @@ -425,7 +425,7 @@ def sub_activity_delete(self, sub_activity, sub_activity_verb, **kwargs): raise SunspearValidationException("Trying to delete something that is not a {}.".format(sub_activity_model.sub_item_verb)) #clean up the reference from the original activity - in_reply_to_key = filter(lambda x: x[0] == 'inreplyto_bin', sub_activity_riak_model.indexes)[0][1] + in_reply_to_key = [x for x in sub_activity_riak_model.indexes if x[0] == 'inreplyto_bin'][0][1] activity = self._activities.get(key=in_reply_to_key) activity_data = activity.data activity_data[sub_activity_model.sub_item_key]['totalItems'] -= 1