xsl DocBook stylesheets.

This commit is contained in:
david 2002-06-19 20:30:18 +00:00
parent 9293e7d8cd
commit c3c1573efa
25 changed files with 2046 additions and 1207 deletions

View File

@ -1,14 +1,21 @@
Copyright 2000, 2001, 2002 David C. Merrill <david@lupercalia.net>, Lead Developer
Rick Welykochy <rick@praxis.com.au>, bugfixes for the original LDP Database
The KDE Project http://www.kde.org, for icons
Copyright 2002 Nicolas Chauvat <nicolas.chauvat@logilab.fr> for the Python port.
Copyright 2002 Xavier Antoviaque for the Python port.
David C. Merrill <david@lupercalia.net>, Lead Developer
Copyright 2000, 2001, 2002 David C. Merrill
Copyright 2002 Nicolas Chauvat <nicolas.chauvat@logilab.fr>
Copyright 2002 Xavier Antoviaque
Work in progress :
I18N support and french localization :
Thanks to:
Rick Welykochy <rick@praxis.com.au>, bugfixes for the original LDPDB
The KDE Project http://www.kde.org, for icons
Current Maintainers:
I18N support and french localization:
Nicolas Chauvat (started on 2002-05-24)
Mirroring and Document Conversion :
Mirroring and Document Conversion:
David Merrill

View File

@ -6,9 +6,9 @@ files.
Files are installed into the following locations by default. To change
them, edit the Makefiles.
binaries: /usr/local/bin
man pages: /usr/share/man/man5
/usr/share/man/man8
binaries: /usr/local/bin
man pages: /usr/share/man/man5
/usr/share/man/man8
Lampadas.pth: /usr/local/lib/site-python
python modules: /usr/local/lib/site-python/Lampadas
html, png, css: /usr/local/share/lampadas/www
@ -23,9 +23,15 @@ PostgreSQL (I think 6.x is okay, but have not tested it).
xsltproc for xml/xslt stylesheet processing
wt2db 0.4 or later for WikiText conversions
texi2db for Texinfo conversions
xmllint for SGML to XML conversions
jade or openjade for LinuxDoc conversions
xmllint for SGML to XML conversions and validation
docbook-to-man for manpage generation
docbook dtds
docbook xsl stylesheets from Norm Walsh
docbook dsssl stylesheets
linuxdoc dtds
linuxdoc dsssl stylesheets
tar for .tar and .tar.gz archive support
gunzip for .gz archive support
make for publishing static content
lynx for text output support

View File

@ -2,7 +2,7 @@ logprefix = /var/log
INSTALLDIR = install -d
all: bin pylib database www conf docs
all: bin pylib database www conf docs xsl
install: bin pylib www conf docs
$(INSTALLDIR) $(logprefix)/lampadas
@ -12,6 +12,7 @@ install: bin pylib www conf docs
cd www; $(MAKE) install
cd conf; $(MAKE) install
cd doc; $(MAKE) install
cd xsl; $(MAKE) install
echo "Lampadas installation complete."
clean:
@ -21,6 +22,7 @@ clean:
cd www; $(MAKE) clean
cd conf; $(MAKE) clean
cd doc; $(MAKE) clean
cd xsl; $(MAKE) clean
bin:
cd bin; $(MAKE) all
@ -40,3 +42,6 @@ conf:
docs:
cd doc; $(MAKE) all
xsl:
cd xsl; $(MAKE) all

View File

