diff --git a/socketio/main.py b/socketio/main.py
new file mode 100644
index 0000000..67d39f7
--- /dev/null
+++ b/socketio/main.py
@@ -0,0 +1,202 @@
+"""
+
+ AUTHOR:
+
+ Khushal P Soonderji
+
+ DATE:
+
+ Create: Saturday, 18th May, 2022
+ Update: Thursday, 22nd Aug. 2024
+
+ OBJECTIVE:
+
+ To provide an easy way to work with '.json' data and files.
+
+ REFERENCES:
+
+ 1) https://www.w3schools.com/python/python_json.asp
+
+ DOWNLOADS:
+
+ N/A
+
+"""
+
+
+# *****************************************************************************************************************
+# ***** ****
+# *** IMPORT ***
+# ***** ****
+# *****************************************************************************************************************
+
+
+# To make sibling directories accessible for imports:
+import sys
+sys.path.append(".")
+sys.path.append("..")
+
+# System-level activities:
+import io
+
+# To work with the JSON standard:
+import json
+
+# To work with files:
+from utils_v2.system import files
+
+
+# *****************************************************************************************************************
+# ***** ****
+# *** MACROS / ONE-TIME INIT ***
+# ***** ****
+# *****************************************************************************************************************
+
+
+# --- Nothing Yet
+
+
+# *****************************************************************************************************************
+# ***** ****
+# *** VARIABLES ***
+# ***** ****
+# *****************************************************************************************************************
+
+
+# --- Nothing Yet
+
+
+# *****************************************************************************************************************
+# ***** ****
+# *** FUNCTIONS ***
+# ***** ****
+# *****************************************************************************************************************
+
+
+def from_string(json_data):
+
+ """
+ Decodes a JSON string to a pythonic variable like a dict.
+ :param json_data: The JSON string to decode.
+ :return: The decoded pythonic variable.
+ """
+
+ python_data = json.loads(json_data)
+ return python_data
+
+
+# ---------------------------------------------------------------------------------------------------------------------
+
+
+def to_string(
+ python_data,
+ indent = 4,
+ default = None,
+ separators = None,
+ no_space = False
+):
+
+ """
+ Converts the given pythonic data to a JSON string.
+ :param python_data: The input data like a dict.
+ :param indent: The tab-width for pretty presentation.
+ :param default: The function to use on something that cannot be directly parsed into a JSON string.
+ :param separators: Custom separators to use.
+ :param no_space: If you want a dense JSON string that saves memory by not using spaces or tabs or line-breaks. Not
+ good for human readability, very good for saving memory. WARNING: THIS OVERRIDES EVERY OTHER PARAMETER EXCEPT
+ 'default'.
+ :return: The JSON string representation of the input pythonic data.
+ """
+
+ if no_space:
+ json_data = json.dumps(
+ python_data,
+ default = default,
+ separators = (',', ':')
+ )
+
+ else:
+ json_data = json.dumps(
+ python_data,
+ indent = indent,
+ default = default,
+ separators = separators
+ )
+
+ return json_data
+
+
+# ---------------------------------------------------------------------------------------------------------------------
+
+
+def from_file(file):
+
+ """
+ Reads a JSON file and returns it as a pythonic variable like a dict.
+ :param file: The path to the file on the disk or a file held in RAM as a BytesIO object.
+ :return: The decoded pythonic variable.
+ """
+
+ if isinstance(file, io.BytesIO):
+ file.seek(0)
+ json_data = file.getvalue()
+ else: json_data = files.read_file(file)
+ python_data = from_string(json_data)
+ return python_data
+
+
+# ---------------------------------------------------------------------------------------------------------------------
+
+
+def to_file(
+ file,
+ python_data,
+ indent = 4,
+ default = None,
+ separators = None,
+ no_space = False
+):
+
+ """
+
+ :param file: Either a path to a file on disk, or a buffer in RAM in the form of a BytesIO object.
+ :param python_data: The pythonic data to be converted to the JSON string.
+ :param indent: The tab-width for pretty presentation.
+ :param default: The function to use on something that cannot be directly parsed into a JSON string.
+ :param separators: Custom separators to use.
+ :param no_space: If you want a dense JSON string that saves memory by not using spaces or tabs or line-breaks. Not
+ good for human readability, very good for saving memory. WARNING: THIS OVERRIDES EVERY OTHER PARAMETER EXCEPT
+ 'default'.
+ :return: True/False if a path was given, else the same BytesIO object with the written JSON data.
+ """
+
+ json_data = to_string(
+ python_data,
+ indent = indent,
+ default = default,
+ separators = separators,
+ no_space = no_space
+ )
+
+ if isinstance(file, io.BytesIO):
+ file.write(json_data.encode("utf-8"))
+ file.seek(0)
+ return file
+
+ else:
+ try:
+ files.write_file(file, json_data, mode = "w")
+ return True
+ except: return False
+
+
+# *****************************************************************************************************************
+# ***** ****
+# *** MAIN PROGRAM ***
+# ***** ****
+# *****************************************************************************************************************
+
+
+if __name__ == "__main__":
+
+ pass
diff --git a/utils_v2/api/async_quart.py b/utils_v2/api/async_quart.py
index a0113ef..d7abe9f 100644
--- a/utils_v2/api/async_quart.py
+++ b/utils_v2/api/async_quart.py
@@ -1255,8 +1255,8 @@ def handle_failed_request(cleanup_func = None, cleanup_coro = None):
except Exception as exception:
kwargs["decorator_count"] -= 1
if hasattr(current_app, "printer"): getattr(current_app, "printer")(exception)
- if cleanup_func is not None: cleanup_func()
- if cleanup_coro is not None: await cleanup_coro()
+ if cleanup_func is not None: return cleanup_func()
+ if cleanup_coro is not None: return await cleanup_coro()
raise exception
return wrapper
diff --git a/views_v2/__init__.py b/views_v2/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/views_v2/finstitutions/__init__.py b/views_v2/finstitutions/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/views_v2/finstitutions/trading/__init__.py b/views_v2/finstitutions/trading/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/views_v2/finstitutions/trading/oauth/__init__.py b/views_v2/finstitutions/trading/oauth/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/views_v2/finstitutions/trading/oauth/oauth_cancelled_v2.html b/views_v2/finstitutions/trading/oauth/oauth_cancelled_v2.html
new file mode 100644
index 0000000..368e9a2
--- /dev/null
+++ b/views_v2/finstitutions/trading/oauth/oauth_cancelled_v2.html
@@ -0,0 +1,114 @@
+
+
+
+
+
+ Authorization Cancelled
+
+
+
+
+
+
+
+
!
+
Authorization Cancelled
+
It seems that the authorization for your {{ mail_client }} account was cancelled unexpectedly.
+ Please feel free to try again whenever you feel like it. You can close this tab at any time.
We have received authorization from your {{ mail_client }} account. You can close this tab at any time.
+
+
+
+
+
+
+
+
+
diff --git a/views_v2/message/__init__.py b/views_v2/message/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/views_v2/message/mail/__init__.py b/views_v2/message/mail/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/views_v2/message/mail/oauth/__init__.py b/views_v2/message/mail/oauth/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/views_v2/message/mail/oauth/oauth_cancelled_v2.html b/views_v2/message/mail/oauth/oauth_cancelled_v2.html
new file mode 100644
index 0000000..0bff500
--- /dev/null
+++ b/views_v2/message/mail/oauth/oauth_cancelled_v2.html
@@ -0,0 +1,114 @@
+
+
+
+
+
+ Authorization Cancelled
+
+
+
+
+
+
+
+
!
+
Authorization Cancelled
+
It seems that the authorization for your {{ client }} account was cancelled unexpectedly.
+ Please feel free to try again whenever you feel like it. You can close this tab at any time.