Skip to content

Commit d2baa4b

Browse files
committed
Added delete_events method.
1 parent 765fb37 commit d2baa4b

File tree

4 files changed

+88
-3
lines changed

4 files changed

+88
-3
lines changed

keen/__init__.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,3 +403,21 @@ def multi_analysis(event_collection, analyses, timeframe=None, interval=None,
403403
return _client.multi_analysis(event_collection=event_collection, timeframe=timeframe,
404404
interval=interval, timezone=timezone, filters=filters,
405405
group_by=group_by, analyses=analyses, max_age=max_age)
406+
407+
408+
def delete_events(*args, **kwargs):
409+
""" Performs a delete for events.
410+
411+
Returns true upon success.
412+
413+
:param event_collection: string, the event collection from which event are being deleted
414+
:param timeframe: string or dict, the timeframe in which the events
415+
happened example: "previous_7_days"
416+
:param timezone: int, the timezone you'd like to use for the timeframe
417+
and interval in seconds
418+
:param filters: array of dict, contains the filters you'd like to apply to the data
419+
example: [{"property_name":"device", "operator":"eq", "property_value":"iPhone"}]
420+
421+
"""
422+
_initialize_client_from_environment()
423+
return _client.delete_events(*args, **kwargs)

keen/api.py

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class HTTPMethods(object):
2323

2424
GET = 'get'
2525
POST = 'post'
26+
DELETE = 'delete'
2627

2728

2829
class KeenAdapter(HTTPAdapter):
@@ -67,7 +68,7 @@ def __init__(self, project_id, write_key=None, read_key=None,
6768
version is used
6869
:param get_timeout: optional, the timeout on GET requests
6970
:param post_timeout: optional, the timeout on POST requests
70-
:param master_key: a Keen IO Master API Key
71+
:param master_key: a Keen IO Master API Key, needed for deletes
7172
"""
7273
# super? recreates the object with values passed into KeenApi
7374
super(KeenApi, self).__init__()
@@ -161,9 +162,32 @@ def query(self, analysis_type, params):
161162

162163
return response.json()["result"]
163164

165+
def delete_events(self, event_collection, params):
166+
"""
167+
Deletes events via the Keen IO API. A master key must be set first.
168+
169+
:param event_collection: string, the event collection from which event are being deleted
170+
171+
"""
172+
if not self.master_key:
173+
raise exceptions.InvalidEnvironmentError(
174+
"The Keen IO API requires a master key to run deletes. "
175+
"Please set a 'master_key' when initializing the KeenApi object."
176+
)
177+
178+
url = "{0}/{1}/projects/{2}/events/{3}".format(self.base_url,
179+
self.api_version,
180+
self.project_id,
181+
event_collection)
182+
headers = {"Content-Type": "application/json", "Authorization": self.master_key}
183+
response = self.fulfill(HTTPMethods.DELETE, url, params=params, headers=headers, timeout=self.post_timeout)
184+
185+
self.error_handling(response)
186+
return True
187+
164188
def error_handling(self, res):
165189
"""
166-
Helper function to do the error handling
190+
Helper function to do the error handling
167191
168192
:params res: the response from a request
169193
"""
@@ -172,5 +196,8 @@ def error_handling(self, res):
172196
try:
173197
error = res.json()
174198
except json.JSONDecodeError:
175-
error = {'message': 'The API did not respond with JSON, but: "{0}"'.format(res.text[:1000]), "error_code": "InvalidResponseFormat"}
199+
error = {
200+
'message': 'The API did not respond with JSON, but: "{0}"'.format(res.text[:1000]),
201+
"error_code": "InvalidResponseFormat"
202+
}
176203
raise exceptions.KeenApiError(error)

keen/client.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,21 @@ def generate_image_beacon(self, event_collection, event_body, timestamp=None):
155155
self.api.write_key.decode(sys.getdefaultencoding()), self._base64_encode(event_json)
156156
)
157157

158+
def delete_events(self, event_collection, timeframe=None, timezone=None, filters=None):
159+
""" Deletes events.
160+
161+
:param event_collection: string, the event collection from which event are being deleted
162+
:param timeframe: string or dict, the timeframe in which the events happened
163+
example: "previous_7_days"
164+
:param timezone: int, the timezone you'd like to use for the timeframe
165+
and interval in seconds
166+
:param filters: array of dict, contains the filters you'd like to apply to the data
167+
example: [{"property_name":"device", "operator":"eq", "property_value":"iPhone"}]
168+
169+
"""
170+
params = self.get_params(timeframe=timeframe, timezone=timezone, filters=filters)
171+
return self.api.delete_events(event_collection, params)
172+
158173
def _base64_encode(self, string_to_encode):
159174
""" Base64 encodes a string, with either Python 2 or 3.
160175

keen/tests/client_tests.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,31 @@ def test_timeout_count(self, get):
435435
# Make sure the requests library was called with `timeout`.
436436
self.assert_equals(get.call_args[1]["timeout"], 0.0001)
437437

438+
439+
@patch("requests.Session.delete")
440+
class DeleteTests(BaseTestCase):
441+
442+
def setUp(self):
443+
super(DeleteTests, self).setUp()
444+
keen._client = None
445+
keen.project_id = "1k4jb23kjbkjkjsd"
446+
keen.master_key = "sdofnasofagaergub"
447+
448+
def tearDown(self):
449+
keen._client = None
450+
keen.project_id = None
451+
keen.master_key = None
452+
super(DeleteTests, self).tearDown()
453+
454+
def test_delete_events(self, delete):
455+
delete.return_value = MockedRequest(status_code=204, json_response=[])
456+
# Assert that the mocked delete function is called the way we expect.
457+
keen.delete_events("foo", filters=[{"property_name": 'username', "operator": 'eq', "property_value": 'Bob'}])
458+
# Check that the URL is generated correctly.
459+
self.assertEqual("https://api.keen.io/3.0/projects/1k4jb23kjbkjkjsd/events/foo", delete.call_args[0][0])
460+
# Check that the master_key is in the Authorization header.
461+
self.assertTrue(keen.master_key in delete.call_args[1]["headers"]["Authorization"])
462+
438463
# only need to test unicode separately in python2
439464
if sys.version_info[0] < 3:
440465

0 commit comments

Comments
 (0)