summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Howitz <mh@gocept.com>2021-05-28 08:06:54 +0200
committerGitHub <noreply@github.com>2021-05-28 08:06:54 +0200
commit285490922584c1be42b5be89c00e7c8e1d972fb8 (patch)
tree1799c5e38f037525a99d6784e6b54f9ae0e6d0b8
parent7153aa0fbb108e9c74d13a2454e1602330bf9b4e (diff)
downloadzope-pagetemplate-285490922584c1be42b5be89c00e7c8e1d972fb8.tar.gz
Config with pure python (#28)
* Lint the code. * Add support for Python 3.9.
-rw-r--r--.coveragerc11
-rw-r--r--.editorconfig39
-rw-r--r--.github/workflows/tests.yml61
-rw-r--r--.gitignore32
-rw-r--r--.meta.toml25
-rw-r--r--.travis.yml21
-rw-r--r--CHANGES.rst2
-rw-r--r--MANIFEST.in15
-rw-r--r--bootstrap.py210
-rw-r--r--setup.cfg12
-rw-r--r--setup.py3
-rw-r--r--src/zope/__init__.py2
-rw-r--r--src/zope/pagetemplate/engine.py35
-rw-r--r--src/zope/pagetemplate/interfaces.py22
-rw-r--r--src/zope/pagetemplate/pagetemplate.py46
-rw-r--r--src/zope/pagetemplate/pagetemplatefile.py6
-rw-r--r--src/zope/pagetemplate/tests/batch.py10
-rw-r--r--src/zope/pagetemplate/tests/test_basictemplate.py15
-rw-r--r--src/zope/pagetemplate/tests/test_engine.py26
-rw-r--r--src/zope/pagetemplate/tests/test_htmltests.py3
-rw-r--r--src/zope/pagetemplate/tests/test_ptfile.py5
-rw-r--r--src/zope/pagetemplate/tests/util.py14
-rw-r--r--tox.ini90
23 files changed, 365 insertions, 340 deletions
diff --git a/.coveragerc b/.coveragerc
deleted file mode 100644
index a644d51..0000000
--- a/.coveragerc
+++ /dev/null
@@ -1,11 +0,0 @@
-[run]
-source = zope.pagetemplate
-
-[report]
-precision = 2
-exclude_lines =
- pragma: no cover
- if __name__ == '__main__':
- raise NotImplementedError
- self.fail
- raise AssertionError
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..f3e46f5
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,39 @@
+# Generated from:
+# https://github.com/zopefoundation/meta/tree/master/config/pure-python
+#
+# EditorConfig Configuration file, for more details see:
+# http://EditorConfig.org
+# EditorConfig is a convention description, that could be interpreted
+# by multiple editors to enforce common coding conventions for specific
+# file types
+
+# top-most EditorConfig file:
+# Will ignore other EditorConfig files in Home directory or upper tree level.
+root = true
+
+
+[*] # For All Files
+# Unix-style newlines with a newline ending every file
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+# Set default charset
+charset = utf-8
+# Indent style default
+indent_style = space
+# Max Line Length - a hard line wrap, should be disabled
+max_line_length = off
+
+[*.{py,cfg,ini}]
+# 4 space indentation
+indent_size = 4
+
+[*.{yml,zpt,pt,dtml}]
+# 2 space indentation
+indent_size = 2
+
+[{Makefile,.gitmodules}]
+# Tab indentation (no size specified, but view as 4 spaces)
+indent_style = tab
+indent_size = unset
+tab_width = unset
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
new file mode 100644
index 0000000..38cb0de
--- /dev/null
+++ b/.github/workflows/tests.yml
@@ -0,0 +1,61 @@
+# Generated from:
+# https://github.com/zopefoundation/meta/tree/master/config/pure-python
+name: tests
+
+on:
+ push:
+ pull_request:
+ schedule:
+ - cron: '0 12 * * 0' # run once a week on Sunday
+ # Allow to run this workflow manually from the Actions tab
+ workflow_dispatch:
+
+jobs:
+ build:
+ strategy:
+ # We want to see all failures:
+ fail-fast: false
+ matrix:
+ config:
+ # [Python version, tox env]
+ - ["3.8", "lint"]
+ - ["2.7", "py27"]
+ - ["3.5", "py35"]
+ - ["3.6", "py36"]
+ - ["3.7", "py37"]
+ - ["3.8", "py38"]
+ - ["3.9", "py39"]
+ - ["pypy2", "pypy"]
+ - ["pypy3", "pypy3"]
+ - ["3.8", "docs"]
+ - ["3.8", "coverage"]
+
+ runs-on: ubuntu-latest
+ name: ${{ matrix.config[1] }}
+ steps:
+ - uses: actions/checkout@v2
+ - name: Set up Python
+ uses: actions/setup-python@v2
+ with:
+ python-version: ${{ matrix.config[0] }}
+ - name: Pip cache
+ uses: actions/cache@v2
+ with:
+ path: ~/.cache/pip
+ key: ${{ runner.os }}-pip-${{ matrix.config[0] }}-${{ hashFiles('setup.*', 'tox.ini') }}
+ restore-keys: |
+ ${{ runner.os }}-pip-${{ matrix.config[0] }}-
+ ${{ runner.os }}-pip-
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install tox
+ - name: Test
+ run: tox -e ${{ matrix.config[1] }}
+ - name: Coverage
+ if: matrix.config[1] == 'coverage'
+ run: |
+ pip install coveralls coverage-python-version
+ coveralls --service=github
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.gitignore b/.gitignore
index aa19a47..9a9e9b9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,17 +1,29 @@
+# Generated from:
+# https://github.com/zopefoundation/meta/tree/master/config/pure-python
+*.egg-info/
+*.profraw
*.pyc
-*.so
-*.dll
-__pycache__
-src/*.egg-info
-
+*.pyo
+.coverage
+.coverage.*
+.eggs/
.installed.cfg
-.tox
+.mr.developer.cfg
+.tox/
+.vscode/
+__pycache__/
bin/
build/
+coverage.xml
develop-eggs/
+develop/
+dist/
+docs/_build
eggs/
+etc/
+lib/
+lib64
+log/
parts/
-dist/
-.coverage
-htmlcov/
-docs/_build/
+pyvenv.cfg
+var/
diff --git a/.meta.toml b/.meta.toml
new file mode 100644
index 0000000..fcc59a1
--- /dev/null
+++ b/.meta.toml
@@ -0,0 +1,25 @@
+# Generated from:
+# https://github.com/zopefoundation/meta/tree/master/config/pure-python
+[meta]
+template = "pure-python"
+commit-id = "785810f9b7cf459f84c3b1a45eb2d639bfb666d2"
+
+[python]
+with-appveyor = false
+with-pypy = true
+with-legacy-python = true
+with-docs = true
+with-sphinx-doctests = true
+
+[tox]
+use-flake8 = true
+
+[coverage]
+fail-under = 97
+
+[manifest]
+additional-rules = [
+ "recursive-include docs *.bat",
+ "recursive-include docs *.pt",
+ "recursive-include src *.html",
+ ]
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 9df35c7..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,21 +0,0 @@
-language: python
-python:
- - 2.7
- - 3.5
- - 3.6
- - 3.7
- - 3.8
- - pypy
- - pypy3
-install:
- - pip install -U pip setuptools
- - pip install -U coverage coveralls
- - pip install -U -e .[test,docs]
-script:
- - coverage run -m zope.testrunner --test-path=src
- - coverage run -a -m sphinx -b doctest -d docs/_build/doctrees docs docs/_build/doctest
-after_success:
- - coveralls
-notifications:
- email: false
-cache: pip
diff --git a/CHANGES.rst b/CHANGES.rst
index 169dfda..68808c3 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -7,6 +7,8 @@
- Avoid traceback reference cycle in ``PageTemplate._cook``.
+- Add support for Python 3.9.
+
4.5.0 (2020-02-10)
==================
diff --git a/MANIFEST.in b/MANIFEST.in
index 0fde81c..8a3cd9b 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,15 +1,16 @@
+# Generated from:
+# https://github.com/zopefoundation/meta/tree/master/config/pure-python
include *.rst
include *.txt
-include bootstrap.py
include buildout.cfg
include tox.ini
-include .travis.yml
-include .coveragerc
-recursive-include src *.txt *.html *.pt
-
-recursive-include docs *.rst
recursive-include docs *.py
-recursive-include docs *.pt
+recursive-include docs *.rst
+recursive-include docs *.txt
recursive-include docs Makefile
+
+recursive-include src *.py
recursive-include docs *.bat
+recursive-include docs *.pt
+recursive-include src *.html
diff --git a/bootstrap.py b/bootstrap.py
deleted file mode 100644
index a459921..0000000
--- a/bootstrap.py
+++ /dev/null
@@ -1,210 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2006 Zope Foundation 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.
-"""
-
-import os
-import shutil
-import sys
-import tempfile
-
-from optparse import OptionParser
-
-__version__ = '2015-07-01'
-# See zc.buildout's changelog if this version is up to date.
-
-tmpeggs = tempfile.mkdtemp(prefix='bootstrap-')
-
-usage = '''\
-[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
-
-Bootstraps a buildout-based project.
-
-Simply run this script in a directory containing a buildout.cfg, using the
-Python that you want bin/buildout to use.
-
-Note that by using --find-links to point to local resources, you can keep
-this script from going over the network.
-'''
-
-parser = OptionParser(usage=usage)
-parser.add_option("--version",
- action="store_true", default=False,
- help=("Return bootstrap.py version."))
-parser.add_option("-t", "--accept-buildout-test-releases",
- dest='accept_buildout_test_releases',
- action="store_true", default=False,
- help=("Normally, if you do not specify a --version, the "
- "bootstrap script and buildout gets the newest "
- "*final* versions of zc.buildout and its recipes and "
- "extensions for you. If you use this flag, "
- "bootstrap and buildout will get the newest releases "
- "even if they are alphas or betas."))
-parser.add_option("-c", "--config-file",
- help=("Specify the path to the buildout configuration "
- "file to be used."))
-parser.add_option("-f", "--find-links",
- help=("Specify a URL to search for buildout releases"))
-parser.add_option("--allow-site-packages",
- action="store_true", default=False,
- help=("Let bootstrap.py use existing site packages"))
-parser.add_option("--buildout-version",
- help="Use a specific zc.buildout version")
-parser.add_option("--setuptools-version",
- help="Use a specific setuptools version")
-parser.add_option("--setuptools-to-dir",
- help=("Allow for re-use of existing directory of "
- "setuptools versions"))
-
-options, args = parser.parse_args()
-if options.version:
- print("bootstrap.py version %s" % __version__)
- sys.exit(0)
-
-
-######################################################################
-# load/install setuptools
-
-try:
- from urllib.request import urlopen
-except ImportError:
- from urllib2 import urlopen
-
-ez = {}
-if os.path.exists('ez_setup.py'):
- exec(open('ez_setup.py').read(), ez)
-else:
- exec(urlopen('https://bootstrap.pypa.io/ez_setup.py').read(), ez)
-
-if not options.allow_site_packages:
- # ez_setup imports site, which adds site packages
- # this will remove them from the path to ensure that incompatible versions
- # of setuptools are not in the path
- import site
- # inside a virtualenv, there is no 'getsitepackages'.
- # We can't remove these reliably
- if hasattr(site, 'getsitepackages'):
- for sitepackage_path in site.getsitepackages():
- # Strip all site-packages directories from sys.path that
- # are not sys.prefix; this is because on Windows
- # sys.prefix is a site-package directory.
- if sitepackage_path != sys.prefix:
- sys.path[:] = [x for x in sys.path
- if sitepackage_path not in x]
-
-setup_args = dict(to_dir=tmpeggs, download_delay=0)
-
-if options.setuptools_version is not None:
- setup_args['version'] = options.setuptools_version
-if options.setuptools_to_dir is not None:
- setup_args['to_dir'] = options.setuptools_to_dir
-
-ez['use_setuptools'](**setup_args)
-import setuptools
-import pkg_resources
-
-# This does not (always?) update the default working set. We will
-# do it.
-for path in sys.path:
- if path not in pkg_resources.working_set.entries:
- pkg_resources.working_set.add_entry(path)
-
-######################################################################
-# Install buildout
-
-ws = pkg_resources.working_set
-
-setuptools_path = ws.find(
- pkg_resources.Requirement.parse('setuptools')).location
-
-# Fix sys.path here as easy_install.pth added before PYTHONPATH
-cmd = [sys.executable, '-c',
- 'import sys; sys.path[0:0] = [%r]; ' % setuptools_path +
- 'from setuptools.command.easy_install import main; main()',
- '-mZqNxd', tmpeggs]
-
-find_links = os.environ.get(
- 'bootstrap-testing-find-links',
- options.find_links or
- ('http://downloads.buildout.org/'
- if options.accept_buildout_test_releases else None)
- )
-if find_links:
- cmd.extend(['-f', find_links])
-
-requirement = 'zc.buildout'
-version = options.buildout_version
-if version is None and not options.accept_buildout_test_releases:
- # Figure out the most recent final version of zc.buildout.
- import setuptools.package_index
- _final_parts = '*final-', '*final'
-
- def _final_version(parsed_version):
- try:
- return not parsed_version.is_prerelease
- except AttributeError:
- # Older setuptools
- for part in parsed_version:
- if (part[:1] == '*') and (part not in _final_parts):
- return False
- return True
-
- index = setuptools.package_index.PackageIndex(
- search_path=[setuptools_path])
- if find_links:
- index.add_find_links((find_links,))
- req = pkg_resources.Requirement.parse(requirement)
- if index.obtain(req) is not None:
- best = []
- bestv = None
- for dist in index[req.project_name]:
- distv = dist.parsed_version
- if _final_version(distv):
- if bestv is None or distv > bestv:
- best = [dist]
- bestv = distv
- elif distv == bestv:
- best.append(dist)
- if best:
- best.sort()
- version = best[-1].version
-if version:
- requirement = '=='.join((requirement, version))
-cmd.append(requirement)
-
-import subprocess
-if subprocess.call(cmd) != 0:
- raise Exception(
- "Failed to execute command:\n%s" % repr(cmd)[1:-1])
-
-######################################################################
-# Import and run buildout
-
-ws.add_entry(tmpeggs)
-ws.require(requirement)
-import zc.buildout.buildout
-
-if not [a for a in args if '=' not in a]:
- args.append('bootstrap')
-
-# if -c was provided, we push it back into args for buildout' main function
-if options.config_file is not None:
- args[0:0] = ['-c', options.config_file]
-
-zc.buildout.buildout.main(args)
-shutil.rmtree(tmpeggs)
diff --git a/setup.cfg b/setup.cfg
index 2a9acf1..8b04203 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,2 +1,14 @@
+# Generated from:
+# https://github.com/zopefoundation/meta/tree/master/config/pure-python
[bdist_wheel]
universal = 1
+
+[flake8]
+doctests = 1
+
+[check-manifest]
+ignore =
+ .editorconfig
+ .meta.toml
+ docs/_build/html/_sources/*
+ docs/_build/doctest/*
diff --git a/setup.py b/setup.py
index 155cf99..72131e7 100644
--- a/setup.py
+++ b/setup.py
@@ -58,6 +58,7 @@ setup(name='zope.pagetemplate',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
'Natural Language :: English',
@@ -99,4 +100,4 @@ setup(name='zope.pagetemplate',
include_package_data=True,
zip_safe=False,
tests_require=TESTS_REQUIRE,
-)
+ )
diff --git a/src/zope/__init__.py b/src/zope/__init__.py
index de40ea7..656dc0f 100644
--- a/src/zope/__init__.py
+++ b/src/zope/__init__.py
@@ -1 +1 @@
-__import__('pkg_resources').declare_namespace(__name__)
+__import__('pkg_resources').declare_namespace(__name__) # pragma: no cover
diff --git a/src/zope/pagetemplate/engine.py b/src/zope/pagetemplate/engine.py
index fc2a0cd..4eb805d 100644
--- a/src/zope/pagetemplate/engine.py
+++ b/src/zope/pagetemplate/engine.py
@@ -29,19 +29,21 @@ from zope.traversing.adapters import traversePathElement
from zope.security.proxy import ProxyFactory, removeSecurityProxy
from zope.i18n import translate
-try:
+try: # pragma: no cover
+ # Until https://github.com/zopefoundation/zope.untrustedpython/issues/2
+ # is fixed Python 3 does not support special handling for untrusted code:
from zope.untrustedpython import rcompile
from zope.untrustedpython.builtins import SafeBuiltins
HAVE_UNTRUSTED = True
-except ImportError: # pragma: no cover
+except ImportError:
HAVE_UNTRUSTED = False
-# PyPy doesn't support assigning to '__builtins__', even when
-# using eval() (http://pypy.readthedocs.org/en/latest/cpython_differences.html),
-# so don't try to use it. It won't work.
-if HAVE_UNTRUSTED:
+# PyPy doesn't support assigning to '__builtins__', even when using eval()
+# (http://pypy.readthedocs.org/en/latest/cpython_differences.html), so don't
+# try to use it. It won't work.
+if HAVE_UNTRUSTED: # pragma: no cover
import platform
- if platform.python_implementation() == 'PyPy': # pragma: no cover
+ if platform.python_implementation() == 'PyPy':
HAVE_UNTRUSTED = False
del rcompile
del SafeBuiltins
@@ -53,9 +55,11 @@ from zope.tales.tales import ExpressionEngine, Context
from zope.pagetemplate.i18n import ZopeMessageFactory as _
+
class InlineCodeError(Exception):
pass
+
class ZopeTraverser(object):
def __init__(self, proxify=None):
@@ -85,15 +89,19 @@ class ZopeTraverser(object):
object = self.proxify(object)
return object
+
zopeTraverser = ZopeTraverser(ProxyFactory)
+
class ZopePathExpr(PathExpr):
def __init__(self, name, expr, engine):
super(ZopePathExpr, self).__init__(name, expr, engine, zopeTraverser)
+
trustedZopeTraverser = ZopeTraverser()
+
class TrustedZopePathExpr(PathExpr):
def __init__(self, name, expr, engine):
@@ -118,9 +126,11 @@ class ZopePythonExpr(PythonExpr):
def _compile(self, text, filename):
return rcompile.compile(text, filename, 'eval')
+
def _get_iinterpreter():
from zope.app.interpreter.interfaces import IInterpreter
- return IInterpreter # pragma: no cover
+ return IInterpreter # pragma: no cover
+
class ZopeContextBase(Context):
"""Base class for both trusted and untrusted evaluation contexts."""
@@ -173,7 +183,10 @@ class ZopeContext(ZopeContextBase):
>>> from zope.pagetemplate.engine import ZopeContext
>>> from zope.tales.tales import ExpressionEngine
>>> from zope.security.proxy import ProxyFactory
- >>> output = [('version', 'xxx'), ('mode', 'html'), ('other', 'things')]
+ >>> output = [
+ ... ('version', 'xxx'),
+ ... ('mode', 'html'),
+ ... ('other', 'things')]
>>> def expression(context):
... return ProxyFactory(output)
...
@@ -305,6 +318,7 @@ class ZopeBaseEngine(ExpressionEngine):
return context
+
class ZopeEngine(ZopeBaseEngine):
"""
Untrusted expression engine.
@@ -439,6 +453,7 @@ class ZopeEngine(ZopeBaseEngine):
return ProxyFactory(
super(ZopeEngine, self).getFunctionNamespace(namespacename))
+
class TrustedZopeEngine(ZopeBaseEngine):
"""
Trusted expression engine.
@@ -498,6 +513,7 @@ def _Engine(engine=None):
return engine
+
def _TrustedEngine(engine=None):
if engine is None:
engine = TrustedZopeEngine()
@@ -506,6 +522,7 @@ def _TrustedEngine(engine=None):
engine.registerBaseName('modules', TraversableModuleImporter())
return engine
+
def _create_base_engine(engine, pathtype):
for pt in pathtype._default_type_names:
engine.registerType(pt, pathtype)
diff --git a/src/zope/pagetemplate/interfaces.py b/src/zope/pagetemplate/interfaces.py
index 9a0fe71..0812a83 100644
--- a/src/zope/pagetemplate/interfaces.py
+++ b/src/zope/pagetemplate/interfaces.py
@@ -50,14 +50,15 @@ class IPageTemplate(Interface):
"""Get the template source
"""
- macros = Attribute("An object that implements the ``__getitem__`` "
- "protocol (e.g., a :class:`dict`), containing page template macros.")
+ macros = Attribute(
+ "An object that implements the ``__getitem__`` "
+ "protocol (e.g., a :class:`dict`), containing page template macros.")
+
class IPageTemplateSubclassing(IPageTemplate):
"""Behavior that may be overridden or used by subclasses
"""
-
def pt_getContext(**kw):
"""Compute a dictionary of top-level template names
@@ -136,13 +137,14 @@ class IPageTemplateProgram(Interface):
Optional arguments:
- :keyword bool debug: enable debugging output to sys.stderr (off by default).
- :keyword int wrap: try to wrap attributes on opening tags to this number of
- column (default: 60).
+ :keyword bool debug: enable debugging output to sys.stderr (off by
+ default).
+ :keyword int wrap: try to wrap attributes on opening tags to this
+ number of column (default: 60).
:keyword bool metal: enable METAL macro processing (on by default).
:keyword bool tal: enable TAL processing (on by default).
- :keyword int showtal: do not strip away TAL directives. A special value of
- -1 (which is the default setting) enables showtal when TAL
+ :keyword int 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 (for historical reasons).
@@ -151,6 +153,6 @@ class IPageTemplateProgram(Interface):
Note that Zope turns this value off by default.
:keyword int stackLimit: set macro nesting limit (default: 100).
:keyword bool i18nInterpolate: enable i18n translations (default: on).
- :keyword bool sourceAnnotations: enable source annotations with HTML comments
- (default: off).
+ :keyword bool sourceAnnotations: enable source annotations with HTML
+ comments (default: off).
"""
diff --git a/src/zope/pagetemplate/pagetemplate.py b/src/zope/pagetemplate/pagetemplate.py
index 78d4d50..bd9eafb 100644
--- a/src/zope/pagetemplate/pagetemplate.py
+++ b/src/zope/pagetemplate/pagetemplate.py
@@ -72,7 +72,7 @@ class PageTemplate(object):
Calls pt_getContext() to construct the top-level namespace
passed to the TALES expression engine, then calls pt_render()
to perform the rendering.
- """
+ """ # noqa: E501 line too long
_error_start = '<!-- Page Template Diagnostics'
_error_end = '-->'
@@ -103,7 +103,7 @@ class PageTemplate(object):
'options': options,
'args': args,
'nothing': None,
- }
+ }
rval.update(self.pt_getEngine().getBaseNames())
return rval
@@ -123,7 +123,7 @@ class PageTemplate(object):
__traceback_supplement__ = (
PageTemplateTracebackSupplement, self, namespace
- )
+ )
if self._v_errors:
raise PTRuntimeError(str(self._v_errors))
@@ -133,7 +133,7 @@ class PageTemplate(object):
return self._v_program(
context, self._v_macros, tal=not source, showtal=showtal,
strictinsert=0, sourceAnnotations=sourceAnnotations
- )
+ )
def pt_errors(self, namespace, check_macro_expansion=True):
self._cook_check()
@@ -144,14 +144,23 @@ class PageTemplate(object):
try:
self.pt_render(namespace, source=1)
except Exception:
- return ('Macro expansion failed', '%s: %s' % sys.exc_info()[:2])
+ return (
+ 'Macro expansion failed', '%s: %s' % sys.exc_info()[:2])
def _convert(self, string, text):
"""Adjust the string type to the type of text"""
- if isinstance(text, six.binary_type) and not isinstance(string, six.binary_type):
+ if isinstance(
+ text,
+ six.binary_type) and not isinstance(
+ string,
+ six.binary_type):
return string.encode('utf-8')
- if isinstance(text, six.text_type) and not isinstance(string, six.text_type):
+ if isinstance(
+ text,
+ six.text_type) and not isinstance(
+ string,
+ six.text_type):
return string.decode('utf-8')
return string
@@ -182,6 +191,7 @@ class PageTemplate(object):
def read(self, request=None):
"""Gets the source, sometimes with macros expanded."""
self._cook_check()
+
def bs(s):
"""Bytes or str"""
return self._convert(s, self._text)
@@ -194,14 +204,14 @@ class PageTemplate(object):
# this point, since we are not evaluating the template.
context = self.pt_getContext(self, request)
return self.pt_render(context, source=1)
- except:
+ except BaseException:
return (bs('%s\n Macro expansion failed\n %s\n-->\n' %
- (self._error_start, "%s: %s" % sys.exc_info()[:2])) +
- self._text)
+ (self._error_start, "%s: %s" %
+ sys.exc_info()[:2])) + self._text)
return bs('%s\n %s\n-->\n' % (self._error_start,
'\n'.join(self._v_errors))) + \
- self._text
+ self._text
def pt_source_file(self):
"""To be overridden."""
@@ -225,16 +235,16 @@ class PageTemplate(object):
try:
engine = queryUtility(
IPageTemplateEngine, default=PageTemplateEngine
- )
+ )
self._v_program, self._v_macros = engine.cook(
source_file, self._text, pt_engine, self.content_type)
- except:
+ except BaseException:
etype, e = sys.exc_info()[:2]
try:
self._v_errors = [
"Compilation failed",
"%s.%s: %s" % (etype.__module__, etype.__name__, e)
- ]
+ ]
finally:
del e
@@ -252,10 +262,10 @@ class PageTemplateEngine(object):
"""
Page template engine that uses the TAL interpreter to render.
- This class implements :class:`zope.pagetemplate.interfaces.IPageTemplateProgram`.
+ This class implements
+ :class:`zope.pagetemplate.interfaces.IPageTemplateProgram`.
"""
-
def __init__(self, program):
self.program = program
@@ -264,7 +274,7 @@ class PageTemplateEngine(object):
interpreter = TALInterpreter(
self.program, macros, context,
stream=output, **options
- )
+ )
interpreter()
return output.getvalue()
@@ -283,7 +293,7 @@ class PageTemplateEngine(object):
return cls(program), macros
-#@implementer(ITracebackSupplement)
+# @implementer(ITracebackSupplement)
class PageTemplateTracebackSupplement(object):
def __init__(self, pt, namespace):
diff --git a/src/zope/pagetemplate/pagetemplatefile.py b/src/zope/pagetemplate/pagetemplatefile.py
index 4cf0bf3..abbea81 100644
--- a/src/zope/pagetemplate/pagetemplatefile.py
+++ b/src/zope/pagetemplate/pagetemplatefile.py
@@ -34,10 +34,12 @@ meta_pattern = re.compile(
br'\s+content=["\']?([^;]+);\s*charset=([^"\']+)["\']?\s*/?\s*>\s*',
re.IGNORECASE)
+
def package_home(gdict):
filename = gdict["__file__"]
return os.path.dirname(filename)
+
class PageTemplateFile(PageTemplate):
"Zope wrapper for filesystem Page Template using TAL, TALES, and METAL"
@@ -109,6 +111,7 @@ class PageTemplateFile(PageTemplate):
def __getstate__(self):
raise TypeError("non-picklable object")
+
XML_PREFIXES = [
b"<?xml", # ascii, utf-8
b"\xef\xbb\xbf<?xml", # utf-8 w/ byte order mark
@@ -116,10 +119,11 @@ XML_PREFIXES = [
b"<\0?\0x\0m\0l\0", # utf-16 little endian
b"\xfe\xff\0<\0?\0x\0m\0l", # utf-16 big endian w/ byte order mark
b"\xff\xfe<\0?\0x\0m\0l\0", # utf-16 little endian w/ byte order mark
- ]
+]
XML_PREFIX_MAX_LENGTH = max(map(len, XML_PREFIXES))
+
def sniff_type(text):
"""Return 'text/xml' if text appears to be XML, otherwise return None."""
for prefix in XML_PREFIXES:
diff --git a/src/zope/pagetemplate/tests/batch.py b/src/zope/pagetemplate/tests/batch.py
index 5d193bd..b6cb872 100644
--- a/src/zope/pagetemplate/tests/batch.py
+++ b/src/zope/pagetemplate/tests/batch.py
@@ -14,6 +14,7 @@
"""Batching support tests
"""
+
class batch(object):
"""Create a sequence batch"""
@@ -38,14 +39,14 @@ class batch(object):
return self._first
def next_sequence_end_item(self):
- _start, end, _spam = opt(self._end+1-self._overlap, 0,
+ _start, end, _spam = opt(self._end + 1 - self._overlap, 0,
self._size, self._orphan, self._sequence)
- return self._sequence[end-1]
+ return self._sequence[end - 1]
def next_sequence_start_item(self):
- start, _end, _spam = opt(self._end+1-self._overlap, 0,
+ start, _end, _spam = opt(self._end + 1 - self._overlap, 0,
self._size, self._orphan, self._sequence)
- return self._sequence[start-1]
+ return self._sequence[start - 1]
def next_sequence(self):
return self._end < len(self._sequence)
@@ -58,6 +59,7 @@ class batch(object):
raise IndexError(index)
return self._sequence[index + self._first]
+
def opt(start, end, size, orphan, sequence):
assert size >= 1
assert start > 0
diff --git a/src/zope/pagetemplate/tests/test_basictemplate.py b/src/zope/pagetemplate/tests/test_basictemplate.py
index f998f21..014dc74 100644
--- a/src/zope/pagetemplate/tests/test_basictemplate.py
+++ b/src/zope/pagetemplate/tests/test_basictemplate.py
@@ -19,6 +19,7 @@ from zope.pagetemplate.tests import util
import zope.pagetemplate.pagetemplate
import zope.component.testing
+
class BasicTemplateTests(unittest.TestCase):
def setUp(self):
@@ -117,7 +118,7 @@ class BasicTemplateTests(unittest.TestCase):
'showtal': False,
'sourceAnnotations': False,
'strictinsert': 0,
- })
+ })
def test_batches_and_formatting(self):
# DTML test 3: batches and formatting:
@@ -234,7 +235,11 @@ class BasicTemplateTests(unittest.TestCase):
self.assertEqual(text, self.t._convert(string, text))
def test_write_error(self):
- self.t.write(self.t._error_start + 'stuff' + self.t._error_end + self.t._newline)
+ self.t.write(
+ self.t._error_start +
+ 'stuff' +
+ self.t._error_end +
+ self.t._newline)
self.assertEqual(self.t._text, '')
def test_read_no_expand(self):
@@ -263,7 +268,8 @@ class TestPageTemplateTracebackSupplement(unittest.TestCase):
def pt_errors(self, ns):
return (ns,)
- pts = zope.pagetemplate.pagetemplate.PageTemplateTracebackSupplement(PT(), 'ns')
+ pts = zope.pagetemplate.pagetemplate.PageTemplateTracebackSupplement(
+ PT(), 'ns')
self.assertEqual(pts.warnings, ['ns'])
@@ -272,5 +278,6 @@ class TestPageTemplateTracebackSupplement(unittest.TestCase):
def pt_errors(self, ns, check_macro_expansion=False):
return None
- pts = zope.pagetemplate.pagetemplate.PageTemplateTracebackSupplement(PT(), 'ns')
+ pts = zope.pagetemplate.pagetemplate.PageTemplateTracebackSupplement(
+ PT(), 'ns')
self.assertEqual(pts.warnings, [])
diff --git a/src/zope/pagetemplate/tests/test_engine.py b/src/zope/pagetemplate/tests/test_engine.py
index 97ec8f6..0caeb93 100644
--- a/src/zope/pagetemplate/tests/test_engine.py
+++ b/src/zope/pagetemplate/tests/test_engine.py
@@ -20,6 +20,7 @@ import zope.pagetemplate.engine
from zope.testing.renormalizing import RENormalizing
from zope.component.testing import PlacelessSetup
+
class EngineTests(PlacelessSetup,
unittest.TestCase):
@@ -41,11 +42,13 @@ class EngineTests(PlacelessSetup,
self.assertEqual(ctx.getValue('request'), 3)
self.assertEqual(ctx.getValue('context'), 4)
+
class DummyEngine(object):
def getTypes(self):
return {}
+
class DummyContext(object):
_engine = DummyEngine()
@@ -53,6 +56,7 @@ class DummyContext(object):
def __init__(self, **kw):
self.vars = kw
+
class ZopePythonExprTests(unittest.TestCase):
def test_simple(self):
@@ -86,8 +90,12 @@ class ZopePythonExprTests(unittest.TestCase):
class TestZopeContext(PlacelessSetup,
unittest.TestCase):
- assertRaisesRegex = getattr(unittest.TestCase, 'assertRaisesRegex',
- getattr(unittest.TestCase, 'assertRaisesRegexp'))
+ assertRaisesRegex = getattr(
+ unittest.TestCase,
+ 'assertRaisesRegex',
+ getattr(
+ unittest.TestCase,
+ 'assertRaisesRegexp'))
def _makeOne(self):
return zope.pagetemplate.engine.ZopeContext(None, {})
@@ -111,8 +119,10 @@ class TestZopeContext(PlacelessSetup,
def test_evaluate_interpreter_not_found(self):
get = zope.pagetemplate.engine._get_iinterpreter
from zope import interface
+
class IInterpreter(interface.Interface):
pass
+
def mock_get():
return IInterpreter
@@ -120,8 +130,9 @@ class TestZopeContext(PlacelessSetup,
ctx.evaluateInlineCode = True
zope.pagetemplate.engine._get_iinterpreter = mock_get
try:
- with self.assertRaisesRegex(zope.pagetemplate.engine.InlineCodeError,
- "No interpreter named"):
+ with self.assertRaisesRegex(
+ zope.pagetemplate.engine.InlineCodeError,
+ "No interpreter named"):
ctx.evaluateCode('lang', 'code')
finally:
zope.pagetemplate.engine._get_iinterpreter = get
@@ -130,8 +141,10 @@ class TestZopeContext(PlacelessSetup,
get = zope.pagetemplate.engine._get_iinterpreter
from zope import interface
from zope import component
+
class IInterpreter(interface.Interface):
pass
+
def mock_get():
return IInterpreter
@@ -167,7 +180,6 @@ class TestTraversableModuleImporter(unittest.TestCase):
with self.assertRaises(TraversalError):
tmi.traverse('zope.pagetemplate.engine.DNE', ())
-
with self.assertRaises(TraversalError):
tmi.traverse('pickle.no_sub_module', ())
@@ -201,7 +213,3 @@ def test_suite():
suite.addTest(doctest.DocTestSuite('zope.pagetemplate.engine',
checker=checker))
return suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='test_suite')
diff --git a/src/zope/pagetemplate/tests/test_htmltests.py b/src/zope/pagetemplate/tests/test_htmltests.py
index 1550634..80f6c0b 100644
--- a/src/zope/pagetemplate/tests/test_htmltests.py
+++ b/src/zope/pagetemplate/tests/test_htmltests.py
@@ -22,6 +22,7 @@ from zope.pagetemplate.pagetemplate import PageTemplate
class Folder(object):
context = property(lambda self: self)
+
class HTMLTests(unittest.TestCase):
def setUp(self):
@@ -58,7 +59,6 @@ class HTMLTests(unittest.TestCase):
out = t(laf=self.folder.laf, getProducts=self.getProducts)
util.check_html(expect, out)
-
def test_3(self):
self.folder.laf.write(util.read_input('teeshoplaf.html'))
@@ -153,5 +153,6 @@ class HTMLTests(unittest.TestCase):
errors = t.pt_errors(namespace, check_macro_expansion=False)
self.assertFalse(errors)
+
def test_suite():
return unittest.defaultTestLoader.loadTestsFromName(__name__)
diff --git a/src/zope/pagetemplate/tests/test_ptfile.py b/src/zope/pagetemplate/tests/test_ptfile.py
index e5cc2e9..ee7fd0d 100644
--- a/src/zope/pagetemplate/tests/test_ptfile.py
+++ b/src/zope/pagetemplate/tests/test_ptfile.py
@@ -20,6 +20,7 @@ import unittest
import six
from zope.pagetemplate.pagetemplatefile import PageTemplateFile
+
class AbstractPTCase(object):
def get_pt(self, text=b'<html />'):
@@ -30,6 +31,7 @@ class AbstractPTCase(object):
pt.read()
return pt
+
class TypeSniffingTestCase(AbstractPTCase,
unittest.TestCase):
@@ -189,7 +191,6 @@ class TestPageTemplateFile(AbstractPTCase,
_prefix=os.path.dirname(__file__))
self.assertEqual(pt.filename, __file__)
-
def test_cook_no_debug(self):
pt = self.get_pt()
pt._v_debug = False
@@ -199,11 +200,11 @@ class TestPageTemplateFile(AbstractPTCase,
pt._cook_check()
self.assertEqual(lr, pt._v_last_read)
-
def test_cook_mtime_fails(self):
pt = self.get_pt()
getmtime = os.path.getmtime
+
def bad(_path):
raise OSError()
os.path.getmtime = bad
diff --git a/src/zope/pagetemplate/tests/util.py b/src/zope/pagetemplate/tests/util.py
index 5ef2ad3..55dbebd 100644
--- a/src/zope/pagetemplate/tests/util.py
+++ b/src/zope/pagetemplate/tests/util.py
@@ -20,6 +20,7 @@ import sys
import unittest
import zope.pagetemplate.tests
+
class arg(object):
__allow_access_to_unprotected_subobjects__ = 1
@@ -29,6 +30,7 @@ class arg(object):
def __str__(self):
return str(self.arg)
+
class argv(object):
__allow_access_to_unprotected_subobjects__ = 1
@@ -40,29 +42,35 @@ class argv(object):
context = property(lambda self: self)
+
class _Test(unittest.TestCase):
- def runTest(self): # pragma: no cover 2.7 compatibility
+ def runTest(self): # pragma: no cover 2.7 compatibility
return
+
_assertEqual = _Test().assertEqual
del _Test
+
def check_html(s1, s2):
s1 = normalize_html(s1)
s2 = normalize_html(s2)
_assertEqual(s1, s2, "HTML Output Changed")
+
def check_xml(s1, s2):
s1 = normalize_xml(s1)
s2 = normalize_xml(s2)
_assertEqual(s1, s2, 'XML Output Changed')
+
def normalize_html(s):
s = re.sub(r"[ \t]+", " ", s)
s = re.sub(r"/>", ">", s)
return s
+
def normalize_xml(s):
s = re.sub(r"\s+", " ", s)
s = re.sub(r"(?s)\s+<", "<", s)
@@ -70,17 +78,17 @@ def normalize_xml(s):
return s
-
-
here = os.path.dirname(zope.pagetemplate.tests.__file__)
input_dir = os.path.join(here, 'input')
output_dir = os.path.join(here, 'output')
+
def read_input(filename):
filename = os.path.join(input_dir, filename)
with open(filename, 'r') as f:
return f.read()
+
def read_output(filename):
filename = os.path.join(output_dir, filename)
with open(filename, 'r') as f:
diff --git a/tox.ini b/tox.ini
index 3132873..bbaa8d6 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,33 +1,87 @@
+# Generated from:
+# https://github.com/zopefoundation/meta/tree/master/config/pure-python
[tox]
+minversion = 3.18
envlist =
- py27,py35,py36,py37,py38,pypy,pypy3,coverage,docs
+ lint
+ py27
+ py35
+ py36
+ py37
+ py38
+ py39
+ pypy
+ pypy3
+ docs
+ coverage
[testenv]
+usedevelop = true
+deps =
+ zope.testrunner
+ # Until repoze.sphinx.autointerface supports Sphinx 4.x we cannot use it:
+ Sphinx < 4
commands =
- zope-testrunner --test-path=src []
- sphinx-build -b doctest -d {envdir}/doctrees docs {envdir}/doctest
-deps=
- py27,pypy: Sphinx < 2
- py27,pypy: sphinxcontrib-websupport < 1.2
+ zope-testrunner --test-path=src {posargs:-vc}
+ sphinx-build -b doctest -d {envdir}/.cache/doctrees docs {envdir}/.cache/doctest
extras =
test
docs
-[testenv:coverage]
-usedevelop = true
-basepython =
- python3.7
-commands =
- coverage run -m zope.testrunner --test-path=src []
- coverage run -a -m sphinx -b doctest -d {envdir}/.cache/doctrees docs {envdir}/.cache/doctest
- coverage html
- coverage report --fail-under=100
+[testenv:lint]
+basepython = python3
+skip_install = true
deps =
- coverage
+ flake8
+ check-manifest
+ check-python-versions
+commands =
+ flake8 src setup.py
+ check-manifest
+ check-python-versions
[testenv:docs]
-basepython =
- python3.7
+basepython = python3
+skip_install = false
+# Until repoze.sphinx.autointerface supports Sphinx 4.x we cannot use it:
+deps = Sphinx < 4
+commands_pre =
commands =
sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html
sphinx-build -b doctest -d docs/_build/doctrees docs docs/_build/doctest
+
+[testenv:coverage]
+basepython = python3
+allowlist_externals =
+ mkdir
+deps =
+ coverage
+ coverage-python-version
+ # Until repoze.sphinx.autointerface supports Sphinx 4.x we cannot use it:
+ Sphinx < 4
+ zope.testrunner
+commands =
+ mkdir -p {toxinidir}/parts/htmlcov
+ coverage run -m zope.testrunner --test-path=src {posargs:-vc}
+ coverage run -a -m sphinx -b doctest -d {envdir}/.cache/doctrees docs {envdir}/.cache/doctest
+ coverage html
+ coverage report -m --fail-under=97
+
+[coverage:run]
+branch = True
+plugins = coverage_python_version
+source = src
+
+[coverage:report]
+precision = 2
+exclude_lines =
+ pragma: no cover
+ pragma: nocover
+ except ImportError:
+ raise NotImplementedError
+ if __name__ == '__main__':
+ self.fail
+ raise AssertionError
+
+[coverage:html]
+directory = parts/htmlcov