Commit 9e603ad7 authored by Jim Fulton's avatar Jim Fulton

new interfaces and RDB

parent 3ce0f3a9
......@@ -10,13 +10,14 @@
##############################################################################
__doc__='''Shared Aqueduct classes and functions
$Id: Aqueduct.py,v 1.7 1997/09/22 18:43:46 jim Exp $'''
__version__='$Revision: 1.7 $'[11:-2]
$Id: Aqueduct.py,v 1.8 1997/09/25 18:40:57 jim Exp $'''
__version__='$Revision: 1.8 $'[11:-2]
from Globals import HTMLFile
import DocumentTemplate, DateTime, regex, regsub, string, urllib, rotor
import binascii
DateTime.now=DateTime.DateTime
from cStringIO import StringIO
dtml_dir="%s/lib/python/Aqueduct/" % SOFTWARE_HOME
default_report_src=open(dtml_dir+'defaultReport.dtml').read()
......@@ -34,7 +35,7 @@ class BaseQuery:
MissingArgumentError='Bad Request'
def _argdata(self,REQUEST,raw=0,return_missing_keys=0):
args=self.arguments
args=self._arg
argdata={}
id=self.id
missing_keys=[]
......@@ -98,7 +99,6 @@ class BaseQuery:
def default_input_form(id,arguments,action='query'):
id=nicify(id)
if arguments:
return (
"%s\n%s%s" % (
......@@ -113,9 +113,17 @@ def default_input_form(id,arguments,action='query'):
map(
lambda a:
('<tr>\t<td><strong>%s</strong>:</td>\n'
'\t<td><input name="%s" width=30></td></tr>'
% (nicify(detypify(a)),a))
, arguments.keys()
'\t<td><input name="%s" width=30 value="%s">'
'</td></tr>'
% (nicify(a[0]),
(
a[1].has_key('type') and
("%s:%s" % (a[0],a[1]['type'])) or
a[0]
),
a[1].has_key('default') and a[1]['default'] or ''
))
, arguments.items()
),
'\n'),
'\n<tr><td></td><td>\n'
......@@ -149,28 +157,29 @@ def default_input_form(id,arguments,action='query'):
custom_default_report_src=DocumentTemplate.File(
dtml_dir+'customDefaultReport.dtml')
def custom_default_report(result, action=''):
names=result.names()
def custom_default_report(id, result, action=''):
columns=result._searchable_result_columns()
heading=('<tr>\n%s</tr>' %
string.joinfields(
map(lambda name:
'\t<th>%s</th>\n' % nicify(name),
names),
map(lambda c:
'\t<th>%s</th>\n' % nicify(c['name']),
columns),
''
)
)
row=('<tr>\n%s</tr>' %
string.joinfields(
map(lambda name, meta:
map(lambda c:
'\t\t<td><!--#var %s%s--></td>\n'
% (urllib.quote(name),
meta['type']!='s' and ' null=""' or '',
% (urllib.quote(c['name']),
c['type']!='s' and ' null=""' or '',
),
names, result.__items__),
columns),
''
)
)
return custom_default_report_src(heading=heading,row=row,action=action)
return custom_default_report_src(
id=id,heading=heading,row=row,action=action)
def detypify(arg):
l=string.find(arg,':')
......@@ -228,6 +237,45 @@ def parse(text,
return parse(text[l:],prefix,result)
def parse(text,
result=None,
unparmre=regex.compile(
'\([\0- ]*\([^\0- =\"]+\)\)'),
parmre=regex.compile(
'\([\0- ]*\([^\0- =\"]+\)=\([^\0- =\"]+\)\)'),
qparmre=regex.compile(
'\([\0- ]*\([^\0- =\"]+\)="\([^"]+\)\"\)'),
):
if result is None: result = {}
__traceback_info__=text
if parmre.match(text) >= 0:
name=parmre.group(2)
value={'default':parmre.group(3)}
l=len(parmre.group(1))
elif qparmre.match(text) >= 0:
name=qparmre.group(2)
value={'default':qparmre.group(3)}
l=len(qparmre.group(1))
elif unparmre.match(text) >= 0:
name=unparmre.group(2)
l=len(unparmre.group(1))
value={}
else:
if not text or not strip(text): return result
raise InvalidParameter, text
lt=string.find(name,':')
if lt > 0:
value['type']=name[lt+1:]
name=name[:lt]
result[name]=value
return parse(text[l:],prefix,result)
def quotedHTML(text,
character_entities=(
(regex.compile('&'), '&amp;'),
......@@ -312,22 +360,12 @@ def delimited_output(results,REQUEST,RESPONSE):
)
##############################################################################
# Test functions:
#
def main():
# The "main" program for this module
import sys
print sys.argv[0]+" is a pure module and doesn't do anything by itself."
if __name__ == "__main__": main()
##############################################################################
#
# $Log: Aqueduct.py,v $
# Revision 1.8 1997/09/25 18:40:57 jim
# new interfaces and RDB
#
# Revision 1.7 1997/09/22 18:43:46 jim
# Got rid of ManageHTML
#
......
......@@ -3,158 +3,43 @@
#
# Copyright
#
# Copyright 1997 Digital Creations, L.C., 910 Princess Anne
# Copyright 1996 Digital Creations, L.C., 910 Princess Anne
# Street, Suite 300, Fredericksburg, Virginia 22401 U.S.A. All
# rights reserved.
#
##############################################################################
__doc__='''Simple RDB data-file reader
__doc__='''Class for reading RDB files
$Id: RDB.py,v 1.3 1997/08/07 13:58:07 jim Exp $'''
__version__='$Revision: 1.3 $'[11:-2]
$Id: RDB.py,v 1.4 1997/09/25 18:40:58 jim Exp $'''
__version__='$Revision: 1.4 $'[11:-2]
import regex, regsub
from string import split, strip, lower, atof, atoi, atol
import DateTime
from Missing import MV
from array import array
from Record import Record
Parsers={'n': atof,
'i': atoi,
'l': atol,
'd': DateTime.DateTime,
}
try:
import DateTime
Parsers['d']=DateTime.DateTime
except: pass
class Record:
def __init__(self, data, schema, names):
'''Create a record with data'''
self._r_data=data
self._r_schema=schema
self._r_names=names
def __len__(self):
'''Return the record length'''
return len(self._r_data)
def __getattr__(self,name):
'''Get the value of the column with name, \'name\' '''
return self._r_data[self._r_schema[name]]
def __getitem__(self,key):
'''Get a value by key
The key may be either an integer column index or a string
column name.
'''
data=self._r_data
if type(key) is type(0): return data[key]
else: return self._r_data[self._r_schema[key]]
def update(self, *args, **name_value_pairs):
'''Update a record
The update method supports a number of syntaxes:
Multiple positional arguments --
In this case, the number of positional arguments must equal
the number of columns in the record.
A single positional argument with optional keyword parameters --
The single argument may be a list, a tuple, or a mapping
object.
If the argument is a list or a tuple, its length must be
equal to the length of the record. The items in the record
are replaced by the values in the argument.
If the argument is a mapping object, it must have a 'keys'
method that returns a sequence of keys. For those keys that
are record item names, the corresponding values are used to
update the record items. The argument may have keys that
are not item names, and it need not have keys for all item
names.
If keyword parameters are provided, they will be used to
update items in the record. All keyword names must match
item names, although keyword arguments need not be provided
for all items.
Keyword arguments with no positional arguments--
The keyword arguments are used to update items in the
record. All keyword names must match item names, although
keyword arguments need not be provided for all items.
For example, if a record, 'r' has items 'col1', 'col2', and 'col2',
then the following expressions are equivalent::
r.update('spam',1,2)
r.update({'col1':'spam', 'col3':2, 'col2': 1})
r.update(col2=1, col1='spam', col3=2)
Note that because records are mapping objects, one record can be
used to update another, even if the records have different schema.
'''
data=self._r_data
schema=self._r_schema
l=len(data)
la=len(args)
if la > 1:
if la != l: raise TypeError, (
'number of arguments does not match record length')
data[:]=list(args)
elif la==1:
args=args[0]
if type(args) is type(()) or type(args) is type([]):
if len(args) != l: raise TypeError, (
'number of arguments does not match record length')
data[:]=list(args)
else:
for k in args.keys():
try: data[schema[k]]=args[k]
except KeyError: pass
for k in name_value_pairs.keys():
data[schema[k]]=name_value_pairs[k]
def keys(self):
'''Return the item names in item order'''
# In this implementation, our class has this information handy
return self._r_item_names
def values(self):
'''Return our data values, in item order'''
return self._r_data[:]
def items(self):
'''Return a sequence of item name and item pairs
The sequence is returned in item order.'''
return map(None, self._r_names, self._r_data)
def has_key(self,key):
'''Return whether the given key is an item name'''
return self._schema.has_key(key)
class RDB:
class File:
"""Class for reading RDB files
"""
_index=None
def __init__(self,file,RecordClass=Record):
def __init__(self,file):
self._file=file
line=file.readline()
self._record_positions=[]
self._Record=RecordClass
readline=file.readline
line=readline()
comment_pattern=regex.compile('#')
while line and comment_pattern.match(line) >= 0: line=file.readline()
while line and comment_pattern.match(line) >= 0: line=readline()
line=line[:-1]
if line[-1:] in '\r\n': line=line[:-1]
......@@ -173,7 +58,7 @@ class RDB:
i=i+1
self._nv=nv=len(names)
line=file.readline()
line=readline()
line=line[:-1]
if line[-1:] in '\r\n': line=line[:-1]
......@@ -186,8 +71,9 @@ class RDB:
i=0
self._parsers=parsers=[]
self.__items__=__items__=[]
defre=regex.compile('\([0-9]*\)\([a-zA-Z]\)?[^\0- ]*[\0- ]*\(.+\)')
defre=regex.compile('\([0-9]*\)\([a-zA-Z]\)?')
self._data_dictionary=dd={}
self.__items__=items=[]
for _def in defs:
_def=strip(_def)
if not _def:
......@@ -196,31 +82,63 @@ class RDB:
raise ValueError, (
'Invalid column definition for, %s, for %s'
% _def, names[i])
width, type, remark = defre.group(1,2,3)
try: width=atoi(width)
except: width=8
type=lower(type)
type=lower(defre.group(2))
width=defre.group(1)
if width: width=atoi(width)
else: width=8
try: parser=Parsers[type]
except: parser=str
name=names[i]
d={'name': name, 'type': type, 'width': width, 'parser': parser}
items.append(d)
dd[name]=d
try: parsers.append(i,Parsers[type])
except: pass
__items__.append({'type':type, 'width': width, 'name': names[i],
'remark':remark})
parsers.append(i,parser)
i=i+1
self._index=-1
self._pos=file.tell()
# Create a record class to hold the records.
class r(Record): pass
r.__record_schema__=schema
self._class=r
# OK, we've read meta data, now get line indexes
p=file.tell()
save=self._lines=array('i')
save=save.append
l=readline()
while l:
save(p)
p=p+len(l)
l=readline()
def _searchable_result_columns(self): return self.__items__
def names(self): return self._names
def data_dictionary(self): return self._data_dictionary
def parse(self, line, _index=-1):
def __len__(self): return len(self._lines)
def __getitem__(self,index):
if index==self._index: return self._row
file=self._file
file.seek(self._lines[index])
line=file.readline()
line=line[:-1]
while line[-1:] in '\r\n': line=line[:-1]
fields=split(line,'\t')
if len(fields) != self._nv: raise ValueError, (
"""The number of items in record %s is invalid
<pre>%s\n%s\n%s\n%s</pre>
"""
% (_index, ('='*40), line, ('='*40), fields))
if line[-1:] in '\r\n': line=line[:-1]
fields=split(line,'\t')
l=len(fields)
nv=self._nv
if l != nv:
if l < nv:
fields=fields+['']*(nv-l)
else:
raise ValueError, (
"""The number of items in record %s is invalid
<pre>%s\n%s\n%s\n%s</pre>
"""
% (index, ('='*40), line, ('='*40), fields))
for i, parser in self._parsers:
try: v=parser(fields[i])
except:
......@@ -228,102 +146,30 @@ class RDB:
raise ValueError, (
"""Invalid value, %s, for %s in record %s"""
% (fields[i], self._names[i], _index))
else: v=None
else: v=MV
fields[i]=v
return fields
def __len__(self):
_index=self._index
try: pos=self._pos
except: return _index+1
file=self._file
readline=file.readline
tell=file.tell
if pos != tell(): file.seek(pos)
save_position=self._record_positions.append
while 1:
line=readline()
if not line:
del self._pos
self._index=_index
return _index+1
_index=_index+1
save_position(pos)
pos=tell()
def __getitem__(self,input_index):
index=input_index
if index < 0:
index=len(self)-index
if index < 0: raise IndexError, input_index
_index=self._index
if index==_index:
try: return self._row
except: pass
if index > _index:
try: pos=self._pos
except: raise IndexError, input_index
file=self._file
readline=file.readline
tell=file.tell
if pos != tell(): file.seek(pos)
save_position=self._record_positions.append
while index > _index:
line=readline()
if not line:
del self._pos
self._index=_index
raise IndexError, input_index
_index=_index+1
save_position(pos)
pos=tell()
if index == _index:
self._pos=pos
self._index=_index
self._row=line=self._Record(
self.parse(line,_index), self._schema, self._names)
return line
else:
file=self._file
file.seek(self._record_positions[index])
return self._Record(
self.parse(file.readline(), index), self._schema, self._names)
raise IndexError, input_index
class rdb:
def __init__(self, file):
self._file=file
##############################################################################
# Test functions:
#
def main():
# The "main" program for this module
import sys
print sys.argv[0]+" is a pure module and doesn't do anything by itself."
if __name__ == "__main__": main()
fields=self._class(fields)
self._index=index
self._row=fields
return fields
##############################################################################
#
# $Log: RDB.py,v $
# Revision 1.3 1997/08/07 13:58:07 jim
# Fixed bug in date-time handling.
# Revision 1.4 1997/09/25 18:40:58 jim
# new interfaces and RDB
#
# Revision 1.4 1997/09/18 17:43:10 jim
# Updated to use Missing.
#
# Revision 1.3 1997/09/12 18:37:11 jim
# Many changes leading to TextIndexes and many bug fixes.
#
# Revision 1.2 1997/07/28 21:30:13 jim
# Fixed bug in handling errors.
# Revision 1.2 1997/09/02 21:24:06 jim
# *** empty log message ***
#
# Revision 1.1 1997/07/25 16:07:19 jim
# initial
# Revision 1.1 1997/08/13 19:15:24 jim
# Converted name->id, description->title, copied from component
#
#
<html> <head>
<title><!--#if title-->
<!--#var title--><!--#else title-->
<!--#var id--><!--#/if title--> Results</title>
</head>
<body>
<FONT SIZE="+2" COLOR="#77003B"><!--#if title-->
<!--#var title--><!--#else title-->
<!--#var id--><!--#/if title--> Results</FONT><br>
<em>As of <!--#var query_date-->
</em><br><br>
<!--#if query_results-->
<p>Results for this
<a href="<!--#var URL2-->/<!--#var id-->%(action)s"><!--#if title-->
<!--#var title--><!--#else title-->
<!--#var id--><!--#/if title--> query</a>:</p>
<!--#in query_results size=50 start=query_start-->
<!--#in %(id)s size=50 start=query_start-->
<!--#if sequence-start-->
<!--#if previous-sequence-->
<a href="<!--#var
......@@ -52,17 +32,10 @@
</a>
<!--#/if next-sequence-->
<!--#/if sequence-end-->
<!--#/in query_results-->
<!--#else query_results-->
<!--#else-->
There was no data matching this.
<!--#if title-->
<!--#var title--><!--#else title-->
<!--#var id--><!--#/if title-->
<a href="<!--#var URL2-->/<!--#var id-->%(action)s">
query</a>.
There was no data matching this <!--#var title_or_id--> query.
<!--#/if query_results-->
<!--#/in-->
</body> </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