import sys import requests import time import json class RequestError(Exception): pass class Response: ''' Response is wrapper for reading + extracting information we care about Primarily created by Requests that get `make`'d. ''' def __init__(self, url: str, body: str, code: int, expected: int, out=sys.stdout, color=True): self.body = body #typically a string before parsing anything self.code = code #u16 self.expected = expected #u16 self.out = out # file handle to write to normally sys.stdout self.color = color # bool telling if log should color anything (on by default) def __color(self, cc, string): nc = '\033[0m' return f'{cc}{string}{nc}' def _color_failing(self, string): red = '\033[1;31m' return self._color(red, string) def _color_passing(self, string): green = '\033[1;32m' return self._color(green, string) def log(self): if self.code != self.expected: msg = f'Failed: {self.method.upper()} {self.url} -> got {self.code} expected {self.expected}' if self.color: msg = self._color_failing(msg) print(msg, file=self.out) else: msg = f'Passing: {self.method} {self.url}' if self.color: msg = self._color_passing(msg) print(msg, file=self.out) def json(self): ''' Force an interpretation of json from the body NOTE: this method is rather obtuse and a massive afterthough so its usage should be limited as much as possible ''' try: return json.loads(self.body) except: return {} def __str__(self): ''' Returns: str(Response) -> `code => response.bdoy` ''' return f'{self.code} => {self.body}' class Request: def __init__(self, method: str, url: str, params: dict): assert(method in ['get', 'post', 'delete']) self.method = method self.url = url self.params = params def _make_request(self, method: str, hope: int): # Lower driver for actuall making the request we are looking for method = method.lower() params = json.dumps(self.params) if method == 'get': resp = requests.get(self.url, data=params) return Response(self.url, resp.text, resp.status_code, hope) elif method == 'post': resp = requests.post(self.url, data=self) return Response(self.url, resp.text, resp.status_code, hope) elif method == 'delete': resp = requests.delete(self.url, data=params) return Response(self.url, resp.text, resp.status_code, hope) else: raise RequestError('Invalid method passed') def make(self, hope: int) -> Response: ''' @param hope: int -> status code we hope to get back @return Response -> Wrapper around server http response ''' return self._make_request(self.method, hope)