Skip to content

Commit

Permalink
Merge branch 'main' into 'prod'
Browse files Browse the repository at this point in the history
Release 1.2.0

See merge request dakota.marshall/ogs-python!39
  • Loading branch information
dakota-marshall committed Aug 28, 2023
2 parents 0921187 + c29d625 commit 9fc540a
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 17 deletions.
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.2.0] - 2023-08-28

### Changed

- Dont instantiate socket connection unless we need to
- Disable loguru logging by default, require user to enable and configure it (#4)

### Added

- Added documentation on how to configure loguru (#4)

### Fixed

- Fixed `POST` requests to the REST API not working correctly due to using data instead of json

## [1.1.3] - 2023-08-24

Expand Down Expand Up @@ -181,6 +195,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Initial release

[unreleased]: https://gitlab.com/dakota.marshall/ogs-python/-/compare/v1.1.2...HEAD
[1.2.0]: https://gitlab.com/dakota.marshall/ogs-python/-/compare/v1.1.3...v1.2.0
[1.1.3]: https://gitlab.com/dakota.marshall/ogs-python/-/compare/v1.1.2...v1.1.3
[1.1.2]: https://gitlab.com/dakota.marshall/ogs-python/-/compare/v1.1.1...v1.1.2
[1.1.1]: https://gitlab.com/dakota.marshall/ogs-python/-/compare/v1.1.0...v1.1.1
Expand Down
42 changes: 42 additions & 0 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,45 @@ ogs.sock.ping()
See the [OGSSocket](/api/#src.ogsapi.ogssocket.OGSSocket) class for more information.


## Logging

The library uses the [Loguru](https://github.com/Delgan/loguru) logging module to handle all logging. Check out their documentation for more advanced logging config, but its highly flexible and pretty easy to setup and use. Here is a basic example that will log all messages of level `INFO` or higher to the console.

!!! warning

Because loguru is setup to catch ExceptionErrors for debugging, the backtrace printouts can expose sensitive information. If you are using this in production, you should disable the backtrace printouts with `backtrace=False` to prevent this.

```python
from ogsapi.client import OGSClient
from loguru import logger

logger.remove()
logger.add(sys.stdout, level="INFO")
logger.enable("ogsapi")
ogs = OGSClient(
client_id=client_id,
client_secret=client_secret,
username=username,
password=password
)
```
Its important to `.enable()` the `ogsapi` logger, otherwise you wont see any logs from the library. If you want to see you the logs from the socket, you can add `socketio.client`, to see the low level `engineio` calls, you can add `engineio.client`.

```python
from ogsapi.client import OGSClient
from loguru import logger

logger.remove()
logger.add(sys.stdout, level="INFO")
logger.enable("ogsapi")
logger.enable("socketio.client")
logger.enable("engineio.client")
ogs = OGSClient(
client_id=client_id,
client_secret=client_secret,
username=username,
password=password
)
```

You can also just call the `enable_logging()` methods on both the `ogs` and the `ogs.sock` object.
14 changes: 12 additions & 2 deletions example.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import dotenv
import os
import sys
from loguru import logger
from src.ogsapi.client import OGSClient
from typing import Callable

Expand Down Expand Up @@ -37,14 +39,22 @@ def move(self, move: str):
def pass_turn(self):
self.game.pass_turn()

# Setup our logging if we want to log somewhere specific
logger.remove()
logger.add("/var/logs/ogsapi.log", rotation="1 MB", level="DEBUG", backtrace=False)
logger.add(sys.stderr, level="DEBUG", backtrace=False)
# Enable ogsapi logging to catch authentication errors (EXPOSES SECRETS TO LOGS)
logger.enable("ogsapi")

# Instantiate Client
ogs = OGSClient(
client_id=client_id,
client_secret=client_secret,
username=username,
password=password,
log_level='DEBUG'
password=password
)

# Enable
ogs.socket_connect(ogs_event_handler)
game_id = 56202921

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "ogsapi"
version = "1.1.3"
version = "1.2.0"
license = {file = "LICENSE"}
authors = [
{ name="Dakota Marshall", email="me@dakotamarshall.net" },
Expand Down
27 changes: 17 additions & 10 deletions src/ogsapi/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@
from .ogsrestapi import OGSRestAPI
from .ogs_api_exception import OGSApiException

# Disable logging from ogsapi by default
logger.disable("src.ogsapi")
logger.disable("urllib3")
logger.disable("engineio.client")
logger.disable("socketio.client")

class InterceptHandler(logging.Handler):
"""Intercepts the logs from SocketIO, EngineIO, and urllib and sends them to the logger"""
def emit(self, record):
Expand Down Expand Up @@ -59,7 +65,6 @@ class OGSClient:
client_secret=client_secret,
username=username,
password=password,
log_level='DEBUG'
)
Connecting to Websocket
Connected to socket, authenticating
Expand All @@ -69,7 +74,6 @@ class OGSClient:
client_secret (str): Client Secret from OGS
username (str): Username of OGS account
password (str): Password of OGS account
log_level (str, optional): Set the log level. Defaults to 'INFO'. Accepts 'TRACE', 'DEBUG', 'INFO', 'SUCCESS', 'WARNING', 'ERROR', 'CRITICAL'
dev (bool, optional): Use the development API. Defaults to False.
Attributes:
Expand All @@ -78,20 +82,21 @@ class OGSClient:
sock (OGSSocket): SocketIO connection to OGS
"""
def __init__(self, client_id, client_secret, username, password, log_level: str = 'INFO', log_file: str = None, dev: bool = False):

# Setup Logging
logger.remove()
logger.add(sys.stderr, level=log_level.upper())
if log_file is not None:
logger.add(log_file)
def __init__(self, client_id, client_secret, username, password, dev: bool = False):

self.credentials = OGSCredentials(client_id=client_id, client_secret=client_secret,
username=username, password=password)
self.api = OGSRestAPI(self.credentials,dev=dev)
self.sock = OGSSocket(self.credentials)
self.credentials.user_id = self.user_vitals()

def enable_logging(self):
"""Enable logging from ogsapi"""
logger.enable("src.ogsapi")

def disable_logging(self):
"""Disable logging from ogsapi"""
logger.disable("src.ogsapi")

# User Specific Resources: /me

def user_vitals(self):
Expand Down Expand Up @@ -534,9 +539,11 @@ def socket_connect(self, callback_handler):
Args:
callback_handler (Callable): Callback function to send socket events to.
"""
self.sock = OGSSocket(self.credentials)
self.sock.callback_handler = callback_handler
self.sock.connect()

def socket_disconnect(self):
"""Disconnect from the socket. You will need to do this before exiting your program, Or else it will hang and require a keyboard interrupt."""
self.sock.disconnect()
del self.sock
8 changes: 5 additions & 3 deletions src/ogsapi/ogsrestapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,16 @@ def call_rest_endpoint(self, method: str, endpoint: str, params: dict = None, pa
method (str): HTTP method to use. Accepts GET, POST, PUT, DELETE
endpoint (str): Endpoint to make request to
params (dict, optional): Parameters to pass to the endpoint. Defaults to None.
payload (dict, optional): Payload to pass to the endpoint. Defaults to None.
Returns:
response (Callable): Returns the request response
"""
method = method.upper()
url = f'{self.base_url}/api/{self.api_ver}{endpoint}'
url = f'{self.base_url}api/{self.api_ver}{endpoint}'
headers = {
'Authorization' : f'Bearer {self.credentials.access_token}'
'Authorization' : f'Bearer {self.credentials.access_token}',
'Content-Type': 'application/json'
}

# Bail if method is invalid
Expand All @@ -100,7 +102,7 @@ def call_rest_endpoint(self, method: str, endpoint: str, params: dict = None, pa
logger.debug(f"Making {method} request to {url}")
if method in ['POST', 'PUT']:
try:
response = requests.request(method, url, headers=headers, params=params, payload=payload, timeout=20)
response = requests.request(method, url, headers=headers, params=params, json=payload, timeout=20)
except requests.exceptions.RequestException as e:
raise OGSApiException(f"{method} Failed") from e
else:
Expand Down
10 changes: 10 additions & 0 deletions src/ogsapi/ogssocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ def __init__(self, credentials: OGSCredentials):
def __del__(self):
self.disconnect()

def enable_logging(self):
"""Enable logging from the socket"""
logger.enable("engineio.client")
logger.enable("socketio.client")

def disable_logging(self):
"""Disable logging from the socket"""
logger.disable("engineio.client")
logger.disable("socketio.client")

@logger.catch
def connect(self):
"""Connect to the socket"""
Expand Down
2 changes: 1 addition & 1 deletion src/tests/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def test_import(self):
self.fail("Failed to import OGSClient")

def test_authentication(self):
self.client = OGSClient(self.client_id, self.client_secret, self.username, self.password, log_level='SUCCESS')
self.client = OGSClient(self.client_id, self.client_secret, self.username, self.password)
self.assertIsNotNone(self.client.credentials.access_token)
self.assertIsNotNone(self.client.credentials.refresh_token)

Expand Down

0 comments on commit 9fc540a

Please sign in to comment.