Skip to content

Commit 74d64a5

Browse files
committed
Adds requests transport
* Adds pypy to .travis.yml file. * Adds requests as a dependency for python >= 2.6. The requests endpoint is * For 2.5 and below, it uses the old xmlrpclib stuff (hacky and deprecated). * Fixed help() for all versions of python.
1 parent 85bf04a commit 74d64a5

12 files changed

Lines changed: 345 additions & 233 deletions

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ python:
55
- "2.7"
66
- "3.2"
77
- "3.3"
8+
- "pypy"
89
# command to install dependencies
910
install:
1011
- "pip install -r requirements.txt --use-mirrors"

SoftLayer/API.py

Lines changed: 49 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -29,23 +29,19 @@
2929
3030
See U{http://sldn.softlayer.com/article/Python}
3131
"""
32-
33-
from urlparse import urlparse
34-
from SoftLayer.consts import API_PUBLIC_ENDPOINT, API_PRIVATE_ENDPOINT
35-
from SoftLayer.transport import ProxyTransport, SecureProxyTransport
36-
import socket
32+
from SoftLayer.consts import API_PUBLIC_ENDPOINT, API_PRIVATE_ENDPOINT, \
33+
USER_AGENT
34+
from SoftLayer.transport import make_api_call
35+
from SoftLayer.exceptions import SoftLayerError
3736
import xmlrpclib
3837
import os
38+
import sys
3939

4040
API_USERNAME = None
4141
API_KEY = None
4242
API_BASE_URL = API_PUBLIC_ENDPOINT
4343

4444

45-
class SoftLayerError(Exception):
46-
pass
47-
48-
4945
class Client(object):
5046
"""A SoftLayer API client
5147
@@ -73,15 +69,16 @@ class Client(object):
7369
7470
"""
7571
_prefix = "SoftLayer_"
76-
_server_proxy = xmlrpclib.ServerProxy
7772

7873
def __init__(self, service_name=None, id=None, username=None, api_key=None,
7974
endpoint_url=None, timeout=None, verbose=False):
80-
self.verbose = verbose
8175
self._service_name = service_name
76+
self.verbose = verbose
8277
self._headers = {}
78+
self._raw_headers = {}
8379

84-
self.username = username or API_USERNAME or os.environ.get('SL_USERNAME')
80+
self.username = username or API_USERNAME or \
81+
os.environ.get('SL_USERNAME')
8582
self.api_key = api_key or API_KEY or os.environ.get('SL_API_KEY')
8683

8784
if not all((self.username, self.api_key)):
@@ -93,22 +90,15 @@ def __init__(self, service_name=None, id=None, username=None, api_key=None,
9390
if id is not None:
9491
self.set_init_parameter(int(id))
9592

96-
self._endpoint_url = (endpoint_url or API_BASE_URL or \
97-
API_PUBLIC_ENDPOINT).rstrip('/')
98-
http_protocol = urlparse(self._endpoint_url).scheme
99-
100-
if http_protocol == "https":
101-
self.transport = SecureProxyTransport()
102-
else:
103-
self.transport = ProxyTransport()
104-
93+
self._endpoint_url = (endpoint_url or API_BASE_URL or
94+
API_PUBLIC_ENDPOINT).rstrip('/')
10595
self.timeout = timeout
10696

10797
def add_raw_header(self, name, value):
10898
""" Set HTTP headers for API calls
10999
.. deprecated:: 2.0.0
110100
"""
111-
self.transport.set_raw_header(name, value)
101+
self._raw_headers[name] = value
112102

113103
def add_header(self, name, value):
114104
""" Set a SoftLayer API call header
@@ -247,9 +237,16 @@ def __call__(self, service, method, *args, **kwargs):
247237
'apiKey': self.api_key,
248238
}}
249239

240+
http_headers = {
241+
'User-Agent': USER_AGENT,
242+
'Content-Type': 'application/xml',
243+
}
244+
if self._raw_headers:
245+
for name, value in self._raw_headers.items():
246+
http_headers[name] = value
250247
if raw_headers:
251248
for name, value in raw_headers.items():
252-
self.transport.set_raw_header(name, value)
249+
http_headers[name] = value
253250

254251
if objectid is not None:
255252
headers[service + 'InitParameters'] = {'id': int(objectid)}
@@ -266,23 +263,15 @@ def __call__(self, service, method, *args, **kwargs):
266263

