跳转到主要内容

快速ZPT引擎。

项目描述

z3c.pt

Latest release Supported Python versions https://github.com/zopefoundation/z3c.pt/actions/workflows/tests.yml/badge.svg https://coveralls.io/repos/github/zopefoundation/z3c.pt/badge.svg?branch=master Documentation Status

这是Zope 3的ZPT模板引擎的快速实现,它使用Chameleon将模板编译成字节码。

该软件包提供了与zope.pagetemplate等效的应用支持。

概览

本节展示了高级模板类。所有z3c.pt中的页面模板类默认使用路径表达式。

页面模板

>>> from z3c.pt.pagetemplate import PageTemplate
>>> from z3c.pt.pagetemplate import PageTemplateFile

使用字符串初始化PageTemplate类。

>>> template = PageTemplate("""\
... <div xmlns="http://www.w3.org/1999/xhtml">
...   Hello World!
... </div>""")
>>> print(template())
<div xmlns="http://www.w3.org/1999/xhtml">
  Hello World!
</div>

使用磁盘上模板文件的绝对路径初始化PageTemplateFile类。

>>> template_file = PageTemplateFile('tests/helloworld.pt')
>>> print(template_file())
<div xmlns="http://www.w3.org/1999/xhtml">
  Hello World!
</div>
>>> import os
>>> os.path.isabs(template_file.filename)
True

如果没有提供content_type并且请求中也没有,它将设置为‘text/html’。

>>> class Response(object):
...     def __init__(self):
...         self.headers = {}
...         self.getHeader = self.headers.get
...         self.setHeader = self.headers.__setitem__
>>> class Request(object):
...     def __init__(self):
...         self.response = Response()
>>> template_file = PageTemplateFile('tests/helloworld.pt')
>>> request = Request()
>>> print(request.response.getHeader('Content-Type'))
None
>>> template = template_file.bind(None, request=request)
>>> print(template())
<div xmlns="http://www.w3.org/1999/xhtml">
  Hello World!
</div>
>>> print(request.response.getHeader('Content-Type'))
text/html

如果请求中存在content_type,则不覆盖它。

>>> request = Request()
>>> request.response.setHeader('Content-Type', 'text/xml')
>>> print(request.response.getHeader('Content-Type'))
text/xml
>>> template = template_file.bind(None, request=request)
>>> print(template())
<div xmlns="http://www.w3.org/1999/xhtml">
  Hello World!
</div>
>>> print(request.response.getHeader('Content-Type'))
text/xml

content_type也可以在实例化时设置,并且将被尊重。

>>> template_file = PageTemplateFile('tests/helloworld.pt',
...                                  content_type='application/rdf+xml')
>>> request = Request()
>>> print(request.response.getHeader('Content-Type'))
None
>>> template = template_file.bind(None, request=request)
>>> print(template())
<div xmlns="http://www.w3.org/1999/xhtml">
  Hello World!
</div>
>>> print(request.response.getHeader('Content-Type'))
application/rdf+xml

两者都可以用作类属性(属性)。

>>> class MyClass(object):
...     template = PageTemplate("""\
...       <div xmlns="http://www.w3.org/1999/xhtml">
...          Hello World!
...       </div>""")
...
...     template_file = PageTemplateFile('tests/helloworld.pt')
>>> instance = MyClass()
>>> print(instance.template())
<div xmlns="http://www.w3.org/1999/xhtml">
  Hello World!
</div>
>>> print(instance.template_file())
<div xmlns="http://www.w3.org/1999/xhtml">
  Hello World!
</div>

视图页面模板

>>> from z3c.pt.pagetemplate import ViewPageTemplate
>>> from z3c.pt.pagetemplate import ViewPageTemplateFile
>>> class View(object):
...     request = u'request'
...     context = u'context'
...
...     def __repr__(self):
...         return 'view'
>>> view = View()

与之前一样,我们可以使用字符串初始化视图页面模板(这里偶然从磁盘加载)。

>>> from z3c.pt import tests
>>> path = tests.__path__[0]
>>> with open(path + '/view.pt') as f:
...     template = ViewPageTemplate(f.read())

要在视图的上下文中渲染模板,我们将模板绑定并传递视图作为参数(视图页面模板从property-类派生,通常定义在视图类的一个属性上)。

>>> print(template.bind(view)(test=u'test'))
<div xmlns="http://www.w3.org/1999/xhtml">
  <span>view</span>
  <span>context</span>
  <span>request</span>
  <span>test</span>
  <span>test</span>
</div>

对于基于文件的变体,操作类似。

>>> template = ViewPageTemplateFile('tests/view.pt')
>>> print(template.bind(view)(test=u'test'))
<div xmlns="http://www.w3.org/1999/xhtml">
  <span>view</span>
  <span>context</span>
  <span>request</span>
  <span>test</span>
  <span>test</span>
</div>

出于兼容性原因,视图模板可以使用替代的上下文和请求调用。

>>> print(template(view, u"alt_context", "alt_request", test=u'test'))
<div xmlns="http://www.w3.org/1999/xhtml">
  <span>view</span>
  <span>alt_context</span>
  <span>alt_request</span>
  <span>test</span>
  <span>test</span>
</div>

非关键字参数

