Esempio n. 1
0
 def __init__(self, expressionCompiler=None, xml=1, source_file=None):
     if not expressionCompiler:
         from zope.tal.dummyengine import DummyEngine
         expressionCompiler = DummyEngine()
     self.expressionCompiler = expressionCompiler
     self.CompilerError = expressionCompiler.getCompilerError()
     # This holds the emitted opcodes representing the input
     self.program = []
     # The program stack for when we need to do some sub-evaluation for an
     # intermediate result.  E.g. in an i18n:name tag for which the
     # contents describe the ${name} value.
     self.stack = []
     # Another stack of postponed actions.  Elements on this stack are a
     # dictionary; key/values contain useful information that
     # emitEndElement needs to finish its calculations
     self.todoStack = []
     self.macros = {}
     # {slot-name --> default content program}
     self.slots = {}
     self.slotStack = []
     self.xml = xml  # true --> XML, false --> HTML
     self.emit("version", TAL_VERSION)
     self.emit("mode", xml and "xml" or "html")
     if source_file is not None:
         self.source_file = source_file
         self.emit("setSourceFile", source_file)
     self.i18nContext = TranslationContext()
     self.i18nLevel = 0
Esempio n. 2
0
 def do_beginI18nContext(self, settings):
     get = settings.get
     self.i18nContext = TranslationContext(self.i18nContext,
                                           domain=get("domain"),
                                           source=get("source"),
                                           target=get("target"))
Esempio n. 3
0
    def __init__(self,
                 program,
                 macros,
                 engine,
                 stream=None,
                 debug=0,
                 wrap=1023,
                 metal=1,
                 tal=1,
                 showtal=-1,
                 strictinsert=1,
                 stackLimit=100,
                 i18nInterpolate=1,
                 sourceAnnotations=0):
        """Create a TAL interpreter.

        Optional arguments:

            stream -- output stream (defaults to sys.stdout).

            debug -- enable debugging output to sys.stderr (off by default).

            wrap -- try to wrap attributes on opening tags to this number of
            column (default: 1023).

            metal -- enable METAL macro processing (on by default).

            tal -- enable TAL processing (on by default).

            showtal -- do not strip away TAL directives.  A special value of
            -1 (which is the default setting) enables showtal when TAL
            processing is disabled, and disables showtal when TAL processing is
            enabled.  Note that you must use 0, 1, or -1; true boolean values
            are not supported (TODO: why?).

            strictinsert -- enable TAL processing and stricter HTML/XML
            checking on text produced by structure inserts (on by default).
            Note that Zope turns this value off by default.

            stackLimit -- set macro nesting limit (default: 100).

            i18nInterpolate -- enable i18n translations (default: on).

            sourceAnnotations -- enable source annotations with HTML comments
            (default: off).

        """
        self.program = program
        self.macros = macros
        self.engine = engine  # Execution engine (aka context)
        self.Default = engine.getDefault()
        self._pending_source_annotation = False
        self._currentTag = ""
        self._stream_stack = [stream or sys.stdout]
        self.popStream()
        self.debug = debug
        self.wrap = wrap
        self.metal = metal
        self.tal = tal
        if tal:
            self.dispatch = self.bytecode_handlers_tal
        else:
            self.dispatch = self.bytecode_handlers
        assert showtal in (-1, 0, 1)
        if showtal == -1:
            showtal = (not tal)
        self.showtal = showtal
        self.strictinsert = strictinsert
        self.stackLimit = stackLimit
        self.html = 0
        self.endsep = "/>"
        self.endlen = len(self.endsep)
        # macroStack entries are MacroStackItem instances;
        # the entries are mutated while on the stack
        self.macroStack = []
        # `inUseDirective` is set iff we're handling either a
        # metal:use-macro or a metal:extend-macro
        self.inUseDirective = False
        self.position = None, None  # (lineno, offset)
        self.col = 0
        self.level = 0
        self.scopeLevel = 0
        self.sourceFile = None
        self.i18nStack = []
        self.i18nInterpolate = i18nInterpolate
        self.i18nContext = TranslationContext()
        self.sourceAnnotations = sourceAnnotations
