[forms] edited_entity must be set before calling session_key()
EntityFieldsForm.__init__ calls FieldsForm.__init__ which in turn
calls self.session_key().
self.session_key() uses self.edited_key to compute the correct session
key. We thus need edited_entity to be set **before** calling super's __init__.
The bug only occured when EntityFieldsForm was selected because of its
one_line_rset() selector instead of match_kwargs('entity').
"""provides simpleTAL extensions for CubicWeb:organization: Logilab:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses"""__docformat__="restructuredtext en"importsysimportrefromos.pathimportexists,isdir,joinfromloggingimportgetLoggerfromStringIOimportStringIOfromsimpletalimportsimpleTAL,simpleTALESfromlogilab.common.decoratorsimportcachedLOGGER=getLogger('cubicweb.tal')classLoggerAdapter(object):def__init__(self,tal_logger):self.tal_logger=tal_loggerdefdebug(self,msg):LOGGER.debug(msg)defwarn(self,msg):LOGGER.warning(msg)def__getattr__(self,attrname):returngetattr(self.tal_logger,attrname)classCubicWebContext(simpleTALES.Context):"""add facilities to access entity / resultset"""def__init__(self,options=None,allowPythonPath=1):simpleTALES.Context.__init__(self,options,allowPythonPath)self.log=LoggerAdapter(self.log)defupdate(self,context):forvarname,valueincontext.items():self.addGlobal(varname,value)defaddRepeat(self,name,var,initialValue):simpleTALES.Context.addRepeat(self,name,var,initialValue)# XXX FIXME need to find a clean to define OPCODE values for extensionsI18N_CONTENT=18I18N_REPLACE=19RQL_EXECUTE=20# simpleTAL uses the OPCODE values to define priority over commands.# TAL_ITER should have the same priority than TAL_REPEAT (i.e. 3), but# we can't use the same OPCODE for two different commands without changing# the simpleTAL implementation. Another solution would be to totally override# the REPEAT implementation with the ITER one, but some specific operations# (involving len() for instance) are not implemented for ITER, so we prefer# to keep both implementations for now, and to fool simpleTAL by using a float# number between 3 and 4TAL_ITER=3.1# FIX simpleTAL HTML 4.01 stupidity# (simpleTAL never closes tags like INPUT, IMG, HR ...)simpleTAL.HTML_FORBIDDEN_ENDTAG.clear()classCubicWebTemplateCompiler(simpleTAL.HTMLTemplateCompiler):"""extends default compiler by adding i18n:content commands"""def__init__(self):simpleTAL.HTMLTemplateCompiler.__init__(self)self.commandHandler[I18N_CONTENT]=self.compile_cmd_i18n_contentself.commandHandler[I18N_REPLACE]=self.compile_cmd_i18n_replaceself.commandHandler[RQL_EXECUTE]=self.compile_cmd_rqlself.commandHandler[TAL_ITER]=self.compile_cmd_tal_iterdefsetTALPrefix(self,prefix):simpleTAL.TemplateCompiler.setTALPrefix(self,prefix)self.tal_attribute_map['i18n:content']=I18N_CONTENTself.tal_attribute_map['i18n:replace']=I18N_REPLACEself.tal_attribute_map['rql:execute']=RQL_EXECUTEself.tal_attribute_map['tal:iter']=TAL_ITERdefcompile_cmd_i18n_content(self,argument):# XXX tal:content structure=, text= should we support this ?structure_flag=0return(I18N_CONTENT,(argument,False,structure_flag,self.endTagSymbol))defcompile_cmd_i18n_replace(self,argument):# XXX tal:content structure=, text= should we support this ?structure_flag=0return(I18N_CONTENT,(argument,True,structure_flag,self.endTagSymbol))defcompile_cmd_rql(self,argument):return(RQL_EXECUTE,(argument,self.endTagSymbol))defcompile_cmd_tal_iter(self,argument):original_id,(var_name,expression,end_tag_symbol)= \simpleTAL.HTMLTemplateCompiler.compileCmdRepeat(self,argument)return(TAL_ITER,(var_name,expression,self.endTagSymbol))defgetTemplate(self):returnCubicWebTemplate(self.commandList,self.macroMap,self.symbolLocationTable)defcompileCmdAttributes(self,argument):"""XXX modified to support single attribute definition ending by a ';' backport this to simpleTAL """# Compile tal:attributes into attribute command# Argument: [(attributeName, expression)]# Break up the list of attribute settings firstcommandArgs=[]# We only want to match semi-colons that are not escapedargumentSplitter=re.compile(r'(?<!;);(?!;)')forattributeStmtinargumentSplitter.split(argument):ifnotattributeStmt.strip():continue# remove any leading space and un-escape any semi-colonsattributeStmt=attributeStmt.lstrip().replace(';;',';')# Break each attributeStmt into name and expressionstmtBits=attributeStmt.split(' ')if(len(stmtBits)<2):# Error, badly formed attributes commandmsg="Badly formed attributes command '%s'. Attributes commands must be of the form: 'name expression[;name expression]'"%argumentself.log.error(msg)raisesimpleTAL.TemplateParseException(self.tagAsText(self.currentStartTag),msg)attName=stmtBits[0]attExpr=" ".join(stmtBits[1:])commandArgs.append((attName,attExpr))return(simpleTAL.TAL_ATTRIBUTES,commandArgs)classCubicWebTemplateInterpreter(simpleTAL.TemplateInterpreter):"""provides implementation for interpreting cubicweb extensions"""def__init__(self):simpleTAL.TemplateInterpreter.__init__(self)self.commandHandler[I18N_CONTENT]=self.cmd_i18nself.commandHandler[TAL_ITER]=self.cmdRepeat# self.commandHandler[RQL_EXECUTE] = self.cmd_rqldefcmd_i18n(self,command,args):"""i18n:content and i18n:replace implementation"""string,replace_flag,structure_flag,end_symbol=argsifreplace_flag:self.outputTag=0result=self.context.globals['_'](string)self.tagContent=(0,result)self.movePCForward=self.symbolTable[end_symbol]self.programCounter+=1classCubicWebTemplate(simpleTAL.HTMLTemplate):"""overrides HTMLTemplate.expand() to systematically use CubicWebInterpreter """defexpand(self,context,outputFile):interpreter=CubicWebTemplateInterpreter()interpreter.initialise(context,outputFile)simpleTAL.HTMLTemplate.expand(self,context,outputFile,# outputEncoding='unicode',interpreter=interpreter)defexpandInline(self,context,outputFile,interpreter):""" Internally used when expanding a template that is part of a context."""try:interpreter.execute(self)exceptUnicodeError,unierror:LOGGER.exception(str(unierror))raisesimpleTALES.ContextContentException("found non-unicode %r string in Context!"%unierror.args[1]),None,sys.exc_info()[-1]defcompile_template(template):"""compiles a TAL template string :type template: unicode :param template: a TAL-compliant template string """string_buffer=StringIO(template)compiler=CubicWebTemplateCompiler()compiler.parseTemplate(string_buffer)# , inputEncoding='unicode')returncompiler.getTemplate()defcompile_template_file(filepath):"""compiles a TAL template file :type filepath: str :param template: path of the file to compile """fp=file(filepath)file_content=unicode(fp.read())# template file should be pure ASCIIfp.close()returncompile_template(file_content)defevaluatePython(self,expr):ifnotself.allowPythonPath:returnself.falseglobals={}forname,valueinself.globals.items():ifisinstance(value,simpleTALES.ContextVariable):value=value.rawValue()globals[name]=valueglobals['path']=self.pythonPathFuncs.pathglobals['string']=self.pythonPathFuncs.stringglobals['exists']=self.pythonPathFuncs.existsglobals['nocall']=self.pythonPathFuncs.nocallglobals['test']=self.pythonPathFuncs.testlocals={}forname,valueinself.locals.items():if(isinstance(value,simpleTALES.ContextVariable)):value=value.rawValue()locals[name]=value# XXX precompile expr will avoid late syntax errortry:result=eval(expr,globals,locals)exceptException,ex:ex=ex.__class__('in %r: %s'%(expr,ex))raiseex,None,sys.exc_info()[-1]if(isinstance(result,simpleTALES.ContextVariable)):returnresult.value()returnresultsimpleTALES.Context.evaluatePython=evaluatePythonclasstalbased(object):def__init__(self,filename,write=True):## if not osp.isfile(filepath):## # print "[tal.py] just for tests..."## # get parent frame## directory = osp.abspath(osp.dirname(sys._getframe(1).f_globals['__file__']))## filepath = osp.join(directory, filepath)self.filename=filenameself.write=writedef__call__(self,viewfunc):defwrapped(instance,*args,**kwargs):variables=viewfunc(instance,*args,**kwargs)html=instance.tal_render(self._compiled_template(instance),variables)ifself.write:instance.w(html)else:returnhtmlreturnwrappeddef_compiled_template(self,instance):forfileordirectoryininstance.config.vregistry_path():filepath=join(fileordirectory,self.filename)ifisdir(fileordirectory)andexists(filepath):returncompile_template_file(filepath)raiseException('no such template %s'%self.filename)_compiled_template=cached(_compiled_template,0)