这些作为options/args传入,当使用__call__方法时。

>>> print(PageTemplate("""\
... <div xmlns="http://www.w3.org/1999/xhtml">
...   <div tal:repeat="arg options/args">
...      <span tal:content="arg" />
...   </div>
... </div>""").__call__(1, 2, 3))
<div xmlns="http://www.w3.org/1999/xhtml">
  <div>
     <span>1</span>
  </div>
  <div>
     <span>2</span>
  </div>
  <div>
     <span>3</span>
  </div>
</div>

全局‘path’函数

zope.pagetemplate一样,在z3c.pt中可以使用全局定义的path()函数在python表达式中。

>>> template = PageTemplate("""\
... <div xmlns="http://www.w3.org/1999/xhtml">
...   <span tal:content="options/test" />
...   <span tal:content="python: path('options/test')" />
... </div>""")
>>> print(template(test='test'))
<div xmlns="http://www.w3.org/1999/xhtml">
  <span>test</span>
  <span>test</span>
</div>

全局‘exists’函数

这同样适用于exists()函数。

>>> template = PageTemplate("""\
... <div xmlns="http://www.w3.org/1999/xhtml">
...   <span tal:content="python: exists('options/test') and 'Yes' or 'No'" />
... </div>""")
>>> print(template(test='test'))
<div xmlns="http://www.w3.org/1999/xhtml">
  <span>Yes</span>
</div>

‘default’和路径表达式

标准ZPT的另一个功能:使用‘default’表示如果条件不满足,将输出包含在HTML中的任何内容。

这对于属性有效

>>> template = PageTemplate("""\
... <div xmlns="http://www.w3.org/1999/xhtml">
...   <span tal:attributes="class options/not-existing | default"
...         class="blue">i'm blue</span>
... </div>""")
>>> print(template())
<div xmlns="http://www.w3.org/1999/xhtml">
  <span class="blue">i'm blue</span>
</div>

也适用于内容

>>> template = PageTemplate("""\
... <div xmlns="http://www.w3.org/1999/xhtml">
...   <span tal:content="options/not-existing | default">default content</span>
... </div>""")
>>> print(template())
<div xmlns="http://www.w3.org/1999/xhtml">
  <span>default content</span>
</div>

‘exists’类型表达式

在非全局名称和全局名称上使用‘exists()’函数

>>> template = PageTemplate("""\
... <div xmlns="http://www.w3.org/1999/xhtml">
...   <span tal:content="python: exists('options/nope') and 'Yes' or 'No'">do I exist?</span>
...   <span tal:content="python: exists('nope') and 'Yes' or 'No'">do I exist?</span>
... </div>""")
>>> print(template())
<div xmlns="http://www.w3.org/1999/xhtml">
  <span>No</span>
  <span>No</span>
</div>

在非全局名称和全局名称上使用‘exists:’表达式

>>> template = PageTemplate("""\
... <div xmlns="http://www.w3.org/1999/xhtml">
...   <span tal:define="yup exists:options/nope"
...         tal:content="python: yup and 'Yes' or 'No'">do I exist?</span>
...   <span tal:define="yup exists:nope"
...         tal:content="python: yup and 'Yes' or 'No'">do I exist?</span>
... </div>""")
>>> print(template())
<div xmlns="http://www.w3.org/1999/xhtml">
  <span>No</span>
  <span>No</span>
</div>

与否定一起使用‘exists:’

>>> print(PageTemplate("""\
... <div xmlns="http://www.w3.org/1999/xhtml">
...   <span tal:condition="not:exists:options/nope">I don't exist?</span>
... </div>""")())
<div xmlns="http://www.w3.org/1999/xhtml">
  <span>I don't exist?</span>
</div>

字典的路径表达式

路径表达式优先选择字典项而不是字典属性。

>>> print(PageTemplate("""\
... <div xmlns="http://www.w3.org/1999/xhtml"
...      tal:define="links python:{'copy':'XXX', 'delete':'YYY'}">
...   <span tal:content="links/copy">ZZZ</span>
... </div>""")())
<div xmlns="http://www.w3.org/1999/xhtml">
  <span>XXX</span>
</div>

一个标签中的变量永远不会泄漏到另一个标签中

>>> body = """\
... <div xmlns="http://www.w3.org/1999/xhtml"
...      xmlns:tal="http://xml.zope.org/namespaces/tal"
...      xmlns:metal="http://xml.zope.org/namespaces/metal">
...   <div class="macro" metal:define-macro="greeting"
...        tal:define="greeting greeting|string:'Hey'">
...       <span tal:replace="greeting" />
...   </div>
...   <div tal:define="greeting string:'Hello'">
...     <metal:block metal:use-macro="python:template.macros['greeting']" />
...   </div>
...   <div>
...     <metal:block metal:use-macro="python:template.macros['greeting']" />
...   </div>
... </div>"""
>>> print(PageTemplate(body)())
<div xmlns="http://www.w3.org/1999/xhtml">
  <div class="macro">
      'Hey'
  </div>
  <div>
    <div class="macro">
      'Hello'
  </div>
<BLANKLINE>
</div>
  <div>
    <div class="macro">
      'Hey'
  </div>
<BLANKLINE>
</div>
</div>

