Compare commits

...

7 Commits

Author SHA1 Message Date
600e58eb90 Update README 2024-03-09 23:03:02 +02:00
815aaca336 Bump version: 0.1.7 → 0.1.8 2024-03-09 22:39:49 +02:00
478f62cc08 Extra methods 2024-03-09 22:39:44 +02:00
cb53b5f719 Bump version: 0.1.6 → 0.1.7 2024-03-09 22:28:33 +02:00
fbb6ec9666 WIP 2024-03-09 22:28:25 +02:00
99daeb6ba0 Bump version: 0.1.5 → 0.1.6 2024-03-09 22:20:47 +02:00
f1d37d8eb4 WIP 2024-03-09 22:20:40 +02:00
5 changed files with 106 additions and 35 deletions

View File

@ -0,0 +1,71 @@
# Example code
```python
# client.py
from api_client import BaseAPIClient
class LocalClient(BaseAPIClient):
name = "local"
_base_url = "https://obligari.serveo.net/ping/local"
def __init__(self, nonce=None):
super().__init__(nonce)
self._session.headers.update(
{"User-Agent": "Mozilla/5.0 (Windows NT 10.0; rv:123.0) Gecko/20100101 Firefox/123.0"}
)
def send_post_ping(self, var1: str, var2: int) -> bool:
res = self.post("/some-post", json={"variable_one": var1, "second_variable": var2})
return res.json().get("status")
def send_put_ping(self, var1: str, var2: int) -> bool:
res = self.put("/some-put", data={"variable_one": var1, "second_variable": var2})
return res.json().get("status")
def send_get_ping(self, var1: str, var2: int) -> bool:
res = self.get("/some-get", params={"variable_one": var1, "second_variable": var2})
return res.json().get("status")
def send_patch_ping(self, var1: str, var2: int) -> bool:
res = self.put("/some-patch", data=(("variable_one", var1), ("variable_one", var2)))
return res.json().get("status")
def send_trace_ping(self, var1: str, var2: int) -> bool:
res = self.trace("/some-trace", params=(("variable_one", var1), ("variable_one", var2)))
return res.json().get("status")
```
```python
# main.py
from .client import LocalClient
client = LocalClient()
client.send_post_ping("asd", 123)
client.send_put_ping("asd", 123)
client.send_get_ping("asd", 123)
client.send_patch_ping("asd", 123)
client.send_trace_ping("asd", 123)
```
## Log output
### Simple
```text
[14d709e02c0c] Preparing POST request to "https://obligari.serveo.net/ping/local/some-post"
[14d709e02c0c] Sending request with payload=b'{"variable_one": "asd", "second_variable": 123}'
[14d709e02c0c] Response response.status_code=200 str_repr_content='{"status":true,"request_id":62}'
[14d709e02c0c] Preparing GET request to "https://obligari.serveo.net/ping/local/some-get"
[14d709e02c0c] Sending request with payload=None
[14d709e02c0c] Response response.status_code=200 str_repr_content='{"status":true,"request_id":63}'
```
### Structured
```json
{"app": "dev", "level": "DEBUG", "name": "APIClient", "date_time": "2024-03-09 22:59:24", "location": "api_client/client.py:_request:71", "message": "[cfbdadc56f53] Preparing POST request to \"https://obligari.serveo.net/ping/local/some-post\"", "extra_data": {"hooks": {"response": []}, "method": "POST", "url": "https://obligari.serveo.net/ping/local/some-post", "headers": {}, "files": [], "data": [], "json": {"variable_one": "asd", "second_variable": 123}, "params": {}, "auth": null, "cookies": null}}
{"app": "dev", "level": "INFO", "name": "APIClient", "date_time": "2024-03-09 22:59:24", "location": "api_client/client.py:_request:74", "message": "[cfbdadc56f53] Sending request with payload=b'{\"variable_one\": \"asd\", \"second_variable\": 123}'", "extra_data": {"payload": "{\"variable_one\": \"asd\", \"second_variable\": 123}"}}
{"app": "dev", "level": "INFO", "name": "APIClient", "date_time": "2024-03-09 22:59:25", "location": "api_client/client.py:_request:81", "message": "[cfbdadc56f53] Response response.status_code=200 str_repr_content='{\"status\":true,\"request_id\":72}'", "extra_data": {"status_code": 200, "content": "{\"status\":true,\"request_id\":72}"}}
{"app": "dev", "level": "DEBUG", "name": "APIClient", "date_time": "2024-03-09 22:59:25", "location": "api_client/client.py:_request:71", "message": "[cfbdadc56f53] Preparing GET request to \"https://obligari.serveo.net/ping/local/some-get\"", "extra_data": {"hooks": {"response": []}, "method": "GET", "url": "https://obligari.serveo.net/ping/local/some-get", "headers": {}, "files": [], "data": [], "json": null, "params": {"variable_one": "asd", "second_variable": 123}, "auth": null, "cookies": null}}
{"app": "dev", "level": "INFO", "name": "APIClient", "date_time": "2024-03-09 22:59:25", "location": "api_client/client.py:_request:74", "message": "[cfbdadc56f53] Sending request with payload=None", "extra_data": {"payload": "{}"}}
{"app": "dev", "level": "INFO", "name": "APIClient", "date_time": "2024-03-09 22:59:25", "location": "api_client/client.py:_request:81", "message": "[cfbdadc56f53] Response response.status_code=200 str_repr_content='{\"status\":true,\"request_id\":74}'", "extra_data": {"status_code": 200, "content": "{\"status\":true,\"request_id\":73}"}}
```

