(20250120) Safety Push.

This commit is contained in:
2025-01-20 14:13:36 +05:30
parent 851cfd457e
commit 1f8e13e1d5
3 changed files with 36 additions and 24 deletions
+8 -8
View File
@@ -545,7 +545,7 @@ def read_input(
def get_session_info( def get_session_info(
key: str, key: str,
model: str = None, controller: str = None,
session_func: str = None, session_func: str = None,
session_coro: str = None, session_coro: str = None,
get: str = None, get: str = None,
@@ -560,12 +560,12 @@ def get_session_info(
PLEASE USE "ResponseModel" AS THE RETURNED VALUE OF THE API ENDPOINT IF YOU ARE USING THIS DECORATOR. PLEASE USE "ResponseModel" AS THE RETURNED VALUE OF THE API ENDPOINT IF YOU ARE USING THIS DECORATOR.
:param key: The key in either the 'inbound_data' or the 'inbound_headers' from which the session info will be :param key: The key in either the 'inbound_data' or the 'inbound_headers' from which the session info will be
available. Examples: 'sessionToken' or 'X-Session-Token'. available. Examples: 'sessionToken' or 'X-Session-Token'.
:param model: The object from which the func/coro should be called. This could be the name of the variable holding :param controller: The object from which the func/coro should be called. This could be the name of the variable
an instance of a class. Should be available in the scope of 'current_app'. holding an instance of a class. Should be available in the scope of 'current_app'.
:param session_func: The synchronous func of the model to call. This can either be an independent function or a :param session_func: The synchronous func of the controller to call. This can either be an independent function or a
class's method. Should be available in the scope of 'current_app'. class's method. Should be available in the scope of 'current_app'.
:param session_coro: The asynchronous func of the model to call. This can either be an independent function or a :param session_coro: The asynchronous func of the controller to call. This can either be an independent function or
class's method. Ignored if 'func' was provided. Should be available in the scope of 'current_app'. a class's method. Ignored if 'func' was provided. Should be available in the scope of 'current_app'.
:param get: The field inside the dict to get. Specify this in dot notation. The whole response will be returned as :param get: The field inside the dict to get. Specify this in dot notation. The whole response will be returned as
is if this is null. is if this is null.
:param mandatory: If set to True, the API call will enforce session checking; and if a session is not found, the :param mandatory: If set to True, the API call will enforce session checking; and if a session is not found, the
@@ -593,12 +593,12 @@ def get_session_info(
# For synchronous functions: # For synchronous functions:
if session_func: if session_func:
if model: session_info = getattr(getattr(current_app, model), session_func)(session_id) if controller: session_info = getattr(getattr(current_app, controller), session_func)(session_id)
else: session_info = getattr(current_app, session_func)(session_id) else: session_info = getattr(current_app, session_func)(session_id)
# For asynchronous coroutines: # For asynchronous coroutines:
elif session_coro: elif session_coro:
if model: session_info = await getattr(getattr(current_app, model), session_coro)(session_id) if controller: session_info = await getattr(getattr(current_app, controller), session_coro)(session_id)
else: session_info = await getattr(current_app, session_coro)(session_id) else: session_info = await getattr(current_app, session_coro)(session_id)
# If something goes wrong: # If something goes wrong:
@@ -51,7 +51,7 @@ from utils_v2.mail import mail_parser
from utils_v2.goog.controllers.base import AsyncGoogleBase from utils_v2.goog.controllers.base import AsyncGoogleBase
from utils_v2.goog.models.auth_tokens import GoogleAuthTokens from utils_v2.goog.models.auth_tokens import GoogleAuthTokens
from utils_v2.goog.models.api_call import GoogleApiResponse from utils_v2.goog.models.api_call import GoogleApiResponse
from utils_v2.goog.controllers.gmail.gmail_message import GMailMessage from utils_v2.goog.controllers.gmail.gmail_message import GmailMessage
# Related to Google: # Related to Google:
from google.auth.transport.requests import Request from google.auth.transport.requests import Request
@@ -857,7 +857,7 @@ class AsyncGmailClient(AsyncGoogleBase):
async def send_message( async def send_message(
self, self,
tokens: GoogleAuthTokens, tokens: GoogleAuthTokens,
message: GMailMessage, message: GmailMessage,
thread_id: str = None, thread_id: str = None,
user_id: str = "me" user_id: str = "me"
) -> GoogleApiResponse: ) -> GoogleApiResponse:
@@ -940,7 +940,7 @@ if __name__ == "__main__":
async def main(): async def main():
# Create an instance of the client: # Create an instance of the client:
my_gmail = AsyncGMailClient( my_gmail = AsyncGmailClient(
service_name = "gmail", service_name = "gmail",
oauth_json = secrets_dict, oauth_json = secrets_dict,
http_client = test_client, http_client = test_client,
@@ -972,7 +972,6 @@ if __name__ == "__main__":
print("DATA:", json.to_string(response.data, default = str)) print("DATA:", json.to_string(response.data, default = str))
if not response.success: if not response.success:
print("\n\n---\n\n") print("\n\n---\n\n")
print("FULL RESPONSE JSON:", json.to_string(await response.get_json()))
asyncio.run(main()) asyncio.run(main())
@@ -96,7 +96,7 @@ from typing import List
# ***************************************************************************************************************** # *****************************************************************************************************************
class GMailMessage: class GmailMessage:
def __init__( def __init__(
self, self,
@@ -160,7 +160,7 @@ class GMailMessage:
# ┣┫┏┫┏┫ ┃ ┏┓┏┓╋┏┓┏┓╋ # ┣┫┏┫┏┫ ┃ ┏┓┏┓╋┏┓┏┓╋
# ┛┗┗┻┗┻ ┗┛┗┛┛┗┗┗ ┛┗┗ # ┛┗┗┻┗┻ ┗┛┗┛┛┗┗┗ ┛┗┗
def add_text(self, text): def add_text(self, text) -> None:
""" """
Add plain-text to the mail body. Add plain-text to the mail body.
@@ -170,7 +170,7 @@ class GMailMessage:
self.message.attach(MIMEText(text, "plain")) self.message.attach(MIMEText(text, "plain"))
def add_html(self, html_text): def add_html(self, html_text) -> None:
""" """
Add HTML text to the mail body. Add HTML text to the mail body.
@@ -185,7 +185,7 @@ class GMailMessage:
image_file: str | io.BytesIO, image_file: str | io.BytesIO,
file_name: str = None, file_name: str = None,
content_id: str = None content_id: str = None
): ) -> None:
""" """
Add an inline image to the body of the mail. Add an inline image to the body of the mail.
@@ -238,7 +238,7 @@ class GMailMessage:
self, self,
attachment_file: str | io.BytesIO, attachment_file: str | io.BytesIO,
file_name: str = None file_name: str = None
): ) -> None:
""" """
Add a file as an attachment to the mail. This file, even if possible, will not be rendered on the screen in-line Add a file as an attachment to the mail. This file, even if possible, will not be rendered on the screen in-line
@@ -246,7 +246,7 @@ class GMailMessage:
:param attachment_file: The file that you would like to attach. :param attachment_file: The file that you would like to attach.
:param file_name: The name of the file. This is the same name by which it will be downloaded. You need not :param file_name: The name of the file. This is the same name by which it will be downloaded. You need not
specify this if the input file is specified as a path. Needed when you give the input file as a buffer. specify this if the input file is specified as a path. Needed when you give the input file as a buffer.
:return: :return: None.
""" """
# Declare the part to be attached to the multipart message: # Declare the part to be attached to the multipart message:
@@ -277,18 +277,19 @@ class GMailMessage:
def get_raw_message( def get_raw_message(
self, self,
as_base64: bool = True as_base64: bool = False
): ) -> str:
""" """
Get the raw string dump from the current contents of the message. This text will be compliant with RFC 5322 and Get the raw string dump from the current contents of the message. This text will be compliant with RFC 5322 and
RFC 2045 (among others). RFC 2045 (among others).
:param
:param as_base64: If set to True, the response will be a URL-safe B64 output, else it'll be a raw string. :param as_base64: If set to True, the response will be a URL-safe B64 output, else it'll be a raw string.
:return: The standardized raw text dump. either as a raw string or as a Base64 (url-safe) string. :return: The standardized raw text dump. either as a raw string or as a Base64 (url-safe) string.
""" """
if not as_base64: return self.message if as_base64: return base64.urlsafe_b64encode(self.message.as_bytes()).decode()
else: return base64.urlsafe_b64encode(self.message.as_bytes()).decode() else: return self.message.as_string()
# ***************************************************************************************************************** # *****************************************************************************************************************
@@ -300,13 +301,16 @@ class GMailMessage:
if __name__ == "__main__": if __name__ == "__main__":
my_mail = GMailMessage( # Create an instance of a mail message:
my_mail = GmailMessage(
from_email = "sender@gmail.com", from_email = "sender@gmail.com",
to_email = "recipient@gmail.com", to_email = "recipient@gmail.com",
subject = "Bhopli is the best!", subject = "Bhopli is the best!",
cc_emails = None, cc_emails = None,
bcc_emails = None bcc_emails = None
) )
# Add content to it:
my_mail.add_html( my_mail.add_html(
""" """
<!DOCTYPE html> <!DOCTYPE html>
@@ -333,4 +337,13 @@ if __name__ == "__main__":
my_mail.add_text("This is how you should pet her 👇") my_mail.add_text("This is how you should pet her 👇")
my_mail.add_inline_image(r"../../../../data/images/cat_petting.png") my_mail.add_inline_image(r"../../../../data/images/cat_petting.png")
my_mail.add_attachment(r"../../../../data/pdf/sample_label.pdf") my_mail.add_attachment(r"../../../../data/pdf/sample_label.pdf")
print(my_mail.get_raw_message(as_base64 = False))
# Get the raw contents of the message:
mail_raw = my_mail.get_raw_message(as_base64 = False)
print("RAW TYPE:", type(mail_raw))
# Try parsing it:
from utils_v2.string import json
from utils_v2.mail import mail_parser
mail_json = mail_parser.parse(mail_raw)
print("PARSED MAIL (JSON):", json.to_string(mail_json, default = str))