(20241225) Small fix in reconnection attempts for MySQL.
This commit is contained in:
@@ -0,0 +1,384 @@
|
||||
"""
|
||||
|
||||
AUTHOR:
|
||||
|
||||
Khushal P Soonderji
|
||||
|
||||
DATE:
|
||||
|
||||
Created: Wednesday, 18th Sept., 2024
|
||||
Updated: Tuesday, 8th Oct., 2024
|
||||
|
||||
OBJECTIVE:
|
||||
|
||||
To be able to fetch setup credentials and data for any project. This could include things like default values,
|
||||
URLs to assets, etc. While 'data' and 'cred' can be used interchangeably, the idea behind giving two services is
|
||||
for the user of this service to be able to organise his setup variables.
|
||||
|
||||
REFERENCES:
|
||||
|
||||
N/A
|
||||
|
||||
DOWNLOADS:
|
||||
|
||||
N/A
|
||||
|
||||
NOTES:
|
||||
|
||||
N/A
|
||||
|
||||
"""
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** IMPORT ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# To make sibling directories accessible for imports:
|
||||
import sys
|
||||
sys.path.append(".")
|
||||
sys.path.append("..")
|
||||
|
||||
# For using Quart:
|
||||
from quart import Blueprint, current_app, make_response
|
||||
|
||||
# My utils:
|
||||
from utils_v2.string import json
|
||||
from utils_v2.api.codes import StatusCodes, HttpCodes
|
||||
from utils_v2.api.response import ResponseModel
|
||||
from utils_v2.api.async_quart import (
|
||||
set_api_version,
|
||||
read_input,
|
||||
log_request_to_mongo,
|
||||
should_not_be_under_maintenance,
|
||||
only_whitelisted_ips,
|
||||
limit_rate,
|
||||
validate_input,
|
||||
handle_cancelled_request,
|
||||
make_ordered_json
|
||||
)
|
||||
|
||||
# For asynchronous activities:
|
||||
import asyncio
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** MACROS / ONE-TIME INIT ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# Related to Quart:
|
||||
cred_and_data_bp = Blueprint("int_cnd", __name__)
|
||||
|
||||
# related to the operations of this blueprint:
|
||||
JSON_TYPE_INFO = {
|
||||
"cred": {
|
||||
"collection": "_scriptCred"
|
||||
},
|
||||
"data": {
|
||||
"collection": "_scriptData"
|
||||
}
|
||||
}
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** VARIABLES ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# --- Nothing Yet
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** FUNCTIONS ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
@cred_and_data_bp.record_once
|
||||
def init(blueprint_setup_state):
|
||||
|
||||
# This gets called when the blueprint is registered.
|
||||
# Consider this to be a one-time setup for the whole blueprint:
|
||||
pass
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@cred_and_data_bp.route("/<json_type>/set", methods = ["POST", "GET"])
|
||||
@set_api_version(api_version = "2.1.0")
|
||||
@read_input(sanitize_headers = True, sanitize_data = True)
|
||||
@log_request_to_mongo(
|
||||
attr_name = "mongo",
|
||||
project = "internal",
|
||||
log_type = "credData",
|
||||
operation = "set",
|
||||
log_input = False,
|
||||
log_output = True
|
||||
)
|
||||
@should_not_be_under_maintenance(attr_name = "is_under_maintenance")
|
||||
@only_whitelisted_ips(attr_name = "whitelisted_ips")
|
||||
@validate_input(mandatory_header_keys = ["X-Script-Id", "X-Script-Desc"])
|
||||
@handle_cancelled_request()
|
||||
async def set_data(
|
||||
json_type: str = None,
|
||||
inbound_headers: dict = None,
|
||||
inbound_data: dict = None,
|
||||
inbound_files: dict = None,
|
||||
**kwargs
|
||||
):
|
||||
|
||||
"""
|
||||
To set the credentials for a particular script. If the document exists, it will be overwritten. If the document
|
||||
doesn't exist, it will be created. Ideally use this for only the first time setup.
|
||||
:param json_type: The choice from one of the fields of 'JSON_TYPE_INFO'.
|
||||
:param inbound_headers: auto-extracted by the decorators.
|
||||
:param inbound_data: auto-extracted by the decorators.
|
||||
:param inbound_files: auto-extracted by the decorators.
|
||||
:param kwargs: Any number of extra inputs supplied by the decorators.
|
||||
:return: A standard response structure.
|
||||
"""
|
||||
|
||||
# If an invalid choice was made:
|
||||
if json_type not in JSON_TYPE_INFO.keys():
|
||||
return ResponseModel(
|
||||
status_code = StatusCodes.FAILED,
|
||||
message = f"invalid path '{json_type}'",
|
||||
http_code = HttpCodes.BAD_REQUEST
|
||||
)
|
||||
|
||||
# Construct the document:
|
||||
description = inbound_headers.get("X-Script-Desc", "")
|
||||
if len(description) > 200: description = description[:200]
|
||||
document = {
|
||||
"scriptId": inbound_headers["X-Script-Id"],
|
||||
"desc": description,
|
||||
"content": inbound_data
|
||||
}
|
||||
|
||||
# Make an attempt to set the credentials:
|
||||
success = await current_app.mongo.replace_one(
|
||||
collection = JSON_TYPE_INFO[json_type]["collection"],
|
||||
filter = {"scriptId": inbound_headers["X-Script-Id"]},
|
||||
replacement = document,
|
||||
upsert = True,
|
||||
raise_exception = True
|
||||
)
|
||||
|
||||
# Return the response:
|
||||
if success: return ResponseModel(status_code = StatusCodes.OK)
|
||||
else: return ResponseModel(status_code = StatusCodes.FAILED)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@cred_and_data_bp.route("/<json_type>/get", methods = ["POST", "GET"])
|
||||
@set_api_version(api_version = "2.1.0")
|
||||
@read_input(sanitize_headers = True, sanitize_data = True)
|
||||
@log_request_to_mongo(
|
||||
attr_name = "mongo",
|
||||
project = "internal",
|
||||
log_type = "credData",
|
||||
operation = "get",
|
||||
log_input = True,
|
||||
log_output = False
|
||||
)
|
||||
@should_not_be_under_maintenance(attr_name = "is_under_maintenance")
|
||||
@only_whitelisted_ips(attr_name = "whitelisted_ips")
|
||||
@validate_input(mandatory_header_keys = ["X-Script-Id"])
|
||||
@handle_cancelled_request()
|
||||
async def get_data(
|
||||
json_type: str = None,
|
||||
inbound_headers: dict = None,
|
||||
inbound_data: dict = None,
|
||||
inbound_files: dict = None,
|
||||
**kwargs
|
||||
):
|
||||
|
||||
"""
|
||||
To retrieve the credentials stored for a specific script. The script's id can be anything set by the programmers.
|
||||
The idea is to have only the script's id stored in the script, and everything else is fetched from the database.
|
||||
This means that we get to store and update everything from one central location.
|
||||
:param json_type: The choice from one of the fields of 'JSON_TYPE_INFO'.
|
||||
:param inbound_headers: auto-extracted by the decorators.
|
||||
:param inbound_data: auto-extracted by the decorators.
|
||||
:param inbound_files: auto-extracted by the decorators.
|
||||
:param kwargs: Any number of extra inputs supplied by the decorators.
|
||||
:return: A standard response structure.
|
||||
"""
|
||||
|
||||
# If an invalid choice was made:
|
||||
if json_type not in JSON_TYPE_INFO.keys():
|
||||
return ResponseModel(
|
||||
status_code = StatusCodes.FAILED,
|
||||
message = f"invalid path '{json_type}'",
|
||||
http_code = HttpCodes.BAD_REQUEST
|
||||
)
|
||||
|
||||
# Make an attempt to retrieve the credentials:
|
||||
data_json = await current_app.mongo.find_one(
|
||||
collection = JSON_TYPE_INFO[json_type]["collection"],
|
||||
filter = {"scriptId": inbound_headers["X-Script-Id"]},
|
||||
projection = {"_id": False, "scriptId": False},
|
||||
raise_exception = True
|
||||
)
|
||||
|
||||
# In case no result was found:
|
||||
if data_json is None:
|
||||
return ResponseModel(
|
||||
status_code = StatusCodes.FAILED,
|
||||
message = "invalid script id"
|
||||
)
|
||||
|
||||
# Successfully retrieved:
|
||||
json_data, http_code = ResponseModel(
|
||||
status_code = StatusCodes.OK,
|
||||
data = data_json["content"],
|
||||
message = data_json["desc"]
|
||||
).for_quart()
|
||||
return await make_ordered_json(json_data, http_code)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@cred_and_data_bp.route("/<json_type>/update", methods = ["POST", "GET"])
|
||||
@set_api_version(api_version = "2.1.0")
|
||||
@read_input(sanitize_headers = True, sanitize_data = True)
|
||||
@log_request_to_mongo(
|
||||
attr_name = "mongo",
|
||||
project = "internal",
|
||||
log_type = "credData",
|
||||
operation = "update",
|
||||
log_input = False,
|
||||
log_output = True
|
||||
)
|
||||
@should_not_be_under_maintenance(attr_name = "is_under_maintenance")
|
||||
@only_whitelisted_ips(attr_name = "whitelisted_ips")
|
||||
@validate_input(mandatory_header_keys = ["X-Script-Id"])
|
||||
@handle_cancelled_request()
|
||||
async def update_cred(
|
||||
json_type: str = None,
|
||||
inbound_headers: dict = None,
|
||||
inbound_data: dict = None,
|
||||
inbound_files: dict = None,
|
||||
**kwargs
|
||||
):
|
||||
|
||||
"""
|
||||
To update values of certain fields for a credentials document. It only updates existing values, does NOT add a new
|
||||
document if the document doesn't already exist.
|
||||
:param json_type: The choice from one of the fields of 'JSON_TYPE_INFO'.
|
||||
:param inbound_headers: auto-extracted by the decorators.
|
||||
:param inbound_data: auto-extracted by the decorators.
|
||||
:param inbound_files: auto-extracted by the decorators.
|
||||
:param kwargs: Any number of extra inputs supplied by the decorators.
|
||||
:return: A standard response structure.
|
||||
"""
|
||||
|
||||
# If an invalid choice was made:
|
||||
if json_type not in JSON_TYPE_INFO.keys():
|
||||
return ResponseModel(
|
||||
status_code = StatusCodes.FAILED,
|
||||
message = f"invalid path '{json_type}'",
|
||||
http_code = HttpCodes.BAD_REQUEST
|
||||
)
|
||||
|
||||
# Pre-process the inbound data:
|
||||
inbound_data = inbound_data or {}
|
||||
|
||||
# Prepare the update JSON. Pre-process the fields to set and unset.
|
||||
# Our actual data/cred are held inside a field called "content", so we must wrap the request in that:
|
||||
update_json = {}
|
||||
if inbound_data.get("unset"):
|
||||
update_json["$unset"] = current_app.mongo.dict_to_dot_notation({"content": inbound_data["unset"]})
|
||||
if inbound_data.get("set"):
|
||||
update_json["$set"] = current_app.mongo.dict_to_dot_notation({"content": inbound_data["set"]})
|
||||
|
||||
# Make an attempt to set the credentials:
|
||||
success = await current_app.mongo.update_one(
|
||||
collection = JSON_TYPE_INFO[json_type]["collection"],
|
||||
filter = {"scriptId": inbound_headers["X-Script-Id"]},
|
||||
update = update_json,
|
||||
upsert = False,
|
||||
raise_exception = True
|
||||
)
|
||||
|
||||
# Return the response:
|
||||
if success: return ResponseModel(status_code = StatusCodes.OK)
|
||||
else: return ResponseModel(status_code = StatusCodes.FAILED)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@cred_and_data_bp.route("/<json_type>/delete", methods = ["POST", "GET"])
|
||||
@set_api_version(api_version = "2.1.0")
|
||||
@read_input(sanitize_headers = True, sanitize_data = True)
|
||||
@log_request_to_mongo(
|
||||
attr_name = "mongo",
|
||||
project = "internal",
|
||||
log_type = "credData",
|
||||
operation = "delete",
|
||||
log_input = True,
|
||||
log_output = True
|
||||
)
|
||||
@should_not_be_under_maintenance(attr_name = "is_under_maintenance")
|
||||
@only_whitelisted_ips(attr_name = "whitelisted_ips")
|
||||
@validate_input(mandatory_header_keys = ["X-Script-Id"])
|
||||
async def delete_data(
|
||||
json_type: str = None,
|
||||
inbound_headers: dict = None,
|
||||
inbound_data: dict = None,
|
||||
inbound_files: dict = None,
|
||||
**kwargs
|
||||
):
|
||||
|
||||
"""
|
||||
To delete a document for a particular script id.
|
||||
:param json_type: The choice from one of the fields of 'JSON_TYPE_INFO'.
|
||||
:param inbound_headers: auto-extracted by the decorators.
|
||||
:param inbound_data: auto-extracted by the decorators.
|
||||
:param inbound_files: auto-extracted by the decorators.
|
||||
:param kwargs: Any number of extra inputs supplied by the decorators.
|
||||
:return: A standard response structure.
|
||||
"""
|
||||
|
||||
# If an invalid choice was made:
|
||||
if json_type not in JSON_TYPE_INFO.keys():
|
||||
return ResponseModel(
|
||||
status_code = StatusCodes.FAILED,
|
||||
message = f"invalid path '{json_type}'",
|
||||
http_code = HttpCodes.BAD_REQUEST
|
||||
)
|
||||
|
||||
# Make an attempt to set the credentials:
|
||||
success = await current_app.mongo.delete_one(
|
||||
collection = JSON_TYPE_INFO[json_type]["collection"],
|
||||
filter = {"scriptId": inbound_headers["X-Script-Id"]},
|
||||
)
|
||||
|
||||
# Return the response:
|
||||
if success: return ResponseModel(status_code = StatusCodes.OK)
|
||||
else: return ResponseModel(status_code = StatusCodes.FAILED)
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** MAIN PROGRAM ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
pass
|
||||
@@ -0,0 +1,216 @@
|
||||
"""
|
||||
|
||||
AUTHOR:
|
||||
|
||||
Khushal P Soonderji
|
||||
|
||||
DATE:
|
||||
|
||||
Wednesday, 25th Dec., 2024.
|
||||
|
||||
OBJECTIVE:
|
||||
|
||||
To provide a structure to work with requests surrounding Cred and Data handling.
|
||||
|
||||
REFERENCES:
|
||||
|
||||
N/A
|
||||
|
||||
DOWNLOADS:
|
||||
|
||||
N/A
|
||||
|
||||
"""
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** IMPORT ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# To make sibling directories accessible for imports:
|
||||
import sys
|
||||
sys.path.append(".")
|
||||
sys.path.append("..")
|
||||
|
||||
# For making data behaviour_models:
|
||||
from pydantic import BaseModel, Field, field_validator, PastDatetime, model_validator
|
||||
from typing import Optional, Literal, Union
|
||||
|
||||
# My utils:
|
||||
from utils_v2.string import regex
|
||||
from utils_v2.date_time import date_time
|
||||
|
||||
# To work with date and time:
|
||||
import datetime
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** MACROS / ONE-TIME INIT ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# --- Nothing Yet
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** VARIABLES ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# --- Nothing Yet
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** FUNCTIONS ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
class CredAndDataSetRequestHeaders(BaseModel):
|
||||
|
||||
scriptId: str = Field(
|
||||
description = "the id of the script for whom you are setting cred/data",
|
||||
frozen = True,
|
||||
alias = "X-Script-Id"
|
||||
)
|
||||
|
||||
scriptDescription: str = Field(
|
||||
description = "a short description of the script and what it does",
|
||||
frozen = True,
|
||||
alias = "X-Script-Desc"
|
||||
)
|
||||
|
||||
# ┏┓ ┏•
|
||||
# ┃ ┏┓┏┓╋┓┏┓
|
||||
# ┗┛┗┛┛┗┛┗┗┫
|
||||
# ┛
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
def model_dump(self, *args, **kwargs):
|
||||
return super().model_dump(*args, by_alias = True, **kwargs)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
class CredAndDataGetRequestHeaders(BaseModel):
|
||||
|
||||
scriptId: str = Field(
|
||||
description = "the id of the script for whom you are getting cred/data",
|
||||
frozen = True,
|
||||
alias = "X-Script-Id"
|
||||
)
|
||||
|
||||
# ┏┓ ┏•
|
||||
# ┃ ┏┓┏┓╋┓┏┓
|
||||
# ┗┛┗┛┛┗┛┗┗┫
|
||||
# ┛
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
def model_dump(self, *args, **kwargs):
|
||||
return super().model_dump(*args, by_alias = True, **kwargs)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
class CredAndDataUpdateRequestHeaders(BaseModel):
|
||||
|
||||
scriptId: str = Field(
|
||||
description = "the id of the script for whom you are updating cred/data",
|
||||
frozen = True,
|
||||
alias = "X-Script-Id"
|
||||
)
|
||||
|
||||
# ┏┓ ┏•
|
||||
# ┃ ┏┓┏┓╋┓┏┓
|
||||
# ┗┛┗┛┛┗┛┗┗┫
|
||||
# ┛
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
def model_dump(self, *args, **kwargs):
|
||||
return super().model_dump(*args, by_alias = True, **kwargs)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
class CredAndDataUpdateRequestData(BaseModel):
|
||||
|
||||
unsetJson: dict = Field(
|
||||
description = "the items to unset; this is performed first",
|
||||
frozen = True,
|
||||
alias = "unset"
|
||||
)
|
||||
|
||||
setJson: dict = Field(
|
||||
description = "the items to set; this is performed after the 'unset' operation",
|
||||
frozen = True,
|
||||
alias = "set"
|
||||
)
|
||||
|
||||
# ┏┓ ┏•
|
||||
# ┃ ┏┓┏┓╋┓┏┓
|
||||
# ┗┛┗┛┛┗┛┗┗┫
|
||||
# ┛
|
||||
|
||||
class Config:
|
||||
extra = "forbid"
|
||||
|
||||
# ┓┏ ┓• ┓ •
|
||||
# ┃┃┏┓┃┓┏┫┏┓╋┓┏┓┏┓
|
||||
# ┗┛┗┻┗┗┗┻┗┻┗┗┗┛┛┗
|
||||
|
||||
@field_validator("unsetJson", "setJson", mode = "before")
|
||||
def ensure_non_null(cls, value):
|
||||
if value is None: value = {}
|
||||
return value
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
class CredAndDataDeleteRequestHeaders(BaseModel):
|
||||
|
||||
scriptId: str = Field(
|
||||
description = "the id of the script for whom you are deleting cred/data",
|
||||
frozen = True,
|
||||
alias = "X-Script-Id"
|
||||
)
|
||||
|
||||
# ┏┓ ┏•
|
||||
# ┃ ┏┓┏┓╋┓┏┓
|
||||
# ┗┛┗┛┛┗┛┗┗┫
|
||||
# ┛
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
def model_dump(self, *args, **kwargs):
|
||||
return super().model_dump(*args, by_alias = True, **kwargs)
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** MAIN PROGRAM ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
pass
|
||||
@@ -0,0 +1,135 @@
|
||||
"""
|
||||
|
||||
AUTHOR:
|
||||
|
||||
Khushal P Soonderji
|
||||
|
||||
DATE:
|
||||
|
||||
Wednesday, 25th Dec., 2024.
|
||||
|
||||
OBJECTIVE:
|
||||
|
||||
To provide a structure to work with requests surrounding Log handling.
|
||||
|
||||
REFERENCES:
|
||||
|
||||
N/A
|
||||
|
||||
DOWNLOADS:
|
||||
|
||||
N/A
|
||||
|
||||
"""
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** IMPORT ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# To make sibling directories accessible for imports:
|
||||
import sys
|
||||
sys.path.append(".")
|
||||
sys.path.append("..")
|
||||
|
||||
# For making data behaviour_models:
|
||||
from pydantic import BaseModel, Field, field_validator, PastDatetime, model_validator
|
||||
from typing import Optional, Literal, Union
|
||||
|
||||
# My utils:
|
||||
from utils_v2.string import regex
|
||||
from utils_v2.date_time import date_time
|
||||
|
||||
# To work with date and time:
|
||||
import datetime
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** MACROS / ONE-TIME INIT ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# --- Nothing Yet
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** VARIABLES ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# --- Nothing Yet
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** FUNCTIONS ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
class LogsByFilterRequestData(BaseModel):
|
||||
|
||||
filter: dict = Field(
|
||||
description = "the filter condition(s) while picking logs",
|
||||
frozen = True
|
||||
)
|
||||
|
||||
limit: int = Field(
|
||||
description = "the max. logs to pick",
|
||||
default = 25,
|
||||
frozen = True
|
||||
)
|
||||
|
||||
skip: int = Field(
|
||||
description = "how many initial matches to skip before picking logs; needed for pagination",
|
||||
default = 0,
|
||||
frozen = True
|
||||
)
|
||||
|
||||
sort: dict = Field(
|
||||
description = "the sorting conditions for the picked logs",
|
||||
default = {"_id": -1},
|
||||
frozen = True
|
||||
)
|
||||
|
||||
projection: dict = Field(
|
||||
description = "to decide what fields are retrieved",
|
||||
default = {"_id": False},
|
||||
frozen = True
|
||||
)
|
||||
|
||||
# ┏┓ ┏•
|
||||
# ┃ ┏┓┏┓╋┓┏┓
|
||||
# ┗┛┗┛┛┗┛┗┗┫
|
||||
# ┛
|
||||
|
||||
class Config:
|
||||
extra = "forbid"
|
||||
|
||||
# ┓┏ ┓• ┓ •
|
||||
# ┃┃┏┓┃┓┏┫┏┓╋┓┏┓┏┓
|
||||
# ┗┛┗┻┗┗┗┻┗┻┗┗┗┛┛┗
|
||||
|
||||
@field_validator("unsetJson", "setJson", mode = "before")
|
||||
def ensure_non_null(cls, value):
|
||||
if value is None: value = {}
|
||||
return value
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** MAIN PROGRAM ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
pass
|
||||
@@ -0,0 +1,216 @@
|
||||
"""
|
||||
|
||||
AUTHOR:
|
||||
|
||||
Khushal P Soonderji
|
||||
|
||||
DATE:
|
||||
|
||||
Wednesday, 25th Dec., 2024.
|
||||
|
||||
OBJECTIVE:
|
||||
|
||||
To provide a structure to work with requests surrounding Cred and Data handling.
|
||||
|
||||
REFERENCES:
|
||||
|
||||
N/A
|
||||
|
||||
DOWNLOADS:
|
||||
|
||||
N/A
|
||||
|
||||
"""
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** IMPORT ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# To make sibling directories accessible for imports:
|
||||
import sys
|
||||
sys.path.append(".")
|
||||
sys.path.append("..")
|
||||
|
||||
# For making data behaviour_models:
|
||||
from pydantic import BaseModel, Field, field_validator, PastDatetime, model_validator
|
||||
from typing import Optional, Literal, Union
|
||||
|
||||
# My utils:
|
||||
from utils_v2.string import regex
|
||||
from utils_v2.date_time import date_time
|
||||
|
||||
# To work with date and time:
|
||||
import datetime
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** MACROS / ONE-TIME INIT ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# --- Nothing Yet
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** VARIABLES ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# --- Nothing Yet
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** FUNCTIONS ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
class CredAndDataSetRequestHeaders(BaseModel):
|
||||
|
||||
scriptId: str = Field(
|
||||
description = "the id of the script for whom you are setting cred/data",
|
||||
frozen = True,
|
||||
alias = "X-Script-Id"
|
||||
)
|
||||
|
||||
scriptDescription: str = Field(
|
||||
description = "a short description of the script and what it does",
|
||||
frozen = True,
|
||||
alias = "X-Script-Desc"
|
||||
)
|
||||
|
||||
# ┏┓ ┏•
|
||||
# ┃ ┏┓┏┓╋┓┏┓
|
||||
# ┗┛┗┛┛┗┛┗┗┫
|
||||
# ┛
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
def model_dump(self, *args, **kwargs):
|
||||
return super().model_dump(*args, by_alias = True, **kwargs)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
class CredAndDataGetRequestHeaders(BaseModel):
|
||||
|
||||
scriptId: str = Field(
|
||||
description = "the id of the script for whom you are getting cred/data",
|
||||
frozen = True,
|
||||
alias = "X-Script-Id"
|
||||
)
|
||||
|
||||
# ┏┓ ┏•
|
||||
# ┃ ┏┓┏┓╋┓┏┓
|
||||
# ┗┛┗┛┛┗┛┗┗┫
|
||||
# ┛
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
def model_dump(self, *args, **kwargs):
|
||||
return super().model_dump(*args, by_alias = True, **kwargs)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
class CredAndDataUpdateRequestHeaders(BaseModel):
|
||||
|
||||
scriptId: str = Field(
|
||||
description = "the id of the script for whom you are updating cred/data",
|
||||
frozen = True,
|
||||
alias = "X-Script-Id"
|
||||
)
|
||||
|
||||
# ┏┓ ┏•
|
||||
# ┃ ┏┓┏┓╋┓┏┓
|
||||
# ┗┛┗┛┛┗┛┗┗┫
|
||||
# ┛
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
def model_dump(self, *args, **kwargs):
|
||||
return super().model_dump(*args, by_alias = True, **kwargs)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
class CredAndDataUpdateRequestData(BaseModel):
|
||||
|
||||
unsetJson: dict = Field(
|
||||
description = "the items to unset; this is performed first",
|
||||
frozen = True,
|
||||
alias = "unset"
|
||||
)
|
||||
|
||||
setJson: dict = Field(
|
||||
description = "the items to set; this is performed after the 'unset' operation",
|
||||
frozen = True,
|
||||
alias = "set"
|
||||
)
|
||||
|
||||
# ┏┓ ┏•
|
||||
# ┃ ┏┓┏┓╋┓┏┓
|
||||
# ┗┛┗┛┛┗┛┗┗┫
|
||||
# ┛
|
||||
|
||||
class Config:
|
||||
extra = "forbid"
|
||||
|
||||
# ┓┏ ┓• ┓ •
|
||||
# ┃┃┏┓┃┓┏┫┏┓╋┓┏┓┏┓
|
||||
# ┗┛┗┻┗┗┗┻┗┻┗┗┗┛┛┗
|
||||
|
||||
@field_validator("unsetJson", "setJson", mode = "before")
|
||||
def ensure_non_null(cls, value):
|
||||
if value is None: value = {}
|
||||
return value
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
class CredAndDataDeleteRequestHeaders(BaseModel):
|
||||
|
||||
scriptId: str = Field(
|
||||
description = "the id of the script for whom you are deleting cred/data",
|
||||
frozen = True,
|
||||
alias = "X-Script-Id"
|
||||
)
|
||||
|
||||
# ┏┓ ┏•
|
||||
# ┃ ┏┓┏┓╋┓┏┓
|
||||
# ┗┛┗┛┛┗┛┗┗┫
|
||||
# ┛
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
def model_dump(self, *args, **kwargs):
|
||||
return super().model_dump(*args, by_alias = True, **kwargs)
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** MAIN PROGRAM ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
pass
|
||||
@@ -0,0 +1,216 @@
|
||||
"""
|
||||
|
||||
AUTHOR:
|
||||
|
||||
Khushal P Soonderji
|
||||
|
||||
DATE:
|
||||
|
||||
Wednesday, 25th Dec., 2024.
|
||||
|
||||
OBJECTIVE:
|
||||
|
||||
To provide a structure to work with requests surrounding Cred and Data handling.
|
||||
|
||||
REFERENCES:
|
||||
|
||||
N/A
|
||||
|
||||
DOWNLOADS:
|
||||
|
||||
N/A
|
||||
|
||||
"""
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** IMPORT ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# To make sibling directories accessible for imports:
|
||||
import sys
|
||||
sys.path.append(".")
|
||||
sys.path.append("..")
|
||||
|
||||
# For making data behaviour_models:
|
||||
from pydantic import BaseModel, Field, field_validator, PastDatetime, model_validator
|
||||
from typing import Optional, Literal, Union
|
||||
|
||||
# My utils:
|
||||
from utils_v2.string import regex
|
||||
from utils_v2.date_time import date_time
|
||||
|
||||
# To work with date and time:
|
||||
import datetime
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** MACROS / ONE-TIME INIT ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# --- Nothing Yet
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** VARIABLES ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# --- Nothing Yet
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** FUNCTIONS ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
class CredAndDataSetRequestHeaders(BaseModel):
|
||||
|
||||
scriptId: str = Field(
|
||||
description = "the id of the script for whom you are setting cred/data",
|
||||
frozen = True,
|
||||
alias = "X-Script-Id"
|
||||
)
|
||||
|
||||
scriptDescription: str = Field(
|
||||
description = "a short description of the script and what it does",
|
||||
frozen = True,
|
||||
alias = "X-Script-Desc"
|
||||
)
|
||||
|
||||
# ┏┓ ┏•
|
||||
# ┃ ┏┓┏┓╋┓┏┓
|
||||
# ┗┛┗┛┛┗┛┗┗┫
|
||||
# ┛
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
def model_dump(self, *args, **kwargs):
|
||||
return super().model_dump(*args, by_alias = True, **kwargs)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
class CredAndDataGetRequestHeaders(BaseModel):
|
||||
|
||||
scriptId: str = Field(
|
||||
description = "the id of the script for whom you are getting cred/data",
|
||||
frozen = True,
|
||||
alias = "X-Script-Id"
|
||||
)
|
||||
|
||||
# ┏┓ ┏•
|
||||
# ┃ ┏┓┏┓╋┓┏┓
|
||||
# ┗┛┗┛┛┗┛┗┗┫
|
||||
# ┛
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
def model_dump(self, *args, **kwargs):
|
||||
return super().model_dump(*args, by_alias = True, **kwargs)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
class CredAndDataUpdateRequestHeaders(BaseModel):
|
||||
|
||||
scriptId: str = Field(
|
||||
description = "the id of the script for whom you are updating cred/data",
|
||||
frozen = True,
|
||||
alias = "X-Script-Id"
|
||||
)
|
||||
|
||||
# ┏┓ ┏•
|
||||
# ┃ ┏┓┏┓╋┓┏┓
|
||||
# ┗┛┗┛┛┗┛┗┗┫
|
||||
# ┛
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
def model_dump(self, *args, **kwargs):
|
||||
return super().model_dump(*args, by_alias = True, **kwargs)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
class CredAndDataUpdateRequestData(BaseModel):
|
||||
|
||||
unsetJson: dict = Field(
|
||||
description = "the items to unset; this is performed first",
|
||||
frozen = True,
|
||||
alias = "unset"
|
||||
)
|
||||
|
||||
setJson: dict = Field(
|
||||
description = "the items to set; this is performed after the 'unset' operation",
|
||||
frozen = True,
|
||||
alias = "set"
|
||||
)
|
||||
|
||||
# ┏┓ ┏•
|
||||
# ┃ ┏┓┏┓╋┓┏┓
|
||||
# ┗┛┗┛┛┗┛┗┗┫
|
||||
# ┛
|
||||
|
||||
class Config:
|
||||
extra = "forbid"
|
||||
|
||||
# ┓┏ ┓• ┓ •
|
||||
# ┃┃┏┓┃┓┏┫┏┓╋┓┏┓┏┓
|
||||
# ┗┛┗┻┗┗┗┻┗┻┗┗┗┛┛┗
|
||||
|
||||
@field_validator("unsetJson", "setJson", mode = "before")
|
||||
def ensure_non_null(cls, value):
|
||||
if value is None: value = {}
|
||||
return value
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
class CredAndDataDeleteRequestHeaders(BaseModel):
|
||||
|
||||
scriptId: str = Field(
|
||||
description = "the id of the script for whom you are deleting cred/data",
|
||||
frozen = True,
|
||||
alias = "X-Script-Id"
|
||||
)
|
||||
|
||||
# ┏┓ ┏•
|
||||
# ┃ ┏┓┏┓╋┓┏┓
|
||||
# ┗┛┗┛┛┗┛┗┗┫
|
||||
# ┛
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
def model_dump(self, *args, **kwargs):
|
||||
return super().model_dump(*args, by_alias = True, **kwargs)
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** MAIN PROGRAM ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
pass
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -96,7 +96,7 @@ import copy
|
||||
ALPHANUMERIC_CHARS = string.ascii_letters + string.digits
|
||||
|
||||
# To capture system information:
|
||||
PROCESS_ID = os.getppid()
|
||||
PROCESS_ID = os.getpid()
|
||||
PARENT_PROCESS_ID = os.getppid()
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -129,7 +129,7 @@ class AsyncMySQL:
|
||||
|
||||
try:
|
||||
|
||||
self.__kwargs["db"] = self.__kwargs.pop("database")
|
||||
self.__kwargs["db"] = self.__kwargs.pop("database", self.__kwargs["db"])
|
||||
self.__pool = await aiomysql.create_pool(
|
||||
minsize = self.__min_pool_size,
|
||||
maxsize = self.__max_pool_size,
|
||||
@@ -220,17 +220,6 @@ class AsyncMySQL:
|
||||
all_result_sets = await self.fetch_all(cursor)
|
||||
if commit: await connection.commit()
|
||||
|
||||
# # Iterate over all result sets,
|
||||
# # and process them one-by-one:
|
||||
# while True:
|
||||
# this_result_set = []
|
||||
# result = await cursor.fetchall()
|
||||
# if not cursor.description: break
|
||||
# columns = [desc[0] for desc in cursor.description]
|
||||
# for row in result: this_result_set.append(dict(zip(columns, self.__parse_row(row))))
|
||||
# all_result_sets.append(this_result_set)
|
||||
# await cursor.nextset()
|
||||
|
||||
# Done here:
|
||||
return all_result_sets
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user