TALES函数命名空间

http://wiki.zope.org/zope3/talesns.html中所述,可以实施自定义TALES命名空间适配器。我们还支持低级TALES函数命名空间(TALES命名空间适配器基于此构建)。

>>> import datetime
>>> import zope.interface
>>> import zope.component
>>> from zope.traversing.interfaces import ITraversable
>>> from zope.traversing.interfaces import IPathAdapter
>>> from zope.tales.interfaces import ITALESFunctionNamespace
>>> from z3c.pt.namespaces import function_namespaces
>>> @zope.interface.implementer(ITALESFunctionNamespace)
... class ns1(object):
...     def __init__(self, context):
...         self.context = context
...     def parent(self):
...         return self.context.parent
>>> function_namespaces.namespaces['ns1'] = ns1
>>> class ns2(object):
...     def __init__(self, context):
...         self.context = context
...     def upper(self):
...         return self.context.upper()
>>> zope.component.getGlobalSiteManager().registerAdapter(
...     ns2, [zope.interface.Interface], IPathAdapter, 'ns2')
>>> class ns3(object):
...     def __init__(self, context):
...         self.context = context
...     def fullDateTime(self):
...         return self.context.strftime('%Y-%m-%d %H:%M:%S')
>>> zope.component.getGlobalSiteManager().registerAdapter(
...     ns3, [zope.interface.Interface], IPathAdapter, 'ns3')

来自遗留应用程序的一个真正边缘案例:TALES命名空间适配器没有可调用的函数,而是遍历剩余的路径

>>> from zope.traversing.interfaces import TraversalError

>>> @zope.interface.implementer(ITraversable)
... class ns4(object):
...
...     def __init__(self, context):
...         self.context = context
...
...     def traverse(self, name, furtherPath):
...         if name == 'page':
...             if len(furtherPath) == 1:
...                 pagetype = furtherPath.pop()
...             elif not furtherPath:
...                 pagetype = 'default'
...             else:
...                 raise TraversalError("Max 1 path segment after ns4:page")
...             return self._page(pagetype)
...         if len(furtherPath) == 1:
...              name = '%s/%s' % (name, furtherPath.pop())
...         return 'traversed: ' + name
...
...     def _page(self, pagetype):
...         return 'called page: ' + pagetype

>>> zope.component.getGlobalSiteManager().registerAdapter(
...     ns4, [zope.interface.Interface], IPathAdapter, 'ns4')

>>> @zope.interface.implementer(ITraversable)
... class ns5(object):
...
...     def __init__(self, context):
...         self.context = context
...
...     def traverse(self, name, furtherPath):
...         name = '/'.join([name] + furtherPath[::-1])
...         del furtherPath[:]
...         return 'traversed: ' + name

>>> zope.component.getGlobalSiteManager().registerAdapter(
...     ns5, [zope.interface.Interface], IPathAdapter, 'ns5')

>>> class Ob(object):
...     def __init__(self, title, date, parent=None, child=None):
...         self.title = title
...         self.date = date
...         self.parent = parent
...         self.child = child

>>> child = Ob('child', datetime.datetime(2008, 12, 30, 13, 48, 0, 0))
>>> father = Ob('father', datetime.datetime(1978, 12, 30, 13, 48, 0, 0))
>>> grandpa = Ob('grandpa', datetime.datetime(1948, 12, 30, 13, 48, 0, 0))

>>> child.parent = father
>>> father.child = child
>>> father.parent = grandpa
>>> grandpa.child = father

>>> class View(object):
...     request = u'request'
...     context = father
...
...     def __repr__(self):
...         return 'view'

>>> view = View()
>>> template = ViewPageTemplateFile('tests/function_namespaces.pt')
>>> print(template.bind(view)())
<div xmlns="http://www.w3.org/1999/xhtml">
  <span>GRANDPA</span>
  <span>2008-12-30 13:48:00</span>
  <span>traversed: link:main</span>
  <span>called page: default</span>
  <span>called page: another</span>
  <span></span>
  <span>traversed: zope.Public</span>
  <span>traversed: text-to-html</span>
  <span>traversed: page/yet/even/another</span>
</div>

更改日志

4.4 (2024-08-07)

  • 扩展布尔html属性列表以包括所有html5布尔属性。

4.3 (2024-02-01)

  • 添加对Python 3.12的支持。

  • 修复Windows测试兼容性。

