[Zope3-checkins] CVS: Zope3/src/zope/app/pythonpage -
MAINTAINER.txt:1.2 README.txt:1.2 __init__.py:1.2
browser.py:1.2 configure.zcml:1.2 edit.pt:1.2 tests.py:1.2
version.txt:1.2
Philipp von Weitershausen
philikon at philikon.de
Tue Feb 24 11:50:29 EST 2004
Update of /cvs-repository/Zope3/src/zope/app/pythonpage
In directory cvs.zope.org:/tmp/cvs-serv27021/src/zope/app/pythonpage
Added Files:
MAINTAINER.txt README.txt __init__.py browser.py
configure.zcml edit.pt tests.py version.txt
Log Message:
Moved the pythonpage package from zope.products to zope.app. Nothing
else has changed except for the imports.
=== Zope3/src/zope/app/pythonpage/MAINTAINER.txt 1.1 => 1.2 ===
--- /dev/null Tue Feb 24 11:50:29 2004
+++ Zope3/src/zope/app/pythonpage/MAINTAINER.txt Tue Feb 24 11:50:28 2004
@@ -0,0 +1,5 @@
+Stephan Richter
+
+ Email: stephan.richter at tufts.edu
+
+ IRC nick: srichter
\ No newline at end of file
=== Zope3/src/zope/app/pythonpage/README.txt 1.1 => 1.2 ===
--- /dev/null Tue Feb 24 11:50:29 2004
+++ Zope3/src/zope/app/pythonpage/README.txt Tue Feb 24 11:50:28 2004
@@ -0,0 +1,29 @@
+Python Page
+===========
+
+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.
+
+
+Example
+-------
+
+Create a new content type called "Python Page" and enter the following
+code example::
+
+ '''
+ <html>
+ <body>
+ <ul>
+ '''
+
+ import time
+ print time.asctime()
+
+ '''
+ </ul>
+ </body>
+ </html>
+ '''
=== Zope3/src/zope/app/pythonpage/__init__.py 1.1 => 1.2 ===
--- /dev/null Tue Feb 24 11:50:29 2004
+++ Zope3/src/zope/app/pythonpage/__init__.py Tue Feb 24 11:50:28 2004
@@ -0,0 +1,182 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""Python Page
+
+$Id$
+"""
+import re
+from persistent import Persistent
+from zope.app import zapi
+from zope.app.container.contained import Contained
+from zope.interface import Interface, implements
+from zope.schema import SourceText, TextLine
+from zope.app.i18n import ZopeMessageIDFactory as _
+
+triple_quotes_start = re.compile('^[ \t]*("""|\'\'\')', re.MULTILINE)
+single_triple_quotes_end = re.compile("'''")
+double_triple_quotes_end = re.compile('"""')
+
+class IPythonPage(Interface):
+ """Python Page
+
+ The Python Page acts as a simple content type that allows you to execute
+ Python in content space. Additionally, if you have a free-standing
+ triple-quoted string, it gets converted to a print statement
+ automatically.
+ """
+
+ source = SourceText(
+ title=_("Source"),
+ description=_("The source of the Python page."),
+ required=False)
+
+ contentType = TextLine(
+ title=_("Content Type"),
+ description=_("The content type the script outputs."),
+ required=True,
+ default=u"text/html")
+
+ def __call__(request, **kw):
+ """Execute the script.
+
+ The script will insert the 'request' and all '**kw' as global
+ variables. Furthermore, the variables 'script' and 'context' (which is
+ the container of the script) will be added.
+ """
+
+
+class PythonPage(Contained, Persistent):
+ r"""Persistent Python Page - Content Type
+
+ Examples::
+
+ >>> from tests import setUp, tearDown, Root
+ >>> setUp()
+
+ >>> pp = PythonPage()
+ >>> pp.__parent__ = Root()
+ >>> pp.__name__ = 'pp'
+ >>> request = None
+
+ >>> pp.setSource(u"'''<html>...</html>'''")
+ >>> pp(request)
+ u'<html>...</html>\n'
+
+ >>> pp.setSource(u"if 1 == 1:\n '''<html>...</html>'''")
+ >>> pp(request)
+ u'<html>...</html>\n'
+
+ >>> pp.setSource(u"print u'<html>...</html>'")
+ >>> pp(request)
+ u'<html>...</html>\n'
+
+ >>> pp.setSource(u"'''<html>%s</html>''' %x")
+ >>> pp(request, x='test')
+ u'<html>test</html>\n'
+
+ >>> pp.setSource(u"'''<html>%s</html>''' %context.__name__")
+ >>> pp(request)
+ u'<html>root</html>\n'
+
+ >>> try:
+ ... pp.setSource(u"'''<html>...</html>") #'''"
+ ... except SyntaxError, err:
+ ... print err
+ No matching closing quotes found. (line 1)
+
+ >>> try:
+ ... pp.setSource(u"prin 'hello'")
+ ... except SyntaxError, err:
+ ... print err
+ invalid syntax (pp, line 1)
+
+ >>> tearDown()
+ """
+
+ implements(IPythonPage)
+
+ def __init__(self, source=u'', contentType=u'text/html'):
+ """Initialize the object."""
+ super(PythonPage, self).__init__()
+ self.source = source
+ self.contentType = contentType
+
+ def __filename(self):
+ if self.__parent__ is None:
+ filename = 'N/A'
+ else:
+ filename = zapi.getPath(self)
+ return filename
+
+ def setSource(self, source):
+ r"""Set the source of the page and compile it.
+
+ This method can raise a syntax error, if the source is not valid.
+ """
+ self.__source = source
+
+ source = source.encode('utf-8')
+ start = 0
+ match = triple_quotes_start.search(source, start)
+ while match:
+ open = match.group()
+ source = source[:match.end()-3] + 'print u' + \
+ source[match.end()-3:]
+ start = match.end() + 7
+
+ # Now let's find the end of the quote
+ if match.group().endswith('"""'):
+ end = double_triple_quotes_end.search(source, start)
+ else:
+ end = single_triple_quotes_end.search(source, start)
+
+ if end is None:
+ lineno = len(source[:start].split('\n'))
+ offset = len(match.group())
+ raise SyntaxError(
+ 'No matching closing quotes found.',
+ (self.__filename(), lineno, offset, match.group()))
+
+ start = end.end()
+ match = triple_quotes_start.search(source, start)
+
+ self.__prepared_source = source
+
+ # Compile objects cannot be pickled
+ self._v_compiled = compile(self.__prepared_source, self.__filename(),
+ 'exec')
+
+ def getSource(self):
+ """Get the original source code."""
+ return self.__source
+
+ # See IPage
+ source = property(getSource, setSource)
+
+
+ def __call__(self, request, **kw):
+ """See IPythonPage"""
+
+ # Compile objects cannot be pickled
+ if not hasattr(self, '_v_compiled'):
+ self._v_compiled = compile(self.__prepared_source,
+ self.__filename(), 'exec')
+
+ kw['request'] = request
+ kw['script'] = self
+ kw['context'] = zapi.getParent(self)
+
+ service = zapi.queryService(self, 'Interpreter')
+ interpreter = service.queryInterpreter('text/server-python')
+ return interpreter.evaluate(self._v_compiled, kw)
=== Zope3/src/zope/app/pythonpage/browser.py 1.1 => 1.2 ===
--- /dev/null Tue Feb 24 11:50:29 2004
+++ Zope3/src/zope/app/pythonpage/browser.py Tue Feb 24 11:50:28 2004
@@ -0,0 +1,46 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""Python Page Browser Views
+
+$Id$
+"""
+from zope.app.browser.form.editview import EditView
+from zope.app.i18n import ZopeMessageIDFactory as _
+
+class PythonPageEval:
+ """Evaluate the Python Page."""
+
+ def index(self, **kw):
+ """Call a Python Page"""
+
+ self.request.response.setHeader('content-type',
+ self.context.contentType)
+
+ return self.context(self.request, **kw)
+
+class PythonPageEditView(EditView):
+ """Edit View Class for Python Page."""
+
+ syntaxError = None
+
+ def update(self):
+ """Update the content with the HTML form data."""
+ try:
+ status = super(PythonPageEditView, self).update()
+ except SyntaxError, err:
+ self.syntaxError = err
+ status = _('A syntax error occured.')
+ self.update_status = status
+
+ return status
=== Zope3/src/zope/app/pythonpage/configure.zcml 1.1 => 1.2 ===
--- /dev/null Tue Feb 24 11:50:29 2004
+++ Zope3/src/zope/app/pythonpage/configure.zcml Tue Feb 24 11:50:28 2004
@@ -0,0 +1,79 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:browser="http://namespaces.zope.org/browser"
+ i18n_domain="zope">
+
+ <interface
+ interface=".IPythonPage"
+ type="zope.app.interfaces.content.IContentType"
+ />
+
+ <content class=".PythonPage">
+
+ <factory
+ id="zope.app.pythonpage.PythonPage"
+ permission="zope.ManageContent"
+ title="Python Page"
+ description="A simple, content-based Python Page"
+ />
+
+ <require
+ permission="zope.View"
+ interface=".IPythonPage"
+ />
+
+ <require
+ permission="zope.ManageContent"
+ set_attributes="source contentType"
+ />
+
+ <implements
+ interface="zope.app.interfaces.annotation.IAttributeAnnotatable" />
+
+ </content>
+
+
+ <!-- browser directives -->
+
+ <browser:page
+ name="index.html"
+ for=".IPythonPage"
+ class=".browser.PythonPageEval"
+ attribute="index"
+ permission="zope.View"
+ />
+
+ <browser:addform
+ label="Add Python Page"
+ name="AddPythonPage"
+ schema=".IPythonPage"
+ content_factory=".PythonPage"
+ permission="zope.ManageContent"
+ menu="add_content" title="Python Page"
+ />
+
+ <browser:editform
+ for=".IPythonPage"
+ schema=".IPythonPage"
+ name="edit.html"
+ label="Edit Python Page"
+ class=".browser.PythonPageEditView"
+ template="edit.pt"
+ permission="zope.ManageContent"
+ menu="zmi_views" title="Edit"
+ />
+
+
+ <!-- Preview view - requires zope.app.preview -->
+
+ <configure package="zope.app.preview">
+ <browser:page
+ for="zope.app.pythonpage.IPythonPage"
+ name="preview.html"
+ template="preview.pt"
+ permission="zope.ManageContent"
+ menu="zmi_views" title="Preview"
+ />
+ </configure>
+
+</configure>
\ No newline at end of file
=== Zope3/src/zope/app/pythonpage/edit.pt 1.1 => 1.2 ===
--- /dev/null Tue Feb 24 11:50:29 2004
+++ Zope3/src/zope/app/pythonpage/edit.pt Tue Feb 24 11:50:28 2004
@@ -0,0 +1,90 @@
+<tal:tag condition="view/update"/>
+<html metal:use-macro="views/standard_macros/page">
+ <body>
+ <div metal:fill-slot="body">
+
+ <div metal:define-macro="body">
+
+ <form action="." tal:attributes="action request/URL" method="POST"
+ enctype="multipart/form-data">
+
+ <div metal:define-macro="formbody">
+
+ <h3 tal:condition="view/label"
+ tal:content="view/label"
+ metal:define-slot="heading"
+ >Edit something</h3>
+
+ <p tal:define="status view/update"
+ tal:condition="status"
+ tal:content="status" />
+
+ <p tal:condition="view/errors" i18n:translate="">
+ There are <strong tal:content="python:len(view.errors)"
+ i18n:name="num_errors">6</strong> input errors.
+ </p>
+
+ <div class="message"
+ tal:condition="view/syntaxError"
+ tal:define="err view/syntaxError">
+ <h3 i18n:translate="">Syntax Error:
+ <span tal:content="err/msg" i18n:name="msg">invalid syntax</span>
+ </h3>
+ <div i18n:translate="">
+ File
+ "<span tal:replace="err/filename" i18n:name="filename">
+ filename
+ </span>",
+ line <span tal:replace="err/lineno" i18n:name="lineno">10</span>,
+ offset <span tal:replace="err/offset" i18n:name="offset">1</span>
+ </div>
+ <pre tal:content="python:err.text+'\n'+' '*err.offset+'^'">
+ prin "foo"
+ ^
+ </pre>
+ </div>
+
+ <div metal:define-slot="extra_info" tal:replace="nothing">
+ </div>
+
+ <div class="row"
+ metal:define-slot="extra_top" tal:replace="nothing">
+ <div class="label">Extra top</div>
+ <div class="field"><input type="text" style="width:100%" /></div>
+ </div>
+ <div class="row"
+ metal:define-macro="widget_rows" tal:repeat="widget view/widgets"
+ tal:content="structure widget/row">
+ <div class="label">Name</div>
+ <div class="field"><input type="text" style="width:100%" /></div>
+ </div>
+ <div class="separator"></div>
+ <div class="row"
+ metal:define-slot="extra_bottom" tal:replace="nothing">
+ <div class="label">Extra bottom</div>
+ <div class="field"><input type="text" style="width:100%" /></div>
+ </div>
+ <div class="separator"></div>
+ </div>
+
+ <div class="row">
+ <div class="controls">
+ <input type="submit" value="Refresh"
+ i18n:attributes="value refresh-button" />
+ <input type="submit" name="UPDATE_SUBMIT" value="Change"
+ i18n:attributes="value submit-button"/>
+ </div>
+ </div>
+ <div class="row" metal:define-slot="extra_buttons" tal:replace="nothing">
+ </div>
+
+ <div class="separator"></div>
+
+ </form>
+
+ </div>
+
+ </div>
+ </body>
+
+</html>
=== Zope3/src/zope/app/pythonpage/tests.py 1.1 => 1.2 ===
--- /dev/null Tue Feb 24 11:50:29 2004
+++ Zope3/src/zope/app/pythonpage/tests.py Tue Feb 24 11:50:28 2004
@@ -0,0 +1,64 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""Tests for Python Page
+
+$Id$
+"""
+import unittest
+from zope.app import zapi
+from zope.app.container.contained import Contained
+from zope.app.interfaces.interpreter import IInterpreter, IInterpreterService
+from zope.app.interfaces.traversing import IContainmentRoot
+from zope.app.interfaces.traversing import IPhysicallyLocatable
+from zope.app.interpreter import interpreterService
+from zope.app.interpreter.python import PythonInterpreter
+from zope.app.location import LocationPhysicallyLocatable
+from zope.app.tests import placelesssetup, ztapi
+from zope.app.traversing.adapters import RootPhysicallyLocatable
+from zope.component.servicenames import Services
+from zope.interface import implements
+from zope.testing.doctestunit import DocTestSuite
+
+
+class Root(Contained):
+ implements(IContainmentRoot)
+
+ __parent__ = None
+ __name__ = 'root'
+
+def setUp():
+ placelesssetup.setUp()
+ interpreterService.provideInterpreter('text/server-python',
+ PythonInterpreter)
+ services = zapi.getService(None, Services)
+ services.defineService('Interpreter', IInterpreterService)
+ services.provideService('Interpreter', interpreterService)
+
+ ztapi.provideAdapter(None, IPhysicallyLocatable,
+ LocationPhysicallyLocatable)
+ ztapi.provideAdapter(IContainmentRoot, IPhysicallyLocatable,
+ RootPhysicallyLocatable)
+
+
+def tearDown():
+ placelesssetup.tearDown()
+
+
+def test_suite():
+ return unittest.TestSuite((
+ DocTestSuite('zope.app.pythonpage'),
+ ))
+
+if __name__ == '__main__':
+ unittest.main()
=== Zope3/src/zope/app/pythonpage/version.txt 1.1 => 1.2 ===
--- /dev/null Tue Feb 24 11:50:29 2004
+++ Zope3/src/zope/app/pythonpage/version.txt Tue Feb 24 11:50:28 2004
@@ -0,0 +1 @@
+PythonPage 0.1
\ No newline at end of file
More information about the Zope3-Checkins
mailing list