You can subscribe to this list here.
| 2001 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(226) |
Aug
(123) |
Sep
(22) |
Oct
(143) |
Nov
(135) |
Dec
(92) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2002 |
Jan
(205) |
Feb
(118) |
Mar
(29) |
Apr
(57) |
May
(133) |
Jun
(71) |
Jul
(209) |
Aug
(94) |
Sep
(467) |
Oct
(139) |
Nov
(38) |
Dec
(63) |
| 2003 |
Jan
(125) |
Feb
(150) |
Mar
(159) |
Apr
(106) |
May
(50) |
Jun
(87) |
Jul
(23) |
Aug
(103) |
Sep
(78) |
Oct
(87) |
Nov
(116) |
Dec
(58) |
| 2004 |
Jan
(57) |
Feb
(117) |
Mar
(213) |
Apr
(136) |
May
(246) |
Jun
(254) |
Jul
(234) |
Aug
(26) |
Sep
(61) |
Oct
(191) |
Nov
(199) |
Dec
(80) |
| 2005 |
Jan
(196) |
Feb
(204) |
Mar
(46) |
Apr
(115) |
May
(63) |
Jun
(66) |
Jul
(52) |
Aug
(4) |
Sep
(20) |
Oct
(16) |
Nov
(3) |
Dec
(24) |
| 2006 |
Jan
(165) |
Feb
(93) |
Mar
(40) |
Apr
(44) |
May
(11) |
Jun
(37) |
Jul
(39) |
Aug
(96) |
Sep
(19) |
Oct
(36) |
Nov
(68) |
Dec
(51) |
| 2007 |
Jan
(18) |
Feb
(12) |
Mar
(22) |
Apr
(26) |
May
(9) |
Jun
(3) |
Jul
(3) |
Aug
(25) |
Sep
(83) |
Oct
(12) |
Nov
(31) |
Dec
(9) |
| 2008 |
Jan
(6) |
Feb
(26) |
Mar
(12) |
Apr
(1) |
May
|
Jun
|
Jul
(5) |
Aug
(64) |
Sep
(19) |
Oct
|
Nov
|
Dec
(1) |
| 2009 |
Jan
|
Feb
(97) |
Mar
(36) |
Apr
|
May
(1) |
Jun
(28) |
Jul
(96) |
Aug
(15) |
Sep
(8) |
Oct
(26) |
Nov
(10) |
Dec
(23) |
| 2010 |
Jan
(20) |
Feb
(30) |
Mar
(5) |
Apr
(7) |
May
(2) |
Jun
(2) |
Jul
(25) |
Aug
(9) |
Sep
(9) |
Oct
(33) |
Nov
(16) |
Dec
(1) |
| 2011 |
Jan
(1) |
Feb
(1) |
Mar
(5) |
Apr
(18) |
May
(12) |
Jun
(8) |
Jul
(20) |
Aug
(2) |
Sep
(6) |
Oct
(17) |
Nov
|
Dec
|
| 2012 |
Jan
|
Feb
(1) |
Mar
|
Apr
(16) |
May
(6) |
Jun
(4) |
Jul
(12) |
Aug
(6) |
Sep
(6) |
Oct
(7) |
Nov
(34) |
Dec
(49) |
| 2013 |
Jan
(58) |
Feb
(35) |
Mar
(12) |
Apr
(15) |
May
(10) |
Jun
(8) |
Jul
(21) |
Aug
|
Sep
(50) |
Oct
(14) |
Nov
(6) |
Dec
(10) |
| 2014 |
Jan
(3) |
Feb
(2) |
Mar
(46) |
Apr
(21) |
May
(12) |
Jun
(4) |
Jul
(22) |
Aug
(15) |
Sep
(6) |
Oct
(23) |
Nov
(10) |
Dec
(23) |
| 2015 |
Jan
(6) |
Feb
(4) |
Mar
(39) |
Apr
(4) |
May
(6) |
Jun
(4) |
Jul
(2) |
Aug
(7) |
Sep
(7) |
Oct
(4) |
Nov
|
Dec
(2) |
| 2016 |
Jan
(59) |
Feb
|
Mar
(2) |
Apr
(16) |
May
(19) |
Jun
(75) |
Jul
(93) |
Aug
(6) |
Sep
(4) |
Oct
(4) |
Nov
(2) |
Dec
(6) |
| 2017 |
Jan
(12) |
Feb
(18) |
Mar
(52) |
Apr
(31) |
May
(3) |
Jun
(2) |
Jul
|
Aug
(35) |
Sep
(49) |
Oct
(22) |
Nov
(6) |
Dec
|
| 2018 |
Jan
|
Feb
|
Mar
(4) |
Apr
(12) |
May
(9) |
Jun
(28) |
Jul
(230) |
Aug
(76) |
Sep
(48) |
Oct
(4) |
Nov
(4) |
Dec
|
| 2019 |
Jan
(55) |
Feb
(33) |
Mar
(99) |
Apr
(60) |
May
(58) |
Jun
(135) |
Jul
(39) |
Aug
(49) |
Sep
(25) |
Oct
(138) |
Nov
(39) |
Dec
(34) |
| 2020 |
Jan
(84) |
Feb
(82) |
Mar
(9) |
Apr
(40) |
May
(54) |
Jun
(54) |
Jul
(57) |
Aug
(19) |
Sep
(17) |
Oct
(26) |
Nov
(16) |
Dec
(27) |
| 2021 |
Jan
(18) |
Feb
(15) |
Mar
(72) |
Apr
(41) |
May
(66) |
Jun
(39) |
Jul
(20) |
Aug
(33) |
Sep
(41) |
Oct
(31) |
Nov
(35) |
Dec
(69) |
| 2022 |
Jan
(60) |
Feb
(15) |
Mar
(18) |
Apr
(39) |
May
(74) |
Jun
(97) |
Jul
(105) |
Aug
(61) |
Sep
(249) |
Oct
(78) |
Nov
(83) |
Dec
(49) |
| 2023 |
Jan
(23) |
Feb
(113) |
Mar
(60) |
Apr
(79) |
May
(230) |
Jun
(125) |
Jul
(126) |
Aug
(32) |
Sep
(66) |
Oct
(55) |
Nov
(32) |
Dec
(28) |
| 2024 |
Jan
(13) |
Feb
(34) |
Mar
(126) |
Apr
(112) |
May
(109) |
Jun
(55) |
Jul
(94) |
Aug
(13) |
Sep
(8) |
Oct
(43) |
Nov
(54) |
Dec
(129) |
| 2025 |
Jan
(91) |
Feb
(10) |
Mar
(6) |
Apr
(1) |
May
(24) |
Jun
(49) |
Jul
(62) |
Aug
(62) |
Sep
(36) |
Oct
(11) |
Nov
(14) |
Dec
|
|
From: Richard J. <ri...@us...> - 2001-07-23 04:17:07
|
Update of /cvsroot/roundup/roundup/roundup/templates/extended/html_templates In directory usw-pr-cvs1:/tmp/cvs-serv31080/html_templates Log Message: Directory /cvsroot/roundup/roundup/roundup/templates/extended/html_templates added to the repository |
|
From: Anthony B. <ant...@us...> - 2001-07-23 04:05:08
|
Update of /cvsroot/roundup/roundup
In directory usw-pr-cvs1:/tmp/cvs-serv29124
Modified Files:
roundup-server
Log Message:
actually quit if python version wrong
Index: roundup-server
===================================================================
RCS file: /cvsroot/roundup/roundup/roundup-server,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -r1.1 -r1.2
*** roundup-server 2001/07/23 03:46:48 1.1
--- roundup-server 2001/07/23 04:05:05 1.2
***************
*** 11,14 ****
--- 11,15 ----
print "Content-Type: text/plain\n"
print "Roundup requires Python 2.0 or newer."
+ sys.exit(0)
__version__ = "0.1"
***************
*** 220,223 ****
--- 221,227 ----
#
# $Log$
+ # Revision 1.2 2001/07/23 04:05:05 anthonybaxter
+ # actually quit if python version wrong
+ #
# Revision 1.1 2001/07/23 03:46:48 richard
# moving the bin files to facilitate out-of-the-boxness
|
|
From: Richard J. <ri...@us...> - 2001-07-23 03:56:33
|
Update of /cvsroot/roundup/roundup/roundup In directory usw-pr-cvs1:/tmp/cvs-serv27402/roundup Modified Files: cgi_client.py Log Message: oops, missed a config removal Index: cgi_client.py =================================================================== RCS file: /cvsroot/roundup/roundup/roundup/cgi_client.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -r1.2 -r1.3 *** cgi_client.py 2001/07/22 12:09:32 1.2 --- cgi_client.py 2001/07/23 03:56:30 1.3 *************** *** 3,7 **** import os, cgi, pprint, StringIO, urlparse, re, traceback ! import config, roundupdb, htmltemplate, date class Unauthorised(ValueError): --- 3,7 ---- import os, cgi, pprint, StringIO, urlparse, re, traceback ! import roundupdb, htmltemplate, date class Unauthorised(ValueError): *************** *** 490,493 **** --- 490,496 ---- # # $Log$ + # Revision 1.3 2001/07/23 03:56:30 richard + # oops, missed a config removal + # # Revision 1.2 2001/07/22 12:09:32 richard # Final commit of Grande Splite |
Update of /cvsroot/roundup/roundup/templates/templates In directory usw-pr-cvs1:/tmp/cvs-serv27102/templates/templates Removed Files: file.index issue.filter issue.index issue.item msg.index msg.item style.css user.index user.item Log Message: byebye. --- file.index DELETED --- --- issue.filter DELETED --- --- issue.index DELETED --- --- issue.item DELETED --- --- msg.index DELETED --- --- msg.item DELETED --- --- style.css DELETED --- --- user.index DELETED --- --- user.item DELETED --- |
|
From: Anthony B. <ant...@us...> - 2001-07-23 03:55:22
|
Update of /cvsroot/roundup/roundup/templates/detectors In directory usw-pr-cvs1:/tmp/cvs-serv27102/templates/detectors Removed Files: __init__.py nosyreaction.py Log Message: byebye. --- __init__.py DELETED --- --- nosyreaction.py DELETED --- |
|
From: Anthony B. <ant...@us...> - 2001-07-23 03:55:22
|
Update of /cvsroot/roundup/roundup/templates In directory usw-pr-cvs1:/tmp/cvs-serv27102/templates Removed Files: __init__.py file.index issue.filter issue.index issue.item msg.index msg.item user.index user.item Log Message: byebye. --- __init__.py DELETED --- --- file.index DELETED --- --- issue.filter DELETED --- --- issue.index DELETED --- --- issue.item DELETED --- --- msg.index DELETED --- --- msg.item DELETED --- --- user.index DELETED --- --- user.item DELETED --- |
|
From: Anthony B. <ant...@us...> - 2001-07-23 03:52:55
|
Update of /cvsroot/roundup/roundup/roundup In directory usw-pr-cvs1:/tmp/cvs-serv26512 Added Files: .cvsignore Log Message: sssh. --- NEW FILE: .cvsignore --- *.pyc |
|
From: Anthony B. <ant...@us...> - 2001-07-23 03:50:49
|
Update of /cvsroot/roundup/roundup/roundup/templates/extended
In directory usw-pr-cvs1:/tmp/cvs-serv26128/templates/extended
Added Files:
__init__.py file.index issue.filter issue.index issue.item
msg.index msg.item style.css user.index user.item
Log Message:
moved templates to proper location
--- NEW FILE: __init__.py ---
# $Id: __init__.py,v 1.1 2001/07/23 03:50:46 anthonybaxter Exp $
MAIL_DOMAIN=MAILHOST=HTTP_HOST=None
HTTP_PORT=0
try:
from localconfig import *
except ImportError:
localconfig = None
import os
# roundup home is this package's directory
ROUNDUP_HOME=os.path.split(__file__)[0]
# The SMTP mail host that roundup will use to send mail
if not MAILHOST:
MAILHOST = 'localhost'
# The domain name used for email addresses.
if not MAIL_DOMAIN:
MAIL_DOMAIN = 'bizarsoftware.com.au'
# the next two are only used for the standalone HTTP server.
if not HTTP_HOST:
HTTP_HOST = ''
if not HTTP_PORT:
HTTP_PORT = 9080
# This is the directory that the database is going to be stored in
DATABASE = os.path.join(ROUNDUP_HOME, 'db')
# This is the directory that the HTML templates reside in
TEMPLATES = os.path.join(ROUNDUP_HOME, 'templates')
# The email address that mail to roundup should go to
ISSUE_TRACKER_EMAIL = 'issue_tracker@%s'%MAIL_DOMAIN
# The email address that roundup will complain to if it runs into trouble
ADMIN_EMAIL = 'roundup-admin@%s'%MAIL_DOMAIN
# Somewhere for roundup to log stuff internally sent to stdout or stderr
LOG = os.path.join(ROUNDUP_HOME, 'roundup.log')
from roundup import hyperdb, hyper_bsddb, roundupdb, cgi_client, mailgw
class Database(roundupdb.Database, hyper_bsddb.Database):
''' Creates a hybrid database from:
. the base Database class given in hyperdb (basic functionlity)
. the BSDDB implementation in hyperdb_bsddb
. the roundup extensions from roundupdb
'''
pass
Class = roundupdb.Class
class IssueClass(roundupdb.IssueClass):
''' issues need the email information
'''
ISSUE_TRACKER_EMAIL = ISSUE_TRACKER_EMAIL
ADMIN_EMAIL = ADMIN_EMAIL
MAILHOST = MAILHOST
FileClass = roundupdb.FileClass
class Client(cgi_client.Client):
''' derives basic mail gateway implementation from the standard module,
with any specific extensions
'''
TEMPLATES = TEMPLATES
pass
class MailGW(mailgw.MailGW):
''' derives basic mail gateway implementation from the standard module,
with any specific extensions
'''
ISSUE_TRACKER_EMAIL = ISSUE_TRACKER_EMAIL
ADMIN_EMAIL = ADMIN_EMAIL
MAILHOST = MAILHOST
def open(name=None):
''' as from the roundupdb method openDB
storagelocator must be the directory the __init__.py file is in
- os.path.split(__file__)[0] gives us that I think
'''
db = Database(DATABASE, name)
pri = Class(db, "priority", name=hyperdb.String(), order=hyperdb.String())
pri.setkey("name")
stat = Class(db, "status", name=hyperdb.String(), order=hyperdb.String())
stat.setkey("name")
Class(db, "keyword", name=hyperdb.String())
user = Class(db, "user", username=hyperdb.String(),
password=hyperdb.String(), address=hyperdb.String(),
realname=hyperdb.String(), phone=hyperdb.String(),
organisation=hyperdb.String())
user.setkey("username")
msg = FileClass(db, "msg", author=hyperdb.Link("user"),
recipients=hyperdb.Multilink("user"), date=hyperdb.Date(),
summary=hyperdb.String(), files=hyperdb.Multilink("file"))
file = FileClass(db, "file", name=hyperdb.String(), type=hyperdb.String())
# bugs and support calls etc
rate = Class(db, "rate", name=hyperdb.String(), order=hyperdb.String())
rate.setkey("name")
source = Class(db, "source", name=hyperdb.String(), order=hyperdb.String())
source.setkey("name")
platform = Class(db, "platform", name=hyperdb.String(), order=hyperdb.String())
platform.setkey("name")
product = Class(db, "product", name=hyperdb.String(), order=hyperdb.String())
product.setkey("name")
Class(db, "timelog", date=hyperdb.Date(), time=hyperdb.String(),
performedby=hyperdb.Link("user"), description=hyperdb.String())
issue = IssueClass(db, "issue", assignedto=hyperdb.Link("user"),
priority=hyperdb.Link("priority"), status=hyperdb.Link("status"),
rate=hyperdb.Link("rate"), source=hyperdb.Link("source"),
product=hyperdb.Link("product"), platform=hyperdb.Multilink("platform"),
version=hyperdb.String(),
timelog=hyperdb.Multilink("timelog"), customername=hyperdb.String())
issue.setkey('title')
import detectors
detectors.init(db)
return db
def init(adminpw):
''' as from the roundupdb method initDB
storagelocator must be the directory the __init__.py file is in
- os.path.split(__file__)[0] gives us that I think
'''
dbdir = os.path.join(DATABASE, 'files')
if not os.path.isdir(dbdir):
os.makedirs(dbdir)
db = open("admin")
db.clear()
pri = db.getclass('priority')
pri.create(name="fatal-bug", order="1")
pri.create(name="bug", order="2")
pri.create(name="usability", order="3")
pri.create(name="feature", order="4")
pri.create(name="support", order="5")
stat = db.getclass('status')
stat.create(name="unread", order="1")
stat.create(name="deferred", order="2")
stat.create(name="chatting", order="3")
stat.create(name="need-eg", order="4")
stat.create(name="in-progress", order="5")
stat.create(name="testing", order="6")
stat.create(name="done-cbb", order="7")
stat.create(name="resolved", order="8")
rate = db.getclass("rate")
rate.create(name='basic', order="1")
rate.create(name='premium', order="2")
rate.create(name='internal', order="3")
source = db.getclass("source")
source.create(name='phone', order="1")
source.create(name='e-mail', order="2")
source.create(name='internal', order="3")
source.create(name='internal-qa', order="4")
platform = db.getclass("platform")
platform.create(name='linux', order="1")
platform.create(name='windows', order="2")
platform.create(name='mac', order="3")
product = db.getclass("product")
product.create(name='Bizar Shop', order="1")
product.create(name='Bizar Shop Developer', order="2")
product.create(name='Bizar Shop Manual', order="3")
product.create(name='Bizar Shop Developer Manual', order="4")
user = db.getclass('user')
user.create(username="admin", password=adminpw, address=ADMIN_EMAIL)
db.close()
#
# $Log: __init__.py,v $
# Revision 1.1 2001/07/23 03:50:46 anthonybaxter
# moved templates to proper location
#
# Revision 1.2 2001/07/22 12:09:32 richard
# Final commit of Grande Splite
#
#
--- NEW FILE: file.index ---
<!-- $Id: file.index,v 1.1 2001/07/23 03:50:46 anthonybaxter Exp $-->
<tr>
<property name="name">
<td><display call="link('name')"></td>
</property>
<property name="type">
<td><display call="plain('type')"></td>
</property>
</tr>
--- NEW FILE: issue.filter ---
<!-- $Id: issue.filter,v 1.1 2001/07/23 03:50:46 anthonybaxter Exp $-->
<property name="title">
<tr><th width="1%" align="right" class="location-bar">Title</th>
<td><display call="field('title')"></td></tr>
</property>
<property name="status">
<tr><th width="1%" align="right" class="location-bar">Status</th>
<td><display call="checklist('status')"></td></tr>
</property>
<property name="priority">
<tr><th width="1%" align="right" class="location-bar">Priority</th>
<td><display call="checklist('priority')"></td></tr>
</property>
<property name="platform">
<tr><th width="1%" align="right" class="location-bar">Platform</th>
<td><display call="checklist('platform')"></td></tr>
</property>
<property name="product">
<tr><th width="1%" align="right" class="location-bar">Product</th>
<td><display call="checklist('product')"></td></tr>
</property>
<property name="version">
<tr><th width="1%" align="right" class="location-bar">Version</th>
<td><display call="field('version')"></td></tr>
</property>
<property name="source">
<tr><th width="1%" align="right" class="location-bar">Source</th>
<td><display call="checklist('source')"></td></tr>
</property>
<property name="assignedto">
<tr><th width="1%" align="right" class="location-bar">Assigned to</th>
<td><display call="checklist('assignedto')"></td></tr>
</property>
<property name="customername">
<tr><th width="1%" align="right" class="location-bar">Customer name</th>
<td><display call="field('customername')"></td></tr>
</property>
--- NEW FILE: issue.index ---
<!-- $Id: issue.index,v 1.1 2001/07/23 03:50:46 anthonybaxter Exp $-->
<tr>
<property name="activity">
<td valign="top"><display call="reldate('activity', pretty=1)"></td>
</property>
<property name="priority">
<td valign="top"><display call="plain('priority')"></td>
</property>
<property name="status">
<td valign="top"><display call="plain('status')"></td>
</property>
<property name="title">
<td valign="top"><display call="link('title')"></td>
</property>
<property name="platform">
<td valign="top"><display call="plain('platform')"></td>
</property>
<property name="product">
<td valign="top"><display call="plain('product')"></td>
</property>
<property name="version">
<td valign="top"><display call="plain('version')"></td>
</property>
<property name="source">
<td valign="top"><display call="plain('source')"></td>
</property>
<property name="assignedto">
<td valign="top"><display call="plain('assignedto')"></td>
</property>
<property name="customername">
<td valign="top"><display call="plain('customername')"></td>
</property>
</tr>
--- NEW FILE: issue.item ---
<!-- $Id: issue.item,v 1.1 2001/07/23 03:50:46 anthonybaxter Exp $-->
<table border=0 cellspacing=0 cellpadding=2>
<tr class="strong-header">
<td colspan=4>Item Information</td>
</td>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Title</span></td>
<td colspan=3 class="form-text"><display call="field('title', size=80)"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Product</span></td>
<td class="form-text" valign=middle><display call="menu('product')">
version:<display call="field('version', 5)"></td>
<td width=1% nowrap align=right><span class="form-label">Platform</span></td>
<td class="form-text" valign=middle><display call="checklist('platform')"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Created</span></td>
<td class="form-text"><display call="reldate('creation', pretty=1)">
(<display call="plain('creator')">)</td>
<td width=1% nowrap align=right><span class="form-label">Last activity</span></td>
<td class="form-text"><display call="reldate('activity', pretty=1)"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Priority</span></td>
<td class="form-text"><display call="field('priority')"></td>
<td width=1% nowrap align=right><span class="form-label">Source</span></td>
<td class="form-text"><display call="field('source')"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Status</span></td>
<td class="form-text"><display call="menu('status')"></td>
<td width=1% nowrap align=right><span class="form-label">Rate</span></td>
<td class="form-text"><display call="field('rate')"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Assigned To</span></td>
<td class="form-text"><display call="field('assignedto')"></td>
<td width=1% nowrap align=right><span class="form-label">Customer Name</span></td>
<td class="form-text"><display call="field('customername')"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Superseder</span></td>
<td class="form-text"><display call="field('superseder', size=40, showid=1)"></td>
<td width=1% nowrap align=right><span class="form-label">Nosy List</span></td>
<td class="form-text"><display call="field('nosy')"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Change Note</span></td>
<td colspan=3 class="form-text"><display call="note()"></td>
</tr>
<tr bgcolor="ffffea">
<td> </td>
<td colspan=3 class="form-text"><display call="submit()"></td>
</tr>
<property name="messages">
<tr class="strong-header">
<td colspan=4><b>Messages</b></td>
</tr>
<tr>
<td colspan=4><display call="list('messages')"></td>
</tr>
</property>
<property name="files">
<tr class="strong-header">
<td colspan=4><b>Files</b></td>
</tr>
<tr>
<td colspan=4><display call="list('files')"></td>
</tr>
</property>
</table>
--- NEW FILE: msg.index ---
<!-- $Id: msg.index,v 1.1 2001/07/23 03:50:46 anthonybaxter Exp $-->
<tr>
<property name="date">
<td><display call="link('date')"></td>
</property>
<property name="author">
<td><display call="plain('author')"></td>
</property>
<property name="summary">
<td><display call="plain('summary')"></td>
</property>
</tr>
--- NEW FILE: msg.item ---
<!-- $Id: msg.item,v 1.1 2001/07/23 03:50:46 anthonybaxter Exp $-->
<table border=0 cellspacing=0 cellpadding=2>
<tr class="strong-header">
<td colspan=2>Message Information</td>
</td>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Author</span></td>
<td class="form-text"><display call="plain('author')"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Recipients</span></td>
<td class="form-text"><display call="plain('recipients')"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Date</span></td>
<td class="form-text"><display call="plain('date')"></td>
</tr>
<tr bgcolor="ffeaff">
<td colspan=2 class="form-text">
<pre><display call="plain('content')"></pre>
</td>
</tr>
<property name="files">
<tr class="strong-header"><td colspan=2><b>Files</b></td></tr>
<tr><td colspan=2><display call="list('files')"></td></tr>
</property>
<tr class="strong-header"><td colspan=2><b>History</b></td><tr>
<tr><td colspan=2><display call="history()"></td></tr>
</table>
--- NEW FILE: style.css ---
h1 {
font-family: Verdana, Helvetica, sans-serif;
font-size: 18pt;
font-weight: bold;
}
h2 {
font-family: Verdana, Helvetica, sans-serif;
font-size: 16pt;
font-weight: bold;
}
h3 {
font-family: Verdana, Helvetica, sans-serif;
font-size: 12pt;
font-weight: bold;
}
a:hover {
font-family: Verdana, Helvetica, sans-serif;
text-decoration: underline;
color: #333333;
}
a:link {
font-family: Verdana, Helvetica, sans-serif;
text-decoration: none;
color: #000099;
}
a {
font-family: Verdana, Helvetica, sans-serif;
text-decoration: none;
color: #000099;
}
p {
font-family: Verdana, Helvetica, sans-serif;
font-size: 10pt;
color: #333333;
}
th {
font-family: Verdana, Helvetica, sans-serif;
font-weight: bold;
font-size: 10pt;
color: #333333;
}
.form-help {
font-family: Verdana, Helvetica, sans-serif;
font-size: 10pt;
color: #333333;
}
.std-text {
font-family: Verdana, Helvetica, sans-serif;
font-size: 10pt;
color: #333333;
}
.tab-small {
font-family: Verdana, Helvetica, sans-serif;
font-size: 8pt;
color: #333333;
}
.location-bar {
background-color: #efefef;
border: none;
}
.strong-header {
font-family: Verdana, Helvetica, sans-serif;
font-size: 12pt;
font-weight: bold;
background-color: #000000;
color: #ffffff;
}
.list-header {
background-color: #c0c0c0;
border: none;
}
.list-item {
font-family: Verdana, Helvetica, sans-serif;
font-size: 10pt;
}
.list-nav {
font-family: Verdana, Helvetica, sans-serif;
font-size: 10pt;
font-weight: bold;
}
.row-normal {
background-color: #ffffff;
border: none;
}
.row-hilite {
background-color: #efefef;
border: none;
}
.section-bar {
background-color: #c0c0c0;
border: none;
}
.system-msg {
font-family: Verdana, Helvetica, sans-serif;
font-size: 10pt;
background-color: #ffffff;
border: 1px solid #000000;
margin-bottom: 6px;
margin-top: 6px;
padding: 4px;
width: 100%;
color: #660033;
}
.form-title {
font-family: Verdana, Helvetica, sans-serif;
font-weight: bold;
font-size: 12pt;
color: #333333;
}
.form-label {
font-family: Verdana, Helvetica, sans-serif;
font-weight: bold;
font-size: 10pt;
color: #333333;
}
.form-optional {
font-family: Verdana, Helvetica, sans-serif;
font-weight: bold;
font-style: italic;
font-size: 10pt;
color: #333333;
}
.form-element {
font-family: Verdana, Helvetica, aans-serif;
font-size: 10pt;
color: #000000;
}
.form-text {
font-family: Verdana, Helvetica, sans-serif;
font-size: 10pt;
color: #333333;
}
.form-mono {
font-family: monospace;
font-size: 12px;
text-decoration: none;
}
--- NEW FILE: user.index ---
<!-- $Id: user.index,v 1.1 2001/07/23 03:50:46 anthonybaxter Exp $-->
<tr>
<property name="username">
<td><display call="link('username')"></td>
</property>
<property name="realname">
<td><display call="plain('realname')"></td>
</property>
<property name="organisation">
<td><display call="plain('organisation')"></td>
</property>
<property name="address">
<td><display call="plain('address')"></td>
</property>
<property name="phone">
<td><display call="plain('phone')"></td>
</property>
</tr>
--- NEW FILE: user.item ---
<!-- $Id: user.item,v 1.1 2001/07/23 03:50:46 anthonybaxter Exp $-->
<table border=0 cellspacing=0 cellpadding=2>
<tr class="strong-header">
<td colspan=2>Your Details</td>
</td>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Name</span></td>
<td class="form-text"><display call="field('realname', size=40)"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Login Name</span></td>
<td class="form-text"><display call="field('username', size=40)"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Login Password</span></td>
<td class="form-text"><display call="field('password', size=10)"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Phone</span></td>
<td class="form-text"><display call="field('phone', size=40)"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Organisation</span></td>
<td class="form-text"><display call="field('organisation', size=40)"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">E-mail address</span></td>
<td class="form-text"><display call="field('address', size=40)"></td>
</tr>
<tr bgcolor="ffffea">
<td> </td>
<td class="form-text"><display call="submit()"></td>
</tr>
<tr class="strong-header">
<td colspan=2><b>History</b></td>
</tr>
<tr>
<td colspan=2><display call="history()"></td>
</tr>
</table>
|
|
From: Anthony B. <ant...@us...> - 2001-07-23 03:50:49
|
Update of /cvsroot/roundup/roundup/roundup/templates/extended/detectors
In directory usw-pr-cvs1:/tmp/cvs-serv26128/templates/extended/detectors
Added Files:
__init__.py nosyreaction.py
Log Message:
moved templates to proper location
--- NEW FILE: __init__.py ---
#$Id: __init__.py,v 1.1 2001/07/23 03:50:47 anthonybaxter Exp $
def init(db):
''' execute the init functions of all the modules in this directory
'''
import os, sys
this_dir = os.path.split(__file__)[0]
try:
sys.path.insert(0, this_dir)
for file in os.listdir(this_dir):
file, ext = os.path.splitext(file)
if file == '__init__': continue
if ext in ('.py', '.pyc'):
module = __import__(file)
module.init(db)
finally:
del sys.path[0]
#
#$Log: __init__.py,v $
#Revision 1.1 2001/07/23 03:50:47 anthonybaxter
#moved templates to proper location
#
#Revision 1.1 2001/07/22 12:09:32 richard
#Final commit of Grande Splite
#
#
--- NEW FILE: nosyreaction.py ---
#$Id: nosyreaction.py,v 1.1 2001/07/23 03:50:47 anthonybaxter Exp $
def nosyreaction(db, cl, nodeid, oldvalues):
''' A standard detector is provided that watches for additions to the
"messages" property.
When a new message is added, the detector sends it to all the users on
the "nosy" list for the issue that are not already on the "recipients"
list of the message.
Those users are then appended to the "recipients" property on the
message, so multiple copies of a message are never sent to the same
user.
The journal recorded by the hyperdatabase on the "recipients" property
then provides a log of when the message was sent to whom.
'''
messages = []
if oldvalues is None:
# the action was a create, so use all the messages in the create
messages = cl.get(nodeid, 'messages')
elif oldvalues.has_key('messages'):
# the action was a set (so adding new messages to an existing issue)
m = {}
for msgid in oldvalues['messages']:
m[msgid] = 1
messages = []
# figure which of the messages now on the issue weren't there before
for msgid in cl.get(nodeid, 'messages'):
if not m.has_key(msgid):
messages.append(msgid)
if not messages:
return
# send a copy to the nosy list
for msgid in messages:
cl.sendmessage(nodeid, msgid)
# update the nosy list with the recipients from the new messages
nosy = cl.get(nodeid, 'nosy')
n = {}
for nosyid in nosy: n[nosyid] = 1
change = 0
# but don't add admin to the nosy list
for msgid in messages:
for recipid in db.msg.get(msgid, 'recipients'):
if recipid != '1' and not n.has_key(recipid):
change = 1
nosy.append(recipid)
authid = db.msg.get(msgid, 'author')
if authid != '1' and not n.has_key(authid):
change = 1
nosy.append(authid)
if change:
cl.set(nodeid, nosy=nosy)
def init(db):
db.issue.react('create', nosyreaction)
db.issue.react('set', nosyreaction)
#
#$Log: nosyreaction.py,v $
#Revision 1.1 2001/07/23 03:50:47 anthonybaxter
#moved templates to proper location
#
#Revision 1.1 2001/07/22 12:09:32 richard
#Final commit of Grande Splite
#
#
|
|
From: Richard J. <ri...@us...> - 2001-07-23 03:46:50
|
Update of /cvsroot/roundup/roundup
In directory usw-pr-cvs1:/tmp/cvs-serv25362
Added Files:
roundup-admin roundup-mailgw roundup-server
Log Message:
moving the bin files to facilitate out-of-the-boxness
--- NEW FILE: roundup-admin ---
#! /usr/bin/python
# $Id: roundup-admin,v 1.1 2001/07/23 03:46:48 richard Exp $
import sys
if int(sys.version[0]) < 2:
print 'Roundup requires python 2.0 or later.'
sys.exit(1)
import string, os, getpass
from roundup import date, roundupdb, init
def determineLogin(instance, argv, n = 2):
name = password = ''
if argv[2] == '-u':
l = argv[3].split(':')
name = l[0]
if len(l) > 1:
password = l[1]
n = 4
elif os.environ.has_key('ROUNDUP_LOGIN'):
l = os.environ['ROUNDUP_LOGIN'].split(':')
name = l[0]
if len(l) > 1:
password = l[1]
while not name:
name = raw_input('Login name: ')
while not password:
password = getpass.getpass(' password: ')
# TODO use the password...
return n, instance.open(name)
def usage(message=''):
if message: message = 'Problem: '+message+'\n'
print '''%sUsage:
roundup [-i instance] init template
-- initialise the database
roundup [-i instance] spec classname
-- show the properties for a classname
roundup [-i instance] create [-u login] classname propname=value ...
-- create a new entry of a given class
roundup [-i instance] list [-c] classname
-- list the instances of a class
roundup [-i instance] history [-c] designator
-- show the history entries of a designator
roundup [-i instance] get [-c] designator[,designator,...] propname
-- get the given property of one or more designator(s)
roundup [-i instance] set [-u login] designator[,designator,...] propname=value ...
-- set the given property of one or more designator(s)
roundup [-i instance] find [-c] classname propname=value ...
-- find the class instances with a given property
roundup [-i instance] retire designator[,designator,...]
-- "retire" a designator
roundup help
-- this help
roundup morehelp
-- even more detailed help
'''%message
def moreusage(message=''):
usage(message)
print '''
All commands (except help) require an instance specifier. This is just the path
to the roundup instance you're working with. It may be specified in the environment
variable ROUNDUP_INSTANCE or on the command line as "-i instance".
A designator is a classname and a nodeid concatenated, eg. bug1, user10, ...
Property values are represented as strings in command arguments and in the
printed results:
. Strings are, well, strings.
. Date values are printed in the full date format in the local time zone, and
accepted in the full format or any of the partial formats explained below.
. Link values are printed as node designators. When given as an argument,
node designators and key strings are both accepted.
. Multilink values are printed as lists of node designators joined by commas.
When given as an argument, node designators and key strings are both
accepted; an empty string, a single node, or a list of nodes joined by
commas is accepted.
When multiple nodes are specified to the roundup get or roundup set
commands, the specified properties are retrieved or set on all the listed
nodes.
When multiple results are returned by the roundup get or roundup find
commands, they are printed one per line (default) or joined by commas (with
the -c) option.
Where the command changes data, a login name/password is required. The
login may be specified as either "name" or "name:password".
. ROUNDUP_LOGIN environment variable
. the -u command-line option
If either the name or password is not supplied, they are obtained from the
command-line.
Date format examples:
"2000-04-17.03:45" means <Date 2000-04-17.08:45:00>
"2000-04-17" means <Date 2000-04-17.00:00:00>
"01-25" means <Date yyyy-01-25.00:00:00>
"08-13.22:13" means <Date yyyy-08-14.03:13:00>
"11-07.09:32:43" means <Date yyyy-11-07.14:32:43>
"14:25" means <Date yyyy-mm-dd.19:25:00>
"8:47:11" means <Date yyyy-mm-dd.13:47:11>
"." means "right now"
'''
def main():
argv = sys.argv
if len(argv) == 1:
usage('No command specified')
return 1
# handle help now
if argv[1] == 'help':
usage()
return 0
if argv[1] == 'morehelp':
moreusage()
return 0
# figure the instance home
n = 1
if argv[1] == '-i':
if len(argv) == 2:
usage()
return 1
instance_home = argv[2]
n = 3
else:
instance_home = os.environ.get('ROUNDUP_INSTANCE', '')
if not instance_home:
usage('No instance home specified')
return 1
# now figure the command
command = argv[n]
n = n + 1
if command == 'init':
adminpw = ''
confirm = 'x'
while adminpw != confirm:
adminpw = getpass.getpass('Admin Password:')
confirm = getpass.getpass(' Confirm:')
init.init(instance_home, argv[n], adminpw)
return 0
# get the instance
path, instance = os.path.split(instance_home)
sys.path.insert(0, path)
try:
instance = __import__(instance)
finally:
del sys.path[0]
if command == 'get':
db = instance.open()
designators = string.split(argv[n], ',')
propname = argv[n+1]
# TODO: handle the -c option
for designator in designators:
classname, nodeid = roundupdb.splitDesignator(designator)
print db.getclass(classname).get(nodeid, propname)
elif command == 'set':
n, db = determineLogin(instance, argv, n)
designators = string.split(argv[n], ',')
props = {}
for prop in argv[n+1:]:
key, value = prop.split('=')
props[key] = value
for designator in designators:
classname, nodeid = roundupdb.splitDesignator(designator)
cl = db.getclass(classname)
properties = cl.getprops()
for key, value in props.items():
type = properties[key]
if type.isStringType:
continue
elif type.isDateType:
props[key] = date.Date(value)
elif type.isIntervalType:
props[key] = date.Interval(value)
elif type.isLinkType:
props[key] = value
elif type.isMultilinkType:
props[key] = value.split(',')
apply(cl.set, (nodeid, ), props)
elif command == 'find':
db = instance.open()
classname = argv[n]
cl = db.getclass(classname)
# look up the linked-to class and get the nodeid that has the value
propname, value = argv[n+1:].split('=')
propcl = cl[propname].classname
nodeid = propcl.lookup(value)
# now do the find
# TODO: handle the -c option
print cl.find(propname, nodeid)
elif command == 'spec':
db = instance.open()
classname = argv[n]
cl = db.getclass(classname)
for key, value in cl.properties.items():
print '%s: %s'%(key, value)
elif command == 'create':
n, db = determineLogin(instance, argv, n)
classname = argv[n]
cl = db.getclass(classname)
props = {}
properties = cl.getprops()
for prop in argv[n+1:]:
key, value = prop.split('=')
type = properties[key]
if type.isStringType:
props[key] = value
elif type.isDateType:
props[key] = date.Date(value)
elif type.isIntervalType:
props[key] = date.Interval(value)
elif type.isLinkType:
props[key] = value
elif type.isMultilinkType:
props[key] = value.split(',')
print apply(cl.create, (), props)
elif command == 'list':
db = instance.open()
classname = argv[n]
cl = db.getclass(classname)
key = cl.getkey() or cl.properties.keys()[0]
# TODO: handle the -c option
for nodeid in cl.list():
value = cl.get(nodeid, key)
print "%4s: %s"%(nodeid, value)
elif command == 'history':
db = instance.open()
classname, nodeid = roundupdb.splitDesignator(argv[n])
# TODO: handle the -c option
print db.getclass(classname).history(nodeid)
elif command == 'retire':
n, db = determineLogin(instance, argv, n)
designators = string.split(argv[n], ',')
for designator in designators:
classname, nodeid = roundupdb.splitDesignator(designator)
db.getclass(classname).retire(nodeid)
else:
print "Unknown command '%s'"%command
usage()
return 1
db.close()
return 0
if __name__ == '__main__':
sys.exit(main())
#
# $Log: roundup-admin,v $
# Revision 1.1 2001/07/23 03:46:48 richard
# moving the bin files to facilitate out-of-the-boxness
#
# Revision 1.1 2001/07/22 11:15:45 richard
# More Grande Splite stuff
#
#
--- NEW FILE: roundup-mailgw ---
#! /usr/bin/python
# $ID: $
import sys
if int(sys.version[0]) < 2:
print "Roundup requires Python 2.0 or newer."
sys.exit(1)
# figure the instance home
import os
if len(sys.argv) > 1:
instance_home = sys.argv[1]
else:
instance_home = os.environ.get('ROUNDUP_INSTANCE', '')
if not instance_home:
print 'No instance home specified'
sys.exit(1)
# get the instance
path, instance = os.path.split(instance_home)
sys.path.insert(0, path)
instance = __import__(instance)
sys.path[0]
# invokde the mail handler
db = instance.open('admin')
handler = instance.MailGW(db)
handler.main(sys.stdin)
#
# $Log: roundup-mailgw,v $
# Revision 1.1 2001/07/23 03:46:48 richard
# moving the bin files to facilitate out-of-the-boxness
#
# Revision 1.1 2001/07/22 11:15:45 richard
# More Grande Splite stuff
#
#
--- NEW FILE: roundup-server ---
#!/usr/bin/python
""" HTTP Server that serves roundup.
Stolen from CGIHTTPServer
$Id: roundup-server,v 1.1 2001/07/23 03:46:48 richard Exp $
"""
import sys
if int(sys.version[0]) < 2:
print "Content-Type: text/plain\n"
print "Roundup requires Python 2.0 or newer."
__version__ = "0.1"
__all__ = ["RoundupRequestHandler"]
import os, urllib, StringIO, traceback, cgi, binascii, string
import BaseHTTPServer
import SimpleHTTPServer
# Roundup modules of use here
from roundup import cgitb, cgi_client
# These are here temporarily until I get a real reload system in place
from roundup import date, hyperdb, hyper_bsddb, roundupdb, htmltemplate
#
## Configuration
#
# This indicates where the Roundup instance lives
ROUNDUPS = {
'test': '/tmp/roundup_test',
}
# Where to log debugging information to. Use an instance of DevNull if you
# don't want to log anywhere.
# TODO: actually use this stuff
#class DevNull:
# def write(self, info):
# pass
#LOG = open('/var/log/roundup.cgi.log', 'a')
#LOG = DevNull()
#
## end configuration
#
class RoundupRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
def send_head(self):
"""Version of send_head that support CGI scripts"""
# TODO: actually do the HEAD ...
return self.run_cgi()
def run_cgi(self):
""" Execute the CGI command. Wrap an innner call in an error
handler so all errors can be caught.
"""
save_stdin = sys.stdin
sys.stdin = self.rfile
try:
self.inner_run_cgi()
except cgi_client.Unauthorised:
self.wfile.write('Content-Type: text/html\n')
self.wfile.write('Status: 403\n')
self.wfile.write('Unauthorised')
except:
try:
reload(cgitb)
self.wfile.write("Content-Type: text/html\n\n")
self.wfile.write(cgitb.breaker())
self.wfile.write(cgitb.html())
except:
self.wfile.write("Content-Type: text/html\n\n")
self.wfile.write("<pre>")
s = StringIO.StringIO()
traceback.print_exc(None, s)
self.wfile.write(cgi.escape(s.getvalue()))
self.wfile.write("</pre>\n")
sys.stdin = save_stdin
def inner_run_cgi(self):
''' This is the inner part of the CGI handling
'''
rest = self.path
i = rest.rfind('?')
if i >= 0:
rest, query = rest[:i], rest[i+1:]
else:
query = ''
# figure the instance
if rest == '/':
raise ValueError, 'No instance specified'
l_path = string.split(rest, '/')
instance = urllib.unquote(l_path[1])
if ROUNDUPS.has_key(instance):
instance_home = ROUNDUPS[instance]
module_path, instance = os.path.split(instance_home)
sys.path.insert(0, module_path)
try:
instance = __import__(instance)
finally:
del sys.path[0]
else:
raise ValueError, 'No such instance "%s"'%instance
# figure out what the rest of the path is
if len(l_path) > 2:
rest = '/'.join(l_path[2:])
else:
rest = '/'
# Set up the CGI environment
env = {}
env['REQUEST_METHOD'] = self.command
env['PATH_INFO'] = urllib.unquote(rest)
if query:
env['QUERY_STRING'] = query
host = self.address_string()
if self.headers.typeheader is None:
env['CONTENT_TYPE'] = self.headers.type
else:
env['CONTENT_TYPE'] = self.headers.typeheader
length = self.headers.getheader('content-length')
if length:
env['CONTENT_LENGTH'] = length
co = filter(None, self.headers.getheaders('cookie'))
if co:
env['HTTP_COOKIE'] = ', '.join(co)
env['SCRIPT_NAME'] = ''
env['SERVER_NAME'] = self.server.server_name
env['SERVER_PORT'] = str(self.server.server_port)
decoded_query = query.replace('+', ' ')
# if root, setuid to nobody
# TODO why isn't this done much earlier? - say, in main()?
if not os.getuid():
nobody = nobody_uid()
os.setuid(nobody)
# reload all modules
# TODO check for file timestamp changes and dependencies
reload(date)
reload(hyperdb)
reload(roundupdb)
reload(htmltemplate)
reload(cgi_client)
sys.path.insert(0, module_path)
try:
reload(instance)
finally:
del sys.path[0]
# initialise the roundupdb, check for auth
db = instance.open('admin')
message = 'Unauthorised'
auth = self.headers.getheader('authorization')
if auth:
l = binascii.a2b_base64(auth.split(' ')[1]).split(':')
user = l[0]
password = None
if len(l) > 1:
password = l[1]
try:
uid = db.user.lookup(user)
except KeyError:
auth = None
message = 'Username not recognised'
else:
if password != db.user.get(uid, 'password'):
message = 'Incorrect password'
auth = None
db.close()
del db
if not auth:
self.send_response(401)
self.send_header('Content-Type', 'text/html')
self.send_header('WWW-Authenticate', 'basic realm="Roundup"')
self.end_headers()
self.wfile.write(message)
return
self.send_response(200, "Script output follows")
# do the roundup thang
db = instance.open(user)
client = instance.Client(self.wfile, db, env, user)
client.main()
do_POST = run_cgi
nobody = None
def nobody_uid():
"""Internal routine to get nobody's uid"""
global nobody
if nobody:
return nobody
try:
import pwd
except ImportError:
return -1
try:
nobody = pwd.getpwnam('nobody')[2]
except KeyError:
nobody = 1 + max(map(lambda x: x[2], pwd.getpwall()))
return nobody
if __name__ == '__main__':
# TODO make this configurable again? command-line seems ok to me...
address = ('', 8080)
httpd = BaseHTTPServer.HTTPServer(address, RoundupRequestHandler)
print 'Roundup server started on', address
httpd.serve_forever()
#
# $Log: roundup-server,v $
# Revision 1.1 2001/07/23 03:46:48 richard
# moving the bin files to facilitate out-of-the-boxness
#
# Revision 1.1 2001/07/22 11:15:45 richard
# More Grande Splite stuff
#
#
|
|
From: Richard J. <ri...@us...> - 2001-07-23 03:46:25
|
Update of /cvsroot/roundup/roundup/bin In directory usw-pr-cvs1:/tmp/cvs-serv25253/bin Removed Files: roundup roundup-mailgw roundup-server Log Message: moving the bin files to facilitate out-of-the-boxness --- roundup DELETED --- --- roundup-mailgw DELETED --- --- roundup-server DELETED --- |
|
From: Anthony B. <ant...@us...> - 2001-07-23 03:45:24
|
Update of /cvsroot/roundup/roundup/roundup/templates/extended/detectors In directory usw-pr-cvs1:/tmp/cvs-serv25105/detectors Log Message: Directory /cvsroot/roundup/roundup/roundup/templates/extended/detectors added to the repository |
|
From: Anthony B. <ant...@us...> - 2001-07-23 03:43:07
|
Update of /cvsroot/roundup/roundup/roundup/templates/extended In directory usw-pr-cvs1:/tmp/cvs-serv24671/extended Log Message: Directory /cvsroot/roundup/roundup/roundup/templates/extended added to the repository |
Update of /cvsroot/roundup/roundup/templates/templates
In directory usw-pr-cvs1:/tmp/cvs-serv2539/roundup/templates/extended/templates
Added Files:
file.index issue.filter issue.index issue.item msg.index
msg.item style.css user.index user.item
Log Message:
Final commit of Grande Splite
--- NEW FILE: file.index ---
<!-- $Id: file.index,v 1.1 2001/07/22 12:09:32 richard Exp $-->
<tr>
<property name="name">
<td><display call="link('name')"></td>
</property>
<property name="type">
<td><display call="plain('type')"></td>
</property>
</tr>
--- NEW FILE: issue.filter ---
<!-- $Id: issue.filter,v 1.1 2001/07/22 12:09:32 richard Exp $-->
<property name="title">
<tr><th width="1%" align="right" class="location-bar">Title</th>
<td><display call="field('title')"></td></tr>
</property>
<property name="status">
<tr><th width="1%" align="right" class="location-bar">Status</th>
<td><display call="checklist('status')"></td></tr>
</property>
<property name="priority">
<tr><th width="1%" align="right" class="location-bar">Priority</th>
<td><display call="checklist('priority')"></td></tr>
</property>
<property name="platform">
<tr><th width="1%" align="right" class="location-bar">Platform</th>
<td><display call="checklist('platform')"></td></tr>
</property>
<property name="product">
<tr><th width="1%" align="right" class="location-bar">Product</th>
<td><display call="checklist('product')"></td></tr>
</property>
<property name="version">
<tr><th width="1%" align="right" class="location-bar">Version</th>
<td><display call="field('version')"></td></tr>
</property>
<property name="source">
<tr><th width="1%" align="right" class="location-bar">Source</th>
<td><display call="checklist('source')"></td></tr>
</property>
<property name="assignedto">
<tr><th width="1%" align="right" class="location-bar">Assigned to</th>
<td><display call="checklist('assignedto')"></td></tr>
</property>
<property name="customername">
<tr><th width="1%" align="right" class="location-bar">Customer name</th>
<td><display call="field('customername')"></td></tr>
</property>
--- NEW FILE: issue.index ---
<!-- $Id: issue.index,v 1.1 2001/07/22 12:09:32 richard Exp $-->
<tr>
<property name="activity">
<td valign="top"><display call="reldate('activity', pretty=1)"></td>
</property>
<property name="priority">
<td valign="top"><display call="plain('priority')"></td>
</property>
<property name="status">
<td valign="top"><display call="plain('status')"></td>
</property>
<property name="title">
<td valign="top"><display call="link('title')"></td>
</property>
<property name="platform">
<td valign="top"><display call="plain('platform')"></td>
</property>
<property name="product">
<td valign="top"><display call="plain('product')"></td>
</property>
<property name="version">
<td valign="top"><display call="plain('version')"></td>
</property>
<property name="source">
<td valign="top"><display call="plain('source')"></td>
</property>
<property name="assignedto">
<td valign="top"><display call="plain('assignedto')"></td>
</property>
<property name="customername">
<td valign="top"><display call="plain('customername')"></td>
</property>
</tr>
--- NEW FILE: issue.item ---
<!-- $Id: issue.item,v 1.1 2001/07/22 12:09:32 richard Exp $-->
<table border=0 cellspacing=0 cellpadding=2>
<tr class="strong-header">
<td colspan=4>Item Information</td>
</td>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Title</span></td>
<td colspan=3 class="form-text"><display call="field('title', size=80)"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Product</span></td>
<td class="form-text" valign=middle><display call="menu('product')">
version:<display call="field('version', 5)"></td>
<td width=1% nowrap align=right><span class="form-label">Platform</span></td>
<td class="form-text" valign=middle><display call="checklist('platform')"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Created</span></td>
<td class="form-text"><display call="reldate('creation', pretty=1)">
(<display call="plain('creator')">)</td>
<td width=1% nowrap align=right><span class="form-label">Last activity</span></td>
<td class="form-text"><display call="reldate('activity', pretty=1)"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Priority</span></td>
<td class="form-text"><display call="field('priority')"></td>
<td width=1% nowrap align=right><span class="form-label">Source</span></td>
<td class="form-text"><display call="field('source')"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Status</span></td>
<td class="form-text"><display call="menu('status')"></td>
<td width=1% nowrap align=right><span class="form-label">Rate</span></td>
<td class="form-text"><display call="field('rate')"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Assigned To</span></td>
<td class="form-text"><display call="field('assignedto')"></td>
<td width=1% nowrap align=right><span class="form-label">Customer Name</span></td>
<td class="form-text"><display call="field('customername')"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Superseder</span></td>
<td class="form-text"><display call="field('superseder', size=40, showid=1)"></td>
<td width=1% nowrap align=right><span class="form-label">Nosy List</span></td>
<td class="form-text"><display call="field('nosy')"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Change Note</span></td>
<td colspan=3 class="form-text"><display call="note()"></td>
</tr>
<tr bgcolor="ffffea">
<td> </td>
<td colspan=3 class="form-text"><display call="submit()"></td>
</tr>
<property name="messages">
<tr class="strong-header">
<td colspan=4><b>Messages</b></td>
</tr>
<tr>
<td colspan=4><display call="list('messages')"></td>
</tr>
</property>
<property name="files">
<tr class="strong-header">
<td colspan=4><b>Files</b></td>
</tr>
<tr>
<td colspan=4><display call="list('files')"></td>
</tr>
</property>
</table>
--- NEW FILE: msg.index ---
<!-- $Id: msg.index,v 1.1 2001/07/22 12:09:32 richard Exp $-->
<tr>
<property name="date">
<td><display call="link('date')"></td>
</property>
<property name="author">
<td><display call="plain('author')"></td>
</property>
<property name="summary">
<td><display call="plain('summary')"></td>
</property>
</tr>
--- NEW FILE: msg.item ---
<!-- $Id: msg.item,v 1.1 2001/07/22 12:09:32 richard Exp $-->
<table border=0 cellspacing=0 cellpadding=2>
<tr class="strong-header">
<td colspan=2>Message Information</td>
</td>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Author</span></td>
<td class="form-text"><display call="plain('author')"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Recipients</span></td>
<td class="form-text"><display call="plain('recipients')"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Date</span></td>
<td class="form-text"><display call="plain('date')"></td>
</tr>
<tr bgcolor="ffeaff">
<td colspan=2 class="form-text">
<pre><display call="plain('content')"></pre>
</td>
</tr>
<property name="files">
<tr class="strong-header"><td colspan=2><b>Files</b></td></tr>
<tr><td colspan=2><display call="list('files')"></td></tr>
</property>
<tr class="strong-header"><td colspan=2><b>History</b></td><tr>
<tr><td colspan=2><display call="history()"></td></tr>
</table>
--- NEW FILE: style.css ---
h1 {
font-family: Verdana, Helvetica, sans-serif;
font-size: 18pt;
font-weight: bold;
}
h2 {
font-family: Verdana, Helvetica, sans-serif;
font-size: 16pt;
font-weight: bold;
}
h3 {
font-family: Verdana, Helvetica, sans-serif;
font-size: 12pt;
font-weight: bold;
}
a:hover {
font-family: Verdana, Helvetica, sans-serif;
text-decoration: underline;
color: #333333;
}
a:link {
font-family: Verdana, Helvetica, sans-serif;
text-decoration: none;
color: #000099;
}
a {
font-family: Verdana, Helvetica, sans-serif;
text-decoration: none;
color: #000099;
}
p {
font-family: Verdana, Helvetica, sans-serif;
font-size: 10pt;
color: #333333;
}
th {
font-family: Verdana, Helvetica, sans-serif;
font-weight: bold;
font-size: 10pt;
color: #333333;
}
.form-help {
font-family: Verdana, Helvetica, sans-serif;
font-size: 10pt;
color: #333333;
}
.std-text {
font-family: Verdana, Helvetica, sans-serif;
font-size: 10pt;
color: #333333;
}
.tab-small {
font-family: Verdana, Helvetica, sans-serif;
font-size: 8pt;
color: #333333;
}
.location-bar {
background-color: #efefef;
border: none;
}
.strong-header {
font-family: Verdana, Helvetica, sans-serif;
font-size: 12pt;
font-weight: bold;
background-color: #000000;
color: #ffffff;
}
.list-header {
background-color: #c0c0c0;
border: none;
}
.list-item {
font-family: Verdana, Helvetica, sans-serif;
font-size: 10pt;
}
.list-nav {
font-family: Verdana, Helvetica, sans-serif;
font-size: 10pt;
font-weight: bold;
}
.row-normal {
background-color: #ffffff;
border: none;
}
.row-hilite {
background-color: #efefef;
border: none;
}
.section-bar {
background-color: #c0c0c0;
border: none;
}
.system-msg {
font-family: Verdana, Helvetica, sans-serif;
font-size: 10pt;
background-color: #ffffff;
border: 1px solid #000000;
margin-bottom: 6px;
margin-top: 6px;
padding: 4px;
width: 100%;
color: #660033;
}
.form-title {
font-family: Verdana, Helvetica, sans-serif;
font-weight: bold;
font-size: 12pt;
color: #333333;
}
.form-label {
font-family: Verdana, Helvetica, sans-serif;
font-weight: bold;
font-size: 10pt;
color: #333333;
}
.form-optional {
font-family: Verdana, Helvetica, sans-serif;
font-weight: bold;
font-style: italic;
font-size: 10pt;
color: #333333;
}
.form-element {
font-family: Verdana, Helvetica, aans-serif;
font-size: 10pt;
color: #000000;
}
.form-text {
font-family: Verdana, Helvetica, sans-serif;
font-size: 10pt;
color: #333333;
}
.form-mono {
font-family: monospace;
font-size: 12px;
text-decoration: none;
}
--- NEW FILE: user.index ---
<!-- $Id: user.index,v 1.1 2001/07/22 12:09:32 richard Exp $-->
<tr>
<property name="username">
<td><display call="link('username')"></td>
</property>
<property name="realname">
<td><display call="plain('realname')"></td>
</property>
<property name="organisation">
<td><display call="plain('organisation')"></td>
</property>
<property name="address">
<td><display call="plain('address')"></td>
</property>
<property name="phone">
<td><display call="plain('phone')"></td>
</property>
</tr>
--- NEW FILE: user.item ---
<!-- $Id: user.item,v 1.1 2001/07/22 12:09:32 richard Exp $-->
<table border=0 cellspacing=0 cellpadding=2>
<tr class="strong-header">
<td colspan=2>Your Details</td>
</td>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Name</span></td>
<td class="form-text"><display call="field('realname', size=40)"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Login Name</span></td>
<td class="form-text"><display call="field('username', size=40)"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Login Password</span></td>
<td class="form-text"><display call="field('password', size=10)"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Phone</span></td>
<td class="form-text"><display call="field('phone', size=40)"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">Organisation</span></td>
<td class="form-text"><display call="field('organisation', size=40)"></td>
</tr>
<tr bgcolor="ffffea">
<td width=1% nowrap align=right><span class="form-label">E-mail address</span></td>
<td class="form-text"><display call="field('address', size=40)"></td>
</tr>
<tr bgcolor="ffffea">
<td> </td>
<td class="form-text"><display call="submit()"></td>
</tr>
<tr class="strong-header">
<td colspan=2><b>History</b></td>
</tr>
<tr>
<td colspan=2><display call="history()"></td>
</tr>
</table>
|
|
From: Richard J. <ri...@us...> - 2001-07-22 12:09:35
|
Update of /cvsroot/roundup/roundup/templates/detectors
In directory usw-pr-cvs1:/tmp/cvs-serv2539/roundup/templates/extended/detectors
Added Files:
__init__.py nosyreaction.py
Log Message:
Final commit of Grande Splite
--- NEW FILE: __init__.py ---
#$Id: __init__.py,v 1.1 2001/07/22 12:09:32 richard Exp $
def init(db):
''' execute the init functions of all the modules in this directory
'''
import os, sys
this_dir = os.path.split(__file__)[0]
try:
sys.path.insert(0, this_dir)
for file in os.listdir(this_dir):
file, ext = os.path.splitext(file)
if file == '__init__': continue
if ext in ('.py', '.pyc'):
module = __import__(file)
module.init(db)
finally:
del sys.path[0]
#
#$Log: __init__.py,v $
#Revision 1.1 2001/07/22 12:09:32 richard
#Final commit of Grande Splite
#
#
--- NEW FILE: nosyreaction.py ---
#$Id: nosyreaction.py,v 1.1 2001/07/22 12:09:32 richard Exp $
def nosyreaction(db, cl, nodeid, oldvalues):
''' A standard detector is provided that watches for additions to the
"messages" property.
When a new message is added, the detector sends it to all the users on
the "nosy" list for the issue that are not already on the "recipients"
list of the message.
Those users are then appended to the "recipients" property on the
message, so multiple copies of a message are never sent to the same
user.
The journal recorded by the hyperdatabase on the "recipients" property
then provides a log of when the message was sent to whom.
'''
messages = []
if oldvalues is None:
# the action was a create, so use all the messages in the create
messages = cl.get(nodeid, 'messages')
elif oldvalues.has_key('messages'):
# the action was a set (so adding new messages to an existing issue)
m = {}
for msgid in oldvalues['messages']:
m[msgid] = 1
messages = []
# figure which of the messages now on the issue weren't there before
for msgid in cl.get(nodeid, 'messages'):
if not m.has_key(msgid):
messages.append(msgid)
if not messages:
return
# send a copy to the nosy list
for msgid in messages:
cl.sendmessage(nodeid, msgid)
# update the nosy list with the recipients from the new messages
nosy = cl.get(nodeid, 'nosy')
n = {}
for nosyid in nosy: n[nosyid] = 1
change = 0
# but don't add admin to the nosy list
for msgid in messages:
for recipid in db.msg.get(msgid, 'recipients'):
if recipid != '1' and not n.has_key(recipid):
change = 1
nosy.append(recipid)
authid = db.msg.get(msgid, 'author')
if authid != '1' and not n.has_key(authid):
change = 1
nosy.append(authid)
if change:
cl.set(nodeid, nosy=nosy)
def init(db):
db.issue.react('create', nosyreaction)
db.issue.react('set', nosyreaction)
#
#$Log: nosyreaction.py,v $
#Revision 1.1 2001/07/22 12:09:32 richard
#Final commit of Grande Splite
#
#
|
Update of /cvsroot/roundup/roundup/roundup
In directory usw-pr-cvs1:/tmp/cvs-serv2539/roundup
Modified Files:
__init__.py cgi_client.py cgitb.py date.py htmltemplate.py
hyper_bsddb.py hyperdb.py init.py mailgw.py roundupdb.py
Log Message:
Final commit of Grande Splite
Index: __init__.py
===================================================================
RCS file: /cvsroot/roundup/roundup/roundup/__init__.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -r1.1 -r1.2
*** __init__.py 2001/07/22 11:58:35 1.1
--- __init__.py 2001/07/22 12:09:32 1.2
***************
*** 0 ****
--- 1,9 ----
+ # $Id$
+
+
+ #
+ # $Log$
+ # Revision 1.2 2001/07/22 12:09:32 richard
+ # Final commit of Grande Splite
+ #
+ #
Index: cgi_client.py
===================================================================
RCS file: /cvsroot/roundup/roundup/roundup/cgi_client.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -r1.1 -r1.2
*** cgi_client.py 2001/07/22 11:58:35 1.1
--- cgi_client.py 2001/07/22 12:09:32 1.2
***************
*** 490,516 ****
#
# $Log$
# Revision 1.1 2001/07/22 11:58:35 richard
# More Grande Splite
#
- # Revision 1.7 2001/07/20 07:35:55 richard
- # largish changes as a start of splitting off bits and pieces to allow more
- # flexible installation / database back-ends
- #
- # Revision 1.6 2001/07/20 00:53:20 richard
- # Default index now filters out the resolved issues ;)
- #
- # Revision 1.5 2001/07/20 00:17:16 richard
- # Fixed adding a new issue when there is no __note
- #
- # Revision 1.4 2001/07/19 06:27:07 anthonybaxter
- # fixing (manually) the (dollarsign)Log(dollarsign) entries caused by
- # my using the magic (dollarsign)Id(dollarsign) and (dollarsign)Log(dollarsign)
- # strings in a commit message. I'm a twonk.
- #
- # Also broke the help string in two.
- #
- # Revision 1.3 2001/07/19 05:52:22 anthonybaxter
- # Added CVS keywords Id and Log to all python files.
- #
- #
-
--- 490,497 ----
#
# $Log$
+ # Revision 1.2 2001/07/22 12:09:32 richard
+ # Final commit of Grande Splite
+ #
# Revision 1.1 2001/07/22 11:58:35 richard
# More Grande Splite
#
Index: cgitb.py
===================================================================
RCS file: /cvsroot/roundup/roundup/roundup/cgitb.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -r1.1 -r1.2
*** cgitb.py 2001/07/22 11:58:35 1.1
--- cgitb.py 2001/07/22 12:09:32 1.2
***************
*** 116,131 ****
#
# $Log$
# Revision 1.1 2001/07/22 11:58:35 richard
# More Grande Splite
- #
- # Revision 1.3 2001/07/19 06:27:07 anthonybaxter
- # fixing (manually) the (dollarsign)Log(dollarsign) entries caused by
- # my using the magic (dollarsign)Id(dollarsign) and (dollarsign)Log(dollarsign)
- # strings in a commit message. I'm a twonk.
- #
- # Also broke the help string in two.
- #
- # Revision 1.2 2001/07/19 05:52:22 anthonybaxter
- # Added CVS keywords Id and Log to all python files.
- #
#
--- 116,123 ----
#
# $Log$
+ # Revision 1.2 2001/07/22 12:09:32 richard
+ # Final commit of Grande Splite
+ #
# Revision 1.1 2001/07/22 11:58:35 richard
# More Grande Splite
#
Index: date.py
===================================================================
RCS file: /cvsroot/roundup/roundup/roundup/date.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -r1.1 -r1.2
*** date.py 2001/07/22 11:58:35 1.1
--- date.py 2001/07/22 12:09:32 1.2
***************
*** 345,361 ****
#
# $Log$
# Revision 1.1 2001/07/22 11:58:35 richard
# More Grande Splite
#
- # Revision 1.3 2001/07/19 06:27:07 anthonybaxter
- # fixing (manually) the (dollarsign)Log(dollarsign) entries caused by
- # my using the magic (dollarsign)Id(dollarsign) and (dollarsign)Log(dollarsign)
- # strings in a commit message. I'm a twonk.
- #
- # Also broke the help string in two.
- #
- # Revision 1.2 2001/07/19 05:52:22 anthonybaxter
- # Added CVS keywords Id and Log to all python files.
- #
- #
-
--- 345,352 ----
#
# $Log$
+ # Revision 1.2 2001/07/22 12:09:32 richard
+ # Final commit of Grande Splite
+ #
# Revision 1.1 2001/07/22 11:58:35 richard
# More Grande Splite
#
Index: htmltemplate.py
===================================================================
RCS file: /cvsroot/roundup/roundup/roundup/htmltemplate.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -r1.1 -r1.2
*** htmltemplate.py 2001/07/22 11:58:35 1.1
--- htmltemplate.py 2001/07/22 12:09:32 1.2
***************
*** 703,722 ****
#
# $Log$
# Revision 1.1 2001/07/22 11:58:35 richard
# More Grande Splite
#
- # Revision 1.5 2001/07/20 07:34:43 richard
- # Quote the value put in the text input value attribute.
- #
- # Revision 1.4 2001/07/19 06:27:07 anthonybaxter
- # fixing (manually) the (dollarsign)Log(dollarsign) entries caused by
- # my using the magic (dollarsign)Id(dollarsign) and (dollarsign)Log(dollarsign)
- # strings in a commit message. I'm a twonk.
- #
- # Also broke the help string in two.
- #
- # Revision 1.3 2001/07/19 05:52:22 anthonybaxter
- # Added CVS keywords Id and Log to all python files.
- #
- #
-
--- 703,710 ----
#
# $Log$
+ # Revision 1.2 2001/07/22 12:09:32 richard
+ # Final commit of Grande Splite
+ #
# Revision 1.1 2001/07/22 11:58:35 richard
# More Grande Splite
#
Index: hyper_bsddb.py
===================================================================
RCS file: /cvsroot/roundup/roundup/roundup/hyper_bsddb.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -r1.1 -r1.2
*** hyper_bsddb.py 2001/07/22 11:58:35 1.1
--- hyper_bsddb.py 2001/07/22 12:09:32 1.2
***************
*** 163,172 ****
#
#$Log$
#Revision 1.1 2001/07/22 11:58:35 richard
#More Grande Splite
#
- #Revision 1.1 2001/07/20 07:35:55 richard
- #largish changes as a start of splitting off bits and pieces to allow more
- #flexible installation / database back-ends
- #
-
--- 163,170 ----
#
#$Log$
+ #Revision 1.2 2001/07/22 12:09:32 richard
+ #Final commit of Grande Splite
+ #
#Revision 1.1 2001/07/22 11:58:35 richard
#More Grande Splite
#
Index: hyperdb.py
===================================================================
RCS file: /cvsroot/roundup/roundup/roundup/hyperdb.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -r1.1 -r1.2
*** hyperdb.py 2001/07/22 11:58:35 1.1
--- hyperdb.py 2001/07/22 12:09:32 1.2
***************
*** 736,750 ****
#
# $Log$
# Revision 1.1 2001/07/22 11:58:35 richard
# More Grande Splite
#
- # Revision 1.6 2001/07/20 08:20:24 richard
- # Fixed a bug in the filter - wrong variable names in the error message.
- # Recognised that the filter has an outstanding bug. Hrm. we need a bug tracker
- # for this project :)
- #
- # Revision 1.5 2001/07/20 07:35:55 richard
- # largish changes as a start of splitting off bits and pieces to allow more
- # flexible installation / database back-ends
- #
-
--- 736,743 ----
#
# $Log$
+ # Revision 1.2 2001/07/22 12:09:32 richard
+ # Final commit of Grande Splite
+ #
# Revision 1.1 2001/07/22 11:58:35 richard
# More Grande Splite
#
Index: init.py
===================================================================
RCS file: /cvsroot/roundup/roundup/roundup/init.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -r1.1 -r1.2
*** init.py 2001/07/22 11:58:35 1.1
--- init.py 2001/07/22 12:09:32 1.2
***************
*** 1,2 ****
--- 1,4 ----
+ # $Id$
+
import os, shutil, sys
***************
*** 44,45 ****
--- 46,53 ----
instance.init(adminpw)
+ #
+ # $Log$
+ # Revision 1.2 2001/07/22 12:09:32 richard
+ # Final commit of Grande Splite
+ #
+ #
Index: mailgw.py
===================================================================
RCS file: /cvsroot/roundup/roundup/roundup/mailgw.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -r1.1 -r1.2
*** mailgw.py 2001/07/22 11:58:35 1.1
--- mailgw.py 2001/07/22 12:09:32 1.2
***************
*** 266,267 ****
--- 266,273 ----
nodeid = cl.create(**props)
+ #
+ # $Log$
+ # Revision 1.2 2001/07/22 12:09:32 richard
+ # Final commit of Grande Splite
+ #
+ #
Index: roundupdb.py
===================================================================
RCS file: /cvsroot/roundup/roundup/roundup/roundupdb.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -r1.1 -r1.2
*** roundupdb.py 2001/07/22 11:58:35 1.1
--- roundupdb.py 2001/07/22 12:09:32 1.2
***************
*** 228,252 ****
#
# $Log$
# Revision 1.1 2001/07/22 11:58:35 richard
# More Grande Splite
#
- # Revision 1.6 2001/07/20 07:35:55 richard
- # largish changes as a start of splitting off bits and pieces to allow more
- # flexible installation / database back-ends
- #
- # Revision 1.5 2001/07/20 00:22:50 richard
- # Priority list changes - removed the redundant TODO and added support. See
- # roundup-devel for details.
- #
- # Revision 1.4 2001/07/19 06:27:07 anthonybaxter
- # fixing (manually) the (dollarsign)Log(dollarsign) entries caused by
- # my using the magic (dollarsign)Id(dollarsign) and (dollarsign)Log(dollarsign)
- # strings in a commit message. I'm a twonk.
- #
- # Also broke the help string in two.
- #
- # Revision 1.3 2001/07/19 05:52:22 anthonybaxter
- # Added CVS keywords Id and Log to all python files.
- #
- #
-
--- 228,235 ----
#
# $Log$
+ # Revision 1.2 2001/07/22 12:09:32 richard
+ # Final commit of Grande Splite
+ #
# Revision 1.1 2001/07/22 11:58:35 richard
# More Grande Splite
#
|
|
From: Richard J. <ri...@us...> - 2001-07-22 12:09:34
|
Update of /cvsroot/roundup/roundup/templates In directory usw-pr-cvs1:/tmp/cvs-serv2539/roundup/templates/extended Modified Files: __init__.py Log Message: Final commit of Grande Splite Index: __init__.py =================================================================== RCS file: /cvsroot/roundup/roundup/templates/__init__.py,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -r1.1 -r1.2 *** __init__.py 2001/07/22 12:01:27 1.1 --- __init__.py 2001/07/22 12:09:32 1.2 *************** *** 180,198 **** # # $Log$ ! # Revision 1.1 2001/07/22 12:01:27 richard ! # More Grande Splite ! # ! # Revision 1.6 2001/07/19 10:43:01 anthonybaxter ! # HTTP_HOST and HTTP_PORT config options. ! # ! # Revision 1.5 2001/07/19 06:27:07 anthonybaxter ! # fixing (manually) the (dollarsign)Log(dollarsign) entries caused by ! # my using the magic (dollarsign)Id(dollarsign) and (dollarsign)Log(dollarsign) ! # strings in a commit message. I'm a twonk. ! # ! # Also broke the help string in two. ! # ! # Revision 1.4 2001/07/19 05:52:22 anthonybaxter ! # Added CVS keywords Id and Log to all python files. # # --- 180,185 ---- # # $Log$ ! # Revision 1.2 2001/07/22 12:09:32 richard ! # Final commit of Grande Splite # # |
|
From: Richard J. <ri...@us...> - 2001-07-22 12:01:29
|
Update of /cvsroot/roundup/roundup/templates
In directory usw-pr-cvs1:/tmp/cvs-serv1328
Added Files:
__init__.py
Log Message:
More Grande Splite
--- NEW FILE: __init__.py ---
# $Id: __init__.py,v 1.1 2001/07/22 12:01:27 richard Exp $
MAIL_DOMAIN=MAILHOST=HTTP_HOST=None
HTTP_PORT=0
try:
from localconfig import *
except ImportError:
localconfig = None
import os
# roundup home is this package's directory
ROUNDUP_HOME=os.path.split(__file__)[0]
# The SMTP mail host that roundup will use to send mail
if not MAILHOST:
MAILHOST = 'localhost'
# The domain name used for email addresses.
if not MAIL_DOMAIN:
MAIL_DOMAIN = 'bizarsoftware.com.au'
# the next two are only used for the standalone HTTP server.
if not HTTP_HOST:
HTTP_HOST = ''
if not HTTP_PORT:
HTTP_PORT = 9080
# This is the directory that the database is going to be stored in
DATABASE = os.path.join(ROUNDUP_HOME, 'db')
# This is the directory that the HTML templates reside in
TEMPLATES = os.path.join(ROUNDUP_HOME, 'templates')
# The email address that mail to roundup should go to
ISSUE_TRACKER_EMAIL = 'issue_tracker@%s'%MAIL_DOMAIN
# The email address that roundup will complain to if it runs into trouble
ADMIN_EMAIL = 'roundup-admin@%s'%MAIL_DOMAIN
# Somewhere for roundup to log stuff internally sent to stdout or stderr
LOG = os.path.join(ROUNDUP_HOME, 'roundup.log')
from roundup import hyperdb, hyper_bsddb, roundupdb, cgi_client, mailgw
class Database(roundupdb.Database, hyper_bsddb.Database):
''' Creates a hybrid database from:
. the base Database class given in hyperdb (basic functionlity)
. the BSDDB implementation in hyperdb_bsddb
. the roundup extensions from roundupdb
'''
pass
Class = roundupdb.Class
class IssueClass(roundupdb.IssueClass):
''' issues need the email information
'''
ISSUE_TRACKER_EMAIL = ISSUE_TRACKER_EMAIL
ADMIN_EMAIL = ADMIN_EMAIL
MAILHOST = MAILHOST
FileClass = roundupdb.FileClass
class Client(cgi_client.Client):
''' derives basic mail gateway implementation from the standard module,
with any specific extensions
'''
TEMPLATES = TEMPLATES
pass
class MailGW(mailgw.MailGW):
''' derives basic mail gateway implementation from the standard module,
with any specific extensions
'''
ISSUE_TRACKER_EMAIL = ISSUE_TRACKER_EMAIL
ADMIN_EMAIL = ADMIN_EMAIL
MAILHOST = MAILHOST
def open(name=None):
''' as from the roundupdb method openDB
storagelocator must be the directory the __init__.py file is in
- os.path.split(__file__)[0] gives us that I think
'''
db = Database(DATABASE, name)
pri = Class(db, "priority", name=hyperdb.String(), order=hyperdb.String())
pri.setkey("name")
stat = Class(db, "status", name=hyperdb.String(), order=hyperdb.String())
stat.setkey("name")
Class(db, "keyword", name=hyperdb.String())
user = Class(db, "user", username=hyperdb.String(),
password=hyperdb.String(), address=hyperdb.String(),
realname=hyperdb.String(), phone=hyperdb.String(),
organisation=hyperdb.String())
user.setkey("username")
msg = FileClass(db, "msg", author=hyperdb.Link("user"),
recipients=hyperdb.Multilink("user"), date=hyperdb.Date(),
summary=hyperdb.String(), files=hyperdb.Multilink("file"))
file = FileClass(db, "file", name=hyperdb.String(), type=hyperdb.String())
# bugs and support calls etc
rate = Class(db, "rate", name=hyperdb.String(), order=hyperdb.String())
rate.setkey("name")
source = Class(db, "source", name=hyperdb.String(), order=hyperdb.String())
source.setkey("name")
platform = Class(db, "platform", name=hyperdb.String(), order=hyperdb.String())
platform.setkey("name")
product = Class(db, "product", name=hyperdb.String(), order=hyperdb.String())
product.setkey("name")
Class(db, "timelog", date=hyperdb.Date(), time=hyperdb.String(),
performedby=hyperdb.Link("user"), description=hyperdb.String())
issue = IssueClass(db, "issue", assignedto=hyperdb.Link("user"),
priority=hyperdb.Link("priority"), status=hyperdb.Link("status"),
rate=hyperdb.Link("rate"), source=hyperdb.Link("source"),
product=hyperdb.Link("product"), platform=hyperdb.Multilink("platform"),
version=hyperdb.String(),
timelog=hyperdb.Multilink("timelog"), customername=hyperdb.String())
issue.setkey('title')
import detectors
detectors.init(db)
return db
def init(adminpw):
''' as from the roundupdb method initDB
storagelocator must be the directory the __init__.py file is in
- os.path.split(__file__)[0] gives us that I think
'''
dbdir = os.path.join(DATABASE, 'files')
if not os.path.isdir(dbdir):
os.makedirs(dbdir)
db = open("admin")
db.clear()
pri = db.getclass('priority')
pri.create(name="fatal-bug", order="1")
pri.create(name="bug", order="2")
pri.create(name="usability", order="3")
pri.create(name="feature", order="4")
pri.create(name="support", order="5")
stat = db.getclass('status')
stat.create(name="unread", order="1")
stat.create(name="deferred", order="2")
stat.create(name="chatting", order="3")
stat.create(name="need-eg", order="4")
stat.create(name="in-progress", order="5")
stat.create(name="testing", order="6")
stat.create(name="done-cbb", order="7")
stat.create(name="resolved", order="8")
rate = db.getclass("rate")
rate.create(name='basic', order="1")
rate.create(name='premium', order="2")
rate.create(name='internal', order="3")
source = db.getclass("source")
source.create(name='phone', order="1")
source.create(name='e-mail', order="2")
source.create(name='internal', order="3")
source.create(name='internal-qa', order="4")
platform = db.getclass("platform")
platform.create(name='linux', order="1")
platform.create(name='windows', order="2")
platform.create(name='mac', order="3")
product = db.getclass("product")
product.create(name='Bizar Shop', order="1")
product.create(name='Bizar Shop Developer', order="2")
product.create(name='Bizar Shop Manual', order="3")
product.create(name='Bizar Shop Developer Manual', order="4")
user = db.getclass('user')
user.create(username="admin", password=adminpw, address=ADMIN_EMAIL)
db.close()
#
# $Log: __init__.py,v $
# Revision 1.1 2001/07/22 12:01:27 richard
# More Grande Splite
#
# Revision 1.6 2001/07/19 10:43:01 anthonybaxter
# HTTP_HOST and HTTP_PORT config options.
#
# Revision 1.5 2001/07/19 06:27:07 anthonybaxter
# fixing (manually) the (dollarsign)Log(dollarsign) entries caused by
# my using the magic (dollarsign)Id(dollarsign) and (dollarsign)Log(dollarsign)
# strings in a commit message. I'm a twonk.
#
# Also broke the help string in two.
#
# Revision 1.4 2001/07/19 05:52:22 anthonybaxter
# Added CVS keywords Id and Log to all python files.
#
#
|
|
From: Richard J. <ri...@us...> - 2001-07-22 11:59:46
|
Update of /cvsroot/roundup/roundup/templates/templates In directory usw-pr-cvs1:/tmp/cvs-serv721/templates Log Message: Directory /cvsroot/roundup/roundup/templates/templates added to the repository |
|
From: Richard J. <ri...@us...> - 2001-07-22 11:59:46
|
Update of /cvsroot/roundup/roundup/templates/detectors In directory usw-pr-cvs1:/tmp/cvs-serv721/detectors Log Message: Directory /cvsroot/roundup/roundup/templates/detectors added to the repository |
|
From: Richard J. <ri...@us...> - 2001-07-22 11:56:46
|
Update of /cvsroot/roundup/roundup/roundup/templates In directory usw-pr-cvs1:/tmp/cvs-serv32174/templates Log Message: Directory /cvsroot/roundup/roundup/roundup/templates added to the repository |
|
From: Richard J. <ri...@us...> - 2001-07-22 11:47:10
|
Update of /cvsroot/roundup/roundup/cgi-bin
In directory usw-pr-cvs1:/tmp/cvs-serv28323
Added Files:
roundup.cgi
Log Message:
More Grande Splite
--- NEW FILE: roundup.cgi ---
#!/usr/bin/env python
# $Id: roundup.cgi,v 1.1 2001/07/22 11:47:07 richard Exp $
# python version check
import sys
if int(sys.version[0]) < 2:
print "Content-Type: text/plain\n"
print "Roundup requires Python 2.0 or newer."
#
## Configuration
#
# This indicates where the Roundup instance lives
ROUNDUPS = {
'test': '/tmp/roundup_test',
}
# Where to log debugging information to. Use an instance of DevNull if you
# don't want to log anywhere.
class DevNull:
def write(self, info):
pass
LOG = open('/var/log/roundup.cgi.log', 'a')
#LOG = DevNull()
#
## end configuration
#
#
# Set up the error handler
#
try:
import traceback, StringIO, cgi
from roundup import cgitb
except:
print "Content-Type: text/html\n"
print "Failed to import cgitb.<pre>"
s = StringIO.StringIO()
traceback.print_exc(None, s)
print cgi.escape(s.getvalue()), "</pre>"
def main(instance, out):
from roundup import cgi_client
db = instance.open('admin')
auth = os.environ.get("HTTP_CGI_AUTHORIZATION", None)
message = 'Unauthorised'
if auth:
l = binascii.a2b_base64(auth.split(' ')[1]).split(':')
user = l[0]
password = None
if len(l) > 1:
password = l[1]
try:
uid = db.user.lookup(user)
except KeyError:
auth = None
message = 'Username not recognised'
else:
if password != db.user.get(uid, 'password'):
message = 'Incorrect password'
auth = None
if not auth:
out.write('Content-Type: text/html\n')
out.write('Status: 401\n')
out.write('WWW-Authenticate: basic realm="Roundup"\n\n')
keys = os.environ.keys()
keys.sort()
out.write(message)
return
client = instance.Client(out, os.environ, user)
try:
client.main()
except cgi_client.Unauthorised:
out.write('Content-Type: text/html\n')
out.write('Status: 403\n\n')
out.write('Unauthorised')
#
# Now do the actual CGI handling
#
out, err = sys.stdout, sys.stderr
try:
sys.stdout = sys.stderr = LOG
import os, string
instance = string.split(os.environ['PATH_INFO'], '/')[1]
if ROUNDUPS.has_key(instance):
instance_home = ROUNDUPS[instance]
sys.path.insert(0, instance_home)
try:
instance = __import__(instance)
finally:
del sys.path[0]
else:
raise ValueError, 'No such instance "%s"'%instance
main(instance, out)
except:
sys.stdout, sys.stderr = out, err
out.write('Content-Type: text/html\n\n')
cgitb.handler()
sys.stdout.flush()
sys.stdout, sys.stderr = out, err
#
# $Log: roundup.cgi,v $
# Revision 1.1 2001/07/22 11:47:07 richard
# More Grande Splite
#
#
|
|
From: Richard J. <ri...@us...> - 2001-07-22 11:15:49
|
Update of /cvsroot/roundup/roundup/bin
In directory usw-pr-cvs1:/tmp/cvs-serv23718
Added Files:
roundup roundup-mailgw roundup-server
Log Message:
More Grande Splite stuff
--- NEW FILE: roundup ---
#! /usr/bin/python
# $Id: roundup,v 1.1 2001/07/22 11:15:45 richard Exp $
import sys
if int(sys.version[0]) < 2:
print 'Roundup requires python 2.0 or later.'
sys.exit(1)
import string, os, getpass
from roundup import date, roundupdb, init
def determineLogin(instance, argv, n = 2):
name = password = ''
if argv[2] == '-u':
l = argv[3].split(':')
name = l[0]
if len(l) > 1:
password = l[1]
n = 4
elif os.environ.has_key('ROUNDUP_LOGIN'):
l = os.environ['ROUNDUP_LOGIN'].split(':')
name = l[0]
if len(l) > 1:
password = l[1]
while not name:
name = raw_input('Login name: ')
while not password:
password = getpass.getpass(' password: ')
# TODO use the password...
return n, instance.open(name)
def usage(message=''):
if message: message = 'Problem: '+message+'\n'
print '''%sUsage:
roundup [-i instance] init template
-- initialise the database
roundup [-i instance] spec classname
-- show the properties for a classname
roundup [-i instance] create [-u login] classname propname=value ...
-- create a new entry of a given class
roundup [-i instance] list [-c] classname
-- list the instances of a class
roundup [-i instance] history [-c] designator
-- show the history entries of a designator
roundup [-i instance] get [-c] designator[,designator,...] propname
-- get the given property of one or more designator(s)
roundup [-i instance] set [-u login] designator[,designator,...] propname=value ...
-- set the given property of one or more designator(s)
roundup [-i instance] find [-c] classname propname=value ...
-- find the class instances with a given property
roundup [-i instance] retire designator[,designator,...]
-- "retire" a designator
roundup help
-- this help
roundup morehelp
-- even more detailed help
'''%message
def moreusage(message=''):
usage(message)
print '''
All commands (except help) require an instance specifier. This is just the path
to the roundup instance you're working with. It may be specified in the environment
variable ROUNDUP_INSTANCE or on the command line as "-i instance".
A designator is a classname and a nodeid concatenated, eg. bug1, user10, ...
Property values are represented as strings in command arguments and in the
printed results:
. Strings are, well, strings.
. Date values are printed in the full date format in the local time zone, and
accepted in the full format or any of the partial formats explained below.
. Link values are printed as node designators. When given as an argument,
node designators and key strings are both accepted.
. Multilink values are printed as lists of node designators joined by commas.
When given as an argument, node designators and key strings are both
accepted; an empty string, a single node, or a list of nodes joined by
commas is accepted.
When multiple nodes are specified to the roundup get or roundup set
commands, the specified properties are retrieved or set on all the listed
nodes.
When multiple results are returned by the roundup get or roundup find
commands, they are printed one per line (default) or joined by commas (with
the -c) option.
Where the command changes data, a login name/password is required. The
login may be specified as either "name" or "name:password".
. ROUNDUP_LOGIN environment variable
. the -u command-line option
If either the name or password is not supplied, they are obtained from the
command-line.
Date format examples:
"2000-04-17.03:45" means <Date 2000-04-17.08:45:00>
"2000-04-17" means <Date 2000-04-17.00:00:00>
"01-25" means <Date yyyy-01-25.00:00:00>
"08-13.22:13" means <Date yyyy-08-14.03:13:00>
"11-07.09:32:43" means <Date yyyy-11-07.14:32:43>
"14:25" means <Date yyyy-mm-dd.19:25:00>
"8:47:11" means <Date yyyy-mm-dd.13:47:11>
"." means "right now"
'''
def main():
argv = sys.argv
if len(argv) == 1:
usage('No command specified')
return 1
# handle help now
if argv[1] == 'help':
usage()
return 0
if argv[1] == 'morehelp':
moreusage()
return 0
# figure the instance home
n = 1
if argv[1] == '-i':
if len(argv) == 2:
usage()
return 1
instance_home = argv[2]
n = 3
else:
instance_home = os.environ.get('ROUNDUP_INSTANCE', '')
if not instance_home:
usage('No instance home specified')
return 1
# now figure the command
command = argv[n]
n = n + 1
if command == 'init':
adminpw = ''
confirm = 'x'
while adminpw != confirm:
adminpw = getpass.getpass('Admin Password:')
confirm = getpass.getpass(' Confirm:')
init.init(instance_home, argv[n], adminpw)
return 0
# get the instance
path, instance = os.path.split(instance_home)
sys.path.insert(0, path)
try:
instance = __import__(instance)
finally:
del sys.path[0]
if command == 'get':
db = instance.open()
designators = string.split(argv[n], ',')
propname = argv[n+1]
# TODO: handle the -c option
for designator in designators:
classname, nodeid = roundupdb.splitDesignator(designator)
print db.getclass(classname).get(nodeid, propname)
elif command == 'set':
n, db = determineLogin(instance, argv, n)
designators = string.split(argv[n], ',')
props = {}
for prop in argv[n+1:]:
key, value = prop.split('=')
props[key] = value
for designator in designators:
classname, nodeid = roundupdb.splitDesignator(designator)
cl = db.getclass(classname)
properties = cl.getprops()
for key, value in props.items():
type = properties[key]
if type.isStringType:
continue
elif type.isDateType:
props[key] = date.Date(value)
elif type.isIntervalType:
props[key] = date.Interval(value)
elif type.isLinkType:
props[key] = value
elif type.isMultilinkType:
props[key] = value.split(',')
apply(cl.set, (nodeid, ), props)
elif command == 'find':
db = instance.open()
classname = argv[n]
cl = db.getclass(classname)
# look up the linked-to class and get the nodeid that has the value
propname, value = argv[n+1:].split('=')
propcl = cl[propname].classname
nodeid = propcl.lookup(value)
# now do the find
# TODO: handle the -c option
print cl.find(propname, nodeid)
elif command == 'spec':
db = instance.open()
classname = argv[n]
cl = db.getclass(classname)
for key, value in cl.properties.items():
print '%s: %s'%(key, value)
elif command == 'create':
n, db = determineLogin(instance, argv, n)
classname = argv[n]
cl = db.getclass(classname)
props = {}
properties = cl.getprops()
for prop in argv[n+1:]:
key, value = prop.split('=')
type = properties[key]
if type.isStringType:
props[key] = value
elif type.isDateType:
props[key] = date.Date(value)
elif type.isIntervalType:
props[key] = date.Interval(value)
elif type.isLinkType:
props[key] = value
elif type.isMultilinkType:
props[key] = value.split(',')
print apply(cl.create, (), props)
elif command == 'list':
db = instance.open()
classname = argv[n]
cl = db.getclass(classname)
key = cl.getkey() or cl.properties.keys()[0]
# TODO: handle the -c option
for nodeid in cl.list():
value = cl.get(nodeid, key)
print "%4s: %s"%(nodeid, value)
elif command == 'history':
db = instance.open()
classname, nodeid = roundupdb.splitDesignator(argv[n])
# TODO: handle the -c option
print db.getclass(classname).history(nodeid)
elif command == 'retire':
n, db = determineLogin(instance, argv, n)
designators = string.split(argv[n], ',')
for designator in designators:
classname, nodeid = roundupdb.splitDesignator(designator)
db.getclass(classname).retire(nodeid)
else:
print "Unknown command '%s'"%command
usage()
return 1
db.close()
return 0
if __name__ == '__main__':
sys.exit(main())
#
# $Log: roundup,v $
# Revision 1.1 2001/07/22 11:15:45 richard
# More Grande Splite stuff
#
#
--- NEW FILE: roundup-mailgw ---
#! /usr/bin/python
# $ID: $
import sys
if int(sys.version[0]) < 2:
print "Roundup requires Python 2.0 or newer."
sys.exit(1)
# figure the instance home
import os
if len(sys.argv) > 1:
instance_home = sys.argv[1]
else:
instance_home = os.environ.get('ROUNDUP_INSTANCE', '')
if not instance_home:
print 'No instance home specified'
sys.exit(1)
# get the instance
path, instance = os.path.split(instance_home)
sys.path.insert(0, path)
instance = __import__(instance)
sys.path[0]
# invokde the mail handler
db = instance.open('admin')
handler = instance.MailGW(db)
handler.main(sys.stdin)
#
# $Log: roundup-mailgw,v $
# Revision 1.1 2001/07/22 11:15:45 richard
# More Grande Splite stuff
#
#
--- NEW FILE: roundup-server ---
#!/usr/bin/python
""" HTTP Server that serves roundup.
Stolen from CGIHTTPServer
$Id: roundup-server,v 1.1 2001/07/22 11:15:45 richard Exp $
"""
import sys
if int(sys.version[0]) < 2:
print "Content-Type: text/plain\n"
print "Roundup requires Python 2.0 or newer."
__version__ = "0.1"
__all__ = ["RoundupRequestHandler"]
import os, urllib, StringIO, traceback, cgi, binascii, string
import BaseHTTPServer
import SimpleHTTPServer
# Roundup modules of use here
from roundup import cgitb, cgi_client
# These are here temporarily until I get a real reload system in place
from roundup import date, hyperdb, hyper_bsddb, roundupdb, htmltemplate
#
## Configuration
#
# This indicates where the Roundup instance lives
ROUNDUPS = {
'test': '/tmp/roundup_test',
}
# Where to log debugging information to. Use an instance of DevNull if you
# don't want to log anywhere.
# TODO: actually use this stuff
#class DevNull:
# def write(self, info):
# pass
#LOG = open('/var/log/roundup.cgi.log', 'a')
#LOG = DevNull()
#
## end configuration
#
class RoundupRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
def send_head(self):
"""Version of send_head that support CGI scripts"""
# TODO: actually do the HEAD ...
return self.run_cgi()
def run_cgi(self):
""" Execute the CGI command. Wrap an innner call in an error
handler so all errors can be caught.
"""
save_stdin = sys.stdin
sys.stdin = self.rfile
try:
self.inner_run_cgi()
except cgi_client.Unauthorised:
self.wfile.write('Content-Type: text/html\n')
self.wfile.write('Status: 403\n')
self.wfile.write('Unauthorised')
except:
try:
reload(cgitb)
self.wfile.write("Content-Type: text/html\n\n")
self.wfile.write(cgitb.breaker())
self.wfile.write(cgitb.html())
except:
self.wfile.write("Content-Type: text/html\n\n")
self.wfile.write("<pre>")
s = StringIO.StringIO()
traceback.print_exc(None, s)
self.wfile.write(cgi.escape(s.getvalue()))
self.wfile.write("</pre>\n")
sys.stdin = save_stdin
def inner_run_cgi(self):
''' This is the inner part of the CGI handling
'''
rest = self.path
i = rest.rfind('?')
if i >= 0:
rest, query = rest[:i], rest[i+1:]
else:
query = ''
# figure the instance
if rest == '/':
raise ValueError, 'No instance specified'
l_path = string.split(rest, '/')
instance = urllib.unquote(l_path[1])
if ROUNDUPS.has_key(instance):
instance_home = ROUNDUPS[instance]
module_path, instance = os.path.split(instance_home)
sys.path.insert(0, module_path)
try:
instance = __import__(instance)
finally:
del sys.path[0]
else:
raise ValueError, 'No such instance "%s"'%instance
# figure out what the rest of the path is
if len(l_path) > 2:
rest = '/'.join(l_path[2:])
else:
rest = '/'
# Set up the CGI environment
env = {}
env['REQUEST_METHOD'] = self.command
env['PATH_INFO'] = urllib.unquote(rest)
if query:
env['QUERY_STRING'] = query
host = self.address_string()
if self.headers.typeheader is None:
env['CONTENT_TYPE'] = self.headers.type
else:
env['CONTENT_TYPE'] = self.headers.typeheader
length = self.headers.getheader('content-length')
if length:
env['CONTENT_LENGTH'] = length
co = filter(None, self.headers.getheaders('cookie'))
if co:
env['HTTP_COOKIE'] = ', '.join(co)
env['SCRIPT_NAME'] = ''
env['SERVER_NAME'] = self.server.server_name
env['SERVER_PORT'] = str(self.server.server_port)
decoded_query = query.replace('+', ' ')
# if root, setuid to nobody
# TODO why isn't this done much earlier? - say, in main()?
if not os.getuid():
nobody = nobody_uid()
os.setuid(nobody)
# reload all modules
# TODO check for file timestamp changes and dependencies
reload(date)
reload(hyperdb)
reload(roundupdb)
reload(htmltemplate)
reload(cgi_client)
sys.path.insert(0, module_path)
try:
reload(instance)
finally:
del sys.path[0]
# initialise the roundupdb, check for auth
db = instance.open('admin')
message = 'Unauthorised'
auth = self.headers.getheader('authorization')
if auth:
l = binascii.a2b_base64(auth.split(' ')[1]).split(':')
user = l[0]
password = None
if len(l) > 1:
password = l[1]
try:
uid = db.user.lookup(user)
except KeyError:
auth = None
message = 'Username not recognised'
else:
if password != db.user.get(uid, 'password'):
message = 'Incorrect password'
auth = None
db.close()
del db
if not auth:
self.send_response(401)
self.send_header('Content-Type', 'text/html')
self.send_header('WWW-Authenticate', 'basic realm="Roundup"')
self.end_headers()
self.wfile.write(message)
return
self.send_response(200, "Script output follows")
# do the roundup thang
db = instance.open(user)
client = instance.Client(self.wfile, db, env, user)
client.main()
do_POST = run_cgi
nobody = None
def nobody_uid():
"""Internal routine to get nobody's uid"""
global nobody
if nobody:
return nobody
try:
import pwd
except ImportError:
return -1
try:
nobody = pwd.getpwnam('nobody')[2]
except KeyError:
nobody = 1 + max(map(lambda x: x[2], pwd.getpwall()))
return nobody
if __name__ == '__main__':
# TODO make this configurable again? command-line seems ok to me...
address = ('', 8080)
httpd = BaseHTTPServer.HTTPServer(address, RoundupRequestHandler)
print 'Roundup server started on', address
httpd.serve_forever()
#
# $Log: roundup-server,v $
# Revision 1.1 2001/07/22 11:15:45 richard
# More Grande Splite stuff
#
#
|
|
From: Richard J. <ri...@us...> - 2001-07-22 11:11:17
|
Update of /cvsroot/roundup/roundup
In directory usw-pr-cvs1:/tmp/cvs-serv20862
Modified Files:
CHANGES README
Removed Files:
cgitb.py config.py date.py hyperdb.py hyperdb_bsddb.py
roundup-mailgw.py roundup.cgi roundup.py roundup_cgi.py
roundupdb.py server.py style.css template.py test.py
Log Message:
Initial commit of the Grande Splite
Index: CHANGES
===================================================================
RCS file: /cvsroot/roundup/roundup/CHANGES,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -r1.5 -r1.6
*** CHANGES 2001/07/20 08:20:39 1.5
--- CHANGES 2001/07/22 11:11:14 1.6
***************
*** 56,57 ****
--- 56,61 ----
. Fixed a bug in the hyperdb filter - wrong variable names in the error
message.
+ . Major reshuffle of code to allow multiple roundup instances and a
+ single, site-packages -based installation. Also allows multiple database
+ back-ends.
+
Index: README
===================================================================
RCS file: /cvsroot/roundup/roundup/README,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -r1.6 -r1.7
*** README 2001/07/20 08:20:24 1.6
--- README 2001/07/22 11:11:14 1.7
***************
*** 12,16 ****
--- 12,18 ----
+ TODO: Instructions need re-writing!!
+
2. Installation
===============
***************
*** 45,55 ****
2.1 Initial Setup
-----------------
- 1. Make a directory in /home/httpd/html called 'roundup'.
- 2. Copy the tar file's contents there.
- 3. Edit config.py
- 4. "python roundup.py init" to initialise the database (by default, it
- goes in a directory called 'db' in the current directory). Choose a
- sensible admin password.
- 5. "chmod -R a+rw db"
--- 47,50 ----
***************
*** 57,66 ****
--------
Set up a mail alias called "issue_tracker" as:
! "|/usr/bin/python /home/httpd/html/roundup/roundup-mailgw.py"
In some installations (e.g. RedHat 6.2 I think) you'll need to set up smrsh
so sendmail will accept the pipe command. In that case, symlink
/etc/smrsh/python to /usr/bin/python and change the command to:
! "|python /home/httpd/html/roundup/roundup-mailgw.py"
--- 52,61 ----
--------
Set up a mail alias called "issue_tracker" as:
! "|/usr/bin/python /home/httpd/html/roundup/roundup-mailgw <instance_home>"
In some installations (e.g. RedHat 6.2 I think) you'll need to set up smrsh
so sendmail will accept the pipe command. In that case, symlink
/etc/smrsh/python to /usr/bin/python and change the command to:
! "|python /home/httpd/html/roundup/roundup-mailgw <instance_home>"
--- cgitb.py DELETED ---
--- config.py DELETED ---
--- date.py DELETED ---
--- hyperdb.py DELETED ---
--- hyperdb_bsddb.py DELETED ---
--- roundup-mailgw.py DELETED ---
--- roundup.cgi DELETED ---
--- roundup.py DELETED ---
--- roundup_cgi.py DELETED ---
--- roundupdb.py DELETED ---
--- server.py DELETED ---
--- style.css DELETED ---
--- template.py DELETED ---
--- test.py DELETED ---
|
|
From: Richard J. <ri...@us...> - 2001-07-22 10:59:35
|
Update of /cvsroot/roundup/roundup/cgi-bin In directory usw-pr-cvs1:/tmp/cvs-serv18329/cgi-bin Log Message: Directory /cvsroot/roundup/roundup/cgi-bin added to the repository |