Skip to content

Commit f8ea686

Browse files
committed
initial import of eventfabric lib
0 parents  commit f8ea686

File tree

4 files changed

+228
-0
lines changed

4 files changed

+228
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
__pycache__
2+
*.pyc

README.rest

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
Event Fabric API Client
2+
=======================
3+
4+
Python 2 and 3 implementation of Event Fabric API to send events.
5+
6+
Setup
7+
-----
8+
9+
The library dependes on the `Requests <http://docs.python-requests.org/en/latest/>`_ HTTP library, install it with::
10+
11+
pip install requests
12+
13+
Usage
14+
-----
15+
16+
see the examples folder for more usage examples
17+
18+
::
19+
20+
# import the library
21+
>>> import eventfabric as ef
22+
23+
# create a client instance specifying username and password
24+
>>> client = ef.Client("username", "password")
25+
26+
# authenticate, should return True and 200, if not there was an error
27+
>>> client.login()
28+
(True, <Response [200]>)
29+
30+
# create an event instance
31+
32+
# the first parameter is a free form JSON
33+
# value that contains information about the event
34+
35+
# the second is the name of the channel where that event will go to
36+
37+
# the channel is used to subscribe to a stream of events with the same
38+
# channel id
39+
>>> event1 = ef.Event({"name": "Bob", "count": 10}, "my.channel")
40+
41+
# send the event, it should return True and 201, if not there was an error,
42+
# make sure to check for authentication errors on long running agents to
43+
# reauthenticate in case your credentials expire
44+
>>> client.send_event(event1)
45+
(True, <Response [201]>)
46+
47+
Test
48+
----
49+
50+
::
51+
52+
python tests/eventfabric_tests.py
53+
54+
License
55+
-------
56+
57+
MIT

eventfabric.py

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
"""Event Fabric API Client Library"""
2+
from __future__ import print_function
3+
4+
import sys
5+
import json
6+
7+
try:
8+
import requests
9+
except ImportError:
10+
print("Couldn't import requests library")
11+
print("Install it with 'pip install requests' and try again")
12+
sys.exit(-1)
13+
14+
class Client(object):
15+
"""API Client"""
16+
def __init__(self, username, password,
17+
root_url="https://event-fabric.com/api/"):
18+
self.root_url = root_url if root_url.endswith("/") else root_url + "/"
19+
self.username = username
20+
self.password = password
21+
self.cookies = None
22+
23+
def login(self, requester=requests.post):
24+
"""login to the service with the specified credentials, return a tuple
25+
with a boolean specifying if the login was successful and the response
26+
object"""
27+
headers = {'content-type': 'application/json'}
28+
response = requester(self.endpoint("session"),
29+
data=json.dumps(self.credentials), headers=headers)
30+
31+
self.cookies = response.cookies
32+
33+
status_ok = response.status_code in (200, 201)
34+
return status_ok, response
35+
36+
@property
37+
def credentials(self):
38+
"""get credentials information"""
39+
return {
40+
"username": self.username,
41+
"password": self.password
42+
}
43+
44+
def endpoint(self, path):
45+
"""return the service endpoint for path"""
46+
return self.root_url + path
47+
48+
def send_event(self, event, requester=requests.post):
49+
"""send event to server, return a tuple with a boolean specifying if
50+
the login was successful and the response object"""
51+
52+
headers = {'content-type': 'application/json'}
53+
response = requester(self.endpoint("event"),
54+
data=json.dumps(event.json), cookies=self.cookies,
55+
headers=headers)
56+
57+
status_ok = response.status_code in (200, 201)
58+
return status_ok, response
59+
60+
class Event(object):
61+
"""an object representing an event to be sent to the server,
62+
63+
value is a free form json value that contains the information from
64+
the event.
65+
channel is a string with the name that identifies this kind of events
66+
username is the logged in username"""
67+
68+
def __init__(self, value, channel):
69+
70+
self.value = value
71+
self.channel = channel
72+
73+
@property
74+
def json(self):
75+
"""return a json representation of the object"""
76+
return {"value": self.value, "channel": self.channel}
77+
78+
def __str__(self):
79+
return json.dumps(self.json)

tests/eventfabric_tests.py

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
"tests for event fabric API"
2+
import os
3+
import sys
4+
import json
5+
import unittest
6+
7+
TEST_DIR = os.path.dirname(__file__)
8+
BASE_DIR = os.path.join(TEST_DIR, '..')
9+
sys.path.append(BASE_DIR)
10+
11+
import eventfabric as ef
12+
13+
class FakeResponse(object):
14+
"fake response object"
15+
def __init__(self, status_code=200, cookies=None):
16+
self.status_code = status_code
17+
self.cookies = cookies
18+
19+
def fake_post(storage, return_value):
20+
"build a fake post function"
21+
def fun(*args, **kwargs):
22+
"receives and stores all args, returns return_value"
23+
storage.append((args, kwargs))
24+
return return_value
25+
26+
return fun
27+
28+
29+
class TestEventFabric(unittest.TestCase):
30+
"tests event fabric api"
31+
32+
def test_client_creation(self):
33+
"test that the client is created and parameters are set correctly"
34+
client = ef.Client("username", "password",
35+
"http://localhost:8080/ef/api")
36+
self.assertEqual(client.username, "username")
37+
self.assertEqual(client.password, "password")
38+
self.assertEqual(client.root_url, "http://localhost:8080/ef/api/")
39+
self.assertEqual(client.cookies, None)
40+
self.assertEqual(client.credentials["username"], "username")
41+
self.assertEqual(client.credentials["password"], "password")
42+
43+
def test_endpoint(self):
44+
"tests that endpoints are created correctly"
45+
client = ef.Client("username", "password",
46+
"http://localhost:8080/ef/api")
47+
self.assertEqual(client.endpoint("session"),
48+
"http://localhost:8080/ef/api/session")
49+
50+
def test_login(self):
51+
client = ef.Client("username", "password",
52+
"http://localhost:8080/ef/api")
53+
storage = []
54+
requester = fake_post(storage, FakeResponse(200, "cookies!"))
55+
status, response = client.login(requester)
56+
args, kwargs = storage.pop()
57+
endpoint = args[0]
58+
data_arg = kwargs["data"]
59+
headers = kwargs["headers"]
60+
61+
self.assertTrue(status)
62+
self.assertEqual(response.status_code, 200)
63+
self.assertEqual(response.cookies, "cookies!")
64+
self.assertEqual(response.cookies, client.cookies)
65+
self.assertEqual(data_arg, json.dumps(client.credentials))
66+
self.assertEqual(headers["content-type"], "application/json")
67+
self.assertEqual(endpoint, "http://localhost:8080/ef/api/session")
68+
69+
def test_send_event(self):
70+
client = ef.Client("username", "password",
71+
"http://localhost:8080/ef/api")
72+
storage = []
73+
requester = fake_post(storage, FakeResponse(201))
74+
data = {"name": "bob", "count": 10}
75+
channel = "my.channel"
76+
event = ef.Event(data, channel)
77+
status, response = client.send_event(event, requester)
78+
args, kwargs = storage.pop()
79+
endpoint = args[0]
80+
data_arg = kwargs["data"]
81+
headers = kwargs["headers"]
82+
83+
self.assertTrue(status)
84+
self.assertEqual(response.status_code, 201)
85+
self.assertEqual(data_arg, json.dumps(event.json))
86+
self.assertEqual(headers["content-type"], "application/json")
87+
self.assertEqual(endpoint, "http://localhost:8080/ef/api/event")
88+
89+
if __name__ == '__main__':
90+
unittest.main()

0 commit comments

Comments
 (0)