Skip to content
This repository has been archived by the owner on Aug 25, 2020. It is now read-only.

Commit

Permalink
Initial Python streamserver library
Browse files Browse the repository at this point in the history
  • Loading branch information
paulj committed Apr 16, 2012
0 parents commit 3fdc813
Show file tree
Hide file tree
Showing 16 changed files with 273 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
@@ -0,0 +1,3 @@
env/
*.pyc
*.egg-info/
13 changes: 13 additions & 0 deletions LICENSE.txt
@@ -0,0 +1,13 @@
Copyright (c) 2012 About Echo.

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
7 changes: 7 additions & 0 deletions Makefile
@@ -0,0 +1,7 @@
init:
virtualenv env
env/bin/python setup.py develop
env/bin/pip install -r requirements.txt

test:
env/bin/nosetests ./tests/*
6 changes: 6 additions & 0 deletions README.rst
@@ -0,0 +1,6 @@
=============================
Echo StreamServer API Library
=============================

The Echo StreamServer API library provides support for working with the Echo StreamServer from Python. All interaction
is via the Echo HTTP/REST API, as described at <http://wiki.aboutecho.com/w/page/35344006/Echo%20overview>.
2 changes: 2 additions & 0 deletions requirements.txt
@@ -0,0 +1,2 @@
nose==1.1.2
rudolf2==0.3
20 changes: 20 additions & 0 deletions setup.py
@@ -0,0 +1,20 @@
try:
from setuptools import setup
except ImportError:
from distutils.core import setup

setup(
name='echo-streamserver',
version='0.1.0',
author='Echo',
author_email='solutions@aboutecho.com',
packages=['streamserver'],
scripts=[],
url='http://pypi.python.org/pypi/echo-streamserver/',
license='LICENSE.txt',
description='Echo StreamServer API library.',
long_description=open('README.rst').read(),
install_requires=[
"requests >= 0.10.8",
],
)
23 changes: 23 additions & 0 deletions streamserver/__init__.py
@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-

"""
Echo StreamServer API library
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:copyright: (c) 2012 by About Echo
:license: ISC, see LICENSE for more details.
"""

__title__ = 'streamserver'
__version__ = '0.0.1'
__build__ = 0x000001
__author__ = 'Paul Jones'
__license__ = 'ISC'
__copyright__ = 'Copyright 2012 About Echo'

from .items_client import ItemsClient
from .feeds_client import FeedsClient
from .users_client import UsersClient
from .kv_client import KVClient
from .echo_client import (EchoAuthMethod, EchoAuthConfig)
50 changes: 50 additions & 0 deletions streamserver/echo_client.py
@@ -0,0 +1,50 @@
import requests
import json

class EchoAuthMethod:
BASIC='basic'
OAUTH='oauth'

class EchoAuthConfig:
def __init__(self, appkey = None, secret = None, method = EchoAuthMethod.BASIC):
self.appkey = appkey
self.secret = secret
self.method = method

class EchoClient:
def __init__(self, auth = EchoAuthConfig(), host = "https://api.echoenabled.com/v1"):
self.auth = auth
self.host = host

def execute_query(self, method, params):
full_params = params.copy()
full_params.update({'appkey' : self.auth.appkey})

res = requests.get(self.host + "/" + method, params=full_params)
self.assert_status(res)

return json.loads(res.content)

def assert_status(self, response):
if response.status_code == 200:
return True
else:
# Attempt to decode as a JSON response
res = json.loads(response.content)
if res.errorCode == "incorrect_appkey":
raise InvalidOrMissingAppKeyException()
else:
# TODO: More decoding!
raise EchoException()


class EchoException(RuntimeError):
"""An exception occurred executing an Echo request"""

class InvalidRequestException(EchoException):
"""A request submitted to Echo was invalid"""

class InvalidOrMissingAppKeyException(InvalidRequestException):
"""The appkey provided to echo was blank or invalid"""


9 changes: 9 additions & 0 deletions streamserver/feeds_client.py
@@ -0,0 +1,9 @@
class FeedsClient:
def list(self):
pass

def register(self):
pass

def unregister(self):
pass
19 changes: 19 additions & 0 deletions streamserver/items_client.py
@@ -0,0 +1,19 @@
from echo_client import EchoClient

class ItemsClient(EchoClient):
def submit(self, items):
pass

def search(self, query, since=None):
params = {'q':str(query)}
if since != None:
params.since = str(since)

return self.execute_query('search', params)

def count(self, query):
res = self.execute_query('count', {'q':str(query)})
return res['count']

def mux(self):
pass
9 changes: 9 additions & 0 deletions streamserver/kv_client.py
@@ -0,0 +1,9 @@
class KVClient:
def get(self, key):
pass

def put(self, key, value, public=False):
pass

def delete(self, key):
pass
62 changes: 62 additions & 0 deletions streamserver/querybuilder.py
@@ -0,0 +1,62 @@
import string

def query():
return MainQueryBuilder()

def subquery():
return SubQueryBuilder()

class QueryBuilderBase:
def __init__(self):
self.terms = []

def add_term(self, term, value = None):
if value == None:
self.terms.append(term)
else:
self.terms.append(term + ":" + str(value))

def __str__(self):
return string.join(self.terms, " ")

class MainQueryBuilder(QueryBuilderBase):
def __init__(self):
QueryBuilderBase.__init__(self)

def scope(self, s):
self.add_term("scope", s)
return self

def childrenof(self, s):
self.add_term("childrenof", s)
return self

def children(self, count=None):
self.add_term("children", count)
return ChildrenQueryBuilder(str(self))

def or_terms(self, *terms):
self.add_term(" OR ".join(map(lambda t: "(" + str(t) + ")", terms)))
return self

class SubQueryBuilder(QueryBuilderBase):
def __init__(self):
QueryBuilderBase.__init__(self)

def scope(self, s):
self.add_term("scope", s)
return self

class ChildrenQueryBuilder(QueryBuilderBase):
def __init__(self, prefix):
QueryBuilderBase.__init__(self)

self.prefix = prefix

def itemsPerPage(self, count):
self.add_term("itemsPerPage", count)
return self

def __str__(self):
return self.prefix + " " + QueryBuilderBase.__str__(self)

9 changes: 9 additions & 0 deletions streamserver/users_client.py
@@ -0,0 +1,9 @@
class UsersClient:
def get(self, identityURL):
pass

def update(self, identityURL, subject, content):
pass

def whoami(self, sessionID):
pass
5 changes: 5 additions & 0 deletions tests/feeds_client_tests.py
@@ -0,0 +1,5 @@
import unittest

class FeedsClientTestSuite(unittest.TestCase):
def test_foo(self):
pass
16 changes: 16 additions & 0 deletions tests/items_client_tests.py
@@ -0,0 +1,16 @@
import unittest

from streamserver import (ItemsClient, EchoAuthConfig)
import streamserver.querybuilder as qb

class ItemsClientTestSuite(unittest.TestCase):
def test_search_items(self):
c = ItemsClient(auth = EchoAuthConfig(appkey = "test.echoenabled.com"))
print(c.search(qb.query().childrenof('http://echosandbox.com/use-cases/commenting')))
# TODO: Validate the response

def test_count_items(self):
c = ItemsClient(auth = EchoAuthConfig(appkey = "test.echoenabled.com"))
print(c.count(qb.query().childrenof('http://echosandbox.com/use-cases/commenting')))
# TODO: Validate the response

20 changes: 20 additions & 0 deletions tests/querybuilder_test.py
@@ -0,0 +1,20 @@
import unittest

import streamserver.querybuilder as qb

class QueryBuilderTestSuite(unittest.TestCase):
def test_scope_only(self):
q = qb.query().scope('http://example.com/m')
self.assertEqual(str(q), "scope:http://example.com/m")

def test_scope_and_children(self):
q = qb.query().scope('http://example.com/m').children(2).itemsPerPage(5)
self.assertEqual(str(q), "scope:http://example.com/m children:2 itemsPerPage:5")

def test_scope_and_unnumbered_children(self):
q = qb.query().scope('http://example.com/m').children().itemsPerPage(5)
self.assertEqual(str(q), "scope:http://example.com/m children itemsPerPage:5")

def test_multiple_or_terms(self):
q = qb.query().or_terms(qb.subquery().scope('http://example.com/m'), qb.subquery().scope('http://example.com/n'))
self.assertEqual(str(q), "(scope:http://example.com/m) OR (scope:http://example.com/n)")

0 comments on commit 3fdc813

Please sign in to comment.