zope.tal-3.5.2/0000755000175000017500000000000011336275656013215 5ustar anthonyanthonyzope.tal-3.5.2/README.txt0000644000175000017500000000105611273124226014677 0ustar anthonyanthonyTemplate Attribute Language (TAL) ================================= Overview -------- The Zope3 Template Attribute Languate (TAL) specifies the custom namespace and attributes which are used by the Zope Page Templates renderer to inject dynamic markup into a page. It also includes the Macro Expansion for TAL (METAL) macro language used in page assembly. The dynamic values themselves are specified using a companion language, TALES (see the 'zope.tales' package for more). See: http://www.zope.org/Wikis/DevSite/Projects/ZPT/TAL%20Specification%201.4 zope.tal-3.5.2/setup.py0000644000175000017500000000621611273124226014716 0ustar anthonyanthony############################################################################## # # Copyright (c) 2006 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## # This package is developed by the Zope Toolkit project, documented here: # http://docs.zope.org/zopetoolkit # When developing and releasing this package, please follow the documented # Zope Toolkit policies as described by this documentation. ############################################################################## """Setup for zope.tal package $Id: setup.py 105409 2009-10-31 17:13:27Z fretin $ """ import os import sys from setuptools import setup, find_packages here = os.path.dirname(__file__) def read(*rnames): return open(os.path.join(here, *rnames)).read() def alltests(): # use the zope.testing testrunner machinery to find all the # test suites we've put under ourselves from zope.testing.testrunner import get_options from zope.testing.testrunner import find_suites from zope.testing.testrunner import configure_logging configure_logging() from unittest import TestSuite here = os.path.abspath(os.path.dirname(sys.argv[0])) args = sys.argv[:] src = os.path.join(here, 'src') defaults = ['--test-path', src] options = get_options(args, defaults) suites = list(find_suites(options)) return TestSuite(suites) setup(name='zope.tal', version = '3.5.2', author='Zope Corporation and Contributors', author_email='zope-dev@zope.org', description='Zope 3 Template Application Languate (TAL)', long_description=( read('README.txt') + '\n\n' + read('CHANGES.txt') ), keywords = "zope3 template xml tal", classifiers = [ 'Development Status :: 5 - Production/Stable', 'Environment :: Web Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: Zope Public License', 'Programming Language :: Python', 'Natural Language :: English', 'Operating System :: OS Independent', 'Topic :: Internet :: WWW/HTTP', 'Framework :: Zope3'], url='http://pypi.python.org/pypi/zope.tal', license='ZPL 2.1', packages=find_packages('src'), package_dir = {'': 'src'}, namespace_packages=['zope'], extras_require = dict( test=['zope.testing', ]), test_suite="__main__.alltests", # to support "setup.py test" tests_require = ['zope.testing'], install_requires=['setuptools', 'zope.i18nmessageid', 'zope.interface', ], include_package_data = True, zip_safe = False, ) zope.tal-3.5.2/buildout.cfg0000644000175000017500000000013211273124226015503 0ustar anthonyanthony[buildout] develop = . parts = test [test] recipe = zc.recipe.testrunner eggs = zope.tal zope.tal-3.5.2/src/0000755000175000017500000000000011336275656014004 5ustar anthonyanthonyzope.tal-3.5.2/src/zope/0000755000175000017500000000000011336275656014761 5ustar anthonyanthonyzope.tal-3.5.2/src/zope/__init__.py0000644000175000017500000000007011273124226017051 0ustar anthonyanthony__import__('pkg_resources').declare_namespace(__name__) zope.tal-3.5.2/src/zope/tal/0000755000175000017500000000000011336275656015541 5ustar anthonyanthonyzope.tal-3.5.2/src/zope/tal/timer.py0000644000175000017500000000333711273124226017223 0ustar anthonyanthony#! /usr/bin/env python ############################################################################## # # Copyright (c) 2001, 2002 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Helper program to time compilation and interpretation $Id: timer.py 25177 2004-06-02 13:17:31Z jim $ """ import getopt import sys import time from cStringIO import StringIO from zope.tal.driver import FILE, compilefile, interpretit def main(): count = 10 try: opts, args = getopt.getopt(sys.argv[1:], "n:") except getopt.error, msg: print msg sys.exit(2) for o, a in opts: if o == "-n": count = int(a) if not args: args = [FILE] for file in args: print file dummyfile = StringIO() it = timefunc(count, compilefile, file) timefunc(count, interpretit, it, None, dummyfile) def timefunc(count, func, *args): sys.stderr.write("%-14s: " % func.__name__) sys.stderr.flush() t0 = time.clock() for i in range(count): result = apply(func, args) t1 = time.clock() sys.stderr.write("%6.3f secs for %d calls, i.e. %4.0f msecs per call\n" % ((t1-t0), count, 1000*(t1-t0)/count)) return result if __name__ == "__main__": main() zope.tal-3.5.2/src/zope/tal/translationcontext.py0000644000175000017500000000276311273124226022050 0ustar anthonyanthony############################################################################## # # Copyright (c) 2001, 2002 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Translation context object for the TALInterpreter's I18N support. The translation context provides a container for the information needed to perform translation of a marked string from a page template. $Id: translationcontext.py 26559 2004-07-15 21:22:32Z srichter $ """ DEFAULT_DOMAIN = "default" class TranslationContext(object): """Information about the I18N settings of a TAL processor.""" def __init__(self, parent=None, domain=None, target=None, source=None): if parent: if not domain: domain = parent.domain if not target: target = parent.target if not source: source = parent.source elif domain is None: domain = DEFAULT_DOMAIN self.parent = parent self.domain = domain self.target = target self.source = source zope.tal-3.5.2/src/zope/tal/DEPENDENCIES.cfg0000644000175000017500000000007511273124226020034 0ustar anthonyanthonyzope.i18n zope.i18nmessageid zope.interface zope.deprecation zope.tal-3.5.2/src/zope/tal/driver.py0000644000175000017500000001541611273124226017377 0ustar anthonyanthony#!/usr/bin/env python ############################################################################## # # Copyright (c) 2001, 2002 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Driver program to test METAL and TAL implementation. Usage: driver.py [options] [file] Options: -h / --help Print this message and exit. -H / --html -x / --xml Explicitly choose HTML or XML input. The default is to automatically select based on the file extension. These options are mutually exclusive. -l Lenient structure insertion. -m Macro expansion only -s Print intermediate opcodes only -t Leave TAL/METAL attributes in output -i Leave I18N substitution strings un-interpolated. -a Enable source annotations $Id: driver.py 29651 2005-03-23 12:56:35Z hdima $ """ import os import sys import getopt if __name__ == "__main__": import setpath # Local hack to tweak sys.path etc. # Import local classes import zope.tal.taldefs from zope.tal.dummyengine import DummyEngine from zope.tal.dummyengine import DummyTranslationDomain FILE = "tests/input/test01.xml" class TestTranslations(DummyTranslationDomain): def translate(self, msgid, mapping=None, context=None, target_language=None, default=None): if msgid == 'timefmt': return '%(minutes)s minutes after %(hours)s %(ampm)s' % mapping elif msgid == 'jobnum': return '%(jobnum)s is the JOB NUMBER' % mapping elif msgid == 'verify': s = 'Your contact email address is recorded as %(email)s' return s % mapping elif msgid == 'mailto:${request/submitter}': return 'mailto:bperson@dom.ain' elif msgid == 'origin': return '%(name)s was born in %(country)s' % mapping return DummyTranslationDomain.translate( self, msgid, mapping, context, target_language, default=default) class TestEngine(DummyEngine): def __init__(self, macros=None): DummyEngine.__init__(self, macros) self.translationDomain = TestTranslations() def evaluatePathOrVar(self, expr): if expr == 'here/currentTime': return {'hours' : 6, 'minutes': 59, 'ampm' : 'PM', } elif expr == 'context/@@object_name': return '7' elif expr == 'request/submitter': return 'aperson@dom.ain' return DummyEngine.evaluatePathOrVar(self, expr) # This is a disgusting hack so that we can use engines that actually know # something about certain object paths. TimeEngine knows about # here/currentTime. ENGINES = {'test23.html': TestEngine, 'test24.html': TestEngine, 'test26.html': TestEngine, 'test27.html': TestEngine, 'test28.html': TestEngine, 'test29.html': TestEngine, 'test30.html': TestEngine, 'test31.html': TestEngine, 'test32.html': TestEngine, } def usage(code, msg=''): print >> sys.stderr, __doc__ if msg: print >> sys.stderr, msg sys.exit(code) def main(): macros = 0 mode = None showcode = 0 showtal = -1 sourceAnnotations = 0 strictinsert = 1 i18nInterpolate = 1 try: opts, args = getopt.getopt(sys.argv[1:], "hHxlmstia", ['help', 'html', 'xml']) except getopt.error, msg: usage(2, msg) for opt, arg in opts: if opt in ('-h', '--help'): usage(0) if opt in ('-H', '--html'): if mode == 'xml': usage(1, '--html and --xml are mutually exclusive') mode = "html" if opt == '-l': strictinsert = 0 if opt == '-m': macros = 1 if opt in ('-x', '--xml'): if mode == 'html': usage(1, '--html and --xml are mutually exclusive') mode = "xml" if opt == '-s': showcode = 1 if opt == '-t': showtal = 1 if opt == '-i': i18nInterpolate = 0 if opt == '-a': sourceAnnotations = 1 if args: file = args[0] else: file = FILE it = compilefile(file, mode) if showcode: showit(it) else: # See if we need a special engine for this test engine = None engineClass = ENGINES.get(os.path.basename(file)) if engineClass is not None: engine = engineClass(macros) interpretit(it, engine=engine, tal=(not macros), showtal=showtal, strictinsert=strictinsert, i18nInterpolate=i18nInterpolate, sourceAnnotations=sourceAnnotations) def interpretit(it, engine=None, stream=None, tal=1, showtal=-1, strictinsert=1, i18nInterpolate=1, sourceAnnotations=0): from zope.tal.talinterpreter import TALInterpreter program, macros = it assert zope.tal.taldefs.isCurrentVersion(program) if engine is None: engine = DummyEngine(macros) TALInterpreter(program, macros, engine, stream, wrap=0, tal=tal, showtal=showtal, strictinsert=strictinsert, i18nInterpolate=i18nInterpolate, sourceAnnotations=sourceAnnotations)() def compilefile(file, mode=None): assert mode in ("html", "xml", None) if mode is None: ext = os.path.splitext(file)[1] if ext.lower() in (".html", ".htm"): mode = "html" else: mode = "xml" from zope.tal.talgenerator import TALGenerator filename = os.path.abspath(file) prefix = os.path.dirname(os.path.abspath(__file__)) + os.path.sep if filename.startswith(prefix): filename = filename[len(prefix):] filename = filename.replace(os.sep, '/') # test files expect slashes if mode == "html": from zope.tal.htmltalparser import HTMLTALParser p = HTMLTALParser(gen=TALGenerator(source_file=filename, xml=0)) else: from zope.tal.talparser import TALParser p = TALParser(gen=TALGenerator(source_file=filename)) p.parseFile(file) return p.getCode() def showit(it): from pprint import pprint pprint(it) if __name__ == "__main__": main() zope.tal-3.5.2/src/zope/tal/xmlparser.py0000644000175000017500000000726611273124226020125 0ustar anthonyanthony############################################################################## # # Copyright (c) 2001, 2002 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Generic Expat-based XML parser base class. This creates a parser with namespace processing enabled. $Id: xmlparser.py 72023 2007-01-14 13:54:17Z philikon $ """ import logging class XMLParser(object): ordered_attributes = 0 handler_names = [ "StartElementHandler", "EndElementHandler", "ProcessingInstructionHandler", "CharacterDataHandler", "UnparsedEntityDeclHandler", "NotationDeclHandler", "StartNamespaceDeclHandler", "EndNamespaceDeclHandler", "CommentHandler", "StartCdataSectionHandler", "EndCdataSectionHandler", "DefaultHandler", "DefaultHandlerExpand", "NotStandaloneHandler", "ExternalEntityRefHandler", "XmlDeclHandler", "StartDoctypeDeclHandler", "EndDoctypeDeclHandler", "ElementDeclHandler", "AttlistDeclHandler" ] def __init__(self, encoding=None): self.parser = p = self.createParser(encoding) if self.ordered_attributes: try: self.parser.ordered_attributes = self.ordered_attributes except AttributeError: logging.warn("TAL.XMLParser: Can't set ordered_attributes") self.ordered_attributes = 0 for name in self.handler_names: method = getattr(self, name, None) if method is not None: try: setattr(p, name, method) except AttributeError: logging.error("TAL.XMLParser: Can't set " "expat handler %s" % name) def createParser(self, encoding=None): global XMLParseError from xml.parsers import expat XMLParseError = expat.ExpatError return expat.ParserCreate(encoding, ' ') def parseFile(self, filename): self.parseStream(open(filename)) def parseString(self, s): if isinstance(s, unicode): # Expat cannot deal with unicode strings, only with # encoded ones. Also, its range of encodings is rather # limited, UTF-8 is the safest bet here. s = s.encode('utf-8') self.parser.Parse(s, 1) def parseURL(self, url): import urllib self.parseStream(urllib.urlopen(url)) def parseStream(self, stream): self.parser.ParseFile(stream) def parseFragment(self, s, end=0): self.parser.Parse(s, end) def getpos(self): # Apparently ErrorLineNumber and ErrorLineNumber contain the current # position even when there was no error. This contradicts the official # documentation[1], but expat.h[2] contains the following definition: # # /* For backwards compatibility with previous versions. */ # #define XML_GetErrorLineNumber XML_GetCurrentLineNumber # # [1] http://python.org/doc/current/lib/xmlparser-objects.html # [2] http://cvs.sourceforge.net/viewcvs.py/expat/expat/lib/expat.h return (self.parser.ErrorLineNumber, self.parser.ErrorColumnNumber) zope.tal-3.5.2/src/zope/tal/tests/0000755000175000017500000000000011336275656016703 5ustar anthonyanthonyzope.tal-3.5.2/src/zope/tal/tests/utils.py0000644000175000017500000000371611273124226020406 0ustar anthonyanthony############################################################################## # # Copyright (c) 2001, 2002 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Helper functions for the test suite. $Id: utils.py 30139 2005-04-24 07:01:43Z hdima $ """ import os import sys mydir = os.path.abspath(os.path.dirname(__file__)) codedir = os.path.dirname(os.path.dirname(os.path.dirname(mydir))) if codedir not in sys.path: sys.path.append(codedir) import unittest # Set skipxml to true if an XML parser could not be found. skipxml = 0 try: import xml.parsers.expat except ImportError: skipxml = 1 def run_suite(suite, outf=None, errf=None): if outf is None: outf = sys.stdout runner = unittest.TextTestRunner(outf) result = runner.run(suite) ## print "\n\n" ## if result.errors: ## print "Errors (unexpected exceptions):" ## map(print_error, result.errors) ## print ## if result.failures: ## print "Failures (assertion failures):" ## map(print_error, result.failures) ## print newerrs = len(result.errors) + len(result.failures) if newerrs: print "'Errors' indicate exceptions other than AssertionError." print "'Failures' indicate AssertionError" if errf is None: errf = sys.stderr errf.write("%d errors, %d failures\n" % (len(result.errors), len(result.failures))) return newerrs def print_error(info): testcase, (type, e, tb) = info zope.tal-3.5.2/src/zope/tal/tests/test_talgettext.py0000644000175000017500000000507111273124226022466 0ustar anthonyanthony############################################################################## # # Copyright (c) 2001, 2002 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Tests for the talgettext utility. $Id: test_talgettext.py 30452 2005-05-20 05:13:10Z fdrake $ """ import sys import unittest from StringIO import StringIO from zope.tal.htmltalparser import HTMLTALParser from zope.tal.talgettext import POTALInterpreter from zope.tal.talgettext import POEngine from zope.tal.tests import utils class test_POEngine(unittest.TestCase): """Test the PO engine functionality, which simply adds items to a catalog as .translate is called """ def test_translate(self): test_keys = ['foo', 'bar', 'blarf', 'washington'] engine = POEngine() engine.file = 'foo.pt' for key in test_keys: engine.translate(key, 'domain') for key in test_keys: self.failIf(key not in engine.catalog['domain'], "POEngine catalog does not properly store message ids" ) def test_dynamic_msgids(self): sample_source = """

Some dynamic text.

A link.

