def setUp(self): """Define test variables and initialize app.""" self.app = create_app() self.client = self.app.test_client self.database_path = environ.get( 'DATABASE_URL_TEST', 'postgresql://app_user@localhost:5432/casting_agency') setup_db(self.app, self.database_path) self.new_actor = { "name": "Elijah Wood", "gender": "male" } self.new_movie = { "title": "Lord of the Rings", "release_date": "2001-12-13", "actors": [1] } self.token_assistant = environ.get('ASSISTANT_TOKEN', '') self.token_director = environ.get('DIRECTOR_TOKEN', '') self.token_producer = environ.get('PRODUCER_TOKEN', '') # binds the app to the current context with self.app.app_context(): self.db = SQLAlchemy() self.db.init_app(self.app)
def setUp(self): """Define test variables and initialize app.""" self.app = create_app() setup_db(self.app, env='test') self.client = self.app.test_client # binds the app to the current context with self.app.app_context(): self.db = SQLAlchemy() self.db.init_app(self.app) # create all tables self.db.create_all()
def reset_db(): reset_database() setup_db()
import pymongo from flask.helpers import make_response from flask.templating import render_template from flask import Flask, redirect, url_for, jsonify, request from bson.objectid import ObjectId from flask.wrappers import Response from pytz import timezone from config import setup_logging, setup_db from lib import TimeFormat, convert_time_fields, TimePattern, convert_to_csv, TimePatternSimple, TimeFormatSimple, \ parse_user_accept_languages from run_import import import_checkins, run_import_dec, run_import_suc logger = setup_logging() db = setup_db() suc_collection = db.suc checkin_collection = db.checkin tz_utc = timezone('UTC') tz_zurich = timezone("Europe/Zurich") max_distance = 20000 pattern_latlng = re.compile("(\d+\.\d+),(\d+\.\d+)") legacy_nof_stalls = 10 class JSONEncoder(json.JSONEncoder): def default(self, o): if isinstance(o, ObjectId): return str(o)
def create_app(test_config=None): # create and configure the app app = Flask(__name__) setup_db(app) cors = CORS(app, resources={r"/v1/*": {"origins": "*"}}) @app.after_request def after_request(response): response.headers.add('Allow-Control-Allow-Headers', 'Content-Type,Authorization,true') response.headers.add('Allow-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS') return response @app.route('/v1/categories', methods=['GET']) def get_all_categories(): categories = Category.query.all() if len(categories) == 0: abort(Not_found) # Create dictionary for categories {id -> type} data = {cate.id: cate.type for cate in categories} return jsonify({"success": True, "categories": data}), Ok @app.route('/v1/questions', methods=['GET']) def get_all_question(): questions = Question.query.order_by(Question.id).all() # get page of questions page = request.args.get('page', 1, type=int) start = (page - 1) * QUESTIONS_PER_PAGE questions_page = Question.query.order_by( Question.id).limit(QUESTIONS_PER_PAGE).offset(start).all() categories = Category.query.all() categories_data = {cate.id: cate.type for cate in categories} # not found if no question or cateqories if len(questions) == 0 or len(categories) == 0\ or len(questions_page) == 0: abort(Not_found) return jsonify({ "success": True, "questions": [q.format() for q in questions_page], "total_questions": len(questions), "categories": categories_data }), Ok @app.route('/v1/questions/<int:question_id>', methods=['DELETE']) def delete_question(question_id): question = Question.query.get(question_id) if question is None: abort(Not_found) try: question.delete() except Exception as e: # not processable if can't delete the question print(e) abort(Not_processable) return jsonify({'success': True, 'deleted_id': question_id}), Ok @app.route('/v1/questions', methods=['POST']) def create_question(): body = request.get_json() search_term = body.get('searchTerm', None) if search_term: # search for questions that has the search term (case insensitive) page = request.args.get('page', 1, type=int) start = (page - 1) * QUESTIONS_PER_PAGE questions = Question.query.filter( Question.question.ilike(f'%{search_term}%')).order_by( Question.id).limit(QUESTIONS_PER_PAGE).offset(start).all() # not found if no questions if len(questions) == 0: abort(Not_found) return jsonify({ 'success': True, 'questions': [q.format() for q in questions], 'total_questions': len(questions) }), Ok else: question = body.get('question', None) answer = body.get('answer', None) difficulty = body.get('difficulty', None) category = body.get('category', None) # bad request if one of the required fields is missing if (question is None) or (answer is None) or\ (difficulty is None) or (category is None): abort(Bad_request) new_question = Question(question=question, answer=answer, difficulty=difficulty, category=category) try: new_question.insert() except Exception as e: # not processable if can't insert the question print(e) abort(Not_processable) questions = Question.query.all() return jsonify({ 'success': True, 'created_id': new_question.id, 'total_questions': len(questions) }), Created @app.route('/v1/categories/<int:category_id>/questions', methods=['GET']) def get_category_questions(category_id): category = Category.query.get(category_id) if category is None: abort(Not_found) page = request.args.get('page', 1, type=int) start = (page - 1) * QUESTIONS_PER_PAGE # get all question of that category questions = Question.query.filter( Question.category == category_id).order_by( Question.id).limit(QUESTIONS_PER_PAGE).offset(start).all() if len(questions) == 0: abort(Not_found) return jsonify({ 'success': True, 'questions': [q.format() for q in questions], 'total_questions': len(questions), 'current_category': category.type }), Ok @app.route('/v1/quizzes', methods=['POST']) def play_quiz(): body = request.get_json() # get the required parameters previous_questions = body.get('previous_questions', None) category = body.get('quiz_category', None) # Bad request if one of the required parameter is none if (previous_questions is None) or (category is None): abort(Bad_request) # get all question if id is 0 if category['id'] == 0: questions = Question.query.all() # get all question of quiz category else: questions = Question.query.filter( Question.category == category['id']).all() if len(questions) == 0: abort(Not_found) if len(previous_questions) >= len(questions): return jsonify({ 'success': True, 'message': "No more questions" }), Ok import numpy as np # make number of trials to avoid infinite loop trials = 0 while trials <= 100: chosen_question = np.random.choice(questions, replace=True) if not (chosen_question.id in previous_questions): break trials += 1 if trials > 100: abort(Not_found) return jsonify({'success': True, 'question': chosen_question.format()}) @app.errorhandler(400) def bad_request(error): return jsonify({ 'success': False, 'error_code': Bad_request, 'message': "Bad Request" }), Bad_request @app.errorhandler(404) def not_found(error): return jsonify({ "success": False, "message": "Not Found", "error_code": Not_found }), Not_found @app.errorhandler(405) def method_not_allowed(error): return jsonify({ "success": False, "message": "Method not Allowed", "error_code": Method_not_allowed }), Method_not_allowed @app.errorhandler(422) def not_processable(error): return jsonify({ 'success': False, 'error_code': Not_processable, 'message': "Cannot be processed" }), Not_processable return app
def create_app(test_config=None): # create and configure the app app = Flask(__name__) setup_db(app) CORS(app, resources={r"/*": {"origins": "*"}}) @app.after_request def after_request(response): response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization,true') response.headers.add('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,OPTIONS') return response # index for check health @app.route('/') def index(): return jsonify({"success": True, "message": 'healthy'}) # ----------------------------------------------------------------------- # # Actors # ----------------------------------------------------------------------- # ''' Endpoint to handle GET requests for actors, including pagination (every 5) This endpoint return a list of actors, their names, and movies participating ''' @app.route('/actors') @requires_auth('get:actors') def get_actors(payload): page = request.args.get('page', 1, type=int) actors = Actor.query.order_by(Actor.id) actors = actors.paginate(page=page, per_page=ACTORS_PER_PAGE) if actors is None: abort(404) return jsonify({ "success": True, "actors": [actor.long() for actor in actors.items], "total": actors.total, }) ''' Endpoint to handle create an actor This endpoint return if success the actor ID, otherwise 400 or 422 errors ''' @app.route('/actors', methods=['POST']) @requires_auth('create:actors') def create_actor(payload): body = request.get_json() if body is None: abort(400) name = body.get('name', None) gender = body.get('gender', None) if name is None or gender is None: abort(400) actor = Actor(name=name, gender=gender) try: actor.insert() except Exception: print(sys.exc_info()) db.session.rollback() abort(422) return jsonify({"success": True, "actor": actor.id}) ''' Endpoint to handle update an actor This endpoint return if success the actor name and gender, otherwise 400 or 422 errors ''' @app.route('/actors/<int:actor_id>', methods=['PATCH']) @requires_auth('update:actors') def update_actor(payload, actor_id): body = request.get_json() if body is None: abort(400) actor = Actor.query.filter_by(id=actor_id).one_or_none() if actor is None: abort(404) name = body.get('name', None) gender = body.get('gender', None) if name is None and gender is None: abort(400) if name is not None: actor.name = name if gender is not None: actor.gender = gender try: actor.update() except Exception: print(sys.exc_info()) db.session.rollback() abort(422) return jsonify({"success": True, "actor": actor.short()}) ''' Endpoint to DELETE actor using a actor ID ''' @app.route('/actors/<int:actor_id>', methods=['DELETE']) @requires_auth('delete:actors') def delete_actor(payload, actor_id): actor = Actor.query.filter_by(id=actor_id).one_or_none() if actor is None: abort(404) try: actor.delete() except Exception: print(sys.exc_info()) db.session.rollback() abort(422) return jsonify({'success': True, 'deleted': actor_id}) # ----------------------------------------------------------------------- # # Movies # ----------------------------------------------------------------------- # ''' Endpoint to handle GET requests for movies, including pagination (every 5) This endpoint return a list of movies, their title, release_date and actors cast ''' @app.route('/movies') @requires_auth('get:movies') def get_movies(payload): page = request.args.get('page', 1, type=int) movies = Movie.query.order_by(Movie.id) movies = movies.paginate(page=page, per_page=MOVIES_PER_PAGE) if movies is None: abort(404) return jsonify({ "success": True, "total": movies.total, "movies": [movie.long() for movie in movies.items], }) ''' Endpoint to handle create a new movie This endpoint return if success the movie ID, otherwise 400 or 422 errors ''' @app.route('/movies', methods=['POST']) @requires_auth('create:movies') def create_movie(payload): body = request.get_json() if body is None: abort(400) title = body.get('title', None) release_date = body.get('release_date', None) actors = body.get('actors', None) if title is None or release_date is None or actors is None: abort(400) movie = Movie(title=title, release_date=release_date) try: movie.insert() except Exception: print(sys.exc_info()) db.session.rollback() abort(422) for actor in actors: cast = Cast(movie_id=movie.id, actor_id=actor) cast.insert() return jsonify({"success": True, "movie": movie.id}) ''' Endpoint to handle update a movie This endpoint return if success the movie title, release_date and cast, otherwise 400 or 422 errors ''' @app.route('/movies/<int:movie_id>', methods=['PATCH']) @requires_auth('update:movies') def update_movie(payload, movie_id): body = request.get_json() if body is None: abort(400) movie = Movie.query.filter_by(id=movie_id).one_or_none() if movie is None: abort(404) title = body.get('title', None) release_date = body.get('release_date', None) actors = body.get('actors', None) if title is None and release_date is None and actors is None: abort(400) if title is not None: movie.title = title if release_date is not None: movie.release_date = release_date if actors is not None: movie.actors = actors try: movie.update() except Exception: print(sys.exc_info()) db.session.rollback() abort(422) return jsonify({"success": True, "movie": movie.long()}) ''' Endpoint to DELETE movie using a movie ID ''' @app.route('/movies/<int:movie_id>', methods=['DELETE']) @requires_auth('delete:movies') def delete_movie(payload, movie_id): movie = Movie.query.filter_by(id=movie_id).one_or_none() if movie is None: abort(404) try: movie.delete() except Exception: print(sys.exc_info()) db.session.rollback() abort(422) return jsonify({'success': True, 'deleted': movie_id}) # ----------------------------------------------------------------------- # # Error handlers for expected errors # imported from previous udacity projects # ----------------------------------------------------------------------- # @app.errorhandler(400) def bad_request(error): return jsonify({ "error": 400, "message": "Bad request", "success": False }), 400 @app.errorhandler(404) def not_found(error): return jsonify({ "error": 404, "message": "Resource could not be found", "success": False }), 404 @app.errorhandler(405) def unprocessable(error): return jsonify({ "error": 405, "message": "Method not allowed", "success": False }), 405 @app.errorhandler(422) def unprocessable(error): return jsonify({ "error": 422, "message": "Request could not be processable", "success": False }), 422 @app.errorhandler(500) def unprocessable(error): return jsonify({ "error": 500, "message": "Internal server error", "success": False }), 500 @app.errorhandler(AuthError) def auth_error(error): return jsonify({ "success": False, "error": error.status_code, "message": error.error['description'] }), error.status_code return app