Esempio n. 4
0
    def emitStartElement(self,
                         name,
                         attrlist,
                         taldict,
                         metaldict,
                         i18ndict,
                         position=(None, None),
                         isend=0):
        if not taldict and not metaldict and not i18ndict:
            # Handle the simple, common case
            self.emitStartTag(name, attrlist, isend)
            self.todoPush({})
            if isend:
                self.emitEndElement(name, isend)
            return
        self.position = position

        replaced = False
        if "replace" in taldict:
            taldict["omit-tag"] = taldict.get("omit-tag", "")
            taldict["content"] = taldict.pop("replace")
            replaced = True

        for key, value in i18ndict.items():
            if key not in taldefs.KNOWN_I18N_ATTRIBUTES:
                raise I18NError("bad i18n attribute: " + repr(key), position)
            if not value and key in ("attributes", "data", "id"):
                raise I18NError(
                    "missing value for i18n attribute: " + repr(key), position)

        todo = {}
        defineMacro = metaldict.get("define-macro")
        extendMacro = metaldict.get("extend-macro")
        useMacro = metaldict.get("use-macro")
        defineSlot = metaldict.get("define-slot")
        fillSlot = metaldict.get("fill-slot")
        define = taldict.get("define")
        condition = taldict.get("condition")
        repeat = taldict.get("repeat")
        content = taldict.get("content")
        script = taldict.get("script")
        attrsubst = taldict.get("attributes")
        onError = taldict.get("on-error")
        omitTag = taldict.get("omit-tag")
        TALtag = taldict.get("tal tag")
        i18nattrs = i18ndict.get("attributes")
        # Preserve empty string if implicit msgids are used.  We'll generate
        # code with the msgid='' and calculate the right implicit msgid during
        # interpretation phase.
        msgid = i18ndict.get("translate")
        varname = i18ndict.get('name')
        i18ndata = i18ndict.get('data')

        if varname and not self.i18nLevel:
            raise I18NError(
                "i18n:name can only occur inside a translation unit", position)

        if i18ndata and not msgid:
            raise I18NError("i18n:data must be accompanied by i18n:translate",
                            position)

        if defineMacro or extendMacro or useMacro:
            useMacro = useMacro or extendMacro

        if content and msgid:
            raise I18NError(
                "explicit message id and tal:content can't be used together",
                position)

        repeatWhitespace = None
        if repeat:
            # Hack to include preceding whitespace in the loop program
            repeatWhitespace = self.unEmitNewlineWhitespace()
        if position != (None, None):
            # TODO: at some point we should insist on a non-trivial position
            self.emit("setPosition", position)
        if self.inMacroUse:
            if fillSlot:
                self.pushProgram()
                # generate a source annotation at the beginning of fill-slot
                if self.source_file is not None:
                    if position != (None, None):
                        self.emit("setPosition", position)
                    self.emit("setSourceFile", self.source_file)
                todo["fillSlot"] = fillSlot
                self.inMacroUse = 0
        if not self.inMacroUse:
            if defineMacro:
                self.pushProgram()
                self.emit("version", TAL_VERSION)
                self.emit("mode", self.xml and "xml" or "html")
                # generate a source annotation at the beginning of the macro
                if self.source_file is not None:
                    if position != (None, None):
                        self.emit("setPosition", position)
                    self.emit("setSourceFile", self.source_file)
                todo["defineMacro"] = defineMacro
                self.inMacroDef = self.inMacroDef + 1
            if useMacro:
                self.pushSlots()
                self.pushProgram()
                todo["useMacro"] = useMacro
                self.inMacroUse = 1
            if defineSlot:
                self.pushProgram()
                todo["defineSlot"] = defineSlot

        if defineSlot or i18ndict:

            domain = i18ndict.get("domain") or self.i18nContext.domain
            source = i18ndict.get("source") or self.i18nContext.source
            target = i18ndict.get("target") or self.i18nContext.target
            if (domain != DEFAULT_DOMAIN or source is not None
                    or target is not None):
                self.i18nContext = TranslationContext(self.i18nContext,
                                                      domain=domain,
                                                      source=source,
                                                      target=target)
                self.emit("beginI18nContext", {
                    "domain": domain,
                    "source": source,
                    "target": target
                })
                todo["i18ncontext"] = 1
        if taldict or i18ndict:
            dict = {}
            for item in attrlist:
                key, value = item[:2]
                dict[key] = value
            self.emit("beginScope", dict)
            todo["scope"] = 1
        if onError:
            self.pushProgram()  # handler
            if TALtag:
                self.pushProgram()  # start
            self.emitStartTag(name, list(attrlist))  # Must copy attrlist!
            if TALtag:
                self.pushProgram()  # start
            self.pushProgram()  # block
            todo["onError"] = onError
        if define:
            self.emitDefines(define)
            todo["define"] = define
        if condition:
            self.pushProgram()
            todo["condition"] = condition
        if repeat:
            todo["repeat"] = repeat
            self.pushProgram()
            if repeatWhitespace:
                self.emitText(repeatWhitespace)
        if content:
            if varname:
                todo['i18nvar'] = varname
                todo["content"] = content
                self.pushProgram()
            else:
                todo["content"] = content
        # i18n:name w/o tal:replace uses the content as the interpolation
        # dictionary values
        elif varname:
            todo['i18nvar'] = varname
            self.pushProgram()
        if msgid is not None:
            self.i18nLevel += 1
            todo['msgid'] = msgid
        if i18ndata:
            todo['i18ndata'] = i18ndata
        optTag = omitTag is not None or TALtag
        if optTag:
            todo["optional tag"] = omitTag, TALtag
            self.pushProgram()
        if attrsubst or i18nattrs:
            if attrsubst:
                try:
                    repldict = taldefs.parseAttributeReplacements(
                        attrsubst, self.xml)
                except TALError:
                    repldict = {}
            else:
                repldict = {}
            if i18nattrs:
                i18nattrs = _parseI18nAttributes(i18nattrs, self.position,
                                                 self.xml)
            else:
                i18nattrs = {}
            # Convert repldict's name-->expr mapping to a
            # name-->(compiled_expr, translate) mapping
            for key, value in sorted(repldict.items()):
                if i18nattrs.get(key, None):
                    raise I18NError(
                        "attribute [%s] cannot both be part of tal:attributes"
                        " and have a msgid in i18n:attributes" % key, position)
                ce = self.compileExpression(value)
                repldict[key] = ce, key in i18nattrs, i18nattrs.get(key)
            for key in sorted(i18nattrs):
                if key not in repldict:
                    repldict[key] = None, 1, i18nattrs.get(key)
        else:
            repldict = {}
        if replaced:
            todo["repldict"] = repldict
            repldict = {}
        if script:
            todo["script"] = script
        self.emitStartTag(name, self.replaceAttrs(attrlist, repldict), isend)
        if optTag:
            self.pushProgram()
        if content and not varname:
            self.pushProgram()
        if not content and msgid is not None:
            self.pushProgram()
        if content and varname:
            self.pushProgram()
        if script:
            self.pushProgram()
        if todo and position != (None, None):
            todo["position"] = position
        self.todoPush(todo)
        if isend:
            self.emitEndElement(name, isend, position=position)