[open-ils-commits] r1274 - conifer/branches/rel_1_6_1/tools (dbs)

svn at svn.open-ils.org svn at svn.open-ils.org
Tue Mar 22 15:54:48 EDT 2011


Author: dbs
Date: 2011-03-22 15:54:43 -0400 (Tue, 22 Mar 2011)
New Revision: 1274

Added:
   conifer/branches/rel_1_6_1/tools/osrf_gateway_request.py
Log:
Provide a sample Python script that makes gateway requests

This script uses the canonical fieldmapper IDL parsing contained
in the Evergreen Python modules to instantiate objects and methods
and to pass them back and forth via HTTP to the OpenSRF gateway.

Many thanks to Bill Erickson for, well, everything :)


Added: conifer/branches/rel_1_6_1/tools/osrf_gateway_request.py
===================================================================
--- conifer/branches/rel_1_6_1/tools/osrf_gateway_request.py	                        (rev 0)
+++ conifer/branches/rel_1_6_1/tools/osrf_gateway_request.py	2011-03-22 19:54:43 UTC (rev 1274)
@@ -0,0 +1,174 @@
+"""
+Demonstrate the use of Python to make OpenSRF gateway requests
+
+Based on Bill Erickson's work in the constrictor Evergreen workloads
+in http://svn.open-ils.org/ILS-Contrib/browser/constrictor/trunk
+"""
+
+import oils.event
+import oils.utils.idl
+import oils.utils.utils
+import osrf.gateway
+import osrf.json
+import tempfile
+import urllib2
+
+# Store local settings inside syrup.py
+import syrup
+
+def load_idl():
+    """
+    Loads the fieldmapper IDL, registering class hints for the defined objects
+
+    We use a temporary file to store the IDL each time load_idl()
+    is invoked to ensure that the IDL is in sync with the target
+    server. One could a HEAD request to do some smarter caching,
+    perhaps.
+    """
+    
+    parser = oils.utils.idl.IDLParser()
+    idlfile = tempfile.TemporaryFile()
+
+    # Get the fm_IDL.xml file from the server
+    try:
+        idl = urllib2.urlopen('%s://%s/%s' % 
+            (syrup.OSRF_HTTP, syrup.OSRF_HOST, syrup.IDL_URL)
+        )
+        idlfile.write(idl.read())
+        # rewind to the beginning of the file
+        idlfile.seek(0)
+
+    except urllib2.URLError, exc:
+        print("Could not open URL to read IDL: %s", exc.code)
+
+    except IOError, exc:
+        print("Could not write IDL to file: %s", exc.code)
+
+    # parse the IDL
+    parser.set_IDL(idlfile)
+    parser.parse_IDL()
+
+def login(username, password, workstation=None):
+    """
+    Login to the server and get back an authtoken
+    """
+
+    __authtoken = None
+
+    print("attempting login with user " + username)
+
+    seed = request(
+        'open-ils.auth', 
+        'open-ils.auth.authenticate.init', username).send()
+
+    # generate the hashed password
+    password = oils.utils.utils.md5sum(seed + oils.utils.utils.md5sum(password))
+
+    result = request(
+        'open-ils.auth',
+        'open-ils.auth.authenticate.complete',
+        {   'workstation' : workstation,
+            'username' : username,
+            'password' : password,
+            'type' : 'staff' 
+        }).send()
+
+    evt = oils.event.Event.parse_event(result)
+    if evt and not evt.success:
+        raise AuthException(evt.text_code)
+
+    __authtoken = result['payload']['authtoken']
+    return __authtoken
+
+def request(service, method, *args):
+    """
+    Make a JSON request to the OpenSRF gateway
+
+    This is as simple as it gets. Atomic requests will require a bit
+    more effort.
+    """
+
+    req = osrf.gateway.JSONGatewayRequest(service, method, *args)
+
+    # The gateway URL ensures we're using JSON v1, not v0
+    req.setPath(syrup.GATEWAY_URL)
+    return req
+
+class AuthException(Exception):
+    """
+    Exceptions for authentication events
+    """
+
+    def __init__(self, msg=''):
+        """
+        Initialize the authentication exception
+        """
+        Exception.__init__(self)
+        self.msg = msg
+
+    def __str__(self):
+        """
+        Stringify the authentication exception
+        """
+        return 'AuthException: %s' % self.msg
+
+if __name__ == '__main__':
+
+    # Set the host for our requests
+    osrf.gateway.GatewayRequest.setDefaultHost(syrup.OSRF_HOST)
+
+    # Pull all of our object definitions together
+    load_idl()
+
+    # Log in and get an authtoken
+    authtoken = login('foo', 'bar')
+
+    # Issue a plain old position-dependent request
+    req = request('open-ils.search', 'open-ils.search.biblio.record.copy_count', 105, 891001, None)
+    res = req.send()
+    print(res[0])
+
+    # Get a plain Jane acp (copy) object by barcode
+    barcode = '791068-1001'
+    req = request('open-ils.search', 'open-ils.search.asset.copy.find_by_barcode', barcode)
+    barcode_copy = req.send()
+    print "Raw JSON: ", osrf.json.to_json(barcode_copy)
+
+    # id() and call_number() are fields defined in fm_IDL.xml
+    print "Copy ID: ", barcode_copy.id()
+    print "Call number ID: ", barcode_copy.call_number()
+
+    # Get a fleshed out copy (now with more fields!) by barcode
+    req = request('open-ils.search', 'open-ils.search.asset.copy.fleshed2.find_by_barcode', barcode)
+    barcode_copy = req.send()
+    print "Raw JSON: ", osrf.json.to_json(barcode_copy)
+
+    # id() and call_number() are fields defined in fm_IDL.xml
+    print "Copy ID: ", barcode_copy.id()
+    print "Call number ID: ", barcode_copy.call_number()
+
+    # Note - fleshed fields don't appear to be retrievable with the expected syntax
+    # The following does _not_ work:
+    #
+    # print "Copy location: ", barcode_copy.acpl().name()
+    #
+    # And the following just prints null values for an acpl object:
+    #
+    # print osrf.json.to_json(barcode_copy.acpl())
+
+    # Get a plain acn (callnumber) object by ID
+    req = request('open-ils.search', 'open-ils.search.asset.call_number.retrieve', barcode_copy.call_number())
+    call_num = req.send()
+    print "Raw JSON: ", osrf.json.to_json(call_num)
+    print "Call number ID: ", call_num.id()
+    print "Call number label: ", call_num.label()
+
+    # Change the call number and update it
+    call_num.label('FOOTWICH')
+    call_num.ischanged(True)
+
+    # volume.fleshed.batch.update expects an array of call number objects 
+    acn = [call_num]
+
+    req = request('open-ils.cat', 'open-ils.cat.asset.volume.fleshed.batch.update', authtoken, acn, False, None)
+    result = req.send()



More information about the open-ils-commits mailing list