Commit 56ee772f authored by Jim Fulton's avatar Jim Fulton

major overhall to add record addressing, brains, and support for new interface

parent ca9ecce4
...@@ -10,11 +10,12 @@ ...@@ -10,11 +10,12 @@
__doc__='''Generic Database Connection Support __doc__='''Generic Database Connection Support
$Id: Connection.py,v 1.1 1997/12/02 17:22:02 jim Exp $''' $Id: Connection.py,v 1.2 1997/12/05 21:33:12 jim Exp $'''
__version__='$Revision: 1.1 $'[11:-2] __version__='$Revision: 1.2 $'[11:-2]
import Globals, OFS.SimpleItem, AccessControl.Role, Persistence, Acquisition import Globals, OFS.SimpleItem, AccessControl.Role, Persistence, Acquisition
from DateTime import DateTime from DateTime import DateTime
from App.Dialogs import MessageDialog
connection_page=Globals.HTMLFile('AqueductDA/connection') connection_page=Globals.HTMLFile('AqueductDA/connection')
...@@ -45,6 +46,26 @@ class Connection( ...@@ -45,6 +46,26 @@ class Connection(
_v_connected='' _v_connected=''
connection_string='' connection_string=''
def __setstate__(self, state):
Persistence.Persistent.__setstate__(self, state)
if self.connection_string: self.connect(self.connection_string)
def title_and_id(self):
s=Connection.inheritedAttribute('title_and_id')(self)
if hasattr(self, '_v_connected') and self._v_connected:
s="%s, which is connected" % s
else:
s="%s, which is <font color=red> not connected</font>" % s
return s
def title_or_id(self):
s=Connection.inheritedAttribute('title_or_id')(self)
if hasattr(self, '_v_connected') and self._v_connected:
s="%s (connected)" % s
else:
s="%s (<font color=red> not connected</font>)" % s
return s
def manage(self, REQUEST): def manage(self, REQUEST):
"Change the database connection string" "Change the database connection string"
return connection_page(self, REQUEST, action='manage_connection', return connection_page(self, REQUEST, action='manage_connection',
...@@ -57,14 +78,22 @@ class Connection( ...@@ -57,14 +78,22 @@ class Connection(
if check: self.connect(value) if check: self.connect(value)
else: self.manage_close_connection(REQUEST) else: self.manage_close_connection(REQUEST)
self.connection_string=value self.connection_string=value
return 'This needs to be changed' if REQUEST: return MessageDialog(
title='Connection Modified',
message='The connection information has been changed',
action='manage',
)
def manage_close_connection(self, REQUEST): def manage_close_connection(self, REQUEST):
" " " "
try: self._v_database_connection.close() try: self._v_database_connection.close()
except: pass except: pass
self._v_connected='' self._v_connected=''
return 'This needs to be changed' if REQUEST: return MessageDialog(
title='Connection Closed',
message='The connection has been closed',
action='manage',
)
def __call__(self, v=None): def __call__(self, v=None):
try: return self._v_database_connection try: return self._v_database_connection
...@@ -91,6 +120,9 @@ class Connection( ...@@ -91,6 +120,9 @@ class Connection(
############################################################################## ##############################################################################
# #
# $Log: Connection.py,v $ # $Log: Connection.py,v $
# Revision 1.2 1997/12/05 21:33:12 jim
# major overhall to add record addressing, brains, and support for new interface
#
# Revision 1.1 1997/12/02 17:22:02 jim # Revision 1.1 1997/12/02 17:22:02 jim
# initial # initial
# #
......
...@@ -11,11 +11,11 @@ ...@@ -11,11 +11,11 @@
__doc__='''Generic Database adapter __doc__='''Generic Database adapter
$Id: DA.py,v 1.15 1997/11/26 20:06:03 jim Exp $''' $Id: DA.py,v 1.16 1997/12/05 21:33:13 jim Exp $'''
__version__='$Revision: 1.15 $'[11:-2] __version__='$Revision: 1.16 $'[11:-2]
import string, OFS.SimpleItem, Aqueduct.Aqueduct, Aqueduct.RDB import OFS.SimpleItem, Aqueduct.Aqueduct, Aqueduct.RDB
import DocumentTemplate, marshal, md5, zlib, base64, DateTime, Acquisition import DocumentTemplate, marshal, md5, base64, DateTime, Acquisition, os
from Aqueduct.Aqueduct import quotedHTML, decodestring, parse, Rotor from Aqueduct.Aqueduct import quotedHTML, decodestring, parse, Rotor
from Aqueduct.Aqueduct import custom_default_report, default_input_form from Aqueduct.Aqueduct import custom_default_report, default_input_form
from Globals import HTMLFile, MessageDialog from Globals import HTMLFile, MessageDialog
...@@ -24,6 +24,11 @@ log_file=None ...@@ -24,6 +24,11 @@ log_file=None
import sys, traceback import sys, traceback
from DocumentTemplate import HTML from DocumentTemplate import HTML
import Globals, OFS.SimpleItem, AccessControl.Role, Persistence import Globals, OFS.SimpleItem, AccessControl.Role, Persistence
from string import atoi, find
import IOBTree
from time import time
from zlib import compress, decompress
md5new=md5.new
addForm=HTMLFile('AqueductDA/daAdd') addForm=HTMLFile('AqueductDA/daAdd')
...@@ -31,7 +36,7 @@ def add(self,klass,id,title,key,arguments,template,REQUEST=None): ...@@ -31,7 +36,7 @@ def add(self,klass,id,title,key,arguments,template,REQUEST=None):
'Add a query' 'Add a query'
q=klass() q=klass()
q.id=id q.id=id
q.manage_edit(key,title,arguments,template) q.manage_edit(title,arguments,template,key)
self._setObject(id,q) self._setObject(id,q)
if REQUEST: return self.manage_main(self,REQUEST) if REQUEST: return self.manage_main(self,REQUEST)
...@@ -44,11 +49,32 @@ class DA( ...@@ -44,11 +49,32 @@ class DA(
'Database Adapter' 'Database Adapter'
icon ='AqueductDA/DBAdapter_icon.gif' icon ='AqueductDA/DBAdapter_icon.gif'
hasAqueductClientInterface=1
_col=None _col=None
sql_delimiter='\0' sql_delimiter='\0'
max_rows_=1000
cache_time_=0
max_cache_=100
rotor=None
key=''
class_name_=class_file_=''
manage=HTMLFile('AqueductDA/edit') manage_options=(
{'icon':icon, 'label':'Basic',
'action':'manage_main', 'target':'manage_main'},
{'icon':icon, 'label':'Advanced',
'action':'manage_advancedForm',
'target':'manage_main'},
{'icon':'AccessControl/AccessControl_icon.gif',
'label':'Access Control',
'action':'manage_rolesForm', 'target':'manage_main'},
{'icon':icon,
'label':'Try It',
'action':'index_html', 'target':'manage_main'},
)
manage_main=HTMLFile('AqueductDA/edit')
manage_advancedForm=HTMLFile('AqueductDA/advanced')
test_url___roles__=None test_url___roles__=None
def test_url_(self): def test_url_(self):
...@@ -57,34 +83,50 @@ class DA( ...@@ -57,34 +83,50 @@ class DA(
def quoted_src(self): return quotedHTML(self.src) def quoted_src(self): return quotedHTML(self.src)
def manage_edit(self,key,title,arguments,template,REQUEST=None): def _setKey(self, key):
if key:
self.key=key
self.rotor=Rotor(key)
elif self.__dict__.has_key('key'):
del self.key
del self.rotor
def manage_edit(self,title,arguments,template,key=None, REQUEST=None):
'change query properties' 'change query properties'
self.title=title self.title=title
self.key=key if key is not None: self._setKey(key)
self.rotor=Rotor(key)
self.arguments_src=arguments self.arguments_src=arguments
self._arg=parse(arguments) self._arg=parse(arguments)
self.src=template self.src=template
self.template=DocumentTemplate.HTML(template) self.template=DocumentTemplate.HTML(template)
if REQUEST: if REQUEST: return self.manage_editedDialog(REQUEST)
return MessageDialog(
title=self.id+' changed',
message=self.id+' has been changed sucessfully.',
action=REQUEST['URL2']+'/manage_main',
)
def manage_advanced(self, key, max_rows, max_cache, cache_time,
class_name, class_file,
REQUEST):
'Change advanced parameters'
self._setKey(key)
self.max_rows_ = max_rows
self.max_cache_, self.cache_time_ = max_cache, cache_time
self.class_name_, self.class_file_ = class_name, class_file
getBrain(self)
if REQUEST: return self.manage_editedDialog(REQUEST)
def manage_testForm(self, REQUEST): def manage_testForm(self, REQUEST):
"""Provide testing interface""" """Provide testing interface"""
input_src=default_input_form(self.title_or_id(), input_src=default_input_form(self.title_or_id(),
self._arg, 'manage_test') self._arg, 'manage_test',
'<!--#var manage_tabs-->')
return HTML(input_src)(self, REQUEST) return HTML(input_src)(self, REQUEST)
def manage_test(self, REQUEST): def manage_test(self, REQUEST):
'Perform an actual query' 'Perform an actual query'
result=self(REQUEST) result=self(REQUEST)
report=HTML(custom_default_report(self.id, result)) report=HTML(
'<html><BODY BGCOLOR="#FFFFFF" LINK="#000099" VLINK="#555555">\n'
'<!--#var manage_tabs-->\n%s\n</body></html>'
% custom_default_report(self.id, result))
return apply(report,(self,REQUEST),{self.id:result}) return apply(report,(self,REQUEST),{self.id:result})
def index_html(self, PARENT_URL): def index_html(self, PARENT_URL):
...@@ -95,15 +137,56 @@ class DA( ...@@ -95,15 +137,56 @@ class DA(
def _searchable_result_columns(self): return self._col def _searchable_result_columns(self): return self._col
def __call__(self,REQUEST): def _cached_result(self, DB__, query, compressed=0):
# Try to fetch from cache
if hasattr(self,'_v_cache'): cache=self._v_cache
else: cache=self._v_cache={}, IOBTree.Bucket()
cache, tcache = cache
max_cache=self.max_cache_
now=time()
t=now-self.cache_time_
if len(cache) > max_cache / 2:
keys=tcache.keys()
keys.reverse()
while keys and (len(keys) > max_cache or keys[-1] < t):
key=keys[-1]
q=tcache[key]
del tcache[key]
del cache[q]
del keys[-1]
if cache.has_key(query):
k, r = cache[query]
if k > t:
result=r
if not compressed: result=decompress(r)
else:
result=apply(DB__.query, query)
r=compress(result)
cache[query]= now, r
if compressed: return r
return result
def __call__(self,REQUEST=None):
if REQUEST is None: REQUEST=self.REQUEST
try: DB__=getattr(self, self.connection_id)() try: DB__=getattr(self, self.connection_id)()
except: raise 'Database Error', ( except: raise 'Database Error', (
'%s is not connected to a database' % self.id) '%s is not connected to a database' % self.id)
argdata=self._argdata(REQUEST) argdata=self._argdata(REQUEST)
query=self.template(self,argdata) query=self.template(self,argdata)
result=DB__.query(query)
result=Aqueduct.RDB.File(StringIO(result)) if self.cache_time_:
result=self._cached_result(DB__, (query, self.max_rows_))
else: result=DB__.query(query, self.max_rows_)
if hasattr(self, '_v_brain'): brain=self._v_brain
else: brain=getBrain(self)
result=Aqueduct.RDB.File(StringIO(result),brain)
columns=result._searchable_result_columns() columns=result._searchable_result_columns()
if columns != self._col: self._col=columns if columns != self._col: self._col=columns
return result return result
...@@ -119,13 +202,16 @@ class DA( ...@@ -119,13 +202,16 @@ class DA(
argdata=decodestring(argdata) argdata=decodestring(argdata)
argdata=self.rotor.decrypt(argdata) argdata=self.rotor.decrypt(argdata)
digest,argdata=argdata[:16],argdata[16:] digest,argdata=argdata[:16],argdata[16:]
if md5.new(argdata).digest() != digest: if md5new(argdata).digest() != digest:
raise 'Bad Request', 'Corrupted Data' raise 'Bad Request', 'Corrupted Data'
argdata=marshal.loads(argdata) argdata=marshal.loads(argdata)
query=apply(self.template,(self,),argdata) query=apply(self.template,(self,),argdata)
result=DB__.query(query) if self.cache_time_:
result=zlib.compress(result,1) result=self._cached_result(DB__, query, 1)
result=md5.new(result).digest()+result else:
result=DB__.query(query, self.max_rows_)
result=compress(result,1)
result=md5new(result).digest()+result
result=self.rotor.encrypt(result) result=self.rotor.encrypt(result)
result=base64.encodestring(result) result=base64.encodestring(result)
RESPONSE['content-type']='text/X-PyDB' RESPONSE['content-type']='text/X-PyDB'
...@@ -136,22 +222,108 @@ class DA( ...@@ -136,22 +222,108 @@ class DA(
result=str(RESPONSE.exception()) result=str(RESPONSE.exception())
serial=str(DateTime.now()) serial=str(DateTime.now())
if log_file: if log_file:
l=string.find(result,"Traceback (innermost last):") l=find(result,"Traceback (innermost last):")
if l >= 0: l=result[l:] if l >= 0: l=result[l:]
else: l=v else: l=v
log_file.write("%s\n%s %s, %s:\n%s\n" % ( log_file.write("%s\n%s %s, %s:\n%s\n" % (
'-'*30, serial, self.id, t, l)) '-'*30, serial, self.id, t, l))
log_file.flush() log_file.flush()
serial="Error number: %s\n" % serial serial="Error number: %s\n" % serial
serial=zlib.compress(serial,1) serial=compress(serial,1)
serial=md5.new(serial).digest()+serial serial=md5new(serial).digest()+serial
serial=self.rotor.encrypt(serial) serial=self.rotor.encrypt(serial)
serial=base64.encodestring(serial) serial=base64.encodestring(serial)
RESPONSE.setBody(serial) RESPONSE.setBody(serial)
def __getitem__(self, key):
self._arg[key] # raise KeyError if not an arg
return Traverse(self,{},key)
class Traverse:
"""Helper class for 'traversing' searches during URL traversal
"""
_r=None
_da=None
def __init__(self, da, args, name=None):
self._da=da
self._args=args
self._name=name
def __bobo_traverse__(self, REQUEST, key):
name=self._name
da=self._da
args=self._args
if name:
args[name]=key
return self.__class__(da, args)
elif da._arg.has_key(key): return self.__class__(da, args, key)
results=da(args)
if results:
if len(results) > 1:
try: return results[atoi(key)].__of__(da)
except: raise KeyError, key
else: raise KeyError, key
r=self._r=results[0].__of__(da)
if hasattr(r,'__bobo_traverse__'):
try: return r.__bobo_traverse__(REQUEST, key)
except: pass
try: return getattr(r,key)
except AttributeError, v:
if v!=key: raise AttributeError, v
return r[key]
def __getattr__(self, name):
r=self._r
if hasattr(r, name): return getattr(r,name)
return getattr(self._da, name)
braindir=SOFTWARE_HOME+'/Extensions'
def getBrain(self,
modules={},
):
'Check/load a class'
module=self.class_file_
class_name=self.class_name_
if not module and not class_name:
c=Aqueduct.RDB.NoBrains
self._v_brain=c
return c
if modules.has_key(module):
m=modules[module]
else:
d,n = os.path.split(module)
if d: raise ValueError, (
'The file name, %s, should be a simple file name' % module)
m={}
exec open("%s/%s.py" % (braindir, module)) in m
modules[module]=m
if not m.has_key(class_name): raise ValueError, (
'The class, %s, is not defined in file, %s' % (class_name, module))
c=m[class_name]
if not hasattr(c,'__bases__'):raise ValueError, (
'%s, is not a class' % class_name)
self._v_brain=c
return c
############################################################################## ##############################################################################
# #
# $Log: DA.py,v $ # $Log: DA.py,v $
# Revision 1.16 1997/12/05 21:33:13 jim
# major overhall to add record addressing, brains, and support for new interface
#
# Revision 1.15 1997/11/26 20:06:03 jim # Revision 1.15 1997/11/26 20:06:03 jim
# New Architecture, note that backward compatibility tools are needed # New Architecture, note that backward compatibility tools are needed
# #
......
...@@ -4,5 +4,5 @@ ...@@ -4,5 +4,5 @@
# install connection.dtml # install connection.dtml
# install daAdd.dtml # install daAdd.dtml
# install edit.dtml # install edit.dtml
# install main.dtml # install advanced.dtml
# install www www/%(package)s # install www www/%(package)s
<HTML><HEAD><TITLE><!--#var title_or_id--> Advanced Options</TITLE></HEAD>
<BODY BGCOLOR="#FFFFFF" LINK="#000099" VLINK="#555555">
<!--#var manage_tabs-->
<H2><!--#var title_or_id--> Advanced Options</H2>
<form action="manage_advanced" method="POST">
<table>
<tr> <th>ID</th>
<td><!--#var id--></td></tr>
<tr> <th>Title</th>
<td><!--#var title--></td></tr>
<tr> <th>Remote access encyption key</th>
<td><input name="key" size="40"
value="<!--#var key-->"></td></tr>
<tr> <th>Maximum number of rows retrieved</th>
<td><input name="max_rows:int" size="10"
value="<!--#var max_rows_-->"></td></tr>
<tr> <th>Maximum number of results in the cache</th>
<td><input name="max_cache:int" size="10"
value="<!--#var max_cache_-->"></td></tr>
<tr> <th>Maximum time (seconds) to cache results</th>
<td><input name="cache_time:int" size="10"
value="<!--#var cache_time_-->"></td></tr>
<tr><td> </td></tr>
<tr><td colspan=2><br><br>
You may specify a <strong>class</strong> for the data records. This
class must be defined in a file that resides in the <code>Extensions</code>
directory of this Principia installation.
</td>
<tr> <th>Class name</th>
<td><input name="class_name" size="40"
value="<!--#var class_name_-->"></td></tr>
<tr> <th>Class file</th>
<td><input name="class_file" size="40"
value="<!--#var class_file_-->"></td></tr>
<tr><td> </td></tr>
<tr><td></td><td><input type="SUBMIT" name="SUBMIT" value="Change"></td></tr>
</table>
</form>
</body></html>
...@@ -7,21 +7,19 @@ ...@@ -7,21 +7,19 @@
<table> <table>
<tr> <td><strong>Id:</strong></td> <tr> <th>Id</th>
<td><input name="id" size="40"></td></tr> <td><input name="id" size="40"></td></tr>
<tr> <td><strong>Title:</strong></td> <tr> <th>Title</th>
<td><input name="title" size="40"></td></tr> <td><input name="title" size="40"></td></tr>
<tr> <td><strong>Access key:</strong></td> <tr> <th>Arguments</th>
<td><input name="key" size="40"></td></tr>
<tr> <td><strong>Arguments:</strong></td>
<td><input name="arguments" size="40"></td></tr> <td><input name="arguments" size="40"></td></tr>
<tr> <td colspan=2><strong>Query template:</strong><br> <tr> <td colspan=2><strong>Query template</strong><br>
<textarea name="template:text" rows=10 cols=60> <textarea name="template:text" rows=10 cols=60>
select * select *
from data from data
</textarea></td></tr> </textarea></td></tr>
<tr><td></td><td> <tr><td><input type="hidden" name="key" value=""></td><td>
<input type="SUBMIT" name="SUBMIT" value="Add Server Query"> <input type="SUBMIT" name="SUBMIT" value="Add Server Query">
</td></tr> </td></tr>
......
...@@ -4,78 +4,17 @@ ...@@ -4,78 +4,17 @@
__doc__='''short description __doc__='''short description
$Id: dbi_db.py,v 1.3 1997/09/11 23:53:28 jim Exp $''' $Id: dbi_db.py,v 1.4 1997/12/05 21:33:16 jim Exp $'''
# Copyright # Copyright
# #
# Copyright 1996 Digital Creations, L.C., 910 Princess Anne # Copyright 1997 Digital Creations, Inc, 910 Princess Anne
# Street, Suite 300, Fredericksburg, Virginia 22401 U.S.A. All # Street, Suite 300, Fredericksburg, Virginia 22401 U.S.A. All
# rights reserved. Copyright in this software is owned by DCLC, # rights reserved.
# unless otherwise indicated. Permission to use, copy and
# distribute this software is hereby granted, provided that the
# above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear. Note that
# any product, process or technology described in this software
# may be the subject of other Intellectual Property rights
# reserved by Digital Creations, L.C. and are not licensed
# hereunder.
#
# Trademarks
#
# Digital Creations & DCLC, are trademarks of Digital Creations, L.C..
# All other trademarks are owned by their respective companies.
#
# No Warranty
#
# The software is provided "as is" without warranty of any kind,
# either express or implied, including, but not limited to, the
# implied warranties of merchantability, fitness for a particular
# purpose, or non-infringement. This software could include
# technical inaccuracies or typographical errors. Changes are
# periodically made to the software; these changes will be
# incorporated in new editions of the software. DCLC may make
# improvements and/or changes in this software at any time
# without notice.
#
# Limitation Of Liability
#
# In no event will DCLC be liable for direct, indirect, special,
# incidental, economic, cover, or consequential damages arising
# out of the use of or inability to use this software even if
# advised of the possibility of such damages. Some states do not
# allow the exclusion or limitation of implied warranties or
# limitation of liability for incidental or consequential
# damages, so the above limitation or exclusion may not apply to
# you.
#
#
# If you have questions regarding this software,
# contact:
#
# Jim Fulton, jim@digicool.com
#
# (540) 371-6909
#
# $Log: dbi_db.py,v $
# Revision 1.3 1997/09/11 23:53:28 jim
# Made RDB rendered remove 'l' from ends if ints.
#
# Revision 1.2 1997/08/06 14:26:45 jim
# *** empty log message ***
#
# Revision 1.1 1997/08/06 14:24:41 jim
# *** empty log message ***
#
# Revision 1.1 1997/07/25 15:49:42 jim
# initial
#
# Revision 1.1 1997/01/27 22:11:16 jim
# *** empty log message ***
#
#
# #
__version__='$Revision: 1.3 $'[11:-2] __version__='$Revision: 1.4 $'[11:-2]
import string, sys import string, sys
from string import strip, split, find, join
failures=0 failures=0
calls=0 calls=0
...@@ -108,13 +47,12 @@ class DB: ...@@ -108,13 +47,12 @@ class DB:
if r[-1:]=='L' and type(v) is not StringType: r=r[:-1] if r[-1:]=='L' and type(v) is not StringType: r=r[:-1]
return r return r
def query(self,query_string): def query(self,query_string, max_rows=9999999):
global failures, calls global failures, calls
calls=calls+1 calls=calls+1
try: try:
c=self.cursor c=self.cursor
queries=filter(None, queries=filter(None, map(strip,split(query_string, '\0')))
map(string.strip,string.split(query_string, '\0')))
if not queries: raise 'Query Error', 'empty query' if not queries: raise 'Query Error', 'empty query'
if len(queries) > 1: if len(queries) > 1:
result=[] result=[]
...@@ -129,7 +67,7 @@ class DB: ...@@ -129,7 +67,7 @@ class DB:
query_string=queries[0] query_string=queries[0]
r=c.execute(query_string) r=c.execute(query_string)
if r is None: if r is None:
result=c.fetchall() result=c.fetchmany(max_rows)
desc=c.description desc=c.description
else: else:
result=((query_string, str(`r`), calls),) result=((query_string, str(`r`), calls),)
...@@ -141,12 +79,14 @@ class DB: ...@@ -141,12 +79,14 @@ class DB:
c.close() c.close()
self.db.rollback() self.db.rollback()
failures=failures+1 failures=failures+1
if ((string.find(mess,": invalid") < 0 and if ((find(mess,": invalid") < 0 and
string.find(mess,"PARSE") < 0) or find(mess,"PARSE") < 0) or
# DBI IS stupid # DBI IS stupid
string.find(mess,"Error while trying to retrieve text for error") > 0 or find(mess,
# If we have a large number of consecutive failures, our connection "Error while trying to retrieve text for error") > 0
# is probably dead. or
# If we have a large number of consecutive failures,
# our connection is probably dead.
failures > 100 failures > 100
): ):
# Hm. maybe the db is hosed. Let's try once to restart it. # Hm. maybe the db is hosed. Let's try once to restart it.
...@@ -162,10 +102,10 @@ class DB: ...@@ -162,10 +102,10 @@ class DB:
else: raise sys.exc_type, sys.exc_value, sys.exc_traceback else: raise sys.exc_type, sys.exc_value, sys.exc_traceback
if result: if result:
result=string.joinfields( result=join(
map( map(
lambda row, self=self: lambda row, self=self:
string.joinfields(map(self.str,row),'\t'), join(map(self.str,row),'\t'),
result), result),
'\n')+'\n' '\n')+'\n'
else: else:
...@@ -173,8 +113,8 @@ class DB: ...@@ -173,8 +113,8 @@ class DB:
return ( return (
"%s\n%s\n%s" % ( "%s\n%s\n%s" % (
string.joinfields(map(lambda d: d[0],desc), '\t'), join(map(lambda d: d[0],desc), '\t'),
string.joinfields( join(
map( map(
lambda d, defs=self.defs: "%d%s" % (d[2],defs[d[1]]), lambda d, defs=self.defs: "%d%s" % (d[2],defs[d[1]]),
desc), desc),
......
<HTML> <HTML><HEAD><TITLE>Edit <!--#var title_or_id--></TITLE></HEAD>
<HEAD>
<TITLE>
Edit
<!--#if title-->
<!--#var title-->
<!--#else title-->
<!--#var id-->
<!--#/if title-->
</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" LINK="#000099" VLINK="#555555"> <BODY BGCOLOR="#FFFFFF" LINK="#000099" VLINK="#555555">
<H2> <!--#var manage_tabs-->
Edit <H2>Edit <!--#var title_or_id--></H2>
<!--#if title-->
<!--#var title-->
<!--#else title-->
<!--#var id-->
<!--#/if title-->
</H2>
<P>
<form action="<!--#var URL2-->/<!--#var id-->/manage_edit" <form action="manage_edit" method="POST">
method="<!--#var web__form__method-->">
<table> <table>
<tr> <td><strong>ID:</strong></td> <tr> <th>ID</th>
<td><!--#var id--></td></tr> <td><!--#var id--></td></tr>
<tr> <td><strong>Title:</strong></td> <tr> <th>Title</th>
<td><input name="title" size="40" <td><input name="title" size="40"
value="<!--#var title-->"></td></tr> value="<!--#var title-->"></td></tr>
<tr> <td><strong>Access key:</strong></td> <tr> <th>Arguments</th>
<td><input name="key" size="40" value="<!--#var key-->"></td></tr> <td><input name="arguments" size="40"
<tr> <td><strong>Arguments:</strong></td> value="<!--#var arguments_src-->"></td>
<td><input name="arguments" size="40" value="<!--#var arguments_src-->"></td>
</tr> </tr>
<tr> <td colspan=2><strong>Query template:</strong><br> <tr> <td colspan=2><strong>Query template</strong><br>
<textarea name="template:text" rows=10 cols=60> <textarea name="template:text" rows=10 cols=60>
<!--#var quoted_src--> <!--#var quoted_src-->
</textarea></td></tr> </textarea></td></tr>
<tr><td></td><td> <tr><td></td><td><input type="SUBMIT" name="SUBMIT" value="Change"></td></tr>
<input type="SUBMIT" name="SUBMIT" value="OK">
<input type="SUBMIT" name="SUBMIT" value="Cancel">
<!--#if HTTP_REFERER-->
<INPUT NAME="CANCEL_ACTION" TYPE="HIDDEN" VALUE="<!--#var HTTP_REFERER-->">
<!--#else HTTP_REFERER-->
<INPUT NAME="CANCEL_ACTION" TYPE="HIDDEN" VALUE="<!--#var URL2-->/manage">
<!--#/if HTTP_REFERER-->
</td></tr>
</table> </table>
</form> </form>
</body> </body></html>
</html>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment