[Zope-Checkins] CVS: Packages/OFS - Examples.py:1.1.2.1 Application.py:1.160.12.1 Folder.py:1.96.12.1
Evan Simpson
evan@zope.com
Tue, 13 Nov 2001 14:39:02 -0500
Update of /cvs-repository/Packages/OFS
In directory cvs.zope.org:/tmp/cvs-serv25062/OFS
Modified Files:
Tag: evan-examples-branch
Application.py Folder.py
Added Files:
Tag: evan-examples-branch
Examples.py
Log Message:
Make formerly reserved objects in the root into shadow objects that are
available even when deleted, and are re-created at startup.
Add standard_template.pt for ZPT.
Add "Examples..." to add lists, which scans for Products with 'examples'
directories with a 'index.xml' manifest file. See Products/PageTemplates
for an example of this.
=== Added File Packages/OFS/Examples.py ===
##############################################################################
#
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
#
# Copyright (c) Digital Creations. All rights reserved.
#
# This license has been certified as Open Source(tm).
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions in source code must retain the above copyright
# notice, this list of conditions, and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# 3. Digital Creations requests that attribution be given to Zope
# in any manner possible. Zope includes a "Powered by Zope"
# button that is installed by default. While it is not a license
# violation to remove this button, it is requested that the
# attribution remain. A significant investment has been put
# into Zope, and this effort will continue if the Zope community
# continues to grow. This is one way to assure that growth.
#
# 4. All advertising materials and documentation mentioning
# features derived from or use of this software must display
# the following acknowledgement:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# In the event that the product being advertised includes an
# intact Zope distribution (with copyright and license included)
# then this clause is waived.
#
# 5. Names associated with Zope or Digital Creations must not be used to
# endorse or promote products derived from this software without
# prior written permission from Digital Creations.
#
# 6. Modified redistributions of any form whatsoever must retain
# the following acknowledgment:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# Intact (re-)distributions of any official Zope release do not
# require an external acknowledgement.
#
# 7. Modifications are encouraged but must be packaged separately as
# patches to official Zope releases. Distributions that do not
# clearly separate the patches from the original work must be clearly
# labeled as unofficial distributions. Modifications which do not
# carry the name Zope may be packaged in any form, as long as they
# conform to all of the clauses above.
#
#
# Disclaimer
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
#
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations. Specific
# attributions are listed in the accompanying credits file.
#
##############################################################################
"""Examples mixin
Provide support for Product examples.
$Id: Examples.py,v 1.1.2.1 2001/11/13 19:39:00 evan Exp $"""
__version__='$Revision: 1.1.2.1 $'[11:-2]
import os, sys, Shared.DC.xml.xmllib
from Globals import DTMLFile
from AccessControl import getSecurityManager
from ObjectManager import ObjectManager
import OFS.Application, StructuredText
from zLOG import LOG, ERROR
from cgi import escape
class Examples:
meta_types = ObjectManager.meta_types + (
{'permission': 'View management interface',
'name': ' Example...',
'action': 'manage_product_examples'},
)
_product_examplesForm=DTMLFile('dtml/product_examples', globals())
def manage_product_examples(self, REQUEST, RESPONSE):
"""Handle display and use of Product examples."""
chosen = REQUEST.form.get('example')
if chosen:
example = self._get_product_example(chosen)
# Do example
for act, path in example['actions']:
if act == 'import':
self._importObjectFromFile(
os.path.join(example['dir'], path))
elif act == 'execute':
execfile(os.path.join(example['dir'], path), {})
elif act == 'call':
self.unrestrictedTraverse(path)()
if example['view']:
RESPONSE.redirect(example['view'])
return self.manage_main(self, REQUEST,
manage_tabs_message="Example %s chosen." % chosen,
title = 'Example chosen',
update_menu=1)
examples = self._get_product_examples()
return self._product_examplesForm(examples=examples)
def _get_product_examples(self):
all_examples = []
for priority, name, i, product_dir in OFS.Application.get_products():
dir = os.path.join(product_dir, name, 'examples')
if not os.path.isdir(dir):
continue
fn = os.path.join(dir, 'index.xml')
if not os.path.isfile(fn):
continue
try:
examples = XmlParser().parse(open(fn).read())
except (ExampleError, RuntimeError):
LOG("Examples", ERROR, fn, error=sys.exc_info())
else:
all_examples.append((name, examples))
return all_examples
def _get_product_example(self, name):
pname, ename = name.split('.', 1)
for priority, name, i, product_dir in OFS.Application.get_products():
if name != pname:
continue
dir = os.path.join(product_dir, name, 'examples')
fn = os.path.join(dir, 'index.xml')
if not os.path.isfile(fn):
break
try:
examples = XmlParser().parse(open(fn).read())
except (ExampleError, RuntimeError):
LOG("Examples", ERROR, fn, error=sys.exc_info())
else:
for example in examples:
if example['name'] != ename:
continue
example['dir'] = dir
return example
break
raise ExampleError, "Example %s not found." % `name`
class ExampleError(Exception):
pass
# Simple XML parser for manifest files
class Node:
allowed_children = ()
def __init__(self, name, attrs):
self.name = name
self.attrs = attrs
self.start()
def start(self):
self.data = []
def end(self, name):
if name == self.name:
return 1
raise ExampleError, "Improperly closed %s" % self.name
def add(self, node):
raise ExampleError, "%s should not have child nodes" % self.name
def addData(self, data, cdata=0):
self.data.append(data)
def noData(self, data, cdata=0):
if data.strip():
raise ExampleError, "%s should not have text" % self.name
def noAttrs(self):
if self.attrs:
raise ExampleError, "%s should not have attributes" % self.name
def getReqAttr(self, attrname):
try:
return self.attrs[attrname]
except KeyError:
raise ExampleError, ("%s missing required attribute %s" %
(self.name, attrname))
class RootNode:
allowed_children = ('example',)
def __init__(self):
self.examples = []
def add(self, node):
self.examples.append(node)
def addData(self, data, cdata=0):
pass
def out(self):
ex = []
for example in self.examples:
ex.append({'name': example.getReqAttr('name'),
'description': example.description,
'actions': example.actions,
'view': example.view})
return ex
class ExampleNode(Node):
allowed_children = ('description', 'payload', 'view')
description = None
view = None
def start(self):
self.payload = []
def add(self, node):
if node.name =='payload':
node.payload = self.payload
else:
if getattr(self, node.name, None) is not None:
raise ExampleError, "Only one %s allowed" % node.name
setattr(self, node.name, node)
def end(self, name):
if self.view is not None:
self.view = self.view.getReqAttr('url')
if self.description is not None:
text = ''.join(self.description.data)
format = self.description.attrs.get('format', 'plain')
if format == 'plain':
text = escape(text)
elif format == 'stx':
text = StructuredText.HTMLNG(
StructuredText.Basic(text), header=0)
elif format != 'html':
raise ExampleError, "Unknown description format %s" % format
self.description = text
self.actions = actions = []
for ob in self.payload:
actions.append((ob.name, ob.getReqAttr(payloadmap[ob.name])))
return Node.end(self, name)
addData = Node.noData
payloadmap = {'import': 'file', 'execute': 'file', 'call': 'path'}
class DescriptionNode(Node):
allowed_children = None
def add(self, (name, attrs)):
data = self.data.append
if not attrs:
data('<%s>' % name)
else:
data('<%s ' % name)
for k, v in attrs.items():
data(' %s="%s"' % (k, escape(v)))
data('>')
def end(self, name):
data = self.data.append
if name == self.name:
return 1
data('</%s>' % name)
class PayloadNode(Node):
allowed_children = ('import', 'execute', 'call')
def start(self):
self.noAttrs()
def add(self, node):
self.payload.append(node)
addData = Node.noData
class AttrNode(Node):
addData = Node.noData
NodeMap = {
'example': ExampleNode,
'description': DescriptionNode,
'payload': PayloadNode,
'view': AttrNode,
'import': AttrNode,
'execute': AttrNode,
'call': AttrNode,
}
class XmlParser(Shared.DC.xml.xmllib.XMLParser):
def __init__(self):
Shared.DC.xml.xmllib.XMLParser.__init__(self)
self.root = self.node = RootNode()
self.tagstack = []
def parse(self, data):
self.feed(data)
self.close()
return self.root.out()
def unknown_starttag(self, name, attrs):
node = self.node
if node.allowed_children is None:
node.add((name, attrs))
else:
if name not in node.allowed_children:
raise ExampleError, '%s not allowed in %s' % (name, node.name)
newnode = NodeMap[name](name, attrs)
node.add(newnode)
self.tagstack.append(node)
self.node = newnode
def unknown_endtag(self, name):
if self.node.end(name):
self.node = self.tagstack.pop()
def handle_cdata(self, data):
self.node.addData(data, cdata=1)
def handle_data(self, data):
self.node.addData(data)
def unknown_entityref(self, data):
self.node.addData(data)
def syntax_error(self, message):
raise ExampleError, message
=== Packages/OFS/Application.py 1.160 => 1.160.12.1 ===
from zLOG import LOG, ERROR, WARNING, INFO
from HelpSys.HelpSys import HelpSys
-
-
-_standard_error_msg='''\
-<dtml-var standard_html_header>
-
-<dtml-if error_message>
- <dtml-var error_message>
-<dtml-else>
-
- <H2>Site Error</H2>
-
- <P>An error was encountered while publishing this resource.
- </P>
-
- <P>
- <STRONG>Error Type: <dtml-var error_type html_quote></STRONG><BR>
- <STRONG>Error Value: <dtml-var error_value html_quote></STRONG><BR>
- </P>
-
- <HR NOSHADE>
-
- <P>Troubleshooting Suggestions</P>
-
- <UL>
- <dtml-if "error_type in ('KeyError','NameError')">
- <LI>This resource may be trying to reference a
- nonexistent object or variable <STRONG><dtml-var error_value></STRONG>.</LI>
- </dtml-if>
- <LI>The URL may be incorrect.</LI>
- <LI>The parameters passed to this resource may be incorrect.</LI>
- <LI>A resource that this resource relies on may be encountering
- an error.</LI>
- </UL>
-
- <P>For more detailed information about the error, please
- refer to the HTML source for this page.
- </P>
-
- <P>If the error persists please contact the site maintainer.
- Thank you for your patience.
- </P>
-
- <dtml-comment>
- Here, events like logging and other actions may also be performed, such as
- sending mail automatically to the administrator.
- </dtml-comment>
-
-</dtml-if>
-<dtml-var standard_html_footer>'''
-
+from Products.PageTemplates.PageTemplateFile import PageTemplateFile
class Application(Globals.ApplicationDefaultPermissions,
ZDOM.Root, Folder.Folder,
@@ -171,10 +122,8 @@
p_=misc_.p_
misc_=misc_.misc_
- _reserved_names=('standard_html_header',
- 'standard_html_footer',
- 'standard_error_message',
- 'Control_Panel')
+ _reserved_names=('Control_Panel',)
+
# This class-default __allow_groups__ ensures that the
# emergency user can still access the system if the top-level
@@ -197,26 +146,6 @@
cpl._init()
self._setObject('Control_Panel', cpl)
- # Note that this may happen before products are
- # installed, so we have to use addDocument as stand-alone.
- import Document
- Document.manage_addDocument(
- self,
- 'standard_html_header',
- 'Standard Html Header', (
- '<html><head><title>&dtml-title_or_id;'
- '</title></head><body bgcolor="#FFFFFF">') )
- Document.manage_addDocument(
- self,
- 'standard_html_footer',
- 'Standard Html Footer',
- '</body></html>')
- Document.manage_addDocument(
- self,
- 'standard_error_message',
- 'Standard Error Message',
- _standard_error_msg)
-
def id(self):
try: return self.REQUEST['SCRIPT_NAME'][1:]
except: return self.title
@@ -363,8 +292,6 @@
return 1
return 0
-
-
class Expired(Globals.Persistent):
icon='p_/broken'
@@ -408,17 +335,6 @@
get_transaction().note('Added Control_Panel.Products')
get_transaction().commit()
- # b/c: Ensure that std err msg exists.
- if not hasattr(app, 'standard_error_message'):
- import Document
- Document.manage_addDocument(
- app,
- 'standard_error_message',
- 'Standard Error Message',
- _standard_error_msg)
- get_transaction().note('Added standard_error_message')
- get_transaction().commit()
-
# b/c: Ensure that Owner role exists.
if hasattr(app, '__ac_roles__') and not ('Owner' in app.__ac_roles__):
app.__ac_roles__=app.__ac_roles__ + ('Owner',)
@@ -449,6 +365,7 @@
get_transaction().commit()
install_products(app)
+ install_standards(app)
# Note that the code from here on only runs if we are not a ZEO
# client, or if we are a ZEO client and we've specified by way
@@ -733,6 +650,28 @@
if raise_exc:
raise
+def install_standards(app):
+ # Install the replaceable standard objects
+ std_dir = os.path.join(Globals.package_home(globals()), 'standard')
+ for fn in os.listdir(std_dir):
+ base, ext = os.path.splitext(fn)
+ if ext == '.dtml':
+ ob = Globals.DTMLFile(base, std_dir)
+ fn = base
+ if not hasattr(app, fn):
+ app.manage_addProduct['OFSP'].manage_addDTMLMethod(
+ id=fn, file=open(ob.raw))
+ elif ext in ('.pt', '.zpt'):
+ ob = PageTemplateFile(fn, std_dir, __name__=fn)
+ if not hasattr(app, fn):
+ app.manage_addProduct['PageTemplates'].manage_addPageTemplate(
+ id=fn, title='', text=open(ob.filename))
+
+ ob.__replaceable__ = Globals.REPLACEABLE
+ setattr(Application, fn, ob)
+
+ get_transaction().note('Installed standard objects')
+ get_transaction().commit()
def reinstall_product(app, product_name):
folder_permissions = get_folder_permissions()
=== Packages/OFS/Folder.py 1.96 => 1.96.12.1 ===
from webdav.WriteLockInterface import WriteLockInterface
from AccessControl import Unauthorized
+import Examples
from Globals import DTMLFile
from AccessControl import getSecurityManager
@@ -141,6 +142,7 @@
class Folder(
+ Examples.Examples,
ObjectManager.ObjectManager,
PropertyManager.PropertyManager,
AccessControl.Role.RoleManager,