Skip to content

Commit 0cd8e5c

Browse files
author
Richard Jones
committed
fixed ZRoundup - mostly changes to classic template
1 parent 90f2520 commit 0cd8e5c

27 files changed

+221
-396
lines changed

CHANGES.txt

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ Feature:
77
- support setgid and running on port < 1024 (sf patch 777528)
88
- using Zope3's test runner now, allowing GC checks, nicer controls and
99
coverage analysis
10-
- added postgresql backend (originally from patch #761740, many changes since)
10+
- added postgresql backend (originally from sf patch 761740, many changes
11+
since)
1112
- all RDBMS backends now have indexes on several columns
1213
- Change nosymessage and send_message to accept msgid=None (RFE #707235).
1314

@@ -17,18 +18,19 @@ Fixed:
1718
couple of cases
1819
- HTML 4.01 validation on the 'classic' backend
1920
- Messages to the mailgw can be about classes other than issues now.
20-
- Signature matching is more precise (bug #827775).
21-
- Anonymous user can no longer edit or view itself (bug #828901).
22-
- Corrected typo in installation.html (bug #822967).
21+
- Signature matching is more precise (sf bug 827775).
22+
- Anonymous user can no longer edit or view itself (sf bug 828901).
23+
- Corrected typo in installation.html (sf bug 822967).
2324
- Clarified listTemplates docstring.
2425
- Print a nicer error message when the address is already in use
25-
(bug #798659).
26+
(sf bug 798659).
2627
- Remove empty lines before sending strings off to the csv parser
27-
(bug #821364).
28-
- Centralised conversion of user-input data to hyperdb values (bug #802405,
29-
bug #817217, rfe #816994)
28+
(sf bug 821364).
29+
- Centralised conversion of user-input data to hyperdb values (sf bug 802405,
30+
sf bug 817217, sf rfe 816994)
3031
- recalculate SHA on template files when installed tracker used as
3132
template (sf bug 827510)
33+
- fixed ZRoundup (sf bug 624380)
3234

3335
Cleanup:
3436
- Replace curuserid attribute on Database with the extended getuid() method.

doc/upgrading.txt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,29 @@ be replaced with a call to Database.getuid().
2121
might still need to create an index "create index ids_name_idx on
2222
ids(name)".
2323

24+
0.7.0 ZRoundup changes
25+
----------------------
26+
27+
The templates in your tracker's html directory will need updating if you
28+
wish to use ZRoundup. If you've not modified those files (or some of them),
29+
you may just copy the new versions from the Roundup source in the
30+
templates/classic/html directory.
31+
32+
If you have modified the html files, then you'll need to manually edit them
33+
to change all occurances of special form variables from using the colon ":"
34+
special character to the at "@" special character. That is, variables such
35+
as::
36+
37+
:action :required :template :remove:messages ...
38+
39+
should become:
40+
41+
@action @required @template @remove@messages ...
42+
43+
Note that ``tal:`` statements are unaffected. So are TAL expression type
44+
prefixes such as ``python:`` and ``string:``. Please ask on the
45+
roundup-users mailing list for help if you're unsure.
46+
2447

2548
Migrating from 0.6.x to 0.6.3
2649
=============================

frontends/ZRoundup/ZRoundup.py

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
1515
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1616
#
17-
# $Id: ZRoundup.py,v 1.16 2002-10-18 03:34:58 richard Exp $
17+
# $Id: ZRoundup.py,v 1.17 2003-11-12 01:00:58 richard Exp $
1818
#
1919
''' ZRoundup module - exposes the roundup web interface to Zope
2020
@@ -26,11 +26,6 @@
2626
independently of Zope. The roundup code is kept in memory though, and it
2727
runs in the same server as all your other Zope stuff, so it does have _some_
2828
advantages over regular CGI :)
29-
30-
It also means that any requests which specify :filter, :columns or :sort
31-
_must_ be done using a GET, so that this interface can re-parse the
32-
QUERY_STRING. Zope interprets the ':' as a special character, and the special
33-
args are lost to it.
3429
'''
3530

3631
import urlparse
@@ -142,16 +137,7 @@ def roundup_opendb(self):
142137
# the last element is the name
143138
env['TRACKER_NAME'] = path_components[-1]
144139

145-
if env['REQUEST_METHOD'] == 'GET':
146-
# force roundup to re-parse the request because Zope fiddles
147-
# with it and we lose all the :filter, :columns, etc goodness
148-
form = None
149-
else:
150-
# For some reason, CRs are embeded in multiline notes.
151-
# It doesn't occur with apache/roundup.cgi, though.
152-
form = FormWrapper(self.REQUEST.form)
153-
154-
print (env['SCRIPT_NAME'], env['PATH_INFO'])
140+
form = FormWrapper(self.REQUEST.form)
155141
return instance.Client(instance, request, env, form)
156142

157143
security.declareProtected('View', 'index_html')
@@ -160,7 +146,7 @@ def index_html(self):
160146
'''
161147
# Redirect misdirected requests -- bugs 558867 , 565992
162148
# PATH_INFO, as defined by the CGI spec, has the *real* request path
163-
orig_path = self.REQUEST.environ[ 'PATH_INFO' ]
149+
orig_path = self.REQUEST.environ['PATH_INFO']
164150
if orig_path[-1] != '/' :
165151
url = urlparse.urlparse( self.absolute_url() )
166152
url = list( url ) # make mutable
@@ -179,31 +165,30 @@ def index_html(self):
179165
def __getitem__(self, item):
180166
'''All other URL accesses are passed throuh to roundup
181167
'''
182-
return PathElement(self, item)
168+
return PathElement(self, item).__of__(self)
183169

184-
class PathElement(Item, Implicit, Persistent):
185-
def __init__(self, parent, path):
186-
self.parent = parent
170+
class PathElement(Item, Implicit):
171+
def __init__(self, zr, path):
172+
self.zr = zr
187173
self.path = path
188174

189175
def __getitem__(self, item):
190176
''' Get a subitem.
191177
'''
192-
return PathElement(self.path + '/' + item)
178+
return PathElement(self.zr, self.path + '/' + item).__of__(self)
193179

194-
def __call__(self, *args, **kw):
180+
def index_html(self, REQUEST=None):
195181
''' Actually call through to roundup to handle the request.
196182
'''
197-
print '*****', self.path
198183
try:
199-
client = self.parent.roundup_opendb()
184+
client = self.zr.roundup_opendb()
200185
# fake the path that roundup should use
201186
client.path = self.path
202187
# and call roundup to do something
203188
client.main()
204189
return ''
205190
except NotFound:
206-
raise 'NotFound', self.REQUEST.URL
191+
raise 'NotFound', REQUEST.URL
207192
pass
208193
except:
209194
import traceback

roundup/backends/back_mysql.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class Database(Database):
5353
mysql_backend = 'InnoDB'
5454
#mysql_backend = 'BDB' # much slower, only use if you have no choice
5555

56-
def open_connection(self):
56+
def sql_open_connection(self):
5757
db = getattr(self.config, 'MYSQL_DATABASE')
5858
try:
5959
self.conn = MySQLdb.connect(*db)
@@ -81,9 +81,6 @@ def open_connection(self):
8181
self.mysql_backend)
8282
self.sql("CREATE INDEX ids_name_idx on ids(name)")
8383

84-
def close(self):
85-
self.conn.close()
86-
8784
def __repr__(self):
8885
return '<myroundsql 0x%x>'%id(self)
8986

roundup/backends/back_postgresql.py

Lines changed: 6 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@
88
# psycopg backend for roundup
99
#
1010

11-
from roundup.backends.rdbms_common import *
11+
from roundup import hyperdb, date
1212
from roundup.backends import rdbms_common
1313
import psycopg
1414
import os, shutil, popen2
1515

16-
class Database(Database):
16+
class Database(rdbms_common.Database):
1717
arg = '%s'
1818

19-
def open_connection(self):
19+
def sql_open_connection(self):
2020
db = getattr(self.config, 'POSTGRESQL_DATABASE')
2121
try:
2222
self.conn = psycopg.connect(**db)
@@ -33,18 +33,9 @@ def open_connection(self):
3333
self.sql("CREATE TABLE schema (schema TEXT)")
3434
self.sql("CREATE TABLE ids (name VARCHAR(255), num INT4)")
3535

36-
def close(self):
37-
self.conn.close()
38-
3936
def __repr__(self):
4037
return '<roundpsycopgsql 0x%x>' % id(self)
4138

42-
def sql_fetchone(self):
43-
return self.cursor.fetchone()
44-
45-
def sql_fetchall(self):
46-
return self.cursor.fetchall()
47-
4839
def sql_stringquote(self, value):
4940
''' psycopg.QuotedString returns a "buffer" object with the
5041
single-quotes around it... '''
@@ -56,44 +47,6 @@ def sql_index_exists(self, table_name, index_name):
5647
self.cursor.execute(sql, (table_name, index_name))
5748
return self.cursor.fetchone()[0]
5849

59-
def save_dbschema(self, schema):
60-
s = repr(self.database_schema)
61-
self.sql('INSERT INTO schema VALUES (%s)', (s,))
62-
63-
def load_dbschema(self):
64-
self.cursor.execute('SELECT schema FROM schema')
65-
schema = self.cursor.fetchone()
66-
if schema:
67-
return eval(schema[0])
68-
69-
def save_journal(self, classname, cols, nodeid, journaldate,
70-
journaltag, action, params):
71-
params = repr(params)
72-
entry = (nodeid, journaldate, journaltag, action, params)
73-
74-
a = self.arg
75-
sql = 'INSERT INTO %s__journal (%s) values (%s, %s, %s, %s, %s)'%(
76-
classname, cols, a, a, a, a, a)
77-
78-
if __debug__:
79-
print >>hyperdb.DEBUG, 'addjournal', (self, sql, entry)
80-
81-
self.cursor.execute(sql, entry)
82-
83-
def load_journal(self, classname, cols, nodeid):
84-
sql = 'SELECT %s FROM %s__journal WHERE nodeid = %s' % (
85-
cols, classname, self.arg)
86-
87-
if __debug__:
88-
print >>hyperdb.DEBUG, 'getjournal', (self, sql, nodeid)
89-
90-
self.cursor.execute(sql, (nodeid,))
91-
res = []
92-
for nodeid, date_stamp, user, action, params in self.cursor.fetchall():
93-
params = eval(params)
94-
res.append((nodeid, date.Date(date_stamp), user, action, params))
95-
return res
96-
9750
def create_class_table(self, spec):
9851
cols, mls = self.determine_columns(spec.properties.items())
9952
cols.append('id')
@@ -126,79 +79,10 @@ def create_multilink_table(self, spec, ml):
12679

12780
self.cursor.execute(sql)
12881

129-
class PsycopgClass:
130-
def find(self, **propspec):
131-
"""Get the ids of nodes in this class which link to the given nodes."""
132-
133-
if __debug__:
134-
print >>hyperdb.DEBUG, 'find', (self, propspec)
135-
136-
# shortcut
137-
if not propspec:
138-
return []
139-
140-
# validate the args
141-
props = self.getprops()
142-
propspec = propspec.items()
143-
for propname, nodeids in propspec:
144-
# check the prop is OK
145-
prop = props[propname]
146-
if not isinstance(prop, Link) and not isinstance(prop, Multilink):
147-
raise TypeError, "'%s' not a Link/Multilink property"%propname
148-
149-
# first, links
150-
l = []
151-
where = []
152-
allvalues = ()
153-
a = self.db.arg
154-
for prop, values in propspec:
155-
if not isinstance(props[prop], hyperdb.Link):
156-
continue
157-
if type(values) is type(''):
158-
allvalues += (values,)
159-
where.append('_%s = %s' % (prop, a))
160-
elif values is None:
161-
where.append('_%s is NULL'%prop)
162-
else:
163-
allvalues += tuple(values.keys())
164-
where.append('_%s in (%s)' % (prop, ','.join([a]*len(values))))
165-
tables = []
166-
if where:
167-
self.db.sql('SELECT id AS nodeid FROM _%s WHERE %s' % (
168-
self.classname, ' and '.join(where)), allvalues)
169-
l += [x[0] for x in self.db.sql_fetchall()]
170-
171-
# now multilinks
172-
for prop, values in propspec:
173-
vals = ()
174-
if not isinstance(props[prop], hyperdb.Multilink):
175-
continue
176-
if type(values) is type(''):
177-
vals = (values,)
178-
s = a
179-
else:
180-
vals = tuple(values.keys())
181-
s = ','.join([a]*len(values))
182-
query = 'SELECT nodeid FROM %s_%s WHERE linkid IN (%s)'%(
183-
self.classname, prop, s)
184-
self.db.sql(query, vals)
185-
l += [x[0] for x in self.db.sql_fetchall()]
186-
187-
if __debug__:
188-
print >>hyperdb.DEBUG, 'find ... ', l
189-
190-
# Remove duplicated ids
191-
d = {}
192-
for k in l:
193-
d[k] = 1
194-
return d.keys()
195-
196-
return l
197-
198-
class Class(PsycopgClass, rdbms_common.Class):
82+
class Class(rdbms_common.Class):
19983
pass
200-
class IssueClass(PsycopgClass, rdbms_common.IssueClass):
84+
class IssueClass(rdbms_common.IssueClass):
20185
pass
202-
class FileClass(PsycopgClass, rdbms_common.FileClass):
86+
class FileClass(rdbms_common.FileClass):
20387
pass
20488

0 commit comments

Comments
 (0)