Skip to content

Commit 345e52e

Browse files
author
Richard Jones
committed
Initial import of code
Currently version 1.0.2 but with the 1.0.3 changes as given in the CHANGES file. Is about ready for a 1.0.3 release. [[This repository is actually a lift into git made in October 2011 of code history originally kept in CVS and later in Subversion. This import marks the point at which the original private CVS moved to public CVS on SourceForge. Due to technical problems with CVS and the CVS to Subversion conversion tools, portions of the early history have somewhat garbled metadata. Here and elsewhere in this repo, comments enclosed in curly braces were added at the time of the git lift in an attempt to document the problem.]]
0 parents  commit 345e52e

22 files changed

+4323
-0
lines changed

CHANGES

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
2001-07-11 - 0.1.0
2+
. Needed a bug tracking system. Looked around. Tried to install many
3+
Perl-based systems, to no avail. Got tired of waiting for Roundup to be
4+
released. Had just finished major product project, so needed something
5+
different for a while. Roundup here I come...
6+
7+
8+
2001-07-18 - 0.1.1
9+
. Initial version release with consent of Roundup spec author, Ka-Ping Yee:
10+
"Amazing! Nice work. I'll watch for the source code on your website."
11+
12+
13+
2001-07-18 - 0.1.2
14+
. Set default index to ?:group=priority&:columns=activity,status,title so
15+
the priority column isn't displayed.
16+
. Thanks Anthony:
17+
. added notes to the README about Python prerequisites
18+
. added check to roundup.py, roundup.cgi, server.py and roundup-mailgw.py
19+
for python 2+ - and made the file itself parseable by 1.5.2 ;)
20+
. python 2.0 didn't have the default args for the time module functions.
21+
. better handling of db directory in initDB
22+
. Sorting on the extra properties defined by roundupdb classes was broken
23+
due to the caching used. May now sort on activity and creation
24+
properties, etc.
25+
. Set the default index to sort on activity
26+
27+
2001-07-XX - 0.1.3
28+
. Reldate now takes an argument "pretty" - when true, it pretty-prints the
29+
interval generated up to 5 days, then pretty-prints the date of last
30+
activity. The issue index and item now use the pretty format.
31+
. Classes list for admin user in CGI interface.
32+
. Made the view configuration more accessible, neater and more realistic.
33+
. Fixed list view grouping handling grouping by a Multilink or String or Link
34+
value of None or Date, ... (mind you, sorting by Date???)
35+
. Fixed bug in the plain formatter when a Link was None.
36+
. Fixed ordering of list view column headings.
37+
. Fixed list view column heading sort links - and limited the number of
38+
columns to sort by to 2.
39+
. Added searching by glob to StringType filtering -
40+
^text - search for text at start of fields
41+
text$ - search for text at end of fields
42+
^text$ - exactly match text in fields
43+
te*xt - search for text matching "te"<any characters>"xt"
44+
te?xt - search for text matching "te"<any one character>"xt"
45+
. Added more fields to the issue.filter and issue.index templates