4.2 (2024-01-31)

  • 添加对“结构”表达式类型的支持。(问题 #17)。

  • 更新测试套件以与较新的Chameleon版本兼容。

4.1 (2024-01-09)

  • 提供自己的接口,因为Chameleon不会在未来版本中提供这些接口。

4.0 (2023-03-27)

  • 添加对Python 3.11的支持。

  • 停止对Python 2.7,3.5,3.6的支持。

3.3.1 (2021-12-17)

  • 添加对Python 3.9和3.10的支持。

3.3.0 (2020-03-31)

  • 停止对Python 3.4的支持

  • 添加对Python 3.8的支持。

  • 防止在注释中插值(即$$*var*, $$${*path*}``替换)。

3.2.0 (2019-01-05)

  • 添加对Python 3.7的支持。

  • 停止使用python setup.py test运行测试。

3.1.0 (2017-10-17)

  • 增加对Python 3.6的支持。

  • 放弃对Python 3.3的支持。

  • 如果可用,使用来自zope.pagetemplate的适配器命名空间,而不是使用zope.app.pagetemplate中的向后兼容层。参见问题3

  • 增加stringnocall函数,以便在Python表达式中使用。参见问题2

  • 使绑定页面模板具有__self____func__属性,使其更像Python 3的绑定方法。(im_funcim_self仍然可用。)参见问题9

3.0 (2016-09-02)

  • 增加了对Python 3.4、3.5、PyPy和PyPy3的支持。

  • 放弃对Python 2.6的支持。

3.0.0a1(2013-02-25)

兼容性

  • 增加对Python 3.3的支持。

  • chameleon.i18n添加一个小补丁以定义basestring

错误修正

  • 允许路径表达式的部分以数字开头。

2.2.3 (2012-06-01)

兼容性

  • 翻译函数现在接受(但忽略)一个context参数。这解决了与Chameleon 2.9.x的兼容性问题。

2.2.2 (2012-04-24)

错误修正

  • 不要依赖于“LANGUAGE”请求键来跳过语言协商。相反,我们假设协商成本低(并且可能已缓存)。

2.2.1 (2012-02-15)

  • 仅要求Chameleon >= 2.4,在上一个版本中无意义地提高了。

  • 添加测试额外,从buildout.cfg中删除版本。

2.2 (2012-01-08)

功能

  • 属性之间的空白现在减少到单个空白字符。

  • request符号不再需要来评估路径表达式;如果没有在命名空间中提供,它现在默认为None

错误修正

  • 内容提供者表达式现在正确应用TAL命名空间数据。

变更

  • 已删除ZopeTraverser类,并用一个简单函数替换。

2.1.5 (2011-11-24)

  • 如果可用,使用非严格模式以与仅在评估时间编译表达式的引用引擎兼容。

2.1.4 (2011-09-14)

  • 提供者表达式现在首先作为字符串表达式评估,其结果用作内容提供者名称。

    这修复了一个问题,即(提供者-)字符串表达式不会得到正确评估,例如provider: ${mgr}

2.1.3 (2011-08-22)

  • 配置HTML布尔属性(仅在HTML模式中)

    "compact", "nowrap", "ismap", "declare", "noshade",
    "checked", "disabled", "readonly", "multiple", "selected",
    "noresize", "defer"

2.1.2 (2011-08-19)

  • 启用选项literal_false以获得当值为False时不会删除属性的行为。

2.1.1 (2011-08-11)

  • 确保内置名称“path”和“exists”可以被重定义。

  • 使用ProxyFactory防止sys.modules(映射到内置变量“modules”)在导入时产生副作用。

2.1 (2011-07-28)

  • 使用Chameleon附带的动力表达式评估框架。

2.0 (2011-07-14)

  • 点发布。

  • 将特定于实现的上下文设置移至render方法。这允许使用已准备好的上下文的模板类。

  • 修复了Zope遍历器编译器上的调用标志问题。

2.0-rc3(2011-07-11)

  • Python表达式不再是TALES表达式;之前,管道操作符会分割Python表达式子句,即使对于Python表达式也允许回退,但这不是ZPT的标准行为。

  • 修复了在动态pathexists评估中发生错误,由于缺少远程上下文而无法传播的问题。

  • 将变量herecontext设置为PageTemplate实例上的绑定实例值。

2.0-rc2(2011-03-24)

  • 修复了与"exists:"表达式的问题,其中会尝试调用可调用对象。现在,这个表达式类型隐含地表示它应该使用"nocall:"说明。

2.0-rc1(2011-02-28)

  • 更新到Chameleon 2.0。

    本版本包含许多更改,并是对1.x系列的全面重写。

    平台

    • 现在需要Python 2.5及以上版本。

    显著变化

    • 表达式插值始终启用。

    • 空白输出不同,现在与模板输入紧密对齐。

    • 新的语言结构

      1. tal:on-error

      2. tal:switch

      3. tal:case

    不兼容性

    • 表达式翻译接口已被表达式引擎取代。这意味着所有表达式都必须重写。

  • 存在表达式评估器应忽略KeyError异常。

  • 特殊处理Zope2的Missing.MV,如Products.ZCatalog在LP#649343中所述。[rossp]

1.2.1 (2010/05/13)

  • 在一般情况下将模板绑定到模板对象。

1.2 (2010/05/12)

  • 修复了与Chameleon最近更改不兼容的问题。

  • 修复了因传递参数而引入的回归。顺便说一句,名称“args”被用作星号参数名称。

  • 在调用zope.i18n协商者之前查看请求上设置的语言。这使得i18n在Zope2上再次工作。

1.1.1 (2010/04/06)

  • 修复了参数未传递给模板作为“args”的问题。

1.1.0 (2010/01/09)

  • 更新到Chameleon组合发行版。

1.0.1 (2009/07/06)

  • 将翻译上下文(请求)绑定到翻译方法。尽管在翻译机的新版本中不是必需的,但某些版本将要求在显式传递语言时请求一个翻译上下文,以协商语言。

  • 当zope.security作为“class”ZCML指令移动到那里时,为类声明zope安全设置。

1.0.0 (2009/07/06)

  • 第一个点发行版。

1.0b17 (2009/06/14)

  • 将重复字典的Zope安全声明设置为依赖于zope.app.security而不是zope.app.component。

1.0b16 (2009/05/20)

  • 更新了运行时表达式评估器方法,以便在Chameleon最近进行架构更改后工作。[malthe]

  • 在尝试设置内容类型之前检查我们是否有一个非平凡响应对象。[malthe]

  • sys.modules字典包装在一个“不透明”的字典类中,这样表示字符串就不会列出所有加载的模块。[malthe]

1.0b15 (2009/04/24)

  • 移除了lxml扩展,因为我们不再依赖于它。[malthe]

  • 确保路径表达式是一个简单的字符串,而不是Unicode。[malthe]

  • 在doctests中使用ViewPageTemplateFile时,正确检测路径前缀。[sidnei]

  • 模板基类已经设置了template符号。[malthe]

  • 设置内容类型头,以便与zope.app.pagetemplate保持向后兼容。[sidnei]

1.0b14 (2009/03/31)

  • 更新语言适配器以使用‘结构’元属性。[malthe]

1.0b13 (2009/03/23)

  • 在字典上遍历时,仅公开字典项(从不公开属性);这是为了避免歧义。[sidnei, malthe]

  • 路径表达式需要以相反顺序传递更多的路径项到traversePathElement,因为这就是它所期望的。[sidnei]

1.0b12 (2009/03/09)

  • 将初始变量上下文插入动态作用域。许多应用程序都期望这些的存在。[malthe]

1.0b11 (2009/03/05)

  • 如果命名空间获取的对象提供了ITraversable,则使用路径遍历。[malthe]

  • 实现了TALES函数命名空间。[sidnei, malthe]

  • 在存在遍历者中捕获NameError(返回false)。[malthe]

  • 在存在评估器中捕获NameError(返回false)。[malthe]

  • 如果提供的contextrequest参数是平凡的,则从视图实例中获取它们。[malthe]

  • 文本模板中的表达式永远不会转义。[malthe]

  • 不要将模板绑定到一个平凡的实例。[malthe]

1.0b10 (2009/02/24)

  • 修复了exists-traverser,使其始终返回布尔值。[malthe]

1.0b9 (2009/02/19)

  • 在运行时评估路径表达式(例如path方法)时,先通过transform运行源代码以支持动态作用域。[malthe]

1.0b8 (2009/02/17)

  • 允许对绑定页面模板上的__call__方法进行属性访问。[malthe]

1.0b7 (2009/02/13)

  • 修复了符号映射在否定(not)下不会传递的问题。[malthe]

  • 优化简单情况:如果路径表达式是单个路径且路径是“nothing”或具有“nocall:”,则直接返回值,而无需通过path_traverse。[sidnei]

  • 将evaluate_path和evaluate_exists从five.pt迁移过来,添加了对全局path()和exists()函数的支持,用于在python表达式(LP #317967)中使用。[malthe]

  • 为repeat字典(tales迭代器)添加了Zope安全声明。[malthe]

1.0b6 (2008/12/18)

  • “not”语句是递归的。[malthe]

1.0b5 (2008/12/15)

  • 视图模板现在支持传递参数以使用不同的上下文和请求(与zope.app.pagetemplate兼容)。[malthe]

  • 默认关闭了$-插值功能;可以通过使用在每个模板上激活它。[seletz]

  • 允许在覆盖PathTranslator方法时具有更多灵活性。[hannosch]

  • 从基准测试套件中删除了强制默认编码。[hannosch]

1.0b4 (2008/11/19)

  • 将内容提供程序函数调用拆分出来,以便通过子类化进行修改。[malthe]

  • 添加了语言协商。[malthe]

  • 简化了模板类继承。[malthe]

  • 在路径表达式中添加了对问号运算符的支持。[malthe]

  • 更新了表达式以符合最近的API更改。[malthe]

  • 添加了“exists”和“not”转换器。[malthe]

    错误修复

  • 调整了bigtable基准测试以符合API更改。[hannosch]

1.0b3 (2008/11/12)

  • 添加了PageTemplate和PageTemplateFile类。[malthe]

1.0b2 (2008/11/03)

错误修复

  • 允许在内容提供程序表达式中使用“.”字符。

  • 允许在路径表达式中使用“+”字符。

1.0b1 (2008/10/02)

包更改

  • 将编译器拆分到“Chameleon”包中。[malthe]

    向后不兼容性

  • 将z3c.pt.macro模块的内容移动到z3c.pt.template中。[malthe]

  • 对于没有显式文档类型的模板,不再渲染命名空间属性“xmlns”。[malthe]

  • 模板方法签名更改。[malthe]

  • 引擎现在期望所有字符串都是unicode或仅包含ASCII字符,除非提供了编码。[malthe]

  • 默认路径遍历器不再代理对象。[malthe]

  • 模板输出现在始终转换为unicode。[malthe]

  • 现在ViewPageTemplateFile类使用“path”作为默认表达式类型。[malthe]

  • 编译器现在期望一个实例化的解析器实例。[malthe]

    功能

  • 添加了“provider:”表达式转换器(它渲染在zope.contentprovider包中定义的内容提供程序)。[malthe]

  • 添加了渲染宏的模板API。[malthe]

  • 优化模板加载器,以确保每个文件只实例化一个模板。[malthe]

  • 将z3c.pt转换为命名空间包。[malthe]

  • 在测试示例中的编译和渲染流程中添加了减少和恢复操作以验证完整性。[malthe]

  • 现在ZPT解析器支持前缀本地属性,例如:

  • 现在在调试模式下将源代码写入磁盘。[malthe]

  • 如果插入的字符串无效(当启用调试模式时),现在将引发自定义验证错误。[malthe]

  • 在动态属性分配中添加了对省略HTML“切换”属性(选项的selected和输入的checked)的支持。如果赋值表达式中的值评估等于布尔值False,则属性将不会被渲染。如果赋值表达式中的值评估等于布尔值True,则属性将被渲染,并且属性的值将是表达式返回的值。[chrism]

  • XML命名空间属性现在始终打印根标签。[malthe]

  • 允许使用标准HTML实体。[malthe]

  • 添加了编译器选项以指定隐式doctype;这目前由模板类使用,以便将松散的XHTML doctype作为默认值。[malthe]

  • 添加了对标签体的翻译支持。[malthe]

  • 为TALES迭代器(重复字典)添加了安全配置。这取决于应用程序安全框架的可用性。[malthe]

  • 动态属性现在按照模板中的顺序排列。[malthe]

  • 添加了symbol_mapping属性到代码流中,以便可以在编译时注册函数依赖。[malthe]

  • 允许BaseTemplate派生类(PageTemplate、PageTemplateFile等)接受一个doctype参数,如果指定,将覆盖模板来源提供的doctype。[chrism]

  • 语言协商留给页面模板超类,因此我们不再需要传递翻译上下文。[malthe]

  • 现在ViewPageTemplateFile类使用调用类的模块路径来获取传递给构造函数的相对文件名的绝对路径。[malthe]

  • 添加了对XInclude include指令的有限支持。实现的子集对应于Genshi实现,除了Match模板,它不提供给调用模板。[malthe]

  • 为文件系统上的模板使用全局模板注册表。这使得多个模板类实例指向同一文件变得非常经济。[malthe]

  • 重新实现了磁盘缓存以正确恢复所有模板数据。该实现将缓存以序列化格式保存在原始模板旁边的文件中。[malthe]

  • 重构了编译类以更好地分离关注点。[malthe]

  • Genshi宏(py:def)现在全局可用。[malthe]

  • 如果插值表达式未耗尽,现在将引发语法错误,例如,只有字符串的一部分是有效的Python表达式。[malthe]

  • 系统变量现在在配置类中定义。[malthe]

  • 通过不重复调用昂贵的“flatten”函数来提高代码生成性能。[chrism]

  • 移除了safe_render实现细节。它隐藏了跟踪信息。[chrism]

  • 实现了TAL全局定义。[malthe]

  • 添加了对全局作用域变量的支持。[malthe]

  • 如果表达式只是一个变量名,现在可以省略表达式插值中的花括号;这符合Genshi语法。[malthe]

  • 对Unicode属性文字进行UTF-8编码。[chrism]

  • 大大减少了lxml CDATA绕过的编译器开销。[malthe]

  • 将Genshi和Zope语言方言的元素编译器类分离开来。[malthe]

  • 将lxml作为setuptools“额外”内容。要使用lxml支持(目前Genshi需要),在buildout或setup.py的install_requires中指定任何引用包的“z3c.pt [lxml]”。[chrism]

  • 向buildout添加test-nolxml和py-nolxml部分,以便在没有lxml的情况下运行包的测试。[chrism]

  • 不再需要默认命名空间。[malthe]

  • 将源代码调试模式文件重命名为.py,而不是.source。

  • 通用ElementTree导入,允许使用Python 2.5的xml.etree模块和独立的ElementTree包。[malthe]

  • 当编译器在调试模式下运行时,现在验证表达式结果是否对XML正确。[malthe]

  • 初步支持使用xml.etree作为lxml.etree的备用方案。[malthe]

  • 字符串表达式现在可以使用双分号(;;)表示分号。[malthe]

  • 保留CDATA部分。[malthe]

  • 移除BaseTemplateFile构造函数中的包相对魔数,改为只要求绝对路径或相对于getcwd()的路径。理由是,当从__main__调用,且模板相对于getcwd()时,它不起作用,这是人们初次尝试的99%的情况。[chrism]

  • 添加了对METAL的支持。[malthe]

  • 添加了TemplateLoader类,以便方便地实例化模板。这与其他模板工具包中的模板加载器类似,使得与Pylons的集成更加简单。[wichert]

  • 将config.py中所有选项的硬编码改为使用模板参数。这也允许我们使用更合理的auto_reload标志,而不是重用PROD_MODE,后者还用于其他目的。[wichert]

  • 将源模板中的注释、处理指令和命名实体视为“字面量”,将按原样渲染到输出中。[chrism]

    错误修正

  • 如果调用模板正在填充它,则跳过“define-slot”子句中的元素。[malthe]

  • 支持具有METAL命名空间的元素上的“fill-slot”。[malthe]

  • 在渲染宏时省略元素文本。[malthe]

  • Macros类不应返回可调用函数,而应返回一个具有render-方法的Macro对象。这使得可以使用路径表达式来获取宏,而不必调用它。[malthe]

  • 修复了重复子句在评估表达式之前重置重复变量的错误。[malthe]

  • 修复了与正确恢复阴影模板对象相关的问题。[malthe]

  • 隐式DOCTYPE现在从缓存中正确重新建立。[malthe]

  • 为了解决从文件缓存加载的XML树解析时产生的语法错误,移除了根标签上的命名空间声明。[malthe]

  • 具有表达式值的属性赋值(以字符in开头,例如info.somename)将渲染到生成的Python中,而不带in前缀(例如fo.somename)。[chrism]

  • 当填充METAL槽(可能是特定版本的libxml2,我使用2.6.32)时,可能导致翻译器尝试向NoneType添加字符串类型(在读取variable = self.symbols.slot+element.node.fill_slot的行中,因为查找fill-slot节点的XPath表达式没有正确工作)。[chrism]

  • 在字符串翻译表达式中保留空白。[malthe]

  • 修复了插值错误,其中多个具有插值表达式的属性会导致输出损坏。[malthe]

  • 当默认表达式类型为'python'时,支持try-except运算符('|')。[malthe]

  • METAL宏应在它们定义的模板中渲染。[malthe]

  • 仅当重复单个项目时避免打印换行符。[malthe]

  • 更正了Genshi命名空间(需要尾部斜杠)。[malthe]

  • 修复了几个UnicodeDecodeErrors(Wiggy提供的测试案例)。特别是,在转换过程中从不提升到unicode,并在Assign表达式(例如py:attrs)中用utf-8对Unicode属性键和值进行编码。[chrism]

  • 修复了插值例程中的off-by-one错误。[malthe]

  • 重复子句不应该在每个迭代中都输出尾部。[malthe]

  • 现在在ElementTree解析器中使用时,正确处理CDATA部分。[malthe]

  • 修复了路径表达式中字符串实例会被(尝试)调用的问题。[malthe]

  • 现在在使用表达式插值时,正确保留CDATA部分。[malthe]

  • 在文本或尾部区域使用时,Genshi插值运算符${}的结果不应被转义。[malthe]

  • 修复了插入数字实体和一组Unicode字节时导致的UnicodeDecodeError边缘情况错误。参见http://groups.google.com/group/z3c_pt/browse_thread/thread/aea963d25a1778d0?hl=en [chrism]

  • 静态属性现在可以通过py:attr-attributes正确覆盖。[malthe]

0.9 (2008/08/07)

  • 添加了对Genshi模板的支持。[malthe]

  • 清理和重构了翻译模块。[malthe]

  • 如果模板源包含DOCTYPE声明,则在渲染时输出。[chrism]

  • 修复了在文本或尾部元素部分指定的数字实体会导致在默认编码为“ascii”的系统上引发UnicodeDecodeError的错误。[chrism]

  • 对基于文件系统的缓存进行了微重构,并添加了对缓存的简单基准测试。与缓存相比,模板的初始加载速度显著下降。与zope.pagetemplate相比,我们只慢3倍,而每次在进程启动时生成每个模板则慢50倍。

  • 完全弃用了_escape函数,并直接内联了实际代码。对于路径和Python表达式,我们再次达到12倍和19倍的速度。:)[hannosch]

  • 避免字符串连接,而是使用多个写入语句。现在这些语句更快,因为我们使用列表append进行内部操作。[hannosch]

  • 内联_escape函数,因为函数调用在Python中代价高昂。为Unicode值添加了缺失的转义。[fschulze, hannosch]

  • 当模板在类定义外部实例化时,将相对文件路径使用模块路径转换为绝对路径。[malthe]

  • 通过将str调用引入函数来简化_escape函数的处理。更正了bigtable hotshot测试,仅对渲染进行基准测试。

  • 用优化的本地版本替换了cgi.escape函数,对于路径和Python表达式,我们达到11倍和16倍的速度。在大表基准测试中,增强效果更为明显——我们现在与spitfire -O1模板的速度相同,只是-O3速度的一半。:)))

  • 添加了一个名为bigtable的新基准测试,它产生的结果可以直接与spitfire项目中的bigtable.py基准测试的结果进行比较。

  • 引入了一个名为Z3C_PT_DISABLE_I18N的新配置选项。如果将此环境变量设置为true,模板引擎将不再调用zope.i18n机制,而是在所有情况下回退到简单的插值。在具有完整i18n基础设施的正常Zope环境中,这将使模板渲染速度比正常TAL快15倍,而不是目前的10倍。

  • 从基准测试套件中删除了第二次渲染测试。由于我们为基准测试启用了文件缓存,因此写入缓存文件后,第一次和第二次渲染之间没有差异。

  • 要求使用zope.i18n 3.5,并添加了对其新negotiate函数的支持。如果您使用zope_i18n_allowed_languages环境变量,则模板的目标语言仅在每个模板上协商一次,而不是在每次translate函数调用上协商一次。这提高了速度超过两倍,基准测试速度回到9.2倍。

  • 扩展了i18n处理,以尊重传递给模板的翻译上下文。通常情况下,这是请求,通过内部名称_context传递给渲染函数。在扩展i18n测试以包括协商者和消息目录后,改进仅为4.5,因为大部分时间都花费在i18n机制中。

  • 添加了持久化文件缓存功能。如果设置了环境变量,每个基于文件系统的模板都会将一个目录添加到缓存中(目前使用文件的绝对路径的SHA-1作为文件夹名称),并在文件夹中为模板的每个参数创建一个文件(缓存文件名为参数的哈希)。一旦模板文件初始化,就会添加一个实例本地注册表,然后查找所有缓存的文件,并预先使用渲染函数填充注册表。

  • 修复了插值边缘情况错误。[malthe]

  • 添加了新的Z3C_PT_FILECACHE环境变量,指向一个目录。如果设置,则将用于缓存编译后的文件。

  • 添加了重复子句的第二个变体,使用简单的for循环。它不支持repeatdict,因此尚未使用。还开始为使用变量的子句添加检查功能。简单的循环使路径表达式的基准测试达到10.5(旧9.5),Python表达式的基准测试达到14.5(12.5)。因此,下一步是引入一个优化阶段,以决定使用哪种循环变体。

  • 使调试模式与Python调试模式独立。现在可以指定名为Z3C_PT_DEBUG的环境变量来启用它。

  • 在filecache模块中添加了一些代码,以后可以用来将编译后的Python代码写入和从文件系统重新加载。我们应该能够避免在Python进程重启时的重新解析。

  • 简化了生成 _escape 代码。cgi.escape的第二个参数是一个简单的布尔值,而不是要转义的字符列表。

  • 使用基于列表的BufferIO类代替cStringIO作为输出流。避免对Unicode数据进行编码是一个更大的胜利。我们不支持在引擎内部任意混合Unicode和非ascii字符。

  • 在Tag子句中将两个相邻的写入合并为一个。

  • 应用了一些微优化。‘’.join({})比‘’.join({}.keys())略快,并且完成相同的功能。在非调试模式下避免使用try/except进行错误处理。测试对‘is None’的结果而不是对模板注册表查找的布尔检查。在config.py中使PROD_MODE可用,定义为‘not DEBUG_MODE’,因此我们避免在每个cook-check中重复使用‘not’。

  • 为文件变体添加了更多基准测试。

  • 类似于写入子句,优化了Tag子句中的‘is None’处理。

  • 使_out.write方法直接在所有作用域中可用,称为_write,从而避免每次都调用方法查找。

  • 优化了写入子句中的‘is None’处理。

  • 稍微重构了基准测试,并添加了对文件变体的测试。

  • 在调试模式下,实际文件模板的源代码写入到.source文件中,以便更容易检查。

  • 在config.py中明确设置调试模式设置。当前它绑定到Python的__debug__,在运行-O时为False,否则为True。

  • 使用简化的UnicodeWrite子句处理_translate调用的结果,因为结果值保证是Unicode。

  • 添加了对i18n处理的基准测试。

  • 添加了对i18n属性处理的更多测试。

  • 对于以分号结尾的表达式,不生成空映射。

  • 在i18n属性处理中修复了未定义的名称‘static’错误,并添加了对i18n属性的引号。

  • 在tal命名空间中对标签的有效属性添加了条件。

  • 确保第一个模板异常的堆栈跟踪传递到__traceback_info__

  • 在渲染模板时引发的异常上添加了模板源注释。

