-
Notifications
You must be signed in to change notification settings - Fork 61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tien&Anya - Sharks Solar_system #27
base: main
Are you sure you want to change the base?
Changes from all commits
966c426
78b1a5e
5f22a57
5e55917
e82f6b0
bf7d0d4
0c5590f
a5a7261
7f14526
7617f58
b2ab384
408a069
48e352b
871e952
8742fb5
8f7677a
6fc1e71
d4241eb
cd269be
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
web: gunicorn 'app:create_app()' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,42 @@ | ||
from flask import Flask | ||
from flask_sqlalchemy import SQLAlchemy | ||
from flask_migrate import Migrate | ||
from dotenv import load_dotenv | ||
import os | ||
|
||
db = SQLAlchemy() | ||
migrate = Migrate() | ||
load_dotenv() | ||
|
||
def create_app(test_config=None): | ||
app = Flask(__name__) | ||
|
||
# app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False | ||
# app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql+psycopg2://postgres:postgres@localhost:5432/solar_system_development' | ||
|
||
if not test_config: | ||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False | ||
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get( | ||
"SQLALCHEMY_DATABASE_URI") | ||
else: | ||
app.config["TESTING"] = True | ||
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False | ||
app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get( | ||
"SQLALCHEMY_TEST_DATABASE_URI") | ||
|
||
db.init_app(app) | ||
migrate.init_app(app, db) | ||
|
||
# Import models here | ||
from app.models.planet import Planet | ||
|
||
# Register Blueprints here | ||
from .routes import planets_bp | ||
app.register_blueprint(planets_bp) | ||
|
||
from app.models.planet import Planet | ||
|
||
return app | ||
|
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
from flask import abort, make_response | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 Great job moving this helper function into a separate file, so that our routes are more clean and easy to read! |
||
from app.models.planet import Planet | ||
|
||
def validate_planet(planet_id): | ||
try: | ||
planet_id = int(planet_id) | ||
except: | ||
abort(make_response({"message":f"planet_id {planet_id} invalid"}, 400)) | ||
|
||
planet = Planet.query.get(planet_id) | ||
|
||
if not planet: | ||
abort(make_response({"message":f"planet {planet_id} not found"}, 404)) | ||
|
||
return planet |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,47 @@ | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
from app import db | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
class Planet(db.Model): | ||||||||||||||||||||||||||||||
id = db.Column(db.Integer, primary_key=True, autoincrement=True) | ||||||||||||||||||||||||||||||
name = db.Column(db.String) | ||||||||||||||||||||||||||||||
description = db.Column(db.String) | ||||||||||||||||||||||||||||||
moons = db.Column(db.Integer) | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
def to_json(self): | ||||||||||||||||||||||||||||||
return { | ||||||||||||||||||||||||||||||
"id": self.id, | ||||||||||||||||||||||||||||||
"name" : self.name, | ||||||||||||||||||||||||||||||
"description": self.description, | ||||||||||||||||||||||||||||||
"moons": self.moons | ||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
def update(self, req_body): | ||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 helper method woo |
||||||||||||||||||||||||||||||
self.name = req_body["name"] | ||||||||||||||||||||||||||||||
self.description = req_body["description"] | ||||||||||||||||||||||||||||||
self.moons = req_body["moons"] | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
@classmethod | ||||||||||||||||||||||||||||||
def create(cls,req_body): | ||||||||||||||||||||||||||||||
new_planet = cls( | ||||||||||||||||||||||||||||||
name=req_body["name"], | ||||||||||||||||||||||||||||||
description=req_body["description"], | ||||||||||||||||||||||||||||||
moons=req_body["moons"] | ||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||
return new_planet | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
# class Planet(): | ||||||||||||||||||||||||||||||
# def __init__(self, id, name, description, moons = None): | ||||||||||||||||||||||||||||||
# self.id = id | ||||||||||||||||||||||||||||||
# self.name = name | ||||||||||||||||||||||||||||||
# self.description = description | ||||||||||||||||||||||||||||||
# self.moons = moons | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
# def to_json(self): | ||||||||||||||||||||||||||||||
# return { | ||||||||||||||||||||||||||||||
# "id": self.id, | ||||||||||||||||||||||||||||||
# "name" : self.name, | ||||||||||||||||||||||||||||||
# "decription": self.description, | ||||||||||||||||||||||||||||||
# "moons": self.moons | ||||||||||||||||||||||||||||||
# } | ||||||||||||||||||||||||||||||
Comment on lines
+34
to
+47
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Forgot delete those lines |
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
@@ -1,2 +1,63 @@ | ||||
from flask import Blueprint | ||||
from requests import request | ||||
from app import db | ||||
from app.models.planet import Planet | ||||
from flask import Blueprint, jsonify, abort, make_response, request | ||||
from .helper import validate_planet | ||||
|
||||
planets_bp = Blueprint("planets_bp", __name__, url_prefix="/planets") | ||||
|
||||
# CREATE PLANET | ||||
@planets_bp.route("", methods=["POST"]) | ||||
def create_planet(): | ||||
request_body = request.get_json() | ||||
|
||||
new_planet = Planet.create(request_body) | ||||
|
||||
db.session.add(new_planet) | ||||
db.session.commit() | ||||
|
||||
# return make_response(jsonify(f"Planet {new_planet.name} successfully created!", 201)) | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks the same as the one below, so let's get rid of this
Suggested change
|
||||
return make_response(jsonify(f"Planet {new_planet.name} successfully created"), 201) | ||||
|
||||
# GET ALL | ||||
@planets_bp.route("", methods=["GET"]) | ||||
def read_all_planets(): | ||||
name_query = request.args.get("name") | ||||
if name_query: | ||||
planets = Planet.query.filter_by(name=name_query) | ||||
else: | ||||
planets = Planet.query.all() | ||||
|
||||
planets_response = [] | ||||
for planet in planets: | ||||
planets_response.append(planet.to_json()) | ||||
|
||||
return jsonify(planets_response), 200 | ||||
|
||||
# GET one planet | ||||
@planets_bp.route("/<planet_id>", methods=["GET"]) | ||||
def read_one_planet(planet_id): | ||||
planet = validate_planet(planet_id) | ||||
# return jsonify(planet.to_json()), 200 | ||||
return jsonify(planet.to_json()) | ||||
Comment on lines
+41
to
+42
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. any reason you removed the status code on line 42? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think no. I am not sure why we removed it. |
||||
|
||||
# UPDATE one planet | ||||
@planets_bp.route("/<planet_id>", methods=["PUT"]) | ||||
def update_planet(planet_id): | ||||
planet = validate_planet(planet_id) | ||||
request_body = request.get_json() | ||||
|
||||
planet.update(request_body) | ||||
|
||||
db.session.commit() | ||||
return make_response(jsonify(f"Planet #{planet.id} successfully updated")), 200 | ||||
|
||||
# DELETE one planet | ||||
@planets_bp.route("/<planet_id>", methods=["DELETE"]) | ||||
def delete_planet(planet_id): | ||||
planet = validate_planet(planet_id) | ||||
|
||||
db.session.delete(planet) | ||||
db.session.commit() | ||||
|
||||
return make_response(jsonify(f"Planet #{planet.id} successfully deleted")), 200 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import pytest | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 looks good |
||
from app import create_app | ||
from app import db | ||
from flask.signals import request_finished | ||
from app.models.planet import Planet | ||
|
||
|
||
@pytest.fixture | ||
def app(): | ||
app = create_app({"TESTING": True}) | ||
|
||
@request_finished.connect_via(app) | ||
def expire_session(sender, response, **extra): | ||
db.session.remove() | ||
|
||
with app.app_context(): | ||
db.create_all() | ||
yield app | ||
|
||
with app.app_context(): | ||
db.drop_all() | ||
|
||
|
||
@pytest.fixture | ||
def client(app): | ||
return app.test_client() | ||
|
||
@pytest.fixture | ||
def two_saved_planets(app): | ||
# Arrange | ||
jupiter = Planet(name="Jupiter", | ||
description="has big spot", | ||
moons=66) | ||
venus = Planet(name="Venus", | ||
description="beauty", | ||
moons=0) | ||
|
||
db.session.add_all([jupiter, venus]) | ||
# Alternatively, we could do | ||
# db.session.add(jupiter) | ||
# db.session.add(venus) | ||
db.session.commit() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
def test_get_all_planets_with_no_records(client): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 looks good |
||
# Act | ||
response = client.get("/planets") | ||
response_body = response.get_json() | ||
|
||
# Assert | ||
assert response.status_code == 200 | ||
assert response_body == [] | ||
|
||
def test_get_one_planet(client, two_saved_planets): | ||
# Act | ||
response = client.get("/planets/1") | ||
response_body = response.get_json() | ||
|
||
# Assert | ||
assert response.status_code == 200 | ||
assert response_body == { | ||
"id": 1, | ||
"name": "Jupiter", | ||
"description": "has big spot", | ||
"moons": 66 | ||
} | ||
|
||
def test_get_one_planet_empty(client): | ||
# Act | ||
response = client.get("/planets/1") | ||
# response_body = response.get_json() | ||
|
||
# Assert | ||
assert response.status_code == 404 | ||
# assert response_body == make_response({"message":f"planet {planet_id} not found"}, 404) | ||
|
||
|
||
|
||
def test_create_one_planet(client): | ||
# Act | ||
response = client.post("/planets", json={ | ||
"name": "Saturn", | ||
"description": "has rings", | ||
"moons": 82 | ||
}) | ||
response_body = response.get_json() | ||
|
||
# Assert | ||
assert response.status_code == 201 | ||
assert response_body == "Planet Saturn successfully created" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
result = [] | ||
def merge_lists(list1, list2): | ||
|
||
if not list1: | ||
return list2 | ||
if not list2: | ||
return list1 | ||
if not list1 and not list2: | ||
return [] | ||
|
||
if list1[0] < list2[0]: | ||
result.append(list1[0]) | ||
merge_lists(list1[1:], list2) | ||
else: | ||
result.append(list2[0]) | ||
merge_lists(list1, list2[1:]) | ||
|
||
return result | ||
|
||
print(merge_lists([1, 2, 4, 5], [1, 2, 4, 5, 6])) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Generic single-database configuration. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# A generic, single database configuration. | ||
|
||
[alembic] | ||
# template used to generate migration files | ||
# file_template = %%(rev)s_%%(slug)s | ||
|
||
# set to 'true' to run the environment during | ||
# the 'revision' command, regardless of autogenerate | ||
# revision_environment = false | ||
|
||
|
||
# Logging configuration | ||
[loggers] | ||
keys = root,sqlalchemy,alembic | ||
|
||
[handlers] | ||
keys = console | ||
|
||
[formatters] | ||
keys = generic | ||
|
||
[logger_root] | ||
level = WARN | ||
handlers = console | ||
qualname = | ||
|
||
[logger_sqlalchemy] | ||
level = WARN | ||
handlers = | ||
qualname = sqlalchemy.engine | ||
|
||
[logger_alembic] | ||
level = INFO | ||
handlers = | ||
qualname = alembic | ||
|
||
[handler_console] | ||
class = StreamHandler | ||
args = (sys.stderr,) | ||
level = NOTSET | ||
formatter = generic | ||
|
||
[formatter_generic] | ||
format = %(levelname)-5.5s [%(name)s] %(message)s | ||
datefmt = %H:%M:%S |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since we now have this string stored in our environmental variables for safe keeping we want to get rid of it from public view
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree, should be deleted from init.py