Merge commit '8c35c01ede8520982232f65f77bf5a8df1ac5ed0' as 'utils_v2'

This commit is contained in:
2024-12-05 14:47:24 +05:30
143 changed files with 128462 additions and 0 deletions
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff
+164
View File
@@ -0,0 +1,164 @@
"""
AUTHOR:
Khushal P Soonderji
DATE:
Thursday, 12th Sept., 2024
OBJECTIVE:
To maintain all status codes in one place.
REFERENCES:
N/A
DOWNLOADS:
N/A
"""
# *****************************************************************************************************************
# ***** ****
# *** IMPORT ***
# ***** ****
# *****************************************************************************************************************
from enum import Enum, unique
# *****************************************************************************************************************
# ***** ****
# *** MACROS / ONE-TIME INIT ***
# ***** ****
# *****************************************************************************************************************
@unique
class HttpCodes(Enum):
"""
Commonly used standard HTTP status codes.
Can be sent after an API Call is processed.
Refer to: https://http.dev/status
NOTE: THIS LIST IS NOT EXHAUSTIVE!
"""
# 1XX - Informational:
CONTINUE = 100 # .............. https://http.dev/102
SWITCHING_PROTOCOLS = 101 # ... https://http.dev/101
PROCESSING = 102 # ............ https://http.dev/102
EARLY_HINTS = 103 # ........... https://http.dev/103
# 2XX - Success:
SUCCESS = 200 # .................. https://http.dev/200
CREATED = 201 # .................. https://http.dev/201
ACCEPTED = 202 # ................. https://http.dev/202
NON_AUTHORITATIVE_INFO = 203 # ... https://http.dev/203
NO_CONTENT = 204 # ............... https://http.dev/204
RESET_CONTENT = 205 # ............ https://http.dev/205
PARTIAL_CONTENT = 206 # .......... https://http.dev/206
MULTI_STATUS = 207 # ............. https://http.dev/207
ALREADY_REPORTED = 208 # ......... https://http.dev/208
THIS_IS_FINE = 218 # ............. https://http.dev/218
IM_USED = 226 # .................. https://http.dev/226
# 3XX - Redirection:
MULTIPLE_CHOICES = 300 # ..... https://http.dev/300
MOVED_PERMANENTLY = 301 # .... https://http.dev/301
MOVED_TEMPORARILY = 302 # .... https://http.dev/302
SEE_OTHER = 303 # ............ https://http.dev/303
NOT_MODIFIED = 304 # ......... https://http.dev/304
USE_PROXY = 305 # ............ https://http.dev/305
SWITCH_PROXY = 306 # ......... https://http.dev/306
TEMPORARY_REDIRECT = 307 # ... https://http.dev/307
PERMANENT_REDIRECT = 308 # ... https://http.dev/308
# 4XX - Client Errors:
BAD_REQUEST = 400 # ..................... https://http.dev/401
UNAUTHORIZED = 401 # .................... https://http.dev/401
PAYMENT_REQUIRED = 402 # ................ https://http.dev/402
FORBIDDEN = 403 # ....................... https://http.dev/403
NOT_FOUND = 404 # ....................... https://http.dev/404
METHOD_NOT_ALLOWED = 405 # .............. https://http.dev/405
NOT_ACCEPTABLE = 406 # .................. https://http.dev/406
PROXY_AUTH_REQUIRED = 407 # ............. https://http.dev/407
REQUEST_TIMEOUT = 408 # ................. https://http.dev/408
CONFLICT = 409 # ........................ https://http.dev/409
GONE = 410 # ............................ https://http.dev/410
LENGTH_REQUIRED = 411 # ................. https://http.dev/411
PRECONDITION_FAILED = 412 # ............. https://http.dev/412
PAYLOAD_TOO_LARGE = 413 # ............... https://http.dev/413
URI_TOO_LONG = 414 # .................... https://http.dev/414
UNSUPPORTED_MEDIA_TYPE = 415 # .......... https://http.dev/415
PAGE_EXPIRED = 419 # .................... https://http.dev/419
TOO_MANY_REQUESTS = 429 # ............... https://http.dev/429
UNAVAILABLE_FOR_LEGAL_REASONS = 451 # ... https://http.dev/451
INVALID_TOKEN = 498 # ................... https://http.dev/498
CLIENT_CLOSED_REQUEST = 499 # ........... https://http.dev/499
# 5XX - Server Errors:
INTERNAL_SERVER_ERROR = 500 # ........... https://http.dev/500
NOT_IMPLEMENTED = 501 # ................. https://http.dev/501
BAD_GATEWAY = 502 # ..................... https://http.dev/502
SERVICE_UNAVAILABLE = 503 # ............. https://http.dev/503
GATEWAY_TIMEOUT = 504 # ................. https://http.dev/504
HTTP_VERSION_NOT_SUPPORTED = 505 # ...... https://http.dev/505
VARIANT_ALSO_NEGOTIATES = 506 # ......... https://http.dev/506
INSUFFICIENT_STORAGE = 507 # ............ https://http.dev/507
LOOP_DETECTED = 508 # ................... https://http.dev/508
BANDWIDTH_LIMIT_EXCEEDED = 509 # ........ https://http.dev/509
WEB_SERVER_DOWN = 521 # ................. https://http.dev/521
ORIGIN_IS_UNREACHABLE = 523 # ........... https://http.dev/523
SERVICE_IS_OVERLOADED = 529 # ........... https://http.dev/529
NETWORK_READ_TIMEOUT_ERROR = 598 # ...... https://http.dev/598
NETWORK_CONNECT_TIMEOUT_ERROR = 599 # ... https://http.dev/599
# ---------------------------------------------------------------------------------------------------------------------
@unique
class StatusCodes(Enum):
"""
To be used internally within the context of your service. Customize these to match your service.
The format is: (SUCCESS_INDICATOR, INTERNAL_NUMERIC_CODE, HTTP_CODE)
Example: (True, 1, 200)
"""
# Legacy Codes:
OK = (True, 1, HttpCodes.SUCCESS.value)
FAILED = (False, 0, HttpCodes.INTERNAL_SERVER_ERROR.value)
PARTIAL_SUCCESS = (True, 2, HttpCodes.PARTIAL_CONTENT.value)
PARTIAL_FAILURE = (False, 3, HttpCodes.PARTIAL_CONTENT.value)
# Authentication Codes:
LOGGED_IN_SUCCESSFULLY = (True, 200, HttpCodes.SUCCESS.value)
LOGIN_FAILED = (False, 201, HttpCodes.UNAUTHORIZED.value)
INVALID_SESSION_TOKEN = (False, 202, HttpCodes.UNAUTHORIZED.value)
AUTHENTICATION_DETAILS_INCOMPLETE = (False, 203, HttpCodes.BAD_REQUEST.value)
# Authorization Codes:
AUTHORIZED_SUCCESSFULLY = (True, 300, HttpCodes.SUCCESS.value)
NOT_ALLOWED = (False, 301, HttpCodes.FORBIDDEN.value)
AUTHORIZATION_DETAILS_INCOMPLETE = (False, 302, HttpCodes.BAD_REQUEST.value)
AUTHORIZATION_FAILED = (False, 303, HttpCodes.UNAUTHORIZED.value)
# General failures:
DOWN_FOR_MAINTENANCE = (False, 800, HttpCodes.SERVICE_UNAVAILABLE.value)
UNKNOWN_ERROR = (False, 801, HttpCodes.INTERNAL_SERVER_ERROR.value)
DATA_INCOMPLETE = (False, 802, HttpCodes.BAD_REQUEST.value)
HEADERS_INCOMPLETE = (False, 803, HttpCodes.BAD_REQUEST.value)
FILES_MISSING = (False, 804, HttpCodes.BAD_REQUEST.value)
CLIENT_CLOSED_REQUEST = (False, 805, HttpCodes.CLIENT_CLOSED_REQUEST.value)
# Validation failure:
DATA_VALIDATION_FAILURE = (False, 900, HttpCodes.BAD_REQUEST.value)
RATE_LIMIT_EXCEEDED = (False, 901, HttpCodes.TOO_MANY_REQUESTS.value)
+139
View File
@@ -0,0 +1,139 @@
"""
AUTHOR:
Khushal P Soonderji
DATE:
Thursday, 12th Sept., 2024
OBJECTIVE:
To have a structure to the response sent from the API calls.
REFERENCES:
N/A
DOWNLOADS:
N/A
"""
# *****************************************************************************************************************
# ***** ****
# *** IMPORT ***
# ***** ****
# *****************************************************************************************************************
# System-level activities:
import distro
import socket
import platform
# For data-modelling:
from pydantic import BaseModel, Field
from typing import Any, Optional, List, Literal
# To work with date and time:
import datetime
# *****************************************************************************************************************
# ***** ****
# *** MACROS / ONE-TIME INIT ***
# ***** ****
# *****************************************************************************************************************
# Info for logging that will stay constant during runtime:
SERVER_HOSTNAME = str(socket.gethostname())
PLATFORM_INFO = platform.uname()
HOST_OS = str(distro.name(True))
HOST_CPU = f"{PLATFORM_INFO.processor} ({PLATFORM_INFO.machine})"
# *****************************************************************************************************************
# ***** ****
# *** VARIABLES ***
# ***** ****
# *****************************************************************************************************************
# --- Nothing Yet
# *****************************************************************************************************************
# ***** ****
# *** CLASSES ***
# ***** ****
# *****************************************************************************************************************
class APILogModel(BaseModel):
# To identify the machine the code is running on.
# DO NOT MODIFY THESE:
hostname: str = SERVER_HOSTNAME
os: str = HOST_OS
cpu: str = HOST_CPU
# Can modify these:
pid: Optional[Any] = None
ppid: Optional[Any] = None
# To identify the project and actions:
project: Optional[str] = None
log: str
operation: str
apiVer: Optional[str] = None
logId: Optional[str] = None
logChain: Optional[str] = None
# Timing metrics:
ts: datetime.datetime
tat: float
cpuTime: float
# To understand the request that came in:
sessionInfo: Optional[Any] = None
method: Optional[str] = None
url: Optional[str] = None
route: Optional[str] = None
headers: Optional[Any] = None
data: Optional[Any] = None
files: Optional[Any] = None
# To understand the output that went out:
exception: Optional[Any] = None
response: Optional[Any] = None
httpCode: Optional[int] = None
# *****************************************************************************************************************
# ***** ****
# *** FUNCTIONS ***
# ***** ****
# *****************************************************************************************************************
# --- Nothing Yet
# *****************************************************************************************************************
# ***** ****
# *** MAIN PROGRAM ***
# ***** ****
# *****************************************************************************************************************
if __name__ == "__main__":
my_log = APILogModel(
log = "internal"
)
print(my_log)
+133
View File
@@ -0,0 +1,133 @@
"""
AUTHOR:
Khushal P Soonderji
DATE:
Thursday, 12th Sept., 2024
OBJECTIVE:
To have a structure to the response sent from the API calls.
REFERENCES:
N/A
DOWNLOADS:
N/A
"""
# *****************************************************************************************************************
# ***** ****
# *** IMPORT ***
# ***** ****
# *****************************************************************************************************************
# For data-modelling:
from pydantic import BaseModel
from typing import Any, Optional, List
# My utils:
from utils_v2.api.codes import StatusCodes, HttpCodes
# *****************************************************************************************************************
# ***** ****
# *** MACROS / ONE-TIME INIT ***
# ***** ****
# *****************************************************************************************************************
# --- Nothing Yet
# *****************************************************************************************************************
# ***** ****
# *** VARIABLES ***
# ***** ****
# *****************************************************************************************************************
# --- Nothing Yet
# *****************************************************************************************************************
# ***** ****
# *** CLASSES ***
# ***** ****
# *****************************************************************************************************************
class ResponseModel(BaseModel):
"""
A model for how the response should be when developing API endpoints.
"""
# The fields that you want in your response:
status_code: StatusCodes
message: Optional[str | List] = None
data: Optional[Any] = None
seconds: Optional[float | int] = None
log_id: Optional[str] = None
http_code: Optional[HttpCodes] = None
api_version: Optional[str] = None
def for_quart(self):
"""
Call this when you are using either Flask or Quart as your framework.
:return: The output as expected by Flask and Quart.
"""
# Construct the basic structure:
response_dict = {
"status": 1 if self.status_code.value[0] else 0,
"code": self.status_code.value[1],
"message": self.message or self.status_code.name.replace("_", " ").lower(),
"data": self.data,
"apiVer": self.api_version
}
# Now add the additional fields:
if self.seconds is not None: response_dict["seconds"] = self.seconds
if self.log_id is not None: response_dict["logId"] = self.log_id
# Figure out the HTTP code:
response_http_code = self.http_code.value if self.http_code is not None else self.status_code.value[2]
# Done here:
return response_dict, response_http_code
# *****************************************************************************************************************
# ***** ****
# *** FUNCTIONS ***
# ***** ****
# *****************************************************************************************************************
# --- Nothing Yet
# *****************************************************************************************************************
# ***** ****
# *** MAIN PROGRAM ***
# ***** ****
# *****************************************************************************************************************
if __name__ == "__main__":
my_response = ResponseModel(
status_code = StatusCodes.RATE_LIMIT_EXCEEDED
)
my_response.log_id = "abc123"
print(my_response.for_quart())