[Zope-dev] Python-Document proof of concept code
Martijn Faassen
M.Faassen@vet.uu.nl
Tue, 15 Jun 1999 19:10:38 +0200
Hi there,
Since I hear Python scripts inside the Zope system are in their
Inception phase now, I thought I'd contribute with some ideas.
What I'm thinking about is how to emulate the DTML experience in Python.
DTML is nice in that it provides a fairly simple interface into the Zope
database, but less nice because fancy things tend to become extremely
cumbersome and complicated in DTML while they wouldn't be so horrible in
Python. Current ways to use Python tend to be even more cumbersome for
various reasons (external methods not editable from the web, products
are often overkill), however.
One other reason why Python might still remain overkill even when it's
editable from the web is the interfacing with Zope. This proof of
concept tries to emulate DTML's way to use the Zope database in Python
code. This way people won't have to learn two different systems and run
into trouble when switching back and forth from DTML and Python
documents.
The proof of concept code does *not* tie into any Zope system, it's just
an attempt to demonstrate my idea of DTML-like constructs in Python.
There are various caveats, such as the HTML that's produced currently
being all rendered to one line. That can be solved by adding \n in
places, but perhaps there's a nicer way still.
Enjoy reading the code. :)
Regards,
Martijn
---- The actual code ----
# Just a proof of concept only! Not based on any actual Zope code, just
# tries to imitate it vaguely. :)
from array import array
class Error(Exception):
"""Simplistic error.
"""
pass
class PyDocument:
"""A PyDocument is like a DTML document, but in reverse. Program
logic
with embedded HTML, instead of the other way around.
The idea is not to replace current DTML documents, which work fine
as
a reporting language, but to provide a starting place for Python
Script Documents in Zope.
"""
def var(self, name):
"""Like var tag, name attribute only. No expr attribute
supported.
"""
obj = self.namespace.get(name, None)
if obj != None:
self.buffer.fromstring(obj(self.namespace))
else:
raise Error, "The name %s does not exist in the namespace."
% name
def call(self, name):
"""Like call tag, name attribute only.
"""
obj = self.namespace.get(name, None)
if obj != None:
obj(self.namespace)
else:
raise Error, "The name %s does not exist in the namespace."
% name
def HTML(self, data):
"""A way to include HTML code.
(or any text, perhaps rename this method to 'raw' or something).
"""
self.buffer.fromstring(data)
def __call__(self, namespace):
"""Render this PyDocument.
"""
self.namespace = namespace
self.buffer = array('c', "")
self.script()
return self.buffer.tostring()
def script(self):
"""Override this method for the actual Python Document.
"""
pass
class StringValue:
"""A var tag calls things to render them. This renders by just
returning
the string.
"""
def __init__(self, value):
self.value = value
def __call__(self, namespace):
return self.value
#####################################################################
# example code
class standard_html_header(PyDocument):
"""A simple standard_html_header.
"""
def script(self):
self.HTML('''<html><title>''')
self.var(name="title")
self.HTML('''</title><body>''')
class standard_html_footer(PyDocument):
"""A simple standard_html_footer.
"""
def script(self):
self.HTML('''</body></html>''')
class SomePage(PyDocument):
"""Some other page.
"""
def script(self):
self.var("standard_html_header")
self.HTML('''<p>''')
self.var("foo")
self.HTML('''</p>''')
self.var("standard_html_footer")
def demo():
# construct a namespace
namespace = {
"foo": StringValue("FOO"),
"title": StringValue("This is the title of the page"),
"standard_html_header" : standard_html_header(),
"standard_html_footer" : standard_html_footer(),
}
# create instance of SomePage class
somepage = SomePage()
# now call somepage with namespace to render it
print somepage(namespace)
def test():
demo()
if __name__=="__main__": test()