[open-ils-commits] r8317 - branches/acq-experiment/Open-ILS/src/python/oils/utils

svn at svn.open-ils.org svn at svn.open-ils.org
Fri Jan 4 16:11:25 EST 2008


Author: erickson
Date: 2008-01-04 15:47:31 -0500 (Fri, 04 Jan 2008)
New Revision: 8317

Modified:
   branches/acq-experiment/Open-ILS/src/python/oils/utils/csedit.py
   branches/acq-experiment/Open-ILS/src/python/oils/utils/idl.py
Log:
syncing to trunk

Modified: branches/acq-experiment/Open-ILS/src/python/oils/utils/csedit.py
===================================================================
--- branches/acq-experiment/Open-ILS/src/python/oils/utils/csedit.py	2008-01-04 20:35:44 UTC (rev 8316)
+++ branches/acq-experiment/Open-ILS/src/python/oils/utils/csedit.py	2008-01-04 20:47:31 UTC (rev 8317)
@@ -23,8 +23,70 @@
 ACTIONS = ['create', 'retrieve', 'batch_retrieve', 'update', 'delete', 'search']
 
 class CSEditor(object):
+    """
+    Contains generated methods for accessing fieldmapper objects using the
+    following syntax:
+    
+        <ret> = <instance>.<action>_<schema>_<table>(<args>)
+
+      * <instance> = CSEditor class instance
+      * <action>   = 
+        * create 
+          <args>   = object to create
+          <ret>    = the numeric ID of the newly created object
+        * retrieve 
+          <args>   = numeric ID of the object to retrieve 
+          <ret>    = object, instance of osrf.net_obj.NetworkObject
+        * batch_retrieve
+          <args>   = list of numeric ID's
+          <ret>    = list of objects, instances of osrf.net_obj.NetworkObject
+        * update
+          <args>   = object to update
+          <ret>    = 1 on success
+        * delete
+          <args>   = object to delete
+          <ret>    = 1 on sucess
+        * search
+          <args>   = a cstore-compatible search dict.  e.g. {"id":1}.  
+            See cstore docs for the full range of search options.
+          <ret>    = a list of search results.  For standard searches, this
+                   will be a list of objects.  idlist searches will return
+                   a list of ID's.
+      * <schema>   = the name of the schema that contains the table
+      * <table>    = the name of the table
+
+    Each generated object has accessor methods corresponding to the fieldmapper
+    name attributes for a given field. The following example demonstrates how to
+    instantiate the CSEditor and a given table object, and how to invoke an
+    accessor method on that table object:
+
+    >>> import oils.utils.csedit
+    >>> import oils.utils.idl
+    >>> import osrf.system
+    >>> osrf.system.connect('/openils/conf/opensrf_core.xml', 'config.opensrf')
+    >>> oils.utils.idl.oilsParseIDL()
+    >>> oils.utils.csedit.oilsLoadCSEditor()
+    >>> editor = oils.utils.csedit.CSEditor()
+    >>> rec = editor.retrieve_biblio_record_entry(-1)
+    >>> print rec.tcn_value()
+    """
+
     def __init__(self, **args):
+        ''' 
+            Creates a new editor object.
 
+            Support keyword arguments:
+            authtoken - Authtoken string -- used to determine 
+                the requestor if none is provided.
+            requestor - existing user (au) object.  The requestor is 
+                is the user performing the action.  This is important 
+                for permission checks, logging, etc.
+            connect - boolean.  If true, a connect call is sent to the opensrf
+                service at session create time
+            xact - boolean.  If true, a cstore transaction is created at 
+                connect time.  xact implies connect.
+        '''
+
         self.app = args.get('app', OILS_APP_CSTORE)
         self.authtoken = args.get('authtoken', args.get('auth'))
         self.requestor = args.get('requestor')
@@ -33,8 +95,15 @@
         self.__session = None
 
     def die_event(self):
+        ''' Rolls back the existing transaction, disconnects our session, 
+            and returns the last received event.
+        '''
         pass
+
     def checkauth(self):
+        ''' Checks the authtoken against open-ils.auth and uses the 
+            retrieved user as the requestor
+        '''
         pass
 
 
@@ -43,6 +112,9 @@
     # to the remote service and starts a transaction
     # -------------------------------------------------------------------------
     def session(self, ses=None):
+        ''' Creates a session if one does not already exist.  If necessary, connects
+            to the remote service and starts a transaction
+        '''
         if not self.__session:
             self.__session = ClientSession(self.app)
 
@@ -57,10 +129,9 @@
         return self.__session
    
 
-    # -------------------------------------------------------------------------
-    # Logs string with some meta info
-    # -------------------------------------------------------------------------
     def log(self, func, string):
+        ''' Logs string with some meta info '''
+
         s = "editor[";
         if self.xact: s += "1|"
         else: s += "0|"
@@ -70,29 +141,25 @@
         func("%s %s" % (s, string))
 
 
-    # -------------------------------------------------------------------------
-    # Rolls back the existing db transaction
-    # -------------------------------------------------------------------------
     def rollback(self):