0.8 (2008/03/19)

  • 添加了对‘nocall’和‘not’(用于路径表达式)的支持。

  • 添加了对路径和字符串表达式的支持。

  • 抽象表达式转换引擎。表达式实现现在是可插拔的。支持整个表达式的名称祈使语。

  • 形式化的表达式类型

  • 添加了对“结构”关键字的支持,用于替换和内容。

  • “替换”和“内容”的结果现在默认转义。

  • 基准现在作为自定义测试运行器构建。

0.7 (2008/03/10)

  • 添加了对注释的支持;注释中允许使用表达式,即。

    <!– ${‘Hello World!’} –>

    注释总是包含在内。

0.7 (2008/02/24)

  • 添加了对文本模板的支持;这些允许在非XML文档(如CSS样式表和javascript文件)中进行表达式插值。

0.5 (2008/02/23)

  • 实现了表达式插值。

0.4 (2008/02/22)

  • 引擎现在使用cStringIO,提供了2.5倍的性能提升。Unicode现在得到正确处理。

0.3 (2007/12/23)

  • 代码优化;修正了一系列错误

  • 添加了ViewPageTemplateFile

  • 添加了对i18n的支持

  • 引擎重写;改进了代码生成抽象

0.2 (2007/12/05)

  • 对生成的代码进行了重大优化

0.1 (2007/12/03)

  • 首次公开发布

项目详情


发布历史 发布通知 | RSS源

下载文件

下载适用于您的平台文件。如果您不确定选择哪个,请了解更多关于 安装包 的信息。

源代码分布

z3c.pt-4.4.tar.gz (68.3 kB 查看哈希值)

上传时间 源代码

构建分布

z3c.pt-4.4-py3-none-any.whl (40.4 kB 查看哈希值)

上传时间 Python 3

由以下支持