Skip to content

C22, Alejandra and Maybellene, part 1#1

Open
mayboolean wants to merge 15 commits intoAda-C22:mainfrom
222alle111:main
Open

C22, Alejandra and Maybellene, part 1#1
mayboolean wants to merge 15 commits intoAda-C22:mainfrom
222alle111:main

Conversation

@mayboolean
Copy link
Copy Markdown

No description provided.

Copy link
Copy Markdown

@anselrognlie anselrognlie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're off to a good start. All the Flask-specific code is on the right on track. There are just a few general Python points to review.

@@ -0,0 +1,20 @@
class Planet:
def __init__(self, id, name, description, size_dia_km):
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Great idea to include more specifics about what "size" means (the diameter in kilometers). This is often useful to do with a data value that's otherwise just a number.

self.id = id
self.name = name
self.description = description
self.size = size_dia_km
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider carrying the additional detail in the name of the attribute itself.

self.description = description
self.size = size_dia_km

def to_dict(self):
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Nice job incorporating this refactor from the live code.

return dict(
id=self.id,
name=self.name,
desc=self.description,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless there's a strong need to, resist the temptation to shorten the name in the dictionary-ified version.

planets = [
Planet(1,"some_planet", "rocky, no signs of life", 100),
Planet(2, "Earth", "with lifeforms, water and land", 5000),
Planet(3, "Pluto", "still a planet", 200)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disagree. 😆

from app.models.planet import planets

# created blueprint
planets_bp = Blueprint("planets_bp",__name__, url_prefix=("/planets"))
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no need to wrap the url_prefix value in ().

Be sure to include a space after ,

planets_bp = Blueprint("planets_bp", __name__, url_prefix="/planets")

Comment on lines +9 to +12
results_list = []

for planet in planets:
results_list.append(planet.to_dict())
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a great opportunity to try to use a list comprehension here.

    results_list = [planet.to_dict() for planet in planets]

planet_id = int(planet_id)
except ValueError:
abort(make_response({"message": f"planet {planet_id} is an invalid ID"}, 400))
for planet in planets:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding a blank line between this line and the previous to help separate these two sections of code that focus on two different things.

Comment on lines +29 to +30
else:
abort(make_response({"message": f"planet {planet_id} not found"}, 404)) No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Python does support else blocks on loops, but as a syntax pattern that's relatively uncommon, I generally avoid it. It's also not necessary here. An else block is run if a loop runs all the way to completion. Since the only way the loop wouldn't run to completion is by finding (and returning) the desired planet, the only way we can reach this code at all is if the loop runs to completion.

We can simplify this by removing the else: an unindenting its block.

Copy link
Copy Markdown

@anselrognlie anselrognlie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work making the modifications to connect your API to your database, expanding the endpoints, and adding some tests. Make sure you're committing any additional migrations (it looks like you update the planet model, but the migration still represents an older schema). Otherwise, everything here should be able to be applied to your task list implementations.



def create_app(test_config=None):
def create_app(config=None):
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Thanks for renaming this. This param could be used for scenarios other than testing (the name was left over from the previous curriculum).

from flask import Flask
from .routes.planet_routes import planets_bp
from .db import db, migrate
from .models import planet
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that once we have the Planet model imported in the routes, and the routes are imported here, we don't technically need to import the planet module here. If you find the fact that VS Code shows this as not being used, it would now be safe to remove.

# registered the planets blueprint with the app

app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get('SQLALCHEMY_DATABASE_URI')
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Loads the connection string from the environment (provided with our .env during development).

from sqlalchemy.orm import Mapped, mapped_column
from ..db import db

class Planet(db.Model):
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Nice modifications to associate this model type with our database.

def create_planet():
request_body = request.get_json()
name = request_body["name"]
description= request_body["description"]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Make sure to include spaces around assignments

    description = request_body["description"]



@pytest.fixture
def three_saved_planets(app):
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Nice test fixture adding three records.

planet3 = Planet(name="Pluto", description="still a planet", size_dia_km=200)

db.session.add_all([planet1, planet2, planet3])
db.session.commit() No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider returning the list of records. The return value becomes the value passed in for the fixture in a test. By returning the records, we could use their ids in the dependent tests. While our approach of dropping and recreating the database for each test should guarantee that these records are ids 1, 2, and 3, we could use the ids actually assigned by the database to remove that assumption.



def test_get_single_planet(client, three_saved_planets):
response = client.get("/planets/1")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we returned the record list from the fixture, then we could write this line as

    response = client.get(f"/planets/{three_saved_planets[0].id}")


assert response.status_code == 200
assert response_body == {
"id": 1,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we returned the record list from the fixture, then we could check the id as

        "id": three_saved_planets[0].id,

response = client.get("/planets/1")
response_body = response.get_json()

assert response.status_code == 404
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👀 Be sure to check that the expected response body is also returned.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants