Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add get and count methods #3688

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@

Jennifer Huang <[email protected]>
Alexa Orrico <[email protected]>
Joann Vuong <[email protected]>
Joann Vuong <[email protected]>
Mark Manani <[email protected]>
Empty file added api/__init__.py
Empty file.
Empty file added api/v1/__init__.py
Empty file.
28 changes: 28 additions & 0 deletions api/v1/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/python3
"""Flask application"""

from flask import Flask, jsonify
from models import storage
from api.v1.views import app_views
import os

app = Flask(__name__)
app.register_blueprint(app_views)


@app.teardown_appcontext
def teardown(exception):
"""Method to handle teardown, closing the storage"""
storage.close()


@app.errorhandler(404)
def not_found(error):
"""Handler for 404 errors that returns a JSON response"""
return jsonify({"error": "Not found"}), 404


if __name__ == "__main__":
host = os.getenv('HBNB_API_HOST', '0.0.0.0')
port = int(os.getenv('HBNB_API_PORT', 5000))
app.run(host=host, port=port, threaded=True)
10 changes: 10 additions & 0 deletions api/v1/views/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/python3
"""Blueprint setup"""

from flask import Blueprint

app_views = Blueprint('app_views', __name__, url_prefix='/api/v1')

# Import routes so they are registered with the Blueprint
from api.v1.views.index import *
from api.v1.views.states import *
26 changes: 26 additions & 0 deletions api/v1/views/index.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/python3
"""Index route for the API"""

from flask import jsonify
from models import storage
from api.v1.views import app_views


@app_views.route('/status', methods=['GET'])
def status():
"""Returns the status of the API"""
return jsonify({"status": "OK"})


@app_views.route('/stats', methods=['GET'], strict_slashes=False)
def stats():
"""Retrieves the number of each objects by type"""
stats = {
"amenities": storage.count("Amenity"),
"cities": storage.count("City"),
"places": storage.count("Place"),
"reviews": storage.count("Review"),
"states": storage.count("State"),
"users": storage.count("User")
}
return jsonify(stats)
64 changes: 64 additions & 0 deletions api/v1/views/states.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/usr/bin/python3
"""State view for handling all default RESTful API actions"""
from flask import jsonify, abort, request, make_response
from models import storage
from models.state import State
from api.v1.views import app_views


@app_views.route('/states', methods=['GET'], strict_slashes=False)
def get_states():
"""Retrieves the list of all State objects"""
states = storage.all(State).values()
return jsonify([state.to_dict() for state in states])


@app_views.route('/states/<state_id>', methods=['GET'], strict_slashes=False)
def get_state(state_id):
"""Retrieves a State object"""
state = storage.get(State, state_id)
if not state:
abort(404)
return jsonify(state.to_dict())


@app_views.route('states/<state_id>', methods=['DELETE'], strict_slashes=False)
def delete_state(state_id):
"""Deletes a State object"""
state = storage.get(State, state_id)
if not state:
abort(404)
storage.delete(state)
storage.save()
return jsonify({}), 200


@app_views.route('/states', methods=['POST'], strict_slashes=False)
def create_state():
"""Creates a State"""
if not request.json:
abort(400, description="Not a JSON")
if 'name' not in request.json(force=True, silent=True):
abort(400, description="Missing name")
new_state = State(**request.get_json())
storage.new(new_state)
storage.save()
return jsonify(new_state.to_dict()), 201


@app_views.route('/states/<state_id>', methods=['PUT'], strict_slashes=False)
def update_state(state_id):
"""Updates a State object"""
state = storage.get(State, state_id)
if not state:
abort(404)
if not request.json():
abort(400, description="Not a JSON")

ignore_keys = ['id', 'created_at', 'updated_at']
data = request.get_json()
for key, value in data.items():
if key not in ignore_keys:
setattr(state, key, value)
storage.save()
return jsonify(state.to_dict()), 200
11 changes: 11 additions & 0 deletions models/engine/db_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,14 @@ def reload(self):
def close(self):
"""call remove() method on the private session attribute"""
self.__session.remove()

def get(self, cls, id):
"""Retrieve one object"""
if cls and id:
key = "{}.{}".format(cls.__name__, id)
return self.all(cls).get(key, None)
return None

def count(self, cls=None):
"""Count the number of objects in storage"""
return len(self.all(cls))
11 changes: 11 additions & 0 deletions models/engine/file_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,14 @@ def delete(self, obj=None):
def close(self):
"""call reload() method for deserializing the JSON file to objects"""
self.reload()

def get(self, cls, id):
"""Retrieve one object"""
if cls and id:
key = "{}.{}".format(cls.__name__, id)
return self.all(cls).get(key, None)
return None

def count(self, cls=None):
"""Count the number of objects in storage"""
return len(self.all(cls))
29 changes: 29 additions & 0 deletions tests/test_models/test_engine/test_db_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,35 @@ def test_dbs_func_docstrings(self):
self.assertTrue(len(func[1].__doc__) >= 1,
"{:s} method needs a docstring".format(func[0]))

def test_count(self):
"""Test the count method."""
all_objects_count = storage.count()
state_objects_count = storage.count(State)
city_objects_count = storage.count(City)

self.assertEqual(all_objects_count, 2)
self.assertEqual(state_objects_count, 1)
self.assertEqual(city_objects_count, 1)

# Adding another state and testing the count again
new_state = State(name="Nevada")
new_state.save()
self.assertEqual(storage.count(State), 2)
new_state.delete()

def test_get(self):
"""Test the get method."""
state = storage.get(State, self.state.id)
self.assertIsNotNone(state)
self.assertEqual(state.id, self.state.id)

city = storage.get(City, self.city.id)
self.assertIsNotNone(city)
self.assertEqual(city.id, self.city.id)

non_existent = storage.get(State, "non-existent-id")
self.assertIsNone(non_existent)


class TestFileStorage(unittest.TestCase):
"""Test the FileStorage class"""
Expand Down
26 changes: 26 additions & 0 deletions tests/test_models/test_engine/test_file_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,32 @@ def test_fs_func_docstrings(self):
self.assertTrue(len(func[1].__doc__) >= 1,
"{:s} method needs a docstring".format(func[0]))

def test_count(self):
"""Test the count method."""
all_objects_count = storage.count()
state_objects_count = storage.count(State)
city_objects_count = storage.count(City)

self.assertEqual(all_objects_count, 2)
self.assertEqual(state_objects_count, 1)
self.assertEqual(city_objects_count, 1)

# Adding another state and testing the count again
new_state = State(name="Nevada")
new_state.save()
self.assertEqual(storage.count(State), 2)
new_state.delete()

def test_get(self):
"""Test the get method."""
state = storage.get(State, self.state.id)
self.assertIsNotNone(state)
self.assertEqual(state.id, self.state.id)

city = storage.get(City, self.city.id)
self.assertIsNotNone(city)
self.assertEqual(city.id, self.city.id)


class TestFileStorage(unittest.TestCase):
"""Test the FileStorage class"""
Expand Down