summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Madden <jason+github@nextthought.com>2017-09-04 08:01:37 -0500
committerGitHub <noreply@github.com>2017-09-04 08:01:37 -0500
commit4e38b01e582697a3b208ca46ade59dc24556fc41 (patch)
tree6208f498417d0a402948e0766c366b6b4c0ab84d
parentb40f742baf274b154f2c3ddbadd8f7098ec4f260 (diff)
parent5c69a15df699dfa278a60ff6e5eb063acd982979 (diff)
downloadzope-pagetemplate-4e38b01e582697a3b208ca46ade59dc24556fc41.tar.gz
Merge pull request #12 from zopefoundation/coverage
100% Test Coverage. 
-rw-r--r--.coveragerc11
-rw-r--r--.gitignore3
-rw-r--r--.travis.yml21
-rw-r--r--CHANGES.rst62
-rw-r--r--MANIFEST.in3
-rw-r--r--README.rst17
-rw-r--r--setup.cfg2
-rw-r--r--setup.py89
-rw-r--r--src/zope/pagetemplate/engine.py25
-rw-r--r--src/zope/pagetemplate/pagetemplate.py22
-rw-r--r--src/zope/pagetemplate/pagetemplatefile.py26
-rw-r--r--src/zope/pagetemplate/tests/batch.py107
-rw-r--r--src/zope/pagetemplate/tests/test_basictemplate.py193
-rw-r--r--src/zope/pagetemplate/tests/test_engine.py140
-rw-r--r--src/zope/pagetemplate/tests/test_htmltests.py25
-rw-r--r--src/zope/pagetemplate/tests/test_ptfile.py98
-rw-r--r--src/zope/pagetemplate/tests/util.py71
-rw-r--r--tox.ini30
18 files changed, 535 insertions, 410 deletions
diff --git a/.coveragerc b/.coveragerc
new file mode 100644
index 0000000..a644d51
--- /dev/null
+++ b/.coveragerc
@@ -0,0 +1,11 @@
+[run]
+source = zope.pagetemplate
+
+[report]
+precision = 2
+exclude_lines =
+ pragma: no cover
+ if __name__ == '__main__':
+ raise NotImplementedError
+ self.fail
+ raise AssertionError
diff --git a/.gitignore b/.gitignore
index 5012fd2..aa19a47 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,3 +12,6 @@ develop-eggs/
eggs/
parts/
dist/
+.coverage
+htmlcov/
+docs/_build/
diff --git a/.travis.yml b/.travis.yml
index 37c5317..f44d718 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,15 +1,20 @@
language: python
sudo: false
python:
- - 2.7
- - 3.3
- - 3.4
- - 3.5
- - pypy
- - pypy3
+ - 2.7
+ - 3.4
+ - 3.5
+ - 3.6
+ - pypy
+ - pypy3.5-5.8.0
install:
- - pip install tox-travis
+ - pip install -U pip setuptools
+ - pip install -U coverage coveralls
+ - pip install -U -e .[test]
script:
- - tox
+ - coverage run -m zope.testrunner --test-path=src
+after_success:
+ - coveralls
notifications:
email: false
+cache: pip
diff --git a/CHANGES.rst b/CHANGES.rst
index 78f1827..4d529ba 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,20 +1,30 @@
-Changes
-=======
+=========
+ Changes
+=========
4.3.0 (unreleased)
-------------------
+==================
-- Add support for Python 3.5.
+- Add support for Python 3.5 and 3.6.
-- Drop support for Python 2.6 and 3.2.
+- Drop support for Python 2.6, 3.2 and 3.3.
+
+- Certain internal test support objects in the ``tests`` package were
+ removed or modified.
+
+- The ``TraversableModuleImporter`` properly turns ``ImportError``
+ into ``TraversalError``. Previously it was catching ``KeyError``,
+ which cannot be raised.
+
+- Reach 100% code coverage and maintain it through automated testing.
4.2.1 (2015-06-06)
-------------------
+==================
- Add support for Python 3.2.
4.2.0 (2015-06-02)
-------------------
+==================
- Allow short-circuit traversal for non-proxied dict subclasses. See:
https://github.com/zopefoundation/zope.pagetemplate/pull/3 .
@@ -22,28 +32,28 @@ Changes
- Add support for PyPy / PyPy3.
4.1.0 (2014-12-27)
-------------------
+==================
- Add support for Python 3.4.
- Add support for testing on Travis.
4.0.4 (2013-03-15)
-------------------
+==================
- Ensure that ``ZopePythonExpr`` and ``PythonExpr`` are separate classes even
when ``zope.untrustedpython`` is not available. Fixes a ZCML conflict error
in ``zope.app.pagetemplate``.
4.0.3 (2013-02-28)
-------------------
+==================
- Only allow ``zope.untrustedpython`` to be a dependency in Python 2.
- Fix buildout to work properly.
4.0.2 (2013-02-22)
-------------------
+==================
- Migrate from ``zope.security.untrustedpython`` to ``zope.untrustedpython``.
@@ -54,14 +64,14 @@ Changes
- Add support for Python 3.3.
4.0.1 (2012-01-23)
-------------------
+==================
- LP#732972: PageTemplateTracebackSupplement no longer passes
``check_macro_expansion=False`` to old templates which do not
accept this argument.
4.0.0 (2012-12-13)
-------------------
+==================
- Replace deprecated ``zope.interface.classProvides`` usage with equivalent
``zope.interface.provider`` decorator.
@@ -78,12 +88,12 @@ Changes
avoid LP#732972.
3.6.3 (2011-09-21)
-------------------
+==================
- Fix test assertions to be compatible with ``zope.tal`` 3.6.
3.6.2 (2011-09-21)
-------------------
+==================
- Change interface for engine and program such that the return type of
the ``cook`` method is a tuple ``(program, macros)``. This follows
@@ -93,12 +103,12 @@ Changes
``_v_macros`` volatile attribute which was missing.
3.6.1 (2011-08-23)
-------------------
+==================
- Fix issue with missing default value for ``strictinsert``.
3.6.0 (2011-08-20)
-------------------
+==================
- Replace StringIO stream class with a faster list-based implementation.
@@ -108,14 +118,14 @@ Changes
- Remove ancient copyright from test files (LP: #607228)
3.5.2 (2010-07-08)
-------------------
+==================
- Fix ``PTRuntimeError`` exception messages to be consistent across Python
versions, and compatibile with the output under Python 2.4. (More
readable than the previous output under Python 2.6 as well.)
3.5.1 (2010-04-30)
-------------------
+==================
- Remove use of ``zope.testing.doctestunit`` in favor of stdlib's doctest.
@@ -123,7 +133,7 @@ Changes
module uses it.
3.5.0 (2009-05-25)
-------------------
+==================
- Add test coverage reporting support.
@@ -131,7 +141,7 @@ Changes
``zope.app.pagetemplate`` package.
3.4.2 (2009-03-17)
-------------------
+==================
- Remove old zpkg-related DEPENDENCIES.cfg file.
@@ -141,19 +151,19 @@ Changes
- Change `cheeseshop` to `pypi` in the packages' homepage url.
3.4.1 (2009-01-27)
-------------------
+==================
- Fix test due to recent changes in zope.tal.
3.4.0 (2007-10-02)
-------------------
+==================
- Initial release independent of the Zope 3 tree.
3.2.0 (2006-01-05)
-------------------
+==================
- Corresponds to the version of the zope.pagetemplate package shipped
as part of the Zope 3.2.0 release.
@@ -166,7 +176,7 @@ Changes
3.1.0 (2005-10-03)
-------------------
+==================
- Corresponds to the version of the zope.pagetemplate package shipped
as part of the Zope 3.1.0 release.
@@ -178,7 +188,7 @@ Changes
3.0.0 (2004-11-07)
-------------------
+==================
- Corresponds to the version of the zope.pagetemplate package shipped
as part of the Zope X3.0.0 release.
diff --git a/MANIFEST.in b/MANIFEST.in
index 35c9bac..931b611 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -3,4 +3,7 @@ include *.txt
include bootstrap.py
include buildout.cfg
include tox.ini
+include .travis.yml
+include .coveragerc
+
recursive-include src *.txt *.html *.pt
diff --git a/README.rst b/README.rst
index 917b6c5..54a3c3b 100644
--- a/README.rst
+++ b/README.rst
@@ -1,9 +1,22 @@
-``zope.pagetemplate``
-=====================
+=======================
+ ``zope.pagetemplate``
+=======================
+
+.. image:: https://img.shields.io/pypi/v/zope.pagetemplate.svg
+ :target: https://pypi.python.org/pypi/zope.pagetemplate/
+ :alt: Latest release
+
+.. image:: https://img.shields.io/pypi/pyversions/zope.pagetemplate.svg
+ :target: https://pypi.org/project/zope.pagetemplate/
+ :alt: Supported Python versions
.. image:: https://travis-ci.org/zopefoundation/zope.pagetemplate.png?branch=master
:target: https://travis-ci.org/zopefoundation/zope.pagetemplate
+.. image:: https://coveralls.io/repos/github/zopefoundation/zope.pagetemplate/badge.svg?branch=master
+ :target: https://coveralls.io/github/zopefoundation/zope.pagetemplate?branch=master
+
+
Page Templates provide an elegant templating mechanism that achieves a
clean separation of presentation and application logic while allowing
for designers to work with templates in their visual editing tools
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..2a9acf1
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,2 @@
+[bdist_wheel]
+universal = 1
diff --git a/setup.py b/setup.py
index 8c45ee4..69a6a37 100644
--- a/setup.py
+++ b/setup.py
@@ -19,54 +19,20 @@
"""Setup for zope.pagetemplate package
"""
import os
-import sys
from setuptools import setup, find_packages
-PY3 = sys.version_info[0] >= 3
-
def read(*rnames):
with open(os.path.join(os.path.dirname(__file__), *rnames)) as f:
return f.read()
-def _modname(path, base, name=''):
- if path == base:
- return name
- dirname, basename = os.path.split(path)
- return _modname(dirname, base, basename + '.' + name)
-
-def alltests():
- import logging
- import pkg_resources
- import unittest
-
- class NullHandler(logging.Handler):
- level = 50
-
- def emit(self, record):
- pass
-
- logging.getLogger().addHandler(NullHandler())
-
- suite = unittest.TestSuite()
- base = pkg_resources.working_set.find(
- pkg_resources.Requirement.parse('zope.pagetemplate')).location
- for dirpath, dirnames, filenames in os.walk(base):
- if os.path.basename(dirpath) == 'tests':
- for filename in filenames:
- if ( filename.endswith('.py') and
- filename.startswith('test') ):
- mod = __import__(
- _modname(dirpath, base, os.path.splitext(filename)[0]),
- {}, {}, ['*'])
- suite.addTest(mod.test_suite())
- return suite
TESTS_REQUIRE = [
- 'zope.testing',
'zope.proxy',
'zope.security',
-] + (['zope.untrustedpython'] if not PY3 else [])
+ 'zope.testing',
+ 'zope.testrunner',
+]
setup(name='zope.pagetemplate',
@@ -77,8 +43,9 @@ setup(name='zope.pagetemplate',
long_description=(
read('README.rst')
+ '\n\n' +
+ '======================\n'
'Detailed Documentation\n' +
- '----------------------'
+ '======================'
+ '\n\n' +
read('src', 'zope', 'pagetemplate', 'architecture.txt')
+ '\n\n' +
@@ -95,36 +62,44 @@ setup(name='zope.pagetemplate',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
- 'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
+ 'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
'Natural Language :: English',
'Operating System :: OS Independent',
'Topic :: Internet :: WWW/HTTP',
- 'Framework :: Zope3'],
- url='http://pypi.python.org/pypi/zope.pagetemplate',
+ 'Framework :: Zope3',
+ ],
+ url='http://github.com/zopefoundation/zope.pagetemplate',
license='ZPL 2.1',
packages=find_packages('src'),
package_dir={'': 'src'},
namespace_packages=['zope'],
- extras_require=dict(
- test=TESTS_REQUIRE,
- untrusted=['zope.untrustedpython'] if not PY3 else [],
- ),
- install_requires=['setuptools',
- 'six',
- 'zope.interface',
- 'zope.component',
- 'zope.tales',
- 'zope.tal >= 4.2.0',
- 'zope.i18n >= 4.0.1',
- 'zope.i18nmessageid',
- 'zope.traversing',
- ],
+ extras_require={
+ 'test': TESTS_REQUIRE,
+ 'test:python_version == "2.7"': [
+ 'zope.untrustedpython',
+ ],
+ 'untrusted': [
+ ],
+ 'untrusted:python_version == "2.7"': [
+ 'zope.untrustedpython',
+ ],
+ },
+ install_requires=[
+ 'setuptools',
+ 'six',
+ 'zope.interface',
+ 'zope.component',
+ 'zope.tales',
+ 'zope.tal >= 4.2.0',
+ 'zope.i18n >= 4.0.1',
+ 'zope.i18nmessageid',
+ 'zope.traversing',
+ ],
include_package_data=True,
zip_safe=False,
tests_require=TESTS_REQUIRE,
- test_suite='__main__.alltests',
- )
+)
diff --git a/src/zope/pagetemplate/engine.py b/src/zope/pagetemplate/engine.py
index f3687d7..cea32d7 100644
--- a/src/zope/pagetemplate/engine.py
+++ b/src/zope/pagetemplate/engine.py
@@ -33,7 +33,7 @@ try:
from zope.untrustedpython import rcompile
from zope.untrustedpython.builtins import SafeBuiltins
HAVE_UNTRUSTED = True
-except ImportError:
+except ImportError: # pragma: no cover
HAVE_UNTRUSTED = False
# PyPy doesn't support assigning to '__builtins__', even when
@@ -41,7 +41,7 @@ except ImportError:
# so don't try to use it. It won't work.
if HAVE_UNTRUSTED:
import platform
- if platform.python_implementation() == 'PyPy':
+ if platform.python_implementation() == 'PyPy': # pragma: no cover
HAVE_UNTRUSTED = False
del rcompile
del SafeBuiltins
@@ -118,10 +118,15 @@ 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
class ZopeContextBase(Context):
"""Base class for both trusted and untrusted evaluation contexts."""
+ request = None
+
def translate(self, msgid, domain=None, mapping=None, default=None):
return translate(msgid, domain, mapping,
context=self.request, default=default)
@@ -131,24 +136,24 @@ class ZopeContextBase(Context):
def evaluateCode(self, lang, code):
if not self.evaluateInlineCode:
raise InlineCodeError(
- _('Inline Code Evaluation is deactivated, which means that '
- 'you cannot have inline code snippets in your Page '
- 'Template. Activate Inline Code Evaluation and try again.'))
+ _('Inline Code Evaluation is deactivated, which means that '
+ 'you cannot have inline code snippets in your Page '
+ 'Template. Activate Inline Code Evaluation and try again.'))
# TODO This is only needed when self.evaluateInlineCode is true,
# so should only be needed for zope.app.pythonpage.
- from zope.app.interpreter.interfaces import IInterpreter
+ IInterpreter = _get_iinterpreter()
interpreter = component.queryUtility(IInterpreter, lang)
if interpreter is None:
error = _('No interpreter named "${lang_name}" was found.',
mapping={'lang_name': lang})
raise InlineCodeError(error)
- globals = self.vars.copy()
- result = interpreter.evaluateRawCode(code, globals)
+ globs = self.vars.copy()
+ result = interpreter.evaluateRawCode(code, globs)
# Add possibly new global variables.
old_names = self.vars.keys()
- for name, value in globals.items():
+ for name, value in globs.items():
if name not in old_names:
self.setGlobal(name, value)
return result
@@ -466,7 +471,7 @@ class TraversableModuleImporter(SimpleModuleImporter):
def traverse(self, name, further_path):
try:
return self[name]
- except KeyError:
+ except ImportError:
raise TraversalError(self, name)
diff --git a/src/zope/pagetemplate/pagetemplate.py b/src/zope/pagetemplate/pagetemplate.py
index b6bf8c2..9c05c89 100644
--- a/src/zope/pagetemplate/pagetemplate.py
+++ b/src/zope/pagetemplate/pagetemplate.py
@@ -30,8 +30,6 @@ from zope.pagetemplate.interfaces import IPageTemplateProgram
from zope.interface import implementer
from zope.interface import provider
-from six import u as _u
-
_default_options = {}
@@ -46,7 +44,7 @@ class StringIO(list):
self.append(value)
def getvalue(self):
- return _u('').join(self)
+ return u''.join(self)
@implementer(IPageTemplateSubclassing)
@@ -87,12 +85,11 @@ class PageTemplate(object):
_v_program = None
_text = ''
+ @property
def macros(self):
self._cook_check()
return self._v_macros
- macros = property(macros)
-
def pt_edit(self, text, content_type):
if content_type:
self.content_type = str(content_type)
@@ -105,7 +102,7 @@ class PageTemplate(object):
'options': options,
'args': args,
'nothing': None,
- }
+ }
rval.update(self.pt_getEngine().getBaseNames())
return rval
@@ -145,15 +142,18 @@ class PageTemplate(object):
if check_macro_expansion:
try:
self.pt_render(namespace, source=1)
- except:
+ except Exception:
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):
+ if isinstance(text, six.binary_type) and not isinstance(string, six.binary_type):
return string.encode('utf-8')
- else:
- return string
+
+ if isinstance(text, six.text_type) and not isinstance(string, six.text_type):
+ return string.decode('utf-8')
+
+ return string
def write(self, text):
# We accept both, since the text can either come from a file (and the
@@ -252,7 +252,7 @@ class PageTemplateEngine(object):
self.program = program
def __call__(self, context, macros, **options):
- output = StringIO(_u(''))
+ output = StringIO(u'')
interpreter = TALInterpreter(
self.program, macros, context,
stream=output, **options
diff --git a/src/zope/pagetemplate/pagetemplatefile.py b/src/zope/pagetemplate/pagetemplatefile.py
index cee1c07..4cf0bf3 100644
--- a/src/zope/pagetemplate/pagetemplatefile.py
+++ b/src/zope/pagetemplate/pagetemplatefile.py
@@ -25,6 +25,8 @@ import logging
from zope.pagetemplate.pagetemplate import PageTemplate
+logger = logging.getLogger(__name__)
+
DEFAULT_ENCODING = "utf-8"
meta_pattern = re.compile(
@@ -40,10 +42,7 @@ class PageTemplateFile(PageTemplate):
"Zope wrapper for filesystem Page Template using TAL, TALES, and METAL"
_v_last_read = 0
-
- #_error_start = b'<!-- Page Template Diagnostics'
- #_error_end = b'-->'
- #_newline = b'\n'
+ _v_debug = __debug__
def __init__(self, filename, _prefix=None):
path = self.get_path_from_prefix(_prefix)
@@ -75,21 +74,18 @@ class PageTemplateFile(PageTemplate):
def _read_file(self):
__traceback_info__ = self.filename
- f = open(self.filename, "rb")
- try:
+ with open(self.filename, "rb") as f:
text = f.read(XML_PREFIX_MAX_LENGTH)
- except:
- f.close()
- raise
- type_ = sniff_type(text)
- text += f.read()
+ type_ = sniff_type(text)
+ text += f.read()
+
if type_ != "text/xml":
text, type_ = self._prepare_html(text)
- f.close()
+
return text, type_
def _cook_check(self):
- if self._v_last_read and not __debug__:
+ if self._v_last_read and not self._v_debug:
return
__traceback_info__ = self.filename
try:
@@ -102,8 +98,8 @@ class PageTemplateFile(PageTemplate):
self.pt_edit(text, type_)
assert self._v_cooked
if self._v_errors:
- logging.error('PageTemplateFile: Error in template %s: %s',
- self.filename, '\n'.join(self._v_errors))
+ logger.error('PageTemplateFile: Error in template %s: %s',
+ self.filename, '\n'.join(self._v_errors))
return
self._v_last_read = mtime
diff --git a/src/zope/pagetemplate/tests/batch.py b/src/zope/pagetemplate/tests/batch.py
index 45f3ad9..5d193bd 100644
--- a/src/zope/pagetemplate/tests/batch.py
+++ b/src/zope/pagetemplate/tests/batch.py
@@ -20,97 +20,52 @@ class batch(object):
def __init__(self, sequence, size, start=0, end=0,
orphan=3, overlap=0):
- start=start+1
+ start = start + 1
- start,end,sz=opt(start,end,size,orphan,sequence)
+ start, end, sz = opt(start, end, size, orphan, sequence)
- self._last=end-1
- self._first=start-1
+ self._last = end - 1
+ self._first = start - 1
- self._sequence=sequence
- self._size=size
- self._start=start
- self._end=end
- self._orphan=orphan
- self._overlap=overlap
+ self._sequence = sequence
+ self._size = size
+ self._start = start
+ self._end = end
+ self._orphan = orphan
+ self._overlap = overlap
- def previous_sequence(self): return self._first
-
- def previous_sequence_end_number(self):
- start,end,spam=opt(0, self._start-1+self._overlap,
- self._size, self._orphan, self._sequence)
- return end
-
- def previous_sequence_start_number(self):
- start,end,spam=opt(0, self._start-1+self._overlap,
- self._size, self._orphan, self._sequence)
- return start
-
- def previous_sequence_end_item(self):
- start,end,spam=opt(0, self._start-1+self._overlap,
- self._size, self._orphan, self._sequence)
- return self._sequence[end-1]
-
- def previous_sequence_start_item(self):
- start,end,spam=opt(0, self._start-1+self._overlap,
- self._size, self._orphan, self._sequence)
- return self._sequence[start-1]
-
- def next_sequence_end_number(self):
- start,end,spam=opt(self._end+1-self._overlap, 0,
- self._size, self._orphan, self._sequence)
- return end
-
- def next_sequence_start_number(self):
- start,end,spam=opt(self._end+1-self._overlap, 0,
- self._size, self._orphan, self._sequence)
- return start
+ def previous_sequence(self):
+ return self._first
def next_sequence_end_item(self):
- start,end,spam=opt(self._end+1-self._overlap, 0,
- self._size, self._orphan, self._sequence)
+ _start, end, _spam = opt(self._end+1-self._overlap, 0,
+ self._size, self._orphan, self._sequence)
return self._sequence[end-1]
def next_sequence_start_item(self):
- start,end,spam=opt(self._end+1-self._overlap, 0,
- self._size, self._orphan, self._sequence)
+ start, _end, _spam = opt(self._end+1-self._overlap, 0,
+ self._size, self._orphan, self._sequence)
return self._sequence[start-1]
-
def next_sequence(self):
- try: self._sequence[self._end]
- except IndexError: return 0
- else: return 1
+ return self._end < len(self._sequence)
+ # try: self._sequence[self._end]
+ # except IndexError: return 0
+ # else: return 1
def __getitem__(self, index):
- if index > self._last: raise IndexError(index)
- return self._sequence[index+self._first]
+ if index > self._last:
+ raise IndexError(index)
+ return self._sequence[index + self._first]
-def opt(start,end,size,orphan,sequence):
- if size < 1:
- if start > 0 and end > 0 and end >= start:
- size=end+1-start
- else: size=7
+def opt(start, end, size, orphan, sequence):
+ assert size >= 1
+ assert start > 0
- if start > 0:
+ start = len(sequence) if start - 1 >= len(sequence) else start
+ assert end <= 0
+ end = start + size - 1
- try: sequence[start-1]
- except: start=len(sequence)
+ assert end + orphan - 1 < len(sequence)
- if end > 0:
- if end < start: end=start
- else:
- end=start+size-1
- try: sequence[end+orphan-1]
- except: end=len(sequence)
- elif end > 0:
- try: sequence[end-1]
- except: end=len(sequence)
- start=end+1-size
- if start - 1 < orphan: start=1
- else:
- start=1
- end=start+size-1
- try: sequence[end+orphan-1]
- except: end=len(sequence)
- return start,end,size
+ return start, end, size
diff --git a/src/zope/pagetemplate/tests/test_basictemplate.py b/src/zope/pagetemplate/tests/test_basictemplate.py
index 430a901..f998f21 100644
--- a/src/zope/pagetemplate/tests/test_basictemplate.py
+++ b/src/zope/pagetemplate/tests/test_basictemplate.py
@@ -15,8 +15,6 @@
"""
import unittest
-from six import u as _u
-
from zope.pagetemplate.tests import util
import zope.pagetemplate.pagetemplate
import zope.component.testing
@@ -32,26 +30,25 @@ class BasicTemplateTests(unittest.TestCase):
def test_if_in_var(self):
# DTML test 1: if, in, and var:
- pass # for unittest
- """
- %(comment)[ blah %(comment)]
- <html><head><title>Test of documentation templates</title></head>
- <body>
- %(if args)[
- <dl><dt>The arguments to this test program were:<p>
- <dd>
- <ul>
- %(in args)[
- <li>Argument number %(num)d was %(arg)s
- %(in args)]
- </ul></dl><p>
- %(if args)]
- %(else args)[
- No arguments were given.<p>
- %(else args)]
- And thats da trooth.
- </body></html>
- """
+
+ # %(comment)[ blah %(comment)]
+ # <html><head><title>Test of documentation templates</title></head>
+ # <body>
+ # %(if args)[
+ # <dl><dt>The arguments to this test program were:<p>
+ # <dd>
+ # <ul>
+ # %(in args)[
+ # <li>Argument number %(num)d was %(arg)s
+ # %(in args)]
+ # </ul></dl><p>
+ # %(if args)]
+ # %(else args)[
+ # No arguments were given.<p>
+ # %(else args)]
+ # And thats da trooth.
+ # </body></html>
+
tal = util.read_input('dtml1.html')
self.t.write(tal)
@@ -88,11 +85,11 @@ class BasicTemplateTests(unittest.TestCase):
from zope.component import provideUtility
class DummyProgram(object):
- def __init__(*args):
+ def __init__(self, *args):
self.args = args
- def __call__(*args, **kwargs):
- return self.args, args, kwargs
+ def __call__(self, *args, **kwargs):
+ return self.args, (self,) + args, kwargs
class DummyEngine(object):
@staticmethod
@@ -102,19 +99,19 @@ class BasicTemplateTests(unittest.TestCase):
provideUtility(DummyEngine, IPageTemplateEngine)
self.t._cook()
- self.assertTrue(isinstance(self.t._v_program, DummyProgram))
+ self.assertIsInstance(self.t._v_program, DummyProgram)
self.assertEqual(self.t._v_macros, "macros")
# "Render" and unpack arguments passed for verification
- ((cls, source_file, text, engine, content_type),
- (program, context, macros),
- options) = \
- self.t.pt_render({})
+ ((source_file, text, _engine, content_type),
+ (program, _context, macros),
+ options) = self.t.pt_render({})
self.assertEqual(source_file, None)
self.assertEqual(text, 'foo')
self.assertEqual(content_type, 'text/html')
- self.assertTrue(isinstance(program, DummyProgram))
+ self.assertEqual(macros, 'macros')
+ self.assertIsInstance(program, DummyProgram)
self.assertEqual(options, {
'tal': True,
'showtal': False,
@@ -124,43 +121,43 @@ class BasicTemplateTests(unittest.TestCase):
def test_batches_and_formatting(self):
# DTML test 3: batches and formatting:
- pass # for unittest
- """
- <html><head><title>Test of documentation templates</title></head>
- <body>
- <!--#if args-->
- The arguments were:
- <!--#in args size=size end=end-->
- <!--#if previous-sequence-->
- (<!--#var previous-sequence-start-arg-->-
- <!--#var previous-sequence-end-arg-->)
- <!--#/if previous-sequence-->
- <!--#if sequence-start-->
- <dl>
- <!--#/if sequence-start-->
- <dt><!--#var sequence-arg-->.</dt>
- <dd>Argument <!--#var num fmt=d--> was <!--#var arg--></dd>
- <!--#if next-sequence-->
- (<!--#var next-sequence-start-arg-->-
- <!--#var next-sequence-end-arg-->)
- <!--#/if next-sequence-->
- <!--#/in args-->
- </dl>
- <!--#else args-->
- No arguments were given.<p>
- <!--#/if args-->
- And I\'m 100% sure!
- </body></html>
- """
+
+ # <html><head><title>Test of documentation templates</title></head>
+ # <body>
+ # <!--#if args-->
+ # The arguments were:
+ # <!--#in args size=size end=end-->
+ # <!--#if previous-sequence-->
+ # (<!--#var previous-sequence-start-arg-->-
+ # <!--#var previous-sequence-end-arg-->)
+ # <!--#/if previous-sequence-->
+ # <!--#if sequence-start-->
+ # <dl>
+ # <!--#/if sequence-start-->
+ # <dt><!--#var sequence-arg-->.</dt>
+ # <dd>Argument <!--#var num fmt=d--> was <!--#var arg--></dd>
+ # <!--#if next-sequence-->
+ # (<!--#var next-sequence-start-arg-->-
+ # <!--#var next-sequence-end-arg-->)
+ # <!--#/if next-sequence-->
+ # <!--#/in args-->
+ # </dl>
+ # <!--#else args-->
+ # No arguments were given.<p>
+ # <!--#/if args-->
+ # And I\'m 100% sure!
+ # </body></html>
+
tal = util.read_input('dtml3.html')
self.t.write(tal)
- aa = util.argv(('one', 'two', 'three', 'four', 'five',
- 'six', 'seven', 'eight', 'nine', 'ten',
- 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen',
- 'sixteen', 'seventeen', 'eighteen', 'nineteen',
- 'twenty',
- ))
+ aa = util.argv((
+ 'one', 'two', 'three', 'four', 'five',
+ 'six', 'seven', 'eight', 'nine', 'ten',
+ 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen',
+ 'sixteen', 'seventeen', 'eighteen', 'nineteen',
+ 'twenty',
+ ))
from zope.pagetemplate.tests import batch
o = self.t(content=aa, batch=batch.batch(aa.args, 5))
@@ -206,7 +203,7 @@ class BasicTemplateTests(unittest.TestCase):
self.t()
def test_unicode_html(self):
- text = _u('<p>\xe4\xf6\xfc\xdf</p>')
+ text = u'<p>\xe4\xf6\xfc\xdf</p>'
# test with HTML parser
self.t.pt_edit(text, 'text/html')
@@ -216,8 +213,64 @@ class BasicTemplateTests(unittest.TestCase):
self.t.pt_edit(text, 'text/xml')
self.assertEqual(self.t().strip(), text)
-def test_suite():
- return unittest.makeSuite(BasicTemplateTests)
+ def test_edit_with_read(self):
+ from io import BytesIO
+ self.t.pt_edit(BytesIO(b"<html/>"), None)
+ self.assertEqual(self.t._text, b'<html/>')
+
+ def test_errors(self):
+ self.t._v_cooked = True
+ self.t._v_errors = 1
+ e = self.t.pt_errors(None)
+ self.assertEqual(e, 1)
+
+ self.t._v_errors = ()
+ e = self.t.pt_errors(None)
+ self.assertEqual(e[0], 'Macro expansion failed')
+
+ def test_convert(self):
+ string = u'binary'
+ text = b'binary'
+ 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.assertEqual(self.t._text, '')
+
+ def test_read_no_expand(self):
+ self.t.expand = False
+ self.t._text = self
+ self.t._v_cooked = True
+
+ self.assertIs(self.t.read(), self)
+
+ def test_read_error_expand(self):
+ self.t.expand = True
+ self.t._text = ''
+ self.t._v_cooked = True
+ text = self.t.read()
+ self.assertIn(self.t._error_start, text)
+ self.assertIn("Macro expansion failed", text)
+
+ def test_macros(self):
+ self.assertEqual(self.t.macros, {})
+
+
+class TestPageTemplateTracebackSupplement(unittest.TestCase):
+
+ def test_errors_old_style(self):
+ class PT(object):
+ def pt_errors(self, ns):
+ return (ns,)
+
+ pts = zope.pagetemplate.pagetemplate.PageTemplateTracebackSupplement(PT(), 'ns')
+
+ self.assertEqual(pts.warnings, ['ns'])
+
+ def test_errors_none(self):
+ class PT(object):
+ def pt_errors(self, ns, check_macro_expansion=False):
+ return None
-if __name__ == '__main__':
- unittest.TextTestRunner().run(test_suite())
+ 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 ab3b5ca..ab61408 100644
--- a/src/zope/pagetemplate/tests/test_engine.py
+++ b/src/zope/pagetemplate/tests/test_engine.py
@@ -18,34 +18,29 @@ import re
import unittest
import zope.pagetemplate.engine
from zope.testing.renormalizing import RENormalizing
+from zope.component.testing import PlacelessSetup
+class EngineTests(PlacelessSetup,
+ unittest.TestCase):
-class DummyNamespace(object):
-
- def __init__(self, context):
- self.context = context
-
-class EngineTests(unittest.TestCase):
-
- def setUp(self):
- from zope.component.testing import setUp
- setUp()
-
- def tearDown(self):
- from zope.component.testing import tearDown
- tearDown()
+ def _makeOne(self):
+ return zope.pagetemplate.engine._Engine()
def test_function_namespaces_return_secured_proxies(self):
# See https://bugs.launchpad.net/zope3/+bug/98323
- from zope.component import provideAdapter
- from zope.traversing.interfaces import IPathAdapter
- from zope.pagetemplate.engine import _Engine
from zope.proxy import isProxy
- provideAdapter(DummyNamespace, (None,), IPathAdapter, name='test')
- engine = _Engine()
+ engine = self._makeOne()
namespace = engine.getFunctionNamespace('test')
self.assertTrue(isProxy(namespace))
+ def test_getContext_namespace(self):
+ engine = self._makeOne()
+ ctx = engine.getContext({'a': 1}, b=2, request=3, context=4)
+ self.assertEqual(ctx.getValue('a'), 1)
+ self.assertEqual(ctx.getValue('b'), 2)
+ self.assertEqual(ctx.getValue('request'), 3)
+ self.assertEqual(ctx.getValue('context'), 4)
+
class DummyEngine(object):
def getTypes(self):
@@ -71,6 +66,8 @@ class ZopePythonExprTests(unittest.TestCase):
DummyEngine())
self.assertEqual(expr(DummyContext()), 'sys')
+ @unittest.skipUnless(zope.pagetemplate.engine.HAVE_UNTRUSTED,
+ "Needs untrusted")
def test_forbidden_module_name(self):
from zope.pagetemplate.engine import ZopePythonExpr
from zope.security.interfaces import Forbidden
@@ -78,12 +75,110 @@ class ZopePythonExprTests(unittest.TestCase):
DummyEngine())
self.assertRaises(Forbidden, expr, DummyContext())
+ @unittest.skipUnless(zope.pagetemplate.engine.HAVE_UNTRUSTED,
+ "Needs untrusted")
def test_disallowed_builtin(self):
from zope.pagetemplate.engine import ZopePythonExpr
expr = ZopePythonExpr('python', 'open("x", "w")', DummyEngine())
self.assertRaises(NameError, expr, DummyContext())
+class TestZopeContext(PlacelessSetup,
+ unittest.TestCase):
+
+ def _makeOne(self):
+ return zope.pagetemplate.engine.ZopeContext(None, {})
+
+ def test_translate(self):
+ ctx = self._makeOne()
+ self.assertEqual(ctx.translate('msgid'), 'msgid')
+
+ def test_evaluate_error(self):
+ ctx = self._makeOne()
+ with self.assertRaisesRegexp(zope.pagetemplate.engine.InlineCodeError,
+ "Inline Code Evaluation is deactivated"):
+ ctx.evaluateCode('lang', 'code')
+
+ def test_evaluate_interpreter_not_importable(self):
+ ctx = self._makeOne()
+ ctx.evaluateInlineCode = True
+ with self.assertRaises(ImportError):
+ ctx.evaluateCode('lang', 'code')
+
+ 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
+
+ ctx = self._makeOne()
+ ctx.evaluateInlineCode = True
+ zope.pagetemplate.engine._get_iinterpreter = mock_get
+ try:
+ with self.assertRaisesRegexp(zope.pagetemplate.engine.InlineCodeError,
+ "No interpreter named"):
+ ctx.evaluateCode('lang', 'code')
+ finally:
+ zope.pagetemplate.engine._get_iinterpreter = get
+
+ def test_evaluate_interpreter_found(self):
+ get = zope.pagetemplate.engine._get_iinterpreter
+ from zope import interface
+ from zope import component
+ class IInterpreter(interface.Interface):
+ pass
+ def mock_get():
+ return IInterpreter
+
+ @interface.implementer(IInterpreter)
+ class Interpreter(object):
+ def evaluateRawCode(self, code, globs):
+ globs['new'] = code
+ return 42
+
+ component.provideUtility(Interpreter(), name='lang')
+
+ ctx = self._makeOne()
+ ctx.evaluateInlineCode = True
+ zope.pagetemplate.engine._get_iinterpreter = mock_get
+ try:
+ result = ctx.evaluateCode('lang', 'code')
+ finally:
+ zope.pagetemplate.engine._get_iinterpreter = get
+
+ self.assertEqual(result, 42)
+ self.assertEqual('code', ctx.getValue('new'))
+
+
+class TestTraversableModuleImporter(unittest.TestCase):
+
+ def test_traverse_fails(self):
+ from zope.traversing.interfaces import TraversalError
+
+ tmi = zope.pagetemplate.engine.TraversableModuleImporter()
+ with self.assertRaises(TraversalError):
+ tmi.traverse('zope.cannot exist', ())
+
+ with self.assertRaises(TraversalError):
+ tmi.traverse('zope.pagetemplate.engine.DNE', ())
+
+
+ with self.assertRaises(TraversalError):
+ tmi.traverse('pickle.no_sub_module', ())
+
+
+class TestAppPT(unittest.TestCase):
+
+ def test_apppt_engine(self):
+ self.assertIs(zope.pagetemplate.engine.AppPT().pt_getEngine(),
+ zope.pagetemplate.engine.Engine)
+
+ def test_trustedapppt_engine(self):
+ self.assertIs(zope.pagetemplate.engine.TrustedAppPT().pt_getEngine(),
+ zope.pagetemplate.engine.TrustedEngine)
+
def test_suite():
@@ -96,15 +191,12 @@ def test_suite():
(re.compile(r"<class 'list'>"), "<type 'list'>"),
# PyPy/pure-Python implementation
(re.compile(r"<class 'zope.security.proxy.ProxyPy'>"),
- "<type 'zope.security._proxy._Proxy'>"),
+ "<type 'zope.security._proxy._Proxy'>"),
])
- suite = unittest.TestSuite()
+ suite = unittest.defaultTestLoader.loadTestsFromName(__name__)
suite.addTest(doctest.DocTestSuite('zope.pagetemplate.engine',
checker=checker))
- suite.addTest(unittest.makeSuite(EngineTests))
- if zope.pagetemplate.engine.HAVE_UNTRUSTED:
- suite.addTest(unittest.makeSuite(ZopePythonExprTests))
return suite
diff --git a/src/zope/pagetemplate/tests/test_htmltests.py b/src/zope/pagetemplate/tests/test_htmltests.py
index c6abd81..1550634 100644
--- a/src/zope/pagetemplate/tests/test_htmltests.py
+++ b/src/zope/pagetemplate/tests/test_htmltests.py
@@ -31,15 +31,17 @@ class HTMLTests(unittest.TestCase):
def getProducts(self):
return [
- {'description': 'This is the tee for those who LOVE Zope. '
- 'Show your heart on your tee.',
- 'price': 12.99, 'image': 'smlatee.jpg'
+ {
+ 'description': ('This is the tee for those who LOVE Zope. '
+ 'Show your heart on your tee.'),
+ 'price': 12.99, 'image': 'smlatee.jpg'
},
- {'description': 'This is the tee for Jim Fulton. '
- 'He\'s the Zope Pope!',
- 'price': 11.99, 'image': 'smpztee.jpg'
+ {
+ 'description': ('This is the tee for Jim Fulton. '
+ 'He\'s the Zope Pope!'),
+ 'price': 11.99, 'image': 'smpztee.jpg'
},
- ]
+ ]
def test_1(self):
laf = self.folder.laf
@@ -53,7 +55,7 @@ class HTMLTests(unittest.TestCase):
t = self.folder.t
t.write(util.read_input('teeshop2.html'))
expect = util.read_output('teeshop2.html')
- out = t(laf = self.folder.laf, getProducts = self.getProducts)
+ out = t(laf=self.folder.laf, getProducts=self.getProducts)
util.check_html(expect, out)
@@ -63,7 +65,7 @@ class HTMLTests(unittest.TestCase):
t = self.folder.t
t.write(util.read_input('teeshop1.html'))
expect = util.read_output('teeshop1.html')
- out = t(laf = self.folder.laf, getProducts = self.getProducts)
+ out = t(laf=self.folder.laf, getProducts=self.getProducts)
util.check_html(expect, out)
def test_SimpleLoop(self):
@@ -152,7 +154,4 @@ class HTMLTests(unittest.TestCase):
self.assertFalse(errors)
def test_suite():
- return unittest.makeSuite(HTMLTests)
-
-if __name__=='__main__':
- unittest.TextTestRunner().run(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 d6ecbcd..e5cc2e9 100644
--- a/src/zope/pagetemplate/tests/test_ptfile.py
+++ b/src/zope/pagetemplate/tests/test_ptfile.py
@@ -20,23 +20,19 @@ import unittest
import six
from zope.pagetemplate.pagetemplatefile import PageTemplateFile
+class AbstractPTCase(object):
-class TypeSniffingTestCase(unittest.TestCase):
-
- TEMPFILENAME = tempfile.mktemp()
-
- def tearDown(self):
- if os.path.exists(self.TEMPFILENAME):
- os.unlink(self.TEMPFILENAME)
-
- def get_pt(self, text):
- f = open(self.TEMPFILENAME, "wb")
- f.write(text)
- f.close()
- pt = PageTemplateFile(self.TEMPFILENAME)
+ def get_pt(self, text=b'<html />'):
+ with tempfile.NamedTemporaryFile(mode='wb', delete=False) as f:
+ f.write(text)
+ self.addCleanup(os.unlink, f.name)
+ pt = PageTemplateFile(f.name)
pt.read()
return pt
+class TypeSniffingTestCase(AbstractPTCase,
+ unittest.TestCase):
+
def check_content_type(self, text, expected_type):
pt = self.get_pt(text)
self.assertEqual(pt.content_type, expected_type)
@@ -123,17 +119,18 @@ class TypeSniffingTestCase(unittest.TestCase):
def test_sniffer_html_ascii(self):
self.check_content_type(
("<!DOCTYPE html [ SYSTEM '%s' ]><html></html>"
- % self.HTML_SYSTEM_ID).encode("utf-8"),
+ % self.HTML_SYSTEM_ID).encode("utf-8"),
"text/html")
self.check_content_type(
b"<html><head><title>sample document</title></head></html>",
"text/html")
- # TODO: This reflects a case that simply isn't handled by the
- # sniffer; there are many, but it gets it right more often than
- # before.
- def donttest_sniffer_xml_simple(self):
- self.check_content_type("<doc><element/></doc>",
+ @unittest.expectedFailure
+ def test_sniffer_xml_simple(self):
+ # TODO: This reflects a case that simply isn't handled by the
+ # sniffer; there are many, but it gets it right more often than
+ # before. This case actually returns text/html
+ self.check_content_type(b"<doc><element/></doc>",
"text/xml")
def test_html_default_encoding(self):
@@ -145,9 +142,9 @@ class TypeSniffingTestCase(unittest.TestCase):
rendered = pt()
self.assertTrue(isinstance(rendered, six.text_type))
self.assertEqual(rendered.strip(),
- six.u("<html><head><title>"
- "\u0422\u0435\u0441\u0442"
- "</title></head></html>"))
+ (u"<html><head><title>"
+ u"\u0422\u0435\u0441\u0442"
+ u"</title></head></html>"))
def test_html_encoding_by_meta(self):
pt = self.get_pt(
@@ -160,9 +157,9 @@ class TypeSniffingTestCase(unittest.TestCase):
rendered = pt()
self.assertTrue(isinstance(rendered, six.text_type))
self.assertEqual(rendered.strip(),
- six.u("<html><head><title>"
- "\u0422\u0435\u0441\u0442"
- "</title></head></html>"))
+ (u"<html><head><title>"
+ u"\u0422\u0435\u0441\u0442"
+ u"</title></head></html>"))
def test_xhtml(self):
pt = self.get_pt(
@@ -175,14 +172,51 @@ class TypeSniffingTestCase(unittest.TestCase):
rendered = pt()
self.assertTrue(isinstance(rendered, six.text_type))
self.assertEqual(rendered.strip(),
- six.u("<html><head><title>"
- "\u0422\u0435\u0441\u0442"
- "</title></head></html>"))
+ (u"<html><head><title>"
+ u"\u0422\u0435\u0441\u0442"
+ u"</title></head></html>"))
+
+
+class TestPageTemplateFile(AbstractPTCase,
+ unittest.TestCase):
+
+ def test_no_such_file(self):
+ with self.assertRaises(ValueError):
+ PageTemplateFile('this file does not exist')
+
+ def test_prefix_str(self):
+ pt = PageTemplateFile(os.path.basename(__file__),
+ _prefix=os.path.dirname(__file__))
+ self.assertEqual(pt.filename, __file__)
+
+
+ def test_cook_no_debug(self):
+ pt = self.get_pt()
+ pt._v_debug = False
+ pt._cook_check()
+ self.assertTrue(pt._v_last_read)
+ lr = pt._v_last_read
+ 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
+ try:
+ pt._cook_check()
+ finally:
+ os.path.getmtime = getmtime
+ self.assertEqual(0, pt._v_last_read)
-def test_suite():
- return unittest.makeSuite(TypeSniffingTestCase)
+ def test_pickle_not_allowed(self):
+ import pickle
+ pt = self.get_pt()
-if __name__ == "__main__":
- unittest.main(defaultTest="test_suite")
+ with self.assertRaises(TypeError):
+ pickle.dumps(pt)
diff --git a/src/zope/pagetemplate/tests/util.py b/src/zope/pagetemplate/tests/util.py
index 8dda99b..5ef2ad3 100644
--- a/src/zope/pagetemplate/tests/util.py
+++ b/src/zope/pagetemplate/tests/util.py
@@ -17,71 +17,46 @@ from __future__ import print_function
import os
import re
import sys
-
-
-class Bruce(object):
- __allow_access_to_unprotected_subobjects__=1
- def __str__(self): return 'bruce'
- def __int__(self): return 42
- def __float__(self): return 42.0
- def keys(self): return ['bruce']*7
- def values(self): return [self]*7
- def items(self): return [('bruce',self)]*7
- def __len__(self): return 7
- def __getitem__(self,index):
- if isinstance(index, int) and (index < 0 or index > 6):
- raise IndexError(index)
- return self
- isDocTemp = 0
- def __getattr__(self,name):
- if name.startswith('_'):
- raise AttributeError(name)
- return self
-
-bruce = Bruce()
+import unittest
+import zope.pagetemplate.tests
class arg(object):
__allow_access_to_unprotected_subobjects__ = 1
- def __init__(self,nn,aa): self.num, self.arg = nn, aa
- def __str__(self): return str(self.arg)
+
+ def __init__(self, nn, aa):
+ self.num, self.arg = nn, aa
+
+ def __str__(self):
+ return str(self.arg)
class argv(object):
__allow_access_to_unprotected_subobjects__ = 1
- def __init__(self, argv=sys.argv[1:]):
+ def __init__(self, argv=None):
args = self.args = []
+ argv = argv if argv is not None else sys.argv[1:]
for aa in argv:
- args.append(arg(len(args)+1,aa))
-
- def items(self):
- return map(lambda a: ('spam%d' % a.num, a), self.args)
-
- def values(self): return self.args
-
- def getRoot(self):
- return self
+ args.append(arg(len(args) + 1, aa))
context = property(lambda self: self)
-def nicerange(lo, hi):
- if hi <= lo+1:
- return str(lo+1)
- else:
- return "%d,%d" % (lo+1, hi)
+class _Test(unittest.TestCase):
+
+ def runTest(self): # pragma: no cover 2.7 compatibility
+ return
-def dump(tag, x, lo, hi):
- for i in xrange(lo, hi):
- print('%s %s' % (tag, x[i]), end=' ')
+_assertEqual = _Test().assertEqual
+del _Test
def check_html(s1, s2):
s1 = normalize_html(s1)
s2 = normalize_html(s2)
- assert s1==s2, (s1, s2, "HTML Output Changed")
+ _assertEqual(s1, s2, "HTML Output Changed")
def check_xml(s1, s2):
s1 = normalize_xml(s1)
s2 = normalize_xml(s2)
- assert s1==s2, ("XML Output Changed:\n%r\n\n%r" % (s1, s2))
+ _assertEqual(s1, s2, 'XML Output Changed')
def normalize_html(s):
s = re.sub(r"[ \t]+", " ", s)
@@ -95,11 +70,11 @@ def normalize_xml(s):
return s
-import zope.pagetemplate.tests
-dir = os.path.dirname(zope.pagetemplate.tests.__file__)
-input_dir = os.path.join(dir, 'input')
-output_dir = os.path.join(dir, 'output')
+
+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)
diff --git a/tox.ini b/tox.ini
index 85dbde1..90869b2 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,26 +1,20 @@
[tox]
envlist =
- py27,py33,py34,py35,pypy,pypy3
+ py27,py34,py35,py36,pypy,pypy3,coverage
[testenv]
-deps =
- zope.pagetemplate[test]
- zope.component
- zope.i18n
- zope.i18nmessageid
- zope.interface
- zope.proxy
- zope.security
- zope.tal
- zope.tales
- zope.testing
- zope.testrunner
- zope.traversing
commands =
- python setup.py -q test -q
+ zope-testrunner --test-path=src []
+deps =
+ .[test]
-[testenv:py27]
+[testenv:coverage]
+usedevelop = true
+basepython =
+ python2.7
+commands =
+ coverage run -m zope.testrunner --test-path=src []
+ coverage report --fail-under=100
deps =
{[testenv]deps}
- zope.untrustedpython
- RestrictedPython
+ coverage