diff --git a/parse_rest/datatypes.py b/parse_rest/datatypes.py index 46de98a..efc3e28 100644 --- a/parse_rest/datatypes.py +++ b/parse_rest/datatypes.py @@ -275,6 +275,22 @@ def _to_native(self): return {'__type': 'Bytes', 'base64': self._encoded} +@complex_type() +class Array(ParseType): + + @classmethod + def from_native(cls, **kw): + return cls(kw) + + def __init__(self, elements): + self._elements = elements + self._orig_elements = elements + + def _to_native(self): + return self._elements + + + @complex_type() class GeoPoint(ParseType): @@ -626,7 +642,6 @@ def manageRelation(self, action, key, className, objectsId): } } self.__class__.PUT(self._absolute_url, **payload) - # self.__dict__[key] = '' def relation(self, key): if not hasattr(self, key): @@ -635,3 +650,31 @@ def relation(self, key): return getattr(self, key).with_parent(parentObject=self, key=key) except: raise ParseError("Column '%s' is not a Relation." % (key,)) + + def addToArray(self, key, objects): + payload = { + key: { + '__op': 'Add', 'objects': objects + } + } + self.__class__.PUT(self._absolute_url, **payload) + self.__dict__[key] = self.__dict__.get(key, []) + objects + + def addUniqueToArray(self, key, objects): + payload = { + key: { + '__op': 'AddUnique', 'objects': objects + } + } + self.__class__.PUT(self._absolute_url, **payload) + data = self.__dict__.get(key, []) + self.__dict__[key] = data + [x for x in objects if x not in data] + + def removeFromArray(self, key, objects): + payload = { + key: { + '__op': 'Remove', 'objects': objects + } + } + self.__class__.PUT(self._absolute_url, **payload) + self.__dict__[key] = [x for x in self.__dict__.get(key, []) if x not in objects] diff --git a/parse_rest/tests.py b/parse_rest/tests.py index 50d87d9..5017e46 100755 --- a/parse_rest/tests.py +++ b/parse_rest/tests.py @@ -81,7 +81,7 @@ class CollectedItem(Object): class TestObject(unittest.TestCase): def setUp(self): - self.score = GameScore(score=1337, player_name='John Doe', cheat_mode=False) + self.score = GameScore(score=1337, player_name='John Doe', cheat_mode=False, achievements=['No Miss', 'Ninja']) self.sao_paulo = City(name='São Paulo', location=GeoPoint(-23.5, -46.6167)) self.collected_item = CollectedItem(type="Sword", isAwesome=True) @@ -150,6 +150,24 @@ def testCanRemoveField(self): self.assertTrue(GameScore.Query.filter(score=None).exists(), 'Failed to remove score on backend') + def testCanOperateArray(self): + self.score.save() + + self.score.addToArray('achievements', ['Ninja Head', 'Thunder', 'Ninja']) + correct = ['No Miss', 'Ninja', 'Ninja Head', 'Thunder', 'Ninja'] + self.assertEqual(self.score.achievements, correct) + self.assertEqual(GameScore.Query.get(objectId=self.score.objectId).achievements, correct) + + self.score.removeFromArray('achievements', ['Ninja']) + correct = ['No Miss', 'Ninja Head', 'Thunder'] + self.assertEqual(self.score.achievements, correct) + self.assertEqual(GameScore.Query.get(objectId=self.score.objectId).achievements, correct) + + self.score.addUniqueToArray('achievements', ['Ninja Head', 'Hero']) + correct = ['No Miss', 'Ninja Head', 'Thunder', 'Hero'] + self.assertEqual(self.score.achievements, correct) + self.assertEqual(GameScore.Query.get(objectId=self.score.objectId).achievements, correct) + def testAssociatedObject(self): """test saving and associating a different object""" @@ -201,7 +219,7 @@ def setUp(self): self.now = datetime.datetime.now() self.score = GameScore( score=1337, player_name='John Doe', cheat_mode=False, - date_of_birth=self.now + date_of_birth=self.now, achievements=['No Miss', 'Ninja'] ) self.sao_paulo = City( name='São Paulo', location=GeoPoint(-23.5, -46.6167) @@ -211,6 +229,10 @@ def testCanConvertToNative(self): native_data = self.sao_paulo._to_native() self.assertIsInstance(native_data, dict, 'Can not convert object to dict') + def testCanConvertArray(self): + native_data = self.score._to_native() + self.assertEqual(native_data['achievements'], ['No Miss', 'Ninja']) + def testCanConvertNestedLocation(self): native_sao_paulo = self.sao_paulo._to_native() location_dict = native_sao_paulo.get('location')