def getApplicableEventsTypesAt(self, obj, date, allEventTypes, preComputed, forBrowser=False): '''Returns the event types that are applicable at a given p_date. More precisely, it returns an object with 2 attributes: * "events" is the list of applicable event types; * "message", not empty if some event types are not applicable, contains a message explaining those event types are not applicable. ''' if not self.applicableEvents: eventTypes = allEventTypes message = None else: eventTypes = allEventTypes[:] message = self.applicableEvents(obj.appy(), date, eventTypes, preComputed) res = Object(eventTypes=eventTypes, message=message) if forBrowser: res.eventTypes = ','.join(res.eventTypes) if not res.message: res.message = '' else: res.message = obj.formatText(res.message, format='js') return res.__dict__ return res
def initialiseLoop(self, context, elems): '''Initialises information about the loop, before entering into it.''' # The "loop" object, made available in the POD context, contains info # about all currently walked loops. For every walked loop, a specific # object, le'ts name it curLoop, accessible at getattr(loop, self.iter), # stores info about its status: # * curLoop.length gives the total number of walked elements withhin # the loop # * curLoop.nb gives the index (starting at 0) if the currently # walked element. # * curLoop.first is True if the currently walked element is the # first one. # * curLoop.last is True if the currently walked element is the # last one. # * curLoop.odd is True if the currently walked element is odd # * curLoop.even is True if the currently walked element is even # For example, if you have a "for" statement like this: # for elem in myListOfElements # Within the part of the ODT document impacted by this statement, you # may access to: # * loop.elem.length to know the total length of myListOfElements # * loop.elem.nb to know the index of the current elem within # myListOfElements. if 'loop' not in context: context['loop'] = Object() try: total = len(elems) except: total = 0 curLoop = Object(length=total) setattr(context['loop'], self.iter, curLoop) return curLoop
def getApplicableEventsTypesAt(self, obj, date, allEventTypes, preComputed, forBrowser=False): '''Returns the event types that are applicable at a given p_date. More precisely, it returns an object with 2 attributes: * "events" is the list of applicable event types; * "message", not empty if some event types are not applicable, contains a message explaining those event types are not applicable. ''' if not self.applicableEvents: eventTypes = allEventTypes message = None else: eventTypes = allEventTypes[:] message = self.applicableEvents(obj.appy(), date, eventTypes, preComputed) res = Object(eventTypes=eventTypes, message=message) if forBrowser: res.eventTypes = ','.join(res.eventTypes) if not res.message: res.message = '' return res
def getRequestValue(self, request, requestName=None): '''Concatenates the list from distinct form elements in the request.''' name = requestName or self.name # A List may be into another List (?) prefix = name + '*' + self.fields[0][0] + '*' res = {} for key in request.keys(): if not key.startswith(prefix): continue # I have found a row. Gets its index row = Object() if '_' in key: key = key[:key.index('_')] rowIndex = int(key.split('*')[-1]) if rowIndex == -1: continue # Ignore the template row. for subName, subField in self.fields: keyName = '%s*%s*%s' % (name, subName, rowIndex) v = subField.getRequestValue(request, requestName=keyName) setattr(row, subName, v) res[rowIndex] = row # Produce a sorted list. keys = res.keys() keys.sort() res = [res[key] for key in keys] # I store in the request this computed value. This way, when individual # subFields will need to get their value, they will take it from here, # instead of taking it from the specific request key. Indeed, specific # request keys contain row indexes that may be wrong after row deletions # by the user. request.set(name, res) return res
def getCustomContext(self, obj, rq): '''Before calling pod to compute a result, if specific elements must be added to the context, compute it here. This request-dependent method is not called when computing a pod field for freezing it into the database.''' res = {} # Get potential custom params from the request. Custom params must be # coded as a string containing a valid Python dict. customParams = rq.get('customParams') if customParams: paramsDict = eval(customParams) res.update(paramsDict) # Compute the selected linked objects if self.getChecked is specified # and if the user can read this Ref field. if self.getChecked and \ obj.allows(obj.getField(self.getChecked).readPermission): # Get the UIDs specified in the request reqUids = rq['checkedUids'] and rq['checkedUids'].split(',') or [] unchecked = rq['checkedSem'] == 'unchecked' objects = [] tool = obj.tool for uid in getattr(obj.o.aq_base, self.getChecked, ()): if unchecked: condition = uid not in reqUids else: condition = uid in reqUids if condition: tied = tool.getObject(uid) if tied.allows('read'): objects.append(tied) res['_checked'] = Object() setattr(res['_checked'], self.getChecked, objects) return res
def getInfo(self, obj, layoutType): '''Gets information about this page, for p_obj, as an object.''' res = Object() for elem in Page.subElements: showable = self.isShowable(obj, layoutType, elem) setattr(res, 'show%s' % elem.capitalize(), showable) return res
def addPageLinks(self, field, obj): '''If p_field is a navigable Ref, we must add, within self.pagesInfo, objects linked to p_obj through this Ref as links.''' if field.page.name in self.hiddenPages: return infos = [] for ztied in field.getValue(obj, appy=False): infos.append(Object(title=ztied.title, url=ztied.absolute_url())) self.pagesInfo[field.page.name].links = infos
def addPage(self, field, obj, layoutType): '''Adds page-related information in the phase.''' # If the page is already there, we have nothing more to do. if (field.page.name in self.pages) or \ (field.page.name in self.hiddenPages): return # Add the page only if it must be shown. showOnView = field.page.isShowable(obj, 'view') showOnEdit = field.page.isShowable(obj, 'edit') if showOnView or showOnEdit: # The page must be added self.pages.append(field.page.name) # Create the dict about page information and add it in self.pageInfo pageInfo = Object(page=field.page, showOnView=showOnView, showOnEdit=showOnEdit, links=None) pageInfo.update(field.page.getInfo(obj, layoutType)) self.pagesInfo[field.page.name] = pageInfo else: self.hiddenPages.append(field.page.name)
def encode(self): # Do nothing if we have a SOAP message already if isinstance(self.data, basestring): return self.data # self.data is here a Python object. Wrap it in a SOAP Body. soap = Object(Body=self.data) # Marshall it. marshaller = XmlMarshaller(rootTag='Envelope', namespaces=self.ns, namespacedTags=self.namespacedTags) return marshaller.marshall(soap)
def getStorableValue(self, value): '''Gets p_value in a form that can be stored in the database.''' res = [] for v in value: sv = Object() for name, field in self.fields: setattr(sv, name, field.getStorableValue(getattr(v, name))) res.append(sv) return res
def getVisibleTemplates(self, obj): '''Returns, among self.template, the template(s) that can be shown.''' res = [] if not self.showTemplate: # Show them all in any format. for template in self.template: res.append(Object(template=template, formats=self.getAllFormats(template), freezeFormats=self.getFreezeFormats(obj, template))) else: isManager = obj.user.has_role('Manager') for template in self.template: formats = self.showTemplate(obj, template) if not formats: continue formats = isManager and self.getAllFormats(template) or formats if isinstance(formats, basestring): formats = (formats,) res.append(Object(template=template, formats=formats, freezeFormats=self.getFreezeFormats(obj, template))) return res
def getOtherEventsAt(self, obj, date, otherCalendars): '''Gets events that are defined in p_otherCalendars at some p_date.''' res = [] for o, field, color in otherCalendars: events = field.getEventsAt(o.o, date) if events: eventType = events[0].eventType eventName = field.getEventName(o.o, eventType) info = Object(name=eventName, color=color) res.append(info) return res
def startElement(self, elem, attrs): # Remember the name of the previous element previousElem = None if self.env.currentElem: previousElem = self.env.currentElem.name e = XmlParser.startElement(self, elem, attrs) # Determine the type of the element. elemType = 'unicode' # Default value if attrs.has_key('type'): elemType = attrs['type'] elif self.tagTypes.has_key(elem): elemType = self.tagTypes[elem] if elemType in self.containerTags: # I must create a new container object. if elemType == 'object': newObject = Object(**self.convertAttrs(attrs)) elif elemType == 'tuple': newObject = [] # Tuples become lists elif elemType == 'list': newObject = [] elif elemType == 'dict': newObject = {} elif elemType == 'file': newObject = UnmarshalledFile() if attrs.has_key('name'): newObject.name = attrs['name'] if attrs.has_key('mimeType'): newObject.mimeType = attrs['mimeType'] else: newObject = Object(**self.convertAttrs(attrs)) # Store the value on the last container, or on the root object. self.storeValue(elem, newObject) # Push the new object on the container stack e.containerStack.append(newObject) else: # If we are already parsing a basic type, it means that we were # wrong for our diagnotsic of the containing element: it was not # basic. We will make the assumption that the containing element is # then an object. if e.currentBasicType: # Previous elem was an object: create it on the stack. newObject = Object() self.storeValue(previousElem, newObject) e.containerStack.append(newObject) e.currentBasicType = elemType
def createEvent(self, obj, date, eventType=None, eventSpan=None, handleEventSpan=True): '''Create a new event in the calendar, at some p_date (day). If p_eventType is given, it is used; else, rq['eventType'] is used. If p_handleEventSpan is True, we will use p_eventSpan (or rq["eventSpan"] if p_eventSpan is not given) and also create the same event for successive days.''' obj = obj.o # Ensure p_obj is not a wrapper. rq = obj.REQUEST # Get values from parameters if not eventType: eventType = rq['eventType'] if handleEventSpan and not eventSpan: eventSpan = rq.get('eventSpan', None) # Split the p_date into separate parts year, month, day = date.year(), date.month(), date.day() # Check that the "preferences" dict exists or not. if not hasattr(obj.aq_base, self.name): # 1st level: create a IOBTree whose keys are years. setattr(obj, self.name, IOBTree()) yearsDict = getattr(obj, self.name) # Get the sub-dict storing months for a given year if year in yearsDict: monthsDict = yearsDict[year] else: yearsDict[year] = monthsDict = IOBTree() # Get the sub-dict storing days of a given month if month in monthsDict: daysDict = monthsDict[month] else: monthsDict[month] = daysDict = IOBTree() # Get the list of events for a given day if day in daysDict: events = daysDict[day] else: daysDict[day] = events = PersistentList() # Create and store the event, excepted if an event already exists. if not events: event = Object(eventType=eventType) events.append(event) # Span the event on the successive days if required if handleEventSpan and eventSpan: nbOfDays = min(int(eventSpan), self.maxEventLength) for i in range(nbOfDays): date = date + 1 self.createEvent(obj, date, handleEventSpan=False)
def process(self, obj): '''Processes a response from Ogone.''' # Call the response method defined in this Ogone field. if not self.ogoneResponseOk(obj): obj.log('Ogone response SHA failed. REQUEST: %s' % \ str(obj.REQUEST.form)) raise Exception('Failure, possible fraud detection, an ' \ 'administrator has been contacted.') # Create a nice object from the form. response = Object() for k, v in obj.REQUEST.form.iteritems(): setattr(response, k, v) # Call the field method that handles the response received from Ogone. url = self.responseMethod(obj.appy(), response) # Redirect the user to the correct page. If the field method returns # some URL, use it. Else, use the view page of p_obj. if not url: url = obj.absolute_url() obj.goto(url)
def getStorableValue(self, obj, value): '''Gets p_value in a form that can be stored in the database.''' res = [] for v in value: sv = Object() for name, field in self.fields: subValue = getattr(v, name) try: setattr(sv, name, field.getStorableValue(obj, subValue)) except ValueError: # The value for this field for this specific row is # incorrect. It can happen in the process of validating the # whole List field (a call to m_getStorableValue occurs at # this time). We don't care about it, because later on we # will have sub-field specific validation that will also # detect the error and will prevent storing the wrong value # in the database. setattr(sv, name, subValue) res.append(sv) return res
def parse(self): '''Parses the CSV file named self.fileName and creates a list of corresponding Python objects (Object instances). Among object fields, some may be references. If it is the case, you may specify in p_references a dict of referred objects. The parser will then replace string values of some fields (which are supposed to be ids of referred objects) with corresponding objects in p_references. How does this work? p_references must be a dictionary: - keys correspond to field names of the current object; - values are 2-tuples: * 1st value is the list of available referred objects; * 2nd value is the name of the attribute on those objects that stores their ID. ''' # The first pass parses the file and creates the Python object f = file(self.fileName) firstLine = True lineNb = 0 for line in f: lineNb += 1 line = line.strip() if not line: continue if firstLine: # The first line declares the structure of the following 'data' # lines. self.identifySeparator(line) self.identifyAttributes(line) firstLine = False else: # Add an object corresponding to this line. lineObject = Object() if self.klass: lineObject.__class__ = self.klass i = -1 # Do we get the right number of field values on this line ? attrValues = line.split(self.sep) if len(attrValues) != len(self.attributes): raise WRONG_LINE % (lineNb, self.fileName) for attrValue in line.split(self.sep): i += 1 theValue = attrValue vType = self.attributesTypes[i] if self.attributesFlags[i]: # The attribute is multi-valued if not attrValue: theValue = [] elif '+' in theValue: theValue = [self.convertValue(v, vType) \ for v in attrValue.split('+')] else: theValue = [self.convertValue(theValue, vType)] else: # The attribute is mono-valued theValue = self.convertValue(theValue, vType) setattr(lineObject, self.attributes[i], theValue) self.res.append(lineObject) f.close() # The second pass resolves the p_references if any for attrName, refInfo in self.references.iteritems(): if attrName in self.attributes: # Replace ID with real object from p_references for obj in self.res: attrValue = getattr(obj, attrName) if isinstance(attrValue, list) or \ isinstance(attrValue, tuple): # Multiple values to resolve newValue = [] for v in attrValue: newValue.append(self.resolveReference(attrName,v)) else: # Only one value to resolve newValue = self.resolveReference(attrName, attrValue) setattr(obj, attrName, newValue) return self.res
def parse(self): '''Parses the CSV file named self.fileName and creates a list of corresponding Python objects (Object instances). Among object fields, some may be references. If it is the case, you may specify in p_references a dict of referred objects. The parser will then replace string values of some fields (which are supposed to be ids of referred objects) with corresponding objects in p_references. How does this work? p_references must be a dictionary: - keys correspond to field names of the current object; - values are 2-tuples: * 1st value is the list of available referred objects; * 2nd value is the name of the attribute on those objects that stores their ID. ''' # The first pass parses the file and creates the Python object f = file(self.fileName) firstLine = True lineNb = 0 for line in f: lineNb += 1 line = line.strip() if not line: continue if firstLine: # The first line declares the structure of the following 'data' # lines. self.identifySeparator(line) self.identifyAttributes(line) firstLine = False else: # Add an object corresponding to this line. lineObject = Object() if self.klass: lineObject.__class__ = self.klass i = -1 # Do we get the right number of field values on this line ? attrValues = line.split(self.sep) if len(attrValues) != len(self.attributes): raise WRONG_LINE % (lineNb, self.fileName) for attrValue in line.split(self.sep): i += 1 theValue = attrValue vType = self.attributesTypes[i] if self.attributesFlags[i]: # The attribute is multi-valued if not attrValue: theValue = [] elif '+' in theValue: theValue = [self.convertValue(v, vType) \ for v in attrValue.split('+')] else: theValue = [self.convertValue(theValue, vType)] else: # The attribute is mono-valued theValue = self.convertValue(theValue, vType) setattr(lineObject, self.attributes[i], theValue) self.res.append(lineObject) f.close() # The second pass resolves the p_references if any for attrName, refInfo in self.references.iteritems(): if attrName in self.attributes: # Replace ID with real object from p_references for obj in self.res: attrValue = getattr(obj, attrName) if isinstance(attrValue, list) or \ isinstance(attrValue, tuple): # Multiple values to resolve newValue = [] for v in attrValue: newValue.append(self.resolveReference(attrName, v)) else: # Only one value to resolve newValue = self.resolveReference(attrName, attrValue) setattr(obj, attrName, newValue) return self.res
import logging logger = logging.getLogger(__name__) import SSDNRequest from appy import Object from appy.shared.dav import Resource from appy.shared.xml_parser import XmlUnmarshaller, XmlMarshaller from xml.dom.minidom import parseString #~ from django.conf import settings.SITE # simulate a Django `settings.SITE` module: settings = Object(SITE=Object(bcss_user_params=dict(UserID='123456', Email='*****@*****.**', OrgUnit='0123456', MatrixID=17, MatrixSubID=1))) class AnyMarshaller(XmlMarshaller): """ An XmlMarshaller who expects an attribute `_any` on its root instance which is expected to contain a string to be written after the other child elements. """ fieldsToExclude = ['_any'] def marshallSpecificElements(self, instance, res): res.write(instance._any)
def getFileInfo(self, fileObject): '''Returns filename and size of p_fileObject.''' if not fileObject: return Object(filename='', size=0) return Object(filename=fileObject.filename, size=fileObject.size)
def main(): allocationReq1 = """<ns1:AllocationRequest xmlns:ns1="http://www.smals.be/XSD/OCMW_CPAS/HeatingAllocationRequest" xmlns:com="http://www.smals.be/XSD/OCMW_CPAS/HeatingAllocationDataTypes"><ns1:ComputeAllocation><ns1:PrimaryBeneficiary><ns1:SSIN>67031703807</ns1:SSIN><ns1:Category>1</ns1:Category></ns1:PrimaryBeneficiary><ns1:Invoice><com:Amount>8390100</com:Amount><com:Quantity>1000</com:Quantity><com:HousingNumber>1</com:HousingNumber><com:DeliveryDate>2011-09-19</com:DeliveryDate><com:UnitFuel>3</com:UnitFuel></ns1:Invoice></ns1:ComputeAllocation><ns1:OCMW_CPAS><ns1:KboBceNumber>0212344876</ns1:KboBceNumber></ns1:OCMW_CPAS></ns1:AllocationRequest>""" ssin = '67031703807' allocationReq = Object(ComputeAllocation=Object( Invoice=Object(Amount="8390100", Quantity=1000, HousingNumber=1, DeliveryDate="2011-09-19", UnitFuel=3), PrimaryBeneficiary=Object(SSIN=ssin, Category="1"), ), OCMW_CPAS=Object(KboBceNumber='0212344876')) ns = dict( ns1="http://www.smals.be/XSD/OCMW_CPAS/HeatingAllocationRequest", com="http://www.smals.be/XSD/OCMW_CPAS/HeatingAllocationDataTypes") nst = dict() nst.update(AllocationRequest='ns1') nst.update(ComputeAllocation='ns1') nst.update(OCMW_CPAS='******') nst.update(KboBceNumber='ns1') nst.update(Invoice='ns1') nst.update(Quantity='com') nst.update(HousingNumber='com') nst.update(DeliveryDate='com') nst.update(UnitFuel='com') m = XmlMarshaller(namespaces=ns, namespacedTags=nst, dumpXmlPrologue=False, rootTag="AllocationRequest") allocationReq2 = m.marshall(allocationReq) #~ assert_equivalent(allocationReq1,allocationReq2) contenu1 = """<SSDNRequest xmlns="http://www.ksz-bcss.fgov.be/XSD/SSDN/Service"> <RequestContext><AuthorizedUser><UserID>00901732883</UserID><Email>[email protected]</Email><OrgUnit>0212344876</OrgUnit><MatrixID>17</MatrixID><MatrixSubID>1</MatrixSubID></AuthorizedUser><Message><Reference>630230001126766</Reference><TimeRequest>20110921T105230</TimeRequest></Message></RequestContext><ServiceRequest><ServiceId>OCMWCPASHeatingAllocation</ServiceId><Version>20090409</Version> %s </ServiceRequest></SSDNRequest>""" % allocationReq1 ssdnReq = Object(RequestContext=Object( AuthorizedUser=Object(**settings.SITE.bcss_user_params), Message=Object(Reference='630230001126766', TimeRequest='20110921T105230')), ServiceRequest=Object( ServiceId="OCMWCPASHeatingAllocation", Version="20090409"), _any=allocationReq2) ns = dict(xmlns="http://www.ksz-bcss.fgov.be/XSD/SSDN/Service") m = AnyMarshaller(namespaces=ns, dumpXmlPrologue=False, rootTag='SSDNRequest') contenu2 = m.marshall(ssdnReq) assert_equivalent(contenu1, contenu2) body = Object( #~ xmlString="<![CDATA[%s]]>" % contenu) xmlString=contenu2) raise Exception("ok jusqu'ici") server = Resource( 'https://bcssksz-services-test.smals.be/connectors/webservice/KSZBCSSWebServiceConnectorPort', measure=True) res = server.soap( body, namespace="http://ksz-bcss.fgov.be/connectors/WebServiceConnector") print res.code print res.data s = str(res.data.xmlString) #~ s = res.data.xmlString.replace('"UTF-8"','"utf-8"') #~ s = s.replace('?>','?>\n') print s reply = XmlUnmarshaller().parse(s) import pdb pdb.set_trace()
def getValue(self, obj, template=None, format=None, result=None, queryData=None, customContext=None, noSecurity=False): '''For a pod field, getting its value means computing a pod document or returning a frozen one. A pod field differs from other field types because there can be several ways to produce the field value (ie: self.template can hold various templates; output file format can be odt, pdf,.... We get those precisions about the way to produce the file, either from params, or from default values. * p_template is the specific template, among self.template, that must be used as base for generating the document; * p_format is the output format of the resulting document; * p_result, if given, must be the absolute path of the document that will be computed by pod. If not given, pod will produce a doc in the OS temp folder; * if the pod document is related to a query, the query parameters needed to re-trigger the query are given in p_queryData; * dict p_customContext may be specified and will override any other value available in the context, including values from the field-specific context. ''' obj = obj.appy() template = template or self.template[0] format = format or 'odt' # Security check. if not noSecurity and not queryData: if self.showTemplate and not self.showTemplate(obj, template): raise Exception(self.UNAUTHORIZED) # Return the possibly frozen document (not applicable for query-related # pods). if not queryData: frozen = self.isFrozen(obj, template, format) if frozen: fileName = self.getDownloadName(obj, template, format, False) return FileInfo(frozen, inDb=False, uploadName=fileName) # We must call pod to compute a pod document from "template". tool = obj.tool diskFolder = tool.getDiskFolder() # Get the path to the pod template. templatePath = self.getTemplatePath(diskFolder, template) # Get or compute the specific POD context specificContext = None if callable(self.context): specificContext = self.callMethod(obj, self.context) else: specificContext = self.context # Compute the name of the result file. if not result: result = '%s/%s_%f.%s' % (sutils.getOsTempFolder(), obj.uid, time.time(), format) # Define parameters to give to the appy.pod renderer podContext = { 'tool': tool, 'user': obj.user, 'self': obj, 'field': self, 'now': obj.o.getProductConfig().DateTime(), '_': obj.translate, 'projectFolder': diskFolder, 'template': template, 'request': tool.request } # If the pod document is related to a query, re-trigger it and put the # result in the pod context. if queryData: # Retrieve query params cmd = ', '.join(tool.o.queryParamNames) cmd += " = queryData.split(';')" exec cmd # (re-)execute the query, but without any limit on the number of # results; return Appy objects. objs = tool.o.executeQuery(obj.o.portal_type, searchName=search, sortBy=sortKey, sortOrder=sortOrder, filterKey=filterKey, filterValue=filterValue, maxResults='NO_LIMIT') podContext['objects'] = [o.appy() for o in objs.objects] podContext['queryData'] = queryData.split(';') # Add the field-specific and custom contexts if present. if specificContext: podContext.update(specificContext) if customContext: podContext.update(customContext) # Variable "_checked" can be expected by a template but absent (ie, # when generating frozen documents). if '_checked' not in podContext: podContext['_checked'] = Object() # Define a potential global styles mapping if callable(self.stylesMapping): stylesMapping = self.callMethod(obj, self.stylesMapping) else: stylesMapping = self.stylesMapping rendererParams = { 'template': templatePath, 'context': podContext, 'result': result, 'stylesMapping': stylesMapping, 'imageResolver': tool.o.getApp(), 'overwriteExisting': True } if tool.unoEnabledPython: rendererParams['pythonWithUnoPath'] = tool.unoEnabledPython if tool.openOfficePort: rendererParams['ooPort'] = tool.openOfficePort # Launch the renderer try: renderer = Renderer(**rendererParams) renderer.run() except PodError, pe: if not os.path.exists(result): # In some (most?) cases, when OO returns an error, the result is # nevertheless generated. obj.log(str(pe).strip(), type='error') return Pod.POD_ERROR