From 6988a8ca40dc06e9c80fff834fb63d8820ed095b Mon Sep 17 00:00:00 2001 From: misha-joy Date: Mon, 24 Oct 2022 12:22:23 -0700 Subject: [PATCH 01/30] add wave 1, get all planets --- app/__init__.py | 9 ++++++--- app/routes.py | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/app/__init__.py b/app/__init__.py index 70b4cabfe..52d208d66 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,7 +1,10 @@ from flask import Flask - -def create_app(test_config=None): +# def create_app(test_config=None): +def create_app(): app = Flask(__name__) - return app + from .routes import planets_bp + app.register_blueprint(planets_bp) + + return app \ No newline at end of file diff --git a/app/routes.py b/app/routes.py index 8e9dfe684..ba191ad06 100644 --- a/app/routes.py +++ b/app/routes.py @@ -1,2 +1,34 @@ -from flask import Blueprint +from flask import Blueprint , jsonify + +#create planet class +class Planets: + def __init__(self, id, name, description, livability): + self.id = id + self.name = name + self.description = description + self.livability = livability + + # planet instances +planets = [ + Planets(1, "earth", "green", 10), + Planets(2, "venus", "orange", 5), + Planets(3, "mars", "red", 7), + Planets(4, "jupiter", "beige", 1), + Planets(5, "neptune", "blue", 3), + ] + +planets_bp = Blueprint("planets", __name__, url_prefix = "/planets") + +@planets_bp.route("", methods = ["GET"]) +#get all planets, return as a lists with all attributes +def get_planets(): + planet_response = [] + for planet in planets: + planet_response.append({ + "id": planet.id, + "name": planet.name, + "description": planet.description, + "livability": planet.livability + }) + return jsonify(planet_response) From 1fd6bd8ff6407d5fe45e7c473ad7d45cdbe416ad Mon Sep 17 00:00:00 2001 From: misha-joy Date: Mon, 24 Oct 2022 14:52:48 -0700 Subject: [PATCH 02/30] updates planet attributes --- app/routes.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/routes.py b/app/routes.py index ba191ad06..1321c2804 100644 --- a/app/routes.py +++ b/app/routes.py @@ -10,11 +10,11 @@ def __init__(self, id, name, description, livability): # planet instances planets = [ - Planets(1, "earth", "green", 10), - Planets(2, "venus", "orange", 5), - Planets(3, "mars", "red", 7), - Planets(4, "jupiter", "beige", 1), - Planets(5, "neptune", "blue", 3), + Planets(3, "earth", "green terrestrial planet", 10.0), + Planets(2, "venus", "orange terrestrial planet", 4.5), + Planets(4, "mars", "red terrestrial planet", 7.9), + Planets(5, "jupiter", "beige gas giant", 1.6), + Planets(8, "neptune", "blue ice giant", 3.4), ] planets_bp = Blueprint("planets", __name__, url_prefix = "/planets") From a4e0a8ece6d0d8ce03786309feeea2b01102acc7 Mon Sep 17 00:00:00 2001 From: Leimomi Bong Date: Mon, 24 Oct 2022 13:01:59 -1000 Subject: [PATCH 03/30] pushing wave 2 completed --- app/routes.py | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/app/routes.py b/app/routes.py index 1321c2804..88f8fae82 100644 --- a/app/routes.py +++ b/app/routes.py @@ -1,4 +1,4 @@ -from flask import Blueprint , jsonify +from flask import Blueprint, jsonify, abort, make_response #create planet class class Planets: @@ -32,3 +32,44 @@ def get_planets(): }) return jsonify(planet_response) +# @planets_bp.route("/name", methods = ["GET"]) +#validate the planet request +def varify_planet_exist(id): + try: + id = int(id) + except: + # return {"message": f"planet {name} invalid"}, 400 + abort(make_response({"message":f"planet {id} is invalid, please search by planet_id."}, 400)) + + for planet in planets: + if planet.id == id: + return planet + + abort(make_response({"message":f"planet {id} doesn't exist."}, 404)) + +@planets_bp.route("/", methods = ["GET"]) +#get ONE planet, send return if there's an error +def get_single_planet_by_id(id): + planet = varify_planet_exist(id) + + return { + "id": planet.id, + "name": planet.name, + "description": planet.description, + "livability": planet.livability, + } + +# SEARCH BY NAME DRAFT +# @planets_bp.route("/", methods = ["GET"]) +# #get ONE planet by name +# def get_single_planet_by_name(name): +# for planet in planets: +# if planet.name == name: +# return { +# "id": planet.id, +# "name": planet.name, +# "description": planet.description, +# "livability": planet.livability, +# } +# else: +# return {"message":f"planet {name} doesn't exist."}, 404 \ No newline at end of file From 6ec6e5d772ee43062bef5e8e3642bc8ebfa612a0 Mon Sep 17 00:00:00 2001 From: Leimomi Bong Date: Fri, 28 Oct 2022 08:32:25 -1000 Subject: [PATCH 04/30] created planet model --- app/__init__.py | 13 ++++++ app/models/__init__.py | 0 app/models/planet.py | 9 ++++ app/routes.py | 94 +++++++++++++++++++++--------------------- 4 files changed, 69 insertions(+), 47 deletions(-) create mode 100644 app/models/__init__.py create mode 100644 app/models/planet.py diff --git a/app/__init__.py b/app/__init__.py index 52d208d66..f93cfebd4 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,10 +1,23 @@ from flask import Flask +from flask_sqlalchemy import SQLAlchemy +from flask_migrate import Migrate + +db = SQLAlchemy() +migrate = Migrate() # def create_app(test_config=None): def create_app(): app = Flask(__name__) + app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False + app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql+psycopg2://postgres:postgres@localhost:5432/solar_system_development' + + db.init_app(app) + migrate.init_app(app, db) + from .routes import planets_bp app.register_blueprint(planets_bp) + from app.models.planet import Planet + return app \ No newline at end of file diff --git a/app/models/__init__.py b/app/models/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/app/models/planet.py b/app/models/planet.py new file mode 100644 index 000000000..aa07c7a7f --- /dev/null +++ b/app/models/planet.py @@ -0,0 +1,9 @@ +from app import db + +class Planet(db.Model): + id = db.Column(db.Integer, primary_key=True, autoincrement=True) + name = db.Column(db.String) + color = db.Column(db.String) + livability = db.Column(db.Integer) + moons = db.Column(db.Integer) + is_dwarf = db.Column(db.Boolean) \ No newline at end of file diff --git a/app/routes.py b/app/routes.py index 88f8fae82..b75d3f8db 100644 --- a/app/routes.py +++ b/app/routes.py @@ -1,63 +1,63 @@ from flask import Blueprint, jsonify, abort, make_response +planets_bp = Blueprint("planets", __name__, url_prefix = "/planets") + #create planet class -class Planets: - def __init__(self, id, name, description, livability): - self.id = id - self.name = name - self.description = description - self.livability = livability +# class Planets: +# def __init__(self, id, name, description, livability): +# self.id = id +# self.name = name +# self.description = description +# self.livability = livability # planet instances -planets = [ - Planets(3, "earth", "green terrestrial planet", 10.0), - Planets(2, "venus", "orange terrestrial planet", 4.5), - Planets(4, "mars", "red terrestrial planet", 7.9), - Planets(5, "jupiter", "beige gas giant", 1.6), - Planets(8, "neptune", "blue ice giant", 3.4), - ] - -planets_bp = Blueprint("planets", __name__, url_prefix = "/planets") +# planets = [ +# Planets(3, "earth", "green terrestrial planet", 10.0), +# Planets(2, "venus", "orange terrestrial planet", 4.5), +# Planets(4, "mars", "red terrestrial planet", 7.9), +# Planets(5, "jupiter", "beige gas giant", 1.6), +# Planets(8, "neptune", "blue ice giant", 3.4), +# ] -@planets_bp.route("", methods = ["GET"]) -#get all planets, return as a lists with all attributes -def get_planets(): - planet_response = [] - for planet in planets: - planet_response.append({ - "id": planet.id, - "name": planet.name, - "description": planet.description, - "livability": planet.livability - }) - return jsonify(planet_response) +# @planets_bp.route("", methods = ["GET"]) +# #get all planets, return as a lists with all attributes +# def get_planets(): +# planet_response = [] +# for planet in planets: +# planet_response.append({ +# "id": planet.id, +# "name": planet.name, +# "description": planet.description, +# "livability": planet.livability +# }) +# return jsonify(planet_response) # @planets_bp.route("/name", methods = ["GET"]) #validate the planet request -def varify_planet_exist(id): - try: - id = int(id) - except: - # return {"message": f"planet {name} invalid"}, 400 - abort(make_response({"message":f"planet {id} is invalid, please search by planet_id."}, 400)) +# def varify_planet_exist(id): +# try: +# id = int(id) +# except: +# # return {"message": f"planet {name} invalid"}, 400 +# abort(make_response({"message":f"planet {id} is invalid, please search by planet_id."}, 400)) - for planet in planets: - if planet.id == id: - return planet +# for planet in planets: +# if planet.id == id: +# return planet - abort(make_response({"message":f"planet {id} doesn't exist."}, 404)) +# # abort(make_response({"message":f"planet {id} doesn't exist."}, 404)) -@planets_bp.route("/", methods = ["GET"]) -#get ONE planet, send return if there's an error -def get_single_planet_by_id(id): - planet = varify_planet_exist(id) +# @planets_bp.route("/", methods = ["GET"]) +# #get ONE planet, send return if there's an error +# def get_single_planet_by_id(id): +# planet = varify_planet_exist(id) - return { - "id": planet.id, - "name": planet.name, - "description": planet.description, - "livability": planet.livability, - } +# return { +# "id": planet.id, +# "name": planet.name, +# "description": planet.description, +# "livability": planet.livability, + # } # SEARCH BY NAME DRAFT # @planets_bp.route("/", methods = ["GET"]) From e9030af91ecea14dae8f9ebad1fe9180d320408b Mon Sep 17 00:00:00 2001 From: Leimomi Bong Date: Fri, 28 Oct 2022 09:06:05 -1000 Subject: [PATCH 05/30] server is working --- app/__init__.py | 4 +- app/models/planet.py | 2 +- app/routes.py | 22 ++++- migrations/README | 1 + migrations/alembic.ini | 45 +++++++++ migrations/env.py | 96 +++++++++++++++++++ migrations/script.py.mako | 24 +++++ .../versions/87f50b336eeb_add_planet_model.py | 36 +++++++ 8 files changed, 225 insertions(+), 5 deletions(-) create mode 100644 migrations/README create mode 100644 migrations/alembic.ini create mode 100644 migrations/env.py create mode 100644 migrations/script.py.mako create mode 100644 migrations/versions/87f50b336eeb_add_planet_model.py diff --git a/app/__init__.py b/app/__init__.py index f93cfebd4..d742be868 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -15,8 +15,8 @@ def create_app(): db.init_app(app) migrate.init_app(app, db) - from .routes import planets_bp - app.register_blueprint(planets_bp) + from .routes import planet_bp + app.register_blueprint(planet_bp) from app.models.planet import Planet diff --git a/app/models/planet.py b/app/models/planet.py index aa07c7a7f..361800530 100644 --- a/app/models/planet.py +++ b/app/models/planet.py @@ -6,4 +6,4 @@ class Planet(db.Model): color = db.Column(db.String) livability = db.Column(db.Integer) moons = db.Column(db.Integer) - is_dwarf = db.Column(db.Boolean) \ No newline at end of file + # is_dwarf = db.Column(db.Boolean) \ No newline at end of file diff --git a/app/routes.py b/app/routes.py index b75d3f8db..0b64b5d6e 100644 --- a/app/routes.py +++ b/app/routes.py @@ -1,7 +1,25 @@ -from flask import Blueprint, jsonify, abort, make_response +from app import db +from app.models.planet import Planet +from flask import Blueprint, jsonify, abort, make_response, request -planets_bp = Blueprint("planets", __name__, url_prefix = "/planets") +planet_bp = Blueprint("planet", __name__, url_prefix = "/planet") +@planet_bp.route("", methods=["POST"]) + +def handle_planets(): + request_body = request.get_json() + new_planet = Planet( + name = request_body["name"], + color = request_body["color"], + moons = request_body["moons"], + livability = request_body["livability"] + # is_dwarf = request_body["is_dwarf"] + ) + + db.session.add(new_planet) + db.session.commit() + + return make_response(f"Planet {new_planet.name} successfully created", 201) #create planet class # class Planets: # def __init__(self, id, name, description, livability): diff --git a/migrations/README b/migrations/README new file mode 100644 index 000000000..98e4f9c44 --- /dev/null +++ b/migrations/README @@ -0,0 +1 @@ +Generic single-database configuration. \ No newline at end of file diff --git a/migrations/alembic.ini b/migrations/alembic.ini new file mode 100644 index 000000000..f8ed4801f --- /dev/null +++ b/migrations/alembic.ini @@ -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 diff --git a/migrations/env.py b/migrations/env.py new file mode 100644 index 000000000..8b3fb3353 --- /dev/null +++ b/migrations/env.py @@ -0,0 +1,96 @@ +from __future__ import with_statement + +import logging +from logging.config import fileConfig + +from sqlalchemy import engine_from_config +from sqlalchemy import pool +from flask import current_app + +from alembic import context + +# this is the Alembic Config object, which provides +# access to the values within the .ini file in use. +config = context.config + +# Interpret the config file for Python logging. +# This line sets up loggers basically. +fileConfig(config.config_file_name) +logger = logging.getLogger('alembic.env') + +# add your model's MetaData object here +# for 'autogenerate' support +# from myapp import mymodel +# target_metadata = mymodel.Base.metadata +config.set_main_option( + 'sqlalchemy.url', + str(current_app.extensions['migrate'].db.engine.url).replace('%', '%%')) +target_metadata = current_app.extensions['migrate'].db.metadata + +# other values from the config, defined by the needs of env.py, +# can be acquired: +# my_important_option = config.get_main_option("my_important_option") +# ... etc. + + +def run_migrations_offline(): + """Run migrations in 'offline' mode. + + This configures the context with just a URL + and not an Engine, though an Engine is acceptable + here as well. By skipping the Engine creation + we don't even need a DBAPI to be available. + + Calls to context.execute() here emit the given string to the + script output. + + """ + url = config.get_main_option("sqlalchemy.url") + context.configure( + url=url, target_metadata=target_metadata, literal_binds=True + ) + + with context.begin_transaction(): + context.run_migrations() + + +def run_migrations_online(): + """Run migrations in 'online' mode. + + In this scenario we need to create an Engine + and associate a connection with the context. + + """ + + # this callback is used to prevent an auto-migration from being generated + # when there are no changes to the schema + # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html + def process_revision_directives(context, revision, directives): + if getattr(config.cmd_opts, 'autogenerate', False): + script = directives[0] + if script.upgrade_ops.is_empty(): + directives[:] = [] + logger.info('No changes in schema detected.') + + connectable = engine_from_config( + config.get_section(config.config_ini_section), + prefix='sqlalchemy.', + poolclass=pool.NullPool, + ) + + with connectable.connect() as connection: + context.configure( + connection=connection, + target_metadata=target_metadata, + process_revision_directives=process_revision_directives, + **current_app.extensions['migrate'].configure_args + ) + + with context.begin_transaction(): + context.run_migrations() + + +if context.is_offline_mode(): + run_migrations_offline() +else: + run_migrations_online() diff --git a/migrations/script.py.mako b/migrations/script.py.mako new file mode 100644 index 000000000..2c0156303 --- /dev/null +++ b/migrations/script.py.mako @@ -0,0 +1,24 @@ +"""${message} + +Revision ID: ${up_revision} +Revises: ${down_revision | comma,n} +Create Date: ${create_date} + +""" +from alembic import op +import sqlalchemy as sa +${imports if imports else ""} + +# revision identifiers, used by Alembic. +revision = ${repr(up_revision)} +down_revision = ${repr(down_revision)} +branch_labels = ${repr(branch_labels)} +depends_on = ${repr(depends_on)} + + +def upgrade(): + ${upgrades if upgrades else "pass"} + + +def downgrade(): + ${downgrades if downgrades else "pass"} diff --git a/migrations/versions/87f50b336eeb_add_planet_model.py b/migrations/versions/87f50b336eeb_add_planet_model.py new file mode 100644 index 000000000..4d2ba0a5a --- /dev/null +++ b/migrations/versions/87f50b336eeb_add_planet_model.py @@ -0,0 +1,36 @@ +"""add Planet model + +Revision ID: 87f50b336eeb +Revises: +Create Date: 2022-10-28 08:36:44.775555 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '87f50b336eeb' +down_revision = None +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('planet', + sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('name', sa.String(), nullable=True), + sa.Column('color', sa.String(), nullable=True), + sa.Column('livability', sa.Integer(), nullable=True), + sa.Column('moons', sa.Integer(), nullable=True), + sa.Column('is_dwarf', sa.Boolean(), nullable=True), + sa.PrimaryKeyConstraint('id') + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('planet') + # ### end Alembic commands ### From c509cd63c9c8e961823a97f43ace1f68ee9a60ea Mon Sep 17 00:00:00 2001 From: misha-joy Date: Fri, 28 Oct 2022 12:06:56 -0700 Subject: [PATCH 06/30] commit before pulling --- migrations/README | 1 + migrations/alembic.ini | 45 +++++++++ migrations/env.py | 96 +++++++++++++++++++ migrations/script.py.mako | 24 +++++ .../05d3b908f3f6_adds_planet_model.py | 36 +++++++ 5 files changed, 202 insertions(+) create mode 100644 migrations/README create mode 100644 migrations/alembic.ini create mode 100644 migrations/env.py create mode 100644 migrations/script.py.mako create mode 100644 migrations/versions/05d3b908f3f6_adds_planet_model.py diff --git a/migrations/README b/migrations/README new file mode 100644 index 000000000..98e4f9c44 --- /dev/null +++ b/migrations/README @@ -0,0 +1 @@ +Generic single-database configuration. \ No newline at end of file diff --git a/migrations/alembic.ini b/migrations/alembic.ini new file mode 100644 index 000000000..f8ed4801f --- /dev/null +++ b/migrations/alembic.ini @@ -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 diff --git a/migrations/env.py b/migrations/env.py new file mode 100644 index 000000000..8b3fb3353 --- /dev/null +++ b/migrations/env.py @@ -0,0 +1,96 @@ +from __future__ import with_statement + +import logging +from logging.config import fileConfig + +from sqlalchemy import engine_from_config +from sqlalchemy import pool +from flask import current_app + +from alembic import context + +# this is the Alembic Config object, which provides +# access to the values within the .ini file in use. +config = context.config + +# Interpret the config file for Python logging. +# This line sets up loggers basically. +fileConfig(config.config_file_name) +logger = logging.getLogger('alembic.env') + +# add your model's MetaData object here +# for 'autogenerate' support +# from myapp import mymodel +# target_metadata = mymodel.Base.metadata +config.set_main_option( + 'sqlalchemy.url', + str(current_app.extensions['migrate'].db.engine.url).replace('%', '%%')) +target_metadata = current_app.extensions['migrate'].db.metadata + +# other values from the config, defined by the needs of env.py, +# can be acquired: +# my_important_option = config.get_main_option("my_important_option") +# ... etc. + + +def run_migrations_offline(): + """Run migrations in 'offline' mode. + + This configures the context with just a URL + and not an Engine, though an Engine is acceptable + here as well. By skipping the Engine creation + we don't even need a DBAPI to be available. + + Calls to context.execute() here emit the given string to the + script output. + + """ + url = config.get_main_option("sqlalchemy.url") + context.configure( + url=url, target_metadata=target_metadata, literal_binds=True + ) + + with context.begin_transaction(): + context.run_migrations() + + +def run_migrations_online(): + """Run migrations in 'online' mode. + + In this scenario we need to create an Engine + and associate a connection with the context. + + """ + + # this callback is used to prevent an auto-migration from being generated + # when there are no changes to the schema + # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html + def process_revision_directives(context, revision, directives): + if getattr(config.cmd_opts, 'autogenerate', False): + script = directives[0] + if script.upgrade_ops.is_empty(): + directives[:] = [] + logger.info('No changes in schema detected.') + + connectable = engine_from_config( + config.get_section(config.config_ini_section), + prefix='sqlalchemy.', + poolclass=pool.NullPool, + ) + + with connectable.connect() as connection: + context.configure( + connection=connection, + target_metadata=target_metadata, + process_revision_directives=process_revision_directives, + **current_app.extensions['migrate'].configure_args + ) + + with context.begin_transaction(): + context.run_migrations() + + +if context.is_offline_mode(): + run_migrations_offline() +else: + run_migrations_online() diff --git a/migrations/script.py.mako b/migrations/script.py.mako new file mode 100644 index 000000000..2c0156303 --- /dev/null +++ b/migrations/script.py.mako @@ -0,0 +1,24 @@ +"""${message} + +Revision ID: ${up_revision} +Revises: ${down_revision | comma,n} +Create Date: ${create_date} + +""" +from alembic import op +import sqlalchemy as sa +${imports if imports else ""} + +# revision identifiers, used by Alembic. +revision = ${repr(up_revision)} +down_revision = ${repr(down_revision)} +branch_labels = ${repr(branch_labels)} +depends_on = ${repr(depends_on)} + + +def upgrade(): + ${upgrades if upgrades else "pass"} + + +def downgrade(): + ${downgrades if downgrades else "pass"} diff --git a/migrations/versions/05d3b908f3f6_adds_planet_model.py b/migrations/versions/05d3b908f3f6_adds_planet_model.py new file mode 100644 index 000000000..3475fded2 --- /dev/null +++ b/migrations/versions/05d3b908f3f6_adds_planet_model.py @@ -0,0 +1,36 @@ +"""adds planet model + +Revision ID: 05d3b908f3f6 +Revises: +Create Date: 2022-10-28 11:36:45.165608 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '05d3b908f3f6' +down_revision = None +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('planet', + sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('name', sa.String(), nullable=True), + sa.Column('color', sa.String(), nullable=True), + sa.Column('livability', sa.Integer(), nullable=True), + sa.Column('moons', sa.Integer(), nullable=True), + sa.Column('is_dwarf', sa.Boolean(), nullable=True), + sa.PrimaryKeyConstraint('id') + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('planet') + # ### end Alembic commands ### From 13b53824f239a8664580f9a611da13f0f13cb2c2 Mon Sep 17 00:00:00 2001 From: Leimomi Bong Date: Fri, 28 Oct 2022 09:24:11 -1000 Subject: [PATCH 07/30] wave 3 is done --- app/routes.py | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/app/routes.py b/app/routes.py index 0b64b5d6e..06dcdb9cd 100644 --- a/app/routes.py +++ b/app/routes.py @@ -4,22 +4,36 @@ planet_bp = Blueprint("planet", __name__, url_prefix = "/planet") -@planet_bp.route("", methods=["POST"]) +@planet_bp.route("", methods=["POST", "GET"]) def handle_planets(): request_body = request.get_json() - new_planet = Planet( - name = request_body["name"], - color = request_body["color"], - moons = request_body["moons"], - livability = request_body["livability"] - # is_dwarf = request_body["is_dwarf"] - ) + if request.method == "GET": + planets = Planet.query.all() + planet_response = [] + for planet in planets: + planet_response.append({ + "name": planet.name, + "color": planet.color, + "livability": planet.livability, + "moons": planet.moons + }) + return jsonify(planet_response) + + elif request.method == "POST": + new_planet = Planet( + name = request_body["name"], + color = request_body["color"], + moons = request_body["moons"], + livability = request_body["livability"] + # is_dwarf = request_body["is_dwarf"] + ) + + db.session.add(new_planet) + db.session.commit() - db.session.add(new_planet) - db.session.commit() + return make_response(f"Planet {new_planet.name} successfully created", 201) - return make_response(f"Planet {new_planet.name} successfully created", 201) #create planet class # class Planets: # def __init__(self, id, name, description, livability): @@ -38,7 +52,7 @@ def handle_planets(): # ] # @planets_bp.route("", methods = ["GET"]) -# #get all planets, return as a lists with all attributes +#get all planets, return as a lists with all attributes # def get_planets(): # planet_response = [] # for planet in planets: From 0541226a63ca95eb95cb0564bdaadab999676e0b Mon Sep 17 00:00:00 2001 From: misha-joy Date: Fri, 28 Oct 2022 18:48:28 -0700 Subject: [PATCH 08/30] commit before pulling --- ...b_add_planet_model.py => 036c26fe57f3_.py} | 9 +++-- .../05d3b908f3f6_adds_planet_model.py | 36 ------------------- 2 files changed, 4 insertions(+), 41 deletions(-) rename migrations/versions/{87f50b336eeb_add_planet_model.py => 036c26fe57f3_.py} (82%) delete mode 100644 migrations/versions/05d3b908f3f6_adds_planet_model.py diff --git a/migrations/versions/87f50b336eeb_add_planet_model.py b/migrations/versions/036c26fe57f3_.py similarity index 82% rename from migrations/versions/87f50b336eeb_add_planet_model.py rename to migrations/versions/036c26fe57f3_.py index 4d2ba0a5a..5d03961ae 100644 --- a/migrations/versions/87f50b336eeb_add_planet_model.py +++ b/migrations/versions/036c26fe57f3_.py @@ -1,8 +1,8 @@ -"""add Planet model +"""empty message -Revision ID: 87f50b336eeb +Revision ID: 036c26fe57f3 Revises: -Create Date: 2022-10-28 08:36:44.775555 +Create Date: 2022-10-28 18:47:18.909945 """ from alembic import op @@ -10,7 +10,7 @@ # revision identifiers, used by Alembic. -revision = '87f50b336eeb' +revision = '036c26fe57f3' down_revision = None branch_labels = None depends_on = None @@ -24,7 +24,6 @@ def upgrade(): sa.Column('color', sa.String(), nullable=True), sa.Column('livability', sa.Integer(), nullable=True), sa.Column('moons', sa.Integer(), nullable=True), - sa.Column('is_dwarf', sa.Boolean(), nullable=True), sa.PrimaryKeyConstraint('id') ) # ### end Alembic commands ### diff --git a/migrations/versions/05d3b908f3f6_adds_planet_model.py b/migrations/versions/05d3b908f3f6_adds_planet_model.py deleted file mode 100644 index 3475fded2..000000000 --- a/migrations/versions/05d3b908f3f6_adds_planet_model.py +++ /dev/null @@ -1,36 +0,0 @@ -"""adds planet model - -Revision ID: 05d3b908f3f6 -Revises: -Create Date: 2022-10-28 11:36:45.165608 - -""" -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = '05d3b908f3f6' -down_revision = None -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.create_table('planet', - sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), - sa.Column('name', sa.String(), nullable=True), - sa.Column('color', sa.String(), nullable=True), - sa.Column('livability', sa.Integer(), nullable=True), - sa.Column('moons', sa.Integer(), nullable=True), - sa.Column('is_dwarf', sa.Boolean(), nullable=True), - sa.PrimaryKeyConstraint('id') - ) - # ### end Alembic commands ### - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.drop_table('planet') - # ### end Alembic commands ### From ae506cd2a4fc37e1571a8351003ec54d2b3de258 Mon Sep 17 00:00:00 2001 From: misha-joy Date: Mon, 31 Oct 2022 16:22:58 -0700 Subject: [PATCH 09/30] adds wave 4 -get 1, update, delete --- app/routes.py | 86 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 63 insertions(+), 23 deletions(-) diff --git a/app/routes.py b/app/routes.py index 06dcdb9cd..8de9678e4 100644 --- a/app/routes.py +++ b/app/routes.py @@ -2,10 +2,9 @@ from app.models.planet import Planet from flask import Blueprint, jsonify, abort, make_response, request -planet_bp = Blueprint("planet", __name__, url_prefix = "/planet") +planet_bp = Blueprint("planets", __name__, url_prefix = "/planets") @planet_bp.route("", methods=["POST", "GET"]) - def handle_planets(): request_body = request.get_json() if request.method == "GET": @@ -13,6 +12,7 @@ def handle_planets(): planet_response = [] for planet in planets: planet_response.append({ + "id": planet.id, "name": planet.name, "color": planet.color, "livability": planet.livability, @@ -22,6 +22,7 @@ def handle_planets(): elif request.method == "POST": new_planet = Planet( + # id = request_body["id"], name = request_body["name"], color = request_body["color"], moons = request_body["moons"], @@ -34,6 +35,58 @@ def handle_planets(): return make_response(f"Planet {new_planet.name} successfully created", 201) + +# GET ONE PLANET BASED ON ID +def validate_planet_id(planet_id): + try: + planet_id = int(planet_id) + except: + # return {"message": f"planet {name} invalid"}, 400 + abort(make_response({"message":f"planet #{planet_id} is invalid, please search by planet_id."}, 400)) + + planet = Planet.query.get(planet_id) + + if not planet: + abort(make_response({"message":f"planet #{planet_id} doesn't exist."}, 404)) + + return planet + +@planet_bp.route("/", methods = ["GET"]) +def get_one_planet(planet_id): + planet = validate_planet_id(planet_id) + + return { + "id": planet.id, + "name": planet.name, + "color": planet.color, + "livability": planet.livability, + "moons": planet.moons + } + +@planet_bp.route("/", methods = ["PUT"]) +def update_planet(planet_id): + planet = validate_planet_id(planet_id) + + request_body = request.get_json() + + # planet.name = request_body["name"], + # planet.color = request_body["color"], + # planet.moons = request_body["moons"], + planet.livability = request_body["livability"] + + db.session.commit() + + return make_response(f"Planet #{planet.id} successfully updated.") + +@planet_bp.route("/", methods = ["DELETE"]) +def delete_planet(planet_id): + planet = validate_planet_id(planet_id) + + db.session.delete(planet) + db.session.commit() + + return make_response(f"Planet #{planet.id} successfully deleted.") + #create planet class # class Planets: # def __init__(self, id, name, description, livability): @@ -64,32 +117,19 @@ def handle_planets(): # }) # return jsonify(planet_response) -# @planets_bp.route("/name", methods = ["GET"]) -#validate the planet request -# def varify_planet_exist(id): -# try: -# id = int(id) -# except: -# # return {"message": f"planet {name} invalid"}, 400 -# abort(make_response({"message":f"planet {id} is invalid, please search by planet_id."}, 400)) - -# for planet in planets: -# if planet.id == id: -# return planet - -# # abort(make_response({"message":f"planet {id} doesn't exist."}, 404)) - -# @planets_bp.route("/", methods = ["GET"]) -# #get ONE planet, send return if there's an error -# def get_single_planet_by_id(id): -# planet = varify_planet_exist(id) +# @planet_bp.route("/", methods = ["GET"]) +#get ONE planet, send return if there's an error +# def get_single_planet_by_id(name): +# planet = varify_planet_exist(name) # return { # "id": planet.id, # "name": planet.name, -# "description": planet.description, +# "color": planet.color, +# # "description": planet.description, # "livability": planet.livability, - # } +# "moons": planet.moons +# } # SEARCH BY NAME DRAFT # @planets_bp.route("/", methods = ["GET"]) From 0a56590d5f258755d148aa6be8bba4abb0a5ba0a Mon Sep 17 00:00:00 2001 From: Leimomi Bong Date: Tue, 1 Nov 2022 07:47:42 -1000 Subject: [PATCH 10/30] added is_dwarf attribute to model --- app/models/planet.py | 2 +- app/routes.py | 81 ++++++-------------------------------------- 2 files changed, 12 insertions(+), 71 deletions(-) diff --git a/app/models/planet.py b/app/models/planet.py index 361800530..aa07c7a7f 100644 --- a/app/models/planet.py +++ b/app/models/planet.py @@ -6,4 +6,4 @@ class Planet(db.Model): color = db.Column(db.String) livability = db.Column(db.Integer) moons = db.Column(db.Integer) - # is_dwarf = db.Column(db.Boolean) \ No newline at end of file + is_dwarf = db.Column(db.Boolean) \ No newline at end of file diff --git a/app/routes.py b/app/routes.py index 8de9678e4..79d8fae5f 100644 --- a/app/routes.py +++ b/app/routes.py @@ -16,7 +16,8 @@ def handle_planets(): "name": planet.name, "color": planet.color, "livability": planet.livability, - "moons": planet.moons + "moons": planet.moons, + "is_dwarf": planet.is_dwarf }) return jsonify(planet_response) @@ -26,8 +27,8 @@ def handle_planets(): name = request_body["name"], color = request_body["color"], moons = request_body["moons"], - livability = request_body["livability"] - # is_dwarf = request_body["is_dwarf"] + livability = request_body["livability"], + is_dwarf = request_body["is_dwarf"] ) db.session.add(new_planet) @@ -35,13 +36,10 @@ def handle_planets(): return make_response(f"Planet {new_planet.name} successfully created", 201) - -# GET ONE PLANET BASED ON ID def validate_planet_id(planet_id): try: planet_id = int(planet_id) except: - # return {"message": f"planet {name} invalid"}, 400 abort(make_response({"message":f"planet #{planet_id} is invalid, please search by planet_id."}, 400)) planet = Planet.query.get(planet_id) @@ -60,7 +58,8 @@ def get_one_planet(planet_id): "name": planet.name, "color": planet.color, "livability": planet.livability, - "moons": planet.moons + "moons": planet.moons, + "is_dwarf": planet.is_dwarf } @planet_bp.route("/", methods = ["PUT"]) @@ -69,10 +68,11 @@ def update_planet(planet_id): request_body = request.get_json() - # planet.name = request_body["name"], - # planet.color = request_body["color"], - # planet.moons = request_body["moons"], + planet.name = request_body["name"], + planet.color = request_body["color"], + planet.moons = request_body["moons"], planet.livability = request_body["livability"] + planet.is_dwarf = request_body["is_dwarf"] db.session.commit() @@ -85,63 +85,4 @@ def delete_planet(planet_id): db.session.delete(planet) db.session.commit() - return make_response(f"Planet #{planet.id} successfully deleted.") - -#create planet class -# class Planets: -# def __init__(self, id, name, description, livability): -# self.id = id -# self.name = name -# self.description = description -# self.livability = livability - - # planet instances -# planets = [ -# Planets(3, "earth", "green terrestrial planet", 10.0), -# Planets(2, "venus", "orange terrestrial planet", 4.5), -# Planets(4, "mars", "red terrestrial planet", 7.9), -# Planets(5, "jupiter", "beige gas giant", 1.6), -# Planets(8, "neptune", "blue ice giant", 3.4), -# ] - -# @planets_bp.route("", methods = ["GET"]) -#get all planets, return as a lists with all attributes -# def get_planets(): -# planet_response = [] -# for planet in planets: -# planet_response.append({ -# "id": planet.id, -# "name": planet.name, -# "description": planet.description, -# "livability": planet.livability -# }) -# return jsonify(planet_response) - -# @planet_bp.route("/", methods = ["GET"]) -#get ONE planet, send return if there's an error -# def get_single_planet_by_id(name): -# planet = varify_planet_exist(name) - -# return { -# "id": planet.id, -# "name": planet.name, -# "color": planet.color, -# # "description": planet.description, -# "livability": planet.livability, -# "moons": planet.moons -# } - -# SEARCH BY NAME DRAFT -# @planets_bp.route("/", methods = ["GET"]) -# #get ONE planet by name -# def get_single_planet_by_name(name): -# for planet in planets: -# if planet.name == name: -# return { -# "id": planet.id, -# "name": planet.name, -# "description": planet.description, -# "livability": planet.livability, -# } -# else: -# return {"message":f"planet {name} doesn't exist."}, 404 \ No newline at end of file + return make_response(f"Planet #{planet.id} successfully deleted.") \ No newline at end of file From 84ba83d231a8cf5987e84673fca6b80be12fc63e Mon Sep 17 00:00:00 2001 From: Leimomi Bong Date: Wed, 2 Nov 2022 09:11:49 -1000 Subject: [PATCH 11/30] Added function for query parameters, search by name --- app/routes.py | 80 +++++++++++++++++++++++++++++---------------------- 1 file changed, 46 insertions(+), 34 deletions(-) diff --git a/app/routes.py b/app/routes.py index 79d8fae5f..d090ab4d1 100644 --- a/app/routes.py +++ b/app/routes.py @@ -4,39 +4,9 @@ planet_bp = Blueprint("planets", __name__, url_prefix = "/planets") -@planet_bp.route("", methods=["POST", "GET"]) -def handle_planets(): - request_body = request.get_json() - if request.method == "GET": - planets = Planet.query.all() - planet_response = [] - for planet in planets: - planet_response.append({ - "id": planet.id, - "name": planet.name, - "color": planet.color, - "livability": planet.livability, - "moons": planet.moons, - "is_dwarf": planet.is_dwarf - }) - return jsonify(planet_response) - - elif request.method == "POST": - new_planet = Planet( - # id = request_body["id"], - name = request_body["name"], - color = request_body["color"], - moons = request_body["moons"], - livability = request_body["livability"], - is_dwarf = request_body["is_dwarf"] - ) - - db.session.add(new_planet) - db.session.commit() - - return make_response(f"Planet {new_planet.name} successfully created", 201) - +# HELPER FUNCTIONS def validate_planet_id(planet_id): + planet = validate_planet_id(planet_id) try: planet_id = int(planet_id) except: @@ -46,9 +16,51 @@ def validate_planet_id(planet_id): if not planet: abort(make_response({"message":f"planet #{planet_id} doesn't exist."}, 404)) - return planet +# MAIN FUNCTIONS HANDLING REQUESTS +@planet_bp.route("", methods=["GET"]) +def get_planets(): + planet = validate_planet_id(planet_id) + planet_response = [] + + name_query = request.args.get("name") + + if name_query is not None: + planets = Planet.query.filter_by(name=name_query) + else: + planets = Planet.query.all() + + for planet in planets: + planet_response.append({ + "id": planet.id, + "name": planet.name, + "color": planet.color, + "livability": planet.livability, + "moons": planet.moons, + "is_dwarf": planet.is_dwarf + }) + return jsonify(planet_response) + +@planet_bp.route("", methods=["POST"]) +def create_new_planet(): + planet = validate_planet_id(planet_id) + + request_body = request.get_json() + + new_planet = Planet( + name = request_body["name"], + color = request_body["color"], + moons = request_body["moons"], + livability = request_body["livability"], + is_dwarf = request_body["is_dwarf"] + ) + + db.session.add(new_planet) + db.session.commit() + + return make_response(f"Planet {new_planet.name} successfully created", 201) + @planet_bp.route("/", methods = ["GET"]) def get_one_planet(planet_id): planet = validate_planet_id(planet_id) @@ -85,4 +97,4 @@ def delete_planet(planet_id): db.session.delete(planet) db.session.commit() - return make_response(f"Planet #{planet.id} successfully deleted.") \ No newline at end of file + return make_response(f"Planet #{planet.id} successfully deleted.") From e94fb40cf328bf27e294a9ab1914f77dd9e3abe0 Mon Sep 17 00:00:00 2001 From: misha-joy Date: Wed, 2 Nov 2022 20:04:49 -0700 Subject: [PATCH 12/30] adds is_dwarf again --- app/routes.py | 1 + .../65348fa233e7_add_is_dwarf_attribute.py | 28 +++++++++++++++++++ project-directions/wave_01.md | 2 +- 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 migrations/versions/65348fa233e7_add_is_dwarf_attribute.py diff --git a/app/routes.py b/app/routes.py index 79d8fae5f..e563e911d 100644 --- a/app/routes.py +++ b/app/routes.py @@ -62,6 +62,7 @@ def get_one_planet(planet_id): "is_dwarf": planet.is_dwarf } + @planet_bp.route("/", methods = ["PUT"]) def update_planet(planet_id): planet = validate_planet_id(planet_id) diff --git a/migrations/versions/65348fa233e7_add_is_dwarf_attribute.py b/migrations/versions/65348fa233e7_add_is_dwarf_attribute.py new file mode 100644 index 000000000..e412e64cd --- /dev/null +++ b/migrations/versions/65348fa233e7_add_is_dwarf_attribute.py @@ -0,0 +1,28 @@ +"""add is_dwarf attribute + +Revision ID: 65348fa233e7 +Revises: 036c26fe57f3 +Create Date: 2022-11-01 10:54:27.577573 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '65348fa233e7' +down_revision = '036c26fe57f3' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('planet', sa.Column('is_dwarf', sa.Boolean(), nullable=True)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('planet', 'is_dwarf') + # ### end Alembic commands ### diff --git a/project-directions/wave_01.md b/project-directions/wave_01.md index a07cc6548..1793f76e3 100644 --- a/project-directions/wave_01.md +++ b/project-directions/wave_01.md @@ -1,6 +1,6 @@ # Wave 01: Setup and Read -## Flask Setup +## Flask Setup *HI THERE Perform following setup steps for the Solar System API repo to get started on this Flask project: 1. Create a virtual environment and activate it From 1a94408467063836fdd56f45dd9c11582badc2c3 Mon Sep 17 00:00:00 2001 From: Leimomi Bong Date: Thu, 3 Nov 2022 06:22:05 -1000 Subject: [PATCH 13/30] reverting back to old version --- app/routes.py | 81 +++++++++++++++++++++++---------------------------- 1 file changed, 37 insertions(+), 44 deletions(-) diff --git a/app/routes.py b/app/routes.py index d090ab4d1..20ca707eb 100644 --- a/app/routes.py +++ b/app/routes.py @@ -4,62 +4,55 @@ planet_bp = Blueprint("planets", __name__, url_prefix = "/planets") -# HELPER FUNCTIONS -def validate_planet_id(planet_id): - planet = validate_planet_id(planet_id) - try: - planet_id = int(planet_id) - except: - abort(make_response({"message":f"planet #{planet_id} is invalid, please search by planet_id."}, 400)) - - planet = Planet.query.get(planet_id) - - if not planet: - abort(make_response({"message":f"planet #{planet_id} doesn't exist."}, 404)) - return planet +@planet_bp.route("", methods=["POST", "GET"]) +def handle_planets(): + request_body = request.get_json() -# MAIN FUNCTIONS HANDLING REQUESTS -@planet_bp.route("", methods=["GET"]) -def get_planets(): - planet = validate_planet_id(planet_id) planet_response = [] name_query = request.args.get("name") - if name_query is not None: - planets = Planet.query.filter_by(name=name_query) - else: + if request.method == "GET": planets = Planet.query.all() - - for planet in planets: - planet_response.append({ - "id": planet.id, - "name": planet.name, - "color": planet.color, - "livability": planet.livability, - "moons": planet.moons, - "is_dwarf": planet.is_dwarf - }) - return jsonify(planet_response) - -@planet_bp.route("", methods=["POST"]) -def create_new_planet(): - planet = validate_planet_id(planet_id) - - request_body = request.get_json() - - new_planet = Planet( + planet_response = [] + for planet in planets: + planet_response.append({ + "id": planet.id, + "name": planet.name, + "color": planet.color, + "livability": planet.livability, + "moons": planet.moons, + "is_dwarf": planet.is_dwarf + }) + return jsonify(planet_response) + + elif request.method == "POST": + new_planet = Planet( + # id = request_body["id"], name = request_body["name"], color = request_body["color"], moons = request_body["moons"], livability = request_body["livability"], is_dwarf = request_body["is_dwarf"] - ) + ) - db.session.add(new_planet) - db.session.commit() + db.session.add(new_planet) + db.session.commit() + + return make_response(f"Planet {new_planet.name} successfully created", 201) + +def validate_planet_id(planet_id): + try: + planet_id = int(planet_id) + except: + abort(make_response({"message":f"planet #{planet_id} is invalid, please search by planet_id."}, 400)) + + planet = Planet.query.get(planet_id) - return make_response(f"Planet {new_planet.name} successfully created", 201) + if not planet: + abort(make_response({"message":f"planet #{planet_id} doesn't exist."}, 404)) + + return planet @planet_bp.route("/", methods = ["GET"]) def get_one_planet(planet_id): @@ -97,4 +90,4 @@ def delete_planet(planet_id): db.session.delete(planet) db.session.commit() - return make_response(f"Planet #{planet.id} successfully deleted.") + return make_response(f"Planet #{planet.id} successfully deleted.") \ No newline at end of file From d5647179a34a4c35bfba86193ff41260b8943a23 Mon Sep 17 00:00:00 2001 From: misha-joy Date: Thu, 3 Nov 2022 11:03:15 -0700 Subject: [PATCH 14/30] add .env file, updates create_app test config --- .gitignore | 1 + app/__init__.py | 23 +++++++++++++++-------- app/routes.py | 9 ++++----- requirements.txt | 8 ++++++++ 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index 4e9b18359..72d16b84c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.env .vscode .DS_Store diff --git a/app/__init__.py b/app/__init__.py index d742be868..205b8e4c1 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,23 +1,30 @@ 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): -def create_app(): +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'] = 'postgresql+psycopg2://postgres:postgres@localhost:5432/solar_system_development' + 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) - + from app.models.planet import Planet from .routes import planet_bp app.register_blueprint(planet_bp) - from app.models.planet import Planet - - return app \ No newline at end of file + return app + \ No newline at end of file diff --git a/app/routes.py b/app/routes.py index ca296425d..95d6776b0 100644 --- a/app/routes.py +++ b/app/routes.py @@ -21,16 +21,15 @@ def validate_planet_id(planet_id): # MAIN FUNCTIONS HANDLING REQUESTS @planet_bp.route("", methods=["GET"]) def get_planets(): - planet = validate_planet_id(planet_id) - planet_response = [] - +# planet = validate_planet_id(planet_id) name_query = request.args.get("name") if name_query is not None: planets = Planet.query.filter_by(name=name_query) else: planets = Planet.query.all() - + + planet_response = [] for planet in planets: planet_response.append({ "id": planet.id, @@ -44,7 +43,7 @@ def get_planets(): @planet_bp.route("", methods=["POST"]) def create_new_planet(): - planet = validate_planet_id(planet_id) + planet = validate_planet_id(planet.id) request_body = request.get_json() diff --git a/requirements.txt b/requirements.txt index fba2b3e38..1eeabccdc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,19 +1,26 @@ alembic==1.5.4 +attrs==22.1.0 autopep8==1.5.5 blinker==1.4 certifi==2020.12.5 chardet==4.0.0 click==7.1.2 +coverage==6.5.0 Flask==1.1.2 Flask-Migrate==2.6.0 Flask-SQLAlchemy==2.4.4 idna==2.10 +iniconfig==1.1.1 itsdangerous==1.1.0 Jinja2==2.11.3 Mako==1.1.4 MarkupSafe==1.1.1 +packaging==21.3 +pluggy==1.0.0 psycopg2-binary==2.9.4 +py==1.11.0 pycodestyle==2.6.0 +pyparsing==3.0.9 pytest==7.1.1 pytest-cov==2.12.1 python-dateutil==2.8.1 @@ -23,5 +30,6 @@ requests==2.25.1 six==1.15.0 SQLAlchemy==1.3.23 toml==0.10.2 +tomli==2.0.1 urllib3==1.26.4 Werkzeug==1.0.1 From fc56176406be75fbabd0aae2222fd19404652476 Mon Sep 17 00:00:00 2001 From: misha-joy Date: Thu, 3 Nov 2022 11:18:54 -0700 Subject: [PATCH 15/30] restoring to previous after merge conflict --- app/routes.py | 81 +++++++++++++++++++++++---------------------------- 1 file changed, 37 insertions(+), 44 deletions(-) diff --git a/app/routes.py b/app/routes.py index 95d6776b0..20ca707eb 100644 --- a/app/routes.py +++ b/app/routes.py @@ -4,61 +4,55 @@ planet_bp = Blueprint("planets", __name__, url_prefix = "/planets") -# HELPER FUNCTIONS -def validate_planet_id(planet_id): - planet = validate_planet_id(planet_id) - try: - planet_id = int(planet_id) - except: - abort(make_response({"message":f"planet #{planet_id} is invalid, please search by planet_id."}, 400)) - - planet = Planet.query.get(planet_id) +@planet_bp.route("", methods=["POST", "GET"]) +def handle_planets(): + request_body = request.get_json() - if not planet: - abort(make_response({"message":f"planet #{planet_id} doesn't exist."}, 404)) - return planet + planet_response = [] -# MAIN FUNCTIONS HANDLING REQUESTS -@planet_bp.route("", methods=["GET"]) -def get_planets(): -# planet = validate_planet_id(planet_id) name_query = request.args.get("name") - if name_query is not None: - planets = Planet.query.filter_by(name=name_query) - else: + if request.method == "GET": planets = Planet.query.all() + planet_response = [] + for planet in planets: + planet_response.append({ + "id": planet.id, + "name": planet.name, + "color": planet.color, + "livability": planet.livability, + "moons": planet.moons, + "is_dwarf": planet.is_dwarf + }) + return jsonify(planet_response) - planet_response = [] - for planet in planets: - planet_response.append({ - "id": planet.id, - "name": planet.name, - "color": planet.color, - "livability": planet.livability, - "moons": planet.moons, - "is_dwarf": planet.is_dwarf - }) - return jsonify(planet_response) - -@planet_bp.route("", methods=["POST"]) -def create_new_planet(): - planet = validate_planet_id(planet.id) - - request_body = request.get_json() - - new_planet = Planet( + elif request.method == "POST": + new_planet = Planet( + # id = request_body["id"], name = request_body["name"], color = request_body["color"], moons = request_body["moons"], livability = request_body["livability"], is_dwarf = request_body["is_dwarf"] - ) + ) - db.session.add(new_planet) - db.session.commit() + db.session.add(new_planet) + db.session.commit() - return make_response(f"Planet {new_planet.name} successfully created", 201) + return make_response(f"Planet {new_planet.name} successfully created", 201) + +def validate_planet_id(planet_id): + try: + planet_id = int(planet_id) + except: + abort(make_response({"message":f"planet #{planet_id} is invalid, please search by planet_id."}, 400)) + + planet = Planet.query.get(planet_id) + + if not planet: + abort(make_response({"message":f"planet #{planet_id} doesn't exist."}, 404)) + + return planet @planet_bp.route("/", methods = ["GET"]) def get_one_planet(planet_id): @@ -73,7 +67,6 @@ def get_one_planet(planet_id): "is_dwarf": planet.is_dwarf } - @planet_bp.route("/", methods = ["PUT"]) def update_planet(planet_id): planet = validate_planet_id(planet_id) @@ -97,4 +90,4 @@ def delete_planet(planet_id): db.session.delete(planet) db.session.commit() - return make_response(f"Planet #{planet.id} successfully deleted.") + return make_response(f"Planet #{planet.id} successfully deleted.") \ No newline at end of file From 0637fa7af49eaf7df2e72a5f5aa5e8d84e61032b Mon Sep 17 00:00:00 2001 From: Leimomi Bong Date: Thu, 3 Nov 2022 08:37:58 -1000 Subject: [PATCH 16/30] added name query --- app/routes.py | 9 +++++++-- app/tests/.env.py | 0 app/tests/__int__.py | 0 app/tests/config.py | 0 app/tests/test_routes.py | 0 5 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 app/tests/.env.py create mode 100644 app/tests/__int__.py create mode 100644 app/tests/config.py create mode 100644 app/tests/test_routes.py diff --git a/app/routes.py b/app/routes.py index 20ca707eb..f1466221d 100644 --- a/app/routes.py +++ b/app/routes.py @@ -5,6 +5,7 @@ planet_bp = Blueprint("planets", __name__, url_prefix = "/planets") @planet_bp.route("", methods=["POST", "GET"]) + def handle_planets(): request_body = request.get_json() @@ -13,7 +14,12 @@ def handle_planets(): name_query = request.args.get("name") if request.method == "GET": - planets = Planet.query.all() + name_query = request.args.get("name") + if name_query: + planets = Planet.query.filter_by(name=name_query) + else: + planets = Planet.query.all() + planet_response = [] for planet in planets: planet_response.append({ @@ -28,7 +34,6 @@ def handle_planets(): elif request.method == "POST": new_planet = Planet( - # id = request_body["id"], name = request_body["name"], color = request_body["color"], moons = request_body["moons"], diff --git a/app/tests/.env.py b/app/tests/.env.py new file mode 100644 index 000000000..e69de29bb diff --git a/app/tests/__int__.py b/app/tests/__int__.py new file mode 100644 index 000000000..e69de29bb diff --git a/app/tests/config.py b/app/tests/config.py new file mode 100644 index 000000000..e69de29bb diff --git a/app/tests/test_routes.py b/app/tests/test_routes.py new file mode 100644 index 000000000..e69de29bb From 640717f91181de265e65102c36886363776e8823 Mon Sep 17 00:00:00 2001 From: Leimomi Bong Date: Thu, 3 Nov 2022 09:09:05 -1000 Subject: [PATCH 17/30] set up test_cofig files and fixtures --- app/{tests => }/test_routes.py | 0 app/tests/{.env.py => __init__.py} | 0 app/tests/__int__.py | 0 app/tests/config.py | 0 app/tests/test_config.py | 43 ++++++++++++++++++++++++++++++ 5 files changed, 43 insertions(+) rename app/{tests => }/test_routes.py (100%) rename app/tests/{.env.py => __init__.py} (100%) delete mode 100644 app/tests/__int__.py delete mode 100644 app/tests/config.py create mode 100644 app/tests/test_config.py diff --git a/app/tests/test_routes.py b/app/test_routes.py similarity index 100% rename from app/tests/test_routes.py rename to app/test_routes.py diff --git a/app/tests/.env.py b/app/tests/__init__.py similarity index 100% rename from app/tests/.env.py rename to app/tests/__init__.py diff --git a/app/tests/__int__.py b/app/tests/__int__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/app/tests/config.py b/app/tests/config.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/app/tests/test_config.py b/app/tests/test_config.py new file mode 100644 index 000000000..8897d8d22 --- /dev/null +++ b/app/tests/test_config.py @@ -0,0 +1,43 @@ +import pytest +from app import create_app +from app import db +from flask.signals import request_finished + +@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 save_planet(app): + test_planet1 = Planet({ + "color": "pink", + "is_dwarf": True, + "livability": 3, + "moons": 99, + "name": "Pretend Planet X" + }) + test_planet2 = Planet({ + "color": "purple", + "is_dwarf": False, + "livability": 7.4, + "moons": 1, + "name": "Planet Pretend Z" + }) + + db.session.add_all([test_planet1, test_planet2]) + db.session.commit() \ No newline at end of file From 7c3f1fecb0c1db7a19fa518f9caad531a1f953ae Mon Sep 17 00:00:00 2001 From: Leimomi Bong Date: Thu, 3 Nov 2022 09:19:13 -1000 Subject: [PATCH 18/30] added to todo list for testing --- app/test_routes.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/test_routes.py b/app/test_routes.py index e69de29bb..34f191298 100644 --- a/app/test_routes.py +++ b/app/test_routes.py @@ -0,0 +1,7 @@ +""" +TODO: +- handle planets: (GET, 200) one and all +- validate planet (GET,200 - id) *** +- update planet (POST, 200) +- delete planet (DELETE, 200) +""" \ No newline at end of file From 266a6deb32817c76301c7d31f241d6ea4ab23f67 Mon Sep 17 00:00:00 2001 From: Leimomi Bong Date: Thu, 3 Nov 2022 13:57:08 -1000 Subject: [PATCH 19/30] two working test --- app/routes.py | 4 - app/test_routes.py | 7 -- app/tests/{test_config.py => conftest.py} | 24 ++---- app/tests/test_routes.py | 89 +++++++++++++++++++++++ coworking_agreement.md | 5 +- 5 files changed, 100 insertions(+), 29 deletions(-) delete mode 100644 app/test_routes.py rename app/tests/{test_config.py => conftest.py} (56%) create mode 100644 app/tests/test_routes.py diff --git a/app/routes.py b/app/routes.py index f1466221d..0334f6faa 100644 --- a/app/routes.py +++ b/app/routes.py @@ -9,10 +9,6 @@ def handle_planets(): request_body = request.get_json() - planet_response = [] - - name_query = request.args.get("name") - if request.method == "GET": name_query = request.args.get("name") if name_query: diff --git a/app/test_routes.py b/app/test_routes.py deleted file mode 100644 index 34f191298..000000000 --- a/app/test_routes.py +++ /dev/null @@ -1,7 +0,0 @@ -""" -TODO: -- handle planets: (GET, 200) one and all -- validate planet (GET,200 - id) *** -- update planet (POST, 200) -- delete planet (DELETE, 200) -""" \ No newline at end of file diff --git a/app/tests/test_config.py b/app/tests/conftest.py similarity index 56% rename from app/tests/test_config.py rename to app/tests/conftest.py index 8897d8d22..01fdbf825 100644 --- a/app/tests/test_config.py +++ b/app/tests/conftest.py @@ -1,9 +1,13 @@ import pytest from app import create_app from app import db +from app.models.planet import Planet from flask.signals import request_finished @pytest.fixture + + + def app(): app = create_app({"TESTING": True}) @@ -16,28 +20,16 @@ def expire_session(sender, response, **extra): yield app with app.app_context(): - db.drop_all + db.drop_all() @pytest.fixture def client(app): return app.test_client() @pytest.fixture -def save_planet(app): - test_planet1 = Planet({ - "color": "pink", - "is_dwarf": True, - "livability": 3, - "moons": 99, - "name": "Pretend Planet X" - }) - test_planet2 = Planet({ - "color": "purple", - "is_dwarf": False, - "livability": 7.4, - "moons": 1, - "name": "Planet Pretend Z" - }) +def saved_test_planets(app): + test_planet1 = Planet(color= "pink", is_dwarf= True, livability= 3, moons= 99, name= "Pretend Planet X") + test_planet2 = Planet(color= "purple", is_dwarf= False, livability= 7.4, moons= 1, name= "Planet Pretend Z") db.session.add_all([test_planet1, test_planet2]) db.session.commit() \ No newline at end of file diff --git a/app/tests/test_routes.py b/app/tests/test_routes.py new file mode 100644 index 000000000..66a8e5643 --- /dev/null +++ b/app/tests/test_routes.py @@ -0,0 +1,89 @@ + +""" +TODO: +- create a new planet ***DONE*** +- (GET, 200) one planet w/ ID ***DONE*** +- (GET, 200) all planet(s) +- update planet (POST, 200) +- delete planet (DELETE, 200) ***DONE*** +- validate planet (GET,200 - id) ***DONE*** +""" + +#INPROGRESS +# def test_get_all_planets_return_no_records(client): +# #pass +# #act +# response = client.get('/planets') +# response_body = response.get_json() + +# #assert +# assert response.status_code == 200 +# assert response_body == [] + +#INPROGRESS +# def test_get_all_planets(client, saved_test_planets): +# # pass +# #act +# response = client.get('/planets') +# # response_body = response.get_json() +# response_body = response.get_data(as_text=True) + +# #assert +# assert response.status_code == 200 +# assert response_body == [{ +# 'id': 1, +# 'color': 'pink', +# 'is_dwarf': True, +# 'livability': 3, +# 'moons': 99, +# 'name': 'Pretend Planet X' +# # "id": 1, +# # "color": "pink", +# # "is_dwarf": True, +# # "livability": 3, +# # "moons": 99, +# # "name": "Pretend Planet X" +# }, +# { +# "id": 2, +# "color": "purple", +# "is_dwarf": False, +# "livability": 7.4, +# "moons": 1, +# "name": "Planet Pretend Z" +# }] + +def test_get_one_book_by_id(client, saved_test_planets): + #pass + #act + response = client.get('/planets/1') + response_body = response.get_json() + + #assert + assert response.status_code == 200 + assert response_body == { + 'id': 1, + 'color': "pink", + 'is_dwarf': True, + 'livability': 3, + 'moons': 99, + 'name': "Pretend Planet X", + } + +def test_create_one_new_planet(client): + #pass + #act + response = client.post("/planets", json={ + "color": "green", + "is_dwarf": False, + "livability": 5.5, + "moons": 43, + "name": "New Pretend Planet Y", + }) + # response_body = response.get_json() + response_body = response.get_data(as_text=True) + + #assert + assert response.status_code == 201 + assert response_body == "Planet New Pretend Planet Y successfully created" + diff --git a/coworking_agreement.md b/coworking_agreement.md index 463598c27..acf3d64f3 100644 --- a/coworking_agreement.md +++ b/coworking_agreement.md @@ -21,5 +21,6 @@ Talk through each section with your partner. Add notes on what you discussed and *Other co-working agreements that were not captured in the above sections.* ## Signatures -______________ _______________ -Date: _________ +Leimomi Bong +Mishella Joy +Novemeber 2022 From 0c97dd59eaddcf4edaa4579bc11927856f1da2af Mon Sep 17 00:00:00 2001 From: Leimomi Bong Date: Thu, 3 Nov 2022 14:45:07 -1000 Subject: [PATCH 20/30] passing all pytest --- app/__init__.py | 15 +++--- app/tests/conftest.py | 5 +- app/tests/test_routes.py | 99 ++++++++++++++++++---------------------- 3 files changed, 56 insertions(+), 63 deletions(-) diff --git a/app/__init__.py b/app/__init__.py index 205b8e4c1..be4a741ca 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -11,20 +11,21 @@ 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'] = 'postgresql+psycopg2://postgres:postgres@localhost:5432/solar_system_development' + 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") + # 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) + from app.models.planet import Planet from .routes import planet_bp app.register_blueprint(planet_bp) - return app - \ No newline at end of file + return app \ No newline at end of file diff --git a/app/tests/conftest.py b/app/tests/conftest.py index 01fdbf825..db50580c7 100644 --- a/app/tests/conftest.py +++ b/app/tests/conftest.py @@ -28,8 +28,11 @@ def client(app): @pytest.fixture def saved_test_planets(app): + test_planet1 = Planet(color= "pink", is_dwarf= True, livability= 3, moons= 99, name= "Pretend Planet X") test_planet2 = Planet(color= "purple", is_dwarf= False, livability= 7.4, moons= 1, name= "Planet Pretend Z") db.session.add_all([test_planet1, test_planet2]) - db.session.commit() \ No newline at end of file + db.session.commit() + + return [test_planet1, test_planet2] \ No newline at end of file diff --git a/app/tests/test_routes.py b/app/tests/test_routes.py index 66a8e5643..d8eb1e13c 100644 --- a/app/tests/test_routes.py +++ b/app/tests/test_routes.py @@ -1,60 +1,43 @@ +from app.models.planet import Planet """ TODO: -- create a new planet ***DONE*** -- (GET, 200) one planet w/ ID ***DONE*** -- (GET, 200) all planet(s) -- update planet (POST, 200) -- delete planet (DELETE, 200) ***DONE*** -- validate planet (GET,200 - id) ***DONE*** +DONE - GET planets/1 to return a response that matches our fixture +DONE - POST /planets with JSON request body and returns 201 +DONE - GET planets/1 with no data in test database return 404 +DONE - GET planets with test data returns 200 with array including test data """ -#INPROGRESS -# def test_get_all_planets_return_no_records(client): -# #pass -# #act -# response = client.get('/planets') -# response_body = response.get_json() +def test_get_all_planets_in_database(client, saved_test_planets): + #pass + #act + response = client.get('/planets') + response_body = Planet.query.all() -# #assert -# assert response.status_code == 200 -# assert response_body == [] + #assert + assert response.status_code == 200 -#INPROGRESS -# def test_get_all_planets(client, saved_test_planets): -# # pass -# #act -# response = client.get('/planets') -# # response_body = response.get_json() -# response_body = response.get_data(as_text=True) +def test_no_data_in_database_for_specific_endpoint(client): + # pass + #act + response = client.get('planets/3') + response_body = response.get_json() -# #assert -# assert response.status_code == 200 -# assert response_body == [{ -# 'id': 1, -# 'color': 'pink', -# 'is_dwarf': True, -# 'livability': 3, -# 'moons': 99, -# 'name': 'Pretend Planet X' -# # "id": 1, -# # "color": "pink", -# # "is_dwarf": True, -# # "livability": 3, -# # "moons": 99, -# # "name": "Pretend Planet X" -# }, -# { -# "id": 2, -# "color": "purple", -# "is_dwarf": False, -# "livability": 7.4, -# "moons": 1, -# "name": "Planet Pretend Z" -# }] + #assert + assert response.status_code == 404 -def test_get_one_book_by_id(client, saved_test_planets): - #pass +def test_get_planets_when_there_are_no_records_in_database(client): + # pass + #act + response = client.get('/planets') + response_body = response.get_json() + + #assert + assert response.status_code == 200 + assert response_body == [] + +def test_get_one_planet_by_id(client, saved_test_planets): + # pass #act response = client.get('/planets/1') response_body = response.get_json() @@ -71,19 +54,25 @@ def test_get_one_book_by_id(client, saved_test_planets): } def test_create_one_new_planet(client): - #pass + # pass #act - response = client.post("/planets", json={ + EXPECTED_PLANET = { "color": "green", "is_dwarf": False, - "livability": 5.5, + "livability": 6, "moons": 43, "name": "New Pretend Planet Y", - }) - # response_body = response.get_json() + } + + response = client.post("/planets", json=EXPECTED_PLANET) response_body = response.get_data(as_text=True) + actual_planet = Planet.query.get(1) #assert assert response.status_code == 201 - assert response_body == "Planet New Pretend Planet Y successfully created" - + assert response_body == f"Planet {EXPECTED_PLANET['name']} successfully created" + assert actual_planet.color == EXPECTED_PLANET["color"] + assert actual_planet.is_dwarf == EXPECTED_PLANET["is_dwarf"] + assert actual_planet.livability == EXPECTED_PLANET["livability"] + assert actual_planet.moons == EXPECTED_PLANET["moons"] + assert actual_planet.name == EXPECTED_PLANET["name"] \ No newline at end of file From 9bce6ccb4a494f6ddea6832844db0a7f56676ceb Mon Sep 17 00:00:00 2001 From: Leimomi Bong Date: Thu, 3 Nov 2022 14:49:45 -1000 Subject: [PATCH 21/30] sorry, beautified the pytest --- app/tests/test_routes.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/app/tests/test_routes.py b/app/tests/test_routes.py index d8eb1e13c..b3d2d7515 100644 --- a/app/tests/test_routes.py +++ b/app/tests/test_routes.py @@ -44,14 +44,7 @@ def test_get_one_planet_by_id(client, saved_test_planets): #assert assert response.status_code == 200 - assert response_body == { - 'id': 1, - 'color': "pink", - 'is_dwarf': True, - 'livability': 3, - 'moons': 99, - 'name': "Pretend Planet X", - } + assert response_body == {'id': 1, 'color': "pink", 'is_dwarf': True, 'livability': 3, 'moons': 99, 'name': "Pretend Planet X"} def test_create_one_new_planet(client): # pass From 83de4463ede5ad51c463ba1c30fe1b625b08a939 Mon Sep 17 00:00:00 2001 From: Leimomi Bong Date: Thu, 3 Nov 2022 16:06:40 -1000 Subject: [PATCH 22/30] cleaned up routes.py a bit --- app/routes.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/routes.py b/app/routes.py index 0334f6faa..800213478 100644 --- a/app/routes.py +++ b/app/routes.py @@ -5,7 +5,6 @@ planet_bp = Blueprint("planets", __name__, url_prefix = "/planets") @planet_bp.route("", methods=["POST", "GET"]) - def handle_planets(): request_body = request.get_json() @@ -52,13 +51,11 @@ def validate_planet_id(planet_id): if not planet: abort(make_response({"message":f"planet #{planet_id} doesn't exist."}, 404)) - return planet @planet_bp.route("/", methods = ["GET"]) def get_one_planet(planet_id): planet = validate_planet_id(planet_id) - return { "id": planet.id, "name": planet.name, From 4a398f9c073f279e0a824c7636e7ef20b50a2186 Mon Sep 17 00:00:00 2001 From: misha-joy Date: Thu, 3 Nov 2022 19:36:27 -0700 Subject: [PATCH 23/30] commit before pulling --- app/routes.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/routes.py b/app/routes.py index f1466221d..7b78bd72a 100644 --- a/app/routes.py +++ b/app/routes.py @@ -8,9 +8,7 @@ def handle_planets(): request_body = request.get_json() - planet_response = [] - name_query = request.args.get("name") if request.method == "GET": @@ -20,7 +18,7 @@ def handle_planets(): else: planets = Planet.query.all() - planet_response = [] + # planet_response = [] for planet in planets: planet_response.append({ "id": planet.id, From c8cd4910e3558a5348cd0606827ccc422f42f374 Mon Sep 17 00:00:00 2001 From: misha-joy Date: Thu, 3 Nov 2022 21:09:15 -0700 Subject: [PATCH 24/30] adds test_model file with tests and helper function to_dict --- app/models/planet.py | 13 ++++++- app/routes.py | 40 +++++++++++--------- app/tests/test_models.py | 80 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+), 18 deletions(-) create mode 100644 app/tests/test_models.py diff --git a/app/models/planet.py b/app/models/planet.py index aa07c7a7f..6dabb31b7 100644 --- a/app/models/planet.py +++ b/app/models/planet.py @@ -6,4 +6,15 @@ class Planet(db.Model): color = db.Column(db.String) livability = db.Column(db.Integer) moons = db.Column(db.Integer) - is_dwarf = db.Column(db.Boolean) \ No newline at end of file + is_dwarf = db.Column(db.Boolean) + + def to_dict(self): + planet_as_dict = {} + planet_as_dict["id"] = self.id + planet_as_dict["name"] = self.name + planet_as_dict["color"] = self.color + planet_as_dict["livability"] = self.livability + planet_as_dict["moons"] = self.moons + planet_as_dict["is_dwarf"] = self.is_dwarf + + return planet_as_dict \ No newline at end of file diff --git a/app/routes.py b/app/routes.py index dcd7466c8..661c4e533 100644 --- a/app/routes.py +++ b/app/routes.py @@ -17,17 +17,21 @@ def handle_planets(): else: planets = Planet.query.all() - # planet_response = [] for planet in planets: - planet_response.append({ - "id": planet.id, - "name": planet.name, - "color": planet.color, - "livability": planet.livability, - "moons": planet.moons, - "is_dwarf": planet.is_dwarf - }) + planet_response.append(planet.to_dict()) + return jsonify(planet_response) + + # ========REPLACED DICT BELOW IN HELPER FUNCTION IN PLANET.PY ========= + # { + # "id": planet.id, + # "name": planet.name, + # "color": planet.color, + # "livability": planet.livability, + # "moons": planet.moons, + # "is_dwarf": planet.is_dwarf + # }) + elif request.method == "POST": new_planet = Planet( @@ -58,14 +62,16 @@ def validate_planet_id(planet_id): @planet_bp.route("/", methods = ["GET"]) def get_one_planet(planet_id): planet = validate_planet_id(planet_id) - return { - "id": planet.id, - "name": planet.name, - "color": planet.color, - "livability": planet.livability, - "moons": planet.moons, - "is_dwarf": planet.is_dwarf - } + return planet.to_dict() + # =========== ALSO REPLACED WITH TO_DICT======== + # return { + # "id": planet.id, + # "name": planet.name, + # "color": planet.color, + # "livability": planet.livability, + # "moons": planet.moons, + # "is_dwarf": planet.is_dwarf + # } @planet_bp.route("/", methods = ["PUT"]) def update_planet(planet_id): diff --git a/app/tests/test_models.py b/app/tests/test_models.py new file mode 100644 index 000000000..bc98e3c67 --- /dev/null +++ b/app/tests/test_models.py @@ -0,0 +1,80 @@ +from app.models.planet import Planet + +def test_to_dict_no_missing_data(): + # Arrange + test_data = Planet( + id = 1, + color = "pink", + is_dwarf = True, + livability = 3, + moons = 99, + name = "Pretend Planet X") + # Act + result = test_data.to_dict() + + # Assert + assert len(result) == 6 + assert result["id"] == 1 + assert result["color"] == "pink" + assert result["livability"] == 3 + assert result["moons"] == 99 + assert result["name"] == "Pretend Planet X" + +def test_to_dict_missing_id(): + # Arrange + test_data = Planet( + color = "pink", + is_dwarf = True, + livability = 3, + moons = 99, + name = "Pretend Planet X") + # Act + result = test_data.to_dict() + + # Assert + assert len(result) == 6 + assert result["id"] is None + assert result["color"] == "pink" + assert result["livability"] == 3 + assert result["moons"] == 99 + assert result["name"] == "Pretend Planet X" + + + +def test_to_dict_missing_name(): + # Arrange + test_data = Planet(id = 1, + color = "pink", + is_dwarf = True, + livability = 3, + moons = 99) + + # Act + result = test_data.to_dict() + + # Assert + assert len(result) == 6 + assert result["id"] == 1 + assert result["color"] == "pink" + assert result["livability"] == 3 + assert result["moons"] == 99 + assert result["name"] is None + +def test_to_dict_missing_moons(): + # Arrange + test_data = Planet(id = 1, + color = "pink", + is_dwarf = True, + livability = 3, + name = "Pretend Planet X") + + # Act + result = test_data.to_dict() + + # Assert + assert len(result) == 6 + assert result["id"] == 1 + assert result["color"] == "pink" + assert result["livability"] == 3 + assert result["moons"] is None + assert result["name"] == "Pretend Planet X" \ No newline at end of file From 1eb2d9a644ce2f64661776ff7e6ea892c07d9bfe Mon Sep 17 00:00:00 2001 From: Leimomi Bong Date: Thu, 3 Nov 2022 21:25:52 -1000 Subject: [PATCH 25/30] Created a classmethod and refactored test_routes.py and routes.py --- app/models/planet.py | 12 +++- app/routes.py | 120 +++++++++++++++++---------------------- app/tests/conftest.py | 5 +- app/tests/test_routes.py | 19 ++----- 4 files changed, 67 insertions(+), 89 deletions(-) diff --git a/app/models/planet.py b/app/models/planet.py index 6dabb31b7..ebe439332 100644 --- a/app/models/planet.py +++ b/app/models/planet.py @@ -17,4 +17,14 @@ def to_dict(self): planet_as_dict["moons"] = self.moons planet_as_dict["is_dwarf"] = self.is_dwarf - return planet_as_dict \ No newline at end of file + return planet_as_dict + + @classmethod + def from_dict(cls, planet_data): + new_planet = Planet(name=planet_data["name"], + color=planet_data["color"], + moons=planet_data["moons"], + livability=planet_data["livability"], + is_dwarf=planet_data["is_dwarf"]) + + return new_planet \ No newline at end of file diff --git a/app/routes.py b/app/routes.py index 661c4e533..a4f4068e8 100644 --- a/app/routes.py +++ b/app/routes.py @@ -2,96 +2,78 @@ from app.models.planet import Planet from flask import Blueprint, jsonify, abort, make_response, request -planet_bp = Blueprint("planets", __name__, url_prefix = "/planets") +planet_bp = Blueprint("planets", __name__, url_prefix="/planets") -@planet_bp.route("", methods=["POST", "GET"]) -def handle_planets(): - request_body = request.get_json() - planet_response = [] - name_query = request.args.get("name") - - if request.method == "GET": - name_query = request.args.get("name") - if name_query: - planets = Planet.query.filter_by(name=name_query) - else: - planets = Planet.query.all() - - for planet in planets: - planet_response.append(planet.to_dict()) - - return jsonify(planet_response) - - # ========REPLACED DICT BELOW IN HELPER FUNCTION IN PLANET.PY ========= - # { - # "id": planet.id, - # "name": planet.name, - # "color": planet.color, - # "livability": planet.livability, - # "moons": planet.moons, - # "is_dwarf": planet.is_dwarf - # }) - - - elif request.method == "POST": - new_planet = Planet( - name = request_body["name"], - color = request_body["color"], - moons = request_body["moons"], - livability = request_body["livability"], - is_dwarf = request_body["is_dwarf"] - ) - - db.session.add(new_planet) - db.session.commit() - - return make_response(f"Planet {new_planet.name} successfully created", 201) - -def validate_planet_id(planet_id): +# HELPER FUNCTION #============ +def validate_model(cls, model_id): try: - planet_id = int(planet_id) + model_id = int(model_id) except: - abort(make_response({"message":f"planet #{planet_id} is invalid, please search by planet_id."}, 400)) + abort(make_response({"message":f"the planet {cls.__name__} {model_id} is invalid, please search by planet_id."}, 400)) - planet = Planet.query.get(planet_id) + planet = cls.query.get(model_id) if not planet: - abort(make_response({"message":f"planet #{planet_id} doesn't exist."}, 404)) + abort(make_response({"message":f"the planet {cls.__name__} {model_id} doesn't exist."}, 404)) return planet -@planet_bp.route("/", methods = ["GET"]) -def get_one_planet(planet_id): - planet = validate_planet_id(planet_id) +# MAIN FUNCTIONS #============ +@planet_bp.route("/", methods = ["GET"]) +def get_one_planet(model_id): + planet = validate_model(Planet, model_id) + # planet = cls.query.get(model_id) return planet.to_dict() - # =========== ALSO REPLACED WITH TO_DICT======== - # return { - # "id": planet.id, - # "name": planet.name, - # "color": planet.color, - # "livability": planet.livability, - # "moons": planet.moons, - # "is_dwarf": planet.is_dwarf - # } - -@planet_bp.route("/", methods = ["PUT"]) -def update_planet(planet_id): - planet = validate_planet_id(planet_id) +@planet_bp.route("", methods=["GET"]) +def get_all_planets(): + name_query = request.args.get("name") + if name_query: + planets = Planet.query.filter_by(name=name_query) + else: + planets = Planet.query.all() + + planet_response = [] + for planet in planets: + planet_response.append(planet.to_dict()) + return jsonify(planet_response) + +@planet_bp.route("", methods=["POST"]) +def create_new_planet(): request_body = request.get_json() + new_planet = Planet.from_dict(request_body) + + #REFACTOR USING A CLS?======== + # new_planet = Planet( + # name = request_body["name"], + # color = request_body["color"], + # moons = request_body["moons"], + # livability = request_body["livability"], + # is_dwarf = request_body["is_dwarf"]) + + db.session.add(new_planet) + db.session.commit() + + return make_response(f"Planet {new_planet.name} successfully created", 201) +@planet_bp.route("/", methods = ["PUT"]) +def update_planet(model_id): + planet = validate_model(Planet, model_id) + request_body = request.get_json() + planet = Planet.from_dict(request_body) # NEED TO FIX THIS LINE + planet.name = request_body["name"], planet.color = request_body["color"], planet.moons = request_body["moons"], - planet.livability = request_body["livability"] + planet.livability = request_body["livability"], planet.is_dwarf = request_body["is_dwarf"] db.session.commit() return make_response(f"Planet #{planet.id} successfully updated.") -@planet_bp.route("/", methods = ["DELETE"]) -def delete_planet(planet_id): - planet = validate_planet_id(planet_id) +@planet_bp.route("/", methods = ["DELETE"]) +def delete_planet(model_id): + planet = validate_model(Planet, model_id) db.session.delete(planet) db.session.commit() diff --git a/app/tests/conftest.py b/app/tests/conftest.py index db50580c7..7ba42a300 100644 --- a/app/tests/conftest.py +++ b/app/tests/conftest.py @@ -5,9 +5,6 @@ from flask.signals import request_finished @pytest.fixture - - - def app(): app = create_app({"TESTING": True}) @@ -35,4 +32,4 @@ def saved_test_planets(app): db.session.add_all([test_planet1, test_planet2]) db.session.commit() - return [test_planet1, test_planet2] \ No newline at end of file + # return [test_planet1, test_planet2] \ No newline at end of file diff --git a/app/tests/test_routes.py b/app/tests/test_routes.py index b3d2d7515..61fc1bedd 100644 --- a/app/tests/test_routes.py +++ b/app/tests/test_routes.py @@ -1,15 +1,8 @@ +import pytest +from app import db from app.models.planet import Planet -""" -TODO: -DONE - GET planets/1 to return a response that matches our fixture -DONE - POST /planets with JSON request body and returns 201 -DONE - GET planets/1 with no data in test database return 404 -DONE - GET planets with test data returns 200 with array including test data -""" - def test_get_all_planets_in_database(client, saved_test_planets): - #pass #act response = client.get('/planets') response_body = Planet.query.all() @@ -17,8 +10,7 @@ def test_get_all_planets_in_database(client, saved_test_planets): #assert assert response.status_code == 200 -def test_no_data_in_database_for_specific_endpoint(client): - # pass +def test_missing_planet_id(client): #act response = client.get('planets/3') response_body = response.get_json() @@ -26,8 +18,7 @@ def test_no_data_in_database_for_specific_endpoint(client): #assert assert response.status_code == 404 -def test_get_planets_when_there_are_no_records_in_database(client): - # pass +def test_get_planets_for_empty_database(client): #act response = client.get('/planets') response_body = response.get_json() @@ -37,7 +28,6 @@ def test_get_planets_when_there_are_no_records_in_database(client): assert response_body == [] def test_get_one_planet_by_id(client, saved_test_planets): - # pass #act response = client.get('/planets/1') response_body = response.get_json() @@ -47,7 +37,6 @@ def test_get_one_planet_by_id(client, saved_test_planets): assert response_body == {'id': 1, 'color': "pink", 'is_dwarf': True, 'livability': 3, 'moons': 99, 'name': "Pretend Planet X"} def test_create_one_new_planet(client): - # pass #act EXPECTED_PLANET = { "color": "green", From 437893dac27a6fbed142b4775cc77494cee9ee4b Mon Sep 17 00:00:00 2001 From: Leimomi Bong Date: Thu, 3 Nov 2022 21:35:38 -1000 Subject: [PATCH 26/30] Cleaned up files. Took out old code and comments. Updated unncessary imports. --- app/models/planet.py | 2 -- app/routes.py | 10 ---------- app/tests/conftest.py | 4 +--- app/tests/test_routes.py | 22 ++++++++++------------ 4 files changed, 11 insertions(+), 27 deletions(-) diff --git a/app/models/planet.py b/app/models/planet.py index ebe439332..ad07200a5 100644 --- a/app/models/planet.py +++ b/app/models/planet.py @@ -16,7 +16,6 @@ def to_dict(self): planet_as_dict["livability"] = self.livability planet_as_dict["moons"] = self.moons planet_as_dict["is_dwarf"] = self.is_dwarf - return planet_as_dict @classmethod @@ -26,5 +25,4 @@ def from_dict(cls, planet_data): moons=planet_data["moons"], livability=planet_data["livability"], is_dwarf=planet_data["is_dwarf"]) - return new_planet \ No newline at end of file diff --git a/app/routes.py b/app/routes.py index a4f4068e8..a6151a70e 100644 --- a/app/routes.py +++ b/app/routes.py @@ -4,7 +4,6 @@ planet_bp = Blueprint("planets", __name__, url_prefix="/planets") -# HELPER FUNCTION #============ def validate_model(cls, model_id): try: model_id = int(model_id) @@ -17,7 +16,6 @@ def validate_model(cls, model_id): abort(make_response({"message":f"the planet {cls.__name__} {model_id} doesn't exist."}, 404)) return planet -# MAIN FUNCTIONS #============ @planet_bp.route("/", methods = ["GET"]) def get_one_planet(model_id): planet = validate_model(Planet, model_id) @@ -41,14 +39,6 @@ def get_all_planets(): def create_new_planet(): request_body = request.get_json() new_planet = Planet.from_dict(request_body) - - #REFACTOR USING A CLS?======== - # new_planet = Planet( - # name = request_body["name"], - # color = request_body["color"], - # moons = request_body["moons"], - # livability = request_body["livability"], - # is_dwarf = request_body["is_dwarf"]) db.session.add(new_planet) db.session.commit() diff --git a/app/tests/conftest.py b/app/tests/conftest.py index 7ba42a300..4baf70fde 100644 --- a/app/tests/conftest.py +++ b/app/tests/conftest.py @@ -30,6 +30,4 @@ def saved_test_planets(app): test_planet2 = Planet(color= "purple", is_dwarf= False, livability= 7.4, moons= 1, name= "Planet Pretend Z") db.session.add_all([test_planet1, test_planet2]) - db.session.commit() - - # return [test_planet1, test_planet2] \ No newline at end of file + db.session.commit() \ No newline at end of file diff --git a/app/tests/test_routes.py b/app/tests/test_routes.py index 61fc1bedd..ffa6d7451 100644 --- a/app/tests/test_routes.py +++ b/app/tests/test_routes.py @@ -1,43 +1,41 @@ -import pytest -from app import db from app.models.planet import Planet def test_get_all_planets_in_database(client, saved_test_planets): - #act + # Act response = client.get('/planets') response_body = Planet.query.all() - #assert + # Assert assert response.status_code == 200 def test_missing_planet_id(client): - #act + # Act response = client.get('planets/3') response_body = response.get_json() - #assert + # Assert assert response.status_code == 404 def test_get_planets_for_empty_database(client): - #act + # Act response = client.get('/planets') response_body = response.get_json() - #assert + # Assert assert response.status_code == 200 assert response_body == [] def test_get_one_planet_by_id(client, saved_test_planets): - #act + # Act response = client.get('/planets/1') response_body = response.get_json() - #assert + # Assert assert response.status_code == 200 assert response_body == {'id': 1, 'color': "pink", 'is_dwarf': True, 'livability': 3, 'moons': 99, 'name': "Pretend Planet X"} def test_create_one_new_planet(client): - #act + # Act EXPECTED_PLANET = { "color": "green", "is_dwarf": False, @@ -50,7 +48,7 @@ def test_create_one_new_planet(client): response_body = response.get_data(as_text=True) actual_planet = Planet.query.get(1) - #assert + # Assert assert response.status_code == 201 assert response_body == f"Planet {EXPECTED_PLANET['name']} successfully created" assert actual_planet.color == EXPECTED_PLANET["color"] From 375836c88a8852771ac4e537367a636de73ffaea Mon Sep 17 00:00:00 2001 From: misha-joy Date: Fri, 4 Nov 2022 11:10:05 -0700 Subject: [PATCH 27/30] edits to update_planet --- app/routes.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/routes.py b/app/routes.py index a6151a70e..0dbe771f5 100644 --- a/app/routes.py +++ b/app/routes.py @@ -59,13 +59,13 @@ def update_planet(model_id): db.session.commit() - return make_response(f"Planet #{planet.id} successfully updated.") + return make_response(f"Planet #{model_id} successfully updated.") @planet_bp.route("/", methods = ["DELETE"]) def delete_planet(model_id): planet = validate_model(Planet, model_id) - db.session.delete(planet) db.session.commit() - return make_response(f"Planet #{planet.id} successfully deleted.") \ No newline at end of file + return make_response(f"Planet #{model_id} successfully deleted.") + \ No newline at end of file From 71436711c2d61013563f8e40c6c8c4eea8cf3392 Mon Sep 17 00:00:00 2001 From: misha-joy Date: Fri, 4 Nov 2022 11:20:11 -0700 Subject: [PATCH 28/30] deleted line in update planet-- works now --- app/routes.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/routes.py b/app/routes.py index 0dbe771f5..c54676817 100644 --- a/app/routes.py +++ b/app/routes.py @@ -49,8 +49,7 @@ def create_new_planet(): def update_planet(model_id): planet = validate_model(Planet, model_id) request_body = request.get_json() - planet = Planet.from_dict(request_body) # NEED TO FIX THIS LINE - + planet.name = request_body["name"], planet.color = request_body["color"], planet.moons = request_body["moons"], @@ -68,4 +67,3 @@ def delete_planet(model_id): db.session.commit() return make_response(f"Planet #{model_id} successfully deleted.") - \ No newline at end of file From f59fe563451f0bba14579d520b5fc7a7c8768319 Mon Sep 17 00:00:00 2001 From: Leimomi Bong Date: Mon, 7 Nov 2022 09:52:07 -1000 Subject: [PATCH 29/30] Procfil creation --- Procfile | 1 + 1 file changed, 1 insertion(+) create mode 100644 Procfile diff --git a/Procfile b/Procfile new file mode 100644 index 000000000..62e430aca --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: gunicorn 'app:create_app()' \ No newline at end of file From 6d9f2eff496d8ed5b42beb92cd4dff61adbdf9cd Mon Sep 17 00:00:00 2001 From: Leimomi Bong Date: Mon, 7 Nov 2022 10:16:38 -1000 Subject: [PATCH 30/30] "hm" --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 1eeabccdc..517b98b2d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,6 +9,7 @@ coverage==6.5.0 Flask==1.1.2 Flask-Migrate==2.6.0 Flask-SQLAlchemy==2.4.4 +gunicorn==20.1.0 idna==2.10 iniconfig==1.1.1 itsdangerous==1.1.0