diff options
author | Michael Howitz <mh@gocept.com> | 2021-05-28 08:06:54 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-28 08:06:54 +0200 |
commit | 285490922584c1be42b5be89c00e7c8e1d972fb8 (patch) | |
tree | 1799c5e38f037525a99d6784e6b54f9ae0e6d0b8 /src | |
parent | 7153aa0fbb108e9c74d13a2454e1602330bf9b4e (diff) | |
download | zope-pagetemplate-285490922584c1be42b5be89c00e7c8e1d972fb8.tar.gz |
Config with pure python (#28)
* Lint the code.
* Add support for Python 3.9.
Diffstat (limited to 'src')
-rw-r--r-- | src/zope/__init__.py | 2 | ||||
-rw-r--r-- | src/zope/pagetemplate/engine.py | 35 | ||||
-rw-r--r-- | src/zope/pagetemplate/interfaces.py | 22 | ||||
-rw-r--r-- | src/zope/pagetemplate/pagetemplate.py | 46 | ||||
-rw-r--r-- | src/zope/pagetemplate/pagetemplatefile.py | 6 | ||||
-rw-r--r-- | src/zope/pagetemplate/tests/batch.py | 10 | ||||
-rw-r--r-- | src/zope/pagetemplate/tests/test_basictemplate.py | 15 | ||||
-rw-r--r-- | src/zope/pagetemplate/tests/test_engine.py | 26 | ||||
-rw-r--r-- | src/zope/pagetemplate/tests/test_htmltests.py | 3 | ||||
-rw-r--r-- | src/zope/pagetemplate/tests/test_ptfile.py | 5 | ||||
-rw-r--r-- | src/zope/pagetemplate/tests/util.py | 14 |
11 files changed, 122 insertions, 62 deletions
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: |