From: erickson Date: Fri, 4 Jan 2008 20:47:31 +0000 (+0000) Subject: syncing to trunk X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=18e1bcb1905b380e51a8d30ddefee0f5b5938375;p=Evergreen.git syncing to trunk git-svn-id: svn://svn.open-ils.org/ILS/branches/acq-experiment@8317 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- diff --git a/Open-ILS/src/python/oils/utils/csedit.py b/Open-ILS/src/python/oils/utils/csedit.py index 0270a342ee..74c1121cbe 100644 --- a/Open-ILS/src/python/oils/utils/csedit.py +++ b/Open-ILS/src/python/oils/utils/csedit.py @@ -23,7 +23,69 @@ import re ACTIONS = ['create', 'retrieve', 'batch_retrieve', 'update', 'delete', 'search'] class CSEditor(object): + """ + Contains generated methods for accessing fieldmapper objects using the + following syntax: + + = .__() + + * = CSEditor class instance + * = + * create + = object to create + = the numeric ID of the newly created object + * retrieve + = numeric ID of the object to retrieve + = object, instance of osrf.net_obj.NetworkObject + * batch_retrieve + = list of numeric ID's + = list of objects, instances of osrf.net_obj.NetworkObject + * update + = object to update + = 1 on success + * delete + = object to delete + = 1 on sucess + * search + = a cstore-compatible search dict. e.g. {"id":1}. + See cstore docs for the full range of search options. + = a list of search results. For standard searches, this + will be a list of objects. idlist searches will return + a list of ID's. + * = the name of the schema that contains the 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')) @@ -33,8 +95,15 @@ class CSEditor(object): 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 @@ class CSEditor(object): # 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 @@ class CSEditor(object): 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 @@ class CSEditor(object): 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 @@ def oilsLoadCSEditor(): 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 diff --git a/Open-ILS/src/python/oils/utils/idl.py b/Open-ILS/src/python/oils/utils/idl.py index b8fdc2e4a3..0a4428a76a 100644 --- a/Open-ILS/src/python/oils/utils/idl.py +++ b/Open-ILS/src/python/oils/utils/idl.py @@ -9,12 +9,11 @@ Typical usage: >>> 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 @@ class oilsIDLParser(object): # 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 - - 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 - - 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) - - if virtual == string.lower('true'): - obj['virtual'] = True - else: - obj['virtual'] = False - - idlobj['fields'].append(obj) + for field in [l for l in fields.childNodes if l.nodeName == 'field']: + + 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) + ) + + 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 + + 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') + -