def test_key_kind(self): """ Checks that db.Keys stored in the database use proper kinds. Key kind should be the name of the table (db_table) of a model for primary keys of entities, but for foreign keys, references in general, it should be the db_table of the model the field refers to. Note that Django hides the underlying db.Key objects well, and it does work even with wrong kinds, but keeping the data consistent may be significant for external tools. TODO: Add DictField / EmbeddedModelField and nesting checks. """ parent = ParentKind.objects.create(pk=1) child = ChildKind.objects.create( pk=2, parent=parent, parents=[parent.pk]) self.assertEqual(child.parent.pk, parent.pk) self.assertEqual(child.parents[0], parent.pk) from google.appengine.api.datastore import Get from google.appengine.api.datastore_types import Key parent_key = Key.from_path(parent._meta.db_table, 1) child_key = Key.from_path(child._meta.db_table, 2) parent_entity = Get(parent_key) child_entity = Get(child_key) parent_column = child._meta.get_field('parent').column parents_column = child._meta.get_field('parents').column self.assertEqual(child_entity[parent_column], parent_key) self.assertEqual(child_entity[parents_column][0], parent_key)
def test_given_score_and_TwoDisapprovingButNonAgreeingReviewerAndOneApprovingReviewer_then_NonApprovingReviewerAreCheater_and_playerVerifiedScoreIsUpdated(self): score = {'score' : 3, 'proof' : "sdsd", 'time' : 0} playerId = "test" createPlayer(playerId, playerId) service.start(playerId) service.setScore(playerId, score) playerKey = Key.from_path('Player', playerId) createReviewerAndReview("test2", playerKey, {'score':99, 'time': 0}) createReviewerAndReview("test3", playerKey, {'score':999, 'time': 0}) createReviewerAndReview("test4", playerKey, {'score':3, 'time': 0}) verifiedScoreWrapper = VerifiedScoreWrapper.get_by_key_name('verifiedScore', parent=playerKey) verifiedScore = verifiedScoreWrapper.verified self.assertEqual(verifiedScore.value, 3) playerKey = Key.from_path('Player', 'test2') playerRecord = Record.get_by_key_name('record', parent=playerKey) self.assertEqual(playerRecord.numCheat, 1) playerKey = Key.from_path('Player', 'test3') playerRecord = Record.get_by_key_name('record', parent=playerKey) self.assertEqual(playerRecord.numCheat, 1)
def test_given_score_and_ThreeDisapprovingReviewerOfWhichTwoAgree_then_NonAgreeingReviewerAndPLayerAreCheater(self): score = {'score' : 99, 'proof' : "sdsd", 'time' : 0} playerId = "test" createPlayer(playerId, playerId) service.start(playerId) service.setScore(playerId, score) playerKey = Key.from_path('Player', playerId) createReviewerAndReview("test2", playerKey, {'score':3, 'time': 0}) createReviewerAndReview("test3", playerKey, {'score':999, 'time': 0}) createReviewerAndReview("test4", playerKey, {'score':3, 'time': 0}) verifiedScore = VerifiedScore.get_by_key_name("verified", parent=playerKey) playerRecord = Record.get_by_key_name('record', parent=playerKey) self.assertTrue(verifiedScore is None or verifiedScore.value == 0) self.assertEqual(playerRecord.numCheat, 1) playerKey = Key.from_path('Player', 'test3') playerRecord = Record.get_by_key_name('record', parent=playerKey) self.assertEqual(playerRecord.numCheat, 1)
def _approveScore(): scoreToApprove = db.get(scoreToApproveKey) if scoreToApprove is None: return {'cheater': None, 'nonCheaters': []} approvedPlayerKey = scoreToApprove.parent_key() cheater = None nonCheaters = [] if scoreToApprove.value == scoreValue and scoreToApprove.time == scoreTime: scoreToApprove.approvedByAdmin = True scoreToApprove.put() else: approvedPlayerRecord = Record.get_by_key_name( 'record', parent=approvedPlayerKey) approvedPlayerRecord.numCheat += 1 approvedPlayerRecord.put() cheater = Key.from_path('Player', scoreToApprove.verifier) for nonCheaterId in scoreToApprove.conflictingReviewers: nonCheaters.append(Key.from_path('Player', nonCheaterId)) scoreToApprove.delete() db.delete( Key.from_path('VerifiedScoreWrapper', 'verifiedScore', parent=approvedPlayerKey)) return {'cheater': cheater, 'nonCheaters': nonCheaters}
def test_given_aAdminReviewerTryingToReviewAsAdmin_ItShouldSucceedAndDeclareNonAgreeingConflictingReviewerAsCheaters(self): setReviewTimeUnit(0) score = {'score' : 99, 'proof' : "sdsd", 'time' : 0} playerId = "test" createPlayer(playerId, playerId) service.start(playerId) service.setScore(playerId, score) playerKey = Key.from_path('Player', playerId) createReviewerAndReview("test2", playerKey, {'score':3, 'time': 0}) createReviewerAndReview("test3", playerKey, {'score':999, 'time': 0}) createReviewerAndReview("test4", playerKey, {'score':3, 'time': 0}, True) verifiedScore = VerifiedScore.get_by_key_name("verified", parent=playerKey) playerRecord = Record.get_by_key_name('record', parent=playerKey) self.assertTrue(verifiedScore is None or verifiedScore.value == 0) self.assertEqual(playerRecord.numCheat, 1) playerKey = Key.from_path('Player', 'test3') playerRecord = Record.get_by_key_name('record', parent=playerKey) self.assertEqual(playerRecord.numCheat, 1) playerKey = Key.from_path('Player', 'test2') playerRecord = Record.get_by_key_name('record', parent=playerKey) self.assertEqual(playerRecord.numCheat, 0)
def test_key_kind(self): """ Checks that db.Keys stored in the database use proper kinds. Key kind should be the name of the table (db_table) of a model for primary keys of entities, but for foreign keys, references in general, it should be the db_table of the model the field refers to. Note that Django hides the underlying db.Key objects well, and it does work even with wrong kinds, but keeping the data consistent may be significant for external tools. TODO: Add DictField / EmbeddedModelField and nesting checks. """ parent = ParentKind.objects.create(pk=1) child = ChildKind.objects.create(pk=2, parent=parent, parents=[parent.pk]) self.assertEqual(child.parent.pk, parent.pk) self.assertEqual(child.parents[0], parent.pk) from google.appengine.api.datastore import Get from google.appengine.api.datastore_types import Key parent_key = Key.from_path(parent._meta.db_table, 1) child_key = Key.from_path(child._meta.db_table, 2) parent_entity = Get(parent_key) child_entity = Get(child_key) parent_column = child._meta.get_field('parent').column parents_column = child._meta.get_field('parents').column self.assertEqual(child_entity[parent_column], parent_key) self.assertEqual(child_entity[parents_column][0], parent_key)
def __init__( self, left, op=None, right=None, ): self.get_all = self.get_one = None if isinstance(left, list): self.filters = left return if isinstance(right, (Field, Expression)): raise SyntaxError, \ 'Query: right side of filter must be a value or entity: %s' \ % right if isinstance(left, Field): # normal filter: field op value assert_filter_fields(left) if left.type == 'id': try: if type(right) == list: #make this work for belongs right = [long(r) for r in right] else: right = long(right or 0) except ValueError: raise SyntaxError, 'id value must be integer: %s' % id if op != '=' and not (op == '>' and right == 0): #get key (or keys) based on path. Note if we later support # ancesters this will not be the proper key for items with # ancesters. #in GAE (with no ancesters) the key is base64 encoded # "table_name: id=<id>". GAE decodes the string and compares # the id if op == 'IN': right = [ Key.from_path(left._tablename, r) for r in right ] else: right = Key.from_path(left._tablename, right) elif op == 'IN': right = [dateobj_to_datetime(obj_represent(r, left.type, left._db)) \ for r in right] else: # filter dates/times need to be datetimes for GAE right = dateobj_to_datetime( obj_represent(right, left.type, left._db)) self.filters = [Filter(left, op, right)] return raise SyntaxError, 'not supported'
def test_given_aAdminReviewerDisapprovingAnAlreadyVerifiedScore_ItShouldDeclareVerifierAsACheaterAndOtherAsNonCheaters(self): setReviewTimeUnit(0) score = {'score' : 99, 'proof' : "sdsd", 'time' : 0} playerId = "test" createPlayer(playerId, playerId) service.start(playerId) service.setScore(playerId, score) playerKey = Key.from_path('Player', playerId) createReviewerAndReview("test2", playerKey, {'score':3, 'time': 0}) createReviewerAndReview("test3", playerKey, {'score':999, 'time': 0}) createReviewerAndReview("test4", playerKey, {'score':99, 'time': 0}) # verified verifiedScoreWrapper = VerifiedScoreWrapper.get_by_key_name('verifiedScore', parent=playerKey) verifiedScore = verifiedScoreWrapper.verified playerRecord = Record.get_by_key_name('record', parent=playerKey) self.assertTrue(verifiedScore.value == 99) self.assertEqual(playerRecord.numCheat, 0) createPlayer('admin1', 'admin1') admin = getAdmin() admin.playerList.append('admin1') setAdmin(admin) service.getHighestNonApprovedScore('admin1') service.approveScore('admin1', {'score':3, 'time': 0}) verifiedScoreWrapper = VerifiedScoreWrapper.get_by_key_name('verifiedScore', parent=playerKey) playerRecord = Record.get_by_key_name('record', parent=playerKey) self.assertTrue(verifiedScoreWrapper is None) self.assertEqual(playerRecord.numCheat, 1) playerKey = Key.from_path('Player', 'test3') playerRecord = Record.get_by_key_name('record', parent=playerKey) self.assertEqual(playerRecord.numCheat, 0) playerKey = Key.from_path('Player', 'test2') playerRecord = Record.get_by_key_name('record', parent=playerKey) self.assertEqual(playerRecord.numCheat, 0) playerKey = Key.from_path('Player', 'test4') playerRecord = Record.get_by_key_name('record', parent=playerKey) self.assertEqual(playerRecord.numCheat, 1)
def test_given_reviewerVerifyingScore_if_playerSetNewScoreInTheMeanTime_when_reviewerSetReviewItShouldBeDiscarded(self): score = {'score' : 3, 'proof' : "sdsd", 'time' : 0} playerId = "test" createPlayer(playerId, playerId) service.start(playerId) service.setScore(playerId, score) playerKey = Key.from_path('Player', playerId) reviewer = createPlayer("reviewer", "reviewer") assignScoreReview(reviewer, playerKey) reviewer2 = createPlayer("reviewer2", "reviewer2") scoreToReview = assignScoreReview(reviewer2, playerKey) score = {'score' : 4, 'proof' : "sdsd", 'time' : 0} service.start(playerId) service.setScore(playerId, score) service.reviewScore("reviewer", {'score':4, 'time': 0}) service.reviewScore("reviewer2", {'score':3, 'time': 0}) verifiedScore = VerifiedScore.get_by_key_name("verified", parent=playerKey) self.assertEqual(verifiedScore, None) # TDO : move to another test? scoreToReview = db.get(scoreToReview.key()) self.assertEqual(scoreToReview, None)
def test_newPlayerWithoutReviewAssigned_shouldGetNoReviews(self): playerId = "test" createPlayer(playerId, playerId) playerKey = Key.from_path('Player', playerId) reviewSession = ReviewSession.get_by_key_name('reviewSession', parent=playerKey) self.assertEqual(reviewSession, None)
def _start(): playerKey = Key.from_path('Player', playerId) rand = random.SystemRandom() seed = struct.pack("4L", rand.randint(1, MAX_INT32_VALUE), rand.randint(1, MAX_INT32_VALUE), rand.randint(1, MAX_INT32_VALUE), rand.randint(1, MAX_INT32_VALUE)) playSession = PlaySession(key_name='playSession', seed=seed, version=config.currentGameMechanicVersion, seedDateTime=datetime.datetime.now(), parent=playerKey) playSession.put() today = datetime.date.today() playerRecord = Record.get_by_key_name('record', parent=playerKey) if playerRecord.lastDayPlayed != today: playerRecord.numDaysPlayed += 1 playerRecord.lastDayPlayed = today playerRecord.put() seedList = struct.unpack("4L", playSession.seed) return {'result': {'seed': seedList, 'version': playSession.version}}
def test_given_aAdminReviewerTryingToReviewAsAdmin_ItShouldSucceed(self): setReviewTimeUnit(0) score = {'score' : 3, 'proof' : "sdsd", 'time' : 0} playerId = "test1" createPlayer(playerId, playerId) service.start(playerId) service.setScore(playerId, score) createPlayer("reviewer1", "reviewer1") admin = getAdmin() admin.playerList.append('reviewer1') setAdmin(admin) service.getRandomScore("reviewer1") response = service.reviewScore("reviewer1", {'score':3, 'time': 0}, True) self.assertTrue('result' in response) playerKey = Key.from_path('Player', playerId) verifiedScoreWrapper = VerifiedScoreWrapper.get_by_key_name('verifiedScore', parent=playerKey) verifiedScore = verifiedScoreWrapper.verified self.assertEqual(verifiedScore.value, 3) self.assertEqual(verifiedScore.approvedByAdmin, True)
def __init__( self, left, op=None, right=None, ): self.get_all = self.get_one = None if isinstance(left, list): self.filters = left return if isinstance(right, (Field, Expression)): raise SyntaxError, \ 'Query: right side of filter must be a value or entity: %s' \ % right if isinstance(left, Field): # normal filter: field op value assert_filter_fields(left) if left.type == 'id': try: if type(right) == list: #make this work for belongs right = [long(r) for r in right] else: right = long(right or 0) except ValueError: raise SyntaxError, 'id value must be integer: %s' % id if op != '=' and not (op == '>' and right == 0): #get key (or keys) based on path. Note if we later support # ancesters this will not be the proper key for items with # ancesters. #in GAE (with no ancesters) the key is base64 encoded # "table_name: id=<id>". GAE decodes the string and compares # the id if op=='IN': right = [Key.from_path(left._tablename, r) for r in right] else: right = Key.from_path(left._tablename, right) elif op=='IN': right = [dateobj_to_datetime(obj_represent(r, left.type, left._db)) \ for r in right] else: # filter dates/times need to be datetimes for GAE right = dateobj_to_datetime(obj_represent(right, left.type, left._db)) self.filters = [Filter(left, op, right)] return raise SyntaxError, 'not supported'
def setUser_MakerSecret(id, maker_secret): key = Key.from_path('UserData', id) entity = datastore.Get(key) entity.update({ 'maker_secret': maker_secret }) datastore.Put(entity) memcache.set(key="MakerSecret-" + id, value=maker_secret)
def test_db_conversion(self): actual_datetime = datetime.datetime.now() entity = FieldsWithoutOptionsModel( datetime=actual_datetime, date=actual_datetime.date(), time=actual_datetime.time(), floating_point=5.97, boolean=True, null_boolean=False, text='Hallo', email='*****@*****.**', comma_seperated_integer='5,4,3,2', ip_address='194.167.1.1', slug='you slugy s**t :)', url='http://www.scholardocs.com', long_text=1000 * 'A', indexed_text='hello', integer=-400, small_integer=-4, positive_integer=400, positive_small_integer=4) entity.save() # Get the gae entity (not the django model instance) and test # if the fields have been converted right to the corresponding # GAE database types. gae_entity = Get( Key.from_path(FieldsWithoutOptionsModel._meta.db_table, entity.pk)) opts = FieldsWithoutOptionsModel._meta for name, types in [('long_text', Text), ('indexed_text', unicode), ('text', unicode), ('ip_address', unicode), ('slug', unicode), ('email', unicode), ('comma_seperated_integer', unicode), ('url', unicode), ('time', datetime.datetime), ('datetime', datetime.datetime), ('date', datetime.datetime), ('floating_point', float), ('boolean', bool), ('null_boolean', bool), ('integer', (int, long)), ('small_integer', (int, long)), ('positive_integer', (int, long)), ('positive_small_integer', (int, long))]: column = opts.get_field_by_name(name)[0].column if not isinstance(types, (list, tuple)): types = (types, ) self.assertTrue(type(gae_entity[column]) in types) # Get the model instance and check if the fields convert back # to the right types. model = FieldsWithoutOptionsModel.objects.get() for name, types in [ ('long_text', unicode), ('indexed_text', unicode), ('text', unicode), ('ip_address', unicode), ('slug', unicode), ('email', unicode), ('comma_seperated_integer', unicode), ('url', unicode), ('datetime', datetime.datetime), ('date', datetime.date), ('time', datetime.time), ('floating_point', float), ('boolean', bool), ('null_boolean', bool), ('integer', (int, long)), ('small_integer', (int, long)), ('positive_integer', (int, long)), ('positive_small_integer', (int, long))]: if not isinstance(types, (list, tuple)): types = (types, ) self.assertTrue(type(getattr(model, name)) in types)
def key_from_path(db_table, value): """ Workaround for GAE choosing not to validate integer ids when creating keys. TODO: Should be removed if it gets fixed. """ if isinstance(value, (int, long)): ValidateInteger(value, 'id') return Key.from_path(db_table, value)
def test_given_aScoreSubmitedTooEarly_ItShouldNotBeSubmited(self): score = {'score' : 3, 'proof' : "sdsd", 'time' : 10000} playerId = "test" createPlayer(playerId, playerId) service.start(playerId) service.setScore(playerId, score) playerKey = Key.from_path('Player', playerId) pendingScore = PendingScore.get_by_key_name('pendingScore', parent=playerKey) self.assertEqual(pendingScore, None)
def getUser_MakerSecret(id): secret = memcache.get(key="MakerSecret-" + id) if secret == None: try: key = Key.from_path('UserData', id) entity = datastore.Get(key) secret = entity['maker_secret'] memcache.set(key="MakerSecret-" + id, value=secret) except: logging.debug(id + u"のIFTTT Maker Secretは登録されていません。") return secret
def deleteUserData(id): # memcache.delete(key="MakerSecret-"+id) # memcache.delete(key="USER-"+id) # dashid=memcache.get(key="User-dash-"+id) # memcache.delete(key = "User-dash-"+id) # memcache.delete(key = "Dash-user-"+str(dashid)) try: key = Key.from_path('UserData', id) entity = datastore.Delete(key) except: logging.debug(id + u"は登録されていません。")
def key_from_path(db_table, value): """ Workaround for GAE choosing not to validate integer ids when creating keys. TODO: Should be removed if it gets fixed. """ from google.appengine.api.datastore_types import Key, ValidateInteger if isinstance(value, (int, long)): ValidateInteger(value, 'id') return Key.from_path(db_table, value)
def reviewScore(playerId, score, adminMode=False): if adminMode: admin = getAdmin() try: admin.playerList.index(playerId) except ValueError: return getErrorResponse(ADMIN_ONLY) scoreValue = score['score'] scoreTime = score['time'] playerKey = Key.from_path('Player', playerId) reviewSession = ReviewSession.get_by_key_name('reviewSession', parent=playerKey) if reviewSession is None: return {'result': {'message': 'nothing to review'}} scoreToReviewKey = ReviewSession.currentScoreToReview.get_value_for_datastore( reviewSession) # We are done with it reviewSession.delete() # The above could have potentially be put in a transaction but since there is only one player concerned, it should not matter def _increaseNumScoreReviewed(): playerRecord = Record.get_by_key_name('record', parent=playerKey) playerRecord.numScoreReviewed += 1 playerRecord.put() db.run_in_transaction(_increaseNumScoreReviewed) try: cheaters = db.run_in_transaction(_checkConflicts, scoreToReviewKey, scoreValue, scoreTime, playerId, adminMode) except TransactionFailedError: return getErrorResponse(CHECKCONFLICT_TRANSACTION_FAILURE, 0) if cheaters: def _cheaterUpdate(cheaterKey): cheaterRecord = Record.get_by_key_name('record', parent=cheaterKey) cheaterRecord.numCheat += 1 cheaterRecord.put() for cheaterKey in cheaters: db.run_in_transaction(_cheaterUpdate, cheaterKey) #TODO : check TRANSACTION ERROR return {'result': {'message': 'review submited'}}
def test_getLineIdFromId(id): result = 'dummy' # return result try: key = Key.from_path('UserData', id) entity = datastore.Get(key) if entity != None: result = entity['lineId'] else: logging.debug(id + u"は登録されていません。") except: logging.debug(id + u"は登録されていません。") return result
def isExistUserData(lineId): id = lineId result = False try: key = Key.from_path('UserData', id) entity = datastore.Get(key) if entity != None: result = True else: logging.debug(id + u"は登録されていません。") except: logging.debug(id + u"は登録されていません。") return result
def _approveScore(): scoreToApprove = db.get(scoreToApproveKey) if scoreToApprove is None: return {'cheater' : None, 'nonCheaters': []} approvedPlayerKey = scoreToApprove.parent_key() cheater = None nonCheaters = [] if scoreToApprove.value == scoreValue and scoreToApprove.time == scoreTime: scoreToApprove.approvedByAdmin = True scoreToApprove.put() else: approvedPlayerRecord = Record.get_by_key_name('record', parent=approvedPlayerKey) approvedPlayerRecord.numCheat += 1 approvedPlayerRecord.put() cheater = Key.from_path('Player', scoreToApprove.verifier) for nonCheaterId in scoreToApprove.conflictingReviewers: nonCheaters.append(Key.from_path('Player', nonCheaterId)) scoreToApprove.delete() db.delete(Key.from_path('VerifiedScoreWrapper', 'verifiedScore', parent = approvedPlayerKey)) return {'cheater' : cheater, 'nonCheaters': nonCheaters}
def test_given_score_and_approvingReviewer_then_playerVerifiedScoreIsUpdated(self): score = {'score' : 3, 'proof' : "sdsd", 'time' : 0} playerId = "test" createPlayer(playerId, playerId) service.start(playerId) service.setScore(playerId, score) playerKey = Key.from_path('Player', playerId) createReviewerAndReview("test2", playerKey, {'score':3, 'time': 0}) verifiedScoreWrapper = VerifiedScoreWrapper.get_by_key_name('verifiedScore', parent=playerKey) verifiedScore = verifiedScoreWrapper.verified self.assertEqual(verifiedScore.value, score['score'])
def _getOwnHighScore(): score = None playerKey = Key.from_path('Player', playerId) bestScore = PendingScore.get_by_key_name("pendingScore", parent=playerKey) if bestScore is None: bestScore = VerifiedScoreWrapper.get_by_key_name("verifiedScore", parent=playerKey) if bestScore is not None: score = bestScore.verified else: score = bestScore.nonVerified if score is None: return {'result' : { 'score' : 0, 'time' : 0} } return {'result' : { 'score' : score.value, 'time' : score.time} }
def _getOwnHighScore(): score = None playerKey = Key.from_path('Player', playerId) bestScore = PendingScore.get_by_key_name("pendingScore", parent=playerKey) if bestScore is None: bestScore = VerifiedScoreWrapper.get_by_key_name("verifiedScore", parent=playerKey) if bestScore is not None: score = bestScore.verified else: score = bestScore.nonVerified if score is None: return {'result': {'score': 0, 'time': 0}} return {'result': {'score': score.value, 'time': score.time}}
def test_given_score_and_twoDisapprovingButAgreeingReviewers_then_playerIsCheater_and_verfiedScoreDoNotChange(self): score = {'score' : 99, 'proof' : "sdsd", 'time' : 0} playerId = "test" createPlayer(playerId, playerId) service.start(playerId) service.setScore(playerId, score) playerKey = Key.from_path('Player', playerId) createReviewerAndReview("test2", playerKey, {'score':3, 'time': 0}) createReviewerAndReview("test3", playerKey, {'score':3, 'time': 0}) verifiedScore = VerifiedScore.get_by_key_name("verified", parent=playerKey) self.assertTrue(verifiedScore is None or verifiedScore.value == 0) playerRecord = Record.get_by_key_name('record', parent=playerKey) self.assertEqual(playerRecord.numCheat, 1)
def test_given_goodScoreWithWrongTime_thenPlayerIsCheater(self): score = {'score' : 3, 'proof' : "sdsd", 'time' : 0} playerId = "test" createPlayer(playerId, playerId) service.start(playerId) service.setScore(playerId, score) playerKey = Key.from_path('Player', playerId) createReviewerAndReview("test2", playerKey, {'score':3, 'time': 3}) createReviewerAndReview("test3", playerKey, {'score':3, 'time': 3}) verifiedScore = VerifiedScore.get_by_key_name("verified", parent=playerKey) self.assertTrue(verifiedScore is None or verifiedScore.value == 0) playerRecord = Record.get_by_key_name('record', parent=playerKey) self.assertEqual(playerRecord.numCheat, 1)
def _start(): playerKey = Key.from_path('Player', playerId) rand = random.SystemRandom() seed = struct.pack("4L", rand.randint(1, MAX_INT32_VALUE), rand.randint(1, MAX_INT32_VALUE), rand.randint(1, MAX_INT32_VALUE), rand.randint(1, MAX_INT32_VALUE)) playSession = PlaySession(key_name='playSession', seed=seed, version=config.currentGameMechanicVersion, seedDateTime=datetime.datetime.now(), parent=playerKey) playSession.put() today = datetime.date.today() playerRecord = Record.get_by_key_name('record', parent=playerKey) if playerRecord.lastDayPlayed != today: playerRecord.numDaysPlayed += 1 playerRecord.lastDayPlayed = today playerRecord.put() seedList = struct.unpack("4L", playSession.seed) return {'result' : { 'seed' : seedList, 'version': playSession.version } }
def reviewScore(playerId, score, adminMode=False): if adminMode: admin = getAdmin() try: admin.playerList.index(playerId) except ValueError: return getErrorResponse(ADMIN_ONLY) scoreValue = score['score'] scoreTime = score['time'] playerKey = Key.from_path('Player', playerId) reviewSession = ReviewSession.get_by_key_name('reviewSession', parent=playerKey) if reviewSession is None: return {'result' : {'message' : 'nothing to review'} } scoreToReviewKey = ReviewSession.currentScoreToReview.get_value_for_datastore(reviewSession) # We are done with it reviewSession.delete() # The above could have potentially be put in a transaction but since there is only one player concerned, it should not matter def _increaseNumScoreReviewed(): playerRecord = Record.get_by_key_name('record', parent=playerKey) playerRecord.numScoreReviewed += 1 playerRecord.put() db.run_in_transaction(_increaseNumScoreReviewed) try: cheaters = db.run_in_transaction(_checkConflicts, scoreToReviewKey, scoreValue, scoreTime, playerId, adminMode) except TransactionFailedError: return getErrorResponse(CHECKCONFLICT_TRANSACTION_FAILURE, 0) if cheaters: def _cheaterUpdate(cheaterKey): cheaterRecord = Record.get_by_key_name('record', parent=cheaterKey) cheaterRecord.numCheat+=1 cheaterRecord.put() for cheaterKey in cheaters: db.run_in_transaction(_cheaterUpdate,cheaterKey) #TODO : check TRANSACTION ERROR return {'result' : {'message' : 'review submited'} }
def matches(self, item): result = self.connector == AND for child in self.children: if isinstance(child, ParseNode): submatch = child.matches(item) else: field, lookup_type, lookup_value = child entity_value = item[field.column] if entity_value is None: if isinstance(lookup_value, (datetime.datetime, datetime.date, datetime.time)): submatch = lookup_type in ('lt', 'lte') elif lookup_type in ( 'startswith', 'contains', 'endswith', 'iexact', 'istartswith', 'icontains', 'iendswith'): submatch = False else: submatch = EMULATED_OPS[lookup_type]( entity_value, lookup_value) elif field.primary_key and field.rel and lookup_type == 'exact': #When we have a foreignkey that's a primary key, things get weird #the query might be filtering on Key('related_model', id) but we're actually #looking up on Key('this_model', id). So here we do a kindless comparison expected = Key.from_path(field.model._meta.db_table, lookup_value.id_or_name()) submatch = expected == entity_value else: submatch = EMULATED_OPS[lookup_type]( entity_value, lookup_value) if self.connector == OR and submatch: result = True break elif self.connector == AND and not submatch: result = False break if self.negated: return not result return result
def getHighestNonApprovedScore(playerId): admin = getAdmin() try: admin.playerList.index(playerId) except ValueError: return getErrorResponse(ADMIN_ONLY) scoreToApprove = db.GqlQuery("SELECT * FROM VerifiedScore WHERE approvedByAdmin = False ORDER BY value DESC").get() if scoreToApprove is not None: playerKey = Key.from_path('Player', playerId) approveSession = ApproveSession(key_name='approveSession', currentScoreToApprove=scoreToApprove, parent=playerKey) approveSession.put() seedList = struct.unpack("4L", scoreToApprove.seed) return {'result' : { 'proof' : scoreToApprove.proof, 'seed' : seedList} } return {'result' : { 'message' : 'Nothing to approve for now'} }
def getHighestNonApprovedScore(playerId): admin = getAdmin() try: admin.playerList.index(playerId) except ValueError: return getErrorResponse(ADMIN_ONLY) scoreToApprove = db.GqlQuery( "SELECT * FROM VerifiedScore WHERE approvedByAdmin = False ORDER BY value DESC" ).get() if scoreToApprove is not None: playerKey = Key.from_path('Player', playerId) approveSession = ApproveSession(key_name='approveSession', currentScoreToApprove=scoreToApprove, parent=playerKey) approveSession.put() seedList = struct.unpack("4L", scoreToApprove.seed) return {'result': {'proof': scoreToApprove.proof, 'seed': seedList}} return {'result': {'message': 'Nothing to approve for now'}}
def test_options(self): entity = FieldsWithOptionsModel() # Try to save the entity with non-nullable field time set to # None, should raise an exception. self.assertRaises(DatabaseError, entity.save) time = datetime.datetime.now().time() entity.time = time entity.save() # Check if primary_key=True is set correctly for the saved entity. self.assertEquals(entity.pk, u'*****@*****.**') gae_entity = Get( Key.from_path(FieldsWithOptionsModel._meta.db_table, entity.pk)) self.assertTrue(gae_entity is not None) self.assertEquals(gae_entity.key().name(), u'*****@*****.**') # Check if default values are set correctly on the db level, # primary_key field is not stored at the db level. for field in FieldsWithOptionsModel._meta.local_fields: if field.default and field.default != NOT_PROVIDED and \ not field.primary_key: self.assertEquals(gae_entity[field.column], field.default) elif field.column == 'time': self.assertEquals( gae_entity[field.column], datetime.datetime(1970, 1, 1, time.hour, time.minute, time.second, time.microsecond)) elif field.null and field.editable: self.assertEquals(gae_entity[field.column], None) # Check if default values are set correct on the model instance # level. entity = FieldsWithOptionsModel.objects.get() for field in FieldsWithOptionsModel._meta.local_fields: if field.default and field.default != NOT_PROVIDED: self.assertEquals(getattr(entity, field.column), field.default) elif field.column == 'time': self.assertEquals(getattr(entity, field.column), time) elif field.null and field.editable: self.assertEquals(getattr(entity, field.column), None) # Check if nullable field with default values can be set to # None. entity.slug = None entity.positive_small_integer = None try: entity.save() except: self.fail() # Check if slug and positive_small_integer will be retrieved # with values set to None (on db level and model instance # level). gae_entity = Get(Key.from_path( FieldsWithOptionsModel._meta.db_table, entity.pk)) opts = FieldsWithOptionsModel._meta self.assertEquals( gae_entity[opts.get_field_by_name('slug')[0].column], None) self.assertEquals( gae_entity[opts.get_field_by_name( 'positive_small_integer')[0].column], None) # On the model instance level. entity = FieldsWithOptionsModel.objects.get() self.assertEquals( getattr(entity, opts.get_field_by_name('slug')[0].column), None) self.assertEquals( getattr(entity, opts.get_field_by_name( 'positive_small_integer')[0].column), None)
def setUser_MakerSecret(id, maker_secret): key = Key.from_path('UserData', id) entity = datastore.Get(key) entity.update({'maker_secret': maker_secret}) datastore.Put(entity) memcache.set(key="MakerSecret-" + id, value=maker_secret)
def approveScore(playerId, score): admin = getAdmin() try: admin.playerList.index(playerId) except ValueError: return getErrorResponse(ADMIN_ONLY) scoreValue = score['score'] scoreTime = score['time'] playerKey = Key.from_path('Player', playerId) approveSession = ApproveSession.get_by_key_name('approveSession', parent=playerKey) if approveSession is None: return getErrorResponse(NOTHING_TO_REVIEW) scoreToApproveKey = ApproveSession.currentScoreToApprove.get_value_for_datastore( approveSession) # We are done with it approveSession.delete() def _approveScore(): scoreToApprove = db.get(scoreToApproveKey) if scoreToApprove is None: return {'cheater': None, 'nonCheaters': []} approvedPlayerKey = scoreToApprove.parent_key() cheater = None nonCheaters = [] if scoreToApprove.value == scoreValue and scoreToApprove.time == scoreTime: scoreToApprove.approvedByAdmin = True scoreToApprove.put() else: approvedPlayerRecord = Record.get_by_key_name( 'record', parent=approvedPlayerKey) approvedPlayerRecord.numCheat += 1 approvedPlayerRecord.put() cheater = Key.from_path('Player', scoreToApprove.verifier) for nonCheaterId in scoreToApprove.conflictingReviewers: nonCheaters.append(Key.from_path('Player', nonCheaterId)) scoreToApprove.delete() db.delete( Key.from_path('VerifiedScoreWrapper', 'verifiedScore', parent=approvedPlayerKey)) return {'cheater': cheater, 'nonCheaters': nonCheaters} try: result = db.run_in_transaction(_approveScore) except TransactionFailedError: return getErrorResponse(APPROVESCORE_TRANSACTION_FAILURE, 0) cheater = result['cheater'] nonCheaters = result['nonCheaters'] if cheater is not None: cheaterRecord = Record.get_by_key_name('record', parent=cheater) cheaterRecord.numCheat += 1 cheaterRecord.put() if nonCheaters: def _nonCheaterUpdate(nonCheaterKey): cheaterRecord = Record.get_by_key_name('record', parent=nonCheaterKey) cheaterRecord.numCheat -= 1 cheaterRecord.put() for nonCheaterKey in nonCheaters: db.run_in_transaction(_nonCheaterUpdate, nonCheaterKey) return {'result': {'message': 'approvement submited'}}
def add_filter(self, field, lookup_type, negated, value): """ This function is used by the default add_filters() implementation. """ if lookup_type == 'ancestor': self.ancestor_key = Key.from_path(value._meta.db_table, value.pk) return if lookup_type not in OPERATORS_MAP: raise DatabaseError("Lookup type %r isn't supported." % lookup_type) # GAE does not let you store empty lists, so we can tell # upfront that queriying for one will return nothing. if value in ([], ()): self.included_pks = [] return # Optimization: batch-get by key; this is only suitable for # primary keys, not for anything that uses the key type. if field.primary_key and lookup_type in ('exact', 'in'): if self.included_pks is not None: raise DatabaseError("You can't apply multiple AND " "filters on the primary key. " "Did you mean __in=[...]?") if not isinstance(value, (tuple, list)): value = [value] pks = [pk for pk in value if pk is not None] if negated: self.excluded_pks = pks else: self.included_pks = pks return # We check for negation after lookup_type isnull because it # simplifies the code. All following lookup_type checks assume # that they're not negated. if lookup_type == 'isnull': if (negated and value) or not value: # TODO/XXX: Is everything greater than None? op = '>' else: op = '=' value = None elif negated and lookup_type == 'exact': if self.has_negated_exact_filter: raise DatabaseError("You can't exclude more than one __exact " "filter.") self.has_negated_exact_filter = True self._combine_filters(field, (('<', value), ('>', value))) return elif negated: try: op = NEGATION_MAP[lookup_type] except KeyError: raise DatabaseError("Lookup type %r can't be negated." % lookup_type) if self.inequality_field and field != self.inequality_field: raise DatabaseError("Can't have inequality filters on " "multiple fields (here: %r and %r)." % (field, self.inequality_field)) self.inequality_field = field elif lookup_type == 'in': # Create sub-query combinations, one for each value. if len(self.gae_query) * len(value) > 30: raise DatabaseError("You can't query against more than " "30 __in filter value combinations.") op_values = [('=', v) for v in value] self._combine_filters(field, op_values) return elif lookup_type == 'startswith': # Lookup argument was converted to [arg, arg + u'\ufffd']. self._add_filter(field, '>=', value[0]) self._add_filter(field, '<=', value[1]) return elif lookup_type in ('range', 'year'): self._add_filter(field, '>=', value[0]) op = '<=' if lookup_type == 'range' else '<' self._add_filter(field, op, value[1]) return else: op = OPERATORS_MAP[lookup_type] self._add_filter(field, op, value)
def setScore(playerId, score): scoreValue = score['score'] scoreTime = score['time'] proof = score['proof'] playerKey = Key.from_path('Player', playerId) playSession = PlaySession.get_by_key_name('playSession', parent=playerKey) if playSession is None: return getErrorResponse(NO_PLAYER_SESSION) seed = playSession.seed version = playSession.version seedDateTime = playSession.seedDateTime now = datetime.datetime.now() # TODO : investigate: should we consider the player as cheater for this two exception ? if seedDateTime + datetime.timedelta(milliseconds=scoreTime) > now: return getErrorResponse(NOT_ENOUGH_TIME) maxScoreTime = scoreTime + MINIMUM_TIME if seedDateTime + datetime.timedelta(milliseconds=maxScoreTime) < now: return getErrorResponse(TOO_MUCH_TIME) def _setScore(): playSession.delete() verifiedScore = None verifiedScoreWrapper = VerifiedScoreWrapper.get_by_key_name("verifiedScore", parent=playerKey) if verifiedScoreWrapper is not None: verifiedScore = verifiedScoreWrapper.verified if verifiedScore is None or scoreValue > verifiedScore.value or (scoreValue == verifiedScore.value and scoreTime < verifiedScore.time): pendingScore = PendingScore.get_by_key_name("pendingScore", parent=playerKey) if pendingScore is not None: nonVerifiedScore = pendingScore.nonVerified else: nonVerifiedScore = None if nonVerifiedScore is None or scoreValue > nonVerifiedScore.value or (scoreValue == nonVerifiedScore.value and scoreTime < nonVerifiedScore.time): try: proofBlob = db.Blob(proof) except Exception: proofText = str(proof) proofBlob = db.Blob(proofText) nonVerifiedScore = NonVerifiedScore(value=scoreValue,time=scoreTime,proof=proofBlob,seed=seed,version=version, parent=playerKey) nonVerifiedScore.put() if pendingScore is None: pendingScore = PendingScore(key_name='pendingScore', parent=playerKey, nonVerified=nonVerifiedScore) else: conflicts = ReviewConflict.gql("WHERE ANCESTOR IS :score", score=pendingScore.nonVerified.key()).fetch(100) # shoud not be more than 2 for conflict in conflicts: conflict.delete() pendingScore.nonVerified.delete() pendingScore.nonVerified = nonVerifiedScore pendingScore.put() return {'result' : {'message' : 'success'} } else: pass # TODO : are you trying to cheat? else: pass # TODO : are you trying to cheat? return getErrorResponse(SCORE_TOO_SMALL) try: return db.run_in_transaction(_setScore) except TransactionFailedError: return getErrorResponse(SETSCORE_TRANSACTION_FAILURE, 0)
def setScore(playerId, score): scoreValue = score['score'] scoreTime = score['time'] proof = score['proof'] playerKey = Key.from_path('Player', playerId) playSession = PlaySession.get_by_key_name('playSession', parent=playerKey) if playSession is None: return getErrorResponse(NO_PLAYER_SESSION) seed = playSession.seed version = playSession.version seedDateTime = playSession.seedDateTime now = datetime.datetime.now() # TODO : investigate: should we consider the player as cheater for this two exception ? if seedDateTime + datetime.timedelta(milliseconds=scoreTime) > now: return getErrorResponse(NOT_ENOUGH_TIME) maxScoreTime = scoreTime + MINIMUM_TIME if seedDateTime + datetime.timedelta(milliseconds=maxScoreTime) < now: return getErrorResponse(TOO_MUCH_TIME) def _setScore(): playSession.delete() verifiedScore = None verifiedScoreWrapper = VerifiedScoreWrapper.get_by_key_name( "verifiedScore", parent=playerKey) if verifiedScoreWrapper is not None: verifiedScore = verifiedScoreWrapper.verified if verifiedScore is None or scoreValue > verifiedScore.value or ( scoreValue == verifiedScore.value and scoreTime < verifiedScore.time): pendingScore = PendingScore.get_by_key_name("pendingScore", parent=playerKey) if pendingScore is not None: nonVerifiedScore = pendingScore.nonVerified else: nonVerifiedScore = None if nonVerifiedScore is None or scoreValue > nonVerifiedScore.value or ( scoreValue == nonVerifiedScore.value and scoreTime < nonVerifiedScore.time): try: proofBlob = db.Blob(proof) except Exception: proofText = str(proof) proofBlob = db.Blob(proofText) nonVerifiedScore = NonVerifiedScore(value=scoreValue, time=scoreTime, proof=proofBlob, seed=seed, version=version, parent=playerKey) nonVerifiedScore.put() if pendingScore is None: pendingScore = PendingScore(key_name='pendingScore', parent=playerKey, nonVerified=nonVerifiedScore) else: conflicts = ReviewConflict.gql( "WHERE ANCESTOR IS :score", score=pendingScore.nonVerified.key()).fetch( 100) # shoud not be more than 2 for conflict in conflicts: conflict.delete() pendingScore.nonVerified.delete() pendingScore.nonVerified = nonVerifiedScore pendingScore.put() return {'result': {'message': 'success'}} else: pass # TODO : are you trying to cheat? else: pass # TODO : are you trying to cheat? return getErrorResponse(SCORE_TOO_SMALL) try: return db.run_in_transaction(_setScore) except TransactionFailedError: return getErrorResponse(SETSCORE_TRANSACTION_FAILURE, 0)
def add_filter(self, field, lookup_type, negated, value): """ This function is used by the default add_filters() implementation. """ if lookup_type == 'ancestor': self.ancestor_key = Key.from_path(value._meta.db_table, value.pk) return if lookup_type not in OPERATORS_MAP: raise DatabaseError("Lookup type %r isn't supported." % lookup_type) # GAE does not let you store empty lists, so we can tell # upfront that queriying for one will return nothing. if value in ([], ()) and not negated: self.included_pks = [] return # Optimization: batch-get by key; this is only suitable for # primary keys, not for anything that uses the key type. if field.primary_key and lookup_type in ('exact', 'in'): if self.included_pks is not None: raise DatabaseError("You can't apply multiple AND " "filters on the primary key. " "Did you mean __in=[...]?") if not isinstance(value, (tuple, list)): value = [value] pks = [pk for pk in value if pk is not None] if field.rel: pks = [ Key.from_path(self.db_table, pk.id_or_name()) for pk in pks ] if negated: self.excluded_pks = pks else: self.included_pks = pks return # We check for negation after lookup_type isnull because it # simplifies the code. All following lookup_type checks assume # that they're not negated. if lookup_type == 'isnull': if (negated and value) or not value: # TODO/XXX: Is everything greater than None? op = '>' else: op = '=' value = None elif negated and lookup_type == 'exact': if self.has_negated_exact_filter: raise DatabaseError("You can't exclude more than one __exact " "filter.") self.has_negated_exact_filter = True self._combine_filters(field, (('<', value), ('>', value))) return elif negated: try: op = NEGATION_MAP[lookup_type] except KeyError: raise DatabaseError("Lookup type %r can't be negated." % lookup_type) if self.inequality_field and field != self.inequality_field: raise DatabaseError("Can't have inequality filters on " "multiple fields (here: %r and %r)." % (field, self.inequality_field)) self.inequality_field = field elif lookup_type == 'in': # Create sub-query combinations, one for each value. if len(self.gae_query) * len(value) > 30: raise DatabaseError("You can't query against more than " "30 __in filter value combinations.") op_values = [('=', v) for v in value] self._combine_filters(field, op_values) return elif lookup_type == 'startswith': # Lookup argument was converted to [arg, arg + u'\ufffd']. self._add_filter(field, '>=', value[0]) self._add_filter(field, '<=', value[1]) return elif lookup_type in ('range', 'year'): self._add_filter(field, '>=', value[0]) op = '<=' if lookup_type == 'range' else '<' self._add_filter(field, op, value[1]) return else: op = OPERATORS_MAP[lookup_type] self._add_filter(field, op, value)