Code

reformatting for 80 cols
[roundup.git] / frontends / ZRoundup / ZRoundup.py
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.4 2002-01-10 03:38:16 richard Exp $
18 #
19 ''' ZRoundup module - exposes the roundup web interface to Zope
21 This frontend works by providing a thin layer that sits between Zope and the
22 regular CGI interface of roundup, providing the web frontend with the minimum
23 of effort.
25 This means that the regular CGI interface does all authentication quite
26 independently of Zope. The roundup code is kept in memory though, and it
27 runs in the same server as all your other Zope stuff, so it does have _some_
28 advantages over regular CGI :)
30 It also means that any requests which specify :filter, :columns or :sort
31 _must_ be done using a GET, so that this interface can re-parse the
32 QUERY_STRING. Zope interprets the ':' as a special character, and the special
33 args are lost to it.
34 '''
35 from Globals import InitializeClass, HTMLFile
36 from OFS.SimpleItem import Item
37 from OFS.PropertyManager import PropertyManager
38 from Acquisition import Implicit
39 from Persistence import Persistent
40 from AccessControl import ClassSecurityInfo
41 from AccessControl import ModuleSecurityInfo
42 modulesecurity = ModuleSecurityInfo()
44 import roundup.instance
45 from roundup import cgi_client
47 modulesecurity.declareProtected('View management screens',
48     'manage_addZRoundupForm')
49 manage_addZRoundupForm = HTMLFile('dtml/manage_addZRoundupForm', globals())
51 modulesecurity.declareProtected('Add Z Roundups', 'manage_addZRoundup')
52 def manage_addZRoundup(self, id, instance_home, REQUEST):
53     """Add a ZRoundup product """
54     # validate the instance_home
55     roundup.instance.open(instance_home)
56     self._setObject(id, ZRoundup(id, instance_home))
57     return self.manage_main(self, REQUEST)
59 class RequestWrapper:
60     '''Make the Zope RESPONSE look like a BaseHTTPServer
61     '''
62     def __init__(self, RESPONSE):
63         self.RESPONSE = RESPONSE
64         self.wfile = self.RESPONSE
65     def send_response(self, status):
66         self.RESPONSE.setStatus(status)
67     def send_header(self, header, value):
68         self.RESPONSE.addHeader(header, value)
69     def end_headers(self):
70         # not needed - the RESPONSE object handles this internally on write()
71         pass
73 class FormItem:
74     '''Make a Zope form item look like a cgi.py one
75     '''
76     def __init__(self, value):
77         self.value = value
78         if hasattr(self.value, 'filename'):
79             self.filename = self.value.filename
80             self.file = self.value
82 class FormWrapper:
83     '''Make a Zope form dict look like a cgi.py one
84     '''
85     def __init__(self, form):
86         self.form = form
87     def __getitem__(self, item):
88         return FormItem(self.form[item])
89     def has_key(self, item):
90         return self.form.has_key(item)
91     def keys(self):
92         return self.form.keys()
94 class ZRoundup(Item, PropertyManager, Implicit, Persistent):
95     '''An instance of this class provides an interface between Zope and
96        roundup for one roundup instance
97     '''
98     meta_type =  'Z Roundup'
99     security = ClassSecurityInfo()
101     def __init__(self, id, instance_home):
102         self.id = id
103         self.instance_home = instance_home
105     # define the properties that define this object
106     _properties = (
107         {'id':'id', 'type': 'string', 'mode': 'w'},
108         {'id':'instance_home', 'type': 'string', 'mode': 'w'},
109     )
110     property_extensible_schema__ = 0
112     # define the tabs for the management interface
113     manage_options= PropertyManager.manage_options + (
114         {'label': 'View', 'action':'index_html'},
115     ) + Item.manage_options
117     icon = "misc_/ZRoundup/icon"
119     security.declarePrivate('_opendb')
120     def _opendb(self):
121         '''Open the roundup instance database for a transaction.
122         '''
123         instance = roundup.instance.open(self.instance_home)
124         request = RequestWrapper(self.REQUEST['RESPONSE'])
125         env = self.REQUEST.environ
126         env['INSTANCE_NAME'] = self.id
127         if env['REQUEST_METHOD'] == 'GET':
128             # force roundup to re-parse the request because Zope fiddles
129             # with it and we lose all the :filter, :columns, etc goodness
130             form = None
131         else:
132             form = FormWrapper(self.REQUEST.form)
133         return instance.Client(instance, request, env, form)
135     security.declareProtected('View', 'index_html')
136     def index_html(self):
137         '''Alias index_html to roundup's index
138         '''
139         client = self._opendb()
140         # fake the path that roundup should use
141         client.split_path = ['index']
142         return client.main()
144     def __getitem__(self, item):
145         '''All other URL accesses are passed throuh to roundup
146         '''
147         try:
148             client = self._opendb()
149             # fake the path that roundup should use
150             client.split_path = [item]
151             # and call roundup to do something 
152             client.main()
153             return ''
154         except cgi_client.NotFound:
155             raise 'NotFound', self.REQUEST.URL
156             pass
157         except:
158             import traceback
159             traceback.print_exc()
160             # all other exceptions in roundup are valid
161             raise
162         raise KeyError, item
165 InitializeClass(ZRoundup)
166 modulesecurity.apply(globals())
170 # $Log: not supported by cvs2svn $
171 # Revision 1.3  2001/12/12 23:55:00  richard
172 # Fixed some problems with user editing
174 # Revision 1.2  2001/12/12 23:33:58  richard
175 # added some implementation notes
177 # Revision 1.1  2001/12/12 23:27:13  richard
178 # Added a Zope frontend for roundup.
182 # vim: set filetype=python ts=4 sw=4 et si