Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/CI_APIUtils.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
with_caching: false

testbed_hello_local:
name: HelloAPI Testbed
name: HelloAPI Local Testbed
needs: build
uses: ./.github/workflows/TEST_HelloAPI_local.yml

Expand Down Expand Up @@ -96,6 +96,6 @@ jobs:
run: echo "Deployed to ${{ env.DEPLOY_URL }}"

testbed_hello_remote:
name: APIUtils Testbed
name: HelloAPI Remote Testbed
needs: deploy_helloapi
uses: ./.github/workflows/TEST_HelloAPI_remote.yml
4 changes: 3 additions & 1 deletion .github/workflows/TEST_APIResponse.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ jobs:
uses: opengamedata/setup-ogd-py-dependencies@v1.0
with:
python_version: ${{ vars.OGD_PYTHON_VERSION }}
- name: Local self-install
run: python -m pip install -e .
- name: Set up Config File
uses: ./.github/actions/test_config
with:
Expand All @@ -45,7 +47,7 @@ jobs:

# 3. Perform export
- name: Execute testbed
run: python -m unittest discover -s tests/cases/utils -p "t_APIResponse.py" -t ./
run: python -m unittest discover -s tests/cases/models -p "t_APIResponse.py" -t ./

# 4. Cleanup & complete
- name: Upload logs as artifacts
Expand Down
18 changes: 10 additions & 8 deletions src/ogd/apis/HelloAPI.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@

# import locals
from ogd.apis.configs.ServerConfig import ServerConfig
from ogd.apis.utils.APIResponse import APIResponse, RESTType, ResponseStatus
from ogd.apis.models.enums.ResponseStatus import ResponseStatus
from ogd.apis.models.enums.RESTType import RESTType
from ogd.apis.models.APIResponse import APIResponse

class HelloAPI:
@staticmethod
Expand All @@ -32,23 +34,23 @@ def get(self):
req_type = RESTType.GET,
val = None,
msg = "Hello! You GETted successfully!",
status = ResponseStatus.SUCCESS)
status = ResponseStatus.OK)
return ret_val.AsDict

def post(self):
ret_val = APIResponse(
req_type = RESTType.POST,
val = None,
msg = "Hello! You POSTed successfully!",
status = ResponseStatus.SUCCESS)
status = ResponseStatus.OK)
return ret_val.AsDict

def put(self):
ret_val = APIResponse(
req_type = RESTType.PUT,
val = None,
msg = "Hello! You PUTted successfully!",
status = ResponseStatus.SUCCESS)
status = ResponseStatus.OK)
return ret_val.AsDict

class ParamHello(Resource):
Expand All @@ -57,23 +59,23 @@ def get(self, name):
req_type = RESTType.GET,
val = None,
msg = f"Hello {name}! You GETted successfully!",
status = ResponseStatus.SUCCESS)
status = ResponseStatus.OK)
return ret_val.AsDict

def post(self, name):
ret_val = APIResponse(
req_type = RESTType.POST,
val = None,
msg = f"Hello {name}! You POSTed successfully!",
status = ResponseStatus.SUCCESS)
status = ResponseStatus.OK)
return ret_val.AsDict

def put(self, name):
ret_val = APIResponse(
req_type = RESTType.PUT,
val = None,
msg = f"Hello {name}! You PUTted successfully!",
status = ResponseStatus.SUCCESS)
status = ResponseStatus.OK)
return ret_val.AsDict

class Version(Resource):
Expand All @@ -82,5 +84,5 @@ def get(self):
req_type = RESTType.GET,
val = { "version" : str(HelloAPI.server_config.Version) },
msg = f"Successfully retrieved API version.",
status = ResponseStatus.SUCCESS)
status = ResponseStatus.OK)
return ret_val.AsDict
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@

# import standard libraries
import json
from enum import IntEnum
from typing import Any, Dict, Optional, Set
from typing import Any, Dict, Optional

# import 3rd-party libraries
from flask import Response
Expand All @@ -18,64 +17,8 @@
import ogd.core.requests.RequestResult as RequestResult

# Import local files

class RESTType(IntEnum):
"""Simple enumerated type to track type of a REST request.
"""
GET = 1
POST = 2
PUT = 3

def __str__(self):
"""Stringify function for RESTTypes.

:return: Simple string version of the name of a RESTType
:rtype: _type_
"""
match self.value:
case RESTType.GET:
return "GET"
case RESTType.POST:
return "POST"
case RESTType.PUT:
return "PUT"
case _:
return "INVALID REST TYPE"

class ResponseStatus(IntEnum):
"""Simple enumerated type to track the status of an API request result.
"""
NONE = 1
SUCCESS = 200
ERR_REQ = 400
ERR_NOTFOUND = 404
ERR_SRV = 500

@staticmethod
def ServerErrors() -> Set["ResponseStatus"]:
return {ResponseStatus.ERR_SRV}

@staticmethod
def ClientErrors() -> Set["ResponseStatus"]:
return {ResponseStatus.ERR_REQ, ResponseStatus.ERR_NOTFOUND}

def __str__(self):
"""Stringify function for ResponseStatus objects.

:return: Simple string version of the name of a ResponseStatus
:rtype: _type_
"""
match self.value:
case ResponseStatus.NONE:
return "NONE"
case ResponseStatus.SUCCESS:
return "SUCCESS"
case ResponseStatus.ERR_SRV:
return "SERVER ERROR"
case ResponseStatus.ERR_REQ:
return "REQUEST ERROR"
case _:
return "INVALID STATUS TYPE"
from ogd.apis.models.enums.RESTType import RESTType
from ogd.apis.models.enums.ResponseStatus import ResponseStatus