README

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
Roundup
2+
=======
3+
4+
5+
1. License
6+
==========
7+
This software is released under the GNU GPL. The copyright is held by Bizar
8+
Software Pty Ltd (http://www.bizarsoftware.com.au).
9+
10+
The stylesheet included with this package has been copied from the Zope
11+
management interface and presumably belongs to Digital Creations.
12+
13+
14+
15+
2. Installation
16+
===============
17+
These instructions work on redhat 6.2 and mandrake 8.0 - with the caveat
18+
that these systems don't come with python 2.0 or newer installed, so you'll
19+
have to upgrade python before this stuff will work.
20+
21+
Note that most of the following is configurable in the config.py, it's just
22+
not documented. At a minimum, you'll want to change the email addresses and
23+
mail host specification in the config.
24+
25+
26+
2.0 Prerequisites
27+
-----------------
28+
Either:
29+
. Python 2.0 with pydoc installed. See http://www.lfw.org/ for pydoc.
30+
or
31+
. Python 2.1
32+
33+
Both need the bsddb module.
34+
35+
36+
2.1 Initial Setup
37+
-----------------
38+
1. Make a directory in /home/httpd/html called 'roundup'.
39+
2. Copy the tar file's contents there.
40+
3. "python roundup.py init" to initialise the database (by default, it
41+
goes in a directory called 'db' in the current directory). Choose a
42+
sensible admin password.
43+
4. "chmod -R a+rw db"
44+
45+
46+
2.2 Mail
47+
--------
48+
Set up a mail alias called "issue_tracker" as:
49+
"|/usr/bin/python /home/httpd/html/roundup/roundup-mailgw.py"
50+
51+
In some installations (e.g. RedHat 6.2 I think) you'll need to set up smrsh
52+
so sendmail will accept the pipe command. In that case, symlink
53+
/etc/smrsh/python to /usr/bin/python and change the command to:
54+
"|python /home/httpd/html/roundup/roundup-mailgw.py"
55+
56+
57+
2.3 Web Interface
58+
-----------------
59+
This software will work through apache or stand-alone.
60+
61+
Stand-alone:
62+
1. Edit server.py at the bottom to set your hostname and a port that is free.
63+
2. "python server.py"
64+
3. Load up the page "/" using the port number you set.
65+
66+
Apache:
67+
1. Make sure roundup.cgi is executable
68+
2. Edit your /etc/httpd/conf/httpd.conf and make sure that the
69+
/home/httpd/html/roundup/roundup.cgi script will be treated as a CGI
70+
script.
71+
3. Add the following to your /etc/httpd/conf/httpd.conf:
72+
snip >>>
73+
RewriteEngine on
74+
RewriteCond %{HTTP:Authorization} ^(.*)
75+
RewriteRule ^/roundup/roundup.cgi(.*) /home/httpd/html/roundup/roundup.cgi$1 [e=HTTP_CGI_AUTHORIZATION:%1,t=application/x-httpd-cgi,l]
76+
<<< snip
77+
note: the RewriteRule must be on one line - no breaks
78+
4. Re-start your apache to re-load the config
79+
5. Load up the page "/roundup/roundup.cgi/"
80+
81+
82+
3. Usage
83+
========
84+
The system is designed to accessed through the command-line, e-mail or web
85+
interface.
86+
87+
3.1 Command-line
88+
----------------
89+
The command-line tool is called "roundup.py" and is used for most low-level
90+
database manipulations such as:
91+
. redefining the list of products ("create" and "retire" commands)
92+
. adding users manually, or setting their passwords ("create" and "set")
93+
. other stuff - run it with no arguments to get a better description of
94+
what it does.
95+
96+
97+
3.2 E-mail
98+
----------
99+
See the docstring at the start of the roundup-mailgw.py source file.
100+
101+
102+
3.3 Web
103+
-------
104+
Hopefully, this interface is pretty self-explanatory...
105+
106+
Index views may be modified by the following arguments:
107+
:sort - sort by prop name, optionally preceeded with '-'
108+
to give descending or nothing for ascending sorting.
109+
:group - group by prop name, optionally preceeded with '-' or
110+
to sort in descending or nothing for ascending order.
111+
:filter - selects which props should be displayed in the filter
112+
section. Default is all.
113+
:columns - selects the columns that should be displayed.
114+
Default is all.
115+
propname - selects the values the node properties given by propname
116+
must have (very basic search/filter).
117+
118+
119+
120+
3. Design
121+
=========
122+
This software was written according to the specification found at
123+
http://software-carpentry.codesourcery.com/entries/second-round/track/Roundup/
124+
125+
... with some modifications. I've marked these in the source with 'XXX'
126+
comments when I remember to.
127+
128+
In short:
129+
Class.find() - may match multiple properties, uses keyword args.
130+
131+
Class.filter() - isn't in the spec and it's very useful to have at the Class
132+
level.
133+
134+
CGI interface index view specifier layout part - lose the '+' from the
135+
sorting arguments (it's a reserved URL character ;). Just made no
136+
prefix mean ascending and '-' prefix descending.
137+
138+
ItemClass - renamed to IssueClass to better match it only having one
139+
hypderdb class "issue". Allowing > 1 hyperdb class breaks the
140+
"superseder" multilink (since it can only link to one thing, and we'd
141+
want bugs to link to support and vice-versa).
142+
143+
templates - the call="link()" is handled by special-case mechanisms in my
144+
top-level CGI handler. In a nutshell, the handler looks for a method on
145+
itself called 'index%s' or 'item%s' where %s is a class. Most items
146+
pass on to the templating mechanism, but the file class _always_ does
147+
downloading. It'll probably stay this way too...
148+
149+
template - call="link(property)" may be used to link "the current node"
150+
(from an index) - the link text is the property specified.
151+
152+
template - added functions that I found very useful: List, History and
153+
Submit.
154+
155+
template - items must specify the message lists, history, etc. Having them
156+
by default was sometimes not wanted.
157+
158+
template - index view determines its default columns from the template's
159+
<property> tags.
160+
161+
template - menu() and field() look awfully similar now .... ;)
162+
163+
roundup.py - the command-line tool has a lot more commands at its disposal
164+
165+
166+
4. TODO
167+
=======
168+
Most of the TODO items are captured in comments in the code. In summary:
169+
170+
in general:
171+
. better error handling (nicer messages for users)
172+
. possibly revert the entire damn thing to 1.5.2 ... :(
173+
hyperdb:
174+
. transaction support
175+
roundupdb:
176+
. split the file storage into multiple files
177+
roundup-mailgw:
178+
. errors as attachments
179+
. snip signatures?
180+
server:
181+
. check the source file timestamps before reloading
182+
date:
183+
. blue Date.__sub__ needs food, badly
184+
config
185+
. default to blank config in distribution and warn appropriately
186+
roundup_cgi
187+
. searching
188+
. keep form fields in form on bad submission - only clear it if all ok
189+
190+
191+
192+
5. Known Bugs
193+
=============
194+
195+
http://dirk.adroit/roundup/roundup.cgi/issue?%3Acolumns%3Dactivity%2Cstatus%2Ctitle&%3Asort%3Dtitle%2C-activity&%3Agroup%3Dpriority
196+
197+
date:
198+
. date subtraction doesn't work correctly "if the dates cross leap years,
199+
phases of the moon, ..."
200+
201+
The software still probably has bugs. Please let me know when you find 'em.
202+
Patches are nice, but there'll probably be a good chance I've changed the
203+
code (there's not much to it ;) so a good description will be appreciated
204+
as well.
205+
206+
207+
208+
6. Author
209+
=========
210+
211+
212+
213+
7. Thanks
214+
=========
215+
Well, Ping, of course ;)
216+
217+
Anthony Baxter, for some good first-release feedback.
218+

cgitb.py

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import sys, os, types, string, keyword, linecache, tokenize, inspect, pydoc
2+
3+
def breaker():
4+
return ('<body bgcolor="#f0f0ff">' +
5+
'<font color="#f0f0ff" size="-5"> > </font> ' +
6+
'</table>' * 5)
7+
8+
def html(context=5):
9+
etype, evalue = sys.exc_type, sys.exc_value
10+
if type(etype) is types.ClassType:
11+
etype = etype.__name__
12+
pyver = 'Python ' + string.split(sys.version)[0] + '<br>' + sys.executable
13+
head = pydoc.html.heading(
14+
'<font size=+1><strong>%s</strong>: %s</font>'%(str(etype), str(evalue)),
15+
'#ffffff', '#aa55cc', pyver)
16+
17+
head = head + ('<p>A problem occurred while running a Python script. '
18+
'Here is the sequence of function calls leading up to '
19+
'the error, with the most recent (innermost) call first.'
20+
'The exception attributes are:')
21+
22+
indent = '<tt><small>%s</small>&nbsp;</tt>' % ('&nbsp;' * 5)
23+
traceback = []
24+
for frame, file, lnum, func, lines, index in inspect.trace(context):
25+
if file is None:
26+
link = '&lt;file is None - probably inside <tt>eval</tt> or <tt>exec</tt>&gt;'
27+
else:
28+
file = os.path.abspath(file)
29+
link = '<a href="file:%s">%s</a>' % (file, pydoc.html.escape(file))
30+
args, varargs, varkw, locals = inspect.getargvalues(frame)
31+
if func == '?':
32+
call = ''
33+
else:
34+
call = 'in <strong>%s</strong>' % func + inspect.formatargvalues(
35+
args, varargs, varkw, locals,
36+
formatvalue=lambda value: '=' + pydoc.html.repr(value))
37+
38+
level = '''
39+
<table width="100%%" bgcolor="#d8bbff" cellspacing=0 cellpadding=2 border=0>
40+
<tr><td>%s %s</td></tr></table>''' % (link, call)
41+
42+
if file is None:
43+
traceback.append('<p>' + level)
44+
continue
45+
46+
# do a fil inspection
47+
names = []
48+
def tokeneater(type, token, start, end, line, names=names):
49+
if type == tokenize.NAME and token not in keyword.kwlist:
50+
if token not in names:
51+
names.append(token)
52+
if type == tokenize.NEWLINE: raise IndexError
53+
def linereader(file=file, lnum=[lnum]):
54+
line = linecache.getline(file, lnum[0])
55+
lnum[0] = lnum[0] + 1
56+
return line
57+
58+
try:
59+
tokenize.tokenize(linereader, tokeneater)
60+
except IndexError: pass
61+
lvals = []
62+
for name in names:
63+
if name in frame.f_code.co_varnames:
64+
if locals.has_key(name):
65+
value = pydoc.html.repr(locals[name])
66+
else:
67+
value = '<em>undefined</em>'
68+
name = '<strong>%s</strong>' % name
69+
else:
70+
if frame.f_globals.has_key(name):
71+
value = pydoc.html.repr(frame.f_globals[name])
72+
else:
73+
value = '<em>undefined</em>'
74+
name = '<em>global</em> <strong>%s</strong>' % name
75+
lvals.append('%s&nbsp;= %s' % (name, value))
76+
if lvals:
77+
lvals = string.join(lvals, ', ')
78+
lvals = indent + '''
79+
<small><font color="#909090">%s</font></small><br>''' % lvals
80+
else:
81+
lvals = ''
82+
83+
excerpt = []
84+
i = lnum - index
85+
for line in lines:
86+
number = '&nbsp;' * (5-len(str(i))) + str(i)
87+
number = '<small><font color="#909090">%s</font></small>' % number
88+
line = '<tt>%s&nbsp;%s</tt>' % (number, pydoc.html.preformat(line))
89+
if i == lnum:
90+
line = '''
91+
<table width="100%%" bgcolor="#ffccee" cellspacing=0 cellpadding=0 border=0>
92+
<tr><td>%s</td></tr></table>''' % line
93+
excerpt.append('\n' + line)
94+
if i == lnum:
95+
excerpt.append(lvals)
96+
i = i + 1
97+
traceback.append('<p>' + level + string.join(excerpt, '\n'))
98+
99+
traceback.reverse()
100+
101+
exception = '<p><strong>%s</strong>: %s' % (str(etype), str(evalue))
102+
attribs = []
103+
if type(evalue) is types.InstanceType:
104+
for name in dir(evalue):
105+
value = pydoc.html.repr(getattr(evalue, name))
106+
attribs.append('<br>%s%s&nbsp;= %s' % (indent, name, value))
107+
108+
return head + string.join(attribs) + string.join(traceback) + '<p>&nbsp;</p>'
109+
110+
def handler():
111+
print breaker()
112+
print html()
113+

config.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# This is the directory that the database is going to be stored in
2+
DATABASE = '/home/httpd/html/roundup/db'
3+
4+
# The email address that mail to roundup should go to
5+
ISSUE_TRACKER_EMAIL = '[email protected]'
6+
7+
# The email address that roundup will complain to if it runs into trouble
8+
ADMIN_EMAIL = "[email protected]"
9+
10+
# The SMTP mail host that roundup will use to send mail
11+
MAILHOST = 'goanna.adroit.net'
12+
13+
# Somewhere for roundup to log stuff internally sent to stdout or stderr
14+
LOG = '/home/httpd/html/roundup/roundup.log'

0 commit comments

Comments
 (0)