267264
if limit:
268265
headers['resultLimit'] = {
269-
'limit': int(limit),
270-
'offset': int(offset)
271-
}
272-
273-
__prevDefaultTimeout = socket.getdefaulttimeout()
274-
try:
275-
uri = '/'.join([self._endpoint_url, service])
276-
socket.setdefaulttimeout(self.timeout)
277-
proxy = self._server_proxy(uri, transport=self.transport,
278-
verbose=self.verbose, allow_none=True)
279-
return getattr(proxy, method)({'headers': headers}, *args)
280-
except xmlrpclib.Fault, e:
281-
raise SoftLayerError(e.faultString)
282-
finally:
283-
socket.setdefaulttimeout(__prevDefaultTimeout)
284-
285-
def __getattribute__(self, name):
266+
'limit': int(limit),
267+
'offset': int(offset)
268+
}
269+
uri = '/'.join([self._endpoint_url, service])
270+
return make_api_call(uri, method, args, headers=headers,
271+
http_headers=http_headers, timeout=self.timeout,
272+
verbose=self.verbose)
273+
274+
def __getattr__(self, name):
286275
""" Attempt a SoftLayer API call
287276
.. deprecated:: 2.0.0
288277
@@ -292,21 +281,23 @@ def __getattribute__(self, name):
292281
attempting a SoftLayer API call and return a simple function that makes
293282
an XML-RPC call.
294283
"""
295-
if name == '__name__': raise AttributeError # for help(self)
296-
try:
297-
return object.__getattribute__(self, name)
298-
except AttributeError:
299-
def call_handler(*args, **kwargs):
300-
if self._service_name is None:
301-
raise SoftLayerError("Service is not set on Client instance.")
302-
kwargs['headers'] = self._headers
303-
return self(self._service_name, name, *args, **kwargs)
304-
return call_handler
284+
if name in ["__name__", "__bases__"]:
285+
raise AttributeError("'Obj' object has no attribute '%s'" % name)
286+
287+
def call_handler(*args, **kwargs):
288+
if self._service_name is None:
289+
raise SoftLayerError(
290+
"Service is not set on Client instance.")
291+
kwargs['headers'] = self._headers
292+
return self(self._service_name, name, *args, **kwargs)
293+
return call_handler
305294

306295
def __repr__(self):
307296
return "<Client: endpoint=%s, user=%s>" \
308297
% (self._endpoint_url, self.username)
309298

299+
__str__ = __repr__
300+
310301

311302
class Service(object):
312303
def __init__(self, client, name):
@@ -316,15 +307,15 @@ def __init__(self, client, name):
316307
def __call__(self, name, *args, **kwargs):
317308
return self.client(self.name, name, *args, **kwargs)
318309

319-
def __getattribute__(self, name):
320-
if name == '__name__': raise AttributeError # for help(self)
321-
try:
322-
return object.__getattribute__(self, name)
323-
except AttributeError:
324-
def call_handler(*args, **kwargs):
325-
return self(name, *args, **kwargs)
326-
return call_handler
310+
def __getattr__(self, name):
311+
if name in ["__name__", "__bases__"]:
312+
raise AttributeError("'Obj' object has no attribute '%s'" % name)
313+
314+
def call_handler(*args, **kwargs):
315+
return self(name, *args, **kwargs)
316+
return call_handler
327317

328318
def __repr__(self):
329319
return "<Service: %s>" % (self.name,)
330320

321+
__str__ = __repr__

SoftLayer/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"""
2727
SoftLayer Python API Client
2828
~~~~~~~~~~~~~~~~~~~~~~~~~~~
29-
A library to contact SoftLayer's backend services through the XML-RPC interface.
29+
A library to contact SoftLayer's backend services through the XML-RPC interface
3030
See U{http://sldn.softlayer.com/article/Python}
3131
3232
@@ -49,5 +49,5 @@
4949
__all__ = ['Client', 'SoftLayerError', 'API_PUBLIC_ENDPOINT',
5050
'API_PRIVATE_ENDPOINT']
5151

52-
from API import Client, SoftLayerError, API_PUBLIC_ENDPOINT, \
53-
API_PRIVATE_ENDPOINT
52+
from API import Client, API_PUBLIC_ENDPOINT, API_PRIVATE_ENDPOINT
53+
from SoftLayer.exceptions import SoftLayerError

SoftLayer/exceptions.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
3+
class SoftLayerError(Exception):
4+
pass

0 commit comments

Comments
 (0)