+        ''' Rolls back the existing db transaction '''
+
         if self.__session and self.xact:
              self.log(log_info, "rolling back db transaction")
              self.request(self.app + '.transaction.rollback')
              self.disconnect()
              
-    # -------------------------------------------------------------------------
-    # Commits the existing db transaction
-    # -------------------------------------------------------------------------
     def commit(self):
+        ''' Commits the existing db transaction and disconnects '''
+
         if self.__session and self.xact:
             self.log(log_info, "comitting db transaction")
             self.request(self.app + '.transaction.commit')
             self.disconnect()
 
 
-    # -------------------------------------------------------------------------
-    # Disconnects from the remote service
-    # -------------------------------------------------------------------------
     def disconnect(self):
+        ''' Disconnects from the remote service '''
         if self.__session:
             self.__session.disconnect()
             self.__session = None
@@ -187,8 +254,8 @@
     for k, fm in obj.iteritems():
         for action in ACTIONS:
 
-            fmname = fm['fieldmapper'].replace('::', '_')
-            type = fm['fieldmapper'].replace('::', '.')
+            fmname = fm.fieldmapper.replace('::', '_')
+            type = fm.fieldmapper.replace('::', '.')
             name = "%s_%s" % (action, fmname)
 
             s = 'def %s(self, arg, **options):\n' % name

Modified: branches/acq-experiment/Open-ILS/src/python/oils/utils/idl.py
===================================================================
--- branches/acq-experiment/Open-ILS/src/python/oils/utils/idl.py	2008-01-04 20:35:44 UTC (rev 8316)
+++ branches/acq-experiment/Open-ILS/src/python/oils/utils/idl.py	2008-01-04 20:47:31 UTC (rev 8317)
@@ -9,12 +9,11 @@
 >>> osrf.system.connect('/openils/conf/opensrf_core.xml', 'config.opensrf')
 >>> oils.utils.idl.oilsParseIDL()
 >>> # 'bre' is a network registry hint, or class ID in the IDL file
