svn merge -r70295:70503 svn+ssh://svn/svn/linden/branches/pylibs-freshen3
parent
7f9aa65bfb
commit
910c792b00
|
|
@ -27,16 +27,20 @@ def load(indra_xml_file=None):
|
|||
config_file.close()
|
||||
#print "loaded config from",indra_xml_file,"into",_g_config_dict
|
||||
|
||||
def update(xml_file):
|
||||
def update(new_conf):
|
||||
"""Load an XML file and apply its map as overrides or additions
|
||||
to the existing config. The dataserver does this with indra.xml
|
||||
and dataserver.xml."""
|
||||
global _g_config_dict
|
||||
if _g_config_dict == None:
|
||||
raise Exception("no config loaded before config.update()")
|
||||
config_file = file(xml_file)
|
||||
overrides = llsd.LLSD().parse(config_file.read())
|
||||
config_file.close()
|
||||
_g_config_dict = {}
|
||||
if isinstance(new_conf, dict):
|
||||
overrides = new_conf
|
||||
else:
|
||||
config_file = file(new_conf)
|
||||
overrides = llsd.LLSD().parse(config_file.read())
|
||||
config_file.close()
|
||||
|
||||
_g_config_dict.update(overrides)
|
||||
|
||||
def get(key, default = None):
|
||||
|
|
@ -44,3 +48,7 @@ def get(key, default = None):
|
|||
if _g_config_dict == None:
|
||||
load()
|
||||
return _g_config_dict.get(key, default)
|
||||
|
||||
def as_dict():
|
||||
global _g_config_dict
|
||||
return _g_config_dict
|
||||
|
|
|
|||
|
|
@ -136,7 +136,8 @@ class LLSDXMLFormatter(object):
|
|||
list : self.ARRAY,
|
||||
tuple : self.ARRAY,
|
||||
types.GeneratorType : self.ARRAY,
|
||||
dict : self.MAP
|
||||
dict : self.MAP,
|
||||
LLSD : self.LLSD
|
||||
}
|
||||
|
||||
def elt(self, name, contents=None):
|
||||
|
|
@ -148,6 +149,8 @@ class LLSDXMLFormatter(object):
|
|||
def xml_esc(self, v):
|
||||
return v.replace('&', '&').replace('<', '<').replace('>', '>')
|
||||
|
||||
def LLSD(self, v):
|
||||
return self.generate(v.thing)
|
||||
def UNDEF(self, v):
|
||||
return self.elt('undef')
|
||||
def BOOLEAN(self, v):
|
||||
|
|
@ -212,9 +215,12 @@ class LLSDNotationFormatter(object):
|
|||
list : self.ARRAY,
|
||||
tuple : self.ARRAY,
|
||||
types.GeneratorType : self.ARRAY,
|
||||
dict : self.MAP
|
||||
dict : self.MAP,
|
||||
LLSD : self.LLSD
|
||||
}
|
||||
|
||||
def LLSD(self, v):
|
||||
return self.generate(v.thing)
|
||||
def UNDEF(self, v):
|
||||
return '!'
|
||||
def BOOLEAN(self, v):
|
||||
|
|
@ -739,6 +745,8 @@ def format_binary(something):
|
|||
def _format_binary_recurse(something):
|
||||
if something is None:
|
||||
return '!'
|
||||
elif isinstance(something, LLSD):
|
||||
return _format_binary_recurse(something.thing)
|
||||
elif isinstance(something, bool):
|
||||
if something:
|
||||
return '1'
|
||||
|
|
@ -807,3 +815,36 @@ class LLSD(object):
|
|||
|
||||
undef = LLSD(None)
|
||||
|
||||
# register converters for stacked, if stacked is available
|
||||
try:
|
||||
from mulib import stacked
|
||||
except ImportError, e:
|
||||
print "Not able to import stacked, skipping registering llsd converters."
|
||||
pass # don't bother with the converters
|
||||
else:
|
||||
def llsd_convert_json(llsd_stuff, request):
|
||||
callback = request.get_header('callback')
|
||||
if callback is not None:
|
||||
## See Yahoo's ajax documentation for information about using this
|
||||
## callback style of programming
|
||||
## http://developer.yahoo.com/common/json.html#callbackparam
|
||||
req.write("%s(%s)" % (callback, simplejson.dumps(llsd_stuff)))
|
||||
else:
|
||||
req.write(simplejson.dumps(llsd_stuff))
|
||||
|
||||
def llsd_convert_xml(llsd_stuff, request):
|
||||
request.write(format_xml(llsd_stuff))
|
||||
|
||||
def llsd_convert_binary(llsd_stuff, request):
|
||||
request.write(format_binary(llsd_stuff))
|
||||
|
||||
for typ in [LLSD, dict, list, tuple, str, int, float, bool, unicode, type(None)]:
|
||||
stacked.add_producer(typ, llsd_convert_json, 'application/json')
|
||||
|
||||
stacked.add_producer(typ, llsd_convert_xml, 'application/llsd+xml')
|
||||
stacked.add_producer(typ, llsd_convert_xml, 'application/xml')
|
||||
stacked.add_producer(typ, llsd_convert_xml, 'text/xml')
|
||||
|
||||
stacked.add_producer(typ, llsd_convert_binary, 'application/llsd+binary')
|
||||
|
||||
stacked.add_producer(LLSD, llsd_convert_xml, '*/*')
|
||||
|
|
|
|||
|
|
@ -258,11 +258,12 @@ def uuid_bits_to_uuid(bits):
|
|||
|
||||
|
||||
try:
|
||||
from mulib import mu
|
||||
from mulib import stacked
|
||||
except ImportError:
|
||||
print "Couldn't import mulib, not registering UUID converter"
|
||||
else:
|
||||
def convertUUID(req, uuid):
|
||||
return str(uuid)
|
||||
def convertUUID(uuid, req):
|
||||
req.write(str(uuid))
|
||||
|
||||
mu.registerConverter(UUID, convertUUID)
|
||||
stacked.add_producer(UUID, convertUUID, "*/*")
|
||||
stacked.add_producer(UUID, convertUUID, "text/html")
|
||||
|
|
|
|||
|
|
@ -10,251 +10,55 @@ import os.path
|
|||
import os
|
||||
import urlparse
|
||||
|
||||
|
||||
from eventlet import httpc as httputil
|
||||
|
||||
|
||||
|
||||
from indra.base import llsd
|
||||
LLSD = llsd.LLSD()
|
||||
|
||||
from eventlet import httpc
|
||||
|
||||
|
||||
class ConnectionError(Exception):
|
||||
def __init__(self, method, host, port, path, status, reason, body):
|
||||
self.method = method
|
||||
self.host = host
|
||||
self.port = port
|
||||
self.path = path
|
||||
self.status = status
|
||||
self.reason = reason
|
||||
self.body = body
|
||||
Exception.__init__(self)
|
||||
|
||||
def __str__(self):
|
||||
return "%s(%r, %r, %r, %r, %r, %r, %r)" % (
|
||||
self.__class__.__name__,
|
||||
self.method, self.host, self.port,
|
||||
self.path, self.status, self.reason, self.body)
|
||||
get, put, delete, post = httpc.make_suite(
|
||||
llsd.format_xml, llsd.parse, 'application/xml+llsd')
|
||||
|
||||
|
||||
class NotFound(ConnectionError):
|
||||
pass
|
||||
|
||||
class Forbidden(ConnectionError):
|
||||
pass
|
||||
|
||||
class MalformedResponse(ConnectionError):
|
||||
pass
|
||||
|
||||
class NotImplemented(ConnectionError):
|
||||
pass
|
||||
|
||||
def runConnection(connection, raise_parse_errors=True):
|
||||
response = connection.getresponse()
|
||||
if (response.status not in [200, 201, 204]):
|
||||
klass = {404:NotFound,
|
||||
403:Forbidden,
|
||||
501:NotImplemented}.get(response.status, ConnectionError)
|
||||
raise klass(
|
||||
connection.method, connection.host, connection.port,
|
||||
connection.path, response.status, response.reason, response.read())
|
||||
content_length = response.getheader('content-length')
|
||||
|
||||
if content_length: # Check to see whether it is not None
|
||||
content_length = int(content_length)
|
||||
|
||||
if content_length: # Check to see whether the length is not 0
|
||||
body = response.read(content_length)
|
||||
else:
|
||||
body = ''
|
||||
|
||||
if not body.strip():
|
||||
#print "No body:", `body`
|
||||
return None
|
||||
try:
|
||||
return LLSD.parse(body)
|
||||
except Exception, e:
|
||||
if raise_parse_errors:
|
||||
print "Exception: %s, Could not parse LLSD: " % (e), body
|
||||
raise MalformedResponse(
|
||||
connection.method, connection.host, connection.port,
|
||||
connection.path, response.status, response.reason, body)
|
||||
else:
|
||||
return None
|
||||
|
||||
class FileScheme(object):
|
||||
"""Retarded scheme to local file wrapper."""
|
||||
host = '<file>'
|
||||
port = '<file>'
|
||||
reason = '<none>'
|
||||
|
||||
def __init__(self, location):
|
||||
pass
|
||||
|
||||
def request(self, method, fullpath, body='', headers=None):
|
||||
self.status = 200
|
||||
self.path = fullpath.split('?')[0]
|
||||
self.method = method = method.lower()
|
||||
assert method in ('get', 'put', 'delete')
|
||||
if method == 'delete':
|
||||
try:
|
||||
os.remove(self.path)
|
||||
except OSError:
|
||||
pass # don't complain if already deleted
|
||||
elif method == 'put':
|
||||
try:
|
||||
f = file(self.path, 'w')
|
||||
f.write(body)
|
||||
f.close()
|
||||
except IOError, e:
|
||||
self.status = 500
|
||||
self.raise_connection_error()
|
||||
elif method == 'get':
|
||||
if not os.path.exists(self.path):
|
||||
self.status = 404
|
||||
self.raise_connection_error(NotFound)
|
||||
|
||||
def connect(self):
|
||||
pass
|
||||
|
||||
def getresponse(self):
|
||||
return self
|
||||
|
||||
def getheader(self, header):
|
||||
if header == 'content-length':
|
||||
try:
|
||||
return os.path.getsize(self.path)
|
||||
except OSError:
|
||||
return 0
|
||||
|
||||
def read(self, howmuch=None):
|
||||
if self.method == 'get':
|
||||
try:
|
||||
return file(self.path, 'r').read(howmuch)
|
||||
except IOError:
|
||||
self.status = 500
|
||||
self.raise_connection_error()
|
||||
return ''
|
||||
|
||||
def raise_connection_error(self, klass=ConnectionError):
|
||||
raise klass(
|
||||
self.method, self.host, self.port,
|
||||
self.path, self.status, self.reason, '')
|
||||
|
||||
scheme_to_factory_map = {
|
||||
'http': httputil.HttpClient,
|
||||
'https': httputil.HttpsClient,
|
||||
'file': FileScheme,
|
||||
}
|
||||
|
||||
def makeConnection(scheme, location, use_proxy):
|
||||
if use_proxy:
|
||||
if "http_proxy" in os.environ:
|
||||
location = os.environ["http_proxy"]
|
||||
elif "ALL_PROXY" in os.environ:
|
||||
location = os.environ["ALL_PROXY"]
|
||||
else:
|
||||
location = "localhost:3128" #default to local squid
|
||||
if location.startswith("http://"):
|
||||
location = location[len("http://"):]
|
||||
return scheme_to_factory_map[scheme](location)
|
||||
for x in (httpc.ConnectionError, httpc.NotFound, httpc.Forbidden):
|
||||
globals()[x.__name__] = x
|
||||
|
||||
|
||||
def get(url, headers=None, use_proxy=False):
|
||||
if headers is None:
|
||||
headers = {}
|
||||
scheme, location, path, params, query, id = urlparse.urlparse(url)
|
||||
connection = makeConnection(scheme, location, use_proxy=use_proxy)
|
||||
fullpath = path
|
||||
if query:
|
||||
fullpath += "?"+query
|
||||
connection.connect()
|
||||
if headers is None:
|
||||
headers=dict()
|
||||
if use_proxy:
|
||||
headers.update({ "Host" : location })
|
||||
connection.request("GET", url, headers=headers)
|
||||
else:
|
||||
connection.request("GET", fullpath, headers=headers)
|
||||
|
||||
return runConnection(connection)
|
||||
|
||||
def put(url, data, headers=None):
|
||||
body = LLSD.toXML(data)
|
||||
scheme, location, path, params, query, id = urlparse.urlparse(url)
|
||||
connection = makeConnection(scheme, location, use_proxy=False)
|
||||
if headers is None:
|
||||
headers = {}
|
||||
headers.update({'Content-Type': 'application/xml'})
|
||||
fullpath = path
|
||||
if query:
|
||||
fullpath += "?"+query
|
||||
connection.request("PUT", fullpath, body, headers)
|
||||
return runConnection(connection, raise_parse_errors=False)
|
||||
|
||||
def delete(url):
|
||||
scheme, location, path, params, query, id = urlparse.urlparse(url)
|
||||
connection = makeConnection(scheme, location, use_proxy=False)
|
||||
connection.request("DELETE", path+"?"+query)
|
||||
return runConnection(connection, raise_parse_errors=False)
|
||||
|
||||
def post(url, data=None):
|
||||
body = LLSD.toXML(data)
|
||||
scheme, location, path, params, query, id = urlparse.urlparse(url)
|
||||
connection = makeConnection(scheme, location, use_proxy=False)
|
||||
connection.request("POST", path+"?"+query, body, {'Content-Type': 'application/xml'})
|
||||
return runConnection(connection)
|
||||
|
||||
def postFile(url, filename):
|
||||
def postFile(url, filename, verbose=False):
|
||||
f = open(filename)
|
||||
body = f.read()
|
||||
f.close()
|
||||
scheme, location, path, params, query, id = urlparse.urlparse(url)
|
||||
connection = makeConnection(scheme, location, use_proxy=False)
|
||||
connection.request("POST", path+"?"+query, body, {'Content-Type': 'application/octet-stream'})
|
||||
return runConnection(connection)
|
||||
llsd_body = llsd.parse(bodY)
|
||||
return post(url, llsd_body, verbose=verbose)
|
||||
|
||||
|
||||
def getStatus(url, use_proxy=False):
|
||||
scheme, location, path, params, query, id = urlparse.urlparse(url)
|
||||
connection = makeConnection(scheme, location, use_proxy=use_proxy)
|
||||
if use_proxy:
|
||||
connection.request("GET", url, headers={ "Host" : location })
|
||||
else:
|
||||
connection.request("GET", path+"?"+query)
|
||||
return connection.getresponse().status
|
||||
status, _headers, _body = get(url, use_proxy=use_proxy, verbose=True)
|
||||
return status
|
||||
|
||||
|
||||
def putStatus(url, data):
|
||||
body = LLSD.toXML(data)
|
||||
scheme, location, path, params, query, id = urlparse.urlparse(url)
|
||||
connection = makeConnection(scheme, location, use_proxy=False)
|
||||
connection.request("PUT", path+"?"+query, body, {'Content-Type': 'application/xml'})
|
||||
return connection.getresponse().status
|
||||
status, _headers, _body = put(url, data, verbose=True)
|
||||
return status
|
||||
|
||||
|
||||
def deleteStatus(url):
|
||||
scheme, location, path, params, query, id = urlparse.urlparse(url)
|
||||
connection = makeConnection(scheme, location, use_proxy=False)
|
||||
connection.request("DELETE", path+"?"+query)
|
||||
return connection.getresponse().status
|
||||
status, _headers, _body = delete(url, verbose=True)
|
||||
return status
|
||||
|
||||
|
||||
def postStatus(url, data):
|
||||
body = LLSD.toXML(data)
|
||||
scheme, location, path, params, query, id = urlparse.urlparse(url)
|
||||
connection = makeConnection(scheme, location, use_proxy=False)
|
||||
connection.request("POST", path+"?"+query, body)
|
||||
return connection.getresponse().status
|
||||
status, _headers, _body = post(url, data, verbose=True)
|
||||
return status
|
||||
|
||||
|
||||
def postFileStatus(url, filename):
|
||||
f = open(filename)
|
||||
body = f.read()
|
||||
f.close()
|
||||
scheme, location, path, params, query, id = urlparse.urlparse(url)
|
||||
connection = makeConnection(scheme, location, use_proxy=False)
|
||||
connection.request("POST", path+"?"+query, body, {'Content-Type': 'application/octet-stream'})
|
||||
response = connection.getresponse()
|
||||
return response.status, response.read()
|
||||
status, _headers, body = postFile(url, filename, verbose=True)
|
||||
return status, body
|
||||
|
||||
|
||||
def getFromSimulator(path, use_proxy=False):
|
||||
return get('http://' + simulatorHostAndPort + path, use_proxy=use_proxy)
|
||||
|
||||
|
||||
def postToSimulator(path, data=None):
|
||||
return post('http://' + simulatorHostAndPort + path, data)
|
||||
|
|
|
|||
|
|
@ -11,15 +11,28 @@ from indra.base import config
|
|||
from indra.ipc import llsdhttp
|
||||
from indra.ipc import russ
|
||||
|
||||
# *NOTE: agent presence relies on this variable existing and being current, it is a huge hack
|
||||
services_config = {}
|
||||
try:
|
||||
services_config = llsdhttp.get(config.get('services-config'))
|
||||
except:
|
||||
pass
|
||||
|
||||
# convenience method for when you can't be arsed to make your own object (i.e. all the time)
|
||||
_g_builder = None
|
||||
def build(name, context):
|
||||
def build(name, context={}, **kwargs):
|
||||
""" Convenience method for using a global, singleton, service builder. Pass arguments either via a dict or via python keyword arguments, or both!
|
||||
|
||||
Example use:
|
||||
> context = {'channel':'Second Life Release', 'version':'1.18.2.0'}
|
||||
> servicebuilder.build('version-manager-version', context)
|
||||
'http://int.util.vaak.lindenlab.com/channel/Second%20Life%20Release/1.18.2.0'
|
||||
> servicebuilder.build('version-manager-version', channel='Second Life Release', version='1.18.2.0')
|
||||
'http://int.util.vaak.lindenlab.com/channel/Second%20Life%20Release/1.18.2.0'
|
||||
> servicebuilder.build('version-manager-version', context, version='1.18.1.2')
|
||||
'http://int.util.vaak.lindenlab.com/channel/Second%20Life%20Release/1.18.1.2'
|
||||
"""
|
||||
context = context.copy() # shouldn't modify the caller's dictionary
|
||||
context.update(kwargs)
|
||||
global _g_builder
|
||||
if _g_builder is None:
|
||||
_g_builder = ServiceBuilder()
|
||||
|
|
|
|||
|
|
@ -189,19 +189,19 @@ def handle(yielder):
|
|||
return result
|
||||
|
||||
|
||||
VALUE = mu.tagFactory('value')
|
||||
BOOLEAN = mu.tagFactory('boolean')
|
||||
INT = mu.tagFactory('int')
|
||||
STRUCT = mu.tagFactory('struct')
|
||||
MEMBER = mu.tagFactory('member')
|
||||
NAME = mu.tagFactory('name')
|
||||
ARRAY = mu.tagFactory('array')
|
||||
DATA = mu.tagFactory('data')
|
||||
STRING = mu.tagFactory('string')
|
||||
DOUBLE = mu.tagFactory('double')
|
||||
METHODRESPONSE = mu.tagFactory('methodResponse')
|
||||
PARAMS = mu.tagFactory('params')
|
||||
PARAM = mu.tagFactory('param')
|
||||
VALUE = mu.tag_factory('value')
|
||||
BOOLEAN = mu.tag_factory('boolean')
|
||||
INT = mu.tag_factory('int')
|
||||
STRUCT = mu.tag_factory('struct')
|
||||
MEMBER = mu.tag_factory('member')
|
||||
NAME = mu.tag_factory('name')
|
||||
ARRAY = mu.tag_factory('array')
|
||||
DATA = mu.tag_factory('data')
|
||||
STRING = mu.tag_factory('string')
|
||||
DOUBLE = mu.tag_factory('double')
|
||||
METHODRESPONSE = mu.tag_factory('methodResponse')
|
||||
PARAMS = mu.tag_factory('params')
|
||||
PARAM = mu.tag_factory('param')
|
||||
|
||||
mu.inline_elements['string'] = True
|
||||
mu.inline_elements['boolean'] = True
|
||||
|
|
|
|||
Loading…
Reference in New Issue