diff --git a/pyscript/README.txt b/pyscript/README.txt index ca4daa5..b9d2a5a 100644 --- a/pyscript/README.txt +++ b/pyscript/README.txt @@ -1,29 +1,92 @@ -Python Page -=========== +============ +Python Pages +============ -Python Page provides the user with a content object that interprets -Python in content space. To save typing and useless messing with -output, any free-standing string and print statement are considered -for output; see the example below. +Persistent Python Page - Content Type +Examples: -Example -------- + >>> from cybertools.pyscript.tests import Root + >>> from cybertools.pyscript.script import PythonPage -Create a new content type called "Python Page" and enter the following -code example:: + >>> pp = PythonPage() + >>> pp.__parent__ = Root() + >>> pp.__name__ = 'pp' + >>> request = None - ''' - - - - - - ''' +A simple test that checks that any lone-standing triple-quotes are +being printed. + + >>> pp.setSource(u"'''...'''\nreturn printed") + >>> pp(request) + '...\n' + +Make sure that strings with prefixes work. + + >>> pp.setSource(ur"ur'''test\r'''" + "\nreturn printed") + >>> pp(request) + 'test\\r\n' + +Make sure that Windows (\r\n) line ends also work. + + >>> pp.setSource(u"if 1 == 1:\r\n\r\n '''...'''\nreturn printed") + >>> pp(request) + '...\n' + +Make sure that unicode strings work as expected. + + >>> #pp.setSource(u"u'''\u0442\u0435\u0441\u0442'''") + >>> #pp(request) + +u'\u0442\u0435\u0441\u0442\n' + +Make sure that multi-line strings work. + + >>> pp.setSource(u"u'''test\ntest\ntest'''\nreturn printed") + >>> pp(request) + 'test\n...test\n...test\n' + +Here you can see a simple Python command... + + >>> pp.setSource(u"print u'...'\nreturn printed") + >>> pp(request) + '...\n' + +... and here a triple quote with some variable replacement. + + >>> pp.setSource(u"'''%s''' %x\nreturn printed") + >>> pp(request, x='test') + 'test\n' + +Make sure that the context of the page is available. + + >>> pp.setSource(u"'''%s''' %context.__name__\nreturn printed") + >>> pp(request) + 'root\n' + +Make sure that faulty syntax is interpreted correctly. + +Note: We cannot just print the error directly, since there is a +'bug' in the Linux version of Python that does not display the filename +of the source correctly. So we construct an information string by hand. + + >>> def print_err(err): + ... print ('%(msg)s, %(filename)s, line %(lineno)i, offset %(offset)i' + ... % err.__dict__) + ... + >>> try: + ... pp.setSource(u"'''...") #'''" + ... except SyntaxError, err: + ... print_err(err) + EOF while scanning triple-quoted string, /pp, line 4, offset 47 + + >>> try: + ... pp.setSource(u"prin 'hello'") + ... except SyntaxError, err: + ... print_err(err) + invalid syntax, /pp, line 3, offset 16 diff --git a/pyscript/interfaces.py b/pyscript/interfaces.py index 0f11a0c..dfaf904 100644 --- a/pyscript/interfaces.py +++ b/pyscript/interfaces.py @@ -24,6 +24,7 @@ $Id$ from zope.interface import Interface from zope import schema +from zope.app.i18n import ZopeMessageFactory as _ class IPythonPage(Interface): diff --git a/pyscript/script.py b/pyscript/script.py index 7af5bd5..61b26d2 100644 --- a/pyscript/script.py +++ b/pyscript/script.py @@ -96,8 +96,7 @@ class PythonPage(Contained, Persistent): self.__filename()) kw['request'] = request kw['script'] = self - kw['untrusted_output'] = output - kw['printed'] = output + kw['untrusted_output'] = kw['printed'] = output kw['context'] = getParent(self) kw['script_result'] = None self._v_compiled(kw) @@ -113,12 +112,12 @@ class Function(object): def __init__(self, source, filename=''): lines = [] - lines.insert(0, 'def dummy():') + lines.insert(0, 'def dummy(): \n pass') for line in source.splitlines(): lines.append(' ' + line) lines.append('script_result = dummy()') source = '\n'.join(lines) - print source + #print source self.code = compile(source, filename, 'exec') def __call__(self, globals): diff --git a/pyscript/tests.py b/pyscript/tests.py index bd4495b..deda160 100644 --- a/pyscript/tests.py +++ b/pyscript/tests.py @@ -15,31 +15,28 @@ $Id$ """ -import unittest +import unittest, doctest import zope.component from zope.interface import implements -from zope.testing.doctestunit import DocTestSuite +from zope.location.traversing import LocationPhysicallyLocatable +from zope.testing.doctestunit import DocFileSuite from zope.traversing.interfaces import IContainmentRoot from zope.traversing.interfaces import IPhysicallyLocatable from zope.traversing.adapters import RootPhysicallyLocatable -from zope.location.traversing import LocationPhysicallyLocatable - from zope.app.container.contained import Contained -#from zope.app.interpreter.interfaces import IInterpreter -#from zope.app.interpreter.python import PythonInterpreter from zope.app.testing import placelesssetup, ztapi + class Root(Contained): implements(IContainmentRoot) __parent__ = None __name__ = 'root' + def setUp(test): placelesssetup.setUp() - sm = zope.component.getGlobalSiteManager() - #sm.registerUtility(PythonInterpreter, IInterpreter, 'text/server-python') ztapi.provideAdapter(None, IPhysicallyLocatable, LocationPhysicallyLocatable) @@ -47,10 +44,10 @@ def setUp(test): RootPhysicallyLocatable) - def test_suite(): + flags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS return unittest.TestSuite(( - DocTestSuite('cybertools.pyscript', + DocFileSuite('README.txt', optionflags=flags, setUp=setUp, tearDown=placelesssetup.tearDown), ))