""" p = HTMLTALParser() p.parseString(sample_source) program, macros = p.getCode() engine = POEngine() engine.file = 'sample_source' POTALInterpreter(program, macros, engine, stream=StringIO(), metal=False)() msgids = [] for domain in engine.catalog.values(): msgids += domain.keys() msgids.sort() self.assertEquals(msgids, ['A link.', 'Some ${DYNAMIC_CONTENT} text.']) def test_suite(): suite = unittest.makeSuite(test_POEngine) return suite if __name__ == "__main__": errs = utils.run_suite(test_suite()) sys.exit(errs and 1 or 0) zope.tal-3.5.2/src/zope/tal/tests/input/0000755000175000017500000000000011336275656020042 5ustar anthonyanthonyzope.tal-3.5.2/src/zope/tal/tests/input/test05.xml0000644000175000017500000000025111273124226021670 0ustar anthonyanthony

This is the body of test5

zope.tal-3.5.2/src/zope/tal/tests/input/test24.html0000644000175000017500000000052411273124226022040 0ustar anthonyanthony zope.tal-3.5.2/src/zope/tal/tests/input/test31.html0000644000175000017500000000040711273124226022036 0ustar anthonyanthony

Your contact email address is recorded as user@host.com

zope.tal-3.5.2/src/zope/tal/tests/input/test22.xml0000644000175000017500000000035611273124226021675 0ustar anthonyanthony content omit replace zope.tal-3.5.2/src/zope/tal/tests/input/test29.html0000644000175000017500000000025311273124226022044 0ustar anthonyanthony
At the tone the time will be 2:32 pm... beep!
zope.tal-3.5.2/src/zope/tal/tests/input/test34.html0000644000175000017500000000036711273124226022046 0ustar anthonyanthony stuff more stuff stuff more stuff zope.tal-3.5.2/src/zope/tal/tests/input/test_sa2.xml0000644000175000017500000000032511273124226022272 0ustar anthonyanthony Simple test of source annotations

Foo!

zope.tal-3.5.2/src/zope/tal/tests/input/test08.html0000644000175000017500000000473311273124226022050 0ustar anthonyanthony

Some headline

This is the real contents of the bottom right slot.

It is supposed to contain a lot of text. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb.

It is supposed to contain a lot of text. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb.

It is supposed to contain a lot of text. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb.

zope.tal-3.5.2/src/zope/tal/tests/input/test27.html0000644000175000017500000000030211273124226022035 0ustar anthonyanthony

Your contact email address is recorded as user@host.com

zope.tal-3.5.2/src/zope/tal/tests/input/test26.html0000644000175000017500000000020511273124226022036 0ustar anthonyanthony Job #NN zope.tal-3.5.2/src/zope/tal/tests/input/test21.html0000644000175000017500000000023611273124226022035 0ustar anthonyanthony was born in . zope.tal-3.5.2/src/zope/tal/tests/input/test02.html0000644000175000017500000000714411273124226022041 0ustar anthonyanthony sample1 a simple invoice
01786 2000-03-17 55377 2000-03-15 GJ03405 DAVE 1 2000-03-17 K5211(34) 23 23
SHIPWRIGHT RESTAURANTS LIMITED 125 NORTH SERVICE ROAD W WESTLAKE ACCESS NORTH BAY L8B1O5 ONTARIO CANADA ATTN: PAULINE DEGRASSI 1 CS DM 5309 #1013 12 OZ.MUNICH STEIN 37.72 37.72 6 DZ ON 6420 PROVINCIAL DINNER FORK 17.98 107.88 72 EA JR20643 PLASTIC HANDLED STEAK KNIFE .81 58.32 6 DZ ON 6410 PROVINCIAL TEASPOONS 12.16 72.96 0 DZ ON 6411 PROVINCIAL RD BOWL SPOON 6 17.98 0.00 1 EA DO 3218 34 OZ DUAL DIAL SCALE AM3218 70.00 5.0 66.50 1 CS DM 195 20 OZ.BEER PUB GLASS 55.90 55.90 399.28 3.50 23.75 29.61 33.84 33.84 486.48
zope.tal-3.5.2/src/zope/tal/tests/input/test22.html0000644000175000017500000000024411273124226022035 0ustar anthonyanthony Jim was born in the USA. zope.tal-3.5.2/src/zope/tal/tests/input/test_domain.html0000644000175000017500000000031211273124226023214 0ustar anthonyanthony
Replace this This is a translated string And another translated string
zope.tal-3.5.2/src/zope/tal/tests/input/test02.xml0000644000175000017500000000717311273124226021677 0ustar anthonyanthony sample1 a simple invoice
01786 2000-03-17 55377 2000-03-15 GJ03405 DAVE 1 2000-03-17 K5211(34) 23 23
SHIPWRIGHT RESTAURANTS LIMITED 125 NORTH SERVICE ROAD W WESTLAKE ACCESS NORTH BAY L8B1O5 ONTARIO CANADA ATTN: PAULINE DEGRASSI 1 CS DM 5309 #1013 12 OZ.MUNICH STEIN 37.72 37.72 6 DZ ON 6420 PROVINCIAL DINNER FORK 17.98 107.88 72 EA JR20643 PLASTIC HANDLED STEAK KNIFE .81 58.32 6 DZ ON 6410 PROVINCIAL TEASPOONS 12.16 72.96 0 DZ ON 6411 PROVINCIAL RD BOWL SPOON 6 17.98 0.00 1 EA DO 3218 34 OZ DUAL DIAL SCALE AM3218 70.00 5.0 66.50 1 CS DM 195 20 OZ.BEER PUB GLASS 55.90 55.90 399.28 3.50 23.75 29.61 33.84 33.84 486.48
zope.tal-3.5.2/src/zope/tal/tests/input/pnome_template.pt0000644000175000017500000000107511273124226023405 0ustar anthonyanthony Title here
"The early bird gets the worm, but the second mouse gets the cheese."
Preferences...
Content here
page footer
zope.tal-3.5.2/src/zope/tal/tests/input/test17.xml0000644000175000017500000000050011273124226021670 0ustar anthonyanthony No No Yes No Yes zope.tal-3.5.2/src/zope/tal/tests/input/test_metal9.html0000644000175000017500000000072211273124226023145 0ustar anthonyanthony
Default for macro1
Macro 2's slot 1 decoration Default for macro2
Custom slot1
zope.tal-3.5.2/src/zope/tal/tests/input/test08.xml0000644000175000017500000000476111273124226021705 0ustar anthonyanthony

Some headline

This is the real contents of the bottom right slot.

It is supposed to contain a lot of text. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb.

It is supposed to contain a lot of text. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb.

It is supposed to contain a lot of text. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb.

zope.tal-3.5.2/src/zope/tal/tests/input/test04.xml0000644000175000017500000000133211273124226021670 0ustar anthonyanthony
  • 1

use-macro fill-slot

use-macro

define-slot

zope.tal-3.5.2/src/zope/tal/tests/input/test09.xml0000644000175000017500000000072211273124226021677 0ustar anthonyanthony

Just a bunch of text.

more text...

  • first item
  • second item
    1. second list, first item
    2. second list, second item
      term 1
      term 2
      definition
  • Now let's have a paragraph...

    My Paragraph

  • And a table in a list item:
zope.tal-3.5.2/src/zope/tal/tests/input/test_metal1.html0000644000175000017500000000216211273124226023135 0ustar anthonyanthony AAA INNER BBB AAA INNER BBB OUTERSLOT AAA INNER INNERSLOT BBB OUTERSLOT INNERSLOT INSLOT zope.tal-3.5.2/src/zope/tal/tests/input/test21.xml0000644000175000017500000000054211273124226021671 0ustar anthonyanthony was born in . zope.tal-3.5.2/src/zope/tal/tests/input/test_metal6.html0000644000175000017500000000022011273124226023133 0ustar anthonyanthony Z3 UI zope.tal-3.5.2/src/zope/tal/tests/input/test32.html0000644000175000017500000000024411273124226022036 0ustar anthonyanthony was born in . zope.tal-3.5.2/src/zope/tal/tests/input/test_failed_attr_translation.html0000644000175000017500000000010211273124226026636 0ustar anthonyanthony zope.tal-3.5.2/src/zope/tal/tests/input/test07.html0000644000175000017500000000044511273124226022043 0ustar anthonyanthony
Top Left Top Right
Bottom left Bottom Right
zope.tal-3.5.2/src/zope/tal/tests/input/test13.html0000644000175000017500000000014011273124226022030 0ustar anthonyanthonyHere's a stray greater than: > zope.tal-3.5.2/src/zope/tal/tests/input/test37.html0000644000175000017500000000015511273124226022044 0ustar anthonyanthony Test zope.tal-3.5.2/src/zope/tal/tests/input/test36.html0000644000175000017500000000041211273124226022037 0ustar anthonyanthony some text zope.tal-3.5.2/src/zope/tal/tests/input/acme_template.pt0000644000175000017500000000061411273124226023172 0ustar anthonyanthony ACME Look and Feel
Copyright 2004 Acme Inc.
Standard disclaimers apply.
zope.tal-3.5.2/src/zope/tal/tests/input/test05.html0000644000175000017500000000022211273124226022032 0ustar anthonyanthony

This is the body of test5

zope.tal-3.5.2/src/zope/tal/tests/input/test01.html0000644000175000017500000000266011273124226022036 0ustar anthonyanthony dadada

This title is not displayed

Title

 &HarryPotter;

foo bar

  • Car Name
python python zope.tal-3.5.2/src/zope/tal/tests/input/test23.html0000644000175000017500000000012111273124226022030 0ustar anthonyanthony2:32 pm zope.tal-3.5.2/src/zope/tal/tests/input/test07.xml0000644000175000017500000000047411273124226021701 0ustar anthonyanthony
Top Left Top Right
Bottom left Bottom Right
zope.tal-3.5.2/src/zope/tal/tests/input/test_sa1.html0000644000175000017500000000013311273124226022432 0ustar anthonyanthony Simple test of source annotations

Foo!

zope.tal-3.5.2/src/zope/tal/tests/input/test28.html0000644000175000017500000000033511273124226022044 0ustar anthonyanthony

Your contact email address is recorded as user@host.com

zope.tal-3.5.2/src/zope/tal/tests/input/test35.html0000644000175000017500000000032011273124226022034 0ustar anthonyanthony

name

zope.tal-3.5.2/src/zope/tal/tests/input/test_sa1.xml0000644000175000017500000000016211273124226022270 0ustar anthonyanthony Simple test of source annotations

Foo!

zope.tal-3.5.2/src/zope/tal/tests/input/test30.html0000644000175000017500000000035011273124226022032 0ustar anthonyanthony

Your contact email address is recorded as user@host.com

zope.tal-3.5.2/src/zope/tal/tests/input/test33.html0000644000175000017500000000006211273124226022035 0ustar anthonyanthonydon't translate me zope.tal-3.5.2/src/zope/tal/tests/input/test10.html0000644000175000017500000000502111273124226022030 0ustar anthonyanthony

Some headline

This is the real contents of the bottom right slot.


It is supposed to contain a lot of text. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb.

It is supposed to contain a lot of text. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb.

It is supposed to contain a lot of text. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb.



zope.tal-3.5.2/src/zope/tal/tests/input/test03.html0000644000175000017500000000062011273124226022032 0ustar anthonyanthony

outer variable x, first appearance inner variable x outer variable x, second appearance

zope.tal-3.5.2/src/zope/tal/tests/input/test_metal4.html0000644000175000017500000000027311273124226023141 0ustar anthonyanthony Z3 UI zope.tal-3.5.2/src/zope/tal/tests/input/test_sa2.html0000644000175000017500000000027611273124226022443 0ustar anthonyanthony Simple test of source annotations

Foo!

zope.tal-3.5.2/src/zope/tal/tests/input/test06.html0000644000175000017500000000023411273124226022036 0ustar anthonyanthony dummy body in test6 zope.tal-3.5.2/src/zope/tal/tests/input/test_sa4.html0000644000175000017500000000052011273124226022435 0ustar anthonyanthony

Some text on sa4 line 3.

This text on sa4 line 5 will disappear. Text from sa4 line 6 is filled into slot1. This text on sa4 line 7 will disappear.

This is some text on sa4 line 9.

zope.tal-3.5.2/src/zope/tal/tests/input/test25.html0000644000175000017500000000005511273124226022040 0ustar anthonyanthony zope.tal-3.5.2/src/zope/tal/tests/input/__init__.py0000644000175000017500000000007511273124226022137 0ustar anthonyanthony# # This file is necessary to make this directory a package. zope.tal-3.5.2/src/zope/tal/tests/input/test11.html0000644000175000017500000000123711273124226022036 0ustar anthonyanthony

dummy text

p

rule
zope.tal-3.5.2/src/zope/tal/tests/input/test19.html0000644000175000017500000000025111273124226022041 0ustar anthonyanthonyReplace this This is a translated string And another translated string zope.tal-3.5.2/src/zope/tal/tests/input/test11.xml0000644000175000017500000000072111273124226021667 0ustar anthonyanthony

dummy text

zope.tal-3.5.2/src/zope/tal/tests/input/test_metal8.html0000644000175000017500000000040411273124226023141 0ustar anthonyanthony
Default body
Filled-in body
zope.tal-3.5.2/src/zope/tal/tests/input/test_metal3.html0000644000175000017500000000011411273124226023132 0ustar anthonyanthonyShould not get attr in metal zope.tal-3.5.2/src/zope/tal/tests/input/test16.html0000644000175000017500000000014311273124226022036 0ustar anthonyanthonyblah, blah zope.tal-3.5.2/src/zope/tal/tests/input/test03.xml0000644000175000017500000000064711273124226021677 0ustar anthonyanthony

outer variable x, first appearance inner variable x outer variable x, second appearance

zope.tal-3.5.2/src/zope/tal/tests/input/test15.html0000644000175000017500000000101411273124226022033 0ustar anthonyanthony INNERSLOT inner-argument
OUTERSLOT
outer-argument
zope.tal-3.5.2/src/zope/tal/tests/input/test17.html0000644000175000017500000000032411273124226022040 0ustar anthonyanthonyNo No Yes No Yes zope.tal-3.5.2/src/zope/tal/tests/input/test18.xml0000644000175000017500000000124011273124226021673 0ustar anthonyanthony

Content

Content

Content

No

No

Yes

Yes

zope.tal-3.5.2/src/zope/tal/tests/input/test18.html0000644000175000017500000000101711273124226022041 0ustar anthonyanthony

Content

Content

Content

No

No

Yes

Yes

zope.tal-3.5.2/src/zope/tal/tests/input/test14.html0000644000175000017500000000031711273124226022037 0ustar anthonyanthony

zope.tal-3.5.2/src/zope/tal/tests/input/test20.xml0000644000175000017500000000042511273124226021670 0ustar anthonyanthony replaceable

content

zope.tal-3.5.2/src/zope/tal/tests/input/test_metal2.html0000644000175000017500000000021011273124226023126 0ustar anthonyanthony
OUTER INNER OUTER
zope.tal-3.5.2/src/zope/tal/tests/input/test14.xml0000644000175000017500000000044611273124226021676 0ustar anthonyanthony

zope.tal-3.5.2/src/zope/tal/tests/input/test09.html0000644000175000017500000000063311273124226022044 0ustar anthonyanthony

Just a bunch of text.

more text...

  • first item
  • second item
    1. second list, first item
    2. second list, second item
      term 1
      term 2
      definition
  • Now let's have a paragraph...

    My Paragraph

  • And a table in a list item:
zope.tal-3.5.2/src/zope/tal/tests/input/test16.xml0000644000175000017500000000025311273124226021674 0ustar anthonyanthony bar zope.tal-3.5.2/src/zope/tal/tests/input/test12.html0000644000175000017500000000122011273124226022027 0ustar anthonyanthony zope.tal-3.5.2/src/zope/tal/tests/input/test_sa3.xml0000644000175000017500000000110311273124226022266 0ustar anthonyanthony
This is macro1 on sa3 line 4. This is slot1 on sa3 line 5. This is the end of macro1 on sa3 line 6.

Some text on sa3 line 8.

This text on sa3 line 10 will disappear. Text from sa3 line 11 is filled into slot1. This text on sa3 line 12 will disappear.

This is some text on sa3 line 14.

zope.tal-3.5.2/src/zope/tal/tests/input/test19.xml0000644000175000017500000000037711273124226021706 0ustar anthonyanthony Replace this This is a translated string And another translated string zope.tal-3.5.2/src/zope/tal/tests/input/test01.xml0000644000175000017500000000270711273124226021674 0ustar anthonyanthony dadada

This title is not displayed

Title

 &HarryPotter;

foo bar

  • Car Name
python python zope.tal-3.5.2/src/zope/tal/tests/input/document_list.pt0000644000175000017500000000100111273124226023232 0ustar anthonyanthony Acme Document List

Documents

  • Rocket Science for Dummies
  • Birds for the Gourmet Chef
This document list is classified.
zope.tal-3.5.2/src/zope/tal/tests/input/test_metal7.html0000644000175000017500000000025011273124226023137 0ustar anthonyanthony zope.tal-3.5.2/src/zope/tal/tests/input/test06.xml0000644000175000017500000000026211273124226021673 0ustar anthonyanthony dummy body in test6 zope.tal-3.5.2/src/zope/tal/tests/input/test_sa3.html0000644000175000017500000000077011273124226022443 0ustar anthonyanthony
This is macro1 on sa3 line 3. This is slot1 on sa3 line 4. This is the end of macro1 on sa3 line 5.

Some text on sa3 line 7.

This text on sa3 line 9 will disappear. Text from sa3 line 10 is filled into slot1. This text on sa3 line 11 will disappear.

This is some text on sa3 line 13.

zope.tal-3.5.2/src/zope/tal/tests/input/test_metal5.html0000644000175000017500000000026111273124226023137 0ustar anthonyanthony Z3 UI zope.tal-3.5.2/src/zope/tal/tests/input/test04.html0000644000175000017500000000130311273124226022032 0ustar anthonyanthony
  • 1

use-macro fill-slot

use-macro

define-slot

zope.tal-3.5.2/src/zope/tal/tests/input/test20.html0000644000175000017500000000012111273124226022025 0ustar anthonyanthonyreplaceable

content

zope.tal-3.5.2/src/zope/tal/tests/test_talinterpreter.py0000644000175000017500000010264611273124226023353 0ustar anthonyanthony# -*- coding: ISO-8859-1 -*- ############################################################################## # # Copyright (c) 2001, 2002 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Tests for TALInterpreter. $Id: test_talinterpreter.py 99007 2009-04-08 12:35:42Z tseaver $ """ import os import sys import unittest from StringIO import StringIO from zope.tal.taldefs import METALError, I18NError, TAL_VERSION from zope.tal.taldefs import TALExpressionError from zope.tal.htmltalparser import HTMLTALParser from zope.tal.talparser import TALParser from zope.tal.talinterpreter import TALInterpreter from zope.tal.talgenerator import TALGenerator from zope.tal.dummyengine import DummyEngine from zope.tal.dummyengine import MultipleDomainsDummyEngine from zope.tal.dummyengine import DummyTranslationDomain from zope.tal.tests import utils from zope.i18nmessageid import Message class TestCaseBase(unittest.TestCase): def _compile(self, source, source_file=None): generator = TALGenerator(xml=0, source_file=source_file) parser = HTMLTALParser(generator) parser.parseString(source) program, macros = parser.getCode() return program, macros class MacroErrorsTestCase(TestCaseBase): def setUp(self): dummy, macros = self._compile('

Booh

') self.macro = macros['M'] self.engine = DummyEngine(macros) program, dummy = self._compile('

Bah

') self.interpreter = TALInterpreter(program, {}, self.engine) def tearDown(self): try: self.interpreter() except METALError: pass else: self.fail("Expected METALError") def test_mode_error(self): self.macro[1] = ("mode", "duh") def test_version_error(self): self.macro[0] = ("version", "duh") class MacroFunkyErrorTest(TestCaseBase): def test_div_in_p_using_macro(self): dummy, macros = self._compile('

Booh

') engine = DummyEngine(macros) program, dummy = self._compile( '

foo

') interpreter = TALInterpreter(program, {}, engine) output = interpreter() self.assertEqual(output, '

foo

') class MacroExtendTestCase(TestCaseBase): def setUp(self): s = self._read(('input', 'pnome_template.pt')) self.pnome_program, pnome_macros = self._compile(s) s = self._read(('input', 'acme_template.pt')) self.acme_program, acme_macros = self._compile(s) s = self._read(('input', 'document_list.pt')) self.doclist_program, doclist_macros = self._compile(s) macros = { 'pnome_macros_page': pnome_macros['page'], 'acme_macros_page': acme_macros['page'], } self.engine = DummyEngine(macros) def _read(self, path): dir = os.path.dirname(__file__) fn = os.path.join(dir, *path) f = open(fn) data = f.read() f.close() return data def test_preview_acme_template(self): # An ACME designer is previewing the ACME design. For the # purposes of this use case, extending a macro should act the # same as using a macro. result = StringIO() interpreter = TALInterpreter( self.acme_program, {}, self.engine, stream=result) interpreter() actual = result.getvalue().strip() expected = self._read(('output', 'acme_template.html')).strip() self.assertEqual(actual, expected) def test_preview_acme_template_source(self): # Render METAL attributes in acme_template result = StringIO() interpreter = TALInterpreter( self.acme_program, {}, self.engine, stream=result, tal=False) interpreter() actual = result.getvalue().strip() expected = self._read(('output', 'acme_template_source.html')).strip() self.assertEqual(actual, expected) class I18NCornerTestCaseBase(TestCaseBase): def factory(self, msgid, default, mapping={}): raise NotImplementedError("abstract method") def setUp(self): self.engine = DummyEngine() # Make sure we'll translate the msgid not its unicode representation self.engine.setLocal('foo', self.factory('FoOvAlUe${empty}', 'default', {'empty': ''})) self.engine.setLocal('bar', 'BaRvAlUe') def _check(self, program, expected): result = StringIO() self.interpreter = TALInterpreter(program, {}, self.engine, stream=result) self.interpreter() self.assertEqual(expected, result.getvalue()) def test_simple_messageid_translate(self): # This test is mainly here to make sure our DummyEngine works # correctly. program, macros = self._compile( '') self._check(program, 'FOOVALUE') program, macros = self._compile( '') self._check(program, 'FOOVALUE') # i18n messages defined in Python are translated automatically # (no i18n:translate necessary) program, macros = self._compile( '') self._check(program, 'FOOVALUE') program, macros = self._compile( '') self._check(program, 'FOOVALUE') def test_attributes_translation(self): program, macros = self._compile( '') self._check(program, '') program, macros = self._compile( '') self._check(program, '') program, macros = self._compile( '') self._check(program, '') # i18n messages defined in Python are translated automatically # (no i18n:attributes necessary) program, macros = self._compile( '') self._check(program, '') def test_text_variable_translate(self): program, macros = self._compile( '') self._check(program, 'BaRvAlUe') program, macros = self._compile( '') self._check(program, 'BARVALUE') program, macros = self._compile( '') self._check(program, 'BARVALUE') def test_text_translate(self): program, macros = self._compile( '') self._check(program, 'BaR') program, macros = self._compile( '') self._check(program, 'BAR') program, macros = self._compile( '') self._check(program, 'BAR') def test_structure_text_variable_translate(self): program, macros = self._compile( '') self._check(program, 'BaRvAlUe') program, macros = self._compile( '') self._check(program, 'BARVALUE') program, macros = self._compile( '') self._check(program, 'BARVALUE') # i18n messages defined in Python are translated automatically # (no i18n:translate necessary) program, macros = self._compile( '') self._check(program, 'FOOVALUE') program, macros = self._compile( '') self._check(program, 'FOOVALUE') def test_structure_text_translate(self): program, macros = self._compile( '') self._check(program, 'BaR') program, macros = self._compile( '') self._check(program, 'BAR') program, macros = self._compile( '') self._check(program, 'BAR') def test_replace_with_messageid_and_i18nname(self): program, macros = self._compile( '
' '' '
') self._check(program, '
FOOVALUE
') def test_pythonexpr_replace_with_messageid_and_i18nname(self): program, macros = self._compile( '
' '' '
') self._check(program, '
FOOVALUE
') def test_structure_replace_with_messageid_and_i18nname(self): program, macros = self._compile( '
' '' '
') self._check(program, '
FOOVALUE
') def test_complex_replace_with_messageid_and_i18nname(self): program, macros = self._compile( '
' '' '' '' '
') self._check(program, '
FOOVALUE
') def test_content_with_messageid_and_i18nname(self): program, macros = self._compile( '
' '' '
') self._check(program, '
FOOVALUE
') def test_content_with_messageid_and_i18nname_and_i18ntranslate(self): # Let's tell the user this is incredibly silly! self.assertRaises( I18NError, self._compile, '') def test_content_with_explicit_messageid(self): # Let's tell the user this is incredibly silly! self.assertRaises( I18NError, self._compile, '') def test_content_with_plaintext_and_i18nname_and_i18ntranslate(self): # Let's tell the user this is incredibly silly! self.assertRaises( I18NError, self._compile, 'green') def test_translate_static_text_as_dynamic(self): program, macros = self._compile( '
This is text for ' '.' '
') self._check(program, '
THIS IS TEXT FOR BaRvAlUe.
') program, macros = self._compile( '
This is text for ' '.' '
') self._check(program, '
THIS IS TEXT FOR BARVALUE.
') def test_translate_static_text_as_dynamic_from_bytecode(self): program = [('version', TAL_VERSION), ('mode', 'html'), ('setPosition', (1, 0)), ('beginScope', {'i18n:translate': ''}), ('startTag', ('div', [('i18n:translate', '', 'i18n')])), ('insertTranslation', ('', [('rawtextOffset', ('This is text for ', 17)), ('setPosition', (1, 40)), ('beginScope', {'tal:content': 'bar', 'i18n:name': 'bar_name', 'i18n:translate': ''}), ('i18nVariable', ('bar_name', [('startTag', ('span', [('i18n:translate', '', 'i18n'), ('tal:content', 'bar', 'tal'), ('i18n:name', 'bar_name', 'i18n')])), ('insertTranslation', ('', [('insertText', ('$bar$', []))])), ('rawtextOffset', ('
', 7))], None, 0)), ('endScope', ()), ('rawtextOffset', ('.', 1))])), ('endScope', ()), ('rawtextOffset', ('
', 6)) ] self._check(program, '
THIS IS TEXT FOR BARVALUE.
') def test_for_correct_msgids(self): self.engine.translationDomain.clearMsgids() result = StringIO() #GChapelle: #I have the feeling the i18n:translate with the i18n:name is wrong # #program, macros = self._compile( # '
This is text for ' # '.
') program, macros = self._compile( '
This is text for ' '.
') self.interpreter = TALInterpreter(program, {}, self.engine, stream=result) self.interpreter() msgids = self.engine.translationDomain.getMsgids('default') msgids.sort() self.assertEqual(1, len(msgids)) self.assertEqual('This is text for ${bar_name}.', msgids[0][0]) self.assertEqual({'bar_name': 'BaRvAlUe'}, msgids[0][1]) self.assertEqual( '
THIS IS TEXT FOR BaRvAlUe.
', result.getvalue()) def test_for_correct_msgids_translate_name(self): self.engine.translationDomain.clearMsgids() result = StringIO() program, macros = self._compile( '
This is text for ' '.
') self.interpreter = TALInterpreter(program, {}, self.engine, stream=result) self.interpreter() msgids = self.engine.translationDomain.getMsgids('default') msgids.sort() self.assertEqual(2, len(msgids)) self.assertEqual('This is text for ${bar_name}.', msgids[1][0]) self.assertEqual({'bar_name': 'BARVALUE'}, msgids[1][1]) self.assertEqual( '
THIS IS TEXT FOR BARVALUE.
', result.getvalue()) def test_i18ntranslate_i18nname_and_attributes(self): # Test for Issue 301: Bug with i18n:name and i18n:translate # on the same element self.engine.translationDomain.clearMsgids() result = StringIO() program, macros = self._compile( '

' 'Some static text and a link text.

') self.interpreter = TALInterpreter(program, {}, self.engine, stream=result) self.interpreter() msgids = self.engine.translationDomain.getMsgids('default') msgids.sort() self.assertEqual(2, len(msgids)) self.assertEqual('Some static text and a ${link}.', msgids[0][0]) self.assertEqual({'link': 'LINK TEXT'}, msgids[0][1]) self.assertEqual('link text', msgids[1][0]) self.assertEqual( '

SOME STATIC TEXT AND A LINK TEXT.

', result.getvalue()) def test_for_raw_msgids(self): # Test for Issue 314: i18n:translate removes line breaks from #
...
contents # HTML mode self.engine.translationDomain.clearMsgids() result = StringIO() program, macros = self._compile( '
This is text\n' ' \tfor\n div.
' '
 This is text\n'
            ' \tfor\n pre. 
') self.interpreter = TALInterpreter(program, {}, self.engine, stream=result) self.interpreter() msgids = self.engine.translationDomain.getMsgids('default') msgids.sort() self.assertEqual(2, len(msgids)) self.assertEqual(' This is text\n \tfor\n pre. ', msgids[0][0]) self.assertEqual('This is text for div.', msgids[1][0]) self.assertEqual( '
THIS IS TEXT FOR DIV.
' '
 THIS IS TEXT\n \tFOR\n PRE. 
', result.getvalue()) # XML mode self.engine.translationDomain.clearMsgids() result = StringIO() parser = TALParser() parser.parseString( '\n' '
 This is text\n'
            ' \tfor\n barvalue. 
') program, macros = parser.getCode() self.interpreter = TALInterpreter(program, {}, self.engine, stream=result) self.interpreter() msgids = self.engine.translationDomain.getMsgids('default') msgids.sort() self.assertEqual(1, len(msgids)) self.assertEqual('This is text for barvalue.', msgids[0][0]) self.assertEqual( '\n' '
THIS IS TEXT  FOR BARVALUE.
', result.getvalue()) def test_raw_msgids_and_i18ntranslate_i18nname(self): self.engine.translationDomain.clearMsgids() result = StringIO() program, macros = self._compile( '
This is text\n \tfor\n' '
 \tbar\n 
.
') self.interpreter = TALInterpreter(program, {}, self.engine, stream=result) self.interpreter() msgids = self.engine.translationDomain.getMsgids('default') msgids.sort() self.assertEqual(2, len(msgids)) self.assertEqual(' \tbar\n ', msgids[0][0]) self.assertEqual('This is text for ${bar}.', msgids[1][0]) self.assertEqual({'bar': '
 \tBAR\n 
'}, msgids[1][1]) self.assertEqual( u'
THIS IS TEXT FOR
 \tBAR\n 
.
', result.getvalue()) def test_for_handling_unicode_vars(self): # Make sure that non-ASCII Unicode is substituted correctly. # http://collector.zope.org/Zope3-dev/264 program, macros = self._compile( "
" "Foo
") self._check(program, u"
FOO \u00C0
") class I18NCornerTestCaseMessage(I18NCornerTestCaseBase): def factory(self, msgid, default=None, mapping={}, domain=None): return Message(msgid, domain=domain, default=default, mapping=mapping) class UnusedExplicitDomainTestCase(I18NCornerTestCaseMessage): def setUp(self): # MultipleDomainsDummyEngine is a Engine # where default domain transforms to uppercase self.engine = MultipleDomainsDummyEngine() self.engine.setLocal('foo', self.factory('FoOvAlUe${empty}', 'default', {'empty': ''})) self.engine.setLocal('bar', 'BaRvAlUe') self.engine.setLocal('baz', self.factory('BaZvAlUe', 'default', {})) # Message ids with different domains self.engine.setLocal('toupper', self.factory('ToUpper', 'default', {})) self.engine.setLocal('tolower', self.factory('ToLower', 'default', {}, domain='lower')) def test_multiple_domains(self): program, macros = self._compile( '
') self._check(program, '
TOUPPER
') program, macros = self._compile( '
') self._check(program, '
tolower
') program, macros = self._compile( '
') self._check(program, '
TOUPPER
') program, macros = self._compile( '
') self._check(program, '
tolower
') program, macros = self._compile( '
') self._check(program, '
TOUPPER
') program, macros = self._compile( '
') self._check(program, '
tolower
') def test_unused_explicit_domain(self): #a_very_explicit_domain_setup_by_template_developer_that_wont_be_taken_into_account_by_the_ZPT_engine #is a domain that transforms to lowercase self.engine.setLocal('othertolower', self.factory('OtherToLower', 'a_very_explicit_domain_setup_by_template_developer_that_wont_be_taken_into_account_by_the_ZPT_engine', {}, domain='lower')) program, macros = self._compile( '
') self._check(program, '
othertolower
') #takes domain into account for strings program, macros = self._compile( '
') self._check(program, '
tolower
') #but not for messageids program, macros = self._compile( '
') self._check(program, '
BAZVALUE
') class ScriptTestCase(TestCaseBase): def setUp(self): self.engine = DummyEngine() def _check(self, program, expected): result = StringIO() self.interpreter = TALInterpreter(program, {}, self.engine, stream=result) self.interpreter() self.assertEqual(expected, result.getvalue()) def test_simple(self): program, macros = self._compile( '

print "hello"

') self._check(program, '

hello\n

') def test_script_and_tal_block(self): program, macros = self._compile( '\n' ' global x\n' ' x = 1\n' '\n' '') self._check(program, '\n1') self.assertEqual(self.engine.codeGlobals['x'], 1) def test_script_and_tal_block_having_inside_print(self): program, macros = self._compile( '\n' ' print "hello"' '') self._check(program, 'hello\n') def test_script_and_omittag(self): program, macros = self._compile( '

\n' ' print "hello"' '

') self._check(program, 'hello\n') def test_script_and_inside_tags(self): program, macros = self._compile( '

\n' ' print "hello"' '

') self._check(program, 'hello\n') def test_script_and_inside_tags_with_tal(self): program, macros = self._compile( '

') self._check(program, 'hello\n') def test_html_script(self): program, macros = self._compile( '') self._check(program, 'Hello world!\n') def test_html_script_and_javascript(self): program, macros = self._compile( '') self._check(program, '', [ ('setPosition', (1, 0)), ('beginScope', {}), ('optTag', ('script', '', None, 0, [('rawtextOffset', ('', [ ('rawtextOffset', ('', 44)) ]) def test_attributes_1(self): self._run_check("" "link", [ ('setPosition', (1, 0)), ('beginScope', {'tal:attributes': 'href string:http://www.zope.org; x string:y', 'name': 'bar', 'href': 'foo'}), ('startTag', ('a', [('href', 'foo', 'replace', '$string:http://www.zope.org$', 0, None), ('name', 'name="bar"'), ('tal:attributes', 'href string:http://www.zope.org; x string:y', 'tal'), ('x', None, 'insert', '$string:y$', 0, None)])), ('endScope', ()), rawtext('link'), ]) def test_attributes_2(self): self._run_check("

duh

", [ ('setPosition', (1, 0)), ('beginScope', {'tal:attributes': 'src string:foo.png', 'tal:replace': 'structure string:'}), ('optTag', ('p', '', None, 0, [('startTag', ('p', [('tal:replace', 'structure string:', 'tal'), ('tal:attributes', 'src string:foo.png', 'tal')]))], [('insertStructure', ('$string:$', {'src': ('$string:foo.png$', False, None)}, [('rawtextOffset', ('duh', 3))]))])), ('endScope', ())]) def test_on_error_1(self): self._run_check("

okay

", [ ('setPosition', (1, 0)), ('beginScope', {'tal:content': 'notHere', 'tal:on-error': 'string:error'}), ('onError', ([('startTag', ('p', [('tal:on-error', 'string:error', 'tal'), ('tal:content', 'notHere', 'tal')])), ('insertText', ('$notHere$', [rawtext('okay')])), rawtext('

')], [('startTag', ('p', [('tal:on-error', 'string:error', 'tal'), ('tal:content', 'notHere', 'tal')])), ('insertText', ('$string:error$', [])), rawtext('

')])), ('endScope', ()), ]) def test_on_error_2(self): self._run_check("

okay

", [ ('setPosition', (1, 0)), ('beginScope', {'tal:replace': 'notHere', 'tal:on-error': 'string:error'}), ('onError', ([('optTag', ('p', '', None, 0, [('startTag', ('p', [('tal:on-error', 'string:error', 'tal'), ('tal:replace', 'notHere', 'tal')]))], [('insertText', ('$notHere$', [('rawtextOffset', ('okay', 4))]))]))], [('startTag', ('p', [('tal:on-error', 'string:error', 'tal'), ('tal:replace', 'notHere', 'tal')])), ('insertText', ('$string:error$', [])), ('rawtextOffset', ('

', 4))])), ('endScope', ()), ]) def test_dup_attr(self): self._should_error("") self._should_error("", taldefs.METALError) def test_tal_errors(self): self._should_error("

") self._should_error("

") self._should_error("

") self._should_error("

") self._should_error("

") for tag in htmltalparser.EMPTY_HTML_TAGS: self._should_error("<%s tal:content='string:foo'>" % tag) def test_metal_errors(self): exc = taldefs.METALError self._should_error(2*"

xxx

", exc) self._should_error("" + 2*"

" + "", exc) self._should_error("

", exc) self._should_error("

", exc) def test_extend_macro_errors(self): exc = taldefs.METALError # extend-macro requires define-macro: self._should_error("

xxx

", exc) # extend-macro prevents use-macro: self._should_error("

xxx

", exc) # use-macro doesn't co-exist with define-macro: self._should_error("

xxx

", exc) # # I18N test cases # def test_i18n_attributes(self): self._run_check("foo", [ ('setPosition', (1, 0)), ('beginScope', {'alt': 'foo', 'i18n:attributes': 'alt'}), ('startTag', ('img', [('alt', 'foo', 'replace', None, 1, None), ('i18n:attributes', 'alt', 'i18n')])), ('endScope', ()), ]) self._run_check("foo", [ ('setPosition', (1, 0)), ('beginScope', {'alt': 'foo', 'i18n:attributes': 'alt foo ; bar'}), ('startTag', ('img', [('alt', 'foo', 'replace', None, 1, 'foo'), ('i18n:attributes', 'alt foo ; bar', 'i18n'), ('bar', None, 'insert', None, 1, None)])), ('endScope', ()), ]) def test_i18n_name_bad_name(self): self._should_error("") self._should_error("") def test_i18n_attributes_repeated_attr(self): self._should_error("") self._should_error("") def test_i18n_translate(self): # input/test19.html self._run_check('''\ Replace this This is a translated string And another translated string ''', [ ('setPosition', (1, 0)), ('beginScope', {'i18n:translate': ''}), ('startTag', ('span', [('i18n:translate', '', 'i18n')])), ('insertTranslation', ('', [('rawtextOffset', ('Replace this', 12))])), ('rawtextBeginScope', ('\n', 0, (2, 0), 1, {'i18n:translate': 'msgid'})), ('startTag', ('span', [('i18n:translate', 'msgid', 'i18n')])), ('insertTranslation', ('msgid', [('rawtextColumn', ('This is a\ntranslated string', 17))])), ('rawtextBeginScope', ('\n', 0, (4, 0), 1, {'i18n:translate': ''})), ('startTag', ('span', [('i18n:translate', '', 'i18n')])), ('insertTranslation', ('', [('rawtextColumn', ('And another\ntranslated string', 17))])), ('endScope', ()), ('rawtextColumn', ('
\n', 0))]) def test_i18n_translate_with_nested_tal(self): self._run_check('''\ replaceable

content

''', [ ('setPosition', (1, 0)), ('beginScope', {'i18n:translate': ''}), ('startTag', ('span', [('i18n:translate', '', 'i18n')])), ('insertTranslation', ('', [('rawtextOffset', ('replaceable ', 12)), ('setPosition', (1, 36)), ('beginScope', {'tal:replace': 'str:here'}), ('optTag', ('p', '', None, 0, [('startTag', ('p', [('tal:replace', 'str:here', 'tal')]))], [('insertText', ('$str:here$', [('rawtextOffset', ('content', 7))]))])), ('endScope', ())])), ('endScope', ()), ('rawtextColumn', ('\n', 0)) ]) def test_i18n_name(self): # input/test21.html self._run_check('''\ was born in . ''', [ ('setPosition', (1, 0)), ('beginScope', {'i18n:translate': ''}), ('startTag', ('span', [('i18n:translate', '', 'i18n')])), ('insertTranslation', ('', [('rawtextBeginScope', ('\n ', 2, (2, 2), 0, {'i18n:name': 'name', 'tal:replace': 'str:Lomax'})), ('i18nVariable', ('name', [('optTag', ('span', '', None, 1, [('startEndTag', ('span', [('tal:replace', 'str:Lomax', 'tal'), ('i18n:name', 'name', 'i18n')]))], [('insertText', ('$str:Lomax$', []))]))], None, 0)), ('rawtextBeginScope', (' was born in\n ', 2, (3, 2), 1, {'i18n:name': 'country', 'tal:replace': 'str:Antarctica'})), ('i18nVariable', ('country', [('optTag', ('span', '', None, 1, [('startEndTag', ('span', [('tal:replace', 'str:Antarctica', 'tal'), ('i18n:name', 'country', 'i18n')]))], [('insertText', ('$str:Antarctica$', []))]))], None, 0)), ('endScope', ()), ('rawtextColumn', ('.\n', 0))])), ('endScope', ()), ('rawtextColumn', ('\n', 0)) ]) def test_i18n_name_with_content(self): self._run_check('
This is text for ' '.' '
', [ ('setPosition', (1, 0)), ('beginScope', {'i18n:translate': ''}), ('startTag', ('div', [('i18n:translate', '', 'i18n')])), ('insertTranslation', ('', [('rawtextOffset', ('This is text for ', 17)), ('setPosition', (1, 40)), ('beginScope', {'tal:content': 'bar', 'i18n:name': 'bar_name', 'i18n:translate': ''}), ('i18nVariable', ('bar_name', [('startTag', ('span', [('i18n:translate', '', 'i18n'), ('tal:content', 'bar', 'tal'), ('i18n:name', 'bar_name', 'i18n')])), ('insertI18nText', ('$bar$', [])), ('rawtextOffset', ('
', 7))], None, 0)), ('endScope', ()), ('rawtextOffset', ('.', 1))])), ('endScope', ()), ('rawtextOffset', ('
', 6)) ]) def test_i18n_name_implicit_value(self): # input/test22.html self._run_check('''\ Jim was born in the USA. ''', [('setPosition', (1, 0)), ('beginScope', {'i18n:translate': ''}), ('startTag', ('span', [('i18n:translate', '', 'i18n')])), ('insertTranslation', ('', [('rawtextBeginScope', ('\n ', 2, (2, 2), 0, {'i18n:name': 'name', 'tal:omit-tag': ''})), ('i18nVariable', ('name', [('optTag', ('span', '', None, 0, [('startTag', ('span', [('tal:omit-tag', '', 'tal'), ('i18n:name', 'name', 'i18n')]))], [('rawtextOffset', ('Jim', 10))]))], None, 0)), ('rawtextBeginScope', (' was born in\n ', 2, (3, 2), 1, {'i18n:name': 'country', 'tal:omit-tag': ''})), ('i18nVariable', ('country', [('optTag', ('span', '', None, 0, [('startTag', ('span', [('tal:omit-tag', '', 'tal'), ('i18n:name', 'country', 'i18n')]))], [('rawtextOffset', ('the USA', 7))]))], None, 0)), ('endScope', ()), ('rawtextColumn', ('.\n', 0))])), ('endScope', ()), ('rawtextColumn', ('\n', 0)) ]) def test_i18n_context_domain(self): self._run_check("", [ ('setPosition', (1, 0)), ('beginI18nContext', {'domain': 'mydomain', 'source': None, 'target': None}), ('beginScope', {'i18n:domain': 'mydomain'}), ('startEndTag', ('span', [('i18n:domain', 'mydomain', 'i18n')])), ('endScope', ()), ('endI18nContext', ()), ]) def test_i18n_context_source(self): self._run_check("", [ ('setPosition', (1, 0)), ('beginI18nContext', {'source': 'en', 'domain': 'default', 'target': None}), ('beginScope', {'i18n:source': 'en'}), ('startEndTag', ('span', [('i18n:source', 'en', 'i18n')])), ('endScope', ()), ('endI18nContext', ()), ]) def test_i18n_context_source_target(self): self._run_check("", [ ('setPosition', (1, 0)), ('beginI18nContext', {'source': 'en', 'target': 'ru', 'domain': 'default'}), ('beginScope', {'i18n:source': 'en', 'i18n:target': 'ru'}), ('startEndTag', ('span', [('i18n:source', 'en', 'i18n'), ('i18n:target', 'ru', 'i18n')])), ('endScope', ()), ('endI18nContext', ()), ]) def test_i18n_context_in_define_slot(self): text = ("
" "
spam
" "
") self._run_check(text, [ ('setPosition', (1, 0)), ('useMacro', ('M', '$M$', {'S': [('startTag', ('div', [('metal:fill-slot', 'S', 'metal')])), rawtext('spam
')]}, [('beginI18nContext', {'domain': 'mydomain', 'source': None, 'target': None}), ('beginScope', {'i18n:domain': 'mydomain', 'metal:use-macro': 'M'}), ('startTag', ('div', [('metal:use-macro', 'M', 'metal'), ('i18n:domain', 'mydomain', 'i18n')])), ('setPosition', (1, 48)), ('fillSlot', ('S', [('startTag', ('div', [('metal:fill-slot', 'S', 'metal')])), rawtext('spam
')])), ('endScope', ()), rawtext('
'), ('endI18nContext', ())])), ]) def test_i18n_data(self): # input/test23.html self._run_check('''\ 2:32 pm ''', [ ('setPosition', (1, 0)), ('beginScope', {'i18n:translate': 'timefmt', 'i18n:data': 'here/currentTime'}), ('startTag', ('span', [('i18n:data', 'here/currentTime', 'i18n'), ('i18n:translate', 'timefmt', 'i18n')])), ('insertTranslation', ('timefmt', [('rawtextOffset', ('2:32 pm', 7))], '$here/currentTime$')), ('endScope', ()), ('rawtextColumn', ('\n', 0)) ]) def test_i18n_data_with_name(self): # input/test29.html self._run_check('''\
At the tone the time will be 2:32 pm... beep!
''', [('setPosition', (1, 0)), ('beginScope', {'i18n:translate': ''}), ('startTag', ('div', [('i18n:translate', '', 'i18n')])), ('insertTranslation', ('', [('rawtextBeginScope', ('At the tone the time will be\n', 0, (2, 0), 0, {'i18n:data': 'here/currentTime', 'i18n:name': 'time', 'i18n:translate': 'timefmt'})), ('i18nVariable', ('time', [('startTag', ('span', [('i18n:data', 'here/currentTime', 'i18n'), ('i18n:translate', 'timefmt', 'i18n'), ('i18n:name', 'time', 'i18n')])), ('insertTranslation', ('timefmt', [('rawtextOffset', ('2:32 pm', 7))], '$here/currentTime$')), ('rawtextOffset', ('', 7))], None, 0)), ('endScope', ()), ('rawtextOffset', ('... beep!', 9))])), ('endScope', ()), ('rawtextColumn', ('
\n', 0)) ]) def test_i18n_name_around_tal_content(self): # input/test28.html self._run_check('''\

Your contact email address is recorded as user@host.com

''', [('setPosition', (1, 0)), ('beginScope', {'i18n:translate': 'verify'}), ('startTag', ('p', [('i18n:translate', 'verify', 'i18n')])), ('insertTranslation', ('verify', [('rawtextBeginScope', ('Your contact email address is recorded as\n ', 4, (2, 4), 0, {'i18n:name': 'email', 'tal:omit-tag': ''})), ('i18nVariable', ('email', [('optTag', ('span', '', None, 0, [('startTag', ('span', [('tal:omit-tag', '', 'tal'), ('i18n:name', 'email', 'i18n')]))], [('rawtextBeginScope', ('\n ', 4, (3, 4), 0, {'href': 'mailto:user@example.com', 'tal:content': 'request/submitter'})), ('startTag', ('a', [('href', 'href="mailto:user@example.com"'), ('tal:content', 'request/submitter', 'tal')])), ('insertText', ('$request/submitter$', [('rawtextOffset', ('user@host.com', 13))])), ('endScope', ()), ('rawtextOffset', ('', 4))]))], None, 0)), ('endScope', ()), ('rawtextColumn', ('\n', 0))])), ('endScope', ()), ('rawtextColumn', ('

\n', 0)) ]) def test_i18n_name_with_tal_content(self): # input/test27.html self._run_check('''\

Your contact email address is recorded as user@host.com

''', [ ('setPosition', (1, 0)), ('beginScope', {'i18n:translate': 'verify'}), ('startTag', ('p', [('i18n:translate', 'verify', 'i18n')])), ('insertTranslation', ('verify', [('rawtextBeginScope', ('Your contact email address is recorded as\n ', 4, (2, 4), 0, {'href': 'mailto:user@example.com', 'i18n:name': 'email', 'tal:content': 'request/submitter'})), ('i18nVariable', ('email', [('startTag', ('a', [('href', 'href="mailto:user@example.com"'), ('tal:content', 'request/submitter', 'tal'), ('i18n:name', 'email', 'i18n')])), ('insertText', ('$request/submitter$', [('rawtextOffset', ('user@host.com', 13))])), ('rawtextOffset', ('', 4))], None, 0)), ('endScope', ()), ('rawtextColumn', ('\n', 0))])), ('endScope', ()), ('rawtextColumn', ('

\n', 0)) ]) def test_suite(): suite = unittest.makeSuite(HTMLTALParserTestCases) suite.addTest(unittest.makeSuite(METALGeneratorTestCases)) suite.addTest(unittest.makeSuite(TALGeneratorTestCases)) return suite if __name__ == "__main__": errs = utils.run_suite(test_suite()) sys.exit(errs and 1 or 0) zope.tal-3.5.2/src/zope/tal/tests/run.py0000644000175000017500000000300211273124226020036 0ustar anthonyanthony#! /usr/bin/env python ############################################################################## # # Copyright (c) 2001, 2002 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Run all tests. $Id: run.py 37557 2005-07-29 18:19:31Z benji_york $ """ import sys import unittest from zope.tal.tests import utils from zope.tal.tests import test_htmltalparser from zope.tal.tests import test_talinterpreter from zope.tal.tests import test_files from zope.tal.tests import test_sourcepos # TODO this code isn't picked up by the Zope 3 test framework.. def test_suite(): suite = unittest.TestSuite() suite.addTest(test_htmltalparser.test_suite()) if not utils.skipxml: import test_xmlparser suite.addTest(test_xmlparser.test_suite()) suite.addTest(test_talinterpreter.test_suite()) suite.addTest(test_files.test_suite()) suite.addTest(test_sourcepos.test_suite()) return suite def main(): return utils.run_suite(test_suite()) if __name__ == "__main__": errs = main() sys.exit(errs and 1 or 0) zope.tal-3.5.2/src/zope/tal/tests/markbench.py0000644000175000017500000001271511273124226021177 0ustar anthonyanthony#! /usr/bin/env python ############################################################################## # # Copyright (c) 2001, 2002 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Run benchmarks of TAL vs. DTML $Id: markbench.py 30139 2005-04-24 07:01:43Z hdima $ """ import warnings warnings.filterwarnings("ignore", category=DeprecationWarning) import os os.environ['NO_SECURITY'] = 'true' import getopt import sys import time from cStringIO import StringIO #from zope.documenttemplate.dt_html import HTMLFile from zope.tal.htmltalparser import HTMLTALParser from zope.tal.talinterpreter import TALInterpreter from zope.tal.dummyengine import DummyEngine def time_apply(f, args, kwargs, count): r = [None] * count for i in range(4): f(*args, **kwargs) t0 = time.clock() for i in r: pass t1 = time.clock() for i in r: f(*args, **kwargs) t = time.clock() - t1 - (t1 - t0) return t / count def time_zpt(fn, count): from zope.pagetemplate.pagetemplate import PageTemplate pt = PageTemplate() pt.write(open(fn).read()) return time_apply(pt.pt_render, (data,), {}, count) def time_tal(fn, count): p = HTMLTALParser() p.parseFile(fn) program, macros = p.getCode() engine = DummyEngine(macros) engine.globals = data tal = TALInterpreter(program, macros, engine, StringIO(), wrap=0, tal=1, strictinsert=0) return time_apply(tal, (), {}, count) def time_dtml(fn, count): html = HTMLFile(fn) return time_apply(html, (), data, count) def profile_zpt(fn, count, profiler): from zope.pagetemplate.pagetemplate import PageTemplate pt = PageTemplate() pt.write(open(fn).read()) for i in range(4): pt.pt_render(extra_context=data) r = [None] * count for i in r: profiler.runcall(pt.pt_render, 0, data) def profile_tal(fn, count, profiler): p = HTMLTALParser() p.parseFile(fn) program, macros = p.getCode() engine = DummyEngine(macros) engine.globals = data tal = TALInterpreter(program, macros, engine, StringIO(), wrap=0, tal=1, strictinsert=0) for i in range(4): tal() r = [None] * count for i in r: profiler.runcall(tal) # Figure out where the benchmark files are: try: fname = __file__ except NameError: fname = sys.argv[0] taldir = os.path.dirname(os.path.dirname(os.path.abspath(fname))) benchdir = os.path.join(taldir, 'benchmark') # Construct templates for the filenames: tal_fn = os.path.join(benchdir, 'tal%.2d.html') dtml_fn = os.path.join(benchdir, 'dtml%.2d.html') def compare(n, count, profiler=None, verbose=1): if verbose: t1 = int(time_zpt(tal_fn % n, count) * 1000 + 0.5) t2 = int(time_tal(tal_fn % n, count) * 1000 + 0.5) t3 = 'n/a' # int(time_dtml(dtml_fn % n, count) * 1000 + 0.5) print '%.2d: %10s %10s %10s' % (n, t1, t2, t3) if profiler: profile_tal(tal_fn % n, count, profiler) def main(count, profiler=None, verbose=1): n = 1 if verbose: print '##: %10s %10s %10s' % ('ZPT', 'TAL', 'DTML') while os.path.isfile(tal_fn % n) and os.path.isfile(dtml_fn % n): compare(n, count, profiler, verbose) n = n + 1 def get_signal_name(sig): import signal for name in dir(signal): if getattr(signal, name) == sig: return name return None data = {'x':'X', 'r2': range(2), 'r8': range(8), 'r64': range(64)} for i in range(10): data['x%s' % i] = 'X%s' % i if __name__ == "__main__": filename = "markbench.prof" profiler = None runtests = False verbose = True opts, args = getopt.getopt(sys.argv[1:], "pqt") for opt, arg in opts: if opt == "-p": import profile profiler = profile.Profile() elif opt == "-q": verbose = False elif opt == "-t": runtests = True if runtests: srcdir = os.path.dirname(os.path.dirname(taldir)) topdir = os.path.dirname(srcdir) pwd = os.getcwd() os.chdir(topdir) rc = os.spawnl(os.P_WAIT, sys.executable, sys.executable, "test.py", "zope.tal.tests") if rc > 0: # TODO: Failing tests don't cause test.py to report an # error; not sure why. ;-( sys.exit(rc) elif rc < 0: sig = -rc print >>sys.stderr, ( "Process exited, signal %d (%s)." % (sig, get_signal_name(sig) or "")) sys.exit(1) os.chdir(pwd) if len(args) >= 1: for arg in args: compare(int(arg), 25, profiler, verbose) else: main(25, profiler, verbose) if profiler is not None: profiler.dump_stats(filename) import pstats p = pstats.Stats(filename) p.strip_dirs() p.sort_stats('time', 'calls') try: p.print_stats(20) except IOError, e: if e.errno != errno.EPIPE: raise zope.tal-3.5.2/src/zope/tal/tests/__init__.py0000644000175000017500000000007511273124226021000 0ustar anthonyanthony# # This file is necessary to make this directory a package. zope.tal-3.5.2/src/zope/tal/tests/test_talparser.py0000644000175000017500000000250511273124226022275 0ustar anthonyanthony############################################################################## # # Copyright (c) 2004 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Tests for zope.tal.talparser. $Id: test_talparser.py 30139 2005-04-24 07:01:43Z hdima $ """ import unittest from zope.tal import talparser class TALParserTestCase(unittest.TestCase): def test_parser_returns_macros(self): parser = talparser.TALParser() parser.parseString( "\n" "\n" " \n" " some text\n" " \n" "") bytecode, macros = parser.getCode() self.assertEqual(macros.keys(), ["MACRO"]) def test_suite(): return unittest.makeSuite(TALParserTestCase) zope.tal-3.5.2/src/zope/tal/tests/output/0000755000175000017500000000000011336275656020243 5ustar anthonyanthonyzope.tal-3.5.2/src/zope/tal/tests/output/test05.xml0000644000175000017500000000014411273124226022072 0ustar anthonyanthony

This is the body of test5

zope.tal-3.5.2/src/zope/tal/tests/output/test24.html0000644000175000017500000000022211273124226022234 0ustar anthonyanthony zope.tal-3.5.2/src/zope/tal/tests/output/test31.html0000644000175000017500000000015311273124226022235 0ustar anthonyanthony

Your contact email address is recorded as aperson@dom.ain

zope.tal-3.5.2/src/zope/tal/tests/output/test22.xml0000644000175000017500000000012311273124226022066 0ustar anthonyanthony content omit replace zope.tal-3.5.2/src/zope/tal/tests/output/test29.html0000644000175000017500000000012411273124226022242 0ustar anthonyanthony
AT THE TONE THE TIME WILL BE 59 minutes after 6 PM... BEEP!
zope.tal-3.5.2/src/zope/tal/tests/output/test34.html0000644000175000017500000000012311273124226022235 0ustar anthonyanthony stuff foobar more stuff STUFF foobar MORE STUFF zope.tal-3.5.2/src/zope/tal/tests/output/test_sa2.xml0000644000175000017500000000062411273124226022475 0ustar anthonyanthony Simple test of source annotations

Foo!

zope.tal-3.5.2/src/zope/tal/tests/output/test08.html0000644000175000017500000000466411273124226022254 0ustar anthonyanthony
Top Left Top Right
Bottom left

Some headline

This is the real contents of the bottom right slot.

It is supposed to contain a lot of text. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb.

It is supposed to contain a lot of text. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb.

It is supposed to contain a lot of text. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb.

zope.tal-3.5.2/src/zope/tal/tests/output/test27.html0000644000175000017500000000014711273124226022245 0ustar anthonyanthony

Your contact email address is recorded as aperson@dom.ain

zope.tal-3.5.2/src/zope/tal/tests/output/test26.html0000644000175000017500000000004111273124226022235 0ustar anthonyanthony7 is the JOB NUMBER zope.tal-3.5.2/src/zope/tal/tests/output/test21.html0000644000175000017500000000005311273124226022233 0ustar anthonyanthonyLomax WAS BORN IN Antarctica. zope.tal-3.5.2/src/zope/tal/tests/output/acme_template.html0000644000175000017500000000063311273124226023715 0ustar anthonyanthony ACME Look and Feel
"The early bird gets the worm, but the second mouse gets the cheese."
Preferences...
Content here
Copyright 2004 Acme Inc.
Standard disclaimers apply.
zope.tal-3.5.2/src/zope/tal/tests/output/test02.html0000644000175000017500000000715611273124226022245 0ustar anthonyanthony sample1 a simple invoice
01786 2000-03-17 55377 2000-03-15 GJ03405 DAVE 1 2000-03-17 K5211(34) 23 23
SHIPWRIGHT RESTAURANTS LIMITED 125 NORTH SERVICE ROAD W WESTLAKE ACCESS NORTH BAY L8B1O5 ONTARIO CANADA ATTN: PAULINE DEGRASSI 1 CS DM 5309 #1013 12 OZ.MUNICH STEIN 37.72 37.72 6 DZ ON 6420 PROVINCIAL DINNER FORK 17.98 107.88 72 EA JR20643 PLASTIC HANDLED STEAK KNIFE .81 58.32 6 DZ ON 6410 PROVINCIAL TEASPOONS 12.16 72.96 0 DZ ON 6411 PROVINCIAL RD BOWL SPOON 6 17.98 0.00 1 EA DO 3218 34 OZ DUAL DIAL SCALE AM3218 70.00 5.0 66.50 1 CS DM 195 20 OZ.BEER PUB GLASS 55.90 55.90 399.28 3.50 23.75 29.61 33.84 33.84 486.48
zope.tal-3.5.2/src/zope/tal/tests/output/test22.html0000644000175000017500000000005511273124226022236 0ustar anthonyanthonyJim WAS BORN IN the USA. zope.tal-3.5.2/src/zope/tal/tests/output/test_domain.html0000644000175000017500000000014511273124226023421 0ustar anthonyanthony
replace this msgid and another translated string
zope.tal-3.5.2/src/zope/tal/tests/output/test02.xml0000644000175000017500000000720011273124226022067 0ustar anthonyanthony sample1 a simple invoice
01786 2000-03-17 55377 2000-03-15 GJ03405 DAVE 1 2000-03-17 K5211(34) 23 23
SHIPWRIGHT RESTAURANTS LIMITED 125 NORTH SERVICE ROAD W WESTLAKE ACCESS NORTH BAY L8B1O5 ONTARIO CANADA ATTN: PAULINE DEGRASSI 1 CS DM 5309 #1013 12 OZ.MUNICH STEIN 37.72 37.72 6 DZ ON 6420 PROVINCIAL DINNER FORK 17.98 107.88 72 EA JR20643 PLASTIC HANDLED STEAK KNIFE .81 58.32 6 DZ ON 6410 PROVINCIAL TEASPOONS 12.16 72.96 0 DZ ON 6411 PROVINCIAL RD BOWL SPOON 6 17.98 0.00 1 EA DO 3218 34 OZ DUAL DIAL SCALE AM3218 70.00 5.0 66.50 1 CS DM 195 20 OZ.BEER PUB GLASS 55.90 55.90 399.28 3.50 23.75 29.61 33.84 33.84 486.48
zope.tal-3.5.2/src/zope/tal/tests/output/test17.xml0000644000175000017500000000007211273124226022075 0ustar anthonyanthony Yes Yes Yes Yes Yes zope.tal-3.5.2/src/zope/tal/tests/output/test_metal9.html0000644000175000017500000000123511273124226023346 0ustar anthonyanthony
Default for macro1
Macro 2's slot 1 decoration Default for macro2
Macro 2's slot 1 decoration Default for macro2
Macro 2's slot 1 decoration Custom slot1
zope.tal-3.5.2/src/zope/tal/tests/output/document_list.html0000644000175000017500000000103511273124226023763 0ustar anthonyanthony Acme Document List
"The early bird gets the worm, but the second mouse gets the cheese."
Preferences...

Documents

  • Rocket Science for Dummies
  • Birds for the Gourmet Chef
Copyright 2004 Acme Inc.
This document list is classified.
zope.tal-3.5.2/src/zope/tal/tests/output/test08.xml0000644000175000017500000000471311273124226022103 0ustar anthonyanthony
Top Left Top Right
Bottom left

Some headline

This is the real contents of the bottom right slot.

It is supposed to contain a lot of text. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb.

It is supposed to contain a lot of text. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb.

It is supposed to contain a lot of text. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb.

zope.tal-3.5.2/src/zope/tal/tests/output/test04.xml0000644000175000017500000000065611273124226022101 0ustar anthonyanthony
  • 0 hello world
  • 1 hello world
  • 0 goodbye cruel world
  • 1 goodbye cruel world

define-slot

zope.tal-3.5.2/src/zope/tal/tests/output/test09.xml0000644000175000017500000000072211273124226022100 0ustar anthonyanthony

Just a bunch of text.

more text...

  • first item
  • second item
    1. second list, first item
    2. second list, second item
      term 1
      term 2
      definition
  • Now let's have a paragraph...

    My Paragraph

  • And a table in a list item:
zope.tal-3.5.2/src/zope/tal/tests/output/test_metal1.html0000644000175000017500000000257711273124226023350 0ustar anthonyanthony AAA INNER BBB AAA INNER BBB INNER AAA INNER BBB AAA INNER BBB INNER AAA OUTERSLOT BBB AAA INNER INNERSLOT BBB AAA INNER INNERSLOT BBB AAA OUTERSLOT BBB INNER INNERSLOT INNER INNERSLOT INNER INSLOT INSLOT zope.tal-3.5.2/src/zope/tal/tests/output/test21.xml0000644000175000017500000000012011273124226022062 0ustar anthonyanthony Lomax WAS BORN IN Antarctica. zope.tal-3.5.2/src/zope/tal/tests/output/test_metal6.html0000644000175000017500000000022011273124226023334 0ustar anthonyanthony Z3 UI zope.tal-3.5.2/src/zope/tal/tests/output/test32.html0000644000175000017500000000010411273124226022232 0ustar anthonyanthonyLomax was born in Antarctica zope.tal-3.5.2/src/zope/tal/tests/output/acme_template_source.html0000644000175000017500000000111711273124226025273 0ustar anthonyanthony ACME Look and Feel
"The early bird gets the worm, but the second mouse gets the cheese."
Preferences...
Content here
Copyright 2004 Acme Inc.
Standard disclaimers apply.
zope.tal-3.5.2/src/zope/tal/tests/output/test_failed_attr_translation.html0000644000175000017500000000004311273124226027043 0ustar anthonyanthony zope.tal-3.5.2/src/zope/tal/tests/output/test07.html0000644000175000017500000000030111273124226022233 0ustar anthonyanthony
Top Left Top Right
Bottom left Bottom Right
zope.tal-3.5.2/src/zope/tal/tests/output/test13.html0000644000175000017500000000014011273124226022231 0ustar anthonyanthonyHere's a stray greater than: > zope.tal-3.5.2/src/zope/tal/tests/output/test37.html0000644000175000017500000000002611273124226022242 0ustar anthonyanthony TEST zope.tal-3.5.2/src/zope/tal/tests/output/test36.html0000644000175000017500000000010511273124226022237 0ustar anthonyanthony<foo> <foo> some text zope.tal-3.5.2/src/zope/tal/tests/output/test05.html0000644000175000017500000000011511273124226022234 0ustar anthonyanthony

This is the body of test5

zope.tal-3.5.2/src/zope/tal/tests/output/test01.html0000644000175000017500000000170311273124226022234 0ustar anthonyanthony dadada

This Is The Replaced Title

 &HarryPotter; here/id

5

honda

subaru

acura

foo bar

  • honda
  • subaru
  • acura
python python  

Header Level 3

 

Header Level 3

zope.tal-3.5.2/src/zope/tal/tests/output/test23.html0000644000175000017500000000004311273124226022234 0ustar anthonyanthony59 minutes after 6 PM zope.tal-3.5.2/src/zope/tal/tests/output/test07.xml0000644000175000017500000000033011273124226022071 0ustar anthonyanthony
Top Left Top Right
Bottom left Bottom Right
zope.tal-3.5.2/src/zope/tal/tests/output/test_sa1.html0000644000175000017500000000043311273124226022636 0ustar anthonyanthony Simple test of source annotations

Foo!

zope.tal-3.5.2/src/zope/tal/tests/output/test28.html0000644000175000017500000000014711273124226022246 0ustar anthonyanthony

Your contact email address is recorded as aperson@dom.ain

zope.tal-3.5.2/src/zope/tal/tests/output/test35.html0000644000175000017500000000002711273124226022241 0ustar anthonyanthony

page

zope.tal-3.5.2/src/zope/tal/tests/output/test_sa1.xml0000644000175000017500000000046111273124226022473 0ustar anthonyanthony Simple test of source annotations

Foo!

zope.tal-3.5.2/src/zope/tal/tests/output/test30.html0000644000175000017500000000015311273124226022234 0ustar anthonyanthony

Your contact email address is recorded as aperson@dom.ain

zope.tal-3.5.2/src/zope/tal/tests/output/test33.html0000644000175000017500000000004011273124226022232 0ustar anthonyanthonydon't translate me zope.tal-3.5.2/src/zope/tal/tests/output/test10.html0000644000175000017500000000475211273124226022243 0ustar anthonyanthony
Top Left Top Right
Bottom left

Some headline

This is the real contents of the bottom right slot.


It is supposed to contain a lot of text. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb.

It is supposed to contain a lot of text. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb.

It is supposed to contain a lot of text. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb. Blah, blah, blab. Blabber, blabber, blah. Baah, baah, barb.



zope.tal-3.5.2/src/zope/tal/tests/output/test03.html0000644000175000017500000000025011273124226022232 0ustar anthonyanthony

hello brave new world goodbye cruel world hello brave new world

zope.tal-3.5.2/src/zope/tal/tests/output/test_metal4.html0000644000175000017500000000027311273124226023342 0ustar anthonyanthony Z3 UI zope.tal-3.5.2/src/zope/tal/tests/output/test_sa2.html0000644000175000017500000000057611273124226022647 0ustar anthonyanthony Simple test of source annotations

Foo!

zope.tal-3.5.2/src/zope/tal/tests/output/test06.html0000644000175000017500000000011311273124226022233 0ustar anthonyanthony

This is the body of test5

zope.tal-3.5.2/src/zope/tal/tests/output/test_sa4.html0000644000175000017500000000233711273124226022646 0ustar anthonyanthony

Some text on sa4 line 3.

This is macro1 on sa3 line 3. Text from sa4 line 6 is filled into slot1. This is the end of macro1 on sa3 line 5.

This is some text on sa4 line 9.

zope.tal-3.5.2/src/zope/tal/tests/output/test25.html0000644000175000017500000000002611273124226022237 0ustar anthonyanthony zope.tal-3.5.2/src/zope/tal/tests/output/__init__.py0000644000175000017500000000007511273124226022340 0ustar anthonyanthony# # This file is necessary to make this directory a package. zope.tal-3.5.2/src/zope/tal/tests/output/test11.html0000644000175000017500000000020511273124226022231 0ustar anthonyanthony bar

bad boy!

x undefined

x undefined x undefined
zope.tal-3.5.2/src/zope/tal/tests/output/test19.html0000644000175000017500000000013011273124226022236 0ustar anthonyanthonyREPLACE THIS MSGID AND ANOTHER TRANSLATED STRING zope.tal-3.5.2/src/zope/tal/tests/output/test11.xml0000644000175000017500000000014011273124226022063 0ustar anthonyanthony bar

bad boy!

x undefined

zope.tal-3.5.2/src/zope/tal/tests/output/test_metal8.html0000644000175000017500000000046311273124226023347 0ustar anthonyanthony
Default body
Filled-in body
zope.tal-3.5.2/src/zope/tal/tests/output/test_metal3.html0000644000175000017500000000011411273124226023333 0ustar anthonyanthonyShould not get attr in metal zope.tal-3.5.2/src/zope/tal/tests/output/test16.html0000644000175000017500000000005711273124226022243 0ustar anthonyanthonyblah, blah zope.tal-3.5.2/src/zope/tal/tests/output/test03.xml0000644000175000017500000000027711273124226022077 0ustar anthonyanthony

hello brave new world goodbye cruel world hello brave new world

zope.tal-3.5.2/src/zope/tal/tests/output/test15.html0000644000175000017500000000040511273124226022237 0ustar anthonyanthony INNERSLOT inner-argument
OUTERSLOT
outer-argument
OUTERSLOT
zope.tal-3.5.2/src/zope/tal/tests/output/test17.html0000644000175000017500000000002511273124226022237 0ustar anthonyanthonyYes Yes Yes Yes Yes zope.tal-3.5.2/src/zope/tal/tests/output/test18.xml0000644000175000017500000000014711273124226022101 0ustar anthonyanthony Content Content

Content

Yes Yes Yes Yes zope.tal-3.5.2/src/zope/tal/tests/output/test18.html0000644000175000017500000000010411273124226022236 0ustar anthonyanthonyContent Content

Content

Yes Yes Yes Yes zope.tal-3.5.2/src/zope/tal/tests/output/test14.html0000644000175000017500000000017611273124226022243 0ustar anthonyanthony
car bike broomstick

Harry Ron Hermione

zope.tal-3.5.2/src/zope/tal/tests/output/test20.xml0000644000175000017500000000010311273124226022062 0ustar anthonyanthony REPLACEABLE HERE zope.tal-3.5.2/src/zope/tal/tests/output/test_metal2.html0000644000175000017500000000026311273124226023337 0ustar anthonyanthony
OUTER INNER OUTER
OUTER INNER OUTER
zope.tal-3.5.2/src/zope/tal/tests/output/test14.xml0000644000175000017500000000024611273124226022075 0ustar anthonyanthony
car bike broomstick

Harry Ron Hermione

zope.tal-3.5.2/src/zope/tal/tests/output/test09.html0000644000175000017500000000071711273124226022250 0ustar anthonyanthony

Just a bunch of text.

more text...

  • first item
  • second item
    1. second list, first item
    2. second list, second item
      term 1
      term 2
      definition
  • Now let's have a paragraph...

    My Paragraph

  • And a table in a list item:
zope.tal-3.5.2/src/zope/tal/tests/output/test16.xml0000644000175000017500000000013611273124226022075 0ustar anthonyanthony bar zope.tal-3.5.2/src/zope/tal/tests/output/test12.html0000644000175000017500000000034611273124226022240 0ustar anthonyanthony zope.tal-3.5.2/src/zope/tal/tests/output/test_sa3.xml0000644000175000017500000000341611273124226022500 0ustar anthonyanthony
This is macro1 on sa3 line 4. This is slot1 on sa3 line 5. This is the end of macro1 on sa3 line 6.

Some text on sa3 line 8.

This is macro1 on sa3 line 4. Text from sa3 line 11 is filled into slot1. This is the end of macro1 on sa3 line 6.

This is some text on sa3 line 14.

zope.tal-3.5.2/src/zope/tal/tests/output/document_list_source.html0000644000175000017500000000125611273124226025350 0ustar anthonyanthony Acme Document List
"The early bird gets the worm, but the second mouse gets the cheese."
Preferences...

Documents

  • Rocket Science for Dummies
  • Birds for the Gourmet Chef
Copyright 2004 Acme Inc.
This document list is classified.
zope.tal-3.5.2/src/zope/tal/tests/output/test19.xml0000644000175000017500000000017511273124226022103 0ustar anthonyanthony REPLACE THIS MSGID AND ANOTHER TRANSLATED STRING zope.tal-3.5.2/src/zope/tal/tests/output/test01.xml0000644000175000017500000000173011273124226022070 0ustar anthonyanthony dadada

This Is The Replaced Title

 &HarryPotter; here/id

5

honda

subaru

acura

foo bar

  • honda
  • subaru
  • acura
python python  

Header Level 3

 

Header Level 3

zope.tal-3.5.2/src/zope/tal/tests/output/test_metal7.html0000644000175000017500000000027311273124226023345 0ustar anthonyanthony zope.tal-3.5.2/src/zope/tal/tests/output/test06.xml0000644000175000017500000000014211273124226022071 0ustar anthonyanthony

This is the body of test5

zope.tal-3.5.2/src/zope/tal/tests/output/test_sa3.html0000644000175000017500000000337611273124226022651 0ustar anthonyanthony
This is macro1 on sa3 line 3. This is slot1 on sa3 line 4. This is the end of macro1 on sa3 line 5.

Some text on sa3 line 7.

This is macro1 on sa3 line 3. Text from sa3 line 10 is filled into slot1. This is the end of macro1 on sa3 line 5.

This is some text on sa3 line 13.

zope.tal-3.5.2/src/zope/tal/tests/output/test_metal5.html0000644000175000017500000000026111273124226023340 0ustar anthonyanthony Z3 UI zope.tal-3.5.2/src/zope/tal/tests/output/test04.html0000644000175000017500000000063111273124226022236 0ustar anthonyanthony
  • 0 hello world
  • 1 hello world
  • 0 goodbye cruel world
  • 1 goodbye cruel world

define-slot

zope.tal-3.5.2/src/zope/tal/tests/output/test20.html0000644000175000017500000000003611273124226022233 0ustar anthonyanthonyREPLACEABLE HERE zope.tal-3.5.2/src/zope/tal/tests/test_sourcepos.py0000644000175000017500000000562611273124226022331 0ustar anthonyanthony############################################################################## # # Copyright (c) 2001, 2002 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Tests for TALInterpreter. $Id: test_sourcepos.py 30452 2005-05-20 05:13:10Z fdrake $ """ import unittest from StringIO import StringIO from zope.tal.htmltalparser import HTMLTALParser from zope.tal.talinterpreter import TALInterpreter from zope.tal.talgenerator import TALGenerator from zope.tal.dummyengine import DummyEngine page1 = '''
page1=
''' main_template = ''' main_template=
main_template=
main_template= ''' footer = '''
footer=
''' expected = ''' main_template=main_template (2,14)
page1=page1 (3,6)
main_template=main_template (4,14)
footer=footer (2,7)
main_template=main_template (6,14) ''' class SourcePosTestCase(unittest.TestCase): def parse(self, eng, s, fn): gen = TALGenerator(expressionCompiler=eng, xml=0, source_file=fn) parser = HTMLTALParser(gen) parser.parseString(s) program, macros = parser.getCode() return program, macros def test_source_positions(self): # Ensure source file and position are set correctly by TAL macros = {} eng = DummyEngine(macros) page1_program, page1_macros = self.parse(eng, page1, 'page1') main_template_program, main_template_macros = self.parse( eng, main_template, 'main_template') footer_program, footer_macros = self.parse(eng, footer, 'footer') macros['main'] = main_template_macros['main'] macros['foot'] = footer_macros['foot'] stream = StringIO() interp = TALInterpreter(page1_program, macros, eng, stream) interp() self.assertEqual(stream.getvalue().strip(), expected.strip(), "Got result:\n%s\nExpected:\n%s" % (stream.getvalue(), expected)) def test_suite(): return unittest.makeSuite(SourcePosTestCase) if __name__ == "__main__": unittest.main(defaultTest='test_suite') zope.tal-3.5.2/src/zope/tal/talgenerator.py0000644000175000017500000010047211273124226020570 0ustar anthonyanthony############################################################################## # # Copyright (c) 2001, 2002 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Code generator for TALInterpreter intermediate code. $Id: talgenerator.py 39119 2005-10-13 19:20:18Z fdrake $ """ import cgi import re from zope.tal import taldefs from zope.tal.taldefs import NAME_RE, TAL_VERSION from zope.tal.taldefs import I18NError, METALError, TALError from zope.tal.taldefs import parseSubstitution from zope.tal.translationcontext import TranslationContext, DEFAULT_DOMAIN _name_rx = re.compile(NAME_RE) class TALGenerator(object): inMacroUse = 0 inMacroDef = 0 source_file = None 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 def getCode(self): assert not self.stack assert not self.todoStack return self.optimize(self.program), self.macros def optimize(self, program): output = [] collect = [] cursor = 0 for cursor in xrange(len(program)+1): try: item = program[cursor] except IndexError: item = (None, None) opcode = item[0] if opcode == "rawtext": collect.append(item[1]) continue if opcode == "endTag": collect.append("" % item[1]) continue if opcode == "startTag": if self.optimizeStartTag(collect, item[1], item[2], ">"): continue if opcode == "startEndTag": endsep = self.xml and "/>" or " />" if self.optimizeStartTag(collect, item[1], item[2], endsep): continue if opcode in ("beginScope", "endScope"): # Push *Scope instructions in front of any text instructions; # this allows text instructions separated only by *Scope # instructions to be joined together. output.append(self.optimizeArgsList(item)) continue if opcode == 'noop': # This is a spacer for end tags in the face of i18n:name # attributes. We can't let the optimizer collect immediately # following end tags into the same rawtextOffset. opcode = None pass text = "".join(collect) if text: i = text.rfind("\n") if i >= 0: i = len(text) - (i + 1) output.append(("rawtextColumn", (text, i))) else: output.append(("rawtextOffset", (text, len(text)))) if opcode != None: output.append(self.optimizeArgsList(item)) collect = [] return self.optimizeCommonTriple(output) def optimizeArgsList(self, item): if len(item) == 2: return item else: return item[0], tuple(item[1:]) # These codes are used to indicate what sort of special actions # are needed for each special attribute. (Simple attributes don't # get action codes.) # # The special actions (which are modal) are handled by # TALInterpreter.attrAction() and .attrAction_tal(). # # Each attribute is represented by a tuple: # # (name, value) -- a simple name/value pair, with # no special processing # # (name, value, action, *extra) -- attribute with special # processing needs, action is a # code that indicates which # branch to take, and *extra # contains additional, # action-specific information # needed by the processing # def optimizeStartTag(self, collect, name, attrlist, end): # return true if the tag can be converted to plain text if not attrlist: collect.append("<%s%s" % (name, end)) return 1 opt = 1 new = ["<" + name] for i in range(len(attrlist)): item = attrlist[i] if len(item) > 2: opt = 0 name, value, action = item[:3] attrlist[i] = (name, value, action) + item[3:] else: if item[1] is None: s = item[0] else: s = '%s="%s"' % (item[0], taldefs.attrEscape(item[1])) attrlist[i] = item[0], s new.append(" " + s) # if no non-optimizable attributes were found, convert to plain text if opt: new.append(end) collect.extend(new) return opt def optimizeCommonTriple(self, program): if len(program) < 3: return program output = program[:2] prev2, prev1 = output for item in program[2:]: if ( item[0] == "beginScope" and prev1[0] == "setPosition" and prev2[0] == "rawtextColumn"): position = output.pop()[1] text, column = output.pop()[1] prev1 = None, None closeprev = 0 if output and output[-1][0] == "endScope": closeprev = 1 output.pop() item = ("rawtextBeginScope", (text, column, position, closeprev, item[1])) output.append(item) prev2 = prev1 prev1 = item return output def todoPush(self, todo): self.todoStack.append(todo) def todoPop(self): return self.todoStack.pop() def compileExpression(self, expr): try: return self.expressionCompiler.compile(expr) except self.CompilerError, err: raise TALError('%s in expression %s' % (err.args[0], `expr`), self.position) def pushProgram(self): self.stack.append(self.program) self.program = [] def popProgram(self): program = self.program self.program = self.stack.pop() return self.optimize(program) def pushSlots(self): self.slotStack.append(self.slots) self.slots = {} def popSlots(self): slots = self.slots self.slots = self.slotStack.pop() return slots def emit(self, *instruction): self.program.append(instruction) def emitStartTag(self, name, attrlist, isend=0): if isend: opcode = "startEndTag" else: opcode = "startTag" self.emit(opcode, name, attrlist) def emitEndTag(self, name): if self.xml and self.program and self.program[-1][0] == "startTag": # Minimize empty element self.program[-1] = ("startEndTag",) + self.program[-1][1:] else: self.emit("endTag", name) def emitOptTag(self, name, optTag, isend): program = self.popProgram() #block start = self.popProgram() #start tag if (isend or not program) and self.xml: # Minimize empty element start[-1] = ("startEndTag",) + start[-1][1:] isend = 1 cexpr = optTag[0] if cexpr: cexpr = self.compileExpression(optTag[0]) self.emit("optTag", name, cexpr, optTag[1], isend, start, program) def emitRawText(self, text): self.emit("rawtext", text) def emitText(self, text): self.emitRawText(cgi.escape(text)) def emitDefines(self, defines): for part in taldefs.splitParts(defines): m = re.match( r"(?s)\s*(?:(global|local)\s+)?(%s)\s+(.*)\Z" % NAME_RE, part) if not m: raise TALError("invalid define syntax: " + `part`, self.position) scope, name, expr = m.group(1, 2, 3) scope = scope or "local" cexpr = self.compileExpression(expr) if scope == "local": self.emit("setLocal", name, cexpr) else: self.emit("setGlobal", name, cexpr) def emitOnError(self, name, onError, TALtag, isend): block = self.popProgram() key, expr = parseSubstitution(onError) cexpr = self.compileExpression(expr) if key == "text": self.emit("insertText", cexpr, []) else: assert key == "structure" self.emit("insertStructure", cexpr, {}, []) if TALtag: self.emitOptTag(name, (None, 1), isend) else: self.emitEndTag(name) handler = self.popProgram() self.emit("onError", block, handler) def emitCondition(self, expr): cexpr = self.compileExpression(expr) program = self.popProgram() self.emit("condition", cexpr, program) def emitRepeat(self, arg): m = re.match("(?s)\s*(%s)\s+(.*)\Z" % NAME_RE, arg) if not m: raise TALError("invalid repeat syntax: " + `arg`, self.position) name, expr = m.group(1, 2) cexpr = self.compileExpression(expr) program = self.popProgram() self.emit("loop", name, cexpr, program) def emitSubstitution(self, arg, attrDict={}): key, expr = parseSubstitution(arg) cexpr = self.compileExpression(expr) program = self.popProgram() if key == "text": self.emit("insertText", cexpr, program) else: assert key == "structure" self.emit("insertStructure", cexpr, attrDict, program) def emitI18nSubstitution(self, arg, attrDict={}): # TODO: Code duplication is BAD, we need to fix it later key, expr = parseSubstitution(arg) cexpr = self.compileExpression(expr) program = self.popProgram() if key == "text": self.emit("insertI18nText", cexpr, program) else: assert key == "structure" self.emit("insertI18nStructure", cexpr, attrDict, program) def emitEvaluateCode(self, lang): program = self.popProgram() self.emit('evaluateCode', lang, program) def emitI18nVariable(self, varname): # Used for i18n:name attributes. m = _name_rx.match(varname) if m is None or m.group() != varname: raise TALError("illegal i18n:name: %r" % varname, self.position) program = self.popProgram() self.emit('i18nVariable', varname, program, None, False) def emitTranslation(self, msgid, i18ndata): program = self.popProgram() if i18ndata is None: self.emit('insertTranslation', msgid, program) else: key, expr = parseSubstitution(i18ndata) cexpr = self.compileExpression(expr) assert key == 'text' self.emit('insertTranslation', msgid, program, cexpr) def emitDefineMacro(self, macroName): program = self.popProgram() macroName = macroName.strip() if self.macros.has_key(macroName): raise METALError("duplicate macro definition: %s" % `macroName`, self.position) if not re.match('%s$' % NAME_RE, macroName): raise METALError("invalid macro name: %s" % `macroName`, self.position) self.macros[macroName] = program self.inMacroDef = self.inMacroDef - 1 self.emit("defineMacro", macroName, program) def emitUseMacro(self, expr): cexpr = self.compileExpression(expr) program = self.popProgram() self.inMacroUse = 0 self.emit("useMacro", expr, cexpr, self.popSlots(), program) def emitExtendMacro(self, defineName, useExpr): cexpr = self.compileExpression(useExpr) program = self.popProgram() self.inMacroUse = 0 self.emit("extendMacro", useExpr, cexpr, self.popSlots(), program, defineName) self.emitDefineMacro(defineName) def emitDefineSlot(self, slotName): program = self.popProgram() slotName = slotName.strip() if not re.match('%s$' % NAME_RE, slotName): raise METALError("invalid slot name: %s" % `slotName`, self.position) self.emit("defineSlot", slotName, program) def emitFillSlot(self, slotName): program = self.popProgram() slotName = slotName.strip() if self.slots.has_key(slotName): raise METALError("duplicate fill-slot name: %s" % `slotName`, self.position) if not re.match('%s$' % NAME_RE, slotName): raise METALError("invalid slot name: %s" % `slotName`, self.position) self.slots[slotName] = program self.inMacroUse = 1 self.emit("fillSlot", slotName, program) def unEmitWhitespace(self): collect = [] i = len(self.program) - 1 while i >= 0: item = self.program[i] if item[0] != "rawtext": break text = item[1] if not re.match(r"\A\s*\Z", text): break collect.append(text) i = i-1 del self.program[i+1:] if i >= 0 and self.program[i][0] == "rawtext": text = self.program[i][1] m = re.search(r"\s+\Z", text) if m: self.program[i] = ("rawtext", text[:m.start()]) collect.append(m.group()) collect.reverse() return "".join(collect) def unEmitNewlineWhitespace(self): collect = [] i = len(self.program) while i > 0: i = i-1 item = self.program[i] if item[0] != "rawtext": break text = item[1] if re.match(r"\A[ \t]*\Z", text): collect.append(text) continue m = re.match(r"(?s)^(.*)(\n[ \t]*)\Z", text) if not m: break text, rest = m.group(1, 2) collect.reverse() rest = rest + "".join(collect) del self.program[i:] if text: self.emit("rawtext", text) return rest return None def replaceAttrs(self, attrlist, repldict): # Each entry in attrlist starts like (name, value). Result is # (name, value, action, expr, xlat, msgid) if there is a # tal:attributes entry for that attribute. Additional attrs # defined only by tal:attributes are added here. # # (name, value, action, expr, xlat, msgid) if not repldict: return attrlist newlist = [] for item in attrlist: key = item[0] if repldict.has_key(key): expr, xlat, msgid = repldict[key] item = item[:2] + ("replace", expr, xlat, msgid) del repldict[key] newlist.append(item) # Add dynamic-only attributes for key, (expr, xlat, msgid) in repldict.items(): newlist.append((key, None, "insert", expr, xlat, msgid)) return newlist 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 # TODO: Ugly hack to work around tal:replace and i18n:translate issue. # I (DV) need to cleanup the code later. replaced = False if "replace" in taldict: if "content" in taldict: raise TALError( "tal:content and tal:replace are mutually exclusive", position) taldict["omit-tag"] = taldict.get("omit-tag", "") taldict["content"] = taldict.pop("replace") replaced = True for key, value in taldict.items(): if key not in taldefs.KNOWN_TAL_ATTRIBUTES: raise TALError("bad TAL attribute: " + `key`, position) if not (value or key == 'omit-tag'): raise TALError("missing value for TAL attribute: " + `key`, position) for key, value in metaldict.items(): if key not in taldefs.KNOWN_METAL_ATTRIBUTES: raise METALError("bad METAL attribute: " + `key`, position) if not value: raise TALError("missing value for METAL attribute: " + `key`, position) for key, value in i18ndict.items(): if key not in taldefs.KNOWN_I18N_ATTRIBUTES: raise I18NError("bad i18n attribute: " + `key`, position) if not value and key in ("attributes", "data", "id"): raise I18NError("missing value for i18n attribute: " + `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 extendMacro: if useMacro: raise METALError( "extend-macro cannot be used with use-macro", position) if not defineMacro: raise METALError( "extend-macro must be used with define-macro", position) if defineMacro or extendMacro or useMacro: if fillSlot or defineSlot: raise METALError( "define-slot and fill-slot cannot be used with " "define-macro, extend-macro, or use-macro", position) if defineMacro and useMacro: raise METALError( "define-macro may not be used with use-macro", position) 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 else: if fillSlot: raise METALError("fill-slot must be within a use-macro", position) 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: if not self.inMacroDef: raise METALError( "define-slot must be within a define-macro", position) 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: repldict = taldefs.parseAttributeReplacements(attrsubst, self.xml) 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 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 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) def emitEndElement(self, name, isend=0, implied=0, position=(None, None)): todo = self.todoPop() if not todo: # Shortcut if not isend: self.emitEndTag(name) return self.position = todo.get("position", (None, None)) defineMacro = todo.get("defineMacro") useMacro = todo.get("useMacro") defineSlot = todo.get("defineSlot") fillSlot = todo.get("fillSlot") repeat = todo.get("repeat") content = todo.get("content") script = todo.get("script") condition = todo.get("condition") onError = todo.get("onError") repldict = todo.get("repldict", {}) scope = todo.get("scope") optTag = todo.get("optional tag") msgid = todo.get('msgid') i18ncontext = todo.get("i18ncontext") varname = todo.get('i18nvar') i18ndata = todo.get('i18ndata') if implied > 0: if defineMacro or useMacro or defineSlot or fillSlot: exc = METALError what = "METAL" else: exc = TALError what = "TAL" raise exc("%s attributes on <%s> require explicit " % (what, name, name), self.position) if script: self.emitEvaluateCode(script) # If there's no tal:content or tal:replace in the tag with the # i18n:name, tal:replace is the default. if content: if msgid is not None: self.emitI18nSubstitution(content, repldict) else: self.emitSubstitution(content, repldict) # If we're looking at an implicit msgid, emit the insertTranslation # opcode now, so that the end tag doesn't become part of the implicit # msgid. If we're looking at an explicit msgid, it's better to emit # the opcode after the i18nVariable opcode so we can better handle # tags with both of them in them (and in the latter case, the contents # would be thrown away for msgid purposes). # # Still, we should emit insertTranslation opcode before i18nVariable # in case tal:content, i18n:translate and i18n:name in the same tag if not content and msgid is not None: self.emitTranslation(msgid, i18ndata) self.i18nLevel -= 1 if optTag: self.emitOptTag(name, optTag, isend) elif not isend: # If we're processing the end tag for a tag that contained # i18n:name, we need to make sure that optimize() won't collect # immediately following end tags into the same rawtextOffset, so # put a spacer here that the optimizer will recognize. if varname: self.emit('noop') self.emitEndTag(name) if varname: self.emitI18nVariable(varname) if repeat: self.emitRepeat(repeat) if condition: self.emitCondition(condition) if onError: self.emitOnError(name, onError, optTag and optTag[1], isend) if scope: self.emit("endScope") if i18ncontext: self.emit("endI18nContext") assert self.i18nContext.parent is not None self.i18nContext = self.i18nContext.parent if defineSlot: self.emitDefineSlot(defineSlot) if fillSlot: self.emitFillSlot(fillSlot) if useMacro or defineMacro: if useMacro and defineMacro: self.emitExtendMacro(defineMacro, useMacro) elif useMacro: self.emitUseMacro(useMacro) elif defineMacro: self.emitDefineMacro(defineMacro) if useMacro or defineSlot: # generate a source annotation after define-slot or use-macro # because the source file might have changed if self.source_file is not None: if position != (None, None): self.emit("setPosition", position) self.emit("setSourceFile", self.source_file) def _parseI18nAttributes(i18nattrs, position, xml): d = {} # Filter out empty items, eg: # i18n:attributes="value msgid; name msgid2;" # would result in 3 items where the last one is empty attrs = [spec for spec in i18nattrs.split(";") if spec] for spec in attrs: parts = spec.split() if len(parts) == 2: attr, msgid = parts elif len(parts) == 1: attr = parts[0] msgid = None else: raise TALError("illegal i18n:attributes specification: %r" % spec, position) if not xml: attr = attr.lower() if attr in d: raise TALError( "attribute may only be specified once in i18n:attributes: %r" % attr, position) d[attr] = msgid return d def test(): t = TALGenerator() t.pushProgram() t.emit("bar") p = t.popProgram() t.emit("foo", p) if __name__ == "__main__": test() zope.tal-3.5.2/src/zope/tal/talparser.py0000644000175000017500000001124011273124226020070 0ustar anthonyanthony############################################################################## # # Copyright (c) 2001, 2002 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Parse XML and compile to TALInterpreter intermediate code. $Id: talparser.py 76887 2007-06-21 10:08:47Z hdima $ """ from zope.tal.taldefs import XML_NS, ZOPE_I18N_NS, ZOPE_METAL_NS, ZOPE_TAL_NS from zope.tal.talgenerator import TALGenerator from zope.tal.xmlparser import XMLParser class TALParser(XMLParser): ordered_attributes = 1 def __init__(self, gen=None, encoding=None): # Override XMLParser.__init__(self, encoding) if gen is None: gen = TALGenerator() self.gen = gen self.nsStack = [] self.nsDict = {XML_NS: 'xml'} self.nsNew = [] def getCode(self): return self.gen.getCode() def StartNamespaceDeclHandler(self, prefix, uri): self.nsStack.append(self.nsDict.copy()) self.nsDict[uri] = prefix self.nsNew.append((prefix, uri)) def EndNamespaceDeclHandler(self, prefix): self.nsDict = self.nsStack.pop() def StartElementHandler(self, name, attrs): if self.ordered_attributes: # attrs is a list of alternating names and values attrlist = [] for i in range(0, len(attrs), 2): key = attrs[i] value = attrs[i + 1] attrlist.append((key, value)) else: # attrs is a dict of {name: value} attrlist = attrs.items() attrlist.sort() # For definiteness name, attrlist, taldict, metaldict, i18ndict \ = self.process_ns(name, attrlist) attrlist = self.xmlnsattrs() + attrlist self.gen.emitStartElement(name, attrlist, taldict, metaldict, i18ndict, self.getpos()) def process_ns(self, name, attrlist): taldict = {} metaldict = {} i18ndict = {} fixedattrlist = [] name, namebase, namens = self.fixname(name) for key, value in attrlist: key, keybase, keyns = self.fixname(key) ns = keyns or namens # default to tag namespace item = key, value if ns == 'metal': metaldict[keybase] = value item = item + ("metal",) elif ns == 'tal': taldict[keybase] = value item = item + ("tal",) elif ns == 'i18n': i18ndict[keybase] = value item = item + ('i18n',) fixedattrlist.append(item) if namens in ('metal', 'tal', 'i18n'): taldict['tal tag'] = namens return name, fixedattrlist, taldict, metaldict, i18ndict _namespaces = { ZOPE_TAL_NS: "tal", ZOPE_METAL_NS: "metal", ZOPE_I18N_NS: "i18n", } def xmlnsattrs(self): newlist = [] for prefix, uri in self.nsNew: if prefix: key = "xmlns:" + prefix else: key = "xmlns" if uri in self._namespaces: item = (key, uri, "xmlns") else: item = (key, uri) newlist.append(item) self.nsNew = [] return newlist def fixname(self, name): if ' ' in name: uri, name = name.split(' ', 1) prefix = self.nsDict[uri] prefixed = name if prefix: prefixed = "%s:%s" % (prefix, name) ns = self._namespaces.get(uri, "x") return (prefixed, name, ns) return (name, name, None) def EndElementHandler(self, name): name = self.fixname(name)[0] self.gen.emitEndElement(name, position=self.getpos()) def DefaultHandler(self, text): self.gen.emitRawText(text) def test(): import sys p = TALParser() file = "tests/input/test01.xml" if sys.argv[1:]: file = sys.argv[1] p.parseFile(file) program, macros = p.getCode() from zope.tal.talinterpreter import TALInterpreter from zope.tal.dummyengine import DummyEngine engine = DummyEngine(macros) TALInterpreter(program, macros, engine, sys.stdout, wrap=0)() if __name__ == "__main__": test() zope.tal-3.5.2/src/zope/tal/ndiff.py0000644000175000017500000006120111273124226017163 0ustar anthonyanthony#! /usr/bin/env python ############################################################################## # # Copyright (c) 2001, 2002 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## # Module ndiff version 1.6.0 # Released to the public domain 08-Dec-2000, # by Tim Peters (tim.one@home.com). # Provided as-is; use at your own risk; no warranty; no promises; enjoy! """ndiff [-q] file1 file2 or ndiff (-r1 | -r2) < ndiff_output > file1_or_file2 Print a human-friendly file difference report to stdout. Both inter- and intra-line differences are noted. In the second form, recreate file1 (-r1) or file2 (-r2) on stdout, from an ndiff report on stdin. In the first form, if -q ("quiet") is not specified, the first two lines of output are -: file1 +: file2 Each remaining line begins with a two-letter code: "- " line unique to file1 "+ " line unique to file2 " " line common to both files "? " line not present in either input file Lines beginning with "? " attempt to guide the eye to intraline differences, and were not present in either input file. These lines can be confusing if the source files contain tab characters. The first file can be recovered by retaining only lines that begin with " " or "- ", and deleting those 2-character prefixes; use ndiff with -r1. The second file can be recovered similarly, but by retaining only " " and "+ " lines; use ndiff with -r2; or, on Unix, the second file can be recovered by piping the output through sed -n '/^[+ ] /s/^..//p' See module comments for details and programmatic interface. $Id: ndiff.py 38178 2005-08-30 21:50:19Z mj $ """ __version__ = 1, 5, 0 # SequenceMatcher tries to compute a "human-friendly diff" between # two sequences (chiefly picturing a file as a sequence of lines, # and a line as a sequence of characters, here). Unlike e.g. UNIX(tm) # diff, the fundamental notion is the longest *contiguous* & junk-free # matching subsequence. That's what catches peoples' eyes. The # Windows(tm) windiff has another interesting notion, pairing up elements # that appear uniquely in each sequence. That, and the method here, # appear to yield more intuitive difference reports than does diff. This # method appears to be the least vulnerable to synching up on blocks # of "junk lines", though (like blank lines in ordinary text files, # or maybe "

" lines in HTML files). That may be because this is # the only method of the 3 that has a *concept* of "junk" . # # Note that ndiff makes no claim to produce a *minimal* diff. To the # contrary, minimal diffs are often counter-intuitive, because they # synch up anywhere possible, sometimes accidental matches 100 pages # apart. Restricting synch points to contiguous matches preserves some # notion of locality, at the occasional cost of producing a longer diff. # # With respect to junk, an earlier version of ndiff simply refused to # *start* a match with a junk element. The result was cases like this: # before: private Thread currentThread; # after: private volatile Thread currentThread; # If you consider whitespace to be junk, the longest contiguous match # not starting with junk is "e Thread currentThread". So ndiff reported # that "e volatil" was inserted between the 't' and the 'e' in "private". # While an accurate view, to people that's absurd. The current version # looks for matching blocks that are entirely junk-free, then extends the # longest one of those as far as possible but only with matching junk. # So now "currentThread" is matched, then extended to suck up the # preceding blank; then "private" is matched, and extended to suck up the # following blank; then "Thread" is matched; and finally ndiff reports # that "volatile " was inserted before "Thread". The only quibble # remaining is that perhaps it was really the case that " volatile" # was inserted after "private". I can live with that . # # NOTE on junk: the module-level names # IS_LINE_JUNK # IS_CHARACTER_JUNK # can be set to any functions you like. The first one should accept # a single string argument, and return true iff the string is junk. # The default is whether the regexp r"\s*#?\s*$" matches (i.e., a # line without visible characters, except for at most one splat). # The second should accept a string of length 1 etc. The default is # whether the character is a blank or tab (note: bad idea to include # newline in this!). # # After setting those, you can call fcompare(f1name, f2name) with the # names of the files you want to compare. The difference report # is sent to stdout. Or you can call main(args), passing what would # have been in sys.argv[1:] had the cmd-line form been used. TRACE = 0 # define what "junk" means import re def IS_LINE_JUNK(line, pat=re.compile(r"\s*#?\s*$").match): return pat(line) is not None def IS_CHARACTER_JUNK(ch, ws=" \t"): return ch in ws del re class SequenceMatcher(object): def __init__(self, isjunk=None, a='', b=''): # Members: # a # first sequence # b # second sequence; differences are computed as "what do # we need to do to 'a' to change it into 'b'?" # b2j # for x in b, b2j[x] is a list of the indices (into b) # at which x appears; junk elements do not appear # b2jhas # b2j.has_key # fullbcount # for x in b, fullbcount[x] == the number of times x # appears in b; only materialized if really needed (used # only for computing quick_ratio()) # matching_blocks # a list of (i, j, k) triples, where a[i:i+k] == b[j:j+k]; # ascending & non-overlapping in i and in j; terminated by # a dummy (len(a), len(b), 0) sentinel # opcodes # a list of (tag, i1, i2, j1, j2) tuples, where tag is # one of # 'replace' a[i1:i2] should be replaced by b[j1:j2] # 'delete' a[i1:i2] should be deleted # 'insert' b[j1:j2] should be inserted # 'equal' a[i1:i2] == b[j1:j2] # isjunk # a user-supplied function taking a sequence element and # returning true iff the element is "junk" -- this has # subtle but helpful effects on the algorithm, which I'll # get around to writing up someday <0.9 wink>. # DON'T USE! Only __chain_b uses this. Use isbjunk. # isbjunk # for x in b, isbjunk(x) == isjunk(x) but much faster; # it's really the has_key method of a hidden dict. # DOES NOT WORK for x in a! self.isjunk = isjunk self.a = self.b = None self.set_seqs(a, b) def set_seqs(self, a, b): self.set_seq1(a) self.set_seq2(b) def set_seq1(self, a): if a is self.a: return self.a = a self.matching_blocks = self.opcodes = None def set_seq2(self, b): if b is self.b: return self.b = b self.matching_blocks = self.opcodes = None self.fullbcount = None self.__chain_b() # For each element x in b, set b2j[x] to a list of the indices in # b where x appears; the indices are in increasing order; note that # the number of times x appears in b is len(b2j[x]) ... # when self.isjunk is defined, junk elements don't show up in this # map at all, which stops the central find_longest_match method # from starting any matching block at a junk element ... # also creates the fast isbjunk function ... # note that this is only called when b changes; so for cross-product # kinds of matches, it's best to call set_seq2 once, then set_seq1 # repeatedly def __chain_b(self): # Because isjunk is a user-defined (not C) function, and we test # for junk a LOT, it's important to minimize the number of calls. # Before the tricks described here, __chain_b was by far the most # time-consuming routine in the whole module! If anyone sees # Jim Roskind, thank him again for profile.py -- I never would # have guessed that. # The first trick is to build b2j ignoring the possibility # of junk. I.e., we don't call isjunk at all yet. Throwing # out the junk later is much cheaper than building b2j "right" # from the start. b = self.b self.b2j = b2j = {} self.b2jhas = b2jhas = b2j.has_key for i in xrange(len(b)): elt = b[i] if b2jhas(elt): b2j[elt].append(i) else: b2j[elt] = [i] # Now b2j.keys() contains elements uniquely, and especially when # the sequence is a string, that's usually a good deal smaller # than len(string). The difference is the number of isjunk calls # saved. isjunk, junkdict = self.isjunk, {} if isjunk: for elt in b2j.keys(): if isjunk(elt): junkdict[elt] = 1 # value irrelevant; it's a set del b2j[elt] # Now for x in b, isjunk(x) == junkdict.has_key(x), but the # latter is much faster. Note too that while there may be a # lot of junk in the sequence, the number of *unique* junk # elements is probably small. So the memory burden of keeping # this dict alive is likely trivial compared to the size of b2j. self.isbjunk = junkdict.has_key def find_longest_match(self, alo, ahi, blo, bhi): """Find longest matching block in a[alo:ahi] and b[blo:bhi]. If isjunk is not defined: Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where alo <= i <= i+k <= ahi blo <= j <= j+k <= bhi and for all (i',j',k') meeting those conditions, k >= k' i <= i' and if i == i', j <= j' In other words, of all maximal matching blocks, return one that starts earliest in a, and of all those maximal matching blocks that start earliest in a, return the one that starts earliest in b. If isjunk is defined, first the longest matching block is determined as above, but with the additional restriction that no junk element appears in the block. Then that block is extended as far as possible by matching (only) junk elements on both sides. So the resulting block never matches on junk except as identical junk happens to be adjacent to an "interesting" match. If no blocks match, return (alo, blo, 0). """ # CAUTION: stripping common prefix or suffix would be incorrect. # E.g., # ab # acab # Longest matching block is "ab", but if common prefix is # stripped, it's "a" (tied with "b"). UNIX(tm) diff does so # strip, so ends up claiming that ab is changed to acab by # inserting "ca" in the middle. That's minimal but unintuitive: # "it's obvious" that someone inserted "ac" at the front. # Windiff ends up at the same place as diff, but by pairing up # the unique 'b's and then matching the first two 'a's. a, b, b2j, isbjunk = self.a, self.b, self.b2j, self.isbjunk besti, bestj, bestsize = alo, blo, 0 # find longest junk-free match # during an iteration of the loop, j2len[j] = length of longest # junk-free match ending with a[i-1] and b[j] j2len = {} nothing = [] for i in xrange(alo, ahi): # look at all instances of a[i] in b; note that because # b2j has no junk keys, the loop is skipped if a[i] is junk j2lenget = j2len.get newj2len = {} for j in b2j.get(a[i], nothing): # a[i] matches b[j] if j < blo: continue if j >= bhi: break k = newj2len[j] = j2lenget(j-1, 0) + 1 if k > bestsize: besti, bestj, bestsize = i-k+1, j-k+1, k j2len = newj2len # Now that we have a wholly interesting match (albeit possibly # empty!), we may as well suck up the matching junk on each # side of it too. Can't think of a good reason not to, and it # saves post-processing the (possibly considerable) expense of # figuring out what to do with it. In the case of an empty # interesting match, this is clearly the right thing to do, # because no other kind of match is possible in the regions. while besti > alo and bestj > blo and \ isbjunk(b[bestj-1]) and \ a[besti-1] == b[bestj-1]: besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 while besti+bestsize < ahi and bestj+bestsize < bhi and \ isbjunk(b[bestj+bestsize]) and \ a[besti+bestsize] == b[bestj+bestsize]: bestsize = bestsize + 1 if TRACE: print "get_matching_blocks", alo, ahi, blo, bhi print " returns", besti, bestj, bestsize return besti, bestj, bestsize def get_matching_blocks(self): if self.matching_blocks is not None: return self.matching_blocks self.matching_blocks = [] la, lb = len(self.a), len(self.b) self.__helper(0, la, 0, lb, self.matching_blocks) self.matching_blocks.append((la, lb, 0)) if TRACE: print '*** matching blocks', self.matching_blocks return self.matching_blocks # builds list of matching blocks covering a[alo:ahi] and # b[blo:bhi], appending them in increasing order to answer def __helper(self, alo, ahi, blo, bhi, answer): i, j, k = x = self.find_longest_match(alo, ahi, blo, bhi) # a[alo:i] vs b[blo:j] unknown # a[i:i+k] same as b[j:j+k] # a[i+k:ahi] vs b[j+k:bhi] unknown if k: if alo < i and blo < j: self.__helper(alo, i, blo, j, answer) answer.append(x) if i+k < ahi and j+k < bhi: self.__helper(i+k, ahi, j+k, bhi, answer) def ratio(self): """Return a measure of the sequences' similarity (float in [0,1]). Where T is the total number of elements in both sequences, and M is the number of matches, this is 2*M / T. Note that this is 1 if the sequences are identical, and 0 if they have nothing in common. """ matches = reduce(lambda sum, triple: sum + triple[-1], self.get_matching_blocks(), 0) return 2.0 * matches / (len(self.a) + len(self.b)) def quick_ratio(self): """Return an upper bound on ratio() relatively quickly.""" # viewing a and b as multisets, set matches to the cardinality # of their intersection; this counts the number of matches # without regard to order, so is clearly an upper bound if self.fullbcount is None: self.fullbcount = fullbcount = {} for elt in self.b: fullbcount[elt] = fullbcount.get(elt, 0) + 1 fullbcount = self.fullbcount # avail[x] is the number of times x appears in 'b' less the # number of times we've seen it in 'a' so far ... kinda avail = {} availhas, matches = avail.has_key, 0 for elt in self.a: if availhas(elt): numb = avail[elt] else: numb = fullbcount.get(elt, 0) avail[elt] = numb - 1 if numb > 0: matches = matches + 1 return 2.0 * matches / (len(self.a) + len(self.b)) def real_quick_ratio(self): """Return an upper bound on ratio() very quickly""" la, lb = len(self.a), len(self.b) # can't have more matches than the number of elements in the # shorter sequence return 2.0 * min(la, lb) / (la + lb) def get_opcodes(self): if self.opcodes is not None: return self.opcodes i = j = 0 self.opcodes = answer = [] for ai, bj, size in self.get_matching_blocks(): # invariant: we've pumped out correct diffs to change # a[:i] into b[:j], and the next matching block is # a[ai:ai+size] == b[bj:bj+size]. So we need to pump # out a diff to change a[i:ai] into b[j:bj], pump out # the matching block, and move (i,j) beyond the match tag = '' if i < ai and j < bj: tag = 'replace' elif i < ai: tag = 'delete' elif j < bj: tag = 'insert' if tag: answer.append((tag, i, ai, j, bj)) i, j = ai+size, bj+size # the list of matching blocks is terminated by a # sentinel with size 0 if size: answer.append(('equal', ai, i, bj, j)) return answer # meant for dumping lines def dump(tag, x, lo, hi): for i in xrange(lo, hi): print tag, x[i], def plain_replace(a, alo, ahi, b, blo, bhi): assert alo < ahi and blo < bhi # dump the shorter block first -- reduces the burden on short-term # memory if the blocks are of very different sizes if bhi - blo < ahi - alo: dump('+', b, blo, bhi) dump('-', a, alo, ahi) else: dump('-', a, alo, ahi) dump('+', b, blo, bhi) # When replacing one block of lines with another, this guy searches # the blocks for *similar* lines; the best-matching pair (if any) is # used as a synch point, and intraline difference marking is done on # the similar pair. Lots of work, but often worth it. def fancy_replace(a, alo, ahi, b, blo, bhi): if TRACE: print '*** fancy_replace', alo, ahi, blo, bhi dump('>', a, alo, ahi) dump('<', b, blo, bhi) # don't synch up unless the lines have a similarity score of at # least cutoff; best_ratio tracks the best score seen so far best_ratio, cutoff = 0.74, 0.75 cruncher = SequenceMatcher(IS_CHARACTER_JUNK) eqi, eqj = None, None # 1st indices of equal lines (if any) # search for the pair that matches best without being identical # (identical lines must be junk lines, & we don't want to synch up # on junk -- unless we have to) for j in xrange(blo, bhi): bj = b[j] cruncher.set_seq2(bj) for i in xrange(alo, ahi): ai = a[i] if ai == bj: if eqi is None: eqi, eqj = i, j continue cruncher.set_seq1(ai) # computing similarity is expensive, so use the quick # upper bounds first -- have seen this speed up messy # compares by a factor of 3. # note that ratio() is only expensive to compute the first # time it's called on a sequence pair; the expensive part # of the computation is cached by cruncher if cruncher.real_quick_ratio() > best_ratio and \ cruncher.quick_ratio() > best_ratio and \ cruncher.ratio() > best_ratio: best_ratio, best_i, best_j = cruncher.ratio(), i, j if best_ratio < cutoff: # no non-identical "pretty close" pair if eqi is None: # no identical pair either -- treat it as a straight replace plain_replace(a, alo, ahi, b, blo, bhi) return # no close pair, but an identical pair -- synch up on that best_i, best_j, best_ratio = eqi, eqj, 1.0 else: # there's a close pair, so forget the identical pair (if any) eqi = None # a[best_i] very similar to b[best_j]; eqi is None iff they're not # identical if TRACE: print '*** best_ratio', best_ratio, best_i, best_j dump('>', a, best_i, best_i+1) dump('<', b, best_j, best_j+1) # pump out diffs from before the synch point fancy_helper(a, alo, best_i, b, blo, best_j) # do intraline marking on the synch pair aelt, belt = a[best_i], b[best_j] if eqi is None: # pump out a '-', '?', '+', '?' quad for the synched lines atags = btags = "" cruncher.set_seqs(aelt, belt) for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes(): la, lb = ai2 - ai1, bj2 - bj1 if tag == 'replace': atags = atags + '^' * la btags = btags + '^' * lb elif tag == 'delete': atags = atags + '-' * la elif tag == 'insert': btags = btags + '+' * lb elif tag == 'equal': atags = atags + ' ' * la btags = btags + ' ' * lb else: raise ValueError('unknown tag ' + `tag`) printq(aelt, belt, atags, btags) else: # the synch pair is identical print ' ', aelt, # pump out diffs from after the synch point fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi) def fancy_helper(a, alo, ahi, b, blo, bhi): if alo < ahi: if blo < bhi: fancy_replace(a, alo, ahi, b, blo, bhi) else: dump('-', a, alo, ahi) elif blo < bhi: dump('+', b, blo, bhi) # Crap to deal with leading tabs in "?" output. Can hurt, but will # probably help most of the time. def printq(aline, bline, atags, btags): common = min(count_leading(aline, "\t"), count_leading(bline, "\t")) common = min(common, count_leading(atags[:common], " ")) print "-", aline, if count_leading(atags, " ") < len(atags): print "?", "\t" * common + atags[common:] print "+", bline, if count_leading(btags, " ") < len(btags): print "?", "\t" * common + btags[common:] def count_leading(line, ch): i, n = 0, len(line) while i < n and line[i] == ch: i = i + 1 return i def fail(msg): import sys out = sys.stderr.write out(msg + "\n\n") out(__doc__) return 0 # open a file & return the file object; gripe and return 0 if it # couldn't be opened def fopen(fname): try: return open(fname, 'r') except IOError, detail: return fail("couldn't open " + fname + ": " + str(detail)) # open two files & spray the diff to stdout; return false iff a problem def fcompare(f1name, f2name): f1 = fopen(f1name) f2 = fopen(f2name) if not f1 or not f2: return 0 a = f1.readlines(); f1.close() b = f2.readlines(); f2.close() cruncher = SequenceMatcher(IS_LINE_JUNK, a, b) for tag, alo, ahi, blo, bhi in cruncher.get_opcodes(): if tag == 'replace': fancy_replace(a, alo, ahi, b, blo, bhi) elif tag == 'delete': dump('-', a, alo, ahi) elif tag == 'insert': dump('+', b, blo, bhi) elif tag == 'equal': dump(' ', a, alo, ahi) else: raise ValueError('unknown tag ' + `tag`) return 1 # crack args (sys.argv[1:] is normal) & compare; # return false iff a problem def main(args): import getopt try: opts, args = getopt.getopt(args, "qr:") except getopt.error, detail: return fail(str(detail)) noisy = 1 qseen = rseen = 0 for opt, val in opts: if opt == "-q": qseen = 1 noisy = 0 elif opt == "-r": rseen = 1 whichfile = val if qseen and rseen: return fail("can't specify both -q and -r") if rseen: if args: return fail("no args allowed with -r option") if whichfile in "12": restore(whichfile) return 1 return fail("-r value must be 1 or 2") if len(args) != 2: return fail("need 2 filename args") f1name, f2name = args if noisy: print '-:', f1name print '+:', f2name return fcompare(f1name, f2name) def restore(which): import sys tag = {"1": "- ", "2": "+ "}[which] prefixes = (" ", tag) for line in sys.stdin.readlines(): if line[:2] in prefixes: print line[2:], if __name__ == '__main__': import sys args = sys.argv[1:] if "-profile" in args: import profile, pstats args.remove("-profile") statf = "ndiff.pro" profile.run("main(args)", statf) stats = pstats.Stats(statf) stats.strip_dirs().sort_stats('time').print_stats() else: main(args) zope.tal-3.5.2/src/zope/tal/htmltalparser.py0000644000175000017500000002647711273124226020777 0ustar anthonyanthony############################################################################## # # Copyright (c) 2001, 2002 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Parse HTML and compile to TALInterpreter intermediate code. $Id: htmltalparser.py 76888 2007-06-21 10:11:17Z hdima $ """ from HTMLParser import HTMLParser, HTMLParseError from zope.tal.taldefs import (ZOPE_METAL_NS, ZOPE_TAL_NS, ZOPE_I18N_NS, METALError, TALError, I18NError) from zope.tal.talgenerator import TALGenerator BOOLEAN_HTML_ATTRS = frozenset([ # List of Boolean attributes in HTML that may be given in # minimized form (e.g. rather than ) # From http://www.w3.org/TR/xhtml1/#guidelines (C.10) "compact", "nowrap", "ismap", "declare", "noshade", "checked", "disabled", "readonly", "multiple", "selected", "noresize", "defer" ]) EMPTY_HTML_TAGS = frozenset([ # List of HTML tags with an empty content model; these are # rendered in minimized form, e.g. . # From http://www.w3.org/TR/xhtml1/#dtds "base", "meta", "link", "hr", "br", "param", "img", "area", "input", "col", "basefont", "isindex", "frame", ]) PARA_LEVEL_HTML_TAGS = frozenset([ # List of HTML elements that close open paragraph-level elements # and are themselves paragraph-level. "h1", "h2", "h3", "h4", "h5", "h6", "p", ]) BLOCK_CLOSING_TAG_MAP = { "tr": frozenset(["tr", "td", "th"]), "td": frozenset(["td", "th"]), "th": frozenset(["td", "th"]), "li": frozenset(["li"]), "dd": frozenset(["dd", "dt"]), "dt": frozenset(["dd", "dt"]), } BLOCK_LEVEL_HTML_TAGS = frozenset([ # List of HTML tags that denote larger sections than paragraphs. "blockquote", "table", "tr", "th", "td", "thead", "tfoot", "tbody", "noframe", "ul", "ol", "li", "dl", "dt", "dd", "div", ]) SECTION_LEVEL_HTML_TAGS = PARA_LEVEL_HTML_TAGS.union(BLOCK_LEVEL_HTML_TAGS) TIGHTEN_IMPLICIT_CLOSE_TAGS = PARA_LEVEL_HTML_TAGS.union(BLOCK_CLOSING_TAG_MAP) class NestingError(HTMLParseError): """Exception raised when elements aren't properly nested.""" def __init__(self, tagstack, endtag, position=(None, None)): self.endtag = endtag if tagstack: if len(tagstack) == 1: msg = ('Open tag <%s> does not match close tag ' % (tagstack[0], endtag)) else: msg = ('Open tags <%s> do not match close tag ' % ('>, <'.join(tagstack), endtag)) else: msg = 'No tags are open to match ' % endtag HTMLParseError.__init__(self, msg, position) class EmptyTagError(NestingError): """Exception raised when empty elements have an end tag.""" def __init__(self, tag, position=(None, None)): self.tag = tag msg = 'Close tag should be removed' % tag HTMLParseError.__init__(self, msg, position) class OpenTagError(NestingError): """Exception raised when a tag is not allowed in another tag.""" def __init__(self, tagstack, tag, position=(None, None)): self.tag = tag msg = 'Tag <%s> is not allowed in <%s>' % (tag, tagstack[-1]) HTMLParseError.__init__(self, msg, position) class HTMLTALParser(HTMLParser): # External API def __init__(self, gen=None): HTMLParser.__init__(self) if gen is None: gen = TALGenerator(xml=0) self.gen = gen self.tagstack = [] self.nsstack = [] self.nsdict = {'tal': ZOPE_TAL_NS, 'metal': ZOPE_METAL_NS, 'i18n': ZOPE_I18N_NS, } def parseFile(self, file): f = open(file) data = f.read() f.close() try: self.parseString(data) except TALError, e: e.setFile(file) raise def parseString(self, data): self.feed(data) self.close() while self.tagstack: self.implied_endtag(self.tagstack[-1], 2) assert self.nsstack == [], self.nsstack def getCode(self): return self.gen.getCode() # Overriding HTMLParser methods def handle_starttag(self, tag, attrs): self.close_para_tags(tag) self.scan_xmlns(attrs) tag, attrlist, taldict, metaldict, i18ndict \ = self.process_ns(tag, attrs) if tag in EMPTY_HTML_TAGS and "content" in taldict: raise TALError( "empty HTML tags cannot use tal:content: %s" % `tag`, self.getpos()) # Support for inline Python code. if tag == 'script': type_attr = [a for a in attrlist if a[0] == "type"] if type_attr and type_attr[0][1].startswith('text/server-'): attrlist.remove(type_attr[0]) taldict = {'script': type_attr[0][1], 'omit-tag': ''} self.tagstack.append(tag) self.gen.emitStartElement(tag, attrlist, taldict, metaldict, i18ndict, self.getpos()) if tag in EMPTY_HTML_TAGS: self.implied_endtag(tag, -1) def handle_startendtag(self, tag, attrs): self.close_para_tags(tag) self.scan_xmlns(attrs) tag, attrlist, taldict, metaldict, i18ndict \ = self.process_ns(tag, attrs) if "content" in taldict: if tag in EMPTY_HTML_TAGS: raise TALError( "empty HTML tags cannot use tal:content: %s" % `tag`, self.getpos()) self.gen.emitStartElement(tag, attrlist, taldict, metaldict, i18ndict, self.getpos()) self.gen.emitEndElement(tag, implied=-1, position=self.getpos()) else: self.gen.emitStartElement(tag, attrlist, taldict, metaldict, i18ndict, self.getpos(), isend=1) self.pop_xmlns() def handle_endtag(self, tag): if tag in EMPTY_HTML_TAGS: # etc. in the source is an error raise EmptyTagError(tag, self.getpos()) self.close_enclosed_tags(tag) self.gen.emitEndElement(tag, position=self.getpos()) self.pop_xmlns() self.tagstack.pop() def close_para_tags(self, tag): if tag in EMPTY_HTML_TAGS: return close_to = -1 if tag in BLOCK_CLOSING_TAG_MAP: blocks_to_close = BLOCK_CLOSING_TAG_MAP[tag] for i, t in enumerate(self.tagstack): if t in blocks_to_close: if close_to == -1: close_to = i elif t in BLOCK_LEVEL_HTML_TAGS: close_to = -1 elif tag in SECTION_LEVEL_HTML_TAGS: for i in range(len(self.tagstack) - 1, -1, -1): closetag = self.tagstack[i] if closetag in BLOCK_LEVEL_HTML_TAGS: break elif closetag in PARA_LEVEL_HTML_TAGS: if closetag != "p": raise OpenTagError(self.tagstack, tag, self.getpos()) close_to = i if close_to >= 0: while len(self.tagstack) > close_to: self.implied_endtag(self.tagstack[-1], 1) def close_enclosed_tags(self, tag): if tag not in self.tagstack: raise NestingError(self.tagstack, tag, self.getpos()) while tag != self.tagstack[-1]: self.implied_endtag(self.tagstack[-1], 1) assert self.tagstack[-1] == tag def implied_endtag(self, tag, implied): assert tag == self.tagstack[-1] assert implied in (-1, 1, 2) isend = (implied < 0) if tag in TIGHTEN_IMPLICIT_CLOSE_TAGS: # Pick out trailing whitespace from the program, and # insert the close tag before the whitespace. white = self.gen.unEmitWhitespace() else: white = None self.gen.emitEndElement(tag, isend=isend, implied=implied, position=self.getpos()) if white: self.gen.emitRawText(white) self.tagstack.pop() self.pop_xmlns() def handle_charref(self, name): self.gen.emitRawText("&#%s;" % name) def handle_entityref(self, name): self.gen.emitRawText("&%s;" % name) def handle_data(self, data): self.gen.emitRawText(data) def handle_comment(self, data): self.gen.emitRawText("" % data) def handle_decl(self, data): self.gen.emitRawText("" % data) def handle_pi(self, data): self.gen.emitRawText("" % data) # Internal thingies def scan_xmlns(self, attrs): nsnew = {} for key, value in attrs: if key.startswith("xmlns:"): nsnew[key[6:]] = value self.nsstack.append(self.nsdict) if nsnew: self.nsdict = self.nsdict.copy() self.nsdict.update(nsnew) def pop_xmlns(self): self.nsdict = self.nsstack.pop() _namespaces = { ZOPE_TAL_NS: "tal", ZOPE_METAL_NS: "metal", ZOPE_I18N_NS: "i18n", } def fixname(self, name): if ':' in name: prefix, suffix = name.split(':', 1) if prefix == 'xmlns': nsuri = self.nsdict.get(suffix) if nsuri in self._namespaces: return name, name, prefix else: nsuri = self.nsdict.get(prefix) if nsuri in self._namespaces: return name, suffix, self._namespaces[nsuri] return name, name, 0 def process_ns(self, name, attrs): attrlist = [] taldict = {} metaldict = {} i18ndict = {} name, namebase, namens = self.fixname(name) for item in attrs: key, value = item key, keybase, keyns = self.fixname(key) ns = keyns or namens # default to tag namespace if ns and ns != 'unknown': item = (key, value, ns) if ns == 'tal': if keybase in taldict: raise TALError("duplicate TAL attribute " + repr(keybase), self.getpos()) taldict[keybase] = value elif ns == 'metal': if keybase in metaldict: raise METALError("duplicate METAL attribute " + repr(keybase), self.getpos()) metaldict[keybase] = value elif ns == 'i18n': if keybase in i18ndict: raise I18NError("duplicate i18n attribute " + repr(keybase), self.getpos()) i18ndict[keybase] = value attrlist.append(item) if namens in ('metal', 'tal', 'i18n'): taldict['tal tag'] = namens return name, attrlist, taldict, metaldict, i18ndict zope.tal-3.5.2/src/zope/tal/dummyengine.py0000644000175000017500000002463311273124226020426 0ustar anthonyanthony############################################################################## # # Copyright (c) 2001, 2002, 2003 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Dummy TAL expression engine so that I can test out the TAL implementation. $Id: dummyengine.py 93717 2008-12-06 13:25:25Z MatthewWilkes $ """ import re from zope.interface import implements from zope.tal.taldefs import NAME_RE, TALExpressionError, ErrorInfo from zope.tal.interfaces import ITALExpressionCompiler, ITALExpressionEngine from zope.i18nmessageid import Message Default = object() name_match = re.compile(r"(?s)(%s):(.*)\Z" % NAME_RE).match class CompilerError(Exception): pass class DummyEngine(object): position = None source_file = None implements(ITALExpressionCompiler, ITALExpressionEngine) def __init__(self, macros=None): if macros is None: macros = {} self.macros = macros dict = {'nothing': None, 'default': Default} self.locals = self.globals = dict self.stack = [dict] self.translationDomain = DummyTranslationDomain() self.useEngineAttrDicts = False # zope.tal.interfaces.ITALExpressionCompiler def getCompilerError(self): return CompilerError def compile(self, expr): return "$%s$" % expr # zope.tal.interfaces.ITALExpressionEngine def setSourceFile(self, source_file): self.source_file = source_file def setPosition(self, position): self.position = position def beginScope(self): self.stack.append(self.locals) def endScope(self): assert len(self.stack) > 1, "more endScope() than beginScope() calls" self.locals = self.stack.pop() def setLocal(self, name, value): if self.locals is self.stack[-1]: # Unmerge this scope's locals from previous scope of first set self.locals = self.locals.copy() self.locals[name] = value def setGlobal(self, name, value): self.globals[name] = value def getValue(self, name, default=None): value = self.globals.get(name, default) if value is default: value = self.locals.get(name, default) return value def evaluate(self, expression): assert expression.startswith("$") and expression.endswith("$"), \ expression expression = expression[1:-1] m = name_match(expression) if m: type, expr = m.group(1, 2) else: type = "path" expr = expression if type in ("string", "str"): return expr if type in ("path", "var", "global", "local"): return self.evaluatePathOrVar(expr) if type == "not": return not self.evaluate(expr) if type == "exists": return self.locals.has_key(expr) or self.globals.has_key(expr) if type == "python": try: return eval(expr, self.globals, self.locals) except: raise TALExpressionError("evaluation error in %s" % `expr`) if type == "position": # Insert the current source file name, line number, # and column offset. if self.position: lineno, offset = self.position else: lineno, offset = None, None return '%s (%s,%s)' % (self.source_file, lineno, offset) raise TALExpressionError("unrecognized expression: " + `expression`) # implementation; can be overridden def evaluatePathOrVar(self, expr): expr = expr.strip() if self.locals.has_key(expr): return self.locals[expr] elif self.globals.has_key(expr): return self.globals[expr] else: raise TALExpressionError("unknown variable: %s" % `expr`) def evaluateValue(self, expr): return self.evaluate(expr) def evaluateBoolean(self, expr): return self.evaluate(expr) def evaluateText(self, expr): text = self.evaluate(expr) if isinstance(text, (str, unicode, Message)): return text if text is not None and text is not Default: text = str(text) return text def evaluateStructure(self, expr): # TODO Should return None or a DOM tree return self.evaluate(expr) # implementation; can be overridden def evaluateSequence(self, expr): # TODO: Should return a sequence return self.evaluate(expr) def evaluateMacro(self, macroName): assert macroName.startswith("$") and macroName.endswith("$"), \ macroName macroName = macroName[1:-1] file, localName = self.findMacroFile(macroName) if not file: # Local macro macro = self.macros[localName] else: # External macro import driver program, macros = driver.compilefile(file) macro = macros.get(localName) if not macro: raise TALExpressionError("macro %s not found in file %s" % (localName, file)) return macro # internal def findMacroFile(self, macroName): if not macroName: raise TALExpressionError("empty macro name") i = macroName.rfind('/') if i < 0: # No slash -- must be a locally defined macro return None, macroName else: # Up to last slash is the filename fileName = macroName[:i] localName = macroName[i+1:] return fileName, localName def setRepeat(self, name, expr): seq = self.evaluateSequence(expr) return Iterator(name, seq, self) def createErrorInfo(self, err, position): return ErrorInfo(err, position) def getDefault(self): return Default def translate(self, msgid, domain=None, mapping=None, default=None): self.translationDomain.domain = domain return self.translationDomain.translate( msgid, mapping, default=default) def evaluateCode(self, lang, code): # We probably implement too much, but I use the dummy engine to test # some of the issues that we will have. # For testing purposes only locals = {} globals = {} if self.useEngineAttrDicts: globals = self.globals.copy() locals = self.locals.copy() assert lang == 'text/server-python' import sys, StringIO # Removing probable comments if code.strip().startswith(''): code = code.strip()[4:-3] # Prepare code. lines = code.split('\n') lines = filter(lambda l: l.strip() != '', lines) code = '\n'.join(lines) # This saves us from all indentation issues :) if code.startswith(' ') or code.startswith('\t'): code = 'if 1 == 1:\n' + code + '\n' tmp = sys.stdout sys.stdout = StringIO.StringIO() try: exec code in globals, locals finally: result = sys.stdout sys.stdout = tmp # For testing purposes only self.codeLocals = locals self.codeGlobals = globals self.locals.update(locals) self.globals.update(globals) return result.getvalue() class Iterator(object): def __init__(self, name, seq, engine): self.name = name self.seq = seq self.engine = engine self.nextIndex = 0 def next(self): i = self.nextIndex try: item = self.seq[i] except IndexError: return 0 self.nextIndex = i+1 self.engine.setLocal(self.name, item) return 1 class DummyTranslationDomain(object): domain = '' msgids = {} def appendMsgid(self, domain, data): if not self.msgids.has_key(domain): self.msgids[domain] = [] self.msgids[domain].append(data) def getMsgids(self, domain): return self.msgids[domain] def clearMsgids(self): self.msgids = {} def translate(self, msgid, mapping=None, context=None, target_language=None, default=None): domain = self.domain # This is a fake translation service which simply uppercases non # ${name} placeholder text in the message id. # # First, transform a string with ${name} placeholders into a list of # substrings. Then upcase everything but the placeholders, then glue # things back together. # If the domain is a string method, then transform the string # by calling that method. # MessageID attributes override arguments if isinstance(msgid, Message): domain = msgid.domain mapping = msgid.mapping default = msgid.default if default is None: # Message doesn't substitute itself for default = msgid # missing default # simulate an unknown msgid by returning None if msgid == "don't translate me": text = default elif domain and hasattr('', domain): text = getattr(msgid, domain)() else: domain = 'default' text = msgid.upper() self.appendMsgid(domain, (msgid, mapping)) def repl(m): return unicode(mapping[m.group(m.lastindex).lower()]) cre = re.compile(r'\$(?:([_A-Za-z][-\w]*)|\{([_A-Za-z][-\w]*)\})') return cre.sub(repl, text) class MultipleDomainsDummyEngine(DummyEngine): def translate(self, msgid, domain=None, mapping=None, default=None): if isinstance(msgid, Message): domain = msgid.domain if domain == 'a_very_explicit_domain_setup_by_template_developer_that_wont_be_taken_into_account_by_the_ZPT_engine': domain = 'lower' self.translationDomain.domain = domain return self.translationDomain.translate( msgid, mapping, default=default) zope.tal-3.5.2/src/zope/tal/taldefs.py0000644000175000017500000001336611273124226017530 0ustar anthonyanthony############################################################################## # # Copyright (c) 2001, 2002 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Common definitions used by TAL and METAL compilation and transformation. $Id: taldefs.py 41477 2006-01-28 19:52:03Z hdima $ """ import re from zope.tal.interfaces import ITALExpressionErrorInfo from zope.interface import implements TAL_VERSION = "1.6" XML_NS = "http://www.w3.org/XML/1998/namespace" # URI for XML namespace XMLNS_NS = "http://www.w3.org/2000/xmlns/" # URI for XML NS declarations ZOPE_TAL_NS = "http://xml.zope.org/namespaces/tal" ZOPE_METAL_NS = "http://xml.zope.org/namespaces/metal" ZOPE_I18N_NS = "http://xml.zope.org/namespaces/i18n" # This RE must exactly match the expression of the same name in the # zope.i18n.simpletranslationservice module: NAME_RE = "[a-zA-Z_][-a-zA-Z0-9_]*" KNOWN_METAL_ATTRIBUTES = frozenset([ "define-macro", "extend-macro", "use-macro", "define-slot", "fill-slot", ]) KNOWN_TAL_ATTRIBUTES = frozenset([ "define", "condition", "content", "replace", "repeat", "attributes", "on-error", "omit-tag", "script", "tal tag", # a pseudo attribute that holds the namespace of elements # like , , ]) KNOWN_I18N_ATTRIBUTES = frozenset([ "translate", "domain", "target", "source", "attributes", "data", "name", ]) class TALError(Exception): def __init__(self, msg, position=(None, None)): assert msg != "" self.msg = msg self.lineno = position[0] self.offset = position[1] self.filename = None def setFile(self, filename): self.filename = filename def __str__(self): result = self.msg if self.lineno is not None: result = result + ", at line %d" % self.lineno if self.offset is not None: result = result + ", column %d" % (self.offset + 1) if self.filename is not None: result = result + ', in file %s' % self.filename return result class METALError(TALError): pass class TALExpressionError(TALError): pass class I18NError(TALError): pass class ErrorInfo(object): implements(ITALExpressionErrorInfo) def __init__(self, err, position=(None, None)): if isinstance(err, Exception): self.type = err.__class__ self.value = err else: self.type = err self.value = None self.lineno = position[0] self.offset = position[1] _attr_re = re.compile(r"\s*([^\s]+)\s+([^\s].*)\Z", re.S) _subst_re = re.compile(r"\s*(?:(text|structure)\s+)?(.*)\Z", re.S) def parseAttributeReplacements(arg, xml): dict = {} for part in splitParts(arg): m = _attr_re.match(part) if not m: raise TALError("Bad syntax in attributes: %r" % part) name, expr = m.groups() if not xml: name = name.lower() if name in dict: raise TALError("Duplicate attribute name in attributes: %r" % part) dict[name] = expr return dict def parseSubstitution(arg, position=(None, None)): m = _subst_re.match(arg) if not m: raise TALError("Bad syntax in substitution text: %r" % arg, position) key, expr = m.groups() if not key: key = "text" return key, expr def splitParts(arg): # Break in pieces at undoubled semicolons and # change double semicolons to singles: arg = arg.replace(";;", "\0") parts = arg.split(';') parts = [p.replace("\0", ";") for p in parts] if len(parts) > 1 and not parts[-1].strip(): del parts[-1] # It ended in a semicolon return parts def isCurrentVersion(program): version = getProgramVersion(program) return version == TAL_VERSION def isinstance_(ob, type): # Proxy-friendly and faster isinstance_ check for new-style objects try: return type in ob.__class__.__mro__ except AttributeError: return False def getProgramMode(program): version = getProgramVersion(program) if (version == TAL_VERSION and isinstance_(program[1], tuple) and len(program[1]) == 2): opcode, mode = program[1] if opcode == "mode": return mode return None def getProgramVersion(program): if (len(program) >= 2 and isinstance_(program[0], tuple) and len(program[0]) == 2): opcode, version = program[0] if opcode == "version": return version return None _ent1_re = re.compile('&(?![A-Z#])', re.I) _entch_re = re.compile('&([A-Z][A-Z0-9]*)(?![A-Z0-9;])', re.I) _entn1_re = re.compile('&#(?![0-9X])', re.I) _entnx_re = re.compile('&(#X[A-F0-9]*)(?![A-F0-9;])', re.I) _entnd_re = re.compile('&(#[0-9][0-9]*)(?![0-9;])') def attrEscape(s): """Replace special characters '&<>' by character entities, except when '&' already begins a syntactically valid entity.""" s = _ent1_re.sub('&', s) s = _entch_re.sub(r'&\1', s) s = _entn1_re.sub('&#', s) s = _entnx_re.sub(r'&\1', s) s = _entnd_re.sub(r'&\1', s) s = s.replace('<', '<') s = s.replace('>', '>') s = s.replace('"', '"') return s import cgi def quote(s, escape=cgi.escape): return '"%s"' % escape(s, 1) del cgi zope.tal-3.5.2/src/zope/tal/__init__.py0000644000175000017500000000007511273124226017636 0ustar anthonyanthony# # This file is necessary to make this directory a package. zope.tal-3.5.2/src/zope/tal/benchmark/0000755000175000017500000000000011336275656017473 5ustar anthonyanthonyzope.tal-3.5.2/src/zope/tal/benchmark/dtml04.html0000644000175000017500000000025411273124224021446 0ustar anthonyanthony &dtml-x0; &dtml-x1; &dtml-x2; &dtml-x3; zope.tal-3.5.2/src/zope/tal/benchmark/tal02.html0000644000175000017500000000764011273124224021272 0ustar anthonyanthony A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. zope.tal-3.5.2/src/zope/tal/benchmark/dtml12.html0000644000175000017500000000061311273124224021444 0ustar anthonyanthony &dtml-y0; &dtml-y1; &dtml-y2; &dtml-y3; &dtml-y4; &dtml-y5; &dtml-y6; &dtml-y7; zope.tal-3.5.2/src/zope/tal/benchmark/dtml08.html0000644000175000017500000000451111273124224021452 0ustar anthonyanthony &dtml-x0; &dtml-x1; &dtml-x2; &dtml-x3; &dtml-x4; &dtml-x5; &dtml-x6; &dtml-x7; &dtml-x0; &dtml-x1; &dtml-x2; &dtml-x3; &dtml-x4; &dtml-x5; &dtml-x6; &dtml-x7; &dtml-x0; &dtml-x1; &dtml-x2; &dtml-x3; &dtml-x4; &dtml-x5; &dtml-x6; &dtml-x7; &dtml-x0; &dtml-x1; &dtml-x2; &dtml-x3; &dtml-x4; &dtml-x5; &dtml-x6; &dtml-x7; &dtml-x0; &dtml-x1; &dtml-x2; &dtml-x3; &dtml-x4; &dtml-x5; &dtml-x6; &dtml-x7; &dtml-x0; &dtml-x1; &dtml-x2; &dtml-x3; &dtml-x4; &dtml-x5; &dtml-x6; &dtml-x7; &dtml-x0; &dtml-x1; &dtml-x2; &dtml-x3; &dtml-x4; &dtml-x5; &dtml-x6; &dtml-x7; &dtml-x0; &dtml-x1; &dtml-x2; &dtml-x3; &dtml-x4; &dtml-x5; &dtml-x6; &dtml-x7; zope.tal-3.5.2/src/zope/tal/benchmark/dtml10.html0000644000175000017500000000767111273124224021455 0ustar anthonyanthony A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. zope.tal-3.5.2/src/zope/tal/benchmark/dtml09.html0000644000175000017500000000050111273124224021446 0ustar anthonyanthony &dtml-x0; &dtml-x1; &dtml-x2; &dtml-x3; &dtml-x4; &dtml-x5; &dtml-x6; &dtml-x7; zope.tal-3.5.2/src/zope/tal/benchmark/dtml11.html0000644000175000017500000000773611273124224021460 0ustar anthonyanthony &dtml-x0; A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. zope.tal-3.5.2/src/zope/tal/benchmark/tal09.html0000644000175000017500000000062011273124224021270 0ustar anthonyanthony zope.tal-3.5.2/src/zope/tal/benchmark/tal12.html0000644000175000017500000000073711273124224021273 0ustar anthonyanthony zope.tal-3.5.2/src/zope/tal/benchmark/tal10.html0000644000175000017500000000771011273124224021267 0ustar anthonyanthony A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. zope.tal-3.5.2/src/zope/tal/benchmark/tal06.html0000644000175000017500000000073511273124224021274 0ustar anthonyanthony zope.tal-3.5.2/src/zope/tal/benchmark/dtml05.html0000644000175000017500000000050011273124224021441 0ustar anthonyanthony &dtml-x0; &dtml-x1; &dtml-x2; &dtml-x3; &dtml-x4; &dtml-x5; &dtml-x6; &dtml-x7; zope.tal-3.5.2/src/zope/tal/benchmark/dtml07.html0000644000175000017500000000451111273124224021451 0ustar anthonyanthony &dtml-x0; &dtml-x1; &dtml-x2; &dtml-x3; &dtml-x4; &dtml-x5; &dtml-x6; &dtml-x7; &dtml-x0; &dtml-x1; &dtml-x2; &dtml-x3; &dtml-x4; &dtml-x5; &dtml-x6; &dtml-x7; &dtml-x0; &dtml-x1; &dtml-x2; &dtml-x3; &dtml-x4; &dtml-x5; &dtml-x6; &dtml-x7; &dtml-x0; &dtml-x1; &dtml-x2; &dtml-x3; &dtml-x4; &dtml-x5; &dtml-x6; &dtml-x7; &dtml-x0; &dtml-x1; &dtml-x2; &dtml-x3; &dtml-x4; &dtml-x5; &dtml-x6; &dtml-x7; &dtml-x0; &dtml-x1; &dtml-x2; &dtml-x3; &dtml-x4; &dtml-x5; &dtml-x6; &dtml-x7; &dtml-x0; &dtml-x1; &dtml-x2; &dtml-x3; &dtml-x4; &dtml-x5; &dtml-x6; &dtml-x7; &dtml-x0; &dtml-x1; &dtml-x2; &dtml-x3; &dtml-x4; &dtml-x5; &dtml-x6; &dtml-x7; zope.tal-3.5.2/src/zope/tal/benchmark/dtml01.html0000644000175000017500000000001111273124224021432 0ustar anthonyanthonybaseline zope.tal-3.5.2/src/zope/tal/benchmark/tal11.html0000644000175000017500000000776511273124224021302 0ustar anthonyanthony A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. zope.tal-3.5.2/src/zope/tal/benchmark/tal03.html0000644000175000017500000000055011273124224021264 0ustar anthonyanthony zope.tal-3.5.2/src/zope/tal/benchmark/tal08.html0000644000175000017500000000731111273124224021273 0ustar anthonyanthony zope.tal-3.5.2/src/zope/tal/benchmark/__init__.py0000644000175000017500000000007511273124224021566 0ustar anthonyanthony# # This file is necessary to make this directory a package. zope.tal-3.5.2/src/zope/tal/benchmark/tal04.html0000644000175000017500000000033311273124224021264 0ustar anthonyanthony zope.tal-3.5.2/src/zope/tal/benchmark/tal01.html0000644000175000017500000000001111273124224021252 0ustar anthonyanthonybaseline zope.tal-3.5.2/src/zope/tal/benchmark/dtml03.html0000644000175000017500000000045011273124224021443 0ustar anthonyanthony &dtml-x0; &dtml-x1; &dtml-x2; &dtml-x3; &dtml-x4; &dtml-x5; &dtml-x6; &dtml-x7; zope.tal-3.5.2/src/zope/tal/benchmark/dtml06.html0000644000175000017500000000056011273124224021450 0ustar anthonyanthony &dtml-x0; &dtml-x1; &dtml-x2; &dtml-x3; &dtml-x4; &dtml-x5; &dtml-x6; &dtml-x7; zope.tal-3.5.2/src/zope/tal/benchmark/tal05.html0000644000175000017500000000061711273124224021272 0ustar anthonyanthony zope.tal-3.5.2/src/zope/tal/benchmark/dtml02.html0000644000175000017500000000764011273124224021452 0ustar anthonyanthony A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. A large chunk of text to be repeated. zope.tal-3.5.2/src/zope/tal/benchmark/tal07.html0000644000175000017500000000551111273124224021272 0ustar anthonyanthony zope.tal-3.5.2/src/zope/tal/talinterpreter.py0000644000175000017500000011303411273124226021143 0ustar anthonyanthony############################################################################## # # Copyright (c) 2001, 2002 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Interpreter for a pre-compiled TAL program. $Id: talinterpreter.py 87220 2008-06-07 03:08:35Z fdrake $ """ import cgi import operator import sys import warnings # Do not use cStringIO here! It's not unicode aware. :( from StringIO import StringIO from zope.i18nmessageid import Message from zope.tal.taldefs import quote, TAL_VERSION, METALError from zope.tal.taldefs import isCurrentVersion from zope.tal.taldefs import getProgramVersion, getProgramMode from zope.tal.talgenerator import TALGenerator from zope.tal.translationcontext import TranslationContext # Avoid constructing this tuple over and over I18nMessageTypes = (Message,) TypesToTranslate = I18nMessageTypes + (str, unicode) BOOLEAN_HTML_ATTRS = frozenset([ # List of Boolean attributes in HTML that should be rendered in # minimized form (e.g. rather than ) # From http://www.w3.org/TR/xhtml1/#guidelines (C.10) # TODO: The problem with this is that this is not valid XML and # can't be parsed back! "compact", "nowrap", "ismap", "declare", "noshade", "checked", "disabled", "readonly", "multiple", "selected", "noresize", "defer" ]) _nulljoin = ''.join _spacejoin = ' '.join def normalize(text): # Now we need to normalize the whitespace in implicit message ids and # implicit $name substitution values by stripping leading and trailing # whitespace, and folding all internal whitespace to a single space. return _spacejoin(text.split()) class AltTALGenerator(TALGenerator): def __init__(self, repldict, expressionCompiler=None, xml=0): self.repldict = repldict self.enabled = 1 TALGenerator.__init__(self, expressionCompiler, xml) def enable(self, enabled): self.enabled = enabled def emit(self, *args): if self.enabled: TALGenerator.emit(self, *args) def emitStartElement(self, name, attrlist, taldict, metaldict, i18ndict, position=(None, None), isend=0): metaldict = {} taldict = {} i18ndict = {} if self.enabled and self.repldict: taldict["attributes"] = "x x" TALGenerator.emitStartElement(self, name, attrlist, taldict, metaldict, i18ndict, position, isend) def replaceAttrs(self, attrlist, repldict): if self.enabled and self.repldict: repldict = self.repldict self.repldict = None return TALGenerator.replaceAttrs(self, attrlist, repldict) class MacroStackItem(list): # This is a `list` subclass for backward compability. """Stack entry for the TALInterpreter.macroStack. This offers convenience attributes for more readable access. """ __slots__ = () # These would be nicer using @syntax, but that would require # Python 2.4.x; this will do for now. macroName = property(lambda self: self[0]) slots = property(lambda self: self[1]) definingName = property(lambda self: self[2]) extending = property(lambda self: self[3]) entering = property(lambda self: self[4], lambda self, value: operator.setitem(self, 4, value)) i18nContext = property(lambda self: self[5]) class TALInterpreter(object): """TAL interpreter. Some notes on source annotations. They are HTML/XML comments added to the output whenever sourceFile is changed by a setSourceFile bytecode. Source annotations are disabled by default, but you can turn them on by passing a sourceAnnotations argument to the constructor. You can change the format of the annotations by overriding formatSourceAnnotation in a subclass. The output of the annotation is delayed until some actual text is output for two reasons: 1. setPosition bytecode follows setSourceFile, and we need position information to output the line number. 2. Comments are not allowed in XML documents before the declaration. For performance reasons (TODO: premature optimization?) instead of checking the value of _pending_source_annotation on every write to the output stream, the _stream_write attribute is changed to point to _annotated_stream_write method whenever _pending_source_annotation is set to True, and to _stream.write when it is False. The following invariant always holds: if self._pending_source_annotation: assert self._stream_write is self._annotated_stream_write else: assert self._stream_write is self.stream.write """ def __init__(self, program, macros, engine, stream=None, debug=0, wrap=60, 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: 60). 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 def StringIO(self): # Third-party products wishing to provide a full Unicode-aware # StringIO can do so by monkey-patching this method. return FasterStringIO() def saveState(self): return (self.position, self.col, self.stream, self._stream_stack, self.scopeLevel, self.level, self.i18nContext) def restoreState(self, state): (self.position, self.col, self.stream, self._stream_stack, scopeLevel, level, i18n) = state if self._pending_source_annotation: self._stream_write = self._annotated_stream_write else: self._stream_write = self.stream.write assert self.level == level while self.scopeLevel > scopeLevel: self.engine.endScope() self.scopeLevel = self.scopeLevel - 1 self.engine.setPosition(self.position) self.i18nContext = i18n def restoreOutputState(self, state): (dummy, self.col, self.stream, self._stream_stack, scopeLevel, level, i18n) = state if self._pending_source_annotation: self._stream_write = self._annotated_stream_write else: self._stream_write = self.stream.write assert self.level == level assert self.scopeLevel == scopeLevel def pushMacro(self, macroName, slots, definingName, extending): if len(self.macroStack) >= self.stackLimit: raise METALError("macro nesting limit (%d) exceeded " "by %s" % (self.stackLimit, `macroName`)) self.macroStack.append( MacroStackItem((macroName, slots, definingName, extending, True, self.i18nContext))) def popMacro(self): return self.macroStack.pop() def __call__(self): assert self.level == 0 assert self.scopeLevel == 0 assert self.i18nContext.parent is None self.interpret(self.program) assert self.level == 0 assert self.scopeLevel == 0 assert self.i18nContext.parent is None def pushStream(self, newstream): self._stream_stack.append(self.stream) self.stream = newstream if self._pending_source_annotation: self._stream_write = self._annotated_stream_write else: self._stream_write = self.stream.write def popStream(self): self.stream = self._stream_stack.pop() if self._pending_source_annotation: self._stream_write = self._annotated_stream_write else: self._stream_write = self.stream.write def _annotated_stream_write(self, s): idx = s.find('= 0 or s.isspace(): # Do not preprend comments in front of the declaration. end_of_doctype = s.find('?>', idx) if end_of_doctype > idx: self.stream.write(s[:end_of_doctype+2]) s = s[end_of_doctype+2:] # continue else: self.stream.write(s) return self._pending_source_annotation = False self._stream_write = self.stream.write self._stream_write(self.formatSourceAnnotation()) self._stream_write(s) def formatSourceAnnotation(self): lineno = self.position[0] if lineno is None: location = self.sourceFile else: location = '%s (line %s)' % (self.sourceFile, lineno) sep = '=' * 78 return '' % (sep, location, sep) def stream_write(self, s, len=len): self._stream_write(s) i = s.rfind('\n') if i < 0: self.col = self.col + len(s) else: self.col = len(s) - (i + 1) bytecode_handlers = {} def interpret(self, program): oldlevel = self.level self.level = oldlevel + 1 handlers = self.dispatch try: if self.debug: for (opcode, args) in program: s = "%sdo_%s(%s)\n" % (" "*self.level, opcode, repr(args)) if len(s) > 80: s = s[:76] + "...\n" sys.stderr.write(s) handlers[opcode](self, args) else: for (opcode, args) in program: handlers[opcode](self, args) finally: self.level = oldlevel def do_version(self, version): assert version == TAL_VERSION bytecode_handlers["version"] = do_version def do_mode(self, mode): assert mode in ("html", "xml") self.html = (mode == "html") if self.html: self.endsep = " />" else: self.endsep = "/>" self.endlen = len(self.endsep) bytecode_handlers["mode"] = do_mode def do_setSourceFile(self, source_file): self.sourceFile = source_file self.engine.setSourceFile(source_file) if self.sourceAnnotations: self._pending_source_annotation = True self._stream_write = self._annotated_stream_write bytecode_handlers["setSourceFile"] = do_setSourceFile def do_setPosition(self, position): self.position = position self.engine.setPosition(position) bytecode_handlers["setPosition"] = do_setPosition def do_startEndTag(self, stuff): self.do_startTag(stuff, self.endsep, self.endlen) bytecode_handlers["startEndTag"] = do_startEndTag def do_startTag(self, (name, attrList), end=">", endlen=1, _len=len): # The bytecode generator does not cause calls to this method # for start tags with no attributes; those are optimized down # to rawtext events. Hence, there is no special "fast path" # for that case. self._currentTag = name L = ["<", name] append = L.append col = self.col + _len(name) + 1 wrap = self.wrap align = col + 1 if align >= wrap/2: align = 4 # Avoid a narrow column far to the right attrAction = self.dispatch[""] try: for item in attrList: if _len(item) == 2: rendered = item[1:] else: # item[2] is the 'action' field: if item[2] in ('metal', 'tal', 'xmlns', 'i18n'): if not self.showtal: continue rendered = self.attrAction(item) else: rendered = attrAction(self, item) if not rendered: continue for s in rendered: slen = _len(s) if (wrap and col >= align and col + 1 + slen > wrap): append("\n") append(" "*align) col = align + slen else: append(" ") col = col + 1 + slen append(s) append(end) col = col + endlen finally: self._stream_write(_nulljoin(L)) self.col = col bytecode_handlers["startTag"] = do_startTag def attrAction(self, item): name, value, action = item[:3] if action == 'insert': return () macs = self.macroStack if action == 'metal' and self.metal and macs: # Drop all METAL attributes at a use-depth beyond the first # use-macro and its extensions if len(macs) > 1: for macro in macs[1:]: if not macro.extending: return () if not macs[-1].entering: return () macs[-1].entering = False # Convert or drop depth-one METAL attributes. i = name.rfind(":") + 1 prefix, suffix = name[:i], name[i:] if suffix == "define-macro": # Convert define-macro as we enter depth one. useName = macs[0].macroName defName = macs[0].definingName res = [] if defName: res.append('%sdefine-macro=%s' % (prefix, quote(defName))) if useName: res.append('%suse-macro=%s' % (prefix, quote(useName))) return res elif suffix == "define-slot": name = prefix + "fill-slot" elif suffix == "fill-slot": pass else: return () if value is None: value = name else: value = "%s=%s" % (name, quote(value)) return [value] def attrAction_tal(self, item): name, value, action = item[:3] ok = 1 expr, xlat, msgid = item[3:] if self.html and name.lower() in BOOLEAN_HTML_ATTRS: evalue = self.engine.evaluateBoolean(item[3]) if evalue is self.Default: if action == 'insert': # Cancelled insert ok = 0 elif evalue: value = None else: ok = 0 elif expr is not None: evalue = self.engine.evaluateText(item[3]) if evalue is self.Default: if action == 'insert': # Cancelled insert ok = 0 else: if evalue is None: ok = 0 value = evalue if ok: if xlat: translated = self.translate(msgid or value, value) if translated is not None: value = translated elif isinstance(value, I18nMessageTypes): translated = self.translate(value) if translated is not None: value = translated if value is None: value = name return ["%s=%s" % (name, quote(value))] else: return () bytecode_handlers[""] = attrAction def no_tag(self, start, program): state = self.saveState() self.stream = stream = self.StringIO() self._stream_write = stream.write self.interpret(start) self.restoreOutputState(state) self.interpret(program) def do_optTag(self, (name, cexpr, tag_ns, isend, start, program), omit=0): if tag_ns and not self.showtal: return self.no_tag(start, program) self.interpret(start) if not isend: self.interpret(program) s = '' % name self._stream_write(s) self.col = self.col + len(s) def do_optTag_tal(self, stuff): cexpr = stuff[1] if cexpr is not None and (cexpr == '' or self.engine.evaluateBoolean(cexpr)): self.no_tag(stuff[-2], stuff[-1]) else: self.do_optTag(stuff) bytecode_handlers["optTag"] = do_optTag def do_rawtextBeginScope(self, (s, col, position, closeprev, dict)): self._stream_write(s) self.col = col self.do_setPosition(position) if closeprev: engine = self.engine engine.endScope() engine.beginScope() else: self.engine.beginScope() self.scopeLevel = self.scopeLevel + 1 def do_rawtextBeginScope_tal(self, (s, col, position, closeprev, dict)): self._stream_write(s) self.col = col engine = self.engine self.position = position engine.setPosition(position) if closeprev: engine.endScope() engine.beginScope() else: engine.beginScope() self.scopeLevel = self.scopeLevel + 1 engine.setLocal("attrs", dict) bytecode_handlers["rawtextBeginScope"] = do_rawtextBeginScope def do_beginScope(self, dict): self.engine.beginScope() self.scopeLevel = self.scopeLevel + 1 def do_beginScope_tal(self, dict): engine = self.engine engine.beginScope() engine.setLocal("attrs", dict) self.scopeLevel = self.scopeLevel + 1 bytecode_handlers["beginScope"] = do_beginScope def do_endScope(self, notused=None): self.engine.endScope() self.scopeLevel = self.scopeLevel - 1 bytecode_handlers["endScope"] = do_endScope def do_setLocal(self, notused): pass def do_setLocal_tal(self, (name, expr)): self.engine.setLocal(name, self.engine.evaluateValue(expr)) bytecode_handlers["setLocal"] = do_setLocal def do_setGlobal_tal(self, (name, expr)): self.engine.setGlobal(name, self.engine.evaluateValue(expr)) bytecode_handlers["setGlobal"] = do_setLocal def do_beginI18nContext(self, settings): get = settings.get self.i18nContext = TranslationContext(self.i18nContext, domain=get("domain"), source=get("source"), target=get("target")) bytecode_handlers["beginI18nContext"] = do_beginI18nContext def do_endI18nContext(self, notused=None): self.i18nContext = self.i18nContext.parent assert self.i18nContext is not None bytecode_handlers["endI18nContext"] = do_endI18nContext def do_insertText(self, stuff): self.interpret(stuff[1]) bytecode_handlers["insertText"] = do_insertText bytecode_handlers["insertI18nText"] = do_insertText def _writeText(self, text): # '&' must be done first! s = text.replace( "&", "&").replace("<", "<").replace(">", ">") self._stream_write(s) i = s.rfind('\n') if i < 0: self.col += len(s) else: self.col = len(s) - (i + 1) def do_insertText_tal(self, stuff): text = self.engine.evaluateText(stuff[0]) if text is None: return if text is self.Default: self.interpret(stuff[1]) return if isinstance(text, I18nMessageTypes): # Translate this now. text = self.translate(text) self._writeText(text) def do_insertI18nText_tal(self, stuff): # TODO: Code duplication is BAD, we need to fix it later text = self.engine.evaluateText(stuff[0]) if text is not None: if text is self.Default: self.interpret(stuff[1]) else: if isinstance(text, TypesToTranslate): text = self.translate(text) self._writeText(text) def do_i18nVariable(self, stuff): varname, program, expression, structure = stuff if expression is None: # The value is implicitly the contents of this tag, so we have to # evaluate the mini-program to get the value of the variable. state = self.saveState() try: tmpstream = self.StringIO() self.pushStream(tmpstream) try: self.interpret(program) finally: self.popStream() if self.html and self._currentTag == "pre": value = tmpstream.getvalue() else: value = normalize(tmpstream.getvalue()) finally: self.restoreState(state) else: # TODO: Seems like this branch not used anymore, we # need to remove it # Evaluate the value to be associated with the variable in the # i18n interpolation dictionary. if structure: value = self.engine.evaluateStructure(expression) else: value = self.engine.evaluate(expression) # evaluate() does not do any I18n, so we do it here. if isinstance(value, I18nMessageTypes): # Translate this now. value = self.translate(value) if not structure: value = cgi.escape(unicode(value)) # Either the i18n:name tag is nested inside an i18n:translate in which # case the last item on the stack has the i18n dictionary and string # representation, or the i18n:name and i18n:translate attributes are # in the same tag, in which case the i18nStack will be empty. In that # case we can just output the ${name} to the stream i18ndict, srepr = self.i18nStack[-1] i18ndict[varname] = value placeholder = '${%s}' % varname srepr.append(placeholder) self._stream_write(placeholder) bytecode_handlers['i18nVariable'] = do_i18nVariable def do_insertTranslation(self, stuff): i18ndict = {} srepr = [] obj = None self.i18nStack.append((i18ndict, srepr)) msgid = stuff[0] # We need to evaluate the content of the tag because that will give us # several useful pieces of information. First, the contents will # include an implicit message id, if no explicit one was given. # Second, it will evaluate any i18nVariable definitions in the body of # the translation (necessary for $varname substitutions). # # Use a temporary stream to capture the interpretation of the # subnodes, which should /not/ go to the output stream. currentTag = self._currentTag tmpstream = self.StringIO() self.pushStream(tmpstream) try: self.interpret(stuff[1]) finally: self.popStream() # We only care about the evaluated contents if we need an implicit # message id. All other useful information will be in the i18ndict on # the top of the i18nStack. default = tmpstream.getvalue() if not msgid: if self.html and currentTag == "pre": msgid = default else: msgid = normalize(default) self.i18nStack.pop() # See if there is was an i18n:data for msgid if len(stuff) > 2: obj = self.engine.evaluate(stuff[2]) xlated_msgid = self.translate(msgid, default, i18ndict, obj) # TODO: I can't decide whether we want to cgi escape the translated # string or not. OTOH not doing this could introduce a cross-site # scripting vector by allowing translators to sneak JavaScript into # translations. OTOH, for implicit interpolation values, we don't # want to escape stuff like ${name} <= "Timmy". assert xlated_msgid is not None self._stream_write(xlated_msgid) bytecode_handlers['insertTranslation'] = do_insertTranslation def do_insertStructure(self, stuff): self.interpret(stuff[2]) bytecode_handlers["insertStructure"] = do_insertStructure bytecode_handlers["insertI18nStructure"] = do_insertStructure def do_insertStructure_tal(self, (expr, repldict, block)): structure = self.engine.evaluateStructure(expr) if structure is None: return if structure is self.Default: self.interpret(block) return if isinstance(structure, I18nMessageTypes): text = self.translate(structure) else: text = unicode(structure) if not (repldict or self.strictinsert): # Take a shortcut, no error checking self.stream_write(text) return if self.html: self.insertHTMLStructure(text, repldict) else: self.insertXMLStructure(text, repldict) def do_insertI18nStructure_tal(self, (expr, repldict, block)): # TODO: Code duplication is BAD, we need to fix it later structure = self.engine.evaluateStructure(expr) if structure is not None: if structure is self.Default: self.interpret(block) else: if not isinstance(structure, TypesToTranslate): structure = unicode(structure) text = self.translate(structure) if not (repldict or self.strictinsert): # Take a shortcut, no error checking self.stream_write(text) elif self.html: self.insertHTMLStructure(text, repldict) else: self.insertXMLStructure(text, repldict) def insertHTMLStructure(self, text, repldict): from zope.tal.htmltalparser import HTMLTALParser gen = AltTALGenerator(repldict, self.engine, 0) p = HTMLTALParser(gen) # Raises an exception if text is invalid p.parseString(text) program, macros = p.getCode() self.interpret(program) def insertXMLStructure(self, text, repldict): from zope.tal.talparser import TALParser gen = AltTALGenerator(repldict, self.engine, 0) p = TALParser(gen) gen.enable(0) p.parseFragment('') gen.enable(1) p.parseFragment(text) # Raises an exception if text is invalid gen.enable(0) p.parseFragment('', 1) program, macros = gen.getCode() self.interpret(program) def do_evaluateCode(self, stuff): lang, program = stuff # Use a temporary stream to capture the interpretation of the # subnodes, which should /not/ go to the output stream. tmpstream = self.StringIO() self.pushStream(tmpstream) try: self.interpret(program) finally: self.popStream() code = tmpstream.getvalue() output = self.engine.evaluateCode(lang, code) self._stream_write(output) bytecode_handlers["evaluateCode"] = do_evaluateCode def do_loop(self, (name, expr, block)): self.interpret(block) def do_loop_tal(self, (name, expr, block)): iterator = self.engine.setRepeat(name, expr) while iterator.next(): self.interpret(block) bytecode_handlers["loop"] = do_loop def translate(self, msgid, default=None, i18ndict=None, obj=None, domain=None): if default is None: default = getattr(msgid, 'default', unicode(msgid)) if i18ndict is None: i18ndict = {} if domain is None: domain = getattr(msgid, 'domain', self.i18nContext.domain) if obj: i18ndict.update(obj) if not self.i18nInterpolate: return msgid # TODO: We need to pass in one of context or target_language return self.engine.translate(msgid, self.i18nContext.domain, i18ndict, default=default) def do_rawtextColumn(self, (s, col)): self._stream_write(s) self.col = col bytecode_handlers["rawtextColumn"] = do_rawtextColumn def do_rawtextOffset(self, (s, offset)): self._stream_write(s) self.col = self.col + offset bytecode_handlers["rawtextOffset"] = do_rawtextOffset def do_condition(self, (condition, block)): if not self.tal or self.engine.evaluateBoolean(condition): self.interpret(block) bytecode_handlers["condition"] = do_condition def do_defineMacro(self, (macroName, macro)): wasInUse = self.inUseDirective self.inUseDirective = False self.interpret(macro) self.inUseDirective = wasInUse bytecode_handlers["defineMacro"] = do_defineMacro def do_useMacro(self, (macroName, macroExpr, compiledSlots, block), definingName=None, extending=False): if not self.metal: self.interpret(block) return macro = self.engine.evaluateMacro(macroExpr) if macro is self.Default: macro = block else: if not isCurrentVersion(macro): raise METALError("macro %s has incompatible version %s" % (`macroName`, `getProgramVersion(macro)`), self.position) mode = getProgramMode(macro) if mode != (self.html and "html" or "xml"): raise METALError("macro %s has incompatible mode %s" % (`macroName`, `mode`), self.position) self.pushMacro(macroName, compiledSlots, definingName, extending) # We want 'macroname' name to be always available as a variable outer = self.engine.getValue('macroname') self.engine.setLocal('macroname', macroName.rsplit('/', 1)[-1]) prev_source = self.sourceFile wasInUse = self.inUseDirective self.inUseDirective = True self.interpret(macro) self.inUseDirective = wasInUse if self.sourceFile != prev_source: self.engine.setSourceFile(prev_source) self.sourceFile = prev_source self.popMacro() # Push the outer macroname again. self.engine.setLocal('macroname', outer) bytecode_handlers["useMacro"] = do_useMacro def do_extendMacro(self, (macroName, macroExpr, compiledSlots, block, definingName)): # extendMacro results from a combination of define-macro and # use-macro. definingName has the value of the # metal:define-macro attribute. extending = self.metal and self.inUseDirective self.do_useMacro((macroName, macroExpr, compiledSlots, block), definingName, extending) bytecode_handlers["extendMacro"] = do_extendMacro def do_fillSlot(self, (slotName, block)): # This is only executed if the enclosing 'use-macro' evaluates # to 'default'. self.interpret(block) bytecode_handlers["fillSlot"] = do_fillSlot def do_defineSlot(self, (slotName, block)): if not self.metal: self.interpret(block) return macs = self.macroStack if macs: len_macs = len(macs) # Measure the extension depth of this use-macro depth = 1 while depth < len_macs: if macs[-depth].extending: depth += 1 else: break # Search for a slot filler from the most specific to the # most general macro. The most general is at the top of # the stack. slot = None i = len_macs - 1 while i >= (len_macs - depth): slot = macs[i].slots.get(slotName) if slot is not None: break i -= 1 if slot is not None: # Found a slot filler. Temporarily chop the macro # stack starting at the macro that filled the slot and # render the slot filler. chopped = macs[i:] del macs[i:] try: self.interpret(slot) finally: # Restore the stack entries. for mac in chopped: mac.entering = False # Not entering macs.extend(chopped) return # Falling out of the 'if' allows the macro to be interpreted. self.interpret(block) bytecode_handlers["defineSlot"] = do_defineSlot def do_onError(self, (block, handler)): self.interpret(block) def do_onError_tal(self, (block, handler)): state = self.saveState() self.stream = stream = self.StringIO() self._stream_write = stream.write try: self.interpret(block) # TODO: this should not catch ZODB.POSException.ConflictError. # The ITALExpressionEngine interface should provide a way of # getting the set of exception types that should not be # handled. except: exc = sys.exc_info()[1] self.restoreState(state) engine = self.engine engine.beginScope() error = engine.createErrorInfo(exc, self.position) engine.setLocal('error', error) try: self.interpret(handler) finally: engine.endScope() else: self.restoreOutputState(state) self.stream_write(stream.getvalue()) bytecode_handlers["onError"] = do_onError bytecode_handlers_tal = bytecode_handlers.copy() bytecode_handlers_tal["rawtextBeginScope"] = do_rawtextBeginScope_tal bytecode_handlers_tal["beginScope"] = do_beginScope_tal bytecode_handlers_tal["setLocal"] = do_setLocal_tal bytecode_handlers_tal["setGlobal"] = do_setGlobal_tal bytecode_handlers_tal["insertStructure"] = do_insertStructure_tal bytecode_handlers_tal["insertI18nStructure"] = do_insertI18nStructure_tal bytecode_handlers_tal["insertText"] = do_insertText_tal bytecode_handlers_tal["insertI18nText"] = do_insertI18nText_tal bytecode_handlers_tal["loop"] = do_loop_tal bytecode_handlers_tal["onError"] = do_onError_tal bytecode_handlers_tal[""] = attrAction_tal bytecode_handlers_tal["optTag"] = do_optTag_tal class FasterStringIO(StringIO): """Append-only version of StringIO. This let's us have a much faster write() method. """ def close(self): if not self.closed: self.write = _write_ValueError StringIO.close(self) def seek(self, pos, mode=0): raise RuntimeError("FasterStringIO.seek() not allowed") def write(self, s): #assert self.pos == self.len self.buflist.append(s) self.len = self.pos = self.pos + len(s) def _write_ValueError(s): raise ValueError("I/O operation on closed file") zope.tal-3.5.2/src/zope/tal/interfaces.py0000644000175000017500000001534511273124226020230 0ustar anthonyanthony############################################################################## # # Copyright (c) 2003 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Interface that a TAL expression implementation provides to the METAL/TAL implementation. $Id: interfaces.py 37831 2005-08-10 15:36:52Z fdrake $ """ from zope.interface import Attribute, Interface class ITALExpressionCompiler(Interface): """Compile-time interface provided by a TAL expression implementation. The TAL compiler needs an instance of this interface to support compilation of TAL expressions embedded in documents containing TAL and METAL constructs. """ def getCompilerError(): """Return the exception class raised for compilation errors. """ def compile(expression): """Return a compiled form of 'expression' for later evaluation. 'expression' is the source text of the expression. The return value may be passed to the various evaluate*() methods of the ITALExpressionEngine interface. No compatibility is required for the values of the compiled expression between different ITALExpressionEngine implementations. """ def getContext(namespace): """Create an expression execution context The given namespace provides the initial top-level names. """ class ITALExpressionEngine(Interface): """Render-time interface provided by a TAL expression implementation. The TAL interpreter uses this interface to TAL expression to support evaluation of the compiled expressions returned by ITALExpressionCompiler.compile(). """ def getDefault(): """Return the value of the 'default' TAL expression. Checking a value for a match with 'default' should be done using the 'is' operator in Python. """ def setPosition((lineno, offset)): """Inform the engine of the current position in the source file. This is used to allow the evaluation engine to report execution errors so that site developers can more easily locate the offending expression. """ def setSourceFile(filename): """Inform the engine of the name of the current source file. This is used to allow the evaluation engine to report execution errors so that site developers can more easily locate the offending expression. """ def beginScope(): """Push a new scope onto the stack of open scopes. """ def endScope(): """Pop one scope from the stack of open scopes. """ def evaluate(compiled_expression): """Evaluate an arbitrary expression. No constraints are imposed on the return value. """ def evaluateBoolean(compiled_expression): """Evaluate an expression that must return a Boolean value. """ def evaluateMacro(compiled_expression): """Evaluate an expression that must return a macro program. """ def evaluateStructure(compiled_expression): """Evaluate an expression that must return a structured document fragment. The result of evaluating 'compiled_expression' must be a string containing a parsable HTML or XML fragment. Any TAL markup contained in the result string will be interpreted. """ def evaluateText(compiled_expression): """Evaluate an expression that must return text. The returned text should be suitable for direct inclusion in the output: any HTML or XML escaping or quoting is the responsibility of the expression itself. If the expression evaluates to None, then that is returned. It represents 'nothing' in TALES. If the expression evaluates to what getDefault() of this interface returns, by comparison using 'is', then that is returned. It represents 'default' in TALES. """ def evaluateValue(compiled_expression): """Evaluate an arbitrary expression. No constraints are imposed on the return value. """ def createErrorInfo(exception, (lineno, offset)): """Returns an ITALExpressionErrorInfo object. The returned object is used to provide information about the error condition for the on-error handler. """ def setGlobal(name, value): """Set a global variable. The variable will be named 'name' and have the value 'value'. """ def setLocal(name, value): """Set a local variable in the current scope. The variable will be named 'name' and have the value 'value'. """ def getValue(name, default=None): """Get a variable by name. If the variable does not exist, return default. """ def setRepeat(name, compiled_expression): """Start a repetition, returning an ITALIterator. The engine is expected to add the a value (typically the returned iterator) for the name to the variable namespace. """ def translate(msgid, domain=None, mapping=None, default=None): """See zope.i18n.interfaces.ITranslationDomain.translate""" # NB: This differs from the Zope 2 equivalent in the order of # the arguments. This will be a (hopefully minor) issue when # creating a unified TAL implementation. def evaluateCode(lang, code): """Evaluates code of the given language. Returns whatever the code outputs. This can be defined on a per-language basis. In Python this usually everything the print statement will return. """ class ITALIterator(Interface): """A TAL iterator Not to be confused with a Python iterator. """ def next(): """Advance to the next value in the iteration, if possible Return a true value if it was possible to advance and return a false value otherwise. """ class ITALExpressionErrorInfo(Interface): type = Attribute("type", "The exception class.") value = Attribute("value", "The exception instance.") lineno = Attribute("lineno", "The line number the error occurred on in the source.") offset = Attribute("offset", "The character offset at which the error occurred.") zope.tal-3.5.2/src/zope/tal/runtest.py0000644000175000017500000001061511273124226017604 0ustar anthonyanthony#! /usr/bin/env python ############################################################################## # # Copyright (c) 2001, 2002 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Driver program to run METAL and TAL regression tests. $Id: runtest.py 29651 2005-03-23 12:56:35Z hdima $ """ import glob import os import sys import traceback from cStringIO import StringIO if __name__ == "__main__": import setpath # Local hack to tweak sys.path etc. import zope.tal.driver import zope.tal.tests.utils def showdiff(a, b): import ndiff cruncher = ndiff.SequenceMatcher(ndiff.IS_LINE_JUNK, a, b) for tag, alo, ahi, blo, bhi in cruncher.get_opcodes(): if tag == "equal": continue print nicerange(alo, ahi) + tag[0] + nicerange(blo, bhi) ndiff.dump('<', a, alo, ahi) if a and b: print '---' ndiff.dump('>', b, blo, bhi) def nicerange(lo, hi): if hi <= lo+1: return str(lo+1) else: return "%d,%d" % (lo+1, hi) def main(): opts = [] args = sys.argv[1:] quiet = 0 unittesting = 0 if args and args[0] == "-q": quiet = 1 del args[0] if args and args[0] == "-Q": unittesting = 1 del args[0] while args and args[0].startswith('-'): opts.append(args[0]) del args[0] if not args: prefix = os.path.join("tests", "input", "test*.") if zope.tal.tests.utils.skipxml: xmlargs = [] else: xmlargs = glob.glob(prefix + "xml") xmlargs.sort() htmlargs = glob.glob(prefix + "html") htmlargs.sort() args = xmlargs + htmlargs if not args: sys.stderr.write("No tests found -- please supply filenames\n") sys.exit(1) errors = 0 for arg in args: locopts = [] if arg.find("metal") >= 0 and "-m" not in opts: locopts.append("-m") if arg.find("_sa") >= 0 and "-a" not in opts: locopts.append("-a") if not unittesting: print arg, sys.stdout.flush() if zope.tal.tests.utils.skipxml and arg.endswith(".xml"): print "SKIPPED (XML parser not available)" continue save = sys.stdout, sys.argv try: try: sys.stdout = stdout = StringIO() sys.argv = [""] + opts + locopts + [arg] zope.tal.driver.main() finally: sys.stdout, sys.argv = save except SystemExit: raise except: errors = 1 if quiet: print sys.exc_type sys.stdout.flush() else: if unittesting: print else: print "Failed:" sys.stdout.flush() traceback.print_exc() continue head, tail = os.path.split(arg) outfile = os.path.join( head.replace("input", "output"), tail) try: f = open(outfile) except IOError: expected = None print "(missing file %s)" % outfile, else: expected = f.readlines() f.close() stdout.seek(0) if hasattr(stdout, "readlines"): actual = stdout.readlines() else: actual = readlines(stdout) if actual == expected: if not unittesting: print "OK" else: if unittesting: print else: print "not OK" errors = 1 if not quiet and expected is not None: showdiff(expected, actual) if errors: sys.exit(1) def readlines(f): L = [] while 1: line = f.readline() if not line: break L.append(line) return L if __name__ == "__main__": main() zope.tal-3.5.2/src/zope/tal/setpath.py0000644000175000017500000000336511273124226017554 0ustar anthonyanthony############################################################################## # # Copyright (c) 2001, 2002 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Read a module search path from .path file. If .path file isn't found in the directory of the setpath.py module, then try to import ZODB. If that succeeds, we assume the path is already set up correctly. If that import fails, an IOError is raised. $Id: setpath.py 29651 2005-03-23 12:56:35Z hdima $ """ # TODO: Why does this want to find ZODB ??? import os import sys dir = os.path.dirname(__file__) path = os.path.join(dir, ".path") try: f = open(path) except IOError: try: # If we can import ZODB, our sys.path is set up well enough already import ZODB except ImportError: raise IOError("Can't find ZODB package. Please edit %s to point to " "your Zope's lib/python directory" % path) else: for line in f.readlines(): line = line.strip() if line and line[0] != '#': for dir in line.split(os.pathsep): dir = os.path.expanduser(os.path.expandvars(dir)) if dir not in sys.path: sys.path.append(dir) # Must import this first to initialize Persistence properly import ZODB zope.tal-3.5.2/src/zope/tal/talgettext.py0000644000175000017500000002444511273124226020273 0ustar anthonyanthony#!/usr/bin/env python ############################################################################## # # Copyright (c) 2002 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Program to extract internationalization markup from Page Templates. Once you have marked up a Page Template file with i18n: namespace tags, use this program to extract GNU gettext .po file entries. Usage: talgettext.py [options] files Options: -h / --help Print this message and exit. -o / --output Output the translation .po file to . -u / --update Update the existing translation with any new translation strings found. $Id: talgettext.py 105021 2009-10-12 06:29:49Z fretin $ """ import sys import time import getopt import traceback from zope.interface import implements from zope.tal.htmltalparser import HTMLTALParser from zope.tal.talinterpreter import TALInterpreter, normalize from zope.tal.dummyengine import DummyEngine from zope.tal.interfaces import ITALExpressionEngine from zope.tal.taldefs import TALExpressionError from zope.i18nmessageid import Message pot_header = '''\ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR ORGANIZATION # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\\n" "POT-Creation-Date: %(time)s\\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n" "Last-Translator: FULL NAME \\n" "Language-Team: LANGUAGE \\n" "MIME-Version: 1.0\\n" "Content-Type: text/plain; charset=CHARSET\\n" "Content-Transfer-Encoding: ENCODING\\n" "Generated-By: talgettext.py %(version)s\\n" ''' NLSTR = '"\n"' def usage(code, msg=''): # Python 2.1 required print >> sys.stderr, __doc__ if msg: print >> sys.stderr, msg sys.exit(code) class POTALInterpreter(TALInterpreter): def translate(self, msgid, default=None, i18ndict=None, obj=None): if default is None: default = getattr(msgid, 'default', unicode(msgid)) # If no i18n dict exists yet, create one. if i18ndict is None: i18ndict = {} if obj: i18ndict.update(obj) # Mmmh, it seems that sometimes the msgid is None; is that really # possible? if msgid is None: return None # TODO: We need to pass in one of context or target_language return self.engine.translate(msgid, self.i18nContext.domain, i18ndict, default=default, position=self.position) class POEngine(DummyEngine): implements(ITALExpressionEngine) def __init__(self, macros=None): self.catalog = {} DummyEngine.__init__(self, macros) def evaluate(*args): # If the result of evaluate ever gets into a message ID, we want # to notice the fact in the .pot file. return '${DYNAMIC_CONTENT}' def evaluatePathOrVar(*args): # Actually this method is never called. return 'XXX' def evaluateSequence(self, expr): return (0,) # dummy def evaluateBoolean(self, expr): return True # dummy def translate(self, msgid, domain=None, mapping=None, default=None, # Position is not part of the ITALExpressionEngine # interface position=None): if default is not None: default = normalize(default) if msgid == default: default = None msgid = Message(msgid, default=default) if domain not in self.catalog: self.catalog[domain] = {} domain = self.catalog[domain] if msgid not in domain: domain[msgid] = [] else: msgids = domain.keys() idx = msgids.index(msgid) existing_msgid = msgids[idx] if msgid.default != existing_msgid.default: references = '\n'.join([location[0]+':'+str(location[1]) for location in domain[msgid]]) print >> sys.stderr, "Warning: msgid '%s' in %s already exists " \ "with a different default (bad: %s, should be: %s)\n" \ "The references for the existent value are:\n%s\n" % \ (msgid, self.file+':'+str(position), msgid.default, existing_msgid.default, references) domain[msgid].append((self.file, position)) return 'x' class UpdatePOEngine(POEngine): """A slightly-less braindead POEngine which supports loading an existing .po file first.""" def __init__ (self, macros=None, filename=None): POEngine.__init__(self, macros) self._filename = filename self._loadFile() self.base = self.catalog self.catalog = {} def __add(self, id, s, fuzzy): "Add a non-fuzzy translation to the dictionary." if not fuzzy and str: # check for multi-line values and munge them appropriately if '\n' in s: lines = s.rstrip().split('\n') s = NLSTR.join(lines) self.catalog[id] = s def _loadFile(self): # shamelessly cribbed from Python's Tools/i18n/msgfmt.py # 25-Mar-2003 Nathan R. Yergler (nathan@zope.org) # 14-Apr-2003 Hacked by Barry Warsaw (barry@zope.com) ID = 1 STR = 2 try: lines = open(self._filename).readlines() except IOError, msg: print >> sys.stderr, msg sys.exit(1) section = None fuzzy = False # Parse the catalog lno = 0 for l in lines: lno += True # If we get a comment line after a msgstr, this is a new entry if l[0] == '#' and section == STR: self.__add(msgid, msgstr, fuzzy) section = None fuzzy = False # Record a fuzzy mark if l[:2] == '#,' and l.find('fuzzy'): fuzzy = True # Skip comments if l[0] == '#': continue # Now we are in a msgid section, output previous section if l.startswith('msgid'): if section == STR: self.__add(msgid, msgstr, fuzzy) section = ID l = l[5:] msgid = msgstr = '' # Now we are in a msgstr section elif l.startswith('msgstr'): section = STR l = l[6:] # Skip empty lines if not l.strip(): continue # TODO: Does this always follow Python escape semantics? l = eval(l) if section == ID: msgid += l elif section == STR: msgstr += '%s\n' % l else: print >> sys.stderr, 'Syntax error on %s:%d' % (infile, lno), \ 'before:' print >> sys.stderr, l sys.exit(1) # Add last entry if section == STR: self.__add(msgid, msgstr, fuzzy) def evaluate(self, expression): try: return POEngine.evaluate(self, expression) except TALExpressionError: pass def evaluatePathOrVar(self, expr): return 'who cares' def translate(self, msgid, domain=None, mapping=None, default=None, position=None): if msgid not in self.base: POEngine.translate(self, msgid, domain, mapping, default, position) return 'x' def main(): try: opts, args = getopt.getopt( sys.argv[1:], 'ho:u:', ['help', 'output=', 'update=']) except getopt.error, msg: usage(1, msg) outfile = None engine = None update_mode = False for opt, arg in opts: if opt in ('-h', '--help'): usage(0) elif opt in ('-o', '--output'): outfile = arg elif opt in ('-u', '--update'): update_mode = True if outfile is None: outfile = arg engine = UpdatePOEngine(filename=arg) if not args: print 'nothing to do' return # We don't care about the rendered output of the .pt file class Devnull(object): def write(self, s): pass # check if we've already instantiated an engine; # if not, use the stupidest one available if not engine: engine = POEngine() # process each file specified for filename in args: try: engine.file = filename p = HTMLTALParser() p.parseFile(filename) program, macros = p.getCode() POTALInterpreter(program, macros, engine, stream=Devnull(), metal=False)() except: # Hee hee, I love bare excepts! print 'There was an error processing', filename traceback.print_exc() # Now output the keys in the engine. Write them to a file if --output or # --update was specified; otherwise use standard out. if (outfile is None): outfile = sys.stdout else: outfile = file(outfile, update_mode and "a" or "w") catalog = {} for domain in engine.catalog.keys(): catalog.update(engine.catalog[domain]) messages = catalog.copy() try: messages.update(engine.base) except AttributeError: pass if '' not in messages: print >> outfile, pot_header % {'time': time.ctime(), 'version': __version__} msgids = catalog.keys() # TODO: You should not sort by msgid, but by filename and position. (SR) msgids.sort() for msgid in msgids: positions = engine.catalog[msgid] for filename, position in positions: outfile.write('#: %s:%s\n' % (filename, position[0])) outfile.write('msgid "%s"\n' % msgid) outfile.write('msgstr ""\n') outfile.write('\n') if __name__ == '__main__': main() zope.tal-3.5.2/src/zope.tal.egg-info/0000755000175000017500000000000011336275656017232 5ustar anthonyanthonyzope.tal-3.5.2/src/zope.tal.egg-info/requires.txt0000644000175000017500000000010111273124236021605 0ustar anthonyanthonysetuptools zope.i18nmessageid zope.interface [test] zope.testingzope.tal-3.5.2/src/zope.tal.egg-info/dependency_links.txt0000644000175000017500000000000111273124236023263 0ustar anthonyanthony zope.tal-3.5.2/src/zope.tal.egg-info/namespace_packages.txt0000644000175000017500000000000511273124236023543 0ustar anthonyanthonyzope zope.tal-3.5.2/src/zope.tal.egg-info/top_level.txt0000644000175000017500000000000511273124236021742 0ustar anthonyanthonyzope zope.tal-3.5.2/src/zope.tal.egg-info/PKG-INFO0000644000175000017500000000643111273124236020316 0ustar anthonyanthonyMetadata-Version: 1.0 Name: zope.tal Version: 3.5.2 Summary: Zope 3 Template Application Languate (TAL) Home-page: http://pypi.python.org/pypi/zope.tal Author: Zope Corporation and Contributors Author-email: zope-dev@zope.org License: ZPL 2.1 Description: Template Attribute Language (TAL) ================================= Overview -------- The Zope3 Template Attribute Languate (TAL) specifies the custom namespace and attributes which are used by the Zope Page Templates renderer to inject dynamic markup into a page. It also includes the Macro Expansion for TAL (METAL) macro language used in page assembly. The dynamic values themselves are specified using a companion language, TALES (see the 'zope.tales' package for more). See: http://www.zope.org/Wikis/DevSite/Projects/ZPT/TAL%20Specification%201.4 ======= CHANGES ======= 3.5.2 (2009-10-31) ------------------ - In talgettext.POEngine.translate, print a warning if a msgid already exists in the domain with a different default. 3.5.1 (2009-03-08) ------------------ - Updated tests of "bad" entities for compatibility with the stricter HTMLParser module shipped with Python 2.6.x. 3.5.0 (2008-06-06) ------------------ - Removed artificial addition of a trailing newline if the output doesn't end in one; this allows the template source to be the full specification of what should be included. (See https://bugs.launchpad.net/launchpad/+bug/218706.) 3.4.1 (2007-11-16) ------------------ - Removed unnecessary ``dummyengine`` dependency on zope.i18n to simplify distribution. The ``dummyengine.DummyTranslationDomain`` class no longer implements ``zope.i18n.interfaces.ITranslationDomain`` as a result. Installing zope.tal with easy_install or buildout no longer pulls in many unrelated distributions. - Support ability to run tests using "setup.py test". - Stop pinning (no longer required) zope.traversing and zope.app.publisher versions in buildout.cfg. 3.4.0 (2007-10-03) ------------------ - Updated package meta-data. 3.4.0b1 ------- - Updated dependency for ``zope.i18n`` that requires the correct version of zope.security to avoid a hidden dependency issue in zope.security. Note: The code changes before 3.4.0b1 where not tracked as an individual package and have been documented in the Zope 3 changelog. Keywords: zope3 template xml tal Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Zope Public License Classifier: Programming Language :: Python Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Topic :: Internet :: WWW/HTTP Classifier: Framework :: Zope3 zope.tal-3.5.2/src/zope.tal.egg-info/SOURCES.txt0000644000175000017500000001754411273124236021114 0ustar anthonyanthonyCHANGES.txt README.txt bootstrap.py buildout.cfg setup.py src/zope/__init__.py src/zope.tal.egg-info/PKG-INFO src/zope.tal.egg-info/SOURCES.txt src/zope.tal.egg-info/dependency_links.txt src/zope.tal.egg-info/namespace_packages.txt src/zope.tal.egg-info/not-zip-safe src/zope.tal.egg-info/requires.txt src/zope.tal.egg-info/top_level.txt src/zope/tal/DEPENDENCIES.cfg src/zope/tal/__init__.py src/zope/tal/driver.py src/zope/tal/dummyengine.py src/zope/tal/htmltalparser.py src/zope/tal/interfaces.py src/zope/tal/ndiff.py src/zope/tal/runtest.py src/zope/tal/setpath.py src/zope/tal/taldefs.py src/zope/tal/talgenerator.py src/zope/tal/talgettext.py src/zope/tal/talinterpreter.py src/zope/tal/talparser.py src/zope/tal/timer.py src/zope/tal/translationcontext.py src/zope/tal/xmlparser.py src/zope/tal/benchmark/__init__.py src/zope/tal/benchmark/dtml01.html src/zope/tal/benchmark/dtml02.html src/zope/tal/benchmark/dtml03.html src/zope/tal/benchmark/dtml04.html src/zope/tal/benchmark/dtml05.html src/zope/tal/benchmark/dtml06.html src/zope/tal/benchmark/dtml07.html src/zope/tal/benchmark/dtml08.html src/zope/tal/benchmark/dtml09.html src/zope/tal/benchmark/dtml10.html src/zope/tal/benchmark/dtml11.html src/zope/tal/benchmark/dtml12.html src/zope/tal/benchmark/tal01.html src/zope/tal/benchmark/tal02.html src/zope/tal/benchmark/tal03.html src/zope/tal/benchmark/tal04.html src/zope/tal/benchmark/tal05.html src/zope/tal/benchmark/tal06.html src/zope/tal/benchmark/tal07.html src/zope/tal/benchmark/tal08.html src/zope/tal/benchmark/tal09.html src/zope/tal/benchmark/tal10.html src/zope/tal/benchmark/tal11.html src/zope/tal/benchmark/tal12.html src/zope/tal/tests/__init__.py src/zope/tal/tests/markbench.py src/zope/tal/tests/run.py src/zope/tal/tests/test_files.py src/zope/tal/tests/test_htmltalparser.py src/zope/tal/tests/test_sourcepos.py src/zope/tal/tests/test_talgettext.py src/zope/tal/tests/test_talinterpreter.py src/zope/tal/tests/test_talparser.py src/zope/tal/tests/test_xmlparser.py src/zope/tal/tests/utils.py src/zope/tal/tests/input/__init__.py src/zope/tal/tests/input/acme_template.pt src/zope/tal/tests/input/document_list.pt src/zope/tal/tests/input/pnome_template.pt src/zope/tal/tests/input/test01.html src/zope/tal/tests/input/test01.xml src/zope/tal/tests/input/test02.html src/zope/tal/tests/input/test02.xml src/zope/tal/tests/input/test03.html src/zope/tal/tests/input/test03.xml src/zope/tal/tests/input/test04.html src/zope/tal/tests/input/test04.xml src/zope/tal/tests/input/test05.html src/zope/tal/tests/input/test05.xml src/zope/tal/tests/input/test06.html src/zope/tal/tests/input/test06.xml src/zope/tal/tests/input/test07.html src/zope/tal/tests/input/test07.xml src/zope/tal/tests/input/test08.html src/zope/tal/tests/input/test08.xml src/zope/tal/tests/input/test09.html src/zope/tal/tests/input/test09.xml src/zope/tal/tests/input/test10.html src/zope/tal/tests/input/test11.html src/zope/tal/tests/input/test11.xml src/zope/tal/tests/input/test12.html src/zope/tal/tests/input/test13.html src/zope/tal/tests/input/test14.html src/zope/tal/tests/input/test14.xml src/zope/tal/tests/input/test15.html src/zope/tal/tests/input/test16.html src/zope/tal/tests/input/test16.xml src/zope/tal/tests/input/test17.html src/zope/tal/tests/input/test17.xml src/zope/tal/tests/input/test18.html src/zope/tal/tests/input/test18.xml src/zope/tal/tests/input/test19.html src/zope/tal/tests/input/test19.xml src/zope/tal/tests/input/test20.html src/zope/tal/tests/input/test20.xml src/zope/tal/tests/input/test21.html src/zope/tal/tests/input/test21.xml src/zope/tal/tests/input/test22.html src/zope/tal/tests/input/test22.xml src/zope/tal/tests/input/test23.html src/zope/tal/tests/input/test24.html src/zope/tal/tests/input/test25.html src/zope/tal/tests/input/test26.html src/zope/tal/tests/input/test27.html src/zope/tal/tests/input/test28.html src/zope/tal/tests/input/test29.html src/zope/tal/tests/input/test30.html src/zope/tal/tests/input/test31.html src/zope/tal/tests/input/test32.html src/zope/tal/tests/input/test33.html src/zope/tal/tests/input/test34.html src/zope/tal/tests/input/test35.html src/zope/tal/tests/input/test36.html src/zope/tal/tests/input/test37.html src/zope/tal/tests/input/test_domain.html src/zope/tal/tests/input/test_failed_attr_translation.html src/zope/tal/tests/input/test_metal1.html src/zope/tal/tests/input/test_metal2.html src/zope/tal/tests/input/test_metal3.html src/zope/tal/tests/input/test_metal4.html src/zope/tal/tests/input/test_metal5.html src/zope/tal/tests/input/test_metal6.html src/zope/tal/tests/input/test_metal7.html src/zope/tal/tests/input/test_metal8.html src/zope/tal/tests/input/test_metal9.html src/zope/tal/tests/input/test_sa1.html src/zope/tal/tests/input/test_sa1.xml src/zope/tal/tests/input/test_sa2.html src/zope/tal/tests/input/test_sa2.xml src/zope/tal/tests/input/test_sa3.html src/zope/tal/tests/input/test_sa3.xml src/zope/tal/tests/input/test_sa4.html src/zope/tal/tests/output/__init__.py src/zope/tal/tests/output/acme_template.html src/zope/tal/tests/output/acme_template_source.html src/zope/tal/tests/output/document_list.html src/zope/tal/tests/output/document_list_source.html src/zope/tal/tests/output/test01.html src/zope/tal/tests/output/test01.xml src/zope/tal/tests/output/test02.html src/zope/tal/tests/output/test02.xml src/zope/tal/tests/output/test03.html src/zope/tal/tests/output/test03.xml src/zope/tal/tests/output/test04.html src/zope/tal/tests/output/test04.xml src/zope/tal/tests/output/test05.html src/zope/tal/tests/output/test05.xml src/zope/tal/tests/output/test06.html src/zope/tal/tests/output/test06.xml src/zope/tal/tests/output/test07.html src/zope/tal/tests/output/test07.xml src/zope/tal/tests/output/test08.html src/zope/tal/tests/output/test08.xml src/zope/tal/tests/output/test09.html src/zope/tal/tests/output/test09.xml src/zope/tal/tests/output/test10.html src/zope/tal/tests/output/test11.html src/zope/tal/tests/output/test11.xml src/zope/tal/tests/output/test12.html src/zope/tal/tests/output/test13.html src/zope/tal/tests/output/test14.html src/zope/tal/tests/output/test14.xml src/zope/tal/tests/output/test15.html src/zope/tal/tests/output/test16.html src/zope/tal/tests/output/test16.xml src/zope/tal/tests/output/test17.html src/zope/tal/tests/output/test17.xml src/zope/tal/tests/output/test18.html src/zope/tal/tests/output/test18.xml src/zope/tal/tests/output/test19.html src/zope/tal/tests/output/test19.xml src/zope/tal/tests/output/test20.html src/zope/tal/tests/output/test20.xml src/zope/tal/tests/output/test21.html src/zope/tal/tests/output/test21.xml src/zope/tal/tests/output/test22.html src/zope/tal/tests/output/test22.xml src/zope/tal/tests/output/test23.html src/zope/tal/tests/output/test24.html src/zope/tal/tests/output/test25.html src/zope/tal/tests/output/test26.html src/zope/tal/tests/output/test27.html src/zope/tal/tests/output/test28.html src/zope/tal/tests/output/test29.html src/zope/tal/tests/output/test30.html src/zope/tal/tests/output/test31.html src/zope/tal/tests/output/test32.html src/zope/tal/tests/output/test33.html src/zope/tal/tests/output/test34.html src/zope/tal/tests/output/test35.html src/zope/tal/tests/output/test36.html src/zope/tal/tests/output/test37.html src/zope/tal/tests/output/test_domain.html src/zope/tal/tests/output/test_failed_attr_translation.html src/zope/tal/tests/output/test_metal1.html src/zope/tal/tests/output/test_metal2.html src/zope/tal/tests/output/test_metal3.html src/zope/tal/tests/output/test_metal4.html src/zope/tal/tests/output/test_metal5.html src/zope/tal/tests/output/test_metal6.html src/zope/tal/tests/output/test_metal7.html src/zope/tal/tests/output/test_metal8.html src/zope/tal/tests/output/test_metal9.html src/zope/tal/tests/output/test_sa1.html src/zope/tal/tests/output/test_sa1.xml src/zope/tal/tests/output/test_sa2.html src/zope/tal/tests/output/test_sa2.xml src/zope/tal/tests/output/test_sa3.html src/zope/tal/tests/output/test_sa3.xml src/zope/tal/tests/output/test_sa4.htmlzope.tal-3.5.2/src/zope.tal.egg-info/not-zip-safe0000644000175000017500000000000111273124230021435 0ustar anthonyanthony zope.tal-3.5.2/CHANGES.txt0000644000175000017500000000275011273124226015014 0ustar anthonyanthony======= CHANGES ======= 3.5.2 (2009-10-31) ------------------ - In talgettext.POEngine.translate, print a warning if a msgid already exists in the domain with a different default. 3.5.1 (2009-03-08) ------------------ - Updated tests of "bad" entities for compatibility with the stricter HTMLParser module shipped with Python 2.6.x. 3.5.0 (2008-06-06) ------------------ - Removed artificial addition of a trailing newline if the output doesn't end in one; this allows the template source to be the full specification of what should be included. (See https://bugs.launchpad.net/launchpad/+bug/218706.) 3.4.1 (2007-11-16) ------------------ - Removed unnecessary ``dummyengine`` dependency on zope.i18n to simplify distribution. The ``dummyengine.DummyTranslationDomain`` class no longer implements ``zope.i18n.interfaces.ITranslationDomain`` as a result. Installing zope.tal with easy_install or buildout no longer pulls in many unrelated distributions. - Support ability to run tests using "setup.py test". - Stop pinning (no longer required) zope.traversing and zope.app.publisher versions in buildout.cfg. 3.4.0 (2007-10-03) ------------------ - Updated package meta-data. 3.4.0b1 ------- - Updated dependency for ``zope.i18n`` that requires the correct version of zope.security to avoid a hidden dependency issue in zope.security. Note: The code changes before 3.4.0b1 where not tracked as an individual package and have been documented in the Zope 3 changelog. zope.tal-3.5.2/PKG-INFO0000644000175000017500000000643111273124236014301 0ustar anthonyanthonyMetadata-Version: 1.0 Name: zope.tal Version: 3.5.2 Summary: Zope 3 Template Application Languate (TAL) Home-page: http://pypi.python.org/pypi/zope.tal Author: Zope Corporation and Contributors Author-email: zope-dev@zope.org License: ZPL 2.1 Description: Template Attribute Language (TAL) ================================= Overview -------- The Zope3 Template Attribute Languate (TAL) specifies the custom namespace and attributes which are used by the Zope Page Templates renderer to inject dynamic markup into a page. It also includes the Macro Expansion for TAL (METAL) macro language used in page assembly. The dynamic values themselves are specified using a companion language, TALES (see the 'zope.tales' package for more). See: http://www.zope.org/Wikis/DevSite/Projects/ZPT/TAL%20Specification%201.4 ======= CHANGES ======= 3.5.2 (2009-10-31) ------------------ - In talgettext.POEngine.translate, print a warning if a msgid already exists in the domain with a different default. 3.5.1 (2009-03-08) ------------------ - Updated tests of "bad" entities for compatibility with the stricter HTMLParser module shipped with Python 2.6.x. 3.5.0 (2008-06-06) ------------------ - Removed artificial addition of a trailing newline if the output doesn't end in one; this allows the template source to be the full specification of what should be included. (See https://bugs.launchpad.net/launchpad/+bug/218706.) 3.4.1 (2007-11-16) ------------------ - Removed unnecessary ``dummyengine`` dependency on zope.i18n to simplify distribution. The ``dummyengine.DummyTranslationDomain`` class no longer implements ``zope.i18n.interfaces.ITranslationDomain`` as a result. Installing zope.tal with easy_install or buildout no longer pulls in many unrelated distributions. - Support ability to run tests using "setup.py test". - Stop pinning (no longer required) zope.traversing and zope.app.publisher versions in buildout.cfg. 3.4.0 (2007-10-03) ------------------ - Updated package meta-data. 3.4.0b1 ------- - Updated dependency for ``zope.i18n`` that requires the correct version of zope.security to avoid a hidden dependency issue in zope.security. Note: The code changes before 3.4.0b1 where not tracked as an individual package and have been documented in the Zope 3 changelog. Keywords: zope3 template xml tal Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Zope Public License Classifier: Programming Language :: Python Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Topic :: Internet :: WWW/HTTP Classifier: Framework :: Zope3 zope.tal-3.5.2/setup.cfg0000644000175000017500000000007311273124236015021 0ustar anthonyanthony[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 zope.tal-3.5.2/bootstrap.py0000644000175000017500000000337211273124226015573 0ustar anthonyanthony############################################################################## # # Copyright (c) 2006 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Bootstrap a buildout-based project Simply run this script in a directory containing a buildout.cfg. The script accepts buildout command-line options, so you can use the -c option to specify an alternate configuration file. $Id: bootstrap.py 73407 2007-03-21 05:28:02Z baijum $ """ import os, shutil, sys, tempfile, urllib2 tmpeggs = tempfile.mkdtemp() ez = {} exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py' ).read() in ez ez['use_setuptools'](to_dir=tmpeggs, download_delay=0) import pkg_resources cmd = 'from setuptools.command.easy_install import main; main()' if sys.platform == 'win32': cmd = '"%s"' % cmd # work around spawn lamosity on windows ws = pkg_resources.working_set assert os.spawnle( os.P_WAIT, sys.executable, sys.executable, '-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout', dict(os.environ, PYTHONPATH= ws.find(pkg_resources.Requirement.parse('setuptools')).location ), ) == 0 ws.add_entry(tmpeggs) ws.require('zc.buildout') import zc.buildout.buildout zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap']) shutil.rmtree(tmpeggs)