Skip to content

Commit

Permalink
feat(event): Add support for ingest API
Browse files Browse the repository at this point in the history
  • Loading branch information
vincent-pochet committed Jun 18, 2024
1 parent b98186f commit 3301843
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 8 deletions.
3 changes: 2 additions & 1 deletion lago_python_client/base_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
class BaseClient(ABC):
"""The base class used for each collection client."""

def __init__(self, base_url: str, api_key: str):
def __init__(self, base_url: str, api_key: str, ingest_url: str = ''):
self.base_url = base_url
self.api_key = api_key
self.ingest_url = ingest_url

@property
@classmethod
Expand Down
20 changes: 18 additions & 2 deletions lago_python_client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,32 @@

class Client:
BASE_URL: Final[str] = 'https://api.getlago.com/'
BASE_INGEST_URL: Final[str] = 'https://ingest.getlago.com/'
API_PATH: Final[str] = 'api/v1/'

def __init__(self, api_key: str = '', api_url: str = '') -> None:
def __init__(self, api_key: str = '', api_url: str = '', ingest_api_url: str = '') -> None:
self.api_key: str = api_key
self.api_url: str = api_url
self.ingest_api_url: str = ingest_api_url

@property
def base_api_url(self) -> str:
return urljoin(self.api_url if self.api_url else Client.BASE_URL, Client.API_PATH)

@property
def base_ingest_api_url(self) -> str:
base_url = ''
if self.ingest_api_url != '':
base_url = self.ingest_api_url
else:
if (self.api_url == '' or self.api_url == Client.BASE_URL):
base_url = Client.BASE_INGEST_URL
else:
base_url = self.api_url

return urljoin(base_url, Client.API_PATH)


@callable_cached_property
def add_ons(self) -> AddOnClient:
return AddOnClient(self.base_api_url, self.api_key)
Expand Down Expand Up @@ -69,7 +85,7 @@ def customers(self) -> CustomerClient:

@callable_cached_property
def events(self) -> EventClient:
return EventClient(self.base_api_url, self.api_key)
return EventClient(self.base_ingest_api_url, self.api_key, self.base_ingest_api_url)

@callable_cached_property
def fees(self) -> FeeClient:
Expand Down
29 changes: 27 additions & 2 deletions lago_python_client/events/clients.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import sys
from typing import Any, ClassVar, Optional, Type

import httpx

from lago_python_client.base_model import BaseModel

from ..base_client import BaseClient
from ..fees.clients import FeeClient
from ..mixins import CreateCommandMixin, FindCommandMixin
from ..mixins import FindCommandMixin
from ..models.event import EventResponse
from ..models.fee import FeeResponse
from ..services.json import to_json
Expand All @@ -18,11 +20,34 @@
from typing import Mapping


class EventClient(CreateCommandMixin[EventResponse], FindCommandMixin[EventResponse], BaseClient):
class EventClient(FindCommandMixin[EventResponse], BaseClient):
API_RESOURCE: ClassVar[str] = 'events'
RESPONSE_MODEL: ClassVar[Type[EventResponse]] = EventResponse
ROOT_NAME: ClassVar[str] = 'event'

def create(self, input_object: BaseModel, timeout: Optional[httpx.Timeout] = None) -> EventResponse:
api_response: Response = send_post_request(
url=make_url(
origin=self.ingest_api_url,
path_parts=(self.API_RESOURCE, ),
),
content=to_json({
self.ROOT_NAME: input_object.dict(),
}),
headers=make_headers(api_key=self.api_key),
timeout=timeout,
)

# Process response data
response_data = get_response_data(response=api_response, key=self.ROOT_NAME)
if not response_data:
return None

return prepare_object_response(
response_model=self.RESPONSE_MODEL,
data=response_data,
)

def batch_create(self, input_object: BaseModel) -> None:
api_response: Response = send_post_request(
url=make_url(
Expand Down
12 changes: 9 additions & 3 deletions tests/test_event_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,25 +42,31 @@ def mock_fees_response():
def test_valid_create_events_request(httpx_mock: HTTPXMock):
client = Client(api_key='886fe239-927d-4072-ab72-6dd345e8dd0d')

httpx_mock.add_response(method='POST', url='https://api.getlago.com/api/v1/events', content=b'')
httpx_mock.add_response(method='POST', url='https://ingest.getlago.com/api/v1/events', content=b'')
client.events.create(create_event()) # Any response means success, any exception - failure


def test_valid_create_events_request_with_string_timestamp(httpx_mock: HTTPXMock):
client = Client(api_key='886fe239-927d-4072-ab72-6dd345e8dd0d')

httpx_mock.add_response(method='POST', url='https://api.getlago.com/api/v1/events', content=b'')
httpx_mock.add_response(method='POST', url='https://ingest.getlago.com/api/v1/events', content=b'')
client.events.create(create_event_with_string_timestamp()) # Any response means success, any exception - failure


def test_invalid_create_events_request(httpx_mock: HTTPXMock):
client = Client(api_key='invalid')

httpx_mock.add_response(method='POST', url='https://api.getlago.com/api/v1/events', status_code=401, content=b'')
httpx_mock.add_response(method='POST', url='https://ingest.getlago.com/api/v1/events', status_code=401, content=b'')

with pytest.raises(LagoApiError):
client.events.create(create_event())

def test_valid_create_event_request_with_custom_ingest_url(httpx_mock: HTTPXMock):
client = Client(api_key='886fe239-927d-4072-ab72-6dd345e8dd0d', ingest_api_url='https://custom-ingest.getlago.com')

httpx_mock.add_response(method='POST', url='https://custom-ingest.getlago.com/api/v1/events', content=b'')
client.events.create(create_event()) # Any response means success, any exception - failure


def test_valid_create_batch_events_request(httpx_mock: HTTPXMock):
client = Client(api_key='886fe239-927d-4072-ab72-6dd345e8dd0d')
Expand Down

0 comments on commit 3301843

Please sign in to comment.