Skip to content

Commit 2ac3900

Browse files
author
Richard Jones
committed
Added a Zope frontend for roundup.
1 parent 338f140 commit 2ac3900

File tree

7 files changed

+246
-3
lines changed

7 files changed

+246
-3
lines changed

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Feature:
2222
. Added the "display" command to the admin tool - displays a node's values
2323
. Message author's name appears in From: instead of roundup instance name
2424
(which still appears in the Reply-To:)
25+
. Added a Zope frontend for roundup.
2526

2627
Fixed:
2728
. Lots of bugs, thanks Roch� and others on the devel mailing list!

frontends/README.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
This directory contains alternate front-ends for Roundup.
2+
3+
Zope - ZRoundup
4+
---------------
5+
Install roundup as usual (see INSTALL.txt in the directory above this one.)
6+
Install as a regular product - copy the ZRoundup directory to your Products directory
7+
either in an INSTANCE_HOME/Products or the Zope code tree lib/python/Products.
8+
9+

frontends/ZRoundup/ZRoundup.py

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
2+
# This module is free software, and you may redistribute it and/or modify
3+
# under the same terms as Python, so long as this copyright message and
4+
# disclaimer are retained in their original form.
5+
#
6+
# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
7+
# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
8+
# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
9+
# POSSIBILITY OF SUCH DAMAGE.
10+
#
11+
# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
12+
# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13+
# FOR A PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
14+
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
15+
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
16+
#
17+
# $Id: ZRoundup.py,v 1.1 2001-12-12 23:27:13 richard Exp $
18+
#
19+
''' ZRoundup module - exposes the roundup web interface to Zope
20+
'''
21+
from Globals import InitializeClass, HTMLFile
22+
from OFS.SimpleItem import Item
23+
from OFS.PropertyManager import PropertyManager
24+
from Acquisition import Implicit
25+
from Persistence import Persistent
26+
from AccessControl import ClassSecurityInfo
27+
from AccessControl import ModuleSecurityInfo
28+
modulesecurity = ModuleSecurityInfo()
29+
30+
import roundup.instance
31+
from roundup import cgi_client
32+
33+
modulesecurity.declareProtected('View management screens', 'manage_addZRoundupForm')
34+
manage_addZRoundupForm = HTMLFile('dtml/manage_addZRoundupForm', globals())
35+
36+
modulesecurity.declareProtected('Add Z Roundups', 'manage_addZRoundup')
37+
def manage_addZRoundup(self, id, instance_home, REQUEST):
38+
"""Add a ZRoundup product """
39+
# validate the instance_home
40+
roundup.instance.open(instance_home)
41+
self._setObject(id, ZRoundup(id, instance_home))
42+
return self.manage_main(self, REQUEST)
43+
44+
class RequestWrapper:
45+
'''Make the Zope RESPONSE look like a BaseHTTPServer
46+
'''
47+
def __init__(self, RESPONSE):
48+
self.RESPONSE = RESPONSE
49+
self.wfile = self.RESPONSE
50+
def send_response(self, status):
51+
self.RESPONSE.setStatus(status)
52+
def send_header(self, header, value):
53+
self.RESPONSE.addHeader(header, value)
54+
def end_headers(self):
55+
# not needed - the RESPONSE object handles this internally on write()
56+
pass
57+
58+
class FormItem:
59+
'''Make a Zope form item look like a cgi.py one
60+
'''
61+
def __init__(self, value):
62+
self.value = value
63+
if hasattr(self.value, 'filename'):
64+
self.filename = self.value.filename
65+
self.file = self.value
66+
67+
class FormWrapper:
68+
'''Make a Zope form dict look like a cgi.py one
69+
'''
70+
def __init__(self, form):
71+
self.form = form
72+
def __getitem__(self, item):
73+
return FormItem(self.form[item])
74+
def has_key(self, item):
75+
return self.form.has_key(item)
76+
def keys(self):
77+
return self.form.keys()
78+
79+
class ZRoundup(Item, PropertyManager, Implicit, Persistent):
80+
'''An instance of this class provides an interface between Zope and roundup for one
81+
roundup instance
82+
'''
83+
meta_type = 'Z Roundup'
84+
security = ClassSecurityInfo()
85+
86+
def __init__(self, id, instance_home):
87+
self.id = id
88+
self.instance_home = instance_home
89+
90+
# define the properties that define this object
91+
_properties = (
92+
{'id':'id', 'type': 'string', 'mode': 'w'},
93+
{'id':'instance_home', 'type': 'string', 'mode': 'w'},
94+
)
95+
property_extensible_schema__ = 0
96+
97+
# define the tabs for the management interface
98+
manage_options= PropertyManager.manage_options + (
99+
{'label': 'View', 'action':'index_html'},
100+
) + Item.manage_options
101+
102+
icon = "misc_/ZRoundup/icon"
103+
104+
security.declarePrivate('_opendb')
105+
def _opendb(self):
106+
'''Open the roundup instnace database for a transaction
107+
'''
108+
instance = roundup.instance.open(self.instance_home)
109+
request = RequestWrapper(self.REQUEST['RESPONSE'])
110+
env = self.REQUEST.environ
111+
env['INSTANCE_NAME'] = self.id
112+
if env['REQUEST_METHOD'] == 'GET':
113+
# force roundup to re-parse the request because Zope fiddles
114+
# with it and we lose all the :filter, :columns, etc goodness
115+
form = None
116+
else:
117+
form = FormWrapper(self.REQUEST.form)
118+
return instance.Client(instance, request, env, form)
119+
120+
security.declareProtected('View', 'index_html')
121+
def index_html(self):
122+
'''Alias index_html to roundup's index
123+
'''
124+
client = self._opendb()
125+
# fake the path that roundup should use
126+
client.split_path = ['index']
127+
return client.main()
128+
129+
def __getitem__(self, item):
130+
'''All other URL accesses are passed throuh to roundup
131+
'''
132+
try:
133+
client = self._opendb()
134+
# fake the path that roundup should use
135+
client.split_path = [item]
136+
# and call roundup to do something
137+
client.main()
138+
return ''
139+
except cgi_client.NotFound:
140+
raise 'NotFound', self.REQUEST.URL
141+
pass
142+
except:
143+
import traceback
144+
traceback.print_exc()
145+
# all other exceptions in roundup are valid
146+
raise
147+
raise KeyError, item
148+
149+
150+
InitializeClass(ZRoundup)
151+
modulesecurity.apply(globals())
152+
153+
154+
#
155+
# $Log: not supported by cvs2svn $
156+
#
157+
#
158+
# vim: set filetype=python ts=4 sw=4 et si

