Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add AxiomError for more detailed error messages #141

Merged
merged 2 commits into from
Sep 24, 2024
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
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "axiom-py"
version = "0.7.0"
version = "0.8.0"
description = "Official bindings for the Axiom API"
readme = "README.md"
requires-python = ">=3.8"
Expand Down
4 changes: 2 additions & 2 deletions src/axiom_py/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""

from .client import (
Error,
AxiomError,
IngestFailure,
IngestStatus,
IngestOptions,
Expand All @@ -27,7 +27,7 @@
)

_all_ = [
Error,
AxiomError,
IngestFailure,
IngestStatus,
IngestOptions,
Expand Down
40 changes: 29 additions & 11 deletions src/axiom_py/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,6 @@
AXIOM_URL = "https://api.axiom.co"


@dataclass
class Error:
status: Optional[int] = field(default=None)
message: Optional[str] = field(default=None)
error: Optional[str] = field(default=None)


@dataclass
class IngestFailure:
"""The ingestion failure of a single event"""
Expand Down Expand Up @@ -118,10 +111,35 @@ class AplOptions:
includeCursor: bool = field(default=False)


def raise_response_error(r):
if r.status_code >= 400:
# TODO: Decode JSON https://github.com/axiomhq/axiom-go/blob/610cfbd235d3df17f96a4bb156c50385cfbd9edd/axiom/error.go#L35-L50
r.raise_for_status()
class AxiomError(Exception):
"""This exception is raised on request errors."""

status: int
message: str

@dataclass
class Response:
message: str
error: Optional[str]

def __init__(self, status: int, res: Response):
message = res.error if res.error is not None else res.message
super().__init__(f"API error {status}: {message}")

self.status = status
self.message = message


def raise_response_error(res):
if res.status_code >= 400:
try:
error_res = from_dict(AxiomError.Response, res.json())
except Exception:
# Response is not in the Axiom JSON format, create generic error
# message
error_res = AxiomError.Response(message=res.reason, error=None)

raise AxiomError(res.status_code, error_res)


class Client: # pylint: disable=R0903
Expand Down
2 changes: 1 addition & 1 deletion src/axiom_py/version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""The current version"""

__version__ = "0.7.0"
__version__ = "0.8.0"
6 changes: 3 additions & 3 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
from logging import getLogger
from datetime import datetime, timedelta
from .helpers import get_random_name
from requests.exceptions import HTTPError
from axiom_py import (
AxiomError,
Client,
AplOptions,
AplResultFormat,
Expand Down Expand Up @@ -264,7 +264,7 @@ def tearDownClass(cls):
"dataset (%s) was not deleted as part of the test, deleting it now."
% cls.dataset_name
)
except HTTPError as err:
except AxiomError as e:
# nothing to do here, since the dataset doesn't exist
cls.logger.warning(err)
cls.logger.warning(e)
cls.logger.info("finish cleaning up after TestClient")
15 changes: 6 additions & 9 deletions tests/test_datasets.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,9 @@
import unittest
from typing import List, Dict
from logging import getLogger
from requests.exceptions import HTTPError
from datetime import timedelta
from .helpers import get_random_name
from axiom_py import (
Client,
)
from axiom_py import Client, AxiomError


class TestDatasets(unittest.TestCase):
Expand Down Expand Up @@ -78,11 +75,11 @@ def test_step999_delete(self):
dataset,
f"expected test dataset (%{self.dataset_name}) to be deleted",
)
except HTTPError as err:
except AxiomError as e:
# the get method returns 404 error if dataset doesn't exist, so
# that means that our tests passed, otherwise, it should fail.
if err.response.status_code != 404:
self.fail(err)
if e.status != 404:
self.fail(e)

@classmethod
def tearDownClass(cls):
Expand All @@ -97,7 +94,7 @@ def tearDownClass(cls):
"dataset (%s) was not deleted as part of the test, deleting it now."
% cls.dataset_name
)
except HTTPError as err:
except AxiomError as e:
# nothing to do here, since the dataset doesn't exist
cls.logger.warning(err)
cls.logger.warning(e)
cls.logger.info("finish cleaning up after TestDatasets")
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.