diff --git a/sample_project.zip b/sample_project.zip deleted file mode 100644 index 2421391..0000000 Binary files a/sample_project.zip and /dev/null differ diff --git a/sample_project/.DS_Store b/sample_project/.DS_Store new file mode 100644 index 0000000..7a85055 Binary files /dev/null and b/sample_project/.DS_Store differ diff --git a/sample_project/.idea/.gitignore b/sample_project/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/sample_project/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/sample_project/.idea/inspectionProfiles/profiles_settings.xml b/sample_project/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/sample_project/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/sample_project/.idea/misc.xml b/sample_project/.idea/misc.xml new file mode 100644 index 0000000..a5223d8 --- /dev/null +++ b/sample_project/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/sample_project/.idea/modules.xml b/sample_project/.idea/modules.xml new file mode 100644 index 0000000..22bdbf5 --- /dev/null +++ b/sample_project/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/sample_project/.idea/sample_project.iml b/sample_project/.idea/sample_project.iml new file mode 100644 index 0000000..d0876a7 --- /dev/null +++ b/sample_project/.idea/sample_project.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/sample_project/__pycache__/config.cpython-312.pyc b/sample_project/__pycache__/config.cpython-312.pyc new file mode 100644 index 0000000..cf470ae Binary files /dev/null and b/sample_project/__pycache__/config.cpython-312.pyc differ diff --git a/sample_project/__pycache__/server.cpython-312.pyc b/sample_project/__pycache__/server.cpython-312.pyc new file mode 100644 index 0000000..dd1e4b0 Binary files /dev/null and b/sample_project/__pycache__/server.cpython-312.pyc differ diff --git a/sample_project/app/__init__.py b/sample_project/app/__init__.py new file mode 100644 index 0000000..a0bda8d --- /dev/null +++ b/sample_project/app/__init__.py @@ -0,0 +1,5 @@ +from config import Config +from app.app_config import register_versions, app + + +register_versions(Config.VERSIONS_ALLOWED) diff --git a/sample_project/app/__init__.pyc b/sample_project/app/__init__.pyc new file mode 100644 index 0000000..3eee410 Binary files /dev/null and b/sample_project/app/__init__.pyc differ diff --git a/sample_project/app/__pycache__/__init__.cpython-312.pyc b/sample_project/app/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..53aced5 Binary files /dev/null and b/sample_project/app/__pycache__/__init__.cpython-312.pyc differ diff --git a/sample_project/app/__pycache__/app_config.cpython-312.pyc b/sample_project/app/__pycache__/app_config.cpython-312.pyc new file mode 100644 index 0000000..e7473e3 Binary files /dev/null and b/sample_project/app/__pycache__/app_config.cpython-312.pyc differ diff --git a/sample_project/app/__pycache__/common_utils.cpython-312.pyc b/sample_project/app/__pycache__/common_utils.cpython-312.pyc new file mode 100644 index 0000000..e27fcbf Binary files /dev/null and b/sample_project/app/__pycache__/common_utils.cpython-312.pyc differ diff --git a/sample_project/app/__pycache__/connections.cpython-312.pyc b/sample_project/app/__pycache__/connections.cpython-312.pyc new file mode 100644 index 0000000..0d18d5c Binary files /dev/null and b/sample_project/app/__pycache__/connections.cpython-312.pyc differ diff --git a/sample_project/app/__pycache__/decorators.cpython-312.pyc b/sample_project/app/__pycache__/decorators.cpython-312.pyc new file mode 100644 index 0000000..18ed954 Binary files /dev/null and b/sample_project/app/__pycache__/decorators.cpython-312.pyc differ diff --git a/sample_project/app/app_config.py b/sample_project/app/app_config.py new file mode 100644 index 0000000..5b95adc --- /dev/null +++ b/sample_project/app/app_config.py @@ -0,0 +1,20 @@ +from flask import Flask +from app.v1.urls import v1 + + +app = Flask(__name__) + + +VERSION_OBJECT_MAPPING = { + '1': v1, +} + + +def get_url_prefix(version): + return '/api/v{version_number}'.format(version_number=str(version)) + + +def register_versions(allowed_versions): + for version in allowed_versions: + app.register_blueprint( + VERSION_OBJECT_MAPPING[version], url_prefix=get_url_prefix(version)) diff --git a/sample_project/app/app_config.pyc b/sample_project/app/app_config.pyc new file mode 100644 index 0000000..0a05400 Binary files /dev/null and b/sample_project/app/app_config.pyc differ diff --git a/sample_project/app/base_coordinator.py b/sample_project/app/base_coordinator.py new file mode 100644 index 0000000..e69de29 diff --git a/sample_project/app/common_utils.py b/sample_project/app/common_utils.py new file mode 100644 index 0000000..bd7c7d8 --- /dev/null +++ b/sample_project/app/common_utils.py @@ -0,0 +1,40 @@ +import json +from flask import Response, request + + +def render_success_response(response, msg='', status=1): + body = { + 's': status, + 'm': msg, + 'd': response + } + return Response(json.dumps(body), status=200, content_type='application/json') + + +def render_error_response(msg, status): + body = { + 's': 0, + 'm': msg, + 'd': dict() + } + return Response(json.dumps(body), status=status, content_type='application/json') + + +def extract_params(): + if request.method == 'POST': + if request.content_type == 'application/x-www-form-urlencoded': + params = request.form + elif 'multipart/form-data' in request.content_type: + params = request + else: + params = request.get_json() + return params + else: + params = request.args + parsed_params = dict() + for key, val in dict(params).items(): + if isinstance(val, list) and val: + parsed_params.update({key: val[0]}) + else: + parsed_params.update({key: val}) + return parsed_params diff --git a/sample_project/app/common_utils.pyc b/sample_project/app/common_utils.pyc new file mode 100644 index 0000000..f854f56 Binary files /dev/null and b/sample_project/app/common_utils.pyc differ diff --git a/sample_project/app/connections.py b/sample_project/app/connections.py new file mode 100644 index 0000000..e9cf59d --- /dev/null +++ b/sample_project/app/connections.py @@ -0,0 +1,75 @@ +from decimal import Decimal +from datetime import datetime +import pymysql as PYMYSQL + + +class SqlConnection(object): + + def __init__(self, db_config): + self.db_config = db_config + try: + self.connection = PYMYSQL.connect(**self.db_config) + self.cursor = self.connection.cursor(dictionary=True) + except Exception as e: + self.connection.close() + + @staticmethod + def parsed_db_result(db_data) -> dict: + parsed_db_data = dict() + for key, val in db_data.items(): + if isinstance(val, Decimal): + parsed_db_data.update({key: float(val)}) + elif isinstance(val, datetime): + parsed_db_data.update({key: val.strftime('%Y-%m-%d %H:%M:%S')}) + elif isinstance(val, str) and val == 'NULL': + parsed_db_data.update({key: None}) + else: + parsed_db_data.update({key: val}) + return parsed_db_data + + def reconnect_db(self): + self.connection = PYMYSQL.connect(**self.db_config) + self.cursor = self.connection.cursor(dictionary=True) + + def query_db(self, query, params=None) -> list: + try: + if params: + self.cursor.execute(query, params) + else: + self.cursor.execute(query) + except Exception as e: + self.reconnect_db() + self.cursor.execute(query) + result = self.cursor.fetchall() + return list(map(lambda row: self.parsed_db_result(row), result)) if result else list() + + def query_db_one(self, query, params=None, parsed=True) -> dict: + try: + if params: + self.cursor.execute(query, params) + else: + self.cursor.execute(query) + except Exception as e: + self.reconnect_db() + self.cursor.execute(query) + result = self.cursor.fetchone() + if not result: + return dict() + return self.parsed_db_result(result) if parsed else result + + def write_db(self, query, params=None) -> int: + try: + if params: + self.cursor.execute(query, params) + else: + self.cursor.execute(query) + self.connection.commit() + except Exception as e: + self.reconnect_db() + self.cursor.execute(query) + self.connection.commit() + return self.cursor.lastrowid + + def __del__(self): + self.cursor.close() + self.connection.close() diff --git a/sample_project/app/decorators.py b/sample_project/app/decorators.py new file mode 100644 index 0000000..a0f0998 --- /dev/null +++ b/sample_project/app/decorators.py @@ -0,0 +1,17 @@ +from flask import request +from functools import wraps +from app.common_utils import render_error_response, extract_params + + +def validate_request(func): + + def extract_headers(): + return dict(request.headers) + + @wraps(func) + def decorated_function(*args, **kwargs): + params = extract_params() + headers = extract_headers() + return func(params=params, headers=headers, *args, **kwargs) + + return decorated_function diff --git a/sample_project/app/decorators.pyc b/sample_project/app/decorators.pyc new file mode 100644 index 0000000..7e21001 Binary files /dev/null and b/sample_project/app/decorators.pyc differ diff --git a/sample_project/app/exceptions.py b/sample_project/app/exceptions.py new file mode 100644 index 0000000..e69de29 diff --git a/sample_project/app/v1/__init__.py b/sample_project/app/v1/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sample_project/app/v1/__init__.pyc b/sample_project/app/v1/__init__.pyc new file mode 100644 index 0000000..22a983c Binary files /dev/null and b/sample_project/app/v1/__init__.pyc differ diff --git a/sample_project/app/v1/__pycache__/__init__.cpython-312.pyc b/sample_project/app/v1/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..0fe0e77 Binary files /dev/null and b/sample_project/app/v1/__pycache__/__init__.cpython-312.pyc differ diff --git a/sample_project/app/v1/__pycache__/urls.cpython-312.pyc b/sample_project/app/v1/__pycache__/urls.cpython-312.pyc new file mode 100644 index 0000000..e8753fd Binary files /dev/null and b/sample_project/app/v1/__pycache__/urls.cpython-312.pyc differ diff --git a/sample_project/app/v1/urls.py b/sample_project/app/v1/urls.py new file mode 100644 index 0000000..cfffca3 --- /dev/null +++ b/sample_project/app/v1/urls.py @@ -0,0 +1,32 @@ +from flask import Blueprint +from app.v1.users import views as sample_subapp_views +from app.v1.users.views1 import User_Book_API + + +v1 = Blueprint('v1', __name__) + + +# subapp1 urls +sample_subapp_prefix = '/users' + +v1.add_url_rule(sample_subapp_prefix + '/getUserName', view_func=sample_subapp_views.GetUserName.as_view('endpoint_1')) + + +v1.add_url_rule( + sample_subapp_prefix + '/getUserDetails', + view_func=sample_subapp_views.GetUserDetails.as_view('endpoint_2') +) + +user_view = User_Book_API.as_view('user_book_api') + +v1.add_url_rule(sample_subapp_prefix + '/books', view_func=user_view, methods=['GET', "POST"]) + +v1.add_url_rule(sample_subapp_prefix + '/books', view_func=user_view, methods=['PUT','DELETE']) + +v1.add_url_rule( + sample_subapp_prefix + '/books/', + view_func=user_view, + methods=['GET'] +) + + diff --git a/sample_project/app/v1/urls.pyc b/sample_project/app/v1/urls.pyc new file mode 100644 index 0000000..6f66f57 Binary files /dev/null and b/sample_project/app/v1/urls.pyc differ diff --git a/sample_project/app/v1/users/__init__.py b/sample_project/app/v1/users/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sample_project/app/v1/users/__init__.pyc b/sample_project/app/v1/users/__init__.pyc new file mode 100644 index 0000000..b75a852 Binary files /dev/null and b/sample_project/app/v1/users/__init__.pyc differ diff --git a/sample_project/app/v1/users/__pycache__/__init__.cpython-312.pyc b/sample_project/app/v1/users/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..59b5b13 Binary files /dev/null and b/sample_project/app/v1/users/__pycache__/__init__.cpython-312.pyc differ diff --git a/sample_project/app/v1/users/__pycache__/service.cpython-312.pyc b/sample_project/app/v1/users/__pycache__/service.cpython-312.pyc new file mode 100644 index 0000000..5600a95 Binary files /dev/null and b/sample_project/app/v1/users/__pycache__/service.cpython-312.pyc differ diff --git a/sample_project/app/v1/users/__pycache__/views.cpython-312.pyc b/sample_project/app/v1/users/__pycache__/views.cpython-312.pyc new file mode 100644 index 0000000..380b21e Binary files /dev/null and b/sample_project/app/v1/users/__pycache__/views.cpython-312.pyc differ diff --git a/sample_project/app/v1/users/__pycache__/views1.cpython-312.pyc b/sample_project/app/v1/users/__pycache__/views1.cpython-312.pyc new file mode 100644 index 0000000..20ea4aa Binary files /dev/null and b/sample_project/app/v1/users/__pycache__/views1.cpython-312.pyc differ diff --git a/sample_project/app/v1/users/coordinator.py b/sample_project/app/v1/users/coordinator.py new file mode 100644 index 0000000..e69de29 diff --git a/sample_project/app/v1/users/service.py b/sample_project/app/v1/users/service.py new file mode 100644 index 0000000..23a6947 --- /dev/null +++ b/sample_project/app/v1/users/service.py @@ -0,0 +1,8 @@ +class SubApp1Service: + + def __init__(self, params, headers): + self.params = params + self.headers = headers + + def get_static_api_response(self): + return self.params, 'success' diff --git a/sample_project/app/v1/users/service.pyc b/sample_project/app/v1/users/service.pyc new file mode 100644 index 0000000..2549365 Binary files /dev/null and b/sample_project/app/v1/users/service.pyc differ diff --git a/sample_project/app/v1/users/views.py b/sample_project/app/v1/users/views.py new file mode 100644 index 0000000..8a9e744 --- /dev/null +++ b/sample_project/app/v1/users/views.py @@ -0,0 +1,119 @@ +from flask.views import MethodView +from app.decorators import validate_request +from app.common_utils import render_success_response +from app.v1.users.service import SubApp1Service +from flask import jsonify +from flask import request +from app.connections import SqlConnection +import pymysql + + + +def db_connection(): + # conn=mysql.connector.connect(host='localhost',user="root",password="root",database= "demo") + # cur=conn.cursor() + + + db_config = { + 'host': 'localhost', + 'user': 'root', + 'password': 'root', + 'database': 'db' + } + + + connection = pymysql.connect(**db_config) + return(connection) +db_connection() +class GetUserName(MethodView): + + @validate_request + def get(self, params, headers, *args, **kwargs): + response, message = SubApp1Service(params, headers).get_static_api_response() + return render_success_response(response, message) + +class GetUserDetails(MethodView): + def get(self): + conn = db_connection() + cursor = conn.cursor(pymysql.cursors.DictCursor) + query = "SELECT * FROM employee" + cursor.execute(query) + results = cursor.fetchall() + cursor.close() + conn.close() + return jsonify({"message": "GET: Data received", "data": results}) + + + + @validate_request + def post(self, *args, **kwargs): + data = request.get_json() + id = data.get('id') + name = data.get('name') + + conn = db_connection() + cursor = conn.cursor() + + query = "INSERT INTO employee (id, name) VALUES (%s, %s)" + values = (id, name) + + cursor.execute(query, values) + conn.commit() + + if cursor.rowcount == 0: + return jsonify({"message": "No user found with the provided ID"}) + + cursor.close() + conn.close() + + return jsonify({"message": "User created successfully"}) + + + @validate_request + def put(self, *args, **kwargs): + data = request.get_json() + id = data.get('id') + name = data.get('name') + + + conn = db_connection() + cursor = conn.cursor() + + query = "UPDATE employee SET name=%s WHERE id=%s" + values = (name, id) + + cursor.execute(query, values) + conn.commit() + + if cursor.rowcount == 0: + return jsonify({"message": "No user found with the provided ID"}) + + cursor.close() + conn.close() + + return jsonify({"message": "User updated successfully"}) + + + @validate_request + def delete(self, *args, **kwargs): + id = request.args.get('id') + + if not id: + return jsonify({"message": "ID is required"}), 400 + + conn = db_connection() + cursor = conn.cursor() + + query = "DELETE FROM employee WHERE id = %s" + values = (id,) + + cursor.execute(query, values) + conn.commit() + + if cursor.rowcount == 0: + return jsonify({"message": "No user found with the provided ID"}), 404 + + cursor.close() + conn.close() + + return jsonify({"message": "User deleted successfully"}), 200 \ No newline at end of file diff --git a/sample_project/app/v1/users/views.pyc b/sample_project/app/v1/users/views.pyc new file mode 100644 index 0000000..a55f2a5 Binary files /dev/null and b/sample_project/app/v1/users/views.pyc differ diff --git a/sample_project/app/v1/users/views1.py b/sample_project/app/v1/users/views1.py new file mode 100644 index 0000000..2c1284b --- /dev/null +++ b/sample_project/app/v1/users/views1.py @@ -0,0 +1,113 @@ +from flask.views import MethodView +from app.decorators import validate_request +from app.common_utils import render_success_response +from app.v1.users.service import SubApp1Service +from flask import jsonify +from flask import request +from app.connections import SqlConnection +import pymysql + + + + +# Database connection +def db_connection(): + db_config = { + 'host': 'localhost', + 'user': 'root', + 'password': 'root', + 'database': 'db' + } + connection = pymysql.connect(**db_config) + return(connection) +db_connection() + + +class User_Book_API(MethodView): + def get(self, id=None): + conn = db_connection() + cursor = conn.cursor() + if id is None: + cursor.execute("SELECT * FROM books") + users = cursor.fetchall() + return jsonify(users) + else: + cursor.execute("SELECT * FROM books WHERE id = %s", (id,)) + user = cursor.fetchone() + if user is None: + return jsonify({"message": "books not found"}) + return jsonify(user) + + + def post(self): + data = request.get_json() + title = data.get('title') + author = data.get('author') + + if not title or not author: + return jsonify({"message": "title and author are required"}) + + conn = db_connection() + cursor = conn.cursor() + query = "INSERT INTO books (title,author) VALUES (%s, %s)" + cursor.execute(query, (title,author)) + conn.commit() + new_user_id = cursor.lastrowid + cursor.close() + conn.close() + + return jsonify({"message": "books created successfully", "user_id": new_user_id}) + + def put(self): + data = request.get_json() + id = data.get('id') + title = data.get('title') + author = data.get('author') + + if not title or not author: + return jsonify({"message": "Title and author are required"}) + + conn = db_connection() + cursor = conn.cursor() + query = "UPDATE books SET title = %s, author = %s WHERE id = %s" + values = (title, author, id) + cursor.execute(query, values) + conn.commit() + + if cursor.rowcount == 0: + cursor.close() + conn.close() + return jsonify({"message": "Book not found"}) + + cursor.close() + conn.close() + + return jsonify({"message": "Book updated successfully"}) + + def delete(self): + data = request.get_json() + book_id = data.get('id') + + if not book_id: + return jsonify({"message": "Book ID is required"}) + + conn = db_connection() + cursor = conn.cursor() + + query = "DELETE FROM books WHERE id = %s" + values = (book_id,) + + cursor.execute(query, values) + conn.commit() + + if cursor.rowcount == 0: + cursor.close() + conn.close() + return jsonify({"message": "Book not found"}) + + cursor.close() + conn.close() + + return jsonify({"message": "Book deleted successfully"}), 200 + + diff --git a/sample_project/config.py b/sample_project/config.py new file mode 100644 index 0000000..e10ce3d --- /dev/null +++ b/sample_project/config.py @@ -0,0 +1,3 @@ +class Config: + + VERSIONS_ALLOWED = ['1'] diff --git a/sample_project/config.pyc b/sample_project/config.pyc new file mode 100644 index 0000000..ee7d4f5 Binary files /dev/null and b/sample_project/config.pyc differ diff --git a/sample_project/server.py b/sample_project/server.py new file mode 100644 index 0000000..8fdaf25 --- /dev/null +++ b/sample_project/server.py @@ -0,0 +1,5 @@ +from app import app + + +if __name__ == "__main__": + app.run(debug=True, host='0.0.0.0', port=8000)