Repository: HTTP-APIs/hydrus
Pull request #117 (2018-02-23 10:28:36)

Fixed the Code according to Conventions (PEP-8).
Fixes: #79
Signed-off-by: Yash Ladha <yashladhapankajladha123@gmail.com>

(cherry picked from commit ccd42a0)
Signed-off-by: Yash Ladha <yashladhapankajladha123@gmail.com>

<!-- Please create/claim an issue before sending a PR -->
<!-- Add issue number (Eg: fixes #123) -->


### Checklist
- [x] My branch is up-to-date with upstream/develop branch.
- [x] Everything works and tested for Python 3.5.2 and above.

### Description
Changes the code to follow pep-8 convention.


Mec-iS: Cool, thanks. Once this is merged we can start improving the docstrings.
yashLadha: Sure @xadahiya :+1: 
Mec-iS: @yashLadha You can confirm that tests pass smoothly?
xadahiya: @yashLadha submit the test logs to confirm everything is working after changes.

Patch:
diff --git a/.gitignore b/.gitignore
index e7218ac..b5403b8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,7 @@
 # Byte-compiled / optimized / DLL files
+
+.idea/**
+
 __pycache__/
 *.py[cod]
 *$py.class
diff --git a/hydrus/app.py b/hydrus/app.py
index 8b5d484..78be629 100644
--- a/hydrus/app.py
+++ b/hydrus/app.py
@@ -1,444 +1,411 @@
-"""Main route for the applciation."""
-
-import json
-from flask import Flask, jsonify, request, abort
-from flask_restful import Api, Resource
-from flask_cors import CORS
-
-from hydrus.data import crud
-from hydrus.data.user import check_authorization
-from hydrus.utils import get_session, get_doc, get_api_name, get_hydrus_server_url, get_authentication
-
-from flask.wrappers import Response
-from typing import Dict, List, Any, Union
-
-
-def validObject(object_: Dict[str, Any]) -> bool:
-    """Check if the data passed in POST is of valid format or not."""
-    if "@type" in object_:
-        return True
-    return False
-
-
-def failed_authentication() -> Response:
-    """Return failed authentication object."""
-    message = {401: "Need credentials to authenticate"}
-    response = set_response_headers(jsonify(message), status_code=401,
-                                    headers=[{'WWW-Authenticate': 'Basic realm="Login Required"'}])
-    return response
-
-
-def set_response_headers(resp: Response, ct: str="application/ld+json", headers: List[Dict[str, Any]]=[], status_code: int=200) -> Response:
-    """Set the response headers."""
-    resp.status_code = status_code
-    for header in headers:
-        resp.headers[list(header.keys())[0]] = header[list(header.keys())[0]]
-    resp.headers['Content-type'] = ct
-    resp.headers['Link'] = '<' + get_hydrus_server_url() + \
-        get_api_name()+'/vocab>; rel="http://www.w3.org/ns/hydra/core#apiDocumentation"'
-    return resp
-
-
-def hydrafy(object_: Dict[str, Any]) -> Dict[str, Any]:
-    """Add hydra context to objects."""
-    object_["@context"] = "/"+get_api_name()+"/contexts/" + object_["@type"] + ".jsonld"
-    return object_
-
-
-def checkEndpoint(method: str, type_: str) -> bool:
-    """Check if endpoint and method is supported in the API."""
-    for endpoint in get_doc().entrypoint.entrypoint.supportedProperty:
-        if type_ == endpoint.name:
-            for operation in endpoint.supportedOperation:
-                if operation.method == method:
-                    return True
-    return False
-
-
-def getType(class_type: str, method: str) -> Any:
-    """Return the @type of object allowed for POST/PUT."""
-    for supportedOp in get_doc().parsed_classes[class_type]["class"].supportedOperation:
-        if supportedOp.method == method:
-            return supportedOp.expects.replace("vocab:", "")
-    # NOTE: Don't use split, if there are more than one substrings with 'vocab:' not everything will be returned.
-
-
-def checkClassOp(class_type: str, method: str) -> bool:
-    """Check if the Class supports the operation."""
-    for supportedOp in get_doc().parsed_classes[class_type]["class"].supportedOperation:
-        if supportedOp.method == method:
-            return True
-    return False
-
-
-class Index(Resource):
-    """Class for the EntryPoint."""
-
-    def get(self)-> Response:
-        """Return main entrypoint for the api."""
-        return set_response_headers(jsonify(get_doc().entrypoint.get()))
-
-
-class Vocab(Resource):
-    """Vocabulary for Hydra."""
-
-    def get(self) -> Response:
-        """Return the main hydra vocab."""
-        return set_response_headers(jsonify(get_doc().generate()))
-
-
-class Entrypoint(Resource):
-    """Hydra EntryPoint."""
-
-    def get(self) -> Response:
-        """Return application main Entrypoint."""
-        response = {"@context": get_doc().entrypoint.context.generate()}
-        return set_response_headers(jsonify(response))
-
-
-class Item(Resource):
-    """Handles all operations(GET, POST, PATCH, DELETE) on Items (item can be anything depending upon the vocabulary)."""
-
-    def get(self, id_: int, type_: str) -> Response:
-        """GET object with id = id_ from the database."""
-        if get_authentication():
-            if request.authorization is None:
-                return failed_authentication()
-            else:
-                try:
-                    auth = check_authorization(request, get_session())
-                    if auth is False:
-                        return failed_authentication()
-                except Exception as e:
-                    status_code, message = e.get_HTTP()  # type: ignore
-                    return set_response_headers(jsonify(message), status_code=status_code)
-
-        class_type = get_doc().collections[type_]["collection"].class_.title
-
-        if checkClassOp(class_type, "GET"):
-
-            try:
-                response = crud.get(id_, class_type, api_name=get_api_name(), session=get_session())
-                return set_response_headers(jsonify(hydrafy(response)))
-
-            except Exception as e:
-                status_code, message = e.get_HTTP() # type: ignore
-                return set_response_headers(jsonify(message), status_code=status_code)
-
-        abort(405)
-
-    def post(self, id_: int, type_: str) -> Response:
-        """Update object of type<type_> at ID<id_> with new object_ using HTTP POST."""
-        if get_authentication():
-            if request.authorization is None:
-                return failed_authentication()
-            else:
-                try:
-                    auth = check_authorization(request, get_session())
-                    if auth is False:
-                        return failed_authentication()
-                except Exception as e:
-                    status_code, message = e.get_HTTP()  # type: ignore
-                    return set_response_headers(jsonify(message), status_code=status_code)
-
-        class_type = get_doc().collections[type_]["collection"].class_.title
-
-        if checkClassOp(class_type, "POST"):
-
-            object_ = json.loads(request.data.decode('utf-8'))
-            obj_type = getType(class_type, "POST")
-
-            if validObject(object_):
-
-                if object_["@type"] == obj_type:
-                    try:
-                        object_id = crud.update(object_=object_, id_=id_, type_=object_["@type"], session=get_session(), api_name=get_api_name())
-                        headers_ = [{"Location": get_hydrus_server_url()+get_api_name()+"/"+type_+"/"+str(object_id)}]
-                        response = {"message": "Object with ID %s successfully updated" % (object_id)}
-                        return set_response_headers(jsonify(response), headers=headers_)
-
-                    except Exception as e:
-                        status_code, message = e.get_HTTP() # type: ignore
-                        return set_response_headers(jsonify(message), status_code=status_code)
-
-            return set_response_headers(jsonify({400: "Data is not valid"}), status_code=400)
-
-        abort(405)
-
-    def put(self, id_: int, type_: str) -> Response:
-        """Add new object_ optional <id_> parameter using HTTP PUT."""
-        if get_authentication():
-            if request.authorization is None:
-                return failed_authentication()
-            else:
-                try:
-                    auth = check_authorization(request, get_session())
-                    if auth is False:
-                        return failed_authentication()
-                except Exception as e:
-                    status_code, message = e.get_HTTP()  # type: ignore
-                    return set_response_headers(jsonify(message), status_code=status_code)
-
-        class_type = get_doc().collections[type_]["collection"].class_.title
-
-        if checkClassOp(class_type, "PUT"):
-
-            object_ = json.loads(request.data.decode('utf-8'))
-            obj_type = getType(class_type, "PUT")
-
-            if validObject(object_):
-
-                if object_["@type"] == obj_type:
-                    try:
-                        object_id = crud.insert(object_=object_, id_=id_, session=get_session())
-                        headers_ = [{"Location": get_hydrus_server_url()+get_api_name()+"/"+type_+"/"+str(object_id)}]
-                        response = {"message": "Object with ID %s successfully added" % (object_id)}
-                        return set_response_headers(jsonify(response), headers=headers_, status_code=201)
-
-                    except Exception as e:
-                        status_code, message = e.get_HTTP() # type: ignore
-                        return set_response_headers(jsonify(message), status_code=status_code)
-
-            return set_response_headers(jsonify({400: "Data is not valid"}), status_code=400)
-
-        abort(405)
-
-    def delete(self, id_: int, type_: str) -> Response:
-        """Delete object with id=id_ from database."""
-        if get_authentication():
-            if request.authorization is None:
-                return failed_authentication()
-            else:
-                try:
-                    auth = check_authorization(request, get_session())
-                    if auth is False:
-                        return failed_authentication()
-                except Exception as e:
-                    status_code, message = e.get_HTTP()  # type: ignore
-                    return set_response_headers(jsonify(message), status_code=status_code)
-
-        class_type = get_doc().collections[type_]["collection"].class_.title
-
-        if checkClassOp(class_type, "DELETE"):
-            try:
-                crud.delete(id_, class_type, session=get_session())
-                response = {"message": "Object with ID %s successfully deleted" % (id_)}
-                return set_response_headers(jsonify(response))
-
-            except Exception as e:
-                status_code, message = e.get_HTTP()  # type: ignore
-                return set_response_headers(jsonify(message), status_code=status_code)
-
-        abort(405)
-
-
-class ItemCollection(Resource):
-    """Handle operation related to ItemCollection (a collection of items)."""
-
-    def get(self, type_: str) -> Response:
-        """Retrieve a collection of items from the database."""
-        if get_authentication():
-            if request.authorization is None:
-                return failed_authentication()
-            else:
-                try:
-                    auth = check_authorization(request, get_session())
-                    if auth is False:
-                        return failed_authentication()
-                except Exception as e:
-                    status_code, message = e.get_HTTP()  # type: ignore
-                    return set_response_headers(jsonify(message), status_code=status_code)
-
-        if checkEndpoint("GET", type_):
-            # Collections
-            if type_ in get_doc().collections:
-
-                collection = get_doc().collections[type_]["collection"]
-                try:
-                    response = crud.get_collection(get_api_name(), collection.class_.title, session=get_session())
-                    return set_response_headers(jsonify(hydrafy(response)))
-
-                except Exception as e:
-                    status_code, message = e.get_HTTP() # type: ignore
-                    return set_response_headers(jsonify(message), status_code=status_code)
-
-            # Non Collection classes
-            elif type_ in get_doc().parsed_classes and type_+"Collection" not in get_doc().collections:
-                try:
-                    response = crud.get_single(type_, api_name=get_api_name(), session=get_session())
-                    return set_response_headers(jsonify(hydrafy(response)))
-
-                except Exception as e:
-                    status_code, message = e.get_HTTP() # type: ignore
-                    return set_response_headers(jsonify(message), status_code=status_code)
-
-        abort(405)
-
-    def put(self, type_: str) -> Response:
-        """Add item to ItemCollection."""
-        if get_authentication():
-            if request.authorization is None:
-                return failed_authentication()
-            else:
-                try:
-                    auth = check_authorization(request, get_session())
-                    if auth is False:
-                        return failed_authentication()
-                except Exception as e:
-                    status_code, message = e.get_HTTP()  # type: ignore
-                    return set_response_headers(jsonify(message), status_code=status_code)
-
-        if checkEndpoint("PUT", type_):
-            object_ = json.loads(request.data.decode('utf-8'))
-
-            # Collections
-            if type_ in get_doc().collections:
-
-                collection = get_doc().collections[type_]["collection"]
-                obj_type = collection.class_.title
-
-                if validObject(object_):
-
-                    if object_["@type"] == obj_type:
-                        try:
-                            object_id = crud.insert(object_=object_, session=get_session())
-                            headers_ = [{"Location": get_hydrus_server_url()+get_api_name()+"/"+type_+"/"+str(object_id)}]
-                            response = {"message": "Object with ID %s successfully deleted" % (object_id)}
-                            return set_response_headers(jsonify(response), headers=headers_, status_code=201)
-                        except Exception as e:
-                            status_code, message = e.get_HTTP() #type: ignore
-                            return set_response_headers(jsonify(message), status_code=status_code)
-
-                return set_response_headers(jsonify({400: "Data is not valid"}), status_code=400)
-
-            # Non Collection classes
-            elif type_ in get_doc().parsed_classes and type_+"Collection" not in get_doc().collections:
-                obj_type = getType(type_, "PUT")
-
-                if object_["@type"] == obj_type:
-
-                    if validObject(object_):
-                        try:
-                            object_id = crud.insert(object_=object_, session=get_session())
-                            headers_ = [{"Location": get_hydrus_server_url()+get_api_name()+"/"+type_+"/"}]
-                            response = {"message": "Object successfully added"}
-                            return set_response_headers(jsonify(response), headers=headers_, status_code=201)
-                        except Exception as e:
-                            status_code, message = e.get_HTTP() # type: ignore
-                            return set_response_headers(jsonify(message), status_code=status_code)
-
-                return set_response_headers(jsonify({400: "Data is not valid"}), status_code=400)
-
-        abort(405)
-
-    def post(self, type_: str) -> Response:
-        """Update Non Collection class item."""
-        if get_authentication():
-            if request.authorization is None:
-                return failed_authentication()
-            else:
-                try:
-                    auth = check_authorization(request, get_session())
-                    if auth is False:
-                        return failed_authentication()
-                except Exception as e:
-                    status_code, message = e.get_HTTP()  # type: ignore
-                    return set_response_headers(jsonify(message), status_code=status_code)
-
-        if checkEndpoint("POST", type_):
-            object_ = json.loads(request.data.decode('utf-8'))
-
-            if type_ in get_doc().parsed_classes and type_+"Collection" not in get_doc().collections:
-                obj_type = getType(type_, "POST")
-
-                if validObject(object_):
-
-                    if object_["@type"] == obj_type:
-                        # try:
-                            crud.update_single(object_=object_, session=get_session(), api_name=get_api_name())
-                            headers_ = [{"Location": get_hydrus_server_url()+get_api_name()+"/"+type_+"/"}]
-                            response = {"message": "Object successfully updated"}
-                            return set_response_headers(jsonify(response), headers=headers_)
-                        # except Exception as e:
-                        #     status_code, message = e.get_HTTP()
-                        #     return set_response_headers(jsonify(message), status_code=status_code)
-
-                return set_response_headers(jsonify({400: "Data is not valid"}), status_code=400)
-
-        abort(405)
-
-    def delete(self, type_: str) -> Response:
-        """Delete a non Collection class item."""
-        if get_authentication():
-            if request.authorization is None:
-                return failed_authentication()
-            else:
-                try:
-                    auth = check_authorization(request, get_session())
-                    if auth is False:
-                        return failed_authentication()
-                except Exception as e:
-                    status_code, message = e.get_HTTP()  # type: ignore
-                    return set_response_headers(jsonify(message), status_code=status_code)
-
-        if checkEndpoint("DELETE", type_):
-            # No Delete Operation for collections
-            if type_ in get_doc().parsed_classes and type_+"Collection" not in get_doc().collections:
-                try:
-                    crud.delete_single(type_, session=get_session())
-                    response = {"message": "Object successfully deleted"}
-                    return set_response_headers(jsonify(response))
-                except Exception as e:
-                    status_code, message = e.get_HTTP() # type: ignore
-                    return set_response_headers(jsonify(message), status_code=status_code)
-        abort(405)
-
-
-class Contexts(Resource):
-    """Dynamically genereated contexts."""
-
-    def get(self, category: str) -> Response:
-        """Return the context for the specified class."""
-        if "Collection" in category:
-
-            if category in get_doc().collections:
-                response = {"@context": get_doc().collections[category]["context"].generate()} # type: Union[Dict[str,Any],Dict[int,str]]
-                return set_response_headers(jsonify(response))
-
-            else:
-                response = {404: "NOT FOUND"}
-                return set_response_headers(jsonify(response), status_code=404)
-
-        else:
-
-            if category in get_doc().parsed_classes:
-                response = {"@context": get_doc().parsed_classes[category]["context"].generate()}
-                return set_response_headers(jsonify(response))
-
-            else:
-                response = {404: "NOT FOUND"}
-                return set_response_headers(jsonify(response), status_code=404)
-
-
-def app_factory(API_NAME: str="api") -> Flask:
-    """Create an app object."""
-    app = Flask(__name__)
-
-    CORS(app)
-    app.url_map.strict_slashes = False
-    api = Api(app)
-
-    api.add_resource(Index, "/"+API_NAME+"/", endpoint="api")
-    api.add_resource(Vocab, "/"+API_NAME+"/vocab", endpoint="vocab")
-    api.add_resource(Contexts, "/"+API_NAME+"/contexts/<string:category>.jsonld", endpoint="contexts")
-    api.add_resource(Entrypoint, "/"+API_NAME+"/contexts/EntryPoint.jsonld", endpoint="main_entrypoint")
-    api.add_resource(ItemCollection, "/"+API_NAME+"/<string:type_>", endpoint="item_collection")
-    api.add_resource(Item, "/"+API_NAME+"/<string:type_>/<int:id_>", endpoint="item")
-
-    return app
-
-
-if __name__ == "__main__":
-
-    app = app_factory("api")
-    app.run(host='127.0.0.1', debug=True, port=8080)
+"""Main route for the applciation."""
+
+import json
+from flask import Flask, jsonify, request, abort
+from flask_restful import Api, Resource
+from flask_cors import CORS
+
+from hydrus.data import crud
+from hydrus.data.user import check_authorization
+from hydrus.utils import get_session, get_doc, get_api_name, get_hydrus_server_url, get_authentication
+
+import pdb
+
+
+def valid_object(object_):
+    """Check if the data passed in POST is of valid format or not."""
+    if "@type" in object_:
+        return True
+    return False
+
+
+def failed_authentication():
+    """Return failed authentication object."""
+    message = {401: "Need credentials to authenticate"}
+    response = set_response_headers(jsonify(message), status_code=401,
+                                    headers=[{'WWW-Authenticate': 'Basic realm="Login Required"'}])
+    return response
+
+
+def set_response_headers(resp, ct="application/ld+json", headers=[], status_code=200):
+    """Set the response headers."""
+    resp.status_code = status_code
+    for header in headers:
+        resp.headers[list(header.keys())[0]] = header[list(header.keys())[0]]
+    resp.headers['Content-type'] = ct
+    resp.headers['Link'] = '<' + get_hydrus_server_url() + \
+        get_api_name()+'/vocab>; rel="http://www.w3.org/ns/hydra/core#apiDocumentation"'
+    return resp
+
+
+def hydrafy(object_):
+    """Add hydra context to objects."""
+    object_["@context"] = "/"+get_api_name()+"/contexts/" + object_["@type"] + ".jsonld"
+    return object_
+
+
+def check_endpoint(method, type_):
+    """Check if endpoint and method is supported in the API."""
+    for endpoint in get_doc().entrypoint.entrypoint.supportedProperty:
+        if type_ == endpoint.name:
+            for operation in endpoint.supportedOperation:
+                if operation.method == method:
+                    return True
+    return False
+
+
+def get_type(class_type, method):
+    """Return the @type of object allowed for POST/PUT."""
+    for supportedOp in get_doc().parsed_classes[class_type]["class"].supportedOperation:
+        if supportedOp.method == method:
+            return supportedOp.expects.replace("vocab:", "")
+    # NOTE: Don't use split, if there are more than one substrings with 'vocab:' not everything will be returned.
+
+
+def check_class_op(class_type, method):
+    """Check if the Class supports the operation."""
+    for supportedOp in get_doc().parsed_classes[class_type]["class"].supportedOperation:
+        if supportedOp.method == method:
+            return True
+    return False
+
+
+class Index(Resource):
+    """Class for the EntryPoint."""
+
+    def get(self):
+        """Return main entrypoint for the api."""
+        return set_response_headers(jsonify(get_doc().entrypoint.get()))
+
+
+class Vocab(Resource):
+    """Vocabulary for Hydra."""
+
+    def get(self):
+        """Return the main hydra vocab."""
+        return set_response_headers(jsonify(get_doc().generate()))
+
+
+class EntryPoint(Resource):
+    """Hydra EntryPoint."""
+
+    def get(self):
+        """Return application main Entrypoint."""
+        response = {"@context": get_doc().entrypoint.context.generate()}
+        return set_response_headers(jsonify(response))
+
+
+class Item(Resource):
+    """Handles all operations(GET, POST, PATCH, DELETE) on Items (item can be anything depending upon the vocabulary)."""
+
+    def get(self, id_, type_):
+        """GET object with id = id_ from the database."""
+        if get_authentication():
+            if request.authorization is None:
+                return failed_authentication()
+            else:
+                auth = check_authorization(request, get_session())
+                if auth is False:
+                    return failed_authentication()
+
+        class_type = get_doc().collections[type_]["collection"].class_.title
+
+        if check_class_op(class_type, "GET"):
+
+            try:
+                response = crud.get(id_, class_type, api_name=get_api_name(), session=get_session())
+                return set_response_headers(jsonify(hydrafy(response)))
+
+            except Exception as e:
+                status_code, message = e.get_HTTP()
+                return set_response_headers(jsonify(message), status_code=status_code)
+
+        abort(405)
+
+    def post(self, id_, type_):
+        """Update object of type<type_> at ID<id_> with new object_ using HTTP POST."""
+        if get_authentication():
+            if request.authorization is None:
+                return failed_authentication()
+            else:
+                auth = check_authorization(request, get_session())
+                if auth is False:
+                    return failed_authentication()
+
+        class_type = get_doc().collections[type_]["collection"].class_.title
+
+        if check_class_op(class_type, "POST"):
+
+            object_ = json.loads(request.data.decode('utf-8'))
+            obj_type = get_type(class_type, "POST")
+
+            if valid_object(object_):
+
+                if object_["@type"] == obj_type:
+                    try:
+                        object_id = crud.update(object_=object_, id_=id_, type_=object_["@type"], session=get_session(), api_name=get_api_name())
+                        headers_ = [{"Location": get_hydrus_server_url()+get_api_name()+"/"+type_+"/"+str(object_id)}]
+                        response = {"message": "Object with ID %s successfully updated" % (object_id)}
+                        return set_response_headers(jsonify(response), headers=headers_)
+
+                    except Exception as e:
+                        status_code, message = e.get_HTTP()
+                        return set_response_headers(jsonify(message), status_code=status_code)
+
+            return set_response_headers(jsonify({400: "Data is not valid"}), status_code=400)
+
+        abort(405)
+
+    def put(self, id_, type_):
+        """Add new object_ optional <id_> parameter using HTTP PUT."""
+        if get_authentication():
+            if request.authorization is None:
+                return failed_authentication()
+            else:
+                auth = check_authorization(request, get_session())
+                if auth is False:
+                    return failed_authentication()
+
+        class_type = get_doc().collections[type_]["collection"].class_.title
+
+        if check_class_op(class_type, "PUT"):
+
+            object_ = json.loads(request.data.decode('utf-8'))
+            obj_type = get_type(class_type, "PUT")
+
+            if valid_object(object_):
+
+                if object_["@type"] == obj_type:
+                    try:
+                        object_id = crud.insert(object_=object_, id_=id_, session=get_session())
+                        headers_ = [{"Location": get_hydrus_server_url()+get_api_name()+"/"+type_+"/"+str(object_id)}]
+                        response = {"message": "Object with ID %s successfully added" % (object_id)}
+                        return set_response_headers(jsonify(response), headers=headers_, status_code=201)
+
+                    except Exception as e:
+                        status_code, message = e.get_HTTP()
+                        return set_response_headers(jsonify(message), status_code=status_code)
+
+            return set_response_headers(jsonify({400: "Data is not valid"}), status_code=400)
+
+        abort(405)
+
+    def delete(self, id_, type_):
+        """Delete object with id=id_ from database."""
+        if get_authentication():
+            if request.authorization is None:
+                return failed_authentication()
+            else:
+                auth = check_authorization(request, get_session())
+                if auth is False:
+                    return failed_authentication()
+
+        class_type = get_doc().collections[type_]["collection"].class_.title
+
+        if check_class_op(class_type, "DELETE"):
+            try:
+                crud.delete(id_, class_type, session=get_session())
+                response = {"message": "Object with ID %s successfully deleted" % (id_)}
+                return set_response_headers(jsonify(response))
+
+            except Exception as e:
+                status_code, message = e.get_HTTP()
+                return set_response_headers(jsonify(message), status_code=status_code)
+
+        abort(405)
+
+
+class ItemCollection(Resource):
+    """Handle operation related to ItemCollection (a collection of items)."""
+
+    def get(self, type_):
+        """Retrieve a collection of items from the database."""
+        if get_authentication():
+            if request.authorization is None:
+                return failed_authentication()
+            else:
+                auth = check_authorization(request, get_session())
+                if auth is False:
+                    return failed_authentication()
+
+        if check_endpoint("GET", type_):
+            # Collections
+            if type_ in get_doc().collections:
+
+                collection = get_doc().collections[type_]["collection"]
+                try:
+                    response = crud.get_collection(get_api_name(), collection.class_.title, session=get_session())
+                    return set_response_headers(jsonify(hydrafy(response)))
+
+                except Exception as e:
+                    status_code, message = e.get_HTTP()
+                    return set_response_headers(jsonify(message), status_code=status_code)
+
+            # Non Collection classes
+            elif type_ in get_doc().parsed_classes and type_+"Collection" not in get_doc().collections:
+                try:
+                    response = crud.get_single(type_, api_name=get_api_name(), session=get_session())
+                    return set_response_headers(jsonify(hydrafy(response)))
+
+                except Exception as e:
+                    status_code, message = e.get_HTTP()
+                    return set_response_headers(jsonify(message), status_code=status_code)
+
+        abort(405)
+
+    def put(self, type_):
+        """Add item to ItemCollection."""
+        if get_authentication():
+            if request.authorization is None:
+                return failed_authentication()
+            else:
+                auth = check_authorization(request, get_session())
+                if auth is False:
+                    return failed_authentication()
+
+        if check_endpoint("PUT", type_):
+            object_ = json.loads(request.data.decode('utf-8'))
+
+            # Collections
+            if type_ in get_doc().collections:
+
+                collection = get_doc().collections[type_]["collection"]
+                obj_type = collection.class_.title
+
+                if valid_object(object_):
+
+                    if object_["@type"] == obj_type:
+                        try:
+                            object_id = crud.insert(object_=object_, session=get_session())
+                            headers_ = [{"Location": get_hydrus_server_url()+get_api_name()+"/"+type_+"/"+str(object_id)}]
+                            response = {"message": "Object with ID %s successfully deleted" % (object_id)}
+                            return set_response_headers(jsonify(response), headers=headers_, status_code=201)
+                        except Exception as e:
+                            status_code, message = e.get_HTTP()
+                            return set_response_headers(jsonify(message), status_code=status_code)
+
+                return set_response_headers(jsonify({400: "Data is not valid"}), status_code=400)
+
+            # Non Collection classes
+            elif type_ in get_doc().parsed_classes and type_+"Collection" not in get_doc().collections:
+                obj_type = get_type(type_, "PUT")
+
+                if object_["@type"] == obj_type:
+
+                    if valid_object(object_):
+                        try:
+                            object_id = crud.insert(object_=object_, session=get_session())
+                            headers_ = [{"Location": get_hydrus_server_url()+get_api_name()+"/"+type_+"/"}]
+                            response = {"message": "Object successfully added"}
+                            return set_response_headers(jsonify(response), headers=headers_, status_code=201)
+                        except Exception as e:
+                            status_code, message = e.get_HTTP()
+                            return set_response_headers(jsonify(message), status_code=status_code)
+
+                return set_response_headers(jsonify({400: "Data is not valid"}), status_code=400)
+
+        abort(405)
+
+    def post(self, type_):
+        """Update Non Collection class item."""
+        if get_authentication():
+            if request.authorization is None:
+                return failed_authentication()
+            else:
+                auth = check_authorization(request, get_session())
+                if auth is False:
+                    return failed_authentication()
+
+        if check_endpoint("POST", type_):
+            object_ = json.loads(request.data.decode('utf-8'))
+
+            if type_ in get_doc().parsed_classes and type_+"Collection" not in get_doc().collections:
+                obj_type = get_type(type_, "POST")
+
+                if valid_object(object_):
+
+                    if object_["@type"] == obj_type:
+                        # try:
+                            crud.update_single(object_=object_, session=get_session(), api_name=get_api_name())
+                            headers_ = [{"Location": get_hydrus_server_url()+get_api_name()+"/"+type_+"/"}]
+                            response = {"message": "Object successfully updated"}
+                            return set_response_headers(jsonify(response), headers=headers_)
+                        # except Exception as e:
+                        #     status_code, message = e.get_HTTP()
+                        #     return set_response_headers(jsonify(message), status_code=status_code)
+
+                return set_response_headers(jsonify({400: "Data is not valid"}), status_code=400)
+
+        abort(405)
+
+    def delete(self, type_):
+        """Delete a non Collection class item."""
+        if get_authentication():
+            if request.authorization is None:
+                return failed_authentication()
+            else:
+                auth = check_authorization(request, get_session())
+                if auth is False:
+                    return failed_authentication()
+
+        if check_endpoint("DELETE", type_):
+            # No Delete Operation for collections
+            if type_ in get_doc().parsed_classes and type_+"Collection" not in get_doc().collections:
+                try:
+                    crud.delete_single(type_, session=get_session())
+                    response = {"message": "Object successfully deleted"}
+                    return set_response_headers(jsonify(response))
+                except Exception as e:
+                    status_code, message = e.get_HTTP()
+                    return set_response_headers(jsonify(message), status_code=status_code)
+        abort(405)
+
+
+class Contexts(Resource):
+    """Dynamically genereated contexts."""
+
+    def get(self, category):
+        """Return the context for the specified class."""
+        if "Collection" in category:
+
+            if category in get_doc().collections:
+                response = {"@context": get_doc().collections[category]["context"].generate()}
+                return set_response_headers(jsonify(response))
+
+            else:
+                response = {404: "NOT FOUND"}
+                return set_response_headers(jsonify(response), status_code=404)
+
+        else:
+
+            if category in get_doc().parsed_classes:
+                response = {"@context": get_doc().parsed_classes[category]["context"].generate()}
+                return set_response_headers(jsonify(response))
+
+            else:
+                response = {404: "NOT FOUND"}
+                return set_response_headers(jsonify(response), status_code=404)
+
+
+def app_factory(API_NAME="api"):
+    """Create an app object."""
+    app = Flask(__name__)
+
+    CORS(app)
+    app.url_map.strict_slashes = False
+    api = Api(app)
+
+    api.add_resource(Index, "/"+API_NAME+"/", endpoint="api")
+    api.add_resource(Vocab, "/"+API_NAME+"/vocab", endpoint="vocab")
+    api.add_resource(Contexts, "/"+API_NAME+"/contexts/<string:category>.jsonld", endpoint="contexts")
+    api.add_resource(EntryPoint, "/" + API_NAME + "/contexts/EntryPoint.jsonld", endpoint="main_entrypoint")
+    api.add_resource(ItemCollection, "/"+API_NAME+"/<string:type_>", endpoint="item_collection")
+    api.add_resource(Item, "/"+API_NAME+"/<string:type_>/<int:id_>", endpoint="item")
+
+    return app
+
+
+if __name__ == "__main__":
+
+    app = app_factory("api")
+    app.run(host='127.0.0.1', debug=True, port=8080)
diff --git a/hydrus/hydraspec/doc_maker.py b/hydrus/hydraspec/doc_maker.py
index 1a6a8f7..0f58dd4 100644
--- a/hydrus/hydraspec/doc_maker.py
+++ b/hydrus/hydraspec/doc_maker.py
@@ -7,7 +7,7 @@ import json
 from typing import Any, Dict, Match, Optional, Tuple, Union
 
 
-def createDoc(doc: Dict[str, Any], HYDRUS_SERVER_URL: str=None, API_NAME: str=None) -> HydraDoc:
+def create_doc(doc, HYDRUS_SERVER_URL=None, API_NAME=None):
     """Create the HydraDoc object from the API Documentation."""
     # Check @id
     try:
@@ -46,7 +46,7 @@ def createDoc(doc: Dict[str, Any], HYDRUS_SERVER_URL: str=None, API_NAME: str=No
         raise SyntaxError("The API Documentation must have [possibleStatus]")
 
     # EntryPoint object
-    entrypoint_obj = getEntrypoint(doc)     # getEntrypoint checks if all classes have @id
+    entrypoint_obj = get_entrypoint(doc)     # get_entrypoint checks if all classes have @id
 
     # Main doc object
     if HYDRUS_SERVER_URL is not None and API_NAME is not None:
@@ -60,13 +60,13 @@ def createDoc(doc: Dict[str, Any], HYDRUS_SERVER_URL: str=None, API_NAME: str=No
 
     # add all parsed_classes
     for class_ in supportedClass:
-        class_obj, collection = createClass(entrypoint_obj, class_)
+        class_obj, collection = create_class(entrypoint_obj, class_)
         if class_obj:
             apidoc.add_supported_class(class_obj, collection=collection)
 
     # add possibleStatus
     for status in possibleStatus:
-        status_obj = createStatus(status)
+        status_obj = create_status(status)
         apidoc.add_possible_status(status_obj)
 
     apidoc.add_baseResource()
@@ -75,7 +75,7 @@ def createDoc(doc: Dict[str, Any], HYDRUS_SERVER_URL: str=None, API_NAME: str=No
     return apidoc
 
 
-def createClass(entrypoint: Dict[str, Any], class_dict: Dict[str, Any]) -> Tuple[HydraClass, bool]:
+def create_class(entrypoint, class_dict):
     """Create HydraClass objects for classes in the API Documentation."""
     # Base classes not used
     exclude_list = ['http://www.w3.org/ns/hydra/core#Resource',
@@ -122,18 +122,18 @@ def createClass(entrypoint: Dict[str, Any], class_dict: Dict[str, Any]) -> Tuple
 
     # Add supportedProperty for the Class
     for prop in supportedProperty:
-        prop_obj = createProperty(prop)
+        prop_obj = create_property(prop)
         class_.add_supported_prop(prop_obj)
 
     # Add supportedOperation for the Class
     for op in supportedOperation:
-        op_obj = createOperation(op)
+        op_obj = create_operation(op)
         class_.add_supported_op(op_obj)
 
     return class_, collection
 
 
-def getEntrypoint(doc: Dict[str, Any]) -> Dict[str, Any]:
+def get_entrypoint(doc):
     """Find and return the entrypoint object in the doc."""
     # Search supportedClass
     for class_ in doc["supportedClass"]:
@@ -173,7 +173,7 @@ def convert_literal(literal: Any) -> Optional[Union[bool, str]]:
         raise TypeError("Literal not recognised")
 
 
-def createProperty(supported_prop: Dict[str, Any]) -> HydraClassProp:
+def create_property(supported_prop):
     """Create a HydraClassProp object from the supportedProperty."""
     # Syntax checks
     try:
@@ -255,7 +255,7 @@ def collection_in_endpoint(class_: Dict[str, Any], entrypoint: Dict[str, Any]) -
     return False
 
 
-def createOperation(supported_op: Dict[str, Any]) -> HydraClassOp:
+def create_operation(supported_op):
     """Create a HyraClassOp object from the supportedOperation."""
     # Syntax checks
     try:
@@ -283,7 +283,7 @@ def createOperation(supported_op: Dict[str, Any]) -> HydraClassOp:
     return op
 
 
-def createStatus(possible_status: Dict[str, Any]) -> HydraStatus:
+def create_status(possible_status):
     """Create a HydraStatus object from the possibleStatus."""
     # Syntax checks
     try:
@@ -304,5 +304,5 @@ def createStatus(possible_status: Dict[str, Any]) -> HydraStatus:
 
 
 if __name__ == "__main__":
-    api_doc = createDoc(sample_document.generate())
-    print(json.dumps(api_doc.generate(), indent=4, sort_keys=True))
\ No newline at end of file
+    api_doc = create_doc(sample_document.generate())
+    print(json.dumps(api_doc.generate(), indent=4, sort_keys=True))
diff --git a/main.py b/main.py
index 1fd3aa4..8297df7 100644
--- a/main.py
+++ b/main.py
@@ -37,7 +37,7 @@ if __name__ == "__main__":
     # NOTE: You can use your own API Documentation and create a HydraDoc object using doc_maker
     #       Or you may create your own HydraDoc Documentation using doc_writer [see hydrus/hydraspec/doc_writer_sample]
     print("Creating the API Documentation")
-    apidoc = doc_maker.createDoc(doc, HYDRUS_SERVER_URL, API_NAME)
+    apidoc = doc_maker.create_doc(doc, HYDRUS_SERVER_URL, API_NAME)
 
     # Start a session with the DB and create all classes needed by the APIDoc
     session = scoped_session(sessionmaker(bind=engine))


Test patch:
diff --git a/hydrus/tests/test_app.py b/hydrus/tests/test_app.py
index d82092d..ae875f9 100644
--- a/hydrus/tests/test_app.py
+++ b/hydrus/tests/test_app.py
@@ -46,7 +46,7 @@ class ViewsTestCase(unittest.TestCase):
         self.API_NAME = "demoapi"
         self.HYDRUS_SERVER_URL = "http://hydrus.com/"
         self.app = app_factory(self.API_NAME)
-        self.doc = doc_maker.createDoc(doc_writer_sample.api_doc.generate(), self.HYDRUS_SERVER_URL, self.API_NAME)
+        self.doc = doc_maker.create_doc(doc_writer_sample.api_doc.generate(), self.HYDRUS_SERVER_URL, self.API_NAME)
 
         test_classes = doc_parse.get_classes(self.doc.generate())
         test_properties = doc_parse.get_all_properties(test_classes)
diff --git a/hydrus/tests/test_auth.py b/hydrus/tests/test_auth.py
index 365fd4d..055a21b 100644
--- a/hydrus/tests/test_auth.py
+++ b/hydrus/tests/test_auth.py
@@ -32,7 +32,7 @@ class AuthTestCase(unittest.TestCase):
         self.API_NAME = "demoapi"
         self.HYDRUS_SERVER_URL = "http://hydrus.com/"
         self.app = app_factory(self.API_NAME)
-        self.doc = doc_maker.createDoc(doc_writer_sample.api_doc.generate(), self.HYDRUS_SERVER_URL, self.API_NAME)
+        self.doc = doc_maker.create_doc(doc_writer_sample.api_doc.generate(), self.HYDRUS_SERVER_URL, self.API_NAME)
 
         test_classes = doc_parse.get_classes(self.doc.generate())
         test_properties = doc_parse.get_all_properties(test_classes)