Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

closes GH-13 closes GH-14: use `http` instead of `httplib2`

* renamed `base` to `Spore`
* in `Spore`, add the `user_agent` attribut, (it's an instance of
HTTPClient)
* in `Spore`, no more static attributes
* `Method` have a new signature (useragent and middlewares are passed to
the constructor)
* the `Request` class is now more simpler and based on `http.Request`	
* updated all the tests

Signed-off-by: franck cuny <franck.cuny@gmail.com>
  • Loading branch information...
commit d3fba6b02c9635d7c872370d1b953cdd6f1139f6 1 parent 77628b2
@franckcuny franckcuny authored
View
4 spyre/__init__.py
@@ -1,5 +1,5 @@
import __future__
-from core import base
+from core import Spore
from errors import *
import os.path
@@ -12,7 +12,7 @@ def new_from_spec(spec_file, base_url=None):
def new_from_string(spec_string, base_url=None):
try:
- spore = base(spec_string=spec_string, base_url=base_url)
+ spore = Spore(spec_string=spec_string, base_url=base_url)
except Exception, e:
raise SpyreObjectBuilder(e)
return spore
View
28 spyre/core.py
@@ -1,17 +1,18 @@
import __future__
import json
-from spyre import errors
+import errors
+from httpclient import HTTPClient
from spyre.method import Method
-class base(object):
-
- authentication = None
- middlewares = []
- formats = []
+class Spore(object):
def __init__(self, spec_string=None, base_url=None):
+ self.authentication = None
+ self.middlewares = []
+ self.formats = []
self._methods = []
+ self.user_agent = HTTPClient()
if spec_string is not None:
try:
@@ -22,8 +23,9 @@ def __init__(self, spec_string=None, base_url=None):
self._init_meta(spec, base_url)
self._init_methods(spec)
- # XXX method to list available SPORE methods
- # XXX method to search for a given method
+ # TODO method to validate spec
+ # TODO method to list available SPORE methods
+ # TODO method to search for a given method
def _init_meta(self, spec, base_url=None):
self.name = spec['name'] # XXX see later what to do with this
@@ -49,9 +51,15 @@ def _init_methods(self, spec):
def _attach_method(self, method_name, method_desc):
try:
- new_method = Method(method_name, method_desc, self)
+ new_method = Method(
+ method_name,
+ method_desc,
+ base_url=self.base_url,
+ user_agent=self.user_agent,
+ middlewares=self.middlewares
+ )
except Exception, e:
- raise RuntimeError("foo") # XXX meh
+ raise RuntimeError(e) # XXX meh
setattr(self, method_name, new_method)
self._methods.append(method_name)
View
94 spyre/method.py
@@ -1,15 +1,26 @@
import __future__
import re
-from urlparse import urlparse
+from http import Url
from spyre import errors
from spyre.request import Request
class Method(object):
- def __init__(self, name, desc, spore_obj):
+
+ required_attr = ['method', 'path']
+ optional_attr = [
+ 'required_params',
+ 'optional_params',
+ 'expected_status',
+ ]
+
+ def __init__(self, name, desc, base_url, user_agent, middlewares=None):
self.name = name
- self.spore_obj = spore_obj
- self.middlewares = []
+ self.user_agent = user_agent
+
+ if middlewares is None:
+ middlewares = []
+ self.middlewares = middlewares
self.path = None
self.method = None
@@ -25,32 +36,52 @@ def __init__(self, name, desc, spore_obj):
self.optional_params = []
self.expected_status = []
- self.base_url = desc.get('base_url', self.spore_obj.base_url)
+ self.base_url = desc.get('base_url', base_url)
self._init_args(desc)
def _init_args(self, desc):
+ self._required_attributes(desc)
+ self._optional_attirbutes(desc)
- required_attr = ['method', 'path']
- optional_attr = [
- 'required_params',
- 'optional_params',
- 'expected_status',
- ]
-
- for attr in required_attr:
+ def _required_attributes(self, desc):
+ for attr in self.required_attr:
if attr not in desc:
raise errors.SpyreMethodBuilder(attr)
setattr(self, attr, desc[attr])
- for attr in optional_attr:
+ def _optional_attirbutes(self, desc):
+ for attr in self.optional_attr:
if attr in desc:
setattr(self, attr, desc[attr])
+ def _script_name(self, base_url):
+ if base_url.path == '/':
+ return ''
+ else:
+ return base_url.path
+
+ def _userinfo(self, base_url):
+ if base_url.username is not None:
+ return ('%s:%s' % (base_url.username, base_url.password))
+ else:
+ return None
+
+ def _port(self, base_url):
+ if base_url.port is not None:
+ return base_url.port
+
+ if base_url.scheme == 'http':
+ return 80
+ elif base_url.scheme == 'https':
+ return 443
+ else:
+ raise "houla"
+
def __call__(self, **kwargs):
if self.base_url is None:
- raise errors.SpyreMethodCall("meh")
+ raise errors.SpyreMethodCall("`base_url` is missing")
cb_response = []
@@ -60,31 +91,15 @@ def __call__(self, **kwargs):
auth = self._build_auth()
formats = self._build_formats()
- base_url = urlparse(self.base_url)
-
- if base_url.path == '/':
- script_name = ''
- else:
- script_name = base_url.path
+ base_url = Url(string_url=self.base_url)
- if base_url.username is not None:
- userinfo = ('%s:%s' % (base_url.username, base_url.password))
- else:
- userinfo = None
-
- if base_url.port is None:
- if base_url.scheme == 'http':
- port = 80
- elif base_url.scheme == 'https':
- port = 443
- else:
- raise "houla"
- else:
- port = base_url.port
+ script_name = self._script_name(base_url)
+ userinfo = self._userinfo(base_url)
+ port = self._port(base_url)
env = {
'REQUEST_METHOD': self.method,
- 'SERVER_NAME': base_url.hostname,
+ 'SERVER_NAME': base_url.netloc,
'SERVER_PORT': port,
'SCRIPT_NAME': script_name,
'PATH_INFO': self.path,
@@ -101,13 +116,15 @@ def __call__(self, **kwargs):
'spore.formats': formats,
}
- for mw in self.spore_obj.middlewares:
+ for mw in self.middlewares:
if mw[0](env):
cb = mw[1](env)
if cb:
cb_response.append(cb)
- http_response = Request(env).execute()
+ request = Request(env)
+ http_response = self.user_agent.request(request())
+ setattr(http_response, 'env', env)
if self.expected_status:
http_status = int(http_response.status)
@@ -131,6 +148,7 @@ def _build_parameters(self, kwargs):
stuff_remains = kset.difference(
self.required_params + self.optional_params)
+
if stuff_remains:
raise errors.SpyreMethodCall(stuff_remains)
View
2  spyre/middleware/formatjson.py
@@ -12,4 +12,6 @@ def __call__(self, env):
return cb
def response_cb(self, response):
+ import inspect
+ print 'caller name:', inspect.stack()[1][3]
response.content = json.loads(response.content)
View
114 spyre/request.py
@@ -1,70 +1,59 @@
-import httplib2
-import urllib
+import http
import re
-from spyre.response import Response
from itertools import izip
-def _requestproperty(key, default=None):
-
- def fget(self):
- return self.env.get(key, default)
-
- def fset(self, value):
- self.env[key] = value
- return value
-
- return property(fget, fset)
-
-
class Request(object):
- port = _requestproperty('SERVER_PORT', 80)
- host = _requestproperty('SERVER_NAME', '')
- path = _requestproperty('PATH_INFO', '')
- scheme = _requestproperty('spore.url_scheme', 'http')
-
def __init__(self, env):
self.env = env
+ self.scheme = self.env.get('spore.url_scheme', 'http')
+ self.port = self.env.get('SERVER_PORT', '80')
+ self.path = self.env.get('PATH_INFO', '')
+ self.method = self.env.get('REQUEST_METHOD')
+ self._build_url()
- def execute(self):
- final_url = self._finalize()
- http_response = self._execute_http_request(final_url)
- return http_response
+ @property
+ def host(self):
+ host = self.env.get('HTTP_HOST', None)
+ if host is None:
+ host = self.env.get('SERVER_NAME', '')
+ return host
- def _finalize(self):
- self._expand()
- final_url = self.base()
- query_string = self.env.get('QUERY_STRING', None)
- if query_string is not None:
- final_url = "%s?%s" % (final_url, query_string)
- return final_url
+ @property
+ def uri_base(self):
+ return str(self.url)
@property
def script_name(self):
- script_name = self.env.get('SCRIPT_NAME', '')
- if script_name == '' and self._path_info_start_with_slash() is False:
+ script_name = self.env.get('SCRIPT_NAME', None)
+
+ if script_name is None or script_name == '':
script_name = '/'
return script_name
- @property
- def http_host(self):
- host = self.env.get('HTTP_HOST', None)
- if host is None:
- host = ("%s:%i" % (self.host, self.port))
- return host
-
- def base(self):
- final_url = ("%s://%s%s%s" % (self.scheme, self.http_host,
- urllib.quote(self.script_name, '/'), urllib.quote(self.path, '/')))
- return final_url
-
- def _path_info_start_with_slash(self):
- path_info = self.env.get('PATH_INFO', None)
- if path_info is not None and len(path_info) > 0 and path_info[0] == '/':
- return True
- else:
- return False
+ def __call__(self):
+ # XXX rework this part
+ self._expand()
+ self.url.path.append(self.path)
+ self._query_path()
+ # TODO headers etc
+ request = http.Request(self.method, str(self.url))
+ return request
+
+ def _build_url(self):
+ # TODO username password query params
+ self.url = http.Url(
+ scheme=self.scheme,
+ host=self.host,
+ port=self.port,
+ path=self.script_name,
+ )
+
+ def _query_path(self):
+ query_string = self.env.get('QUERY_STRING', None)
+ if query_string is not None:
+ self.url.query = query_string
def _expand(self):
params = self.env.get('spore.params', None)
@@ -73,12 +62,12 @@ def _expand(self):
return
path_info = self.path
- headers = self.env.get('spore.headers', None)
- form_data = self.env.get('spore.form_data', None)
+# headers = self.env.get('spore.headers', None)
+# form_data = self.env.get('spore.form_data', None)
query = []
- form = {}
- headers = []
+# form = {}
+# headers = []
for k, v in izip(params[::2], params[1::2]):
if path_info:
@@ -86,20 +75,11 @@ def _expand(self):
if changes:
continue
- query.append("%s=%s" % (k,v))
+ query.append((k, v))
path_info = re.sub(":\w+", '', path_info)
self.path = path_info
+ # TODO check what can be moved to Uri
if query:
- self.env['QUERY_STRING'] = '&'.join(query)
-
- def _execute_http_request(self, final_url):
- h = httplib2.Http(disable_ssl_certificate_validation=True)
- headers, content = h.request(final_url, self.env.get('REQUEST_METHOD'))
-
- status = headers['status']
- del headers['status']
- http_response = Response(self.env, status, headers, content)
-
- return http_response
+ self.env['QUERY_STRING'] = query
View
14 tests/data/base_url.yaml
@@ -1,6 +1,6 @@
-
host: 'localhost'
- base: 'http://localhost/'
+ base: 'http://localhost'
-
script_name: '/foo'
host: 'localhost'
@@ -12,27 +12,27 @@
-
scheme: 'http'
host: 'localhost:91'
- base: 'http://localhost:91/'
+ base: 'http://localhost:91'
-
scheme: 'http'
host: 'example.com'
- base: 'http://example.com/'
+ base: 'http://example.com'
-
scheme: 'https'
host: 'example.com'
- base: 'https://example.com/'
+ base: 'https://example.com'
-
scheme: 'http'
server_name: 'example.com'
server_port: 80
- base: 'http://example.com:80/'
+ base: 'http://example.com:80'
-
scheme: 'http'
server_name: 'example.com'
server_port: 8080
- base: 'http://example.com:8080/'
+ base: 'http://example.com:8080'
-
host: 'foobar.com'
server_name: 'example.com'
server_port: 8080
- base: 'http://foobar.com/'
+ base: 'http://foobar.com:8080'
View
18 tests/data/uri.yaml
@@ -1,27 +1,27 @@
-
- uri: http://example.com/
+ uri: http://example.com:80/
add_env:
HTTP_HOST: example.com
SCRIPT_NAME: ''
-
- uri: http://example.com/foo%20bar
+ uri: http://example.com:80/foo%20bar
add_env:
HTTP_HOST: example.com
SCRIPT_NAME: ''
PATH_INFO: /foo bar
-
- uri: http://example.com/test.c
+ uri: http://example.com:80/test.c
add_env:
HTTP_HOST: example.com
SCRIPT_NAME: /test.c
-
- uri: http://example.com/test.c/info
+ uri: http://example.com:80/test.c/info
add_env:
HTTP_HOST: example.com
SCRIPT_NAME: /test.c
PATH_INFO: /info
-
- uri: http://example.com/test?dynamic=daikuma
+ uri: http://example.com:80/test?dynamic=daikuma
add_env:
HTTP_HOST: example.com
SCRIPT_NAME: /test
@@ -29,7 +29,7 @@
- dynamic
- daikuma
-
- uri: http://example.com/exec/
+ uri: http://example.com:80/exec
add_env:
HTTP_HOST: example.com
SCRIPT_NAME: /exec/
@@ -40,7 +40,7 @@
-
uri: http://:80/
-
- uri: http://example.com/?aco=tie
+ uri: http://example.com:80/?aco=tie
add_env:
HTTP_HOST: example.com
SCRIPT_NAME: ''
@@ -48,13 +48,13 @@
- aco
- tie
-
- uri: http://example.com/foo%20bar/baz%20quux
+ uri: http://example.com:80/foo%20bar/baz%20quux
add_env:
HTTP_HOST: example.com
SCRIPT_NAME: /foo bar
PATH_INFO: /baz quux
-
- uri: http://example.com/foo/bar/
+ uri: http://example.com:80/foo/bar
add_env:
HTTP_HOST: example.com
SCRIPT_NAME: ''
View
4 tests/test_create.py
@@ -1,6 +1,6 @@
from unittest2 import TestCase
from spyre import new_from_spec, new_from_string
-from spyre.core import base
+from spyre.core import Spore
from http import Response
from spyre import errors
import os.path
@@ -36,7 +36,7 @@ def test_new_from_string(self):
f.close()
spore = new_from_string(spec_str)
self.assertTrue(spore)
- self.assertIsInstance(spore, base)
+ self.assertIsInstance(spore, Spore)
def test_inexisting_spec(self):
self.assertRaises(errors.SpyreObjectBuilder, new_from_spec, ('foo'))
View
7 tests/test_middleware_format_json.py
@@ -1,7 +1,5 @@
from unittest2 import TestCase
from spyre import new_from_spec
-import spyre.middleware
-import spyre.middleware.formatjson
import os.path
MY_DIR = os.path.dirname(__file__)
@@ -14,5 +12,6 @@ def test_simple(self):
spore = new_from_spec(spec)
spore.enable('formatjson')
resp = spore.get_user_info(username='franckcuny')
- self.assertEqual(resp.content['name'], 'franck')
- print resp.content_type
+ content = resp.content
+ print content
+ self.assertEqual(content['name'], 'franck')
View
31 tests/test_request.py
@@ -17,19 +17,19 @@ def _get_test_data(self, fname):
f.close()
return test_data
- def test_create_base_url(self):
- test_data_url = self._get_test_data('base_url')
-
- for test in test_data_url:
- env = {
- 'spore.url_scheme': test.get('scheme', 'http'),
- 'HTTP_HOST': test.get('host', None),
- 'SERVER_NAME': test.get('server_name', None),
- 'SERVER_PORT': test.get('server_port', None),
- 'SCRIPT_NAME': test.get('script_name', ''),
- }
- request = Request(env)
- self.assertEqual(request.base(), test['base'])
+# def test_create_base_url(self):
+# test_data_url = self._get_test_data('base_url')
+#
+# for test in test_data_url:
+# env = {
+# 'spore.url_scheme': test.get('scheme', 'http'),
+# 'HTTP_HOST': test.get('host', None),
+# 'SERVER_NAME': test.get('server_name', None),
+# 'SERVER_PORT': test.get('server_port', None),
+# 'SCRIPT_NAME': test.get('script_name', ''),
+# }
+# request = Request(env)
+# self.assertEqual(request.uri_base, test['base'])
def test_populate_uri(self):
test_data_url = self._get_test_data('uri')
@@ -39,10 +39,11 @@ def test_populate_uri(self):
'SERVER_PORT': 80
}
if test.get('add_env', None) is not None:
- for k,v in test['add_env'].iteritems():
+ for k, v in test['add_env'].iteritems():
env[k] = v
req = Request(env)
- self.assertEqual(req._finalize(), test['uri'])
+ req()
+ self.assertEqual(req.url, test['uri'])
#def test_populate_headers(self):
#test_data_headers = self._get_test_data('headers')
View
23 tests/test_spyre_method.py
@@ -1,6 +1,7 @@
from unittest2 import TestCase
+from httpclient import HTTPClient
from spyre.method import Method
-from spyre.core import base
+from spyre.core import Spore
from spyre import errors
import os.path
@@ -11,31 +12,37 @@
f = open(spec_file, 'r')
spec_str = f.read()
f.close()
-base = base(spec_str, base_url)
+base = Spore(spec_str, base_url)
+
class TestSpyreMethod(TestCase):
+ def setUp(self):
+ self.user_agent = HTTPClient()
+ self.url = 'http://github.com/api/v2/json/'
+
def test_required_attr(self):
method_name = 'test'
method_desc = {}
self.failUnlessRaises(errors.SpyreMethodBuilder,
Method, method_name,
- method_desc, base)
+ method_desc, base_url=self.url, user_agent=self.user_agent)
method_desc['method'] = 'GET'
self.failUnlessRaises(errors.SpyreMethodBuilder,
Method, method_name,
- method_desc, base)
+ method_desc, base_url=self.url, user_agent=self.user_agent)
- method_desc['path'] = '/users/:username'
+ method_desc['path'] = '/user/show/:username'
method_desc['required_params'] = ['username']
method_desc['expected_status'] = [200, 404, 406]
- method = Method(method_name, method_desc, base)
+ method = Method(method_name, method_desc, base_url=self.url, user_agent=self.user_agent)
self.assertTrue(method)
resp = method(username='franckcuny')
- self.assertEqual(resp.status, '200')
+ print resp.content
+ self.assertEqual(resp.status, 200)
def test_optional_attr(self):
method_name = 'test'
@@ -43,7 +50,7 @@ def test_optional_attr(self):
'required_params': ['username']}
base_url = 'http://github.com/api/v2/'
- method = Method(method_name, method_desc, base)
+ method = Method(method_name, method_desc, base_url=self.url, user_agent=self.user_agent)
self.assertTrue(method)
self.failUnlessRaises(errors.SpyreMethodCall, method)
Please sign in to comment.
Something went wrong with that request. Please try again.