1- # Copyright 2016, 2019 John J. Rofrano. All Rights Reserved.
1+ # Copyright 2016, 2024 John J. Rofrano. All Rights Reserved.
22#
33# Licensed under the Apache License, Version 2.0 (the "License");
44# you may not use this file except in compliance with the License.
1515"""
1616Pet Store Service
1717
18- Paths:
19- ------
20- GET /pets - Returns a list all of the Pets
21- GET /pets/{id} - Returns the Pet with a given id number
22- POST /pets - creates a new Pet record in the database
23- PUT /pets/{id} - updates a Pet record in the database
24- DELETE /pets/{id} - deletes a Pet record in the database
18+ This service implements a REST API that allows you to Create, Read, Update
19+ and Delete Pets from the inventory of pets in the PetShop
2520"""
2621
2722from flask import jsonify , request , url_for , abort
3328######################################################################
3429# GET HEALTH CHECK
3530######################################################################
36- @app .route ("/healthcheck " )
37- def healthcheck ():
31+ @app .route ("/health " )
32+ def health_check ():
3833 """Let them know our heart is still beating"""
3934 return jsonify (status = 200 , message = "Healthy" ), status .HTTP_200_OK
4035
@@ -63,7 +58,10 @@ def index():
6358def list_pets ():
6459 """Returns all of the Pets"""
6560 app .logger .info ("Request for pet list" )
61+
6662 pets = []
63+
64+ # See if any query filters were passed in
6765 category = request .args .get ("category" )
6866 name = request .args .get ("name" )
6967 if category :
@@ -79,7 +77,7 @@ def list_pets():
7977
8078
8179######################################################################
82- # RETRIEVE A PET
80+ # READ A PET
8381######################################################################
8482@app .route ("/pets/<int:pet_id>" , methods = ["GET" ])
8583def get_pets (pet_id ):
@@ -89,32 +87,35 @@ def get_pets(pet_id):
8987 This endpoint will return a Pet based on it's id
9088 """
9189 app .logger .info ("Request for pet with id: %s" , pet_id )
90+
9291 pet = Pet .find (pet_id )
9392 if not pet :
94- abort (status .HTTP_404_NOT_FOUND , f"Pet with id '{ pet_id } ' was not found." )
93+ error (status .HTTP_404_NOT_FOUND , f"Pet with id '{ pet_id } ' was not found." )
9594
9695 app .logger .info ("Returning pet: %s" , pet .name )
9796 return jsonify (pet .serialize ()), status .HTTP_200_OK
9897
9998
10099######################################################################
101- # ADD A NEW PET
100+ # CREATE A NEW PET
102101######################################################################
103102@app .route ("/pets" , methods = ["POST" ])
104103def create_pets ():
105104 """
106105 Creates a Pet
106+
107107 This endpoint will create a Pet based the data in the body that is posted
108108 """
109109 app .logger .info ("Request to create a pet" )
110110 check_content_type ("application/json" )
111+
111112 pet = Pet ()
112113 pet .deserialize (request .get_json ())
113114 pet .create ()
114115 message = pet .serialize ()
115116 location_url = url_for ("get_pets" , pet_id = pet .id , _external = True )
116117
117- app .logger .info ("Pet with ID [%s] created." , pet .id )
118+ app .logger .info ("Pet with ID: %d created." , pet .id )
118119 return jsonify (message ), status .HTTP_201_CREATED , {"Location" : location_url }
119120
120121
@@ -128,18 +129,18 @@ def update_pets(pet_id):
128129
129130 This endpoint will update a Pet based the body that is posted
130131 """
131- app .logger .info ("Request to update pet with id: %s " , pet_id )
132+ app .logger .info ("Request to update pet with id: %d " , pet_id )
132133 check_content_type ("application/json" )
133134
134135 pet = Pet .find (pet_id )
135136 if not pet :
136- abort (status .HTTP_404_NOT_FOUND , f"Pet with id '{ pet_id } ' was not found." )
137+ error (status .HTTP_404_NOT_FOUND , f"Pet with id: '{ pet_id } ' was not found." )
137138
138139 pet .deserialize (request .get_json ())
139140 pet .id = pet_id
140141 pet .update ()
141142
142- app .logger .info ("Pet with ID [%s] updated." , pet .id )
143+ app .logger .info ("Pet with ID: %d updated." , pet .id )
143144 return jsonify (pet .serialize ()), status .HTTP_200_OK
144145
145146
@@ -153,12 +154,13 @@ def delete_pets(pet_id):
153154
154155 This endpoint will delete a Pet based the id specified in the path
155156 """
156- app .logger .info ("Request to delete pet with id: %s" , pet_id )
157+ app .logger .info ("Request to delete pet with id: %d" , pet_id )
158+
157159 pet = Pet .find (pet_id )
158160 if pet :
159161 pet .delete ()
160162
161- app .logger .info ("Pet with ID [%s] delete complete." , pet_id )
163+ app .logger .info ("Pet with ID: %d delete complete." , pet_id )
162164 return "" , status .HTTP_204_NO_CONTENT
163165
164166
@@ -167,14 +169,22 @@ def delete_pets(pet_id):
167169######################################################################
168170@app .route ("/pets/<int:pet_id>/purchase" , methods = ["PUT" ])
169171def purchase_pets (pet_id ):
170- """Purchasing a Pet makes it unavailable"""
172+ """
173+ Purchasing a Pet
174+
175+ This endpoint will purchase a pet makes it unavailable
176+ """
177+ app .logger .info ("Request to purchase pet with id: %d" , pet_id )
178+
171179 pet = Pet .find (pet_id )
172180 if not pet :
173- abort (status .HTTP_404_NOT_FOUND , f"Pet with id '{ pet_id } ' was not found." )
181+ error (status .HTTP_404_NOT_FOUND , f"Pet with id '{ pet_id } ' was not found." )
182+
183+ # you can only purchase pets that are available
174184 if not pet .available :
175- abort (
185+ error (
176186 status .HTTP_409_CONFLICT ,
177- f"Pet with id '{ pet_id } ' is not available." ,
187+ f"Pet with ID: '{ pet_id } ' is not available." ,
178188 )
179189
180190 # At this point you would execute code to purchase the pet
@@ -183,6 +193,7 @@ def purchase_pets(pet_id):
183193 pet .available = False
184194 pet .update ()
185195
196+ app .logger .info ("Pet with ID: %d has been purchased." , pet_id )
186197 return pet .serialize (), status .HTTP_200_OK
187198
188199
@@ -191,11 +202,14 @@ def purchase_pets(pet_id):
191202######################################################################
192203
193204
205+ ######################################################################
206+ # Checks the ContentType of a request
207+ ######################################################################
194208def check_content_type (content_type ):
195209 """Checks that the media type is correct"""
196210 if "Content-Type" not in request .headers :
197211 app .logger .error ("No Content-Type specified." )
198- abort (
212+ error (
199213 status .HTTP_415_UNSUPPORTED_MEDIA_TYPE ,
200214 f"Content-Type must be { content_type } " ,
201215 )
@@ -204,7 +218,16 @@ def check_content_type(content_type):
204218 return
205219
206220 app .logger .error ("Invalid Content-Type: %s" , request .headers ["Content-Type" ])
207- abort (
221+ error (
208222 status .HTTP_415_UNSUPPORTED_MEDIA_TYPE ,
209223 f"Content-Type must be { content_type } " ,
210224 )
225+
226+
227+ ######################################################################
228+ # Logs error messages before aborting
229+ ######################################################################
230+ def error (status_code , reason ):
231+ """Logs the error and then aborts"""
232+ app .logger .error (reason )
233+ abort (status_code , reason )
0 commit comments