@ -5,10 +5,6 @@ Lampadas is a young project, although it is based on the LDP Database,
which has been in actual use for over a year. It is not yet recommended
for production use.
Requirements
------------
See INSTALL for requirements.
@ -17,25 +13,32 @@ Applicable Standards
Lampadas adheres to the following standards:
ISO 8879, Standard Generalized Markup Language
XML?
HTML?
CSS?
XSLT?
ISO 639 Language Codes, http://www.w3.org/WAI/ER/IG/ert/iso639.htm
Unicode Encoding, http://www.unicode.org/unicode/standard/standard.html
DocBook XML DTD
OMF XML DTD
Security
--------
Anyone may browse and search the database, however only registered users can
make changes to the database at this time.
make changes to the database.
Each user is recorded in the `username' table. If the 'admin' field is 't',
the user may alter any document information in the database. If the 'sysadmin'
field is set to 't', the user may also alter system data, such as
configuration records. If the document_user table has a record for a user,
the user may edit those documents and their meta-data.
the user may edit any assigned documents and their meta-data.
Admins may add new maintainers and documents.
Only admins and authors may edit documents, and authors may only edit their
Only admins and authors may edit documents, but authors may only edit their
own documents.
The SysAdmin level allows very low level system configuration. I recommend

View File

@ -17,11 +17,12 @@ just be a call to that library. So put the Python module in pylib, but put the
wrapper script under /lampadas/cron (a new directory). See the old Perl code,
and just port it. Feel free to recommend additional metrics that would be
valuable to the management of the site. Also add user count, which didn't
apply to the LDPL but does apply to Lampadas. And docs served, pages served.
apply to the LDPDB but does apply to Lampadas. And docs served, pages served.
Write a Makefile to install Lampadas onto a fresh system. Also let `make test`
run the unit tests, and `make clean` remove any installation. `make tar` and
other build targets would be nice, too.
-- wrote Makefiles, but no test target yet
Add date_entered timestamps to additional records where it is appropriate.
Maybe even to all of them. It's nice meta-data to have. And add creator_id
@ -74,6 +75,7 @@ high priority because it will give us a huge amount of visibility and help
build the project.
Write manpage.
-- done, for lampadasdb and lampadasweb
Need mod_perl front end.

View File

@ -9,128 +9,130 @@ import StringIO
import shutil
import StringIO
import BaseHTTPServer
import CGIHTTPServer
from Log import Log
from Config import config
from Log import log
from HTML import PageFactory
from Globals import VERSION
import Config
from URLParse import URI
Log = Log()
Config = Config.Config()
P = PageFactory()
BaseClass = BaseHTTPServer.BaseHTTPRequestHandler
#BaseClass = BaseHTTPServer.BaseHTTPRequestHandler
BaseClass = CGIHTTPServer.CGIHTTPRequestHandler
class RequestHandler(BaseClass):
"""
Intercepts the HTTP requests and serves them.
"""
def do_GET(self):
fd = self.send_head()
if fd:
shutil.copyfileobj(fd, self.wfile)
fd.close
def do_HEAD(self):
fd = self.send_head()
fd.close()
def send_head(self):
"""
Send the requested page.
"""
uri = URI(self.path)
filename = Config.FileDir + uri.Path + uri.Filename
filename = filename.replace('//','/')
Log.Write(3, 'looking for file ' + filename)
if os.path.isfile(filename):
return self.send_File(filename)
"""
Intercepts the HTTP requests and serves them.
"""
def do_GET(self):
fd = self.send_head()
if fd:
shutil.copyfileobj(fd, self.wfile)
fd.close
def do_HEAD(self):
fd = self.send_head()
fd.close()
def send_head(self):
"""
Send the requested page
"""
uri = URI(self.path)
print uri.Path
print uri.Filename
filename = config.file_dir + uri.path + '/' + uri.filename
filename = filename.replace('//','/')
Log.Write(3, 'looking for file ' + filename)
if os.path.isfile(filename):
return self.send_File(filename)
Log.Write(3, 'Sending dynamic page')
return self.send_HTML(P.Page(self.path, 'EN'))
Log.Write(3, 'Sending dynamic page')
return self.send_HTML(P.Page(self.path))
def send_HTML(self, HTML):
"""
Send the passed HTML page.
"""
self.send_response(200)
self.send_header("Content-type", "text/html")
self.send_header("Content-length", len(HTML))
self.end_headers()
return StringIO.StringIO(HTML)
def send_File(self, filename):
"""
Send the requested file.
"""
Log.Write(3, 'Sending file ' + filename)
temp = string.split(filename, ".")
if len(temp) > 1:
fileext = temp[1]
else:
if os.path.isfile(filename + ".png"):
fileext = "png"
elif os.path.isfile(filename + ".jpeg"):
fileext = "jpeg"
if os.path.isfile(filename + ".jpg"):
fileext = "jpg"
if os.path.isfile(filename + ".gif"):
fileext = "gif"
if fileext:
filename += "." + fileext
def send_HTML(self, HTML):
"""
Send the passed HTML page.
"""
self.send_response(200)
self.send_header("Content-type", "text/html")
self.send_header("Content-length", len(HTML))
self.end_headers()
return StringIO.StringIO(HTML)
def send_File(self, filename):
"""
Send the requested file.
"""
Log.Write(3, 'Sending file ' + filename)
temp = string.split(filename, ".")
if len(temp) > 1:
fileext = temp[1]
else:
if os.path.isfile(filename + ".png"):
fileext = "png"
elif os.path.isfile(filename + ".jpeg"):
fileext = "jpeg"
if os.path.isfile(filename + ".jpg"):
fileext = "jpg"
if os.path.isfile(filename + ".gif"):
fileext = "gif"
if fileext:
filename += "." + fileext
# Determine mimetype from extension
if fileext == "html" or fileext == "htm":
mimetype = "text/html"
elif fileext == "png":
mimetype = "image/png"
elif fileext == "gif":
mimetype = "image/gif"
elif fileext == "jpg" or fileext == "jpeg":
mimetype = "image/jpeg"
elif fileext == "css":
mimetype = "text/css"
else:
mimetype = "text/plain"
# Determine mimetype from extension
if fileext == "html" or fileext == "htm":
mimetype = "text/html"
elif fileext == "png":
mimetype = "image/png"
elif fileext == "gif":
mimetype = "image/gif"
elif fileext == "jpg" or fileext == "jpeg":
mimetype = "image/jpeg"
elif fileext == "css":
mimetype = "text/css"
else:
mimetype = "text/plain"
fd = open(filename, 'r')
filesize = os.fstat(fd.fileno())[stat.ST_SIZE]
self.send_response(200)
self.send_header("Content-type", mimetype)
self.send_header("Content-length", filesize)
self.end_headers()
return fd
fd = open(filename, 'r')
filesize = os.fstat(fd.fileno())[stat.ST_SIZE]
self.send_response(200)
self.send_header("Content-type", mimetype)
self.send_header("Content-length", filesize)
self.end_headers()
return fd
def send_Text(self, text):
"""
Send a text message.
"""
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.send_header("Content-length", len(text))
self.end_headers()
return StringIO.StringIO(text)
def send_Text(self, text):
"""
Send a text message.
"""
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.send_header("Content-length", len(text))
self.end_headers()
return StringIO.StringIO(text)
def WebServer():
"""
Initialize the server.
"""
interface = Config.Interface
port = Config.Port
"""
Initialize the server.
"""
interface = config.interface
port = config.port
print "Lampadas " + VERSION + " -- development version!"
if interface != '':
print '(Listening on interface %s, port %s)' % (interface, port)
else:
print '(Listening on all interfaces, port %s)' % port
server = BaseHTTPServer.HTTPServer((interface, port), RequestHandler)
server.serve_forever()
print "Lampadas " + VERSION + " -- development version!"
if interface != '':
print '(Listening on interface %s, port %s)' % (interface, port)
else:
print '(Listening on all interfaces, port %s)' % port
# server = BaseHTTPServer.HTTPServer((interface, port), RequestHandler)
server = CGIHTTPServer.BaseHTTPServer.HTTPServer((interface, port), RequestHandler)
server.serve_forever()
if __name__ == '__main__':
WebServer()
WebServer()

View File

@ -1,5 +1,23 @@
#!/usr/bin/python
#
# This file is part of the Lampadas Documentation System.
#
# Copyright (c) 2000, 2001, 2002 David Merrill <david@lupercalia.net>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
These base classes are used to build other Lampadas objects upon.
"""

View File

@ -1,5 +1,23 @@
#!/usr/bin/python
#
# This file is part of the Lampadas Documentation System.
#
# Copyright (c) 2000, 2001, 2002 David Merrill <david@lupercalia.net>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Lampadas Configuration module
@ -11,81 +29,91 @@ This module provides configuration information from lampadas.conf.
# Globals
CONF_FILE = '/etc/lampadas.conf'
CONF_FILE = '/etc/lampadas/lampadas.conf'
# BaseConfig ###############################################################
class ConfigFileReadErrorException(Exception) :
pass
pass
class Config:
"""
Basic configuration options (dbname, dbtype), used to know where we can find
the database.
"""
"""
Basic configuration options (dbname, dbtype), used to know where we can find
the database.
"""
DBType = ''
DBName = ''
LogFile = ''
LogLevel = 0
LogSQL = ''
LogConsole = 0
Interface = ''
Port = 80
Hostname = ''
RootDir = ''
FileDir = ''
CVSRoot = ''
CacheDir = ''
db_type = ''
db_name = ''
log_file = ''
log_level = 0
log_sql = ''
log_console = 0
interface = ''
port = 80
hostname = ''
root_dir = ''
file_dir = ''
cvs_root = ''
cache_dir = ''
xslt_html = ''
xslt_chunk = ''
xslt_print = ''
def __init__(self) :
import ConfigParser
def __init__(self) :
import ConfigParser
self.config = ConfigParser.ConfigParser()
self.config.readfp(open(CONF_FILE))
self.config = ConfigParser.ConfigParser()
self.config.readfp(open(CONF_FILE))
self.DBType = self.ReadVar('DB', 'dbtype')
self.DBName = self.ReadVar('DB', 'dbname')
self.LogFile = self.ReadVar('LOG', 'logfile')
self.LogLevel = int(self.ReadVar('LOG', 'loglevel'))
self.LogSQL = int(self.ReadVar('LOG', 'logsql'))
self.LogConsole = int(self.ReadVar('LOG', 'logcon'))
self.Interface = self.ReadVar('WEBSERVER', 'interface')
self.Port = int(self.ReadVar('WEBSERVER', 'port'))
self.Hostname = self.ReadVar('WEBSERVER', 'hostname')
self.RootDir = self.ReadVar('WEBSERVER', 'rootdir')
self.FileDir = self.ReadVar('WEBSERVER', 'filedir')
self.CVSRoot = self.ReadVar('CVS', 'cvsroot')
self.cache_dir = self.ReadVar('MIRROR', 'cachedir')
self.db_type = self.read_var('DB', 'dbtype')
self.db_name = self.read_var('DB', 'dbname')
self.log_file = self.read_var('LOG', 'logfile')
self.log_level = int(self.read_var('LOG', 'loglevel'))
self.log_sql = int(self.read_var('LOG', 'logsql'))
self.log_console = int(self.read_var('LOG', 'logcon'))
self.interface = self.read_var('WEBSERVER', 'interface')
self.port = int(self.read_var('WEBSERVER', 'port'))
self.hostname = self.read_var('WEBSERVER', 'hostname')
self.root_dir = self.read_var('WEBSERVER', 'rootdir')
self.file_dir = self.read_var('WEBSERVER', 'filedir')
self.cvs_root = self.read_var('CVS', 'cvsroot')
self.cache_dir = self.read_var('MIRROR', 'cachedir')
self.xslt_html = self.read_var('XSLT', 'xslt_html')
self.xslt_chunk = self.read_var('XSLT', 'xslt_chunk')
self.xslt_print = self.read_var('XSLT', 'xslt_print')
def ReadVar(self, section, name):
if not self.config.has_section(section) :
raise ConfigFileReadErrorException("File '" + CONF_FILE + "' is missing or does not contain a '" + section + "' section")
def read_var(self, section, name):
if not self.config.has_section(section) :
raise ConfigFileReadErrorException("File '" + CONF_FILE + "' is missing or does not contain a '" + section + "' section")
if not self.config.has_option(section, name):
raise ConfigFileReadErrorException("Can't read option '" + name + "' from " + CONF_FILE)
if not self.config.has_option(section, name):
raise ConfigFileReadErrorException("Can't read option '" + name + "' from " + CONF_FILE)
return self.config.get(section, name)
return self.config.get(section, name)
## exports ##
config = Config()
# main
if __name__ == '__main__' :
print "Running unit tests..."
Config = Config()
assert Config.DBType > ''
print "DBType= " + Config.DBType
assert Config.DBName > ''
print "DBName= " + Config.DBName
assert Config.LogFile > ''
print "LogFile=" + Config.LogFile
print "LogSQL=" + str(Config.LogSQL)
print "LogConsole=" + str(Config.LogConsole)
print "Interface=" + Config.Interface
print "Port=" + str(Config.Port)
print "Hostname=" + Config.Hostname
print "RootDir=" + Config.RootDir
print "CVSRoot=" + Config.CVSRoot
print "FileDir=" + Config.FileDir
print "cache_dir=" + Config.cache_dir
print "Unit tests complete."
print "Running unit tests..."
assert config.db_type > ''
print "db_type= " + config.db_type
assert config.db_name > ''
print "db_name= " + config.db_name
assert config.log_file > ''
print "log_file=" + config.log_file
print "log-sql=" + str(config.log_sql)
print "log_console=" + str(config.log_console)
print "interface=" + config.interface
print "port=" + str(config.port)
print "hostname=" + config.hostname
print "root_dir=" + config.root_dir
print "cvs_root=" + config.cvs_root
print "file_dir=" + config.file_dir
print "cache_dir=" + config.cache_dir
print "xslt_html=" + config.xslt_html
print "xslt_chunk=" + config.xslt_chunk
print "xslt_print=" + config.xslt_print
print "Unit tests complete."

View File

@ -1,8 +1,30 @@
#!/usr/bin/python
#
# This file is part of the Lampadas Documentation System.
#
# Copyright (c) 2000, 2001, 2002 David Merrill <david@lupercalia.net>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Lampadas Conversion Module
NOTE: This module is obsolete. When I realized every conversion
was a call to an external program, I began writing a Makefile for
each document during the mirroring process.
This module converts source documents into DocBook XML format.
Currently supported source formats are:
@ -11,11 +33,15 @@ Currently supported source formats are:
WikiText
Texinfo
DocBook SGML
Linuxdoc
Working on:
Linuxdoc
Pie-in-the-sky:
DebianDoc
PyDoc
*roff
"""
# Modules ##################################################################
@ -38,7 +64,7 @@ class Converter:
def text(self, Filename, Format):
Log(3, 'Converting ' + Filename + ' from text')
return WikiText(Filename)
return wikitext(Filename)
def wikitext(self, Filename):
Log(3, 'Converting ' + Filename + ' from WikiText')
@ -52,32 +78,25 @@ class Converter:
result = commands.getoutput(command)
return result
def dbsgml(self, Filename):
Log(3, 'Converting ' + Filename + ' from DocBook SGML')
command = 'xmllint --sgml ' + Filename
result = commands.getoutput(command)
return result
def ldsgml(self, Filename):
Log(3, 'Converting ' + Filename + ' from LinuxDoc SGML')
command = ''
result = commands.getoutput(command)
return result
def xml(self, Filename):
command = 'xsltproc /usr/share/sgml/docbook/stylesheet/xsl/nwalsh/html/docbook.xsl ' + Filename
result = commands.getoutput(command)
return result
def sgml(self, Filename, Format):
command = 'xsltproc --docbook /usr/share/sgml/docbook/stylesheet/xsl/nwalsh/html/docbook.xsl ' + Filename
def dbsgml(self, Filename):
Log(3, 'Converting ' + Filename + ' from DocBook SGML')
command = 'xmllint --sgml ' + Filename
result = commands.getoutput(command)
return result
if __name__ == "__main__":
def main():
C = Converter()
# output = C.texinfo('test/texinfo/texinfo.txi')
output = C.dbsgml('test/db3.0sgml/RPM-HOWTO.sgml')
print output
if __name__ == "__main__":
main()

View File

@ -1,5 +1,23 @@
#!/usr/bin/python
#
# This file is part of the Lampadas Documentation System.
#
# Copyright (c) 2000, 2001, 2002 David Merrill <david@lupercalia.net>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Lampadas Object Hierarchy Module
@ -15,18 +33,14 @@ performed through this layer.
from Globals import *
from BaseClasses import *
import Config
import Database
import Log
from Config import config
from Database import db
from Log import log
# Globals
Config = Config.Config()
DB = Database.Database()
DB.Connect(Config.DBType, Config.DBName)
Log = Log.Log()
db.connect(config.db_type, config.db_name)
# Lampadas
@ -42,19 +56,18 @@ class Lampadas:
"""
def __init__(self):
self.Log = Log
self.Classes = Classes()
self.Classes = Classes()
self.Classes.Load()
self.Config = Cfg()
self.Docs = Docs()
self.Config = Cfg()
self.Docs = Docs()
self.Docs.Load()
self.DTDs = DTDs()
self.Formats = Formats()
self.Languages = Languages()
self.PubStatuses = PubStatuses()
self.ReviewStatuses = ReviewStatuses()
self.Topics = Topics()
self.Users = Users()
self.DTDs = DTDs()
self.Formats = Formats()
self.Languages = Languages()
self.PubStatuses = PubStatuses()
self.ReviewStatuses = ReviewStatuses()
self.Topics = Topics()
self.Users = Users()
def User(self, UserID):
return User(UserID)
@ -72,7 +85,7 @@ class Classes(LampadasCollection):
def Load(self):
self.sql = "SELECT class_id FROM class"
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
row = self.cursor.fetchone()
if row == None: break
@ -94,7 +107,7 @@ class Class:
def Load(self, row):
self.ID = row[0]
self.sql = "SELECT lang, class_name, class_description FROM class_i18n WHERE class_id=" + str(self.ID)
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
self.row = self.cursor.fetchone()
if self.row == None: break
@ -129,7 +142,7 @@ class Cfg(LampadasCollection):
def Load(self):
self.sql = "SELECT name, value FROM config"
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
row = self.cursor.fetchone()
if row == None: break
@ -145,81 +158,82 @@ class Docs(LampadasCollection):
def Load(self):
self.sql = "SELECT doc_id, title, class_id, format_id, dtd, dtd_version, version, last_update, url, isbn, pub_status, review_status, tickle_date, pub_date, ref_url, tech_review_status, maintained, license, abstract, rating, lang, sk_seriesid FROM document"
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
Log(3, 'Loading document')
self.row = self.cursor.fetchone()
if self.row == None: break
newDoc = Doc()
newDoc.Load(self.row)
newDoc.LoadRow(self.row)
self[newDoc.ID] = newDoc
Log(3, 'Loaded document ' + str(newDoc.ID))
# FIXME: try instantiating a new document, then adding *it* to the collection,
# rather than passing in all these parameters.
def Add(self, Title, ClassID, FormatID, DTD, DTDVersion, Version, LastUpdate, URL, ISBN, PubStatusCode, ReviewStatus, TickleDate, PubDate, HomeURL, TechReviewStatus, License, Abstract, Lang, SeriesID):
self.id = DB.Value('SELECT max(doc_id) from document') + 1
self.id = db.value('SELECT max(doc_id) from document') + 1
self.sql = "INSERT INTO document(doc_id, title, class_id, format_id, dtd, dtd_version, version, last_update, url, isbn, pub_status, review_status, tickle_date, pub_date, ref_url, tech_review_status, license, abstract, lang, sk_seriesid) VALUES (" + str(self.id) + ", " + wsq(Title) + ", " + str(ClassID) + ", " + dbint(FormatID) + ", " + wsq(DTD) + ", " + wsq(DTDVersion) + ", " + wsq(Version) + ", " + wsq(LastUpdate) + ", " + wsq(URL) + ", " + wsq(ISBN) + ", " + wsq(PubStatusCode) + ", " + wsq(ReviewStatus) + ", " + wsq(TickleDate) + ", " + wsq(PubDate) + ", " + wsq(HomeURL) + ", " + wsq(TechReviewStatus) + ", " + wsq(License) + ", " + wsq(Abstract) + ", " + wsq(Lang) + ", " + wsq(SeriesID) + ")"
assert DB.Exec(self.sql) == 1
DB.Commit()
self.NewID = DB.Value('SELECT MAX(doc_id) from document')
assert db.run_sql(self.sql) == 1
db.commit()
self.NewID = db.value('SELECT MAX(doc_id) from document')
newDoc = Doc(self.NewID)
self[self.NewID] = newDoc
return self.NewID
def Del(self, id):
self.sql = ('DELETE from document WHERE doc_id=' + str(id))
assert DB.Exec(self.sql) == 1
DB.Commit()
assert db.runsql(self.sql) == 1
db.commit()
del self[id]
class Doc:
"""
A document in any format, whether local or remote.
"""
"""
A document in any format, whether local or remote.
"""
def __init__(self, id=None):
if id == None: return
self.sql = "SELECT doc_id, title, class_id, format_id, dtd, dtd_version, version, last_update, url, isbn, pub_status, review_status, tickle_date, pub_date, ref_url, tech_review_status, maintained, license, abstract, rating, lang, sk_seriesid FROM document WHERE doc_id=" + str(id)
self.cursor = DB.Select(self.sql)
self.row = self.cursor.fetchone()
self.Load(self.row)
def __init__(self, id=None):
if id == None: return
self.Load(id)
def Load(self, row):
self.ID = row[0]
self.Title = trim(row[1])
self.ClassID = row[2]
self.FormatID = row[3]
self.DTD = trim(row[4])
self.DTDVersion = trim(row[5])
self.Version = trim(row[6])
self.LastUpdate = trim(row[7])
self.URL = trim(row[8])
self.ISBN = trim(row[9])
self.PubStatusCode = trim(row[10])
self.ReviewStatus = trim(row[11])
self.TickleDate = trim(row[12])
self.PubDate = trim(row[13])
self.HomeURL = trim(row[14])
self.TechReviewStatus = trim(row[15])
self.Maintained = tf2bool(row[16])
self.License = trim(row[17])
self.Abstract = trim(row[18])
self.Rating = safeint(row[19])
self.Lang = trim(row[20])
self.SeriesID = trim(row[21])
def Load(self, id):
sql = "SELECT doc_id, title, class_id, format_id, dtd, dtd_version, version, last_update, url, isbn, pub_status, review_status, tickle_date, pub_date, ref_url, tech_review_status, maintained, license, abstract, rating, lang, sk_seriesid FROM document WHERE doc_id=" + str(id)
cursor = db.select(sql)
row = cursor.fetchone()
self.LoadRow(row)
self.Errs = DocErrs(self.ID)
self.Files = DocFiles(self.ID)
self.Ratings = DocRatings(self.ID)
self.Ratings.Parent = self
self.Versions = DocVersions(self.ID)
def LoadRow(self, row):
self.ID = row[0]
self.Title = trim(row[1])
self.ClassID = row[2]
self.FormatID = row[3]
self.DTD = trim(row[4])
self.DTDVersion = trim(row[5])
self.Version = trim(row[6])
self.LastUpdate = trim(row[7])
self.URL = trim(row[8])
self.ISBN = trim(row[9])
self.PubStatusCode = trim(row[10])
self.ReviewStatus = trim(row[11])
self.TickleDate = trim(row[12])
self.PubDate = trim(row[13])
self.HomeURL = trim(row[14])
self.TechReviewStatus = trim(row[15])
self.Maintained = tf2bool(row[16])
self.License = trim(row[17])
self.Abstract = trim(row[18])
self.Rating = safeint(row[19])
self.Lang = trim(row[20])
self.SeriesID = trim(row[21])
def Save(self):
self.sql = "UPDATE document SET title=" + wsq(self.Title) + ", class_id=" + str(self.ClassID) + ", format_id=" + dbint(self.FormatID) + ", dtd=" + wsq(self.DTD) + ", dtd_version=" + wsq(self.DTDVersion) + ", version=" + wsq(self.Version) + ", last_update=" + wsq(self.LastUpdate) + ", url=" + wsq(self.URL) + ", isbn=" + wsq(self.ISBN) + ", pub_status=" + wsq(self.PubStatusCode) + ", review_status=" + wsq(self.ReviewStatus) + ", tickle_date=" + wsq(self.TickleDate) + ", pub_date=" + wsq(self.PubDate) + ", ref_url=" + wsq(self.HomeURL) + ", tech_review_status=" + wsq(self.TechReviewStatus) + ", maintained=" + wsq(bool2tf(self.Maintained)) + ", license=" + wsq(self.License) + ", abstract=" + wsq(self.Abstract) + ", rating=" + dbint(self.Rating) + ", lang=" + wsq(self.Lang) + ", sk_seriesid=" + wsq(self.SeriesID) + " WHERE doc_id=" + str(self.ID)
DB.Exec(self.sql)
DB.Commit()
self.Errs = DocErrs(self.ID)
self.Files = DocFiles(self.ID)
self.Ratings = DocRatings(self.ID)
self.Ratings.Parent = self
self.Versions = DocVersions(self.ID)
def Save(self):
self.sql = "UPDATE document SET title=" + wsq(self.Title) + ", class_id=" + str(self.ClassID) + ", format_id=" + dbint(self.FormatID) + ", dtd=" + wsq(self.DTD) + ", dtd_version=" + wsq(self.DTDVersion) + ", version=" + wsq(self.Version) + ", last_update=" + wsq(self.LastUpdate) + ", url=" + wsq(self.URL) + ", isbn=" + wsq(self.ISBN) + ", pub_status=" + wsq(self.PubStatusCode) + ", review_status=" + wsq(self.ReviewStatus) + ", tickle_date=" + wsq(self.TickleDate) + ", pub_date=" + wsq(self.PubDate) + ", ref_url=" + wsq(self.HomeURL) + ", tech_review_status=" + wsq(self.TechReviewStatus) + ", maintained=" + wsq(bool2tf(self.Maintained)) + ", license=" + wsq(self.License) + ", abstract=" + wsq(self.Abstract) + ", rating=" + dbint(self.Rating) + ", lang=" + wsq(self.Lang) + ", sk_seriesid=" + wsq(self.SeriesID) + " WHERE doc_id=" + str(self.ID)
db.runsql(self.sql)
db.commit()
# DocErrs
@ -234,7 +248,7 @@ class DocErrs(LampadasList):
assert not DocID == None
self.DocID = DocID
self.sql = "SELECT err_id FROM document_error WHERE doc_id=" + str(DocID)
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
row = self.cursor.fetchone()
if row == None: break
@ -244,8 +258,8 @@ class DocErrs(LampadasList):
def Clear(self):
self.sql = "DELETE FROM document_error WHERE doc_id=" + str(self.DocID)
DB.Exec(self.sql)
DB.Commit()
db.runsql(self.sql)
db.commit()
self.list = []
# FIXME: Try instantiating a DocErr object, then adding it to the *document*
@ -253,12 +267,12 @@ class DocErrs(LampadasList):
def Add(self, ErrID):
self.sql = "INSERT INTO document_error(doc_id, err_id) VALUES (" + str(self.DocID) + ", " + wsq(ErrID)
assert DB.Exec(self.sql) == 1
assert db.runsql(self.sql) == 1
newDocErr = DocErr()
newDocErr.DocID = self.DocID
newDocErr.ErrID = ErrID
self.list = self.list + [newDocErr]
DB.Commit()
db.commit()
class DocErr:
"""
@ -284,7 +298,7 @@ class DocFiles(LampadasCollection):
assert not DocID == None
self.DocID = DocID
self.sql = "SELECT filename, format_id FROM document_file WHERE doc_id=" + str(DocID)
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
row = self.cursor.fetchone()
if row == None: break
@ -294,8 +308,8 @@ class DocFiles(LampadasCollection):
def Add(self, DocID, Filename, FormatID=None):
self.sql = 'INSERT INTO document_file (doc_id, filename, format_id) VALUES (' + str(DocID) + ', ' + wsq(Filename) + ', ' + dbint(FormatID) + ')'
assert DB.Exec(self.sql) == 1
DB.Commit()
assert db.runsql(self.sql) == 1
db.commit()
newDocFile = DocFile()
newDocFile.DocID = DocID
newDocFile.Filename = Filename
@ -303,8 +317,8 @@ class DocFiles(LampadasCollection):
def Clear(self):
self.sql = "DELETE FROM document_file WHERE doc_id=" + str(self.DocID)
DB.Exec(self.sql)
DB.Commit()
db.runsql(self.sql)
db.commit()
self.data = {}
class DocFile:
@ -312,6 +326,8 @@ class DocFile:
An association between a document and a file.
"""
import os.path
def Load(self, DocID, row):
assert not DocID == None
assert not row == None
@ -319,19 +335,25 @@ class DocFile:
self.Filename = trim(row[0])
self.FormatID = row[1]
if self.Filename[:5] == 'http:' or self.Filename[:4] == 'ftp:':
self.Local = 0
self.IsLocal = 0
else:
self.Local = 1
self.IsLocal = 1
self.file_only = self.os.path.split(self.Filename)[1]
self.basename = self.os.path.splitext(self.file_only)[0]
# FIXME: this is a stub. We need a new field in the database.
self.is_primary = self.IsLocal
def Save(self):
self.sql = "UPDATE document_file SET format_id=" + dbint(self.FormatID) + " WHERE doc_id=" + str(self.DocID) + " AND filename=" + wsq(self.Filename)
DB.Exec(self.sql)
DB.Commit()
db.runsql(self.sql)
db.commit()
def Del(self):
self.sql = "DELETE FROM document_file WHERE doc_id=" + str(self.DocID) + " AND filename=" + wsq(self.Filename)
DB.Exec(self.sql)
DB.Commit()
db.runsql(self.sql)
db.commit()
# DocRatings
@ -347,7 +369,7 @@ class DocRatings(LampadasCollection):
assert not DocID == None
self.DocID = DocID
self.sql = "SELECT user_id, date_entered, vote FROM doc_vote WHERE doc_id=" + str(DocID)
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
self.row = self.cursor.fetchone()
if self.row == None: break
@ -369,12 +391,12 @@ class DocRatings(LampadasCollection):
if self.data[UserID] == None: return
del self.data[UserID]
self.sql = 'DELETE FROM doc_vote WHERE doc_id=' + str(self.DocID) + ' AND user_id=' + str(UserID)
DB.Exec(self.sql)
db.runsql(self.sql)
self.CalcAverage()
def Clear(self):
self.sql = "DELETE FROM doc_vote WHERE doc_id=" + str(self.DocID)
DB.Exec(self.sql)
db.runsql(self.sql)
self.data = {}
self.CalcAverage()
@ -386,8 +408,8 @@ class DocRatings(LampadasCollection):
self.Average = self.Average + self.data[key].Rating
self.Average = self.Average / self.Count()
self.sql = "UPDATE document SET rating=" + str(self.Average) + " WHERE doc_id=" + str(self.DocID)
# DB.Exec(self.sql)
# DB.Commit()
# db.runsql(self.sql)
# db.commit()
if not self.Parent == None:
self.Parent.Rating = self.Average
@ -406,10 +428,10 @@ class DocRating:
def Save(self):
self.sql = "DELETE from doc_vote WHERE doc_id=" + str(self.DocID) + " AND user_id=" + str(self.UserID)
DB.Exec(self.sql)
db.runsql(self.sql)
self.sql = "INSERT INTO doc_vote (doc_id, user_id, vote) VALUES (" + str(self.DocID) + ", " + str(self.UserID) + ", " + str(self.Rating) + ")"
DB.Exec(self.sql)
DB.Commit()
db.runsql(self.sql)
db.commit()
# DocVersions
@ -424,7 +446,7 @@ class DocVersions(LampadasCollection):
assert not DocID == None
self.DocID = DocID
self.sql = "SELECT rev_id, version, pub_date, initials, notes FROM document_rev WHERE doc_id=" + str(DocID)
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
self.row = self.cursor.fetchone()
if self.row == None: break
@ -449,8 +471,8 @@ class DocVersion:
def Save(self):
self.sql = "UPDATE document_rev SET version=" + wsq(self.Version) + ", pub_date=" + wsq(self.PubDate) + ", initials=" + wsq(self.Initials) + ", notes=" + wsq(self.Notes) + "WHERE doc_id=" + str(self.DocID) + " AND rev_id" + wsq(self.ID)
assert DB.Exec(self.sql) == 1
DB.Commit()
assert db.runsql(self.sql) == 1
db.commit()
# DTDs
@ -463,7 +485,7 @@ class DTDs(LampadasCollection):
def __init__(self):
self.data = {}
self.sql = "SELECT dtd from dtd"
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
row = self.cursor.fetchone()
if row == None: break
@ -494,7 +516,7 @@ class Errs(LampadasCollection):
def __init__(self):
self.data = {}
self.sql = "SELECT err_id FROM error"
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
row = self.cursor.fetchone()
if row == None: break
@ -515,7 +537,7 @@ class Err:
def Load(self, row):
self.ErrID = trim(row[0])
self.sql = "SELECT lang, err_name, err_desc FROM error_i18n WHERE err_id=" + wsq(self.ErrID)
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
self.row = self.cursor.fetchone()
if self.row == None: break
@ -543,7 +565,7 @@ class Formats(LampadasCollection):
def __init__(self):
self.data = {}
self.sql = "SELECT format_id FROM format"
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
row = self.cursor.fetchone()
if row == None: break
@ -564,7 +586,7 @@ class Format:
def Load(self, row):
self.ID = row[0]
self.sql = "SELECT lang, format_name, format_desc FROM format_i18n WHERE format_id=" + str(self.ID)
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
self.row = self.cursor.fetchone()
if self.row == None: break
@ -593,7 +615,7 @@ class Languages(LampadasCollection):
def __init__(self):
self.data = {}
self.sql = "SELECT isocode, supported FROM language"
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
row = self.cursor.fetchone()
if row == None: break
@ -612,14 +634,14 @@ class Language:
if LanguageCode == None: return
self.Code = LanguageCode
self.sql = "SELECT isocode, supported FROM language WHERE isocode= " + wsq(LanguageCode)
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
self.Load(self.sql)
def Load(self, row):
self.Code = trim(row[0])
self.Supported = tf2bool(row[1])
self.sql = "SELECT lang, language_name FROM language_i18n WHERE isocode=" + wsq(self.Code)
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
self.row = self.cursor.fetchone()
if self.row == None: break
@ -646,7 +668,7 @@ class PubStatuses(LampadasCollection):
def __init__(self):
self.data = {}
self.sql = "SELECT pub_status FROM pub_status"
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
row = self.cursor.fetchone()
if row == None: break
@ -668,7 +690,7 @@ class PubStatus:
def Load(self, row):
self.Code = trim(row[0])
self.sql = "SELECT lang, pub_status_name, pub_status_desc FROM pub_status_i18n WHERE pub_status=" + wsq(self.Code)
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
self.row = self.cursor.fetchone()
if self.row == None: break
@ -696,7 +718,7 @@ class ReviewStatuses(LampadasCollection):
def __init__(self):
self.data = {}
self.sql = "SELECT review_status FROM review_status"
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
row = self.cursor.fetchone()
if row == None: break
@ -718,7 +740,7 @@ class ReviewStatus:
def Load(self, row):
self.Code = trim(row[0])
self.sql = "SELECT lang, review_status_name, review_status_desc FROM review_status_i18n WHERE review_status=" + wsq(self.Code)
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
self.row = self.cursor.fetchone()
if self.row == None: break
@ -746,7 +768,7 @@ class Topics(LampadasCollection):
def __init__(self):
self.data = {}
self.sql = "SELECT topic_num FROM topic"
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
row = self.cursor.fetchone()
if row == None: break
@ -769,7 +791,7 @@ class Topic:
def Load(self, row):
self.Num = trim(row[0])
self.sql = "SELECT lang, topic_name, topic_description FROM topic_i18n string_i18n WHERE topic_num=" + wsq(self.Num)
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
self.row = self.cursor.fetchone()
if self.row == None: break
@ -793,19 +815,19 @@ class Users:
"""
def Count(self):
return DB.Value('SELECT count(*) from username')
return db.value('SELECT count(*) from username')
def Add(self, Username, FirstName, MiddleName, Surname, Email, IsAdmin, IsSysadmin, Password, Notes, Stylesheet):
self.id = DB.Value('SELECT max(user_id) from username') + 1
self.id = db.value('SELECT max(user_id) from username') + 1
self.sql = "INSERT INTO username (user_id, username, first_name, middle_name, surname, email, admin, sysadmin, password, notes, stylesheet) VALUES (" + str(self.id) + ", " + wsq(Username) + ", " + wsq(FirstName) + ", " + wsq(MiddleName) + ", " + wsq(Surname) + ", " + wsq(Email) + ", " + wsq(bool2tf(IsAdmin)) + ", " + wsq(bool2tf(IsSysadmin)) + ", " + wsq(Password) + ", " + wsq(Notes) + ", " + wsq(Stylesheet) + ")"
assert DB.Exec(self.sql) == 1
DB.Commit()
return DB.Value('SELECT max(user_id) from username')
assert db.runsql(self.sql) == 1
db.commit()
return db.value('SELECT max(user_id) from username')
def Del(self, id):
self.sql = ('DELETE from username WHERE user_id=' + str(id))
assert DB.Exec(self.sql) == 1
DB.Commit()
assert db.runsql(self.sql) == 1
db.commit()
class User:
"""
@ -815,7 +837,7 @@ class User:
def __init__(self, id) :
self.sql = 'SELECT user_id, username, session_id, first_name, middle_name, surname, email, admin, sysadmin, password, notes, stylesheet FROM username WHERE user_id=' + str(id)
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
row = self.cursor.fetchone()
self.ID = row[0]
self.Username = trim(row[1])
@ -845,55 +867,69 @@ class UserDocs(LampadasList):
assert not UserID == None
self.UserID = UserID
self.sql = "SELECT doc_id, user_id, role, email, active FROM document_user WHERE user_id=" + str(self.UserID)
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
row = self.cursor.fetchone()
if row == None: break
newUserDoc = UserDoc(UserID, row[0])
newUserDoc.Load(row)
newUserDoc = UserDoc(row[0], UserID)
self.list = self.list + [newUserDoc]
def Add(self, DocID, Role, Email, Active):
self.sql = "INSERT INTO document_user(doc_id, user_id, role, email, active) VALUES (" + str(DocID) + ", " + str(self.UserID) + ", " + wsq(Role) + ", " + wsq(Email) + ", " + wsq(bool2tf(Active)) + " )"
assert DB.Exec(self.sql) == 1
DB.Commit()
assert db.runsql(self.sql) == 1
db.commit()
def Del(self, DocID):
self.sql = ('DELETE from document_user WHERE doc_id=' + str(DocID) + ' AND user_id=' + str(self.UserID))
assert DB.Exec(self.sql) == 1
DB.Commit()
assert db.runsql(self.sql) == 1
db.commit()
del self.col[DocID]
class UserDoc:
"""
An association between a user and a document. This association defines the role
which the user plays in the production of the document.
"""
class UserDoc(Doc):
"""
An association between a user and a document. This association defines the role
which the user plays in the production of the document.
"""
def __init__(self, UserID=None, DocID=None):
self.UserID = UserID
self.DocID = DocID
if DocID == None: return
if UserID == None: return
self.sql = "SELECT doc_id, user_id, role, email, active FROM document_user WHERE doc_id=" + str(DocID) + " AND user_id=" + str(UserID)
self.cursor = DB.Select(self.sql)
row = self.cursor.fetchone()
self.Load(row)
def __init__(self, DocID=None, UserID=None):
Doc.__init__(self)
self.DocID = DocID
self.UserID = UserID
if DocID == None: return
if UserID == None: return
self.Load(DocID, UserID)
def Load(self, row):
assert not row == None
self.DocID = row[0]
self.UserID = row[1]
self.Role = trim(row[2])
self.Email = trim(row[3])
self.Active = tf2bool(row[4])
def Load(self, DocID=None, UserID=None):
if not DocID == None:
self.DocID = DocID
assert not self.DocID == None
if not UserID == None:
self.UserID = UserID
assert not self.UserID == None
sql = "SELECT doc_id, user_id, role, email, active FROM document_user WHERE doc_id=" + str(self.DocID) + " AND user_id=" + str(self.UserID)
cursor = db.select(sql)
row = cursor.fetchone()
self.LoadRow(row)
Doc.Load(self, self.DocID)
def Save(self):
self.sql = "UPDATE document_user SET role=" + wsq(self.Role) + ", email=" + wsq(self.Email) + ", active=" + wsq(bool2tf(self.Active)) + " WHERE doc_id=" + str(self.DocID) + " AND user_id=" + str(self.UserID)
DB.Exec(self.sql)
DB.Commit()
def LoadRow(self, row):
assert not row == None
self.DocID = row[0]
self.UserID = row[1]
self.Role = trim(row[2])
self.Email = trim(row[3])
self.Active = tf2bool(row[4])
def Save(self):
self.sql = "UPDATE document_user SET role=" + wsq(self.Role) + ", email=" + wsq(self.Email) + ", active=" + wsq(bool2tf(self.Active)) + " WHERE doc_id=" + str(self.DocID) + " AND user_id=" + str(self.UserID)
db.runsql(self.sql)
db.commit()
Doc.Save(self)
lampadas = Lampadas()
# main
if __name__ == '__main__' :
print "Running unit tests..."

View File

@ -1,5 +1,23 @@
#!/usr/bin/python
#
# This file is part of the Lampadas Documentation System.
#
# Copyright (c) 2000, 2001, 2002 David Merrill <david@lupercalia.net>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Lampadas Database Module
@ -9,113 +27,102 @@ This module generates a Database object for accessing a back-end RDBMS
# Modules ##################################################################
import pyPgSQL
import Config
import Log
from Config import config
from Log import log
# Database
class UnknownDBException(Exception):
pass
pass
class Database:
"""
The database contains all users and documents
"""
"""
The database contains all users and documents
"""
Config = Config.Config()
Log = Log.Log()
Connected = 0
connected = 0
def __del__(self):
if self.Connected:
self.db.connection.close()
def Connect(self, dbtype, dbname):
"""
Connect to the database specified in Config.
"""
def __del__(self):
if self.connected:
self.database.connection.close()
def connect(self, db_type, db_name):
"""
Connect to the database specified in Config.
"""
if dbname == '':
raise UnknownDBException('Database name not specified')
elif dbtype == 'pgsql':
self.db = PgSQLDatabase(dbname)
self.Connected = 1
else:
raise UnknownDBException('Unknown database type %s' % dbtype)
if db_name == '':
raise UnknownDBException('Database name not specified')
elif db_type == 'pgsql':
self.database = PgSQLDatabase(db_name)
self.connected = 1
else:
raise UnknownDBException('Unknown database type %s' % db_type)
# self.Log(3, 'Thread safety ' + str(self.db.connection.threadsafety()))
def connection(self):
return self.database.connection
def Connection(self):
return self.db.connection
def cursor(self):
return self.database.connection.cursor()
def Cursor(self):
return self.db.connection.cursor()
# FIXME : the python DB-API 2.0 states that you can transfer the burden
# of quoting values to the cursor as in
#
# sql = "select * from document where doc_id = %(did)s"
# param = {'did':'123'}
# my_cursor.execute(sql,param)
#
# I like Python :-)
#
def select(self, sql):
if config.log_sql:
log(3, sql)
self.cursor = self.database.connection.cursor()
self.cursor.execute(sql)
return self.cursor
# FIXME : the python DB-API 2.0 states that you can transfer the burden
# of quoting values to the cursor as in
#
# sql = "select * from document where doc_id = %(did)s"
# param = {'did':'123'}
# my_cursor.execute(sql,param)
#
# I like Python :-)
#
def Select(self, sql):
if self.Config.LogSQL:
self.Log(3, sql)
self.cursor = self.db.connection.cursor()
self.cursor.execute(sql)
return self.cursor
def value(self, sql):
if config.log_sql:
log(3, sql)
self.cursor = self.database.connection.cursor()
self.cursor.execute(sql)
self.row = self.cursor.fetchone()
if self.row == None:
self.value = None
else:
self.value = self.row[0]
return self.value
def Value(self, sql):
if self.Config.LogSQL:
self.Log(3, sql)
self.cursor = self.db.connection.cursor()
self.cursor.execute(sql)
self.row = self.cursor.fetchone()
if self.row == None:
self.value = None
else:
self.value = self.row[0]
return self.value
def runsql(self, sql):
if config.log_sql:
log(3, sql)
self.cursor = self.database.connection.cursor()
self.cursor.execute(sql)
return self.cursor.rowcount
def Exec(self, sql):
if self.Config.LogSQL:
self.Log(3, sql)
self.cursor = self.db.connection.cursor()
self.cursor.execute(sql)
return self.cursor.rowcount
def Commit(self):
self.Log(3, 'Committing database')
self.db.connection.commit()
def commit(self):
log(3, 'Committing database')
self.database.connection.commit()
# Specific derived DB classes ##################################################
class PgSQLDatabase(Database):
def __init__(self,dbname):
from pyPgSQL import PgSQL
self.connection = PgSQL.connect(database=dbname)
def __init__(self,db_name):
from pyPgSQL import PgSQL
self.connection = PgSQL.connect(database=db_name)
# except ImportError:
# # PostgresSQL back-end is not available
# pass
class MySQLDatabase(Database):
def __init__(self,dbname):
from pyMySQL import MySQL
self.cnx = MySQL.connection(dbname=dbname)
def __init__(self,db_name):
from pyMySQL import MySQL
self.cnx = MySQL.connection(db_name=db_name)
# except ImportError:
# # MySQL back-end is not available
# pass
db = Database()
db.connect(config.db_type, config.db_name)
# main
if __name__ == '__main__':
print "Running unit tests..."
print "Unit tests run."
print "Running unit tests..."
print "Unit tests run."

View File

@ -1,5 +1,23 @@
#!/usr/bin/python
#
# This file is part of the Lampadas Documentation System.
#
# Copyright (c) 2000, 2001, 2002 David Merrill <david@lupercalia.net>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
The Globals module implements low level utility and convenience routines.
"""

View File

@ -1,5 +1,23 @@
#!/usr/bin/python
#
# This file is part of the Lampadas Documentation System.
#
# Copyright (c) 2000, 2001, 2002 David Merrill <david@lupercalia.net>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Lampadas HTML Primitives Module
@ -10,20 +28,20 @@ to the Lampadas system.
# Modules ##################################################################
from Globals import *
from Config import Config
from Log import Log
from Config import config
from Log import log
from URLParse import URI
from DataLayer import Lampadas
import WebLayer
import commands
from string import split
import sys
import os
# Globals
Config = Config()
Log = Log()
L = Lampadas()
@ -36,385 +54,375 @@ EDIT_ICON = '<img src="images/edit.png" alt="Edit" height="20" width="20" border
class ComboFactory:
def Class(self, value, lang):
self.combo = "<select name='class'>\n"
keys = L.Classes.keys()
for key in keys:
classfoo = L.Classes[key]
assert not classfoo == None
self.combo = self.combo + "<option "
if classfoo.ID == value:
self.combo = self.combo + "selected "
self.combo = self.combo + "value='" + str(classfoo.ID) + "'>"
self.combo = self.combo + classfoo.I18n[lang].Name
self.combo = self.combo + "</option>\n"
self.combo = self.combo + "</select>"
return self.combo
def Class(self, value, lang):
self.combo = "<select name='class'>\n"
keys = L.Classes.keys()
for key in keys:
classfoo = L.Classes[key]
assert not classfoo == None
self.combo = self.combo + "<option "
if classfoo.ID == value:
self.combo = self.combo + "selected "
self.combo = self.combo + "value='" + str(classfoo.ID) + "'>"
self.combo = self.combo + classfoo.I18n[lang].Name
self.combo = self.combo + "</option>\n"
self.combo = self.combo + "</select>"
return self.combo
def Doc(self, value, lang):
self.combo = "<select name='doc'>\n"
keys = L.Docs.keys()
for key in keys:
doc = L.Docs[key]
assert not doc == None
if doc.LanguageCode == lang or lang == None:
self.combo = self.combo + "<option "
if doc.ID == value:
self.combo = self.combo + "selected "
self.combo = self.combo + "value='" + str(doc.ID) + "'>"
self.combo = self.combo + doc.Title
self.combo = self.combo + "</option>\n"
self.combo = self.combo + "</select>"
return self.combo
def Doc(self, value, lang):
self.combo = "<select name='doc'>\n"
keys = L.Docs.keys()
for key in keys:
doc = L.Docs[key]
assert not doc == None
if doc.LanguageCode == lang or lang == None:
self.combo = self.combo + "<option "
if doc.ID == value:
self.combo = self.combo + "selected "
self.combo = self.combo + "value='" + str(doc.ID) + "'>"
self.combo = self.combo + doc.Title
self.combo = self.combo + "</option>\n"
self.combo = self.combo + "</select>"
return self.combo
def DTD(self, value, lang):
self.combo = "<select name='dtd'>\n"
keys = L.DTDs.keys()
for key in keys:
dtd = L.DTDs[key]
assert not dtd == None
self.combo = self.combo + "<option "
if dtd.DTD == value:
self.combo = self.combo + "selected "
self.combo = self.combo + "value='" + dtd.DTD + "'>"
self.combo = self.combo + dtd.DTD
self.combo = self.combo + "</option>\n"
self.combo = self.combo + "</select>"
return self.combo
def Format(self, value, lang):
self.combo = "<select name='format'>\n"
keys = L.Formats.keys()
for key in keys:
format = L.Formats[key]
assert not format == None
self.combo = self.combo + "<option "
if format.ID == value:
self.combo = self.combo + "selected "
self.combo = self.combo + "value='" + str(format.ID) + "'>"
self.combo = self.combo + format.I18n[lang].Name
self.combo = self.combo + "</option>\n"
self.combo = self.combo + "</select>"
return self.combo
def DTD(self, value, lang):
self.combo = "<select name='dtd'>\n"
keys = L.DTDs.keys()
for key in keys:
dtd = L.DTDs[key]
assert not dtd == None
self.combo = self.combo + "<option "
if dtd.DTD == value:
self.combo = self.combo + "selected "
self.combo = self.combo + "value='" + dtd.DTD + "'>"
self.combo = self.combo + dtd.DTD
self.combo = self.combo + "</option>\n"
self.combo = self.combo + "</select>"
return self.combo
def Format(self, value, lang):
self.combo = "<select name='format'>\n"
keys = L.Formats.keys()
for key in keys:
format = L.Formats[key]
assert not format == None
self.combo = self.combo + "<option "
if format.ID == value:
self.combo = self.combo + "selected "
self.combo = self.combo + "value='" + str(format.ID) + "'>"
self.combo = self.combo + format.I18n[lang].Name
self.combo = self.combo + "</option>\n"
self.combo = self.combo + "</select>"
return self.combo
def Language(self, value, lang):
return "lang"
def Language(self, value, lang):
return "lang"
def License(self, value, lang):
return "license"
def License(self, value, lang):
return "license"
def PubStatus(self, value, lang):
self.combo = "<select name='pub_status'>\n"
keys = L.PubStatuses.keys()
for key in keys:
PubStatus = L.PubStatuses[key]
assert not PubStatus == None
self.combo = self.combo + "<option "
if PubStatus.Code == value:
self.combo = self.combo + "selected "
self.combo = self.combo + "value='" + str(PubStatus.Code) + "'>"
self.combo = self.combo + PubStatus.I18n[lang].Name
self.combo = self.combo + "</option>\n"
self.combo = self.combo + "</select>"
return self.combo
def ReviewStatus(self, value, lang):
self.combo = "<select name='review_status'>\n"
keys = L.ReviewStatuses.keys()
for key in keys:
ReviewStatus = L.ReviewStatuses[key]
assert not ReviewStatus == None
self.combo = self.combo + "<option "
if ReviewStatus.Code == value:
self.combo = self.combo + "selected "
self.combo = self.combo + "value='" + str(ReviewStatus.Code) + "'>"
self.combo = self.combo + ReviewStatus.I18n[lang].Name
self.combo = self.combo + "</option>\n"
self.combo = self.combo + "</select>"
return self.combo
def PubStatus(self, value, lang):
self.combo = "<select name='pub_status'>\n"
keys = L.PubStatuses.keys()
for key in keys:
PubStatus = L.PubStatuses[key]
assert not PubStatus == None
self.combo = self.combo + "<option "
if PubStatus.Code == value:
self.combo = self.combo + "selected "
self.combo = self.combo + "value='" + str(PubStatus.Code) + "'>"
self.combo = self.combo + PubStatus.I18n[lang].Name
self.combo = self.combo + "</option>\n"
self.combo = self.combo + "</select>"
return self.combo
def ReviewStatus(self, value, lang):
self.combo = "<select name='review_status'>\n"
keys = L.ReviewStatuses.keys()
for key in keys:
ReviewStatus = L.ReviewStatuses[key]
assert not ReviewStatus == None
self.combo = self.combo + "<option "
if ReviewStatus.Code == value:
self.combo = self.combo + "selected "
self.combo = self.combo + "value='" + str(ReviewStatus.Code) + "'>"
self.combo = self.combo + ReviewStatus.I18n[lang].Name
self.combo = self.combo + "</option>\n"
self.combo = self.combo + "</select>"
return self.combo
# BoxFactory
class BoxFactory:
def MainMenu(self, lang):
self.box = ''
self.box = self.box + '<table class="navbox"><tr><th>|mmtitle|</th></tr>'
self.box = self.box + '<tr><td>'
self.box = self.box + '<a href="home">|home|</a><br>'
self.box = self.box + '<a href="doctable">|doctable|</a><br>'
self.box = self.box + '<a href="downloads">Downloads</a>'
self.box = self.box + '</td></tr>'
self.box = self.box + '</table>'
return self.box
def MainMenu(self, lang):
self.box = ''
self.box = self.box + '<table class="navbox"><tr><th>|mmtitle|</th></tr>'
self.box = self.box + '<tr><td>'
self.box = self.box + '<a href="home">|home|</a><br>'
self.box = self.box + '<a href="doctable">|doctable|</a><br>'
self.box = self.box + '<a href="downloads">Downloads</a>'
self.box = self.box + '</td></tr>'
self.box = self.box + '</table>'
return self.box
class TableFactory:
Combo = ComboFactory()
Combo = ComboFactory()
def BarGraph(self, value, max, lang):
return str(value) + '/' + str(max)
def BarGraph(self, value, max, lang):
return str(value) + '/' + str(max)
def Doc(self, DocID, lang):
self.box = ''
self.box = self.box + '<table class="box" style="width:100%"><tr><th colspan="6">|docdetails|</th></tr>'
if DocID:
Doc = L.Docs[DocID]
self.box = self.box + '<form method=POST action="docsave" name="document">'
else:
Doc = Doc()
self.box = self.box + '<form method=POST action="docadd" name="document">'
self.box = self.box + '<input name="doc_id" type=hidden value=' + str(Doc.ID) + '>\n'
self.box = self.box + '<tr>\n'
self.box = self.box + '<th align=right>Title</th><td colspan=5><input type=text name=title size=60 style="width:100%" value="' + Doc.Title + '"></td>\n'
self.box = self.box + '</tr>\n'
self.box = self.box + '<tr>\n'
self.box = self.box + '<th align=right>'
if Doc.URL:
self.box = self.box + '<a href="' + Doc.URL + '">URL</a>'
else:
self.box = self.box + 'URL'
self.box = self.box + '</th><td colspan=5><input type=text name=url size=60 style="width:100%" value="' + Doc.URL + '"></td>'
self.box = self.box + '</tr>\n<tr>\n'
self.box = self.box + '<th align=right>'
def Doc(self, DocID, lang):
self.box = ''
self.box = self.box + '<table class="box" style="width:100%"><tr><th colspan="6">|docdetails|</th></tr>'
if DocID:
Doc = L.Docs[DocID]
self.box = self.box + '<form method=POST action="docsave" name="document">'
else:
Doc = Doc()
self.box = self.box + '<form method=POST action="docadd" name="document">'
self.box = self.box + '<input name="doc_id" type=hidden value=' + str(Doc.ID) + '>\n'
self.box = self.box + '<tr>\n'
self.box = self.box + '<th align=right>Title</th><td colspan=5><input type=text name=title size=60 style="width:100%" value="' + Doc.Title + '"></td>\n'
self.box = self.box + '</tr>\n'
self.box = self.box + '<tr>\n'
self.box = self.box + '<th align=right>'
if Doc.URL:
self.box = self.box + '<a href="' + Doc.URL + '">URL</a>'
else:
self.box = self.box + 'URL'
self.box = self.box + '</th><td colspan=5><input type=text name=url size=60 style="width:100%" value="' + Doc.URL + '"></td>'
self.box = self.box + '</tr>\n<tr>\n'
self.box = self.box + '<th align=right>'
if Doc.HomeURL:
self.box = self.box + '<a href="' + Doc.HomeURL + '">Home URL</a>'
else:
self.box = self.box + 'Home URL'
self.box = self.box + '</th><td colspan=5><input type=text name=ref_url size=60 style="width:100%" value="' + Doc.HomeURL + '"></td>'
self.box = self.box + '</tr>\n<tr>\n'
self.box = self.box + '<th align=right>Status</th><td>'
self.box = self.box + self.Combo.PubStatus(Doc.PubStatusCode, lang)
self.box = self.box + '</td>'
self.box = self.box + '<th align=right>Class</th><td>\n'
self.box = self.box + self.Combo.Class(Doc.ClassID, lang)
self.box = self.box + '</td>'
self.box = self.box + '<th align=right>Maint</th><td>\n'
if Doc.Maintained:
self.box = self.box + "Yes"
else:
self.box = self.box + "No"
self.box = self.box + '</td>'
self.box = self.box + '</tr>\n<tr>\n'
self.box = self.box + '<th align=right>Language</th><td>'
self.box = self.box + self.Combo.ReviewStatus(Doc.ReviewStatus, lang)
self.box = self.box + '</td>'
self.box = self.box + '<th align=right>Accuracy</th><td>'
self.box = self.box + self.Combo.ReviewStatus(Doc.TechReviewStatus, lang)
self.box = self.box + '</td>'
self.box = self.box + '<th align=right>License</th><td>'
self.box = self.box + self.Combo.License(Doc.License, lang)
self.box = self.box + '</td>'
self.box = self.box + '</tr>\n<tr>\n'
self.box = self.box + '<th align=right>Pub Date</th><td><input type=text name=pub_date size=10 value="' + Doc.PubDate + '"></td>'
self.box = self.box + '<th align=right>Updated</th><td><input type=text name=last_update size=10 value="' + Doc.LastUpdate + '"></td>'
self.box = self.box + '<th align=right>Version</th><td><input type=text name=version size=10 value="' + Doc.Version + '"></td>'
self.box = self.box + '</tr>\n<tr>\n'
self.box = self.box + '<th align=right>Tickle Date</th><td><input type=text name=tickle_date size=10 value="' + Doc.TickleDate + '"></td>'
self.box = self.box + '<th align=right>ISBN</th><td><input type=text name=isbn size=14 value="' + Doc.ISBN + '"></td>'
self.box = self.box + '<th align=right>Rating</th>\n'
self.box = self.box + '<td>'
self.box = self.box + self.BarGraph(Doc.Rating, 10, lang)
self.box = self.box + '</td>\n'
if DocID:
self.box = self.box + '</tr>\n<tr>\n'
self.box = self.box + '<th align=right>Format</th><td>'
self.box = self.box + L.Formats[Doc.FormatID].I18n[lang].Name
self.box = self.box + '</td>'
self.box = self.box + '<th align=right>DTD</th><td>'
self.box = self.box + Doc.DTD + ' ' + Doc.DTDVersion
self.box = self.box + '</td>'
self.box = self.box + '<th align=right>Lang</th><td>'
self.box = self.box + self.Combo.Language(Doc.Lang, lang)
self.box = self.box + '</td>'
self.box = self.box + '</tr>\n<tr>\n'
self.box = self.box + '<th align=right>Abstract</th>'
self.box = self.box + '<td colspan=5><textarea name=abstract rows=6 cols=40 style="width:100%" wrap>' + Doc.Abstract + '</textarea></td>\n'
self.box = self.box + '</tr>\n'
self.box = self.box + '<tr><td></td><td><input type=submit name=save value=Save></td></tr>\n'
self.box = self.box + '</form>\n'
self.box = self.box + '</table>\n'
if Doc.HomeURL:
self.box = self.box + '<a href="' + Doc.HomeURL + '">Home URL</a>'
else:
self.box = self.box + 'Home URL'
self.box = self.box + '</th><td colspan=5><input type=text name=ref_url size=60 style="width:100%" value="' + Doc.HomeURL + '"></td>'
self.box = self.box + '</tr>\n<tr>\n'
self.box = self.box + '<th align=right>Status</th><td>'
self.box = self.box + self.Combo.PubStatus(Doc.PubStatusCode, lang)
self.box = self.box + '</td>'
self.box = self.box + '<th align=right>Class</th><td>\n'
self.box = self.box + self.Combo.Class(Doc.ClassID, lang)
self.box = self.box + '</td>'
self.box = self.box + '<th align=right>Maint</th><td>\n'
if Doc.Maintained:
self.box = self.box + "Yes"
else:
self.box = self.box + "No"
self.box = self.box + '</td>'
self.box = self.box + '</tr>\n<tr>\n'
self.box = self.box + '<th align=right>Language</th><td>'
self.box = self.box + self.Combo.ReviewStatus(Doc.ReviewStatus, lang)
self.box = self.box + '</td>'
self.box = self.box + '<th align=right>Accuracy</th><td>'
self.box = self.box + self.Combo.ReviewStatus(Doc.TechReviewStatus, lang)
self.box = self.box + '</td>'
self.box = self.box + '<th align=right>License</th><td>'
self.box = self.box + self.Combo.License(Doc.License, lang)
self.box = self.box + '</td>'
self.box = self.box + '</tr>\n<tr>\n'
self.box = self.box + '<th align=right>Pub Date</th><td><input type=text name=pub_date size=10 value="' + Doc.PubDate + '"></td>'
self.box = self.box + '<th align=right>Updated</th><td><input type=text name=last_update size=10 value="' + Doc.LastUpdate + '"></td>'
self.box = self.box + '<th align=right>Version</th><td><input type=text name=version size=10 value="' + Doc.Version + '"></td>'
self.box = self.box + '</tr>\n<tr>\n'
self.box = self.box + '<th align=right>Tickle Date</th><td><input type=text name=tickle_date size=10 value="' + Doc.TickleDate + '"></td>'
self.box = self.box + '<th align=right>ISBN</th><td><input type=text name=isbn size=14 value="' + Doc.ISBN + '"></td>'
self.box = self.box + '<th align=right>Rating</th>\n'
self.box = self.box + '<td>'
self.box = self.box + self.BarGraph(Doc.Rating, 10, lang)
self.box = self.box + '</td>\n'
if DocID:
self.box = self.box + '</tr>\n<tr>\n'
self.box = self.box + '<th align=right>Format</th><td>'
self.box = self.box + L.Formats[Doc.FormatID].I18n[lang].Name
self.box = self.box + '</td>'
self.box = self.box + '<th align=right>DTD</th><td>'
self.box = self.box + Doc.DTD + ' ' + Doc.DTDVersion
self.box = self.box + '</td>'
self.box = self.box + '<th align=right>Lang</th><td>'
self.box = self.box + self.Combo.Language(Doc.Lang, lang)
self.box = self.box + '</td>'
self.box = self.box + '</tr>\n<tr>\n'
self.box = self.box + '<th align=right>Abstract</th>'
self.box = self.box + '<td colspan=5><textarea name=abstract rows=6 cols=40 style="width:100%" wrap>' + Doc.Abstract + '</textarea></td>\n'
self.box = self.box + '</tr>\n'
self.box = self.box + '<tr><td></td><td><input type=submit name=save value=Save></td></tr>\n'
self.box = self.box + '</form>\n'
self.box = self.box + '</table>\n'
return self.box
return self.box
def Docs(self, lang):
self.box = ''
self.box = self.box + '<table class="box"><tr><th colspan="2">Title</th></tr>'
keys = L.Docs.keys()
for key in keys:
if L.Docs[key].Lang == lang:
self.box = self.box + '<tr>'
self.box = self.box + '<td><a href="editdoc/' + str(L.Docs[key].ID) + '">' + EDIT_ICON + '</a></td>'
self.box = self.box + '<td><a href="' + str(L.Docs[key].URL) + '">' + L.Docs[key].Title + '</a></td>'
self.box = self.box + '</tr>'
self.box = self.box + '</table>'
return self.box
def Docs(self, lang):
self.box = ''
self.box = self.box + '<table class="box"><tr><th colspan="2">Title</th></tr>'
keys = L.Docs.keys()
for key in keys:
if L.Docs[key].Lang == lang:
self.box = self.box + '<tr>'
self.box = self.box + '<td><a href="/editdoc/' + str(L.Docs[key].ID) + '/">' + EDIT_ICON + '</a></td>'
self.box = self.box + '<td><a href="/doc/' + str(L.Docs[key].ID) + '/">' + L.Docs[key].Title + '</a></td>'
self.box = self.box + '</tr>'
self.box = self.box + '</table>'
return self.box
# PageFactory
class PageFactory:
Pages = WebLayer.Pages()
Blocks = WebLayer.Blocks()
Strings = WebLayer.Strings()
Templates = WebLayer.Templates()
Box = BoxFactory()
Table = TableFactory()
Pages = WebLayer.Pages()
Blocks = WebLayer.Blocks()
Strings = WebLayer.Strings()
Templates = WebLayer.Templates()
Box = BoxFactory()
Table = TableFactory()
def __call__(self, key, lang):
return self.Page(key, lang)
def __call__(self, key, lang):
return self.Page(key, lang)
def Page(self, key, lang):
if key == '' or key == '/':
key='home'
if key[0] == '/':
key = key[1:]
Keys = split(key, '/')
# Allow the language to be specified in the URL
#
Log.Write(3, 'Testing language ' + Keys[0])
forcelang = 0
if Keys[0] in L.Languages.keys():
Log.Write(3, 'URL specified the ' + Keys[0] + ' translation')
if L.Languages[Keys[0]].Supported:
lang = Keys[0]
forcelang = 1
else:
Log.Write(3, 'Language ' + Keys[0] + ' not supported')
Keys = Keys[1:]
Log.Write(3, 'Serving language ' + lang)
pagecode = Keys[0]
Log.Write(3, 'Building page ' + pagecode)
if pagecode == 'doc':
DocID = int(Keys[1])
page = self.DocPage(DocID, lang)
else:
Page = self.Pages[pagecode]
if Page == None:
Page = self.Pages['404']
assert not Page == None
Template = self.Templates[Page.TemplateCode]
assert not Template == None
page = Template.Template
def Page(self, key):
uri = URI(key)
uri.printdebug()
Log.Write(3, 'Serving language ' + uri.Language)
if uri.Service == 'doc':
if uri.Format == '':
page = self.DocPage(uri)
else:
Page = self.Pages[uri.Filename]
if Page == None:
Page = self.Pages['404']
assert not Page == None
page = self.build_page(Page, uri)
page = page.replace('\|', 'DCM_PIPE')
pos = page.find('|')
while pos <> -1 :
pos2 = page.find('|', pos+1)
if pos2 == -1:
pos = -1
else:
oldstring = page[pos:pos2+1]
token = page[pos+1:pos2]
newstring = ''
# Built-ins
if token=='title':
newstring = Page.I18n[lang].Title
if token=='body':
newstring = Page.I18n[lang].Page
if token=='hostname':
newstring = Config.Hostname
if token=='rootdir':
newstring = Config.RootDir
if token=='port':
newstring = str(Config.Port)
if token=='base':
newstring = 'http://' + Config.Hostname + ':' + str(Config.Port) + Config.RootDir
if forcelang:
newstring = newstring + lang + '/'
if token=='page':
newstring = pagecode
if token=='stylesheet':
newstring='default' #FIXME
return page
# Boxes
#
if token=='boxmainmenu':
newstring = self.Box.MainMenu(lang)
# Tables
#
if token=='tabdocstable':
newstring = self.Table.Docs(lang)
if token=='tabeditdoc':
DocID = int(Keys[1])
newstring = self.Table.Doc(DocID, lang)
# Blocks and Strings
#
if newstring == '':
Block = self.Blocks[token]
if Block == None:
String = self.Strings[token]
if String == None:
newstring = 'ERROR'
Log.Write(1, 'Could not replace token ' + token)
else:
newstring = String.I18n[lang].String
else:
newstring = Block.I18n[lang].Block
if newstring == '':
Log.Write(1, 'Could not replace token ' + token)
else:
page = page.replace(page[pos:pos2+1], newstring)
page = page.replace('\|', 'DCM_PIPE')
pos = page.find('|')
page = page.replace('DCM_PIPE', '|')
Log.Write(3, 'Page built ' + pagecode)
return page
def build_page(self, Page, uri):
Template = self.Templates[Page.TemplateCode]
assert not Template == None
page = Template.Template
def DocPage(self, DocID, lang):
Doc = L.Docs[DocID]
if Doc == None:
page = "Error, could not locate document " + str(DocID)
else:
docformat = L.Formats[Doc.FormatID].I18n[lang].Name
if docformat=='SGML' or docformat=='XML':
Files = Doc.Files
if Files.Count() == 0:
page = 'No file to process'
elif Files.Count() > 1:
page = 'Only single files supported right now'
else:
keys = Files.keys()
for key in keys:
File = Files[key]
page = page.replace('\|', 'DCM_PIPE')
pos = page.find('|')
while pos <> -1 :
pos2 = page.find('|', pos+1)
if pos2 == -1:
pos = -1
else:
oldstring = page[pos:pos2+1]
token = page[pos+1:pos2]
newstring = ''
# Built-ins
#
if token=='title':
newstring = Page.I18n[uri.Language].Title
if token=='body':
newstring = Page.I18n[uri.Language].Page
if token=='hostname':
newstring = config.hostname
if token=='rootdir':
newstring = config.root_dir
if token=='port':
newstring = str(config.pport)
if token=='base':
newstring = 'http://' + config.hostname + ':' + str(config.port) + config.root_dir
if uri.ForceLang:
newstring = newstring + uri.Language + '/'
if token=='page':
newstring = Page.Code
if token=='stylesheet':
newstring='default'
# FIXME: This must process the XML file that came out of
# Converter(), not the source file.
# Boxes
#
if token=='boxmainmenu':
newstring = self.Box.MainMenu(uri.Language)
# Tables
#
if token=='tabdocstable':
newstring = self.Table.Docs(uri.Language)
if token=='tabeditdoc':
newstring = self.Table.Doc(uri.ID, uri.Language)
# Blocks and Strings
#
if newstring == '':
Block = self.Blocks[token]
if Block == None:
String = self.Strings[token]
if String == None:
newstring = 'ERROR'
Log.Write(1, 'Could not replace token ' + token)
else:
newstring = String.I18n[uri.Language].String
else:
newstring = Block.I18n[uri.Language].Block
if newstring == '':
Log.Write(1, 'Could not replace token ' + token)
else:
page = page.replace(page[pos:pos2+1], newstring)
page = page.replace('\|', 'DCM_PIPE')
pos = page.find('|')
page = page.replace('DCM_PIPE', '|')
Log.Write(3, 'Page built ' + Page.Code)
return page
command = 'xsltproc /usr/share/sgml/docbook/stylesheet/xsl/nwalsh/html/docbook.xsl ' + Config.CVSRoot + File.Filename
page = commands.getoutput(command)
else:
page = 'FORMAT ' + docformat + ' NOT YET SUPPORTED'
return page
def DocPage(self, uri):
DocID = uri.ID
lang = uri.Language
Doc = L.Docs[DocID]
if Doc == None:
page = "Error, could not locate document " + str(DocID)
else:
cachedir = config.cache_dir + str(Doc.ID) + '/'
Files = Doc.Files
if Files.Count() == 0:
page = 'No file to process'
elif Files.Count() > 1:
page = 'Only single files supported right now'
else:
command = 'cd ' + cachedir + '; make index'
os.system(command)
if uri.Filename == '':
uri.Filename = 'index.html'
if os.access(cachedir + uri.Filename, os.F_OK):
fh = open(cachedir + uri.Filename)
page = fh.read()
fh.close()
else:
page = 'Document cannot be found'
return page
def main():
F = PageFactory()
for arg in sys.argv[1:]:
print F.Page(arg, 'EN')
F = PageFactory()
for arg in sys.argv[1:]:
print F.Page(arg)
def usage():
print "HTML.py version " + VERSION
print "HTML.py version " + VERSION
if __name__ == "__main__":
main()
main()

View File

@ -1,5 +1,23 @@
#!/usr/bin/python
#
# This file is part of the Lampadas Documentation System.
#
# Copyright (c) 2000, 2001, 2002 David Merrill <david@lupercalia.net>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Lampadas Error Checking Module
@ -45,7 +63,7 @@ class Lintadas:
File = Doc.Files[key]
if File.Local:
if File.IsLocal:
self.L.Log.Write(3, 'Checking filename ' + key)
else:
self.L.Log.Write(3, 'Skipping remote file ' + key)

View File

@ -1,11 +1,39 @@
#!/usr/bin/python
#
# This file is part of the Lampadas Documentation System.
#
# Copyright (c) 2000, 2001, 2002 David Merrill <david@lupercalia.net>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Lampadas Log Module
This module generates the system log for Lampadas.
Logs are assigned one of the following severities:
0 critical errors
1 errors
2 warnings
3 system events
4 debugging messages
"""
from Config import config
# Modules ##################################################################
@ -14,28 +42,34 @@ class Log:
Write to the system log.
"""
import Config
Config = Config.Config()
import time
def __call__(self, level, message):
self.Write(level, message)
self.write(level, message)
def Write(self, level, message):
if self.Config.LogLevel >= level:
self.log = open(self.Config.LogFile, 'a+')
self.log.write(message + "\n")
def write(self, level, message):
if config.log_level >= level:
timestamp = self.time.time()
logmessage = self.time.ctime(self.time.time()) + ' ' + message
self.log = open(config.log_file, 'a+')
self.log.write(logmessage + "\n")
self.log.close
if self.Config.LogConsole > 0:
print message
if config.log_console > 0:
print logmessage
def Truncate(self):
self.log = open(self.Config.LogFile, 'w+')
def truncate(self):
self.log = open(config.log_file, 'w+')
self.log.close
if __name__ == "__main__":
Log = Log()
Log(1, 'level 1')
Log(2, 'level 2')
Log(3, 'level 3')
log = Log()
if __name__ == "__main__":
config.log_level = 3
config.log_sql = 1
config.log_console = 1
log.write(1, 'level 1')
log.write(2, 'level 2')
log.write(3, 'level 3')

View File

@ -1,5 +1,23 @@
#!/usr/bin/python
#
# This file is part of the Lampadas Documentation System.
#
# Copyright (c) 2000, 2001, 2002 David Merrill <david@lupercalia.net>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Lampadas Mirroring Module
@ -28,33 +46,99 @@ class Mirror:
Lint = Lintadas()
def mirror_all(self):
dockeys = self.Lint.L.Docs.keys()
for dockey in dockeys:
self.Lint.L.Log(3, 'Mirroring all documents')
for dockey in self.Lint.L.Docs.keys():
self.mirror_doc(dockey)
self.write_main_makefile()
def mirror_doc(self, DocID):
self.Lint.L.Log.Write(3, 'Mirroring document ' + str(DocID))
self.Doc = self.Lint.L.Docs[DocID]
# decide if the document is remote
#
self.is_remote = 0
filekeys = self.Doc.Files.keys()
for filekey in filekeys:
self.File = self.Doc.Files[filekey]
if not self.File.Local:
self.filename = self.File.Filename
self.Lint.L.Log(3, 'mirroring ' + self.filename)
self.basename = self.os.path.basename(self.filename)
self.localdir = self.C.cache_dir + str(self.Doc.ID) + '/'
if not self.os.access(self.localdir, self.os.F_OK):
self.os.mkdir(self.localdir)
self.localname = self.localdir + self.basename
self.urllib.urlretrieve(self.File.Filename, self.localname)
command = 'cd ' + self.localdir + '; gunzip -f ' + self.basename
self.os.system(command)
if not self.Doc.Files[filekey].IsLocal:
self.is_remote = 1
# delete list of local files if document is remote
#
if self.is_remote:
filekeys = self.Doc.Files.keys()
for filekey in filekeys:
if self.Doc.Files[filekey].Local:
if self.Doc.Files[filekey].IsLocal:
self.Doc.Files[filekey].Del()
for file in self.os.listdir(self.localdir):
self.Doc.Files.Add(self.Doc.ID, file)
self.Lint.CheckDoc(DocID)
# mirror all files into cache, whether from remote
# or local storage
#
# filename can look like: http://foo.org/foo.sgml
# ftp://foo.org/foo.sgml
# howto/docbook/big-memory-howto.sgml
#
for filekey in filekeys:
# create cache directory for this document
#
self.cachedir = self.C.cache_dir + str(self.Doc.ID) + '/'
if not self.os.access(self.cachedir, self.os.F_OK):
self.os.mkdir(self.cachedir)
self.File = self.Doc.Files[filekey]
self.filename = self.File.Filename
self.file_only = self.File.file_only
self.cachename = self.cachedir + self.file_only
if self.File.IsLocal:
# It is expensive to copy local documents into a cache directory,
# but it avoids publishing documents directly out of CVS.
# Some publishing tools leave clutter in the directory on failure.
#
if not self.os.access(self.C.CVSRoot + self.filename, self.os.F_OK):
self.Lint.L.Log(2, 'Cannot mirror missing file: ' + self.filename)
continue
self.Lint.L.Log(3, 'mirroring local file ' + self.filename)
command = 'cd ' + self.cachedir + '; cp -pu ' + self.C.CVSRoot + self.filename + ' .'
self.os.system(command)
else:
try:
self.Lint.L.Log(3, 'mirroring remote file ' + self.filename)
# FIXME: self.urllib.urlretrieve(self.File.Filename, self.cachename)
except IOError:
self.Lint.L.Log(0, 'error retrieving remote file ' + self.filename)
continue
if self.unpack(self.cachedir, self.file_only):
for file in self.os.listdir(self.cachedir):
if file[-5:] <> '.html':
self.Doc.Files.Add(self.Doc.ID, file)
self.Lint.CheckDoc(DocID)
self.Lint.L.Log(3, 'Mirroring document ' + str(DocID) + ' complete.')
def unpack(self, dir, file):
"""
Goes to the specified directory and unpacks a file.
Returns 1 if an archive was identified and unpacked.
Returns 0 if it was not a recognized archive.
Supported archives are .tar, .gz and .tar.gz.
"""
cmd_start = 'cd ' + dir + '; '
if file[-7:] == '.tar.gz':
self.os.system(cmd_start + 'tar -zxf ' + file)
return 1
elif file[-4:] == '.tar':
self.os.system(cmd_start + 'tar -xf ' + file)
return 1
elif file[-3:] == '.gz':
self.os.system(cmd_start + 'gunzip -f ' + file)
return 1
if __name__ == "__main__":

View File

@ -1,76 +1,148 @@
#!/usr/bin/python
#
# This file is part of the Lampadas Documentation System.
#
# Copyright (c) 2000, 2001, 2002 David Merrill <david@lupercalia.net>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
The URLParse module deciphers a Lampadas URL into its component parts.
The API is documented in the Lampadas Programmer's Guide. A summary:
[Language/][doc/<ID>[/<format>]|author/<ID>|$topic/$class]
"""
import string
from DataLayer import lampadas
def splitterm(term, sep):
"""
Splits the term into 2 pieces according to the seperator,
and returns them. If the term does not contain the sep,
the second string the returned tuple wil be ''.
"""
temp = string.split(term, sep, 1)
if len(temp) > 1:
return temp[0], temp[1]
else:
return temp[0], ''
class URI:
URI = ""
Protocol = ""
Server = ""
Port = ""
Language = ""
Path = ""
Filename = ""
Parameter = ""
Anchor = ""
def __init__(self, uri):
def __init__(self, uri):
self.protocol = ""
self.server = ""
self.port = ""
self.language = "EN"
self.force_lang = 0
self.path = ""
self.service = ""
self.format = ""
self.filename = "home"
self.id = 0
self.parameter = ""
self.anchor = ""
self.URI = uri
if not uri:
return
temp = uri
if temp[:7] == "http://":
self.Protocol = "http://"
temp = temp[7:]
self.uri = uri
temp = uri
if len(temp) == 0:
return
if temp[0] == '/':
temp = temp[1:]
if len(temp) == 0:
return
if temp[-1] == '/':
temp = temp[:-1]
temp = string.split(temp,"#")
if len(temp) > 1:
self.Anchor = temp[1]
temp = temp[0]
temp = string.split(temp,"?")
if len(temp) > 1:
self.Parameter = temp[1]
temp = temp[0]
temp = string.split(temp,"/")
if len(temp) > 1:
self.Filename = temp[-1]
temp = string.join(temp[:len(temp)-1],"/")
if temp.find('://') > 0:
self.protocol, temp = splitterm(temp, '://')
self.server, temp = splitterm(temp,'/')
if self.server.find(':') > 0:
self.server, self.port = splitterm(self.server, ':')
if temp.find('#') > 0:
temp, self.anchor = splitterm(temp, '#')
if temp.find('?') > 0:
temp, self.parameter = splitterm(temp, '?')
temp = string.split(temp, '/')
temp = string.split(temp,"/")
if len(temp) > 1:
self.Path = string.join(temp[1:],'/') + '/'
temp = temp[0]
if len(temp) > 0:
lang = lampadas.Languages[temp[0]]
if not lang == None:
self.language = temp[0]
temp = temp[1:]
self.force_lang = 1
temp = string.split(temp,":")
if len(temp) > 1:
self.Port = temp[1]
self.Server = temp[0]
if len(self.Path) > 1:
if len(self.Path) == 2:
self.Language = self.Path
self.Path = ''
elif self.Path[2] == '/':
self.Language = self.Path[:2]
self.Path = self.Path[2:]
if len(temp) > 0:
if temp[0] == 'doc' or temp[0] == 'editdoc':
# FIXME:
#
# This really should eb using only a single attribute, 'Filename'.
# The 'doc' kludge should use a regular page which then embeds document
# content.
if temp[0] == 'doc':
self.service = temp[0]
self.filename = ''
else:
self.service = ''
self.filename = temp[0]
temp = temp[1:]
if len(temp) > 0:
self.id = int(temp[0])
temp = temp[1:]
if len(temp) > 0:
if temp[0] == 'xml' or temp[0] == 'html' or temp[0] == 'omf':
self.format = temp[0]
else:
self.filename = temp[0]
else:
if len(temp) == 1:
self.path = '/'
if len(temp[0]) > 0:
self.filename = temp[0]
else:
self.path = string.join(temp[:-1], '/')
if len(temp[-1]) > 0:
self.filename = temp[-1]
# This is a tricky area, so leave this for testing when problems arise
# due to strange URIs.
# print "URI: [" + self.URI + "]"
# print "Language: [" + self.Language + "]"
# print "Protocol: [" + self.Protocol + "]"
# print "Server: [" + self.Server + "]"
# print "Port: [" + self.Port + "]"
# print "Path: [" + self.Path + "]"
# print "Filename: [" + self.Filename + "]"
# print "Parameter: [" + self.Parameter + "]"
# print "Anchor: [" + self.Anchor + "]"
def printdebug(self):
print "URI: [" + self.uri + "]"
print "Protocol: [" + self.protocol + "]"
print "Server: [" + self.server + "]"
print "Port: [" + self.port + "]"
print "Path: [" + self.path + "]"
print "Language: [" + self.language + "]"
print "Forced Language: [" + str(self.force_lang) + "]"
print "Service: [" + self.service+ "]"
print "ID [" + str(self.id) + "]"
print "Format [" + str(self.format) + "]"
print "Filename: [" + self.filename + "]"
print "Parameter: [" + self.parameter + "]"
print "Anchor: [" + self.anchor + "]"
if __name__ == '__main__':
foo = URI('http://localhost:8000/EN/editdoc/1/home#foo')
import sys
foo = URI(sys.argv[1])
#'http://localhost:8000/EN/editdoc/1/home?docid=1#foo')
foo.printdebug()

View File

@ -1,22 +1,34 @@
#!/usr/bin/python
#
# This file is part of the Lampadas Documentation System.
#
# Copyright (c) 2000, 2001, 2002 David Merrill <david@lupercalia.net>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Lampadas UnitTest Module
"""
import unittest
import Config
import Database
import DataLayer
import Converter
#import HTML
from Config import config
from Database import db
from DataLayer import lampadas
from Log import log
import commands
Config = Config.Config()
DB = Database.Database()
L = DataLayer.Lampadas()
# Test Suite ###################################################################
#def TS():
@ -27,350 +39,369 @@ L = DataLayer.Lampadas()
# Unit Tests ###################################################################
class testConfigFile(unittest.TestCase):
def testConfigFIle(self):
L.Log(3, 'testing Config file')
assert Config.DBType == "pgsql", "DBType is not valid"
assert Config.DBName == "lampadas", "Database name is not valid"
assert Config.CVSRoot > ''
L.Log(3, 'testing Config file done')
def testConfigFIle(self):
log(3, 'testing Config file')
assert config.db_type == "pgsql", "DBType is not valid"
assert config.db_name == "lampadas", "Database name is not valid"
assert config.cvs_root > ''
log(3, 'testing Config file done')
class testDatabase(unittest.TestCase):
def setUp(self):
DB.Connect(Config.DBType, Config.DBName)
def setUp(self):
DB.Connect(Config.DBType, Config.DBName)
def testDatabase(self):
L.Log(3, 'testing database')
assert not DB.Connection == None
L.Log(3, 'testing database done')
def testDatabase(self):
log(3, 'testing database')
assert not DB.Connection == None
log(3, 'testing database done')
def testCursor(self):
log(3, 'testing cursor')
self.Cursor = DB.Cursor
assert not self.Cursor == None
log(3, 'testing cursor done')
def testCursor(self):
L.Log(3, 'testing cursor')
self.Cursor = DB.Cursor
assert not self.Cursor == None
L.Log(3, 'testing cursor done')
class testClasses(unittest.TestCase):
def testClasses(self):
L.Log(3, 'testing classes')
assert not L.Classes == None
assert L.Classes.Count() > 0
L.Log(3, 'testing classes done')
def testClasses(self):
log(3, 'testing classes')
assert not L.Classes == None
assert lampadas.Classes.Count() > 0
log(3, 'testing classes done')
class testConfig(unittest.TestCase):
def testConfig(self):
L.Log(3, 'testing Config')
assert not L.Config == None
assert L.Config['project_short'] == 'LDP'
L.Log(3, 'testing Config done')
def testConfig(self):
log(3, 'testing Config')
assert not config == None
assert config['project_short'] == 'LDP'
log(3, 'testing Config done')
class testDocs(unittest.TestCase):
def testDocs(self):
L.Log(3, 'testing Docs')
assert not L.Docs == None
assert L.Docs.Count() > 0
def testDocs(self):
log(3, 'testing Docs')
assert not lampadas.Docs == None
assert lampadas.Docs.Count() > 0
DB.Exec("DELETE FROM document where title='testharness'")
DB.Commit()
self.OldID = DB.Value('SELECT max(doc_id) from document')
self.NewID = L.Docs.Add('testharness', 1, 1, 'DocBook', '4.1.2', '1.0', '2002-04-04', 'http://www.example.com/HOWTO.html', 'ISBN', 'N', 'N', '2002-04-05', '2002-04-10', 'http://www.home.com', 'N', 'GFDL', 'This is a document.', 'EN', 'fooseries')
assert self.NewID > 0
assert self.OldID + 1 == self.NewID
self.Doc = L.Doc(self.NewID)
assert not self.Doc == None
assert self.Doc.ID == self.NewID
assert self.Doc.Title == 'testharness'
assert self.Doc.FormatID == 1
L.Docs.Del(self.NewID)
self.NewID = DB.Value('SELECT MAX(doc_id) from document')
assert self.NewID == self.OldID
DB.Exec("DELETE FROM document where title='testharness'")
DB.Commit()
self.OldID = DB.Value('SELECT max(doc_id) from document')
self.NewID = lampadas.Docs.Add('testharness', 1, 1, 'DocBook', '4.1.2', '1.0', '2002-04-04', 'http://www.example.com/HOWTO.html', 'ISBN', 'N', 'N', '2002-04-05', '2002-04-10', 'http://www.home.com', 'N', 'GFDL', 'This is a document.', 'EN', 'fooseries')
assert self.NewID > 0
assert self.OldID + 1 == self.NewID
self.Doc = lampadas.Doc(self.NewID)
assert not self.Doc == None
assert self.Doc.ID == self.NewID
assert self.Doc.Title == 'testharness'
assert self.Doc.FormatID == 1
lampadas.Docs.Del(self.NewID)
self.NewID = DB.Value('SELECT MAX(doc_id) from document')
assert self.NewID == self.OldID
keys = L.Docs.keys()
for key in keys:
self.Doc = L.Docs[key]
assert self.Doc.ID == key
L.Log(3, 'testing Docs done')
keys = lampadas.Docs.keys()
for key in keys:
self.Doc = lampadas.Docs[key]
assert self.Doc.ID == key
log(3, 'testing Docs done')
def testMapping(self):
L.Log(3, 'testing Docs Mapping')
self.Doc = L.Docs[100]
assert not self.Doc == None
assert not self.Doc.Title == ''
assert self.Doc.ID == 100
self.Doc = L.Docs[2]
assert self.Doc.ID == 2
L.Log(3, 'testing Docs Mapping done')
def testMapping(self):
log(3, 'testing Docs Mapping')
self.Doc = lampadas.Docs[100]
assert not self.Doc == None
assert not self.Doc.Title == ''
assert self.Doc.ID == 100
self.Doc = lampadas.Docs[2]
assert self.Doc.ID == 2
log(3, 'testing Docs Mapping done')
def testSave(self):
log(3, 'testing Docs Save')
self.Doc = lampadas.Docs[100]
self.Title = self.Doc.Title
self.Doc.Title = 'Foo'
assert self.Doc.Title == 'Foo'
self.Doc.Save()
self.Doc2 = lampadas.Docs[100]
assert self.Doc2.Title == 'Foo'
self.Doc.Title = self.Title
assert self.Doc.Title == self.Title
self.Doc.Save()
self.Doc2 = lampadas.Docs[100]
assert self.Doc2.Title == self.Title
log(3, 'testing Docs Save done')
def testSave(self):
L.Log(3, 'testing Docs Save')
self.Doc = L.Docs[100]
self.Title = self.Doc.Title
self.Doc.Title = 'Foo'
assert self.Doc.Title == 'Foo'
self.Doc.Save()
self.Doc2 = L.Docs[100]
assert self.Doc2.Title == 'Foo'
self.Doc.Title = self.Title
assert self.Doc.Title == self.Title
self.Doc.Save()
self.Doc2 = L.Docs[100]
assert self.Doc2.Title == self.Title
L.Log(3, 'testing Docs Save done')
class testDocErrs(unittest.TestCase):
def testDocErrs(self):
L.Log(3, 'testing DocErrs')
keys = L.Docs.keys()
for key in keys:
Doc = L.Docs[key]
assert not Doc == None
if Doc.Errs.Count() > 0:
print "found a doc with errors"
for Err in Doc.Errs:
assert not Err == None
assert Err.DocID == Doc.ID
assert Err.ErrID > 1
L.Log(3, 'testing DocErrs done')
def testDocErrs(self):
log(3, 'testing DocErrs')
keys = lampadas.Docs.keys()
for key in keys:
Doc = lampadas.Docs[key]
assert not Doc == None
if Doc.Errs.Count() > 0:
log("found a doc with errors")
for Err in Doc.Errs:
assert not Err == None
assert Err.DocID == Doc.ID
assert Err.ErrID > 1
log(3, 'testing DocErrs done')
class testDocFiles(unittest.TestCase):
def testDocFiles(self):
L.Log(3, 'testing DocFiles')
Doc = L.Docs[100]
assert not Doc == None
assert Doc.Files.Count() > 0
keys = Doc.Files.keys()
for key in keys:
File = Doc.Files[key]
if File == None: break
assert File.DocID == Doc.ID
assert File.Filename > ''
L.Log(3, 'testing DocFiles done')
def testDocFiles(self):
log(3, 'testing DocFiles')
Doc = lampadas.Docs[100]
assert not Doc == None
assert Doc.Files.Count() > 0
keys = Doc.Files.keys()
for key in keys:
File = Doc.Files[key]
if File == None: break
assert File.DocID == Doc.ID
assert File.Filename > ''
log(3, 'testing DocFiles done')
class testDocRatings(unittest.TestCase):
def testDocRatings(self):
L.Log(3, 'testing DocRatings')
Doc = L.Docs[100]
assert not Doc == None
Doc.Ratings.Clear()
assert Doc.Ratings.Count() == 0
assert Doc.Rating == 0
def testDocRatings(self):
log(3, 'testing DocRatings')
Doc = lampadas.Docs[100]
assert not Doc == None
Doc.Ratings.Clear()
assert Doc.Ratings.Count() == 0
assert Doc.Rating == 0
# Add UserID: 1 Rating: 5 -- Avg: 5
# Add UserID: 1 Rating: 5 -- Avg: 5
Doc.Ratings.Add(1, 5)
assert Doc.Ratings.Count() == 1
assert Doc.Ratings.Average == 5
assert Doc.Rating == 5
Doc.Ratings.Add(1, 5)
assert Doc.Ratings.Count() == 1
assert Doc.Ratings.Average == 5
assert Doc.Rating == 5
# Add UserID: 2 Rating: 7 -- Avg: 6
Doc.Ratings.Add(2, 7)
assert Doc.Ratings.Count() == 2
assert Doc.Ratings.Average == 6
assert Doc.Rating == 6
# Add UserID: 2 Rating: 7 -- Avg: 6
Doc.Ratings.Add(2, 7)
assert Doc.Ratings.Count() == 2
assert Doc.Ratings.Average == 6
assert Doc.Rating == 6
# Del UserID: 1
Doc.Ratings.Del(1)
assert Doc.Ratings.Count() == 1
assert Doc.Ratings.Average == 7
assert Doc.Rating == 7
# Del UserID: 1
Doc.Ratings.Del(1)
assert Doc.Ratings.Count() == 1
assert Doc.Ratings.Average == 7
assert Doc.Rating == 7
# Clear again
# Clear again
Doc.Ratings.Clear()
assert Doc.Ratings.Count() == 0
assert Doc.Ratings.Average == 0
assert Doc.Rating == 0
log(3, 'testing DocRatings done')
Doc.Ratings.Clear()
assert Doc.Ratings.Count() == 0
assert Doc.Ratings.Average == 0
assert Doc.Rating == 0
L.Log(3, 'testing DocRatings done')
class testDocVersions(unittest.TestCase):
def testDocVersions(self):
L.Log(3, 'testing DocVersions')
keys = L.Docs.keys()
found = 0
for key in keys:
Doc = L.Docs[key]
assert not Doc == None
if Doc.Versions.Count() > 0:
found = 1
vkeys = Doc.Versions.keys()
for vkey in vkeys:
Version = Doc.Versions[vkey]
assert not Version == None
assert Version.PubDate > ''
assert Version.Initials > ''
assert found == 1
L.Log(3, 'testing DocVersions done')
def testDocVersions(self):
log(3, 'testing DocVersions')
keys = lampadas.Docs.keys()
found = 0
for key in keys:
Doc = lampadas.Docs[key]
assert not Doc == None
if Doc.Versions.Count() > 0:
found = 1
vkeys = Doc.Versions.keys()
for vkey in vkeys:
Version = Doc.Versions[vkey]
assert not Version == None
assert Version.PubDate > ''
assert Version.Initials > ''
assert found == 1
log(3, 'testing DocVersions done')
class testDTDs(unittest.TestCase):
def testDTDs(self):
L.Log(3, 'testing DTDs')
assert L.DTDs.Count() > 0
assert not L.DTDs['DocBook'] == None
L.Log(3, 'testing DTDs done')
def testDTDs(self):
log(3, 'testing DTDs')
assert lampadas.DTDs.Count() > 0
assert not lampadas.DTDs['DocBook'] == None
log(3, 'testing DTDs done')
class testFormats(unittest.TestCase):
def testFormats(self):
L.Log(3, 'testing Formats')
assert L.Formats.Count() > 0
assert not L.Formats[1] == None
assert not L.Formats[1].I18n == None
assert not L.Formats[1].I18n['EN'] == None
assert L.Formats[1].I18n['EN'].Name > ''
assert L.Formats[1].I18n['EN'].Description > ''
L.Log(3, 'testing Formats done')
def testFormats(self):
log(3, 'testing Formats')
assert lampadas.Formats.Count() > 0
assert not lampadas.Formats[1] == None
assert not lampadas.Formats[1].I18n == None
assert not lampadas.Formats[1].I18n['EN'] == None
assert lampadas.Formats[1].I18n['EN'].Name > ''
assert lampadas.Formats[1].I18n['EN'].Description > ''
log(3, 'testing Formats done')
class testLanguages(unittest.TestCase):
def testLanguages(self):
L.Log(3, 'testing Languages')
assert L.Languages['EN'].Supported
assert L.Languages['EN'].I18n['EN'].Name == 'English'
assert L.Languages['FR'].Supported
assert L.Languages['FR'].I18n['EN'].Name == 'French'
assert L.Languages.Count() == 136
L.Log(3, 'testing Languages done')
def testLanguages(self):
log(3, 'testing Languages')
assert lampadas.Languages['EN'].Supported
assert lampadas.Languages['EN'].I18n['EN'].Name == 'English'
assert lampadas.Languages['FR'].Supported
assert lampadas.Languages['FR'].I18n['EN'].Name == 'French'
assert lampadas.Languages.Count() == 136
log(3, 'testing Languages done')
class testPubStatuses(unittest.TestCase):
def testPubStatuses(self):
L.Log(3, 'testing PubStatuses')
assert not L.PubStatuses == None
assert L.PubStatuses.Count() > 0
assert not L.PubStatuses['A'] == None
assert not L.PubStatuses['A'].I18n == None
assert not L.PubStatuses['A'].I18n['EN'] == None
assert L.PubStatuses['A'].I18n['EN'].Name > ''
assert L.PubStatuses['A'].I18n['EN'].Description > ''
L.Log(3, 'testing PubStatuses done')
def testPubStatuses(self):
log(3, 'testing PubStatuses')
assert not lampadas.PubStatuses == None
assert lampadas.PubStatuses.Count() > 0
assert not lampadas.PubStatuses['A'] == None
assert not lampadas.PubStatuses['A'].I18n == None
assert not lampadas.PubStatuses['A'].I18n['EN'] == None
assert lampadas.PubStatuses['A'].I18n['EN'].Name > ''
assert lampadas.PubStatuses['A'].I18n['EN'].Description > ''
log(3, 'testing PubStatuses done')
class testTopics(unittest.TestCase):
def testTopics(self):
L.Log(3, 'testing Topics')
assert not L.Topics == None
assert L.Topics.Count() > 0
keys = L.Topics.keys()
for key in keys:
Topic = L.Topics[key]
assert Topic.Num > 0
assert Topic.I18n['EN'].Name > ''
L.Log(3, 'testing Topics done')
def testTopics(self):
log(3, 'testing Topics')
assert not lampadas.Topics == None
assert lampadas.Topics.Count() > 0
keys = lampadas.Topics.keys()
for key in keys:
Topic = lampadas.Topics[key]
assert Topic.Num > 0
assert Topic.I18n['EN'].Name > ''
log(3, 'testing Topics done')
class testUsers(unittest.TestCase):
def testUsers(self):
L.Log(3, 'testing Users')
assert not L.Users == None
assert L.Users.Count() > 0
def testUsers(self):
log(3, 'testing Users')
assert not lampadas.Users == None
assert lampadas.Users.Count() > 0
DB.Exec("DELETE FROM username where email='foo@example.com'")
DB.Commit()
self.OldID = DB.Value('SELECT MAX(user_id) from username')
self.NewID = lampadas.Users.Add('testuser', 'j', 'random', 'hacker', 'foo@example.com', 1, 1, 'pw', 'notes go here', 'default')
assert self.NewID > 0
assert self.OldID + 1 == self.NewID
self.User = lampadas.User(self.NewID)
assert not self.User == None
assert self.User.ID == self.NewID
assert self.User.Username == 'testuser'
assert self.User.Email == 'foo@example.com'
lampadas.Users.Del(self.NewID)
self.NewID = DB.Value('SELECT MAX(user_id) from username')
assert self.NewID == self.OldID
log(3, 'testing Users done')
DB.Exec("DELETE FROM username where email='foo@example.com'")
DB.Commit()
self.OldID = DB.Value('SELECT MAX(user_id) from username')
self.NewID = L.Users.Add('testuser', 'j', 'random', 'hacker', 'foo@example.com', 1, 1, 'pw', 'notes go here', 'default')
assert self.NewID > 0
assert self.OldID + 1 == self.NewID
self.User = L.User(self.NewID)
assert not self.User == None
assert self.User.ID == self.NewID
assert self.User.Username == 'testuser'
assert self.User.Email == 'foo@example.com'
L.Users.Del(self.NewID)
self.NewID = DB.Value('SELECT MAX(user_id) from username')
assert self.NewID == self.OldID
L.Log(3, 'testing Users done')
class testUserDocs(unittest.TestCase):
def testUserDocs(self):
log(3, 'testing UserDocs')
self.User = lampadas.User(11)
assert len(self.User.Docs) > 0
assert self.User.Docs.Count() > 0
assert not self.User.Docs == None
for UserDoc in self.User.Docs:
assert not UserDoc == None
assert not UserDoc.DocID == None
assert UserDoc.DocID > 0
assert UserDoc.DocID == UserDoc.ID
assert UserDoc.Active == 1 or UserDoc.Active == 0
log(3, 'testing UserDocs done')
def testUserDocs(self):
L.Log(3, 'testing UserDocs')
self.User = L.User(11)
assert len(self.User.Docs) > 0
assert self.User.Docs.Count() > 0
assert not self.User.Docs == None
for UserDoc in self.User.Docs:
assert not UserDoc == None
assert not UserDoc.DocID == None
assert UserDoc.DocID > 0
assert UserDoc.Active == 1 or UserDoc.Active == 0
L.Log(3, 'testing UserDocs done')
class testConverter(unittest.TestCase):
def setUp(self):
self.C = Converter.Converter()
def run(self, dir, base, ext, output):
self.filename = dir + base + ext
self.xmlnew = dir + base + '.xml.new'
self.md5new = dir + base + '.md5.new'
self.md5old = dir + base + '.md5.old'
fd = open(self.xmlnew, 'w')
fd.write(output + "\n")
fd.close()
newchecksum = commands.getoutput('md5sum < ' + self.xmlnew)
newchecksum = newchecksum + "\n"
fd = open(self.md5new, 'w')
fd.write(newchecksum)
fd.close()
fd = open(self.md5old, 'r')
oldchecksum = fd.read()
fd.close()
assert oldchecksum == newchecksum
def testWikiText(self):
output = self.C.wikitext('test/wt/Lampadas.wt')
self.run('test/wt/', 'Lampadas', '.wt', output)
def testTexinfo(self):
output = self.C.texinfo('test/texinfo/texinfo.txi')
self.run('test/texinfo/', 'texinfo', '.txi', output)
def testDBSGML(self):
output = self.C.dbsgml('test/db3.0sgml/RPM-HOWTO.sgml')
self.run('test/db3.0sgml/', 'RPM-HOWTO', '.sgml', output)
output = self.C.dbsgml('test/db3.1sgml/XFree86-Second-Mouse.sgml')
self.run('test/db3.1sgml/', 'XFree86-Second-Mouse', '.sgml', output)
output = self.C.dbsgml('test/db4.1sgml/Small-Memory.sgml')
self.run('test/db4.1sgml/', 'Small-Memory', '.sgml', output)
#class testConverter(unittest.TestCase):
#
# import Converter
#
# def setUp(self):
# self.C = Converter.Converter()
#
# def run(self, dir, base, ext, output):
# self.filename = dir + base + ext
# self.xmlnew = dir + base + '.xml.new'
# self.md5new = dir + base + '.md5.new'
# self.md5old = dir + base + '.md5.old'
#
# fd = open(self.xmlnew, 'w')
# fd.write(output + "\n")
# fd.close()
#
# newchecksum = commands.getoutput('md5sum < ' + self.xmlnew)
# newchecksum = newchecksum + "\n"
#
# fd = open(self.md5new, 'w')
# fd.write(newchecksum)
# fd.close()
#
# fd = open(self.md5old, 'r')
# oldchecksum = fd.read()
# fd.close()
#
# assert oldchecksum == newchecksum
#
# def testWikiText(self):
#
# output = self.C.wikitext('test/wt/Lampadas.wt')
# self.run('test/wt/', 'Lampadas', '.wt', output)
#
# def testTexinfo(self):
# output = self.C.texinfo('test/texinfo/texinfo.txi')
# self.run('test/texinfo/', 'texinfo', '.txi', output)
#
# def testDBSGML(self):
# output = self.C.dbsgml('test/db3.0sgml/RPM-HOWTO.sgml')
# self.run('test/db3.0sgml/', 'RPM-HOWTO', '.sgml', output)
#
# output = self.C.dbsgml('test/db3.1sgml/XFree86-Second-Mouse.sgml')
# self.run('test/db3.1sgml/', 'XFree86-Second-Mouse', '.sgml', output)
#
# output = self.C.dbsgml('test/db4.1sgml/Small-Memory.sgml')
# self.run('test/db4.1sgml/', 'Small-Memory', '.sgml', output)
#class testHTML(unittest.TestCase):
# def setUp(self):
# self.HTML = HTML.HTMLFactory()
# self.HTML = HTMlampadas.HTMLFactory()
# def testHTML(self):
# assert not self.HTML.Page == None
# assert self.HTML.Page('test', 'EN') > ''
# assert not self.HTMlampadas.Page == None
# assert self.HTMlampadas.Page('test', 'EN') > ''
if __name__ == "__main__":
unittest.main()
unittest.main()

View File

@ -1,5 +1,23 @@
#!/usr/bin/python
#
# This file is part of the Lampadas Documentation System.
#
# Copyright (c) 2000, 2001, 2002 David Merrill <david@lupercalia.net>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Lampadas Web Objects Module
@ -12,15 +30,12 @@ should come through this layer.
from Globals import *
from BaseClasses import *
import Config
import Database
from Config import config
from Database import db
# Globals
Config = Config.Config()
DB = Database.Database()
DB.Connect(Config.DBType, Config.DBName)
# Blocks
@ -30,7 +45,7 @@ class Blocks(LampadasCollection):
def __init__(self):
self.data = {}
self.sql = "SELECT block_code FROM block"
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
self.row = self.cursor.fetchone()
if self.row == None: break
@ -46,7 +61,7 @@ class Block:
def Load(self, row):
self.Code = trim(row[0])
self.sql = "SELECT lang, block FROM block_i18n WHERE block_code=" + wsq(self.Code)
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
self.row = self.cursor.fetchone()
if self.row == None: break
@ -68,7 +83,7 @@ class Sections(LampadasCollection):
def __init__(self):
self.data = {}
self.sql = "SELECT section_code FROM section"
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
self.row = self.cursor.fetchone()
if self.row == None: break
@ -84,7 +99,7 @@ class Section:
def Load(self, row):
self.Code = trim(row[0])
self.sql = "SELECT lang, section_name FROM section_i18n WHERE section_code=" + wsq(self.Code)
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
self.row = self.cursor.fetchone()
if self.row == None: break
@ -106,7 +121,7 @@ class Pages(LampadasCollection):
def __init__(self):
self.data = {}
self.sql = "SELECT page_code, section_code, template_code FROM page"
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
self.row = self.cursor.fetchone()
if self.row == None: break
@ -124,7 +139,7 @@ class Page:
self.SectionCode = trim(row[1])
self.TemplateCode = trim(row[2])
self.sql = "SELECT lang, title, page FROM page_i18n WHERE page_code=" + wsq(self.Code)
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
self.row = self.cursor.fetchone()
if self.row == None: break
@ -150,7 +165,7 @@ class Strings(LampadasCollection):
def __init__(self):
self.data = {}
self.sql = "SELECT string_code FROM string"
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
row = self.cursor.fetchone()
if row == None: break
@ -169,7 +184,7 @@ class String:
def Load(self, row):
self.Code = trim(row[0])
self.sql = "SELECT lang, string FROM string_i18n WHERE string_code=" + wsq(self.Code)
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
self.row = self.cursor.fetchone()
if self.row == None: break
@ -193,7 +208,7 @@ class Templates(LampadasCollection):
def __init__(self):
self.data = {}
self.sql = "SELECT template_code, template FROM template"
self.cursor = DB.Select(self.sql)
self.cursor = db.select(self.sql)
while (1):
self.row = self.cursor.fetchone()
if self.row == None: break

View File

@ -15,14 +15,7 @@ H1 {
letter-spacing: .05em;
}
H2 {
color: brown;
font-family: times;
font-size: 16pt;
font-style: bold;
letter-spacing: .05em;
}
H2
H2 SUP {
font-size: 8pt;
font-family: helvetica;
@ -92,6 +85,18 @@ TABLE.layout TD {
padding: 3;
}
TABLE.revhistory {
color: black;
background-color: tan;
border: solid brown;
border-width: 1;
}
TABLE.revhistory TH {
padding: 5;
}
TABLE.navbar {
border: solid brown;
border-width: 0;

16
LDP/lampadas/xsl/Makefile Normal file
View File

@ -0,0 +1,16 @@
xslprefix = /usr/local/share
INSTALLDIR = install -d
INSTALLXSL = install -p -m 644
all: build
build:
install: all
$(INSTALLDIR) $(xslprefix)/lampadas
$(INSTALLDIR) $(xslprefix)/lampadas/xsl
$(INSTALLXSL) *.xsl $(xslprefix)/lampadas/xsl
clean:

View File

@ -0,0 +1,30 @@
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version='1.0'
xmlns="http://www.w3.org/TR/xhtml1/transitional"
exclude-result-prefixes="#default">
<!-- $Id$ -->
<!-- This stylesheet is based on the ldp-html-chunk.xsl stylesheet
by Dan York -->
<!-- This stylesheet calls Norman Walsh's 'docbook.xsl' stylesheet
and therefore generates MULTIPLE HTML FILES as output. -->
<!-- Note the the *order* of the import statements below is important and
should not be changed. -->
<!-- Change this to the path to where you have installed Norman
Walsh's XSL stylesheets -->
<xsl:import href="/usr/share/sgml/docbook/stylesheet/xsl/nwalsh/html/chunk.xsl"/>
<!-- Imports the common LDP customization layer. -->
<xsl:import href="lampadas-html-common.xsl"/>
<!-- If there was some reason to override 'lampadas-html-common.xsl' or to
perform any other customizations that affect *only* the generation
of multiple HTML files, those templates or parameters could be
entered here. -->
</xsl:stylesheet>

View File

@ -0,0 +1,328 @@
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version='1.0'
xmlns="http://www.w3.org/TR/xhtml1/transitional"
exclude-result-prefixes="#default"
>
<!-- $Id -->
<!-- This stylesheet is based on ldp-html-common.xsl, an
experimental stylesheet by Dan York:
This is an attempt to replicate the customizations done in ldp.dsl
Each customization in ldp.dsl is listed in the order in which it
appears (in ldp.dsl) with the corresponding XSLT template or setting
below it. Where there is no XSLT code below an item, that particular
customization of ldp.dsl is not yet supported here. Some additional
options and features have been added and are noted as not being in
ldp.dsl. The work on this stylesheet began 5 Jul 2001. -->
<!-- Note that this file, 'lampadas-html-common.xsl', is NOT intended to be
called directly. Instead, you should call either of two stylesheets:
'lampadas-html.xsl' or 'lampadas-html-chunk.xsl'. The former generates a SINGLE
HTML file, while the latter performs "chunking" to generate MULTIPLE
HTML files. Both of those files import the appropriate Norman Walsh
stylesheet and then import this customization layer. -->
<!-- NOT IN LDP.DSL - This stylesheet supports the additional use of the
"role" and "condition" attributes to the <author> tag. The XSLT template
is listed later in the stylesheet, but the text lables are listed
here in order to make localization of the stylesheet easier. Note
that spaces *are* significant in the value, so you should have a
space after the colon. -->
<xsl:variable name="maintainerlabel">Maintainer</xsl:variable>
<xsl:variable name="editorlabel">Editor</xsl:variable>
<xsl:variable name="translatorlabel">Translator</xsl:variable>
<xsl:variable name="converterlabel">Converter</xsl:variable>
<xsl:variable name="authorlabel">Author</xsl:variable>
<!-- NOT IN LDP.DSL
Creates header content in all generated HTML files -->
<xsl:template name="user.head.content">
<xsl:param name="node" select="."/>
<meta name="generator" content="Lampadas XSL $Revision$"/>
<link rel="stylesheet" href="/css/default.css" type="text/css"/>
<xsl:text>
</xsl:text>
<xsl:comment> Generated by Lampadas XSLT customization layer
based on Dan York's hack of Norman Walsh's DocBook XSL stylesheets.
More information at http://www.tldp.org/ </xsl:comment>
<xsl:text>
</xsl:text>
</xsl:template>
<!-- generate-legalnotice-link?
Not currently supported in Norm's XSL stylesheets. Logged
at SourceForge as a bug. -->
<!-- Should graphics be used for admonitions (notes, warnings)? 0 or 1 -->
<xsl:param name="admon.graphics" select="0"/>
<!-- If using admon graphics (1 above), what is path to graphics?
Should be the path relative to your document and MUST end with
a trailing slash. Also, this parameter needs to be on a
single line. -->
<xsl:param name="admon.graphics.path">images/</xsl:param>
<!-- Make funcsynopsis look pretty -->
<xsl:param name="funcsynopsis.decoration" select="1" doc:type="boolean"/>
<!-- Extension for HTML files -->
<xsl:param name="html.ext" select="'.html'"/>
<!-- Generate TOCs for book, article, part -->
<xsl:param name="generate.book.toc" select="1" doc:type="boolean"/>
<xsl:param name="generate.article.toc" select="1" doc:type="boolean"/>
<xsl:param name="generate.part.toc" select="1" doc:type="boolean"/>
<!-- generate-book-titlepage -->
<!-- generate-article-titlepage -->
<!-- Equivalent to chunk-skip-first-element-list - forces TOC on separate page
If 0, first sect is on page for chapter or article -->
<xsl:param name="chunk.first.sections" select="'1'"/>
<!-- NOT IN LDP.DSL -->
<!-- Create chunks for top-level sections. If 0, chunks will only be
created for chapters/appendixes, and NOT for sectx elements -->
<xsl:param name="chunk.sections" select="'1'"/>
<!-- list-element-list - NO LONGER NEEDED - bug fix -->
<!-- Filename for the root chunk -->
<xsl:param name="root.filename" select="'index'"/>
<!-- shade-verbatim
I have created a function below that shades the verbatim sections.
logic would need to be added to check if this is set.
Norm has added parameters to his 1.44 stylesheets that support
shading verbatim sections. However, it looks like it requires
an attribute to a table to have verbatim shading. Needs to be
explored further. -->
<!-- When chunking, use id attribute as filename? 0 or 1 -->
<xsl:param name="use.id.as.filename" select="1"/>
<!-- graphic-extensions - NO LONGER NEEDED?? -->
<!-- default graphic filename extension -->
<xsl:param name="graphic.default.extension" select="'.gif'" doc:type="string"/>
<!-- Should chapters be labeled? 0 or 1 -->
<xsl:param name="chapter.autolabel" select="1"/>
<!-- Should sections be labeled? 0 or 1 -->
<xsl:param name="section.autolabel" select="1"/>
<!-- Related to section labels, should those labels include the chapter
number in them (i.e., 1.1, 1.2, 1.3, 1.4 )-->
<xsl:param name="section.label.includes.component.label" select="1" doc:type="boolean"/>
<!-- To what depth (in sections) should the TOC go? -->
<xsl:param name="toc.section.depth" select="3"/>
<!-- Custom 'emphasis' template to allow 'role="strong"' to
also produce a bold item. -->
<xsl:template match="emphasis">
<xsl:choose>
<xsl:when test="(@role='strong') or (@role='bold')">
<xsl:call-template name="inline.boldseq"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="inline.italicseq"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- book-titlepage-recto-elements
article-titlepage-recto-elements
article-titlepage-recto-mode
article-title
- Customizing these elements (for instance, to list what is on the
title page) involves writing a layer for html/titlepage.templates.xml and the
other files html/titlepage.xsl and html/titlepage.templates.xsl - Norm
is doing something funky here and I haven't fully figured it out. -->
<!-- The remainder of ldp.dsl deals with changing the foreground and
background colors of verbatim elements although in reading through the
DSSSL it doesn't look like it actually changed the foreground colors.
The changing of the background shading can be done at two locations
(one numbered, one not) in the template below. -->
<!-- Custom template for programlisting, screen and synopsis to generate a gray
background to the item. -->
<xsl:template match="programlisting|screen|synopsis">
<xsl:param name="suppress-numbers" select="'0'"/>
<xsl:variable name="vendor" select="system-property('xsl:vendor')"/>
<xsl:variable name="id"><xsl:call-template name="object.id"/></xsl:variable>
<xsl:if test="@id">
<a href="{$id}"/>
</xsl:if>
<xsl:choose>
<xsl:when test="$suppress-numbers = '0'
and @linenumbering = 'numbered'
and $use.extensions != '0'
and $linenumbering.extension != '0'">
<xsl:variable name="rtf">
<xsl:apply-templates/>
</xsl:variable>
<!-- Change the color bacground color in the line below. -->
<table border="0" bgcolor="#E0E0E0" width="90%">
<tr><td>
<pre class="{name(.)}">
<xsl:call-template name="number.rtf.lines">
<xsl:with-param name="rtf" select="$rtf"/>
</xsl:call-template>
</pre>
</td></tr></table>
</xsl:when>
<xsl:otherwise>
<!-- Change the color bacground color in the line below. -->
<table border="0" bgcolor="#E0E0E0" width="90%">
<tr><td>
<pre class="{name(.)}">
<xsl:apply-templates/>
</pre>
</td></tr></table>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- NOT IN LDP.DSL. Custom template to allow Maintainer to be a role in
the Author element. It also checks for a "condition" attribute
to the <author> element. If it finds the condition attribute, it
copies VERBATIM the value of the attribute to be in front of the
word Author or Maintainer. This is done to allow maximum flexibility.
Note that an <xsl:text> element was necessary to put the space
between the condition and the word Author or Maintainer. -->
<xsl:template match="author" mode="titlepage.mode">
<!-- If there is a condition attribute, print it VERBATIM first -->
<xsl:if test="@condition"><i><xsl:value-of select="@condition"/></i>
<xsl:text> </xsl:text></xsl:if>
<!-- Test to see if there is a role. If maintainer, print that. If not,
assume it is an author. -->
<table class="box"><tr><th colspan="2">
<xsl:choose>
<xsl:when test="@role='maintainer'">
<xsl:value-of select="$maintainerlabel"/>
</xsl:when>
<xsl:when test="@role='editor'">
<xsl:value-of select="$editorlabel"/>
</xsl:when>
<xsl:when test="@role='translator'">
<xsl:value-of select="$translatorlabel"/>
</xsl:when>
<xsl:when test="@role='converter'">
<xsl:value-of select="$converterlabel"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$authorlabel"/>
</xsl:otherwise>
</xsl:choose>
</th></tr>
<tr><td>
<xsl:call-template name="person.name"/>
</td><td>
<xsl:apply-templates mode="titlepage.mode" select="./contrib"/>
<xsl:apply-templates mode="titlepage.mode" select="./affiliation"/>
</td></tr></table>
</xsl:template>
<!-- Custom template to allow roles to be assigned to the OtherCredit
element. Roles are editor, translator, and converter. -->
<xsl:template match="othercredit" mode="titlepage.mode">
<!-- If there is a condition attribute, print it VERBATIM first -->
<xsl:if test="@condition"><i><xsl:value-of select="@condition"/></i>
<xsl:text> </xsl:text></xsl:if>
<!-- Test to see if there is a role. If no role is included,
assume it is maintainer. -->
<table class="box"><tr><th colspan="2">
<xsl:choose>
<xsl:when test="@role='editor'">
<xsl:value-of select="$editorlabel"/>
</xsl:when>
<xsl:when test="@role='translator'">
<xsl:value-of select="$translatorlabel"/>
</xsl:when>
<xsl:when test="@role='converter'">
<xsl:value-of select="$converterlabel"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$maintainerlabel"/>
</xsl:otherwise>
</xsl:choose>
</th></tr>
<tr><td>
<xsl:call-template name="person.name"/>
</td><td>
<xsl:apply-templates mode="titlepage.mode" select="./contrib"/>
<xsl:apply-templates mode="titlepage.mode" select="./affiliation"/>
</td></tr></table>
</xsl:template>
<xsl:template match="revhistory" mode="titlepage.mode">
<xsl:variable name="numcols">
<xsl:choose>
<xsl:when test="//authorinitials">3</xsl:when>
<xsl:otherwise>2</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<div class="{name(.)}">
<table class="box" summary="Revision history">
<tr>
<th colspan="{$numcols}">
<b>
<xsl:call-template name="gentext">
<xsl:with-param name="key" select="'RevHistory'"/>
</xsl:call-template>
</b>
</th>
</tr>
<xsl:apply-templates mode="titlepage.mode">
<xsl:with-param name="numcols" select="$numcols"/>
</xsl:apply-templates>
</table>
</div>
</xsl:template>
<xsl:template match="pubdate" mode="titlepage.mode">
<table class="box"><tr><th><xsl:value-of select="."/></th></tr></table>
</xsl:template>
<xsl:template match="abstract" mode="titlepage.mode">
<table class="box">
<tr><th>
<xsl:call-template name="anchor"/>
<xsl:call-template name="formal.object.heading">
<xsl:with-param name="title">
<xsl:apply-templates select="." mode="title.markup"/>
</xsl:with-param>
</xsl:call-template>
</th></tr>
<tr><td>
<xsl:apply-templates mode="titlepage.mode"/>
</td></tr>
</table>
</xsl:template>
<xsl:template name="formal.object.heading">
<xsl:apply-templates select="." mode="object.title.markup">
<xsl:with-param name="allow-anchors" select="1"/>
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>

View File

@ -0,0 +1,29 @@
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version='1.0'
xmlns="http://www.w3.org/TR/xhtml1/transitional"
exclude-result-prefixes="#default">
<!-- $Id$ -->
<!-- This stylesheet is based on ldp-html.xsl by Dan York. -->
<!-- This stylesheet calls Norman Walsh's 'docbook.xsl' stylesheet
and therefore generates a SINGLE HTML FILE as output. -->
<!-- Note the the *order* of the import statements below is important and
should not be changed. -->
<!-- Change this to the path to where you have installed Norman
Walsh's XSL stylesheets. -->
<xsl:import href="/usr/share/sgml/docbook/stylesheet/xsl/nwalsh/html/docbook.xsl"/>
<!-- Imports the common LDP customization layer. -->
<xsl:import href="lampadas-html-common.xsl"/>
<!-- If there was some reason to override 'lampadas-html-common.xsl' or to
perform any other customizations that affect *only* the generation
of a single HTML file, those templates or parameters could be
entered here. -->
</xsl:stylesheet>

View File

@ -0,0 +1,18 @@
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version='1.0'
xmlns="http://www.w3.org/TR/xhtml1/transitional"
exclude-result-prefixes="#default">
<!-- $Id$ -->
<!-- This stylesheet is based on the ldp-print.xsl stylesheet
written by Dan York.
<!-- Change this to the path to where you have installed Norman
Walsh's XSL stylesheets. -->
<xsl:import href="/usr/share/sgml/docbook/docbook-xsl-1.41/fo/docbook.xsl"/>
<!-- Customized parameters and templates go here. -->
</xsl:stylesheet>