View File

@ -44,7 +44,7 @@ version = { attr = "api_client.__version__" }
[tool.bumpversion]
current_version = "0.1.5"
current_version = "0.1.8"
commit = true
tag = true
tag_name = "v{new_version}"

View File

@ -1,29 +1,4 @@
import logging.config
from .client import BaseAPIClient
__version__ = "0.1.5"
__version__ = "0.1.8"
__all__ = ["BaseAPIClient"]
LOGGING: dict = {
"version": 1,
"disable_existing_loggers": False,
"filters": {},
"formatters": {
"api-client.structured": {
"()": "api_client.utils.APIClientLogJSONFormatter",
},
"api-client.simple": {
"format": "[%(asctime)s] %(levelname)s: %(message)s",
"datefmt": "%F %T",
},
},
"handlers": {
"api-client.structured": {
"level": "DEBUG",
"class": "logging.StreamHandler",
"formatter": "api-client.structured",
},
},
}
logging.config.dictConfig(LOGGING)

View File

@ -21,14 +21,32 @@ class BaseAPIClient(ABC):
self._session = requests.Session()
self._logger = get_logger("APIClient")
def get(self, endpoint: str, *, params: Any = None, **kwargs: Any) -> requests.Response:
return self._request("GET", endpoint, params=params, **kwargs)
def post(self, endpoint: str, *, json: Any = None, data: Any = None, **kwargs: Any) -> requests.Response:
return self._request("POST", endpoint, json=json, data=data, **kwargs)
def put(self, endpoint: str, *, json: Any = None, data: Any = None, **kwargs: Any) -> requests.Response:
return self._request("PUT", endpoint, json=json, data=data, **kwargs)
def get(self, endpoint: str, *, params: Any = None, **kwargs: Any) -> requests.Response:
return self._request("GET", endpoint, params=params, **kwargs)
def patch(self, endpoint: str, *, json: Any = None, data: Any = None, **kwargs: Any) -> requests.Response:
return self._request("PATCH", endpoint, json=json, data=data, **kwargs)
def delete(self, endpoint: str, *, params: Any = None, **kwargs: Any) -> requests.Response:
return self._request("DELETE", endpoint, params=params, **kwargs)
def head(self, endpoint: str, *, params: Any = None, **kwargs: Any) -> requests.Response:
return self._request("HEAD", endpoint, params=params, **kwargs)
def options(self, endpoint: str, *, params: Any = None, **kwargs: Any) -> requests.Response:
return self._request("OPTIONS", endpoint, params=params, **kwargs)
def trace(self, endpoint: str, *, params: Any = None, **kwargs: Any) -> requests.Response:
return self._request("TRACE", endpoint, params=params, **kwargs)
def connect(self, endpoint: str, *, params: Any = None, **kwargs: Any) -> requests.Response:
return self._request("CONNECT", endpoint, params=params, **kwargs)
def _make_full_url(self, endpoint: str) -> str:
return f"{self._base_url}{endpoint}"
@ -70,13 +88,16 @@ class BaseAPIClient(ABC):
pass
def _info(self, msg: str, *args: Any, **kwargs: Any) -> None:
self._logger.info(f"[{self._nonce}] {msg}", *args, **kwargs)
self._logger.info(f"[{self._nonce}] {msg}", *args, stacklevel=2, **kwargs)
def _debug(self, msg: str, *args: Any, **kwargs: Any) -> None:
self._logger.debug(f"[{self._nonce}] {msg}", *args, **kwargs)
self._logger.debug(f"[{self._nonce}] {msg}", *args, stacklevel=2, **kwargs)
def _warn(self, msg: str, *args: Any, **kwargs: Any) -> None:
self._logger.warning(f"[{self._nonce}] {msg}", *args, **kwargs)
self._logger.warning(f"[{self._nonce}] {msg}", *args, stacklevel=2, **kwargs)
def _error(self, msg: str, *args: Any, **kwargs: Any) -> None:
self._logger.error(f"[{self._nonce}] {msg}", *args, **kwargs)
self._logger.error(f"[{self._nonce}] {msg}", *args, stacklevel=2, **kwargs)
def _critical(self, msg: str, *args: Any, **kwargs: Any) -> None:
self._logger.critical(f"[{self._nonce}] {msg}", *args, stacklevel=2, **kwargs)

View File

@ -49,6 +49,7 @@ class APIClientLogJSONFormatter(logging.Formatter):
"levelname",
"levelno",
"pathname",
"exc_info",
"filename",
"lineno",
"funcName",
@ -61,15 +62,18 @@ class APIClientLogJSONFormatter(logging.Formatter):
"process",
"message",
"asctime",
"module",
"exc_text",
"stack_info",
]
structured_data = dict(
app=os.environ.get("PROJECT_NAME", "dev"),
app=os.environ.get("APP_NAME", "dev"),
level=record.levelname,
name=record.name,
date_time=datetime.datetime.fromtimestamp(record.created).strftime(self.default_time_format),
location=f"{record.pathname or record.filename}:{record.funcName}:{record.lineno}",
message=record.getMessage(),
extra_data={k: record.__dict__[k] for k in record.__dict__.keys() if k not in record_default_keys},
)
structured_data.update(**{k: record.__dict__[k] for k in record.__dict__.keys() if k not in record_default_keys})
return json.dumps(structured_data, cls=APIClientJSONEncoder)