adding oils libs
authorerickson <erickson@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Fri, 5 Jan 2007 19:16:20 +0000 (19:16 +0000)
committererickson <erickson@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Fri, 5 Jan 2007 19:16:20 +0000 (19:16 +0000)
git-svn-id: svn://svn.open-ils.org/ILS/trunk@6725 dcc99617-32d9-48b4-a31d-7c20da2025e4

Open-ILS/src/python/oils/__init__.py [new file with mode: 0644]
Open-ILS/src/python/oils/const.py [new file with mode: 0644]
Open-ILS/src/python/oils/system.py [new file with mode: 0644]
Open-ILS/src/python/oils/utils/__init__.py [new file with mode: 0644]
Open-ILS/src/python/oils/utils/csedit.py [new file with mode: 0644]
Open-ILS/src/python/oils/utils/idl.py [new file with mode: 0644]
Open-ILS/src/python/oils/utils/utils.py [new file with mode: 0644]

diff --git a/Open-ILS/src/python/oils/__init__.py b/Open-ILS/src/python/oils/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/Open-ILS/src/python/oils/const.py b/Open-ILS/src/python/oils/const.py
new file mode 100644 (file)
index 0000000..52ee81f
--- /dev/null
@@ -0,0 +1,22 @@
+# -----------------------------------------------------------------------
+# Copyright (C) 2007  Georgia Public Library Service
+# Bill Erickson <billserickson@gmail.com>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# -----------------------------------------------------------------------
+
+
+OILS_NS_OBJ='http://open-ils.org/spec/opensrf/IDL/objects/v1'
+OILS_NS_PERSIST='http://open-ils.org/spec/opensrf/IDL/persistance/v1'
+OILS_NS_REPORTER='http://open-ils.org/spec/opensrf/IDL/reporter/v1'
+
+OILS_APP_CSTORE='open-ils.cstore'
+
diff --git a/Open-ILS/src/python/oils/system.py b/Open-ILS/src/python/oils/system.py
new file mode 100644 (file)
index 0000000..b010db2
--- /dev/null
@@ -0,0 +1,26 @@
+# -----------------------------------------------------------------------
+# Copyright (C) 2007  Georgia Public Library Service
+# Bill Erickson <billserickson@gmail.com>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# -----------------------------------------------------------------------
+
+from osrf.log import *
+from osrf.system import osrfConnect
+from oils.utils.idl import oilsParseIDL
+from oils.utils.csedit import oilsLoadCSEditor
+
+def oilsConnect(config):
+       """Connects to the opensrf network,  parses the IDL file, and loads the CSEditor"""
+       osrfLogInfo("oilsConnect(): connecting with config %s" % config)
+       osrfConnect(config)
+       oilsParseIDL()
+       oilsLoadCSEditor()
diff --git a/Open-ILS/src/python/oils/utils/__init__.py b/Open-ILS/src/python/oils/utils/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/Open-ILS/src/python/oils/utils/csedit.py b/Open-ILS/src/python/oils/utils/csedit.py
new file mode 100644 (file)
index 0000000..8054196
--- /dev/null
@@ -0,0 +1,175 @@
+# -----------------------------------------------------------------------
+# Copyright (C) 2007  Georgia Public Library Service
+# Bill Erickson <billserickson@gmail.com>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# -----------------------------------------------------------------------
+
+from osrf.log import *
+from osrf.json import *
+from oils.utils.utils import replace
+from oils.utils.idl import oilsGetIDLParser
+from osrf.ses import osrfClientSession
+from oils.const import *
+import re
+
+ACTIONS = ['create', 'retrieve', 'update', 'delete', 'search']
+
+class CSEditor(object):
+   def __init__(self, **args):
+
+      self.app = args.get('app', OILS_APP_CSTORE)
+      self.authtoken = args.get('authtoken', args.get('auth'))
+      self.requestor = args.get('requestor')
+      self.connect = args.get('connect')
+      self.xact = args.get('xact')
+      self.__session = None
+
+   def die_event(self):
+      pass
+   def checkauth(self):
+      pass
+
+
+   # -------------------------------------------------------------------------
+   # Creates a session if one does not already exist.  If necessary, connects
+   # to the remote service and starts a transaction
+   # -------------------------------------------------------------------------
+   def session(self, ses=None):
+      if not self.__session:
+         self.__session = osrfClientSession(self.app)
+
+         if self.connect or self.xact:
+            self.log(osrfLogDebug,'connecting to ' + self.app)
+            self.__session.connect() 
+
+         if self.xact:
+            self.log(osrfLogInfo, "starting new db transaction")
+            self.request(self.app + '.transaction.begin')
+
+      return self.__session
+   
+
+   # -------------------------------------------------------------------------
+   # Logs string with some meta info
+   # -------------------------------------------------------------------------
+   def log(self, func, string):
+      s = "editor[";
+      if self.xact: s += "1|"
+      else: s += "0|"
+      if self.requestor: s += str(self.requestor.id())
+      else: s += "0"
+      s += "]"
+      func("%s %s" % (s, string))
+
+
+   # -------------------------------------------------------------------------
+   # Rolls back the existing db transaction
+   # -------------------------------------------------------------------------
+   def rollback(self):
+      if self.__session and self.xact:
+         self.log(osrfLogInfo, "rolling back db transaction")
+         self.request(self.app + '.transaction.rollback')
+         self.disconnect()
+         
+   # -------------------------------------------------------------------------
+   # Commits the existing db transaction
+   # -------------------------------------------------------------------------
+   def commit(self):
+      if self.__session and self.xact:
+         self.log(osrfLogInfo, "comitting db transaction")
+         self.request(self.app + '.transaction.commit')
+         self.disconnect()
+
+
+   # -------------------------------------------------------------------------
+   # Disconnects from the remote service
+   # -------------------------------------------------------------------------
+   def disconnect(self):
+      if self.__session:
+         self.__session.disconnect()
+         self.__session = None
+
+
+   # -------------------------------------------------------------------------
+   # Sends a request
+   # -------------------------------------------------------------------------
+   def request(self, method, params=[]):
+
+      # XXX improve param logging here
+
+      self.log(osrfLogInfo, "request %s %s" % (method, str(params)))
+
+      if self.xact and self.session().state != OSRF_APP_SESSION_CONNECTED:
+         self.log(osrfLogErr, "csedit lost it's connection!")
+
+      val = None
+
+      try:
+         req = self.session().request2(method, params)
+         resp = req.recv()
+         val = resp.content()
+
+      except Exception, e:
+         self.log(osrfLogErr, "request error: %s" % str(e))
+         raise e
+
+      return val
+
+
+   # -------------------------------------------------------------------------
+   # Returns true if our requestor is allowed to perform the request action
+   # 'org' defaults to the requestors ws_ou
+   # -------------------------------------------------------------------------
+   def allowed(self, perm, org=None):
+      pass
+
+
+   def runMethod(self, action, type, arg, options={}):
+
+      method = "%s.direct.%s.%s" % (self.app, type, action)
+
+      if options.get('idlist'):
+         method = replace(method, 'search', 'id_list')
+         del options['idlist']
+
+      if action == 'search':
+         method = replace(method, '$', '.atomic')
+
+      params = [arg];
+      if len(options.keys()):
+         params.append(options)
+
+      val = self.request( method, params )
+
+      return val
+
+
+
+# -------------------------------------------------------------------------
+# Creates a class method for each action on each type of fieldmapper object
+# -------------------------------------------------------------------------
+def oilsLoadCSEditor():
+   obj = oilsGetIDLParser().IDLObject
+
+   for k, fm in obj.iteritems():
+      for action in ACTIONS:
+
+         fmname = replace(fm['fieldmapper'], '::', '_')
+         type = replace(fm['fieldmapper'], '::', '.')
+         name = "%s_%s" % (action, fmname)
+
+         str = 'def %s(self, arg, **options):\n' % name
+         str += '\treturn self.runMethod("%s", "%s", arg, dict(options))\n' % (action, type)
+         str += 'setattr(CSEditor, "%s", %s)' % (name, name)
+
+         exec(str)
+
diff --git a/Open-ILS/src/python/oils/utils/idl.py b/Open-ILS/src/python/oils/utils/idl.py
new file mode 100644 (file)
index 0000000..7a7fa1e
--- /dev/null
@@ -0,0 +1,133 @@
+# -----------------------------------------------------------------------
+# Copyright (C) 2007  Georgia Public Library Service
+# Bill Erickson <billserickson@gmail.com>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# -----------------------------------------------------------------------
+
+from osrf.json import *
+from osrf.log import *
+from osrf.set import osrfSettingsValue
+
+import sys, libxml2, osrf.conf, string
+from oils.const import OILS_NS_OBJ, OILS_NS_PERSIST, OILS_NS_REPORTER
+
+__global_parser = None
+
+def oilsParseIDL():
+       global __global_parser
+       idlParser = oilsIDLParser();
+       idlParser.setIDL(osrfSettingsValue('IDL'))
+       idlParser.parseIDL()
+       __global_parser = idlParser
+
+def oilsGetIDLParser():
+       global __global_parser
+       return __global_parser
+
+class oilsIDLParser(object):
+
+       def __init__(self):
+               self.IDLObject = {}
+
+       def setIDL(self, file):
+               osrfLogInfo("setting IDL file to " + file)
+               self.idlFile = file
+
+       def parseIDL(self):
+               """Parses the IDL file and builds class objects"""
+
+               doc     = libxml2.parseFile(self.idlFile)
+               root    = doc.children
+               child = root.children
+
+               while child:
+               
+                       if child.type == 'element':
+               
+                               # -----------------------------------------------------------------------
+                               # 'child' is the main class node for a fieldmapper class.
+                               # It has 'fields' and 'links' nodes as children.
+                               # -----------------------------------------------------------------------
+
+                               id = child.prop('id')
+                               self.IDLObject[id] = {}
+                               obj = self.IDLObject[id]
+                               obj['fields'] = []
+
+                               obj['controller'] = child.prop('controller')
+                               obj['fieldmapper'] = child.nsProp('fieldmapper', OILS_NS_OBJ)
+                               obj['virtual'] = child.nsProp('virtual', OILS_NS_PERSIST)
+                               obj['rpt_label'] = child.nsProp('label', OILS_NS_REPORTER)
+
+                               class_node = child.children
+                               #osrfLogInternal("parseIDL(): parsing class %s" % id)
+               
+                               keys = []
+                               while class_node:
+                                       if class_node.type == 'element':
+                                               if class_node.name == 'fields':
+                                                       keys = self.parseFields(id, class_node)
+                                       class_node = class_node.next
+
+                               #obj['fields'] = keys
+                               osrfNetworkRegisterHint(id, keys, 'array' )
+
+                       child = child.next
+
+               doc.freeDoc()
+
+
+       def parseFields(self, cls, fields):
+               """Takes the fields node and parses the included field elements"""
+
+               field = fields.children
+               keys = []
+               idlobj = self.IDLObject[cls]
+
+               while field:
+                       if field.type == 'element':
+                               keys.append(None)
+                       field = field.next
+               
+               field = fields.children
+               while field:
+                       obj = {}
+                       if field.type == 'element':
+                               name                    = field.prop('name')
+                               position                = int(field.nsProp('array_position', OILS_NS_OBJ))
+                               obj['name'] = name
+
+                               try:
+                                       keys[position] = name
+                               except Exception, e:
+                                       osrfLogErr("parseFields(): position out of range.  pos=%d : key-size=%d" % (position, len(keys)))
+                                       raise e
+
+                               virtual = field.nsProp('virtual', OILS_NS_PERSIST)
+                               obj['rpt_label']        = field.nsProp('label', OILS_NS_REPORTER)
+                               obj['rpt_dtype']        = field.nsProp('datatype', OILS_NS_REPORTER)
+                               obj['rpt_select']       = field.nsProp('selector', OILS_NS_REPORTER)
+
+                               if virtual == string.lower('true'):
+                                       obj['virtual']  = True
+                               else:
+                                       obj['virtual']  = False
+
+                               idlobj['fields'].append(obj)
+
+                       field = field.next
+
+               return keys
+
+
+
+       
diff --git a/Open-ILS/src/python/oils/utils/utils.py b/Open-ILS/src/python/oils/utils/utils.py
new file mode 100644 (file)
index 0000000..9e03cb9
--- /dev/null
@@ -0,0 +1,32 @@
+# -----------------------------------------------------------------------
+# Copyright (C) 2007  Georgia Public Library Service
+# Bill Erickson <billserickson@gmail.com>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# -----------------------------------------------------------------------
+
+import re
+
+# -----------------------------------------------------------------------
+# Grab-bag of general utility functions
+# -----------------------------------------------------------------------
+
+
+# -----------------------------------------------------------------------
+# more succinct search/replace call
+# -----------------------------------------------------------------------
+def replace(str, pattern, replace):
+   return re.compile(pattern).sub(replace, str)
+
+
+
+      
+