def get(self): url_match = request.args.get("url_match", "/resources/%") cur = db.cursor() result = cur.execute( fetch_query_string( "select_rendered_puzzle_files_with_url_like.sql"), { "url_match": url_match }, ).fetchall() if not result: puzzle_files = [] else: (result, col_names) = rowify(result, cur.description) puzzle_files = result response = { "puzzle_files": puzzle_files, } cur.close() return make_response(json.jsonify(response), 200)
def migrate_s3_puzzle(puzzle): """ Download the file from S3 and update the url in the puzzle file. """ if not exists: logging.info("Bucket doesn't exist") return cur = db.cursor() puzzle_id = puzzle.get('puzzle_id') puzzle_dir = create_puzzle_dir(puzzle_id) url_components = urlparse(puzzle.get('url')) key = url_components.path[1:] file_name = os.path.basename(key) file_path = os.path.join(puzzle_dir, file_name) local_url = "/resources/{puzzle_id}/{file_name}".format( puzzle_id=puzzle_id, file_name=file_name) logging.info("Downloading {}".format( os.path.join(puzzle_dir, os.path.basename(key)))) s3.download_file(BUCKET_NAME, key, file_path) cur.execute( query_update_puzzle_file_url, { 'puzzle': puzzle.get('puzzle'), 'name': puzzle.get('name'), 'url': local_url }) db.commit() cur.close() logging.info( "{puzzle} migrating s3 puzzle file {name} ({puzzle_id}): {url}".format( **puzzle))
def get_offset_of_adjacent_pieces(piece, mask_width, piece_width): cur = db.cursor() offsets = {} x = piece['x'] y = piece['y'] t = mask_width - piece_width sides = [ {'side':{ (360, 0):'top_path', }, 'other_side':{ (360, 0):'bottom_path', }, 'x':x, 'y':((y+t) - mask_width)}, {'side':{ (360, 0):'right_path', }, 'other_side':{ (360, 0):'left_path', }, 'x':((x-t) + mask_width), 'y':y}, {'side':{ (360, 0):'bottom_path', }, 'other_side':{ (360, 0):'top_path', }, 'x':x, 'y':((y-t) + mask_width)}, {'side':{ (360, 0):'left_path', }, 'other_side':{ (360, 0):'right_path', }, 'x':((x+t) - mask_width), 'y':(y)}, ] piece_alignment = (360, 0) query = """select * from Piece where (id != :id) and (puzzle = :puzzle) and ((top_path = :bottom_path) or (bottom_path = :top_path) or (right_path = :left_path) or (left_path = :right_path))""" (d, col_names) = rowify(cur.execute(query, piece).fetchall(), cur.description) for adjacent_piece in d: for s in sides: try: if adjacent_piece[s['other_side'][piece_alignment]] == piece[s['side'][piece_alignment]]: # always check if the sides match offset = { 'x': int(math.ceil(piece_width)*FITS_MAPPING[s['side'][piece_alignment]]['x']), 'y': int(math.ceil(piece_width)*FITS_MAPPING[s['side'][piece_alignment]]['y']) } offsets[adjacent_piece['id']] = '{x},{y}'.format(**offset) break except KeyError: continue cur.close() return offsets
def post(self): args = {} xhr_data = request.get_json() if xhr_data: args.update(xhr_data) args.update(request.form.to_dict(flat=True)) args.update(request.args.to_dict(flat=True)) if len(args.keys()) == 0: abort(400) # Start db operations cur = db.cursor() llamas = 0 result = cur.execute(fetch_query_string("get-llama-count.sql")).fetchall() if result: (result, col_names) = rowify(result, cur.description) llamas = result[0]["llamas"] # TODO: Process args for llamaness processed = {"llama-check": True, "count": llamas} db.commit() cur.close() return json.jsonify(processed)
def post(self): args = {} if request.form: args.update(request.form.to_dict(flat=True)) # Verify args action = args.get("action") if action not in SLOT_ACTIONS: abort(400) player = args.get("player") if not player: abort(400) cur = db.cursor() if action == "add": cur.execute(fetch_query_string("add-new-user-puzzle-slot.sql"), {"player": player}) elif action == "delete": cur.execute(fetch_query_string("delete-user-puzzle-slot.sql"), {"player": player}) cur.close() db.commit() return redirect( "/chill/site/admin/player/details/{player}/".format(player=player))
def update_user_points_and_m_date(player, points, score): cur = db.cursor() try: result = cur.execute( fetch_query_string("update_user_points_and_m_date.sql"), { "id": player, "points": points, "score": score, "POINTS_CAP": current_app.config["POINTS_CAP"], }, ) except sqlite3.IntegrityError: err_msg = { "msg": "Database integrity error. Does the player ({}) exist?".format( player), "status_code": 400, } cur.close() return err_msg cur.close() db.commit() msg = {"rowcount": result.rowcount, "msg": "Executed", "status_code": 200} return msg
def migrate_next_puzzle(puzzle): cur = db.cursor() logging.info("migrating puzzle {}".format(puzzle)) # Update any original that have an empty url cur.execute(query_update_puzzle_file_original_null_url, {'puzzle': puzzle}) # Update any original that have a '0' for url cur.execute(query_update_puzzle_file_original_s3_url, {'puzzle': puzzle}) db.commit() result = cur.execute(query_select_puzzle_file_to_migrate_from_s3, { 'puzzle': puzzle }).fetchall() if result: (result, col_names) = rowify(result, cur.description) for item in result: migrate_s3_puzzle(item) result = cur.execute(query_select_puzzle_file_to_migrate_from_unsplash, { 'puzzle': puzzle, }).fetchall() if result: (result, col_names) = rowify(result, cur.description) for item in result: migrate_unsplash_puzzle(item) cur.close()
def do_task(self): super().do_task() cur = db.cursor() result = cur.execute( read_query_file( "select-user-name-waiting-to-be-approved.sql")).fetchall() if result: self.log_task() names = [] (result, col_names) = rowify(result, cur.description) for item in result: names.append("{approved_date} - {display_name}".format(**item)) message = "\n".join(names) # Send a notification email (silent fail if not configured) current_app.logger.debug(message) if not current_app.config.get("DEBUG", True): try: send_message( current_app.config.get("EMAIL_MODERATOR"), "Puzzle Massive - new names", message, current_app.config, ) except Exception as err: current_app.logger.warning( "Failed to send notification message. {}".format(err)) pass cur.close()
def get(self, puzzle_id): "" ip = request.headers.get("X-Real-IP") user = int( current_app.secure_cookie.get(u"user") or user_id_from_ip(ip)) cur = db.cursor() result = cur.execute( fetch_query_string("select_viewable_puzzle_id.sql"), { "puzzle_id": puzzle_id }, ).fetchall() if not result: # 404 if puzzle does not exist abort(404) (result, col_names) = rowify(result, cur.description) puzzle = result[0].get("puzzle") status = result[0].get("status") now = int(time.time()) count = (redis_connection.zcount( "timeline:{puzzle}".format(puzzle=puzzle), now - 5 * 60, "+inf") or 0) player_active_count = {"now": now, "count": count} cur.close() return json.jsonify(player_active_count)
def post(self, puzzle_id): "Ping and record the time in milliseconds for this player." now_ms = int(time.time() * 1000) response = {"message": "", "name": ""} user = current_app.secure_cookie.get(u"user") or user_id_from_ip( request.headers.get("X-Real-IP"), skip_generate=True) if user == None: response["message"] = "Player not currently logged in." response["name"] = "error" return make_response(json.jsonify(response), 400) user = int(user) cur = db.cursor() # Validate the puzzle_id result = cur.execute( fetch_query_string("select_viewable_puzzle_id.sql"), { "puzzle_id": puzzle_id }, ).fetchall() if not result: response["message"] = "Invalid puzzle id." response["name"] = "error" cur.close() db.commit() return make_response(json.jsonify(response), 400) else: (result, col_names) = rowify(result, cur.description) puzzle = result[0].get("puzzle") status = result[0].get("status") if status != ACTIVE: response["message"] = "Puzzle not active" response["name"] = "invalid" cur.close() db.commit() return make_response(json.jsonify(response), 200) # publish to the puzzle channel the ping with the user id. This will # allow that player to determine their latency. token = uuid.uuid4().hex[:4] pingtoken_key = get_pingtoken_key(puzzle, user, token) redis_connection.setex(pingtoken_key, 60, now_ms) current_app.logger.debug( "publish ping {puzzle_id}".format(puzzle_id=puzzle_id)) sse.publish( "{user}:{token}".format(user=user, token=token), type="ping", channel="puzzle:{puzzle_id}".format(puzzle_id=puzzle_id), ) response["message"] = "ping accepted" response["name"] = "accepted" response = make_response(json.jsonify(response), 202) cur.close() db.commit() return response
def get(self): cur = db.cursor() response = make_response(redirect("/chill/site/admin/puzzle/")) # Delete the shareduser cookie if it exists expires = datetime.datetime.utcnow() - datetime.timedelta(days=365) current_app.secure_cookie.set("shareduser", "", response, expires=expires) current_app.secure_cookie.set("user", str(ADMIN_USER_ID), response, expires_days=365) cur.execute( fetch_query_string("extend-cookie_expires-for-user.sql"), {"id": ADMIN_USER_ID}, ) db.commit() cur.close() return response
def test_next_migrate_script(self): "Get next migrate script to run" with self.app.app_context(): with self.app.test_client(): cur = db.cursor() cur.execute(read_query_file("create_table_puzzle_massive.sql")) cur.execute( read_query_file("upsert_puzzle_massive.sql"), { "key": "database_version", "label": "Database Version", "description": "something", "intvalue": 1, "textvalue": None, "blobvalue": None }) db.commit() script_files = [ "some/path/to/migrate_puzzle_massive_database_version_021.py", "some/path/to/migrate_puzzle_massive_database_version_901.py", "some/path/to/migrate_puzzle_massive_database_version_001.py", "some/path/to/migrate_puzzle_massive_database_version_000.py", "some/path/to/migrate_puzzle_massive_database_version_002.py", ] migrate_script = get_next_migrate_script(script_files) # The initial one should be migrate_puzzle_massive_database_version_000.py assert migrate_script == "some/path/to/migrate_puzzle_massive_database_version_002.py"
def test_next_migrate_script_when_a_gap_exists(self): "Get next migrate script to run when a gap in version numbers exist" with self.app.app_context(): with self.app.test_client(): cur = db.cursor() cur.execute(read_query_file("create_table_puzzle_massive.sql")) cur.execute( read_query_file("upsert_puzzle_massive.sql"), { "key": "database_version", "label": "Database Version", "description": "something", "intvalue": 21, "textvalue": None, "blobvalue": None }) db.commit() script_files = [ "some/path/to/migrate_puzzle_massive_database_version_021.py", "some/path/to/migrate_puzzle_massive_database_version_901.py", "some/path/to/migrate_puzzle_massive_database_version_001.py", "some/path/to/migrate_puzzle_massive_database_version_000.py", "some/path/to/migrate_puzzle_massive_database_version_002.py", ] self.assertRaises(MigrateGapError, get_next_migrate_script, script_files)
def get(self, puzzle_id): "" cur = db.cursor() result = cur.execute( fetch_query_string("select_viewable_puzzle_id.sql"), { "puzzle_id": puzzle_id }, ).fetchall() if not result: # 404 if puzzle does not exist abort(404) (result, col_names) = rowify(result, cur.description) puzzle = result[0].get("puzzle") status = result[0].get("status") now = int(time.time()) count = (redis_connection.zcount( "timeline:{puzzle}".format(puzzle=puzzle), now - 5 * 60, "+inf") or 0) player_active_count = {"now": now, "count": count} cur.close() return make_response(json.jsonify(player_active_count), 200)
def __init__(self, ip): self.ip = ip self.headers = {"X-Real-IP": ip} self.api_host = "http://localhost:{PORTAPI}".format( PORTAPI=current_app.config["PORTAPI"]) self.publish_host = "http://localhost:{PORTPUBLISH}".format( PORTPUBLISH=current_app.config["PORTPUBLISH"]) cur = db.cursor() result = cur.execute( read_query_file("select-user-id-by-ip-and-no-password.sql"), { "ip": ip }).fetchall() if result: (result, col_names) = rowify(result, cur.description) shareduser = result[0]["id"] redis_connection.zrem("bannedusers", shareduser) cur.close() # get test user current_user_id = requests.get("{0}/current-user-id/".format( self.api_host), headers=self.headers) # print('ip {} and {}'.format(ip, current_user_id.cookies)) self.shareduser_cookie = current_user_id.cookies["shareduser"] self.shareduser = int(current_user_id.content)
def delete_puzzle_timeline(puzzle_id): "" cur = db.cursor() result = cur.execute( fetch_query_string("select-internal-puzzle-details-for-puzzle_id.sql"), { "puzzle_id": puzzle_id }, ).fetchall() if not result: err_msg = {"msg": "No puzzle found", "status_code": 400} cur.close() return err_msg (result, col_names) = rowify(result, cur.description) puzzle_data = result[0] puzzle = puzzle_data["id"] result = cur.execute(fetch_query_string("delete_puzzle_timeline.sql"), {"puzzle": puzzle}) cur.close() db.commit() redis_connection.delete("timeline:{puzzle}".format(puzzle=puzzle)) redis_connection.delete("score:{puzzle}".format(puzzle=puzzle)) msg = {"rowcount": result.rowcount, "msg": "Deleted", "status_code": 200} return msg
def reward_player_for_score_threshold(player): cur = db.cursor() try: result = cur.execute( fetch_query_string( "reward_player_for_score_threshold--puzzle-instance-slot.sql"), { "player": player, "score_threshold": int( current_app.config.get( "REWARD_INSTANCE_SLOT_SCORE_THRESHOLD", '0')) }, ) except sqlite3.IntegrityError: err_msg = { "msg": "Database integrity error. Does the player ({}) exist?".format( player), "status_code": 400, } cur.close() return err_msg cur.close() db.commit() msg = {"rowcount": result.rowcount, "msg": "Executed", "status_code": 200} return msg
def set_lost_unsplash_photo(puzzle): """ remove the link the unsplash license is irrevocable: https://unsplash.com/license create a new preview photo from the original? """ logging.info( "{puzzle} unsplash puzzle file {name} not found: {url}".format( **puzzle)) cur = db.cursor() description = "{} / originally found on Unsplash".format( puzzle['description']) cur.execute( """update Puzzle set link = :link, description = :description, permission = -1 -- NOT PUBLIC where puzzle_id = :puzzle_id; """, { 'puzzle_id': puzzle['puzzle_id'], 'link': None, 'description': description }) insert_file = "update PuzzleFile set url = :url where puzzle = :puzzle and name = :name;" cur.execute(insert_file, { 'puzzle': puzzle['puzzle'], 'name': 'preview_full', 'url': '' }) db.commit() cur.close()
def test_connection(self): "Connection to db" with self.app.app_context(): with self.app.test_client(): cursor = db.cursor() result = cursor.execute("select 'test' as test") (result, col_names) = rowify(result, cursor.description) assert result[0]["test"] == "test"
def get(self, puzzle_id): """ deletePenalty: number; canFreeze: boolean; canDelete: boolean; canReset: boolean; hasActions: boolean; deleteDisabledMessage: string; //Not enough dots to delete this puzzle isFrozen: boolean; status: number; """ ip = request.headers.get("X-Real-IP") user = int(current_app.secure_cookie.get("user") or user_id_from_ip(ip)) cur = db.cursor() # validate the puzzle_id result = cur.execute( fetch_query_string("select-puzzle-details-for-puzzle_id.sql"), {"puzzle_id": puzzle_id}, ).fetchall() if not result: # 400 if puzzle does not exist err_msg = { "msg": "No puzzle found", } cur.close() return make_response(json.jsonify(err_msg), 400) (result, col_names) = rowify(result, cur.description) puzzleData = result[0] (delete_penalty, can_delete, delete_disabled_message) = self.get_delete_prereq( puzzleData ) response = { "canDelete": can_delete, "canFreeze": puzzleData.get("status") in (FROZEN, BUGGY_UNLISTED, ACTIVE), "canReset": puzzleData.get("permission") == PRIVATE and not puzzleData.get("is_original") and puzzleData.get("status") in (FROZEN, BUGGY_UNLISTED, ACTIVE, COMPLETED), "hasActions": puzzleData.get("status") in ( FROZEN, ACTIVE, COMPLETED, BUGGY_UNLISTED, RENDERING_FAILED, REBUILD, IN_RENDER_QUEUE, MAINTENANCE, ), "deleteDisabledMessage": delete_disabled_message, "deletePenalty": delete_penalty, "isFrozen": puzzleData.get("status") == FROZEN, "status": puzzleData.get("status", -99), } cur.close() return make_response(json.jsonify(response), 200)
def user_id_from_ip(ip, skip_generate=True): cur = db.cursor() shareduser = current_app.secure_cookie.get(u"shareduser") if shareduser != None: # Check if this shareduser is still valid and another user hasn't chosen # a bit icon. result = cur.execute( fetch_query_string("select-user-by-id-and-no-password.sql"), { "id": shareduser }, ).fetchall() if result: cur.close() return int(shareduser) # Handle players that had a cookie in their browser, but then deleted it. # Or new players that are from the same ip that existing players are on. # These players are shown the new-player page. result = cur.execute( fetch_query_string("select-user-id-by-ip-and-no-password.sql"), { "ip": ip }).fetchall() user_id = ANONYMOUS_USER_ID # No ip in db so create it except if the skip_generate flag is set if not result: if skip_generate: cur.close() return None login = generate_user_login() cur.execute( fetch_query_string("add-new-user-for-ip.sql"), { "ip": ip, "login": login, "points": current_app.config["NEW_USER_STARTING_POINTS"], }, ) db.commit() result = cur.execute( fetch_query_string("select-user-id-by-ip-and-login.sql"), { "ip": ip, "login": login }, ).fetchall() (result, col_names) = rowify(result, cur.description) user_id = result[0]["id"] else: (result, col_names) = rowify(result, cur.description) user_id = result[0]["id"] cur.close() return user_id
def delete_puzzle_file(puzzle_id, file_name): "" cur = db.cursor() result = cur.execute( fetch_query_string("select-internal-puzzle-details-for-puzzle_id.sql"), { "puzzle_id": puzzle_id }, ).fetchall() if not result: err_msg = {"msg": "No puzzle found", "status_code": 400} cur.close() return err_msg (result, col_names) = rowify(result, cur.description) puzzle_data = result[0] puzzle = puzzle_data["id"] result = cur.execute( fetch_query_string("select_puzzle_file_with_attribution.sql"), { "puzzle": puzzle, "name": file_name }, ).fetchall() if result: (result, col_names) = rowify(result, cur.description) puzzle_file_with_attribution_data = result[0] # Delete previous attribution if it exists if puzzle_file_with_attribution_data["attribution_id"]: result = cur.execute( fetch_query_string("delete_attribution_from_puzzle_file.sql"), {"id": puzzle_file_with_attribution_data["puzzle_file_id"]}, ) result = cur.execute( fetch_query_string("delete_attribution.sql"), { "attribution": puzzle_file_with_attribution_data["attribution_id"] }, ) result = cur.execute( fetch_query_string("delete_puzzle_file_with_name_for_puzzle.sql"), { "puzzle": puzzle, "name": file_name }, ) db.commit() cur.close() msg = {"rowcount": result.rowcount, "msg": "Deleted", "status_code": 200} return msg
def add_to_timeline(puzzle_id, player, points=0, timestamp=None, message=""): "" if timestamp is None: _timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()) else: # TODO: Should verify timestamp is in ISO format. _timestamp = timestamp if not isinstance(points, int): err_msg = {"msg": "points needs to be an integer", "status_code": 400} return err_msg cur = db.cursor() result = cur.execute( fetch_query_string("select-internal-puzzle-details-for-puzzle_id.sql"), { "puzzle_id": puzzle_id }, ).fetchall() if not result: err_msg = {"msg": "No puzzle found", "status_code": 400} cur.close() return err_msg (result, col_names) = rowify(result, cur.description) puzzle_data = result[0] puzzle = puzzle_data["id"] # TODO: The message is not added to the Timeline DB table for now since that # information is not currently being used. try: result = cur.execute( fetch_query_string("insert_batchpoints_to_timeline.sql"), { "puzzle": puzzle, "player": player, "points": points, "timestamp": _timestamp, }, ) except sqlite3.IntegrityError: err_msg = { "msg": "Database integrity error. Does the player ({}) exist?".format( player), "status_code": 400, } cur.close() return err_msg cur.close() db.commit() msg = {"rowcount": result.rowcount, "msg": "Inserted", "status_code": 200} return msg
def get(self): "" ip = request.headers.get("X-Real-IP") user = current_app.secure_cookie.get(u"user") or user_id_from_ip(ip) if user != None: user = int(user) args = {} if request.args: args.update(request.args.to_dict(flat=True)) count = args.get("count") if count == None: return make_response( encoder.encode({"msg": "missing count param"}), 400) count = int(count) if count > 45: return make_response( encoder.encode({"msg": "Count arg is too high"}), 400) cur = db.cursor() now = int(time.time()) active_players = frozenset( map( int, redis_connection.zrevrangebyscore("timeline", "+inf", now - ACTIVE_RANGE), )) rank_slice = redis_connection.zrevrange("rank", 0, -1, withscores=True) ranks = [] has_user_in_ranks = False user_in_ranks_index = -1 for index, item in enumerate(rank_slice): (player, score) = map(int, item) if not has_user_in_ranks and player == user: has_user_in_ranks = True user_in_ranks_index = len(ranks) if player in active_players or player == user: ranks.append({ "id": player, "score": score, }) ranks_near_user = [] if has_user_in_ranks: start = max(0, user_in_ranks_index - int(count / 2)) end = min(len(ranks), user_in_ranks_index + int(count / 2)) ranks_near_user = ranks[start:end] player_ranks = { "rank_slice": ranks_near_user, } cur.close() return encoder.encode(player_ranks)
def post(self): """Update shareduser to user""" # Prevent creating a new user if no support for cookies. Player should # have 'ot' already set by viewing the page. uses_cookies = current_app.secure_cookie.get(u"ot") if not uses_cookies: abort(400) cur = db.cursor() response = make_response("", 200) user = user_id_from_ip(request.headers.get("X-Real-IP")) if user == None: abort(400) user = int(user) # Only set new user if enough dots result = cur.execute( fetch_query_string("select-minimum-points-for-user.sql"), { "user": user, "points": current_app.config["NEW_USER_STARTING_POINTS"] + current_app.config["POINT_COST_FOR_CHANGING_BIT"], }, ).fetchone() if result: self.register_new_user(user) # Save as a cookie current_app.secure_cookie.set(u"user", str(user), response, expires_days=365) # Remove shareduser expires = datetime.datetime.utcnow() - datetime.timedelta(days=365) current_app.secure_cookie.set(u"shareduser", "", response, expires=expires) cur.execute( fetch_query_string("decrease-user-points.sql"), { "user": user, "points": current_app.config["POINT_COST_FOR_CHANGING_BIT"], }, ) cur.close() db.commit() return response
def reset_puzzle_pieces_and_handle_errors(puzzle): cur = db.cursor() result = cur.execute( fetch_query_string("select_all_from_puzzle_for_id.sql"), { "id": puzzle }, ).fetchall() if not result: cur.close() raise DataError("No puzzle found with that id.") (result, col_names) = rowify(result, cur.description) puzzle_data = result[0] cur.close() try: reset_puzzle_pieces(puzzle) # TODO: Fix handling of errors on puzzle reset pieces except Error as err: # Update puzzle status to RENDERING_FAILED r = requests.patch( "http://{HOSTAPI}:{PORTAPI}/internal/puzzle/{puzzle_id}/details/". format( HOSTAPI=current_app.config["HOSTAPI"], PORTAPI=current_app.config["PORTAPI"], puzzle_id=puzzle_data["puzzle_id"], ), json={"status": RENDERING_FAILED}, ) sse.publish( "status:{}".format(RENDERING_FAILED), channel="puzzle:{puzzle_id}".format( puzzle_id=puzzle_data["puzzle_id"]), ) if r.status_code != 200: raise Exception("Puzzle details api error") # Update puzzle status to ACTIVE and sse publish r = requests.patch( "http://{HOSTAPI}:{PORTAPI}/internal/puzzle/{puzzle_id}/details/". format( HOSTAPI=current_app.config["HOSTAPI"], PORTAPI=current_app.config["PORTAPI"], puzzle_id=puzzle_data["puzzle_id"], ), json={"status": ACTIVE}, ) sse.publish( "status:{}".format(ACTIVE), channel="puzzle:{puzzle_id}".format( puzzle_id=puzzle_data["puzzle_id"]), ) if r.status_code != 200: raise Exception("Puzzle details api error")
def migrate(config): "Migrate the sqlite3 database from the current database_version." cur = db.cursor() for filename in [ "create_user_puzzle_index.sql", ]: cur.execute(read_query_file(filename)) db.commit() cur.close()
def test_next_migrate_script_when_none_are_found(self): "Get next migrate script when none are found" with self.app.app_context(): with self.app.test_client(): cur = db.cursor() cur.execute(read_query_file("create_table_puzzle_massive.sql")) db.commit() script_files = [] self.assertRaises(MigrateError, get_next_migrate_script, script_files)
def test_get_latest_version_when_no_migrate_scripts(self): "Get latest version when no migrate scripts" with self.app.app_context(): with self.app.test_client(): cur = db.cursor() cur.execute(read_query_file("create_table_puzzle_massive.sql")) db.commit() script_files = [] self.assertRaises(Exception, get_latest_version_based_on_migrate_scripts, script_files)
def __init__(self, puzzle_id, ip): self.puzzle_id = puzzle_id self.ip = ip cur = db.cursor() result = cur.execute( "select id, table_width, table_height from Puzzle where puzzle_id = :puzzle_id;", { "puzzle_id": self.puzzle_id }, ).fetchall() (result, col_names) = rowify(result, cur.description) self.puzzle_details = result[0] cur.close()