-... print oils.utils.idl.oilsGetIDLParser().IDLObject['bre']['tablename']
+... print oils.utils.idl.oilsGetIDLParser().IDLObject['bre'].tablename
 biblio.record_entry
 """
 import osrf.net_obj
-import osrf.log
-import osrf.set
+import osrf.log, osrf.set, osrf.ex
 
 import sys, string, xml.dom.minidom
 from oils.const import OILS_NS_OBJ, OILS_NS_PERSIST, OILS_NS_REPORTER
@@ -67,71 +66,135 @@
                 # It has 'fields' and 'links' nodes as children.
                 # -----------------------------------------------------------------------
 
-                id = self.__getAttr(child, 'id')
-                self.IDLObject[id] = {}
-                obj = self.IDLObject[id]
-                obj['fields'] = []
+                obj = IDLClass(
+                    self.__getAttr(child, 'id'),
+                    controller = self.__getAttr(child, 'controller'),
+                    fieldmapper = self.__getAttr(child, 'oils_obj:fieldmapper', OILS_NS_OBJ),
+                    virtual = self.__getAttr(child, 'oils_persist:virtual', OILS_NS_PERSIST),
+                    label = self.__getAttr(child, 'reporter:label', OILS_NS_REPORTER),
+                    tablename = self.__getAttr(child, 'oils_persist:tablename', OILS_NS_REPORTER),
+                )
 
-                obj['controller'] = self.__getAttr(child, 'controller')
-                obj['fieldmapper'] = self.__getAttr(child, 'oils_obj:fieldmapper', OILS_NS_OBJ)
-                obj['virtual'] = self.__getAttr(child, 'oils_persist:virtual', OILS_NS_PERSIST)
-                obj['rpt_label'] = self.__getAttr(child, 'reporter:label', OILS_NS_REPORTER)
-                obj['tablename'] = self.__getAttr(child, 'oils_persist:tablename', OILS_NS_REPORTER)
 
-                keys = []
-                for classNode in child.childNodes:
-                    if classNode.nodeType == classNode.ELEMENT_NODE:
-                        if classNode.nodeName == 'fields':
-                            keys = self.parseFields(id, classNode)
+                self.IDLObject[obj.name] = obj
 
-                osrf.net_obj.register_hint(id, keys, 'array')
+                fields = [f for f in child.childNodes if f.nodeName == 'fields']
+                links = [f for f in child.childNodes if f.nodeName == 'links']
+                keys = self.parseFields(obj, fields[0])
+                if len(links) > 0:
+                    self.parse_links(obj, links[0])
 
+                osrf.net_obj.register_hint(obj.name, keys, 'array')
+
         doc.unlink()
 
 
-    def parseFields(self, cls, fields):
+    def parse_links(self, idlobj, links):
+
+        for link in [l for l in links.childNodes if l.nodeName == 'link']:
+            obj = IDLLink(
+                field = idlobj.get_field(self.__getAttr(link, 'field')),
+                rel_type = self.__getAttr(link, 'rel_type'),
+                key = self.__getAttr(link, 'key'),
+                map = self.__getAttr(link, 'map')
+            )
+            idlobj.links.append(obj)
+
+
+    def parseFields(self, idlobj, fields):
         """Takes the fields node and parses the included field elements"""
 
         keys = []
-        idlobj = self.IDLObject[cls]
 
-        idlobj['field_meta'] = {
-            'primary': self.__getAttr(fields, 'oils_persist:primary', OILS_NS_PERSIST),
-            'sequence': self.__getAttr(fields, 'oils_persist:sequence', OILS_NS_PERSIST)
-        }
+        idlobj.primary = self.__getAttr(fields, 'oils_persist:primary', OILS_NS_PERSIST)
+        idlobj.sequence =  self.__getAttr(fields, 'oils_persist:sequence', OILS_NS_PERSIST)
 
+        # pre-flesh the array of keys to accomodate random index insertions
         for field in fields.childNodes:
             if field.nodeType == field.ELEMENT_NODE:
                 keys.append(None)
         
-        for field in fields.childNodes:
-            obj = {}
-            if field.nodeType == fields.ELEMENT_NODE:
-                name            = self.__getAttr(field, 'name')
-                position        = int(self.__getAttr(field, 'oils_obj:array_position', OILS_NS_OBJ))
-                obj['name'] = name
+        for field in [l for l in fields.childNodes if l.nodeName == 'field']:
 
-                try:
-                    keys[position] = name
-                except Exception, e:
-                    osrf.log.log_error("parseFields(): position out of range.  pos=%d : key-size=%d" % (position, len(keys)))
-                    raise e
+            obj = IDLField(
+                idlobj,
+                name = self.__getAttr(field, 'name'),
+                position = int(self.__getAttr(field, 'oils_obj:array_position', OILS_NS_OBJ)),
+                virtual = self.__getAttr(field, 'oils_persist:virtual', OILS_NS_PERSIST),
+                label = self.__getAttr(field, 'reporter:label', OILS_NS_REPORTER),
+                rpt_datatype = self.__getAttr(field, 'reporter:datatype', OILS_NS_REPORTER),
+                rpt_select = self.__getAttr(field, 'reporter:selector', OILS_NS_REPORTER),
+                primitive = self.__getAttr(field, 'oils_persist:primitive', OILS_NS_PERSIST)
+            )
 
-                virtual = self.__getAttr(field, 'oils_persist:virtual', OILS_NS_PERSIST)
-                obj['rpt_label'] = self.__getAttr(field, 'reporter:label', OILS_NS_REPORTER)
-                obj['rpt_dtype'] = self.__getAttr(field, 'reporter:datatype', OILS_NS_REPORTER)
-                obj['rpt_select'] = self.__getAttr(field, 'reporter:selector', OILS_NS_REPORTER)
-                obj['primitive'] = self.__getAttr(field, 'oils_persist:primitive', OILS_NS_PERSIST)
+            try:
+                keys[obj.position] = obj.name
+            except Exception, e:
+                osrf.log.log_error("parseFields(): position out of range.  pos=%d : key-size=%d" % (obj.position, len(keys)))
+                raise e
 
-                if virtual == string.lower('true'):
-                    obj['virtual']  = True
-                else:
-                    obj['virtual']  = False
+            idlobj.fields.append(obj)
 
-                idlobj['fields'].append(obj)
-
         return keys
 
 
+class IDLException(osrf.ex.OSRFException):
+    pass
 
-    
+class IDLClass(object):
+    def __init__(self, name, **kwargs):
+        self.name = name
+        self.controller = kwargs.get('controller')
+        self.fieldmapper = kwargs.get('fieldmapper')
+        self.virtual = kwargs.get('virtual')
+        self.label = kwargs.get('label')
+        self.tablename = kwargs.get('tablename')
+        self.primary = kwargs.get('primary')
+        self.sequence = kwargs.get('sequence')
+        self.fields = []
+        self.links = []
+
+        if self.virtual and self.virtual.lower() == 'true':
+            self.virtul = True
+        else:
+            self.virtual = False
+
+    def get_field(self, field_name):
+        try:
+            return [f for f in self.fields if f.name == field_name][0]
+        except:
+            msg = "No field '%s' in IDL class '%s'" % (field_name, self.name)
+            #osrf.log.log_error(msg)
+            raise IDLException(msg)
+
+class IDLField(object):
+    def __init__(self, idl_class, **kwargs):
+        '''
+            @param idl_class The IDLClass object which owns this field
+        '''
+        self.idl_class = idl_class
+        self.name = kwargs.get('name')
+        self.label = kwargs.get('label')
+        self.rpt_datatype = kwargs.get('rpt_datatype')
+        self.rpt_select = kwargs.get('rpt_select')
+        self.primitive = kwargs.get('primitive')
+        self.virtual = kwargs.get('virtual')
+        self.position = kwargs.get('position')
+
+        if self.virtual and self.virtual.lower() == 'true':
+            self.virtul = True
+        else:
+            self.virtual = False
+
+
+class IDLLink(object):
+    def __init__(self, field, **kwargs):
+        '''
+            @param field The IDLField object this link references
+        '''
+        self.field = field
+        self.rel_type = kwargs.get('rel_type')
+        self.key = kwargs.get('key')
+        self.map = kwargs.get('map')
+
+



More information about the open-ils-commits mailing list