class APIResponse:
def __init__(self, req_type:Optional[RESTType], val:Optional[Map], msg:str, status:ResponseStatus):
Expand Down Expand Up @@ -113,11 +56,11 @@ def FromRequestResult(result:RequestResult.RequestResult, req_type:RESTType) ->
_status : ResponseStatus
match result.Status:
case RequestResult.ResultStatus.SUCCESS:
_status = ResponseStatus.SUCCESS
_status = ResponseStatus.OK
case RequestResult.ResultStatus.FAILURE:
_status = ResponseStatus.ERR_REQ
_status = ResponseStatus.BAD_REQUEST
case _:
_status = ResponseStatus.ERR_SRV
_status = ResponseStatus.INTERNAL_ERR
ret_val = APIResponse(req_type=req_type, val={"session_count":result.SessionCount, "duration":str(result.Duration)}, msg=result.Message, status=_status)
return ret_val

Expand Down Expand Up @@ -199,14 +142,14 @@ def AsFlaskResponse(self) -> Response:
return Response(response=self.AsJSON, status=self.Status.value, mimetype='application/json')

def RequestErrored(self, msg:str, status:Optional[ResponseStatus]=None):
self._status = status if status is not None and status in ResponseStatus.ClientErrors() else ResponseStatus.ERR_REQ
self._status = status if status is not None and status in ResponseStatus.ClientErrors() else ResponseStatus.BAD_REQUEST
self.Message = f"ERROR: {msg}"

def ServerErrored(self, msg:str, status:Optional[ResponseStatus]=None):
self._status = status if status is not None and status in ResponseStatus.ServerErrors() else ResponseStatus.ERR_SRV
self._status = status if status is not None and status in ResponseStatus.ServerErrors() else ResponseStatus.INTERNAL_ERR
self.Message = f"SERVER ERROR: {msg}"

def RequestSucceeded(self, msg:str, val:Optional[Map]):
self._status = ResponseStatus.SUCCESS
self._status = ResponseStatus.OK
self.Message = f"SUCCESS: {msg}"
self.Value = val
Empty file added src/ogd/apis/models/__init__.py
Empty file.
25 changes: 25 additions & 0 deletions src/ogd/apis/models/enums/RESTType.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from enum import IntEnum
from typing import Set

class RESTType(IntEnum):
"""Simple enumerated type to track type of a REST request.
"""
GET = 1
POST = 2
PUT = 3

def __str__(self):
"""Stringify function for RESTTypes.

:return: Simple string version of the name of a RESTType
:rtype: _type_
"""
match self.value:
case RESTType.GET:
return "GET"
case RESTType.POST:
return "POST"
case RESTType.PUT:
return "PUT"
case _:
return "INVALID REST TYPE"
98 changes: 98 additions & 0 deletions src/ogd/apis/models/enums/ResponseStatus.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
from enum import IntEnum
from typing import Set

class ResponseStatus(IntEnum):
"""Enumerated type to track the status of an API request result.
"""
NONE = 1
CONTINUE = 100
OK = 200
MULTI_CHOICES = 300
BAD_REQUEST = 400
INTERNAL_ERR = 500

# 100s
SWITCHING_PROTOCOLS = 101
PROCESSING = 102
EARLY_HINTS = 103

# 200s
CREATED = 201
ACCEPTED = 202
NON_AUTHORITATIVE = 203
NO_CONTENT = 204
RESET = 205
PARTIAL = 206
MULTI_STATUS = 207
ALREADY_REPORTED = 208
IM_USED = 226

# 300s
MOVED = 301
FOUND = 302
SEE_OTHER = 303
NOT_MODIFIED = 304
TEMPORARY_REDIR = 307
PERMANENT_REDIR = 308

# 400s
UNAUTORIZED = 401
PAYMENT_REQUIRED = 402
FORBIDDEN = 403
NOT_FOUND = 404
METHOD_NOT_ALLOWED = 405
NOT_ACCEPTABLE = 406
PROXY_AUTH_REQUIRED = 407
REQUEST_TIMEOUT = 408
CONFLICT = 409
GONE = 410
LENGTH_REQUIRED = 411
PRECONDITION_FAILED = 412
CONENT_TOO_LARGE = 413
URI_TOO_LONG = 414
UNSUPPORTED_MEDIA = 415
RANGE_INVALID = 416
EXPECTATION_FAIL = 417
IM_A_TEAPOT = 418
MISDIRECTED = 421
TOO_EARLY = 425
UPGRADE_REQUIRED = 426
PRECONDITION_REQUIRED = 428
TOO_MANY_REQUESTS = 429
HEADERS_TOO_LARGE = 431
ILLEGAL = 451

# 400s WebDAV
UNPROCESSABLE = 422
LOCKED = 423
FAILED_DEPENDENCY = 424

# 500s
NOT_IMPLEMENTED = 501
BAD_GATEWAY = 502
UNAVAILABLE = 503
GATEWAY_TIMEOUT = 504
UNSUPPORTED_HTTP_VERSION = 505
VARIANT_NEGOTIATES = 506
NOT_EXTENDED = 510
NETWORK_AUTH_REQUIRED = 511

# 500s WebDAV
INSUFFICIENT_STORAGE = 507
LOOP_DETECTED = 508

@staticmethod
def ClientErrors() -> Set["ResponseStatus"]:
return {status for status in set(ResponseStatus) if status in range(400, 499)}

@staticmethod
def ServerErrors() -> Set["ResponseStatus"]:
return {status for status in set(ResponseStatus) if status in range(500, 599)}

def __str__(self):
"""Stringify function for ResponseStatus objects.

:return: Simple string version of the name of a ResponseStatus
:rtype: _type_
"""
return self.name
Empty file.
Empty file added tests/cases/models/__init__.py
Empty file.
Loading
Loading