frontends/ZRoundup/__init__.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
2+
# This module is free software, and you may redistribute it and/or modify
3+
# under the same terms as Python, so long as this copyright message and
4+
# disclaimer are retained in their original form.
5+
#
6+
# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
7+
# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
8+
# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
9+
# POSSIBILITY OF SUCH DAMAGE.
10+
#
11+
# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
12+
# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13+
# FOR A PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
14+
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
15+
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
16+
#
17+
# $Id: __init__.py,v 1.1 2001-12-12 23:27:14 richard Exp $
18+
#
19+
__version__='1.0'
20+
21+
import os
22+
# figure where ZRoundup is installed
23+
here = None
24+
if os.environ.has_key('INSTANCE_HOME'):
25+
here = os.environ['INSTANCE_HOME']
26+
path = os.path.join(here, 'Products', 'ZRoundup')
27+
if not os.path.exists(path):
28+
path = os.path.join(here, 'lib', 'python', 'Products', 'ZRoundup')
29+
if not os.path.exists(path):
30+
here = None
31+
if here is None:
32+
from __main__ import here
33+
path = os.path.join(here, 'Products', 'ZRoundup')
34+
if not os.path.exists(path):
35+
path = os.path.join(here, 'lib', 'python', 'Products', 'ZRoundup')
36+
if not os.path.exists(path):
37+
raise ValueError, "Can't determine where ZRoundup is installed"
38+
39+
# product initialisation
40+
import ZRoundup
41+
def initialize(context):
42+
context.registerClass(
43+
ZRoundup, meta_type = 'Z Roundup',
44+
constructors = (
45+
ZRoundup.manage_addZRoundupForm, ZRoundup.manage_addZRoundup
46+
)
47+
)
48+
49+
# set up the icon
50+
from ImageFile import ImageFile
51+
misc_ = {
52+
'icon': ImageFile('icons/tick_symbol.gif', path),
53+
}
54+
55+
56+
#
57+
# $Log: not supported by cvs2svn $
58+
#
59+
#
60+
# vim: set filetype=python ts=4 sw=4 et si
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<form action="manage_addZRoundup">
2+
ID: <input type="text" name="id"><br>
3+
Instance Home: <input type="text" name="instance_home"><br>
4+
<input type="submit">
5+
</form>
175 Bytes
Loading

roundup/cgi_client.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
1616
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1717
#
18-
# $Id: cgi_client.py,v 1.79 2001-12-10 22:20:01 richard Exp $
18+
# $Id: cgi_client.py,v 1.80 2001-12-12 23:27:14 richard Exp $
1919

2020
__doc__ = """
2121
WWW request handler (also used in the stand-alone server).
@@ -60,14 +60,17 @@ class Client:
6060
ANONYMOUS_ACCESS = 'deny' # one of 'deny', 'allow'
6161
ANONYMOUS_REGISTER = 'deny' # one of 'deny', 'allow'
6262

63-
def __init__(self, instance, request, env):
63+
def __init__(self, instance, request, env, form=None):
6464
self.instance = instance
6565
self.request = request
6666
self.env = env
6767
self.path = env['PATH_INFO']
6868
self.split_path = self.path.split('/')
6969

70-
self.form = cgi.FieldStorage(environ=env)
70+
if form is None:
71+
self.form = cgi.FieldStorage(environ=env)
72+
else:
73+
self.form = form
7174
self.headers_done = 0
7275
try:
7376
self.debug = int(env.get("ROUNDUP_DEBUG", 0))
@@ -1087,6 +1090,13 @@ def parsePropsFromForm(db, cl, form, nodeid=0):
10871090

10881091
#
10891092
# $Log: not supported by cvs2svn $
1093+
# Revision 1.79 2001/12/10 22:20:01 richard
1094+
# Enabled transaction support in the bsddb backend. It uses the anydbm code
1095+
# where possible, only replacing methods where the db is opened (it uses the
1096+
# btree opener specifically.)
1097+
# Also cleaned up some change note generation.
1098+
# Made the backends package work with pydoc too.
1099+
#
10901100
# Revision 1.78 2001/12/07 05:59:27 rochecompaan
10911101
# Fixed small bug that prevented adding issues through the web.
10921102
#

0 commit comments

Comments
 (0)