Skip to content
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
7 changes: 7 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
master
------

7.1.0 (2026-05-29)
------------------

Features:
~~~~~~~~~
- add ``events_schema``, ``query_events``, and ``group_events`` for the Events API

7.0.0 (2026-05-29)
------------------

Expand Down
12 changes: 12 additions & 0 deletions castle/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
from castle.commands.list_items.unarchive import CommandsListItemsUnarchive
from castle.commands.privacy.request_data import CommandsPrivacyRequestData
from castle.commands.privacy.delete_data import CommandsPrivacyDeleteData
from castle.commands.events.schema import CommandsEventsSchema
from castle.commands.events.query import CommandsEventsQuery
from castle.commands.events.group import CommandsEventsGroup
from castle.configuration import configuration
from castle.context.prepare import ContextPrepare
from castle.errors import InternalServerError, RequestError
Expand Down Expand Up @@ -138,6 +141,15 @@ def request_user_data(self, options):
def delete_user_data(self, options):
return self.api.call(CommandsPrivacyDeleteData.call(options))

def events_schema(self, options=None):
return self.api.call(CommandsEventsSchema.call(options))

def query_events(self, options):
return self.api.call(CommandsEventsQuery.call(options))

def group_events(self, options):
return self.api.call(CommandsEventsGroup.call(options))

def disable_tracking(self):
self.do_not_track = True

Expand Down
Empty file.
14 changes: 14 additions & 0 deletions castle/commands/events/group.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from castle.command import Command
from castle.validators.present import ValidatorsPresent


class CommandsEventsGroup(object):
@staticmethod
def call(options=None):
options = options or {}
for query_filter in options.get('filters') or []:
ValidatorsPresent.call(query_filter, 'field', 'op', 'value')
if options.get('sort'):
ValidatorsPresent.call(options['sort'], 'field', 'order')

return Command(method='post', path='events/group', data=options)
14 changes: 14 additions & 0 deletions castle/commands/events/query.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from castle.command import Command
from castle.validators.present import ValidatorsPresent


class CommandsEventsQuery(object):
@staticmethod
def call(options=None):
options = options or {}
for query_filter in options.get('filters') or []:
ValidatorsPresent.call(query_filter, 'field', 'op', 'value')
if options.get('sort'):
ValidatorsPresent.call(options['sort'], 'field', 'order')

return Command(method='post', path='events/query', data=options)
7 changes: 7 additions & 0 deletions castle/commands/events/schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from castle.command import Command


class CommandsEventsSchema(object):
@staticmethod
def call(options=None):
return Command(method='get', path='events/schema', data=None)
1 change: 1 addition & 0 deletions castle/test/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
'castle.test.commands.lists_test',
'castle.test.commands.list_items_test',
'castle.test.commands.privacy_test',
'castle.test.commands.events_test',
'castle.test.configuration_test',
'castle.test.context.get_default_test',
'castle.test.context.merge_test',
Expand Down
36 changes: 36 additions & 0 deletions castle/test/client_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,42 @@ def test_delete_user_data(self):
options = {'identifier': 'a@b.com', 'identifier_type': '$email'}
self.assertEqual(client.delete_user_data(options), response_text)

@responses.activate
def test_events_schema(self):
response_text = {'fields': []}
responses.add(
responses.GET,
'https://api.castle.io/v1/events/schema',
json=response_text,
status=200,
)
client = Client.from_request(request(), {})
self.assertEqual(client.events_schema(), response_text)

@responses.activate
def test_query_events(self):
response_text = {'data': []}
responses.add(
responses.POST,
'https://api.castle.io/v1/events/query',
json=response_text,
status=200,
)
client = Client.from_request(request(), {})
self.assertEqual(client.query_events({'filters': []}), response_text)

@responses.activate
def test_group_events(self):
response_text = {'data': []}
responses.add(
responses.POST,
'https://api.castle.io/v1/events/group',
json=response_text,
status=200,
)
client = Client.from_request(request(), {})
self.assertEqual(client.group_events({'filters': []}), response_text)

def test_disable_tracking(self):
client = Client.from_request(request(), {})
client.disable_tracking()
Expand Down
39 changes: 39 additions & 0 deletions castle/test/commands/events_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from castle.test import unittest
from castle.command import Command
from castle.commands.events.schema import CommandsEventsSchema
from castle.commands.events.query import CommandsEventsQuery
from castle.commands.events.group import CommandsEventsGroup
from castle.errors import InvalidParametersError


class CommandsEventsTestCase(unittest.TestCase):
def test_schema(self):
self.assertEqual(
CommandsEventsSchema.call(),
Command(method='get', path='events/schema', data=None),
)

def test_query(self):
options = {
'filters': [{'field': 'name', 'op': '$eq', 'value': 'x'}],
'sort': {'field': 'created_at', 'order': 'desc'},
}
self.assertEqual(
CommandsEventsQuery.call(options),
Command(method='post', path='events/query', data=options),
)

def test_query_invalid_filter(self):
with self.assertRaises(InvalidParametersError):
CommandsEventsQuery.call({'filters': [{'field': 'name'}]})

def test_group(self):
options = {'filters': [{'field': 'name', 'op': '$eq', 'value': 'x'}]}
self.assertEqual(
CommandsEventsGroup.call(options),
Command(method='post', path='events/group', data=options),
)

def test_group_invalid_sort(self):
with self.assertRaises(InvalidParametersError):
CommandsEventsGroup.call({'sort': {'field': 'created_at'}})
2 changes: 1 addition & 1 deletion castle/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
VERSION = '7.0.0'
VERSION = '7.1.0'
Loading