From cff4a0ee0f4aaed78c316cf70e2a3263f3158f02 Mon Sep 17 00:00:00 2001 From: richard Date: Wed, 11 Feb 2004 23:55:10 +0000 Subject: [PATCH] documentation cleanup git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@2073 57a73879-2fb5-44c3-a270-3262357dd7e2 --- TODO.txt | 5 +- doc/.cvsignore | 2 +- doc/admin_guide.txt | 6 +- roundup/__init__.py | 15 +- roundup/admin.py | 7 +- roundup/backends/__init__.py | 5 +- roundup/backends/back_anydbm.py | 67 ++++---- roundup/backends/back_bsddb.py | 6 +- roundup/backends/back_bsddb3.py | 6 +- roundup/backends/back_metakit.py | 169 ++++++------------- roundup/backends/back_mysql.py | 31 ++-- roundup/backends/back_postgresql.py | 5 +- roundup/backends/back_sqlite.py | 7 +- roundup/backends/blobfiles.py | 6 +- roundup/backends/locking.py | 3 +- roundup/backends/portalocker.py | 20 ++- roundup/backends/rdbms_common.py | 49 +++--- roundup/backends/sessions.py | 7 +- roundup/cgi/PageTemplates/Expressions.py | 3 +- roundup/cgi/PageTemplates/PageTemplate.py | 3 +- roundup/cgi/PageTemplates/PathIterator.py | 3 +- roundup/cgi/PageTemplates/PythonExpr.py | 3 +- roundup/cgi/PageTemplates/TALES.py | 3 +- roundup/cgi/PageTemplates/__init__.py | 3 +- roundup/cgi/TAL/HTMLParser.py | 1 + roundup/cgi/TAL/HTMLTALParser.py | 4 +- roundup/cgi/TAL/TALDefs.py | 4 +- roundup/cgi/TAL/TALGenerator.py | 4 +- roundup/cgi/TAL/TALInterpreter.py | 4 +- roundup/cgi/TAL/TALParser.py | 4 +- roundup/cgi/TAL/XMLParser.py | 4 +- roundup/cgi/TAL/__init__.py | 3 +- roundup/cgi/TAL/markupbase.py | 4 +- roundup/cgi/ZTUtils/Batch.py | 5 +- roundup/cgi/ZTUtils/Iterator.py | 5 +- roundup/cgi/ZTUtils/__init__.py | 5 +- roundup/cgi/__init__.py | 3 +- roundup/cgi/cgitb.py | 6 +- roundup/cgi/client.py | 192 ++++++++++++---------- roundup/cgi/templating.py | 112 +++++++------ roundup/date.py | 36 ++-- roundup/hyperdb.py | 60 ++++--- roundup/i18n.py | 10 +- roundup/indexer.py | 33 ++-- roundup/init.py | 47 +++--- roundup/install_util.py | 6 +- roundup/instance.py | 6 +- roundup/mailer.py | 6 +- roundup/mailgw.py | 6 +- roundup/password.py | 6 +- roundup/rcsv.py | 5 +- roundup/rfc2822.py | 9 +- roundup/roundupdb.py | 26 +-- roundup/scripts/__init__.py | 8 +- roundup/scripts/roundup_admin.py | 6 +- roundup/scripts/roundup_mailgw.py | 6 +- roundup/scripts/roundup_server.py | 6 +- roundup/security.py | 4 + roundup/token.py | 28 ++-- roundup/version_check.py | 6 +- 60 files changed, 580 insertions(+), 534 deletions(-) diff --git a/TODO.txt b/TODO.txt index cf79d7f..f300d4f 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,7 +1,10 @@ This file has been re-purposed to contain specifically the items that need doing before the next release: +- sessions, otks and indexing in RDBMSes - add tests for group-by-multilink so I finally implement it for the RDBMSes - full coverage analysis for unit tests -- migrate to numeric ID values (fixes bug 817217) +- s/getnode/getitem in backends (and s/Node/Item) +- activity_by meta-property +- migrate to numeric ID values (fixes bug 817217) diff --git a/doc/.cvsignore b/doc/.cvsignore index 77efb76..1a1a62a 100644 --- a/doc/.cvsignore +++ b/doc/.cvsignore @@ -11,7 +11,7 @@ features.html upgrading.html glossary.html design.html -maintenance.html +admin_guide.html overview.html mysql.html postgresql.html diff --git a/doc/admin_guide.txt b/doc/admin_guide.txt index a48678a..558ea38 100644 --- a/doc/admin_guide.txt +++ b/doc/admin_guide.txt @@ -2,7 +2,7 @@ Administration Guide ==================== -:Version: $Revision: 1.1 $ +:Version: $Revision: 1.2 $ .. contents:: @@ -23,7 +23,7 @@ There's two "installations" that we talk about when using Roundup: Support files \share\roundup\... - and on *nix (eg. Linux): + and on Unix-like systems (eg. Linux): Scripts /bin/... @@ -84,7 +84,7 @@ Maintenance of Roundup can involve one of the following: 1. `tracker backup`_ 2. `software upgrade`_ 3. `migrating backends`_ -3. `moving a tracker`_ +4. `moving a tracker`_ Tracker Backup diff --git a/roundup/__init__.py b/roundup/__init__.py index 24f50c4..f2abcc0 100644 --- a/roundup/__init__.py +++ b/roundup/__init__.py @@ -15,9 +15,9 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: __init__.py,v 1.26 2004-01-20 00:05:07 richard Exp $ +# $Id: __init__.py,v 1.27 2004-02-11 23:55:08 richard Exp $ -''' Roundup - issue tracking for knowledge workers. +'''Roundup - issue tracking for knowledge workers. This is a simple-to-use and -install issue-tracking system with command-line, web and e-mail interfaces. @@ -43,11 +43,11 @@ Roundup's structure is that of a cake:: | Storage Layer | ------------------------------------------------------------------------- -The first layer represents the users (chocolate). -The second layer is the Roundup interface to the users (vanilla). -The third and fourth layers are the internal Roundup database storage - mechanisms (strawberry). -The final, lowest layer is the underlying database storage (rum). +1. The first layer represents the users (chocolate). +2. The second layer is the Roundup interface to the users (vanilla). +3. The third and fourth layers are the internal Roundup database storage + mechanisms (strawberry). +4. The final, lowest layer is the underlying database storage (rum). These are implemented in the code in the following manner:: @@ -66,6 +66,7 @@ For more information, see the original overview and specification documents written by Ka-Ping Yee in the "doc" directory. If nothing else, it has a much prettier cake :) ''' +__docformat__ = 'restructuredtext' __version__ = '0.7.0b1' diff --git a/roundup/admin.py b/roundup/admin.py index 9ae6ba3..c08f0e8 100644 --- a/roundup/admin.py +++ b/roundup/admin.py @@ -16,10 +16,11 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: admin.py,v 1.61 2003-11-13 04:12:10 richard Exp $ +# $Id: admin.py,v 1.62 2004-02-11 23:55:08 richard Exp $ '''Administration commands for maintaining Roundup trackers. ''' +__docformat__ = 'restructuredtext' import sys, os, getpass, getopt, re, UserDict, shutil, rfc822 from roundup import date, hyperdb, roundupdb, init, password, token, rcsv @@ -826,6 +827,7 @@ Command help: specified, all properties are displayed. By default, the column widths are the width of the largest value. The width may be explicitly defined by defining the property as "name:width". For example:: + roundup> table priority id,name:10 Id Name 1 fatal-bug @@ -834,7 +836,8 @@ Command help: 4 feature Also to make the width of the column the width of the label, - leave a trailing : without a width on the property. E.G. + leave a trailing : without a width on the property. For example:: + roundup> table priority id,name: Id Name 1 fata diff --git a/roundup/backends/__init__.py b/roundup/backends/__init__.py index 15ae2ac..ecacacb 100644 --- a/roundup/backends/__init__.py +++ b/roundup/backends/__init__.py @@ -15,13 +15,14 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: __init__.py,v 1.25 2003-10-25 22:53:26 richard Exp $ +# $Id: __init__.py,v 1.26 2004-02-11 23:55:08 richard Exp $ -''' Container for the hyperdb storage backend implementations. +'''Container for the hyperdb storage backend implementations. The __all__ variable is constructed containing only the backends which are available. ''' +__docformat__ = 'restructuredtext' __all__ = [] diff --git a/roundup/backends/back_anydbm.py b/roundup/backends/back_anydbm.py index 6450b26..6ea53c0 100644 --- a/roundup/backends/back_anydbm.py +++ b/roundup/backends/back_anydbm.py @@ -15,13 +15,13 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -#$Id: back_anydbm.py,v 1.134 2003-12-10 01:40:51 richard Exp $ -''' -This module defines a backend that saves the hyperdatabase in a database -chosen by anydbm. It is guaranteed to always be available in python +#$Id: back_anydbm.py,v 1.135 2004-02-11 23:55:08 richard Exp $ +'''This module defines a backend that saves the hyperdatabase in a +database chosen by anydbm. It is guaranteed to always be available in python versions >2.1.1 (the dumbdbm fallback in 2.1.1 and earlier has several serious bugs, and is not available) ''' +__docformat__ = 'restructuredtext' try: import anydbm, sys @@ -50,10 +50,10 @@ class Database(FileStorage, hyperdb.Database, roundupdb.Database): '''A database for storing records containing flexible data types. Transaction stuff TODO: - . check the timestamp of the class file and nuke the cache if it's - modified. Do some sort of conflict checking on the dirty stuff. - . perhaps detect write collisions (related to above)? - + + - check the timestamp of the class file and nuke the cache if it's + modified. Do some sort of conflict checking on the dirty stuff. + - perhaps detect write collisions (related to above)? ''' def __init__(self, config, journaltag=None): '''Open a hyperdatabase given a specifier to some storage. @@ -92,14 +92,15 @@ class Database(FileStorage, hyperdb.Database, roundupdb.Database): self.lockfile.flush() def post_init(self): - ''' Called once the schema initialisation has finished. + '''Called once the schema initialisation has finished. ''' # reindex the db if necessary if self.indexer.should_reindex(): self.reindex() def refresh_database(self): - "Rebuild the database" + """Rebuild the database + """ self.reindex() def reindex(self): @@ -1366,8 +1367,11 @@ class Class(hyperdb.Class): WARNING: this method should never be used except in extremely rare situations where there could never be links to the node being deleted + WARNING: use retire() instead + WARNING: the properties of this node will not be available ever again + WARNING: really, use retire() instead Well, I think that's enough warnings. This method exists mostly to @@ -1418,14 +1422,15 @@ class Class(hyperdb.Class): return self.key def labelprop(self, default_to_id=0): - ''' Return the property name for a label for the given node. + '''Return the property name for a label for the given node. This method attempts to generate a consistent label for the node. It tries the following in order: - 1. key property - 2. "name" property - 3. "title" property - 4. first property from the sorted property name list + + 1. key property + 2. "name" property + 3. "title" property + 4. first property from the sorted property name list ''' k = self.getkey() if k: @@ -1597,21 +1602,23 @@ class Class(hyperdb.Class): def filter(self, search_matches, filterspec, sort=(None,None), group=(None,None), num_re = re.compile('^\d+$')): - ''' Return a list of the ids of the active nodes in this class that - match the 'filter' spec, sorted by the group spec and then the - sort spec. - - "filterspec" is {propname: value(s)} - "sort" and "group" are (dir, prop) where dir is '+', '-' or None - and prop is a prop name or None - "search_matches" is {nodeid: marker} - - The filter must match all properties specificed - but if the - property value to match is a list, any one of the values in the - list may match for that property to match. Unless the property - is a Multilink, in which case the item's property list must - match the filterspec list. - ''' + """Return a list of the ids of the active nodes in this class that + match the 'filter' spec, sorted by the group spec and then the + sort spec. + + "filterspec" is {propname: value(s)} + + "sort" and "group" are (dir, prop) where dir is '+', '-' or None + and prop is a prop name or None + + "search_matches" is {nodeid: marker} + + The filter must match all properties specificed - but if the + property value to match is a list, any one of the values in the + list may match for that property to match. Unless the property + is a Multilink, in which case the item's property list must + match the filterspec list. + """ cn = self.classname # optimise filterspec diff --git a/roundup/backends/back_bsddb.py b/roundup/backends/back_bsddb.py index 37abdd8..0251da8 100644 --- a/roundup/backends/back_bsddb.py +++ b/roundup/backends/back_bsddb.py @@ -15,10 +15,10 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -#$Id: back_bsddb.py,v 1.28 2003-11-14 00:11:18 richard Exp $ -''' -This module defines a backend that saves the hyperdatabase in BSDDB. +#$Id: back_bsddb.py,v 1.29 2004-02-11 23:55:08 richard Exp $ +'''This module defines a backend that saves the hyperdatabase in BSDDB. ''' +__docformat__ = 'restructuredtext' import bsddb, os, marshal from roundup import hyperdb, date diff --git a/roundup/backends/back_bsddb3.py b/roundup/backends/back_bsddb3.py index 444fe65..dbf8675 100644 --- a/roundup/backends/back_bsddb3.py +++ b/roundup/backends/back_bsddb3.py @@ -15,10 +15,10 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -#$Id: back_bsddb3.py,v 1.21 2003-11-14 00:11:18 richard Exp $ -''' -This module defines a backend that saves the hyperdatabase in BSDDB3. +#$Id: back_bsddb3.py,v 1.22 2004-02-11 23:55:08 richard Exp $ +'''This module defines a backend that saves the hyperdatabase in BSDDB3. ''' +__docformat__ = 'restructuredtext' import bsddb3, os, marshal from roundup import hyperdb, date diff --git a/roundup/backends/back_metakit.py b/roundup/backends/back_metakit.py index 201dd4e..1d2a111 100755 --- a/roundup/backends/back_metakit.py +++ b/roundup/backends/back_metakit.py @@ -1,111 +1,46 @@ -# $Id: back_metakit.py,v 1.57 2004-01-27 18:10:48 wc2so1 Exp $ +# $Id: back_metakit.py,v 1.58 2004-02-11 23:55:08 richard Exp $ +'''Metakit backend for Roundup, originally by Gordon McMillan. + +Known Current Bugs: + +- You can't change a class' key properly. This shouldn't be too hard to fix. +- Some unit tests are overridden. + +Notes by Richard: + +This backend has some behaviour specific to metakit: + +- there's no concept of an explicit "unset" in metakit, so all types + have some "unset" value: + + ========= ===== ====================================================== + Type Value Action when fetching from mk + ========= ===== ====================================================== + Strings '' convert to None + Date 0 (seconds since 1970-01-01.00:00:00) convert to None + Interval '' convert to None + Number 0 ambiguious :( - do nothing (see BACKWARDS_COMPATIBLE) + Boolean 0 ambiguious :( - do nothing (see BACKWARDS_COMPATABILE) + Link 0 convert to None + Multilink [] actually, mk can handle this one ;) + Password '' convert to None + ========= ===== ====================================================== + + The get/set routines handle these values accordingly by converting + to/from None where they can. The Number/Boolean types are not able + to handle an "unset" at all, so they default the "unset" to 0. +- Metakit relies in reference counting to close the database, there is + no explicit close call. This can cause issues if a metakit + database is referenced multiple times, one might not actually be + closing the db. +- probably a bunch of stuff that I'm not aware of yet because I haven't + fully read through the source. One of these days.... ''' - Metakit backend for Roundup, originally by Gordon McMillan. - - Notes by Richard: - - This backend has some behaviour specific to metakit: - - - there's no concept of an explicit "unset" in metakit, so all types - have some "unset" value: - - ========= ===== ==================================================== - Type Value Action when fetching from mk - ========= ===== ==================================================== - Strings '' convert to None - Date 0 (seconds since 1970-01-01.00:00:00) convert to None - Interval '' convert to None - Number 0 ambiguious :( - do nothing (see BACKWARDS_COMPATIBLE) - Boolean 0 ambiguious :( - do nothing (see BACKWARDS_COMPATABILE) - Link 0 convert to None - Multilink [] actually, mk can handle this one ;) - Password '' convert to None - ========= ===== ==================================================== - - The get/set routines handle these values accordingly by converting - to/from None where they can. The Number/Boolean types are not able - to handle an "unset" at all, so they default the "unset" to 0. - - Metakit relies in reference counting to close the database, there is - no explicit close call. This can cause issues if a metakit - database is referenced multiple times, one might not actually be - closing the db. - - - probably a bunch of stuff that I'm not aware of yet because I haven't - fully read through the source. One of these days.... -''' -# Enable this flag to break backwards compatibility (i.e. can't read old databases) -# but comply with more roundup features, like adding NULL support. +__docformat__ = 'restructuredtext' +# Enable this flag to break backwards compatibility (i.e. can't read old +# databases) but comply with more roundup features, like adding NULL support. BACKWARDS_COMPATIBLE = True -# Changes to version 1.55: -# 1 Added an explicit close to the Indexer class. This was handled -# by garbage collection before. -# -# 2 Added an MKBackendError exception that gets thrown on some metakit errors. -# Should there be a general rdbms exception? -# -# 3 Added a sanity check when creating metakit tables in __getview -# There are some test cases that create columns of the same name -# with different metakit types. This can cause crashing issues with -# older version of metakit. We catch these before hand and raise -# an exception. -# -# 4 metakit db's cannot be weakref'd so this was removed -# -# 5 fixed a metakit.append, metakit must append lists, objects or -# dictionaries, it can't handle scalars. -# sv.append(int(entry)) -# became -# sv.append((int(entry),)) -# -# 6 To make it easier to compare to the other backends -# Class.keyname is changed to Class.key -# -# 7 Fixed Class.lookup, sometimes it would claim that a valid -# row was not valid (an _isdel row _property of 0 would -# be reported as 1) This is because metakit's view.find -# operation was returning bad results. This should be -# view.select or view.find on a single property. -# -# 8 calling create with no parameters raises a value error -# I'm not sure if this is appropriate, but it fixes -# a regression test :) -# -# 9 The get method was only converting results for commited -# values. uncommited values were not being converted -# using the metakit conversion table -# -# 10 Added a check to the Class.__init__ to raise a ValueError -# if the database already has a class of the same name. -# -# 11 Boolean and Number types can now have null values. This -# is a backwards incompatible fix in that old databases -# won't work correctly. -# -# The fix is simple. For a boolean column, 0 is now None -# 1 is False (returns 0) -# 2 is True (returns 1) -# For a numeric column, 0 is now None -# values 0 get returned as value-1 -# values < 0 get returned as value -# Set the BACKWARDS_COMPATIBLE flag to False to enable this fix. -# -# 12 Enumerated READ and READWRITE for the getview and getindexedview -# These will probably be removed because they are not used -# -# Changed to 1.56 -# -# 13 worked-around a current metakit bug, so retiring properties now -# works correctly. -# metakit 2.9.2 has a bug when using "find" on ordered views, -# using multiple arguments for find doesn't work. -# -# Known Current Bugs: -# You can't change a class' key properly. -# This shouldn't be too hard to fix. -# - from roundup import hyperdb, date, password, roundupdb, security import metakit from sessions import Sessions, OneTimeKeys @@ -940,18 +875,19 @@ class Class(hyperdb.Class): def find(self, **propspec): """Get the ids of nodes in this class which link to the given nodes. - 'propspec' consists of keyword args propname={nodeid:1,} - 'propname' must be the name of a property in this class, or a - KeyError is raised. That property must be a Link or - Multilink property, or a TypeError is raised. + 'propspec' + consists of keyword args propname={nodeid:1,} + 'propname' + must be the name of a property in this class, or a + KeyError is raised. That property must be a Link or + Multilink property, or a TypeError is raised. Any node in this class whose propname property links to any of the nodeids will be returned. Used by the full text indexing, which knows that "foo" occurs in msg1, msg3 and file7; so we have hits on these - issues: + issues:: db.issue.find(messages={'1':1,'3':1}, files={'7':1}) - """ propspec = propspec.items() for propname, nodeid in propspec: @@ -1249,14 +1185,15 @@ class Class(hyperdb.Class): return int(nodeid) < self.maxid def labelprop(self, default_to_id=0): - ''' Return the property name for a label for the given node. + '''Return the property name for a label for the given node. This method attempts to generate a consistent label for the node. It tries the following in order: - 1. key property - 2. "name" property - 3. "title" property - 4. first property from the sorted property name list + + 1. key property + 2. "name" property + 3. "title" property + 4. first property from the sorted property name list ''' k = self.getkey() if k: diff --git a/roundup/backends/back_mysql.py b/roundup/backends/back_mysql.py index fa3c6d4..8d8ea34 100644 --- a/roundup/backends/back_mysql.py +++ b/roundup/backends/back_mysql.py @@ -5,8 +5,9 @@ # under the same terms as Python, so long as this copyright message and # disclaimer are retained in their original form. # -# Mysql backend for roundup -# + +'''This module defines a backend implementation for MySQL.''' +__docformat__ = 'restructuredtext' from roundup.backends.rdbms_common import * from roundup.backends import rdbms_common @@ -208,18 +209,20 @@ class MysqlClass: # look for "I can't believe it's not a toy RDBMS" below def filter(self, search_matches, filterspec, sort=(None,None), group=(None,None)): - ''' Return a list of the ids of the active nodes in this class that - match the 'filter' spec, sorted by the group spec and then the - sort spec - - "filterspec" is {propname: value(s)} - "sort" and "group" are (dir, prop) where dir is '+', '-' or None - and prop is a prop name or None - "search_matches" is {nodeid: marker} - - The filter must match all properties specificed - but if the - property value to match is a list, any one of the values in the - list may match for that property to match. + '''Return a list of the ids of the active nodes in this class that + match the 'filter' spec, sorted by the group spec and then the + sort spec + + "filterspec" is {propname: value(s)} + + "sort" and "group" are (dir, prop) where dir is '+', '-' or None + and prop is a prop name or None + + "search_matches" is {nodeid: marker} + + The filter must match all properties specificed - but if the + property value to match is a list, any one of the values in the + list may match for that property to match. ''' # just don't bother if the full-text search matched diddly if search_matches == {}: diff --git a/roundup/backends/back_postgresql.py b/roundup/backends/back_postgresql.py index 5a28fa7..13f2e2f 100644 --- a/roundup/backends/back_postgresql.py +++ b/roundup/backends/back_postgresql.py @@ -5,8 +5,9 @@ # under the same terms as Python, so long as this copyright message and # disclaimer are retained in their original form. # -# psycopg backend for roundup -# +'''Postgresql backend via psycopg for Roundup.''' +__docformat__ = 'restructuredtext' + from roundup import hyperdb, date from roundup.backends import rdbms_common diff --git a/roundup/backends/back_sqlite.py b/roundup/backends/back_sqlite.py index 6315fc8..c17235d 100644 --- a/roundup/backends/back_sqlite.py +++ b/roundup/backends/back_sqlite.py @@ -1,7 +1,10 @@ -# $Id: back_sqlite.py,v 1.12 2003-11-12 01:00:58 richard Exp $ -__doc__ = ''' +# $Id: back_sqlite.py,v 1.13 2004-02-11 23:55:09 richard Exp $ +'''Implements a backend for SQLite. + See https://pysqlite.sourceforge.net/ for pysqlite info ''' +__docformat__ = 'restructuredtext' + import os, base64, marshal from roundup import hyperdb diff --git a/roundup/backends/blobfiles.py b/roundup/backends/blobfiles.py index 1a04aae..673bd93 100644 --- a/roundup/backends/blobfiles.py +++ b/roundup/backends/blobfiles.py @@ -15,11 +15,11 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -#$Id: blobfiles.py,v 1.10 2003-12-05 03:28:38 richard Exp $ -''' -This module exports file storage for roundup backends. +#$Id: blobfiles.py,v 1.11 2004-02-11 23:55:09 richard Exp $ +'''This module exports file storage for roundup backends. Files are stored into a directory hierarchy. ''' +__docformat__ = 'restructuredtext' import os diff --git a/roundup/backends/locking.py b/roundup/backends/locking.py index 36833d0..4fe955f 100644 --- a/roundup/backends/locking.py +++ b/roundup/backends/locking.py @@ -19,13 +19,14 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -# $Id: locking.py,v 1.7 2003-07-03 23:43:46 richard Exp $ +# $Id: locking.py,v 1.8 2004-02-11 23:55:09 richard Exp $ '''This module provides a generic interface to acquire and release exclusive access to a file. It should work on Unix and Windows. ''' +__docformat__ = 'restructuredtext' import portalocker diff --git a/roundup/backends/portalocker.py b/roundup/backends/portalocker.py index 9c8389e..538529b 100644 --- a/roundup/backends/portalocker.py +++ b/roundup/backends/portalocker.py @@ -2,11 +2,11 @@ # Requires python 1.5.2 or better. # ID line added by richard for Roundup file tracking -# $Id: portalocker.py,v 1.7 2003-08-26 00:29:20 richard Exp $ +# $Id: portalocker.py,v 1.8 2004-02-11 23:55:09 richard Exp $ -""" Cross-platform (posix/nt) API for flock-style file locking. +"""Cross-platform (posix/nt) API for flock-style file locking. -Synopsis: +Synopsis:: import portalocker file = open("somefile", "r+") @@ -15,18 +15,18 @@ Synopsis: file.write("foo") file.close() -If you know what you're doing, you may choose to +If you know what you're doing, you may choose to:: portalocker.unlock(file) before closing the file, but why? -Methods: +Methods:: lock( file, flags ) unlock( file ) -Constants: +Constants:: LOCK_EX LOCK_SH @@ -36,10 +36,12 @@ I learned the win32 technique for locking files from sample code provided by John Nielsen in the documentation that accompanies the win32 modules. -Author: Jonathan Feinberg -Version: Id: portalocker.py,v 1.3 2001/05/29 18:47:55 Administrator Exp - **un-cvsified by richard so the version doesn't change** +:Author: Jonathan Feinberg +:Version: Id: portalocker.py,v 1.3 2001/05/29 18:47:55 Administrator Exp + **un-cvsified by richard so the version doesn't change** """ +__docformat__ = 'restructuredtext' + import os if os.name == 'nt': diff --git a/roundup/backends/rdbms_common.py b/roundup/backends/rdbms_common.py index aebd259..e7d141c 100644 --- a/roundup/backends/rdbms_common.py +++ b/roundup/backends/rdbms_common.py @@ -1,4 +1,4 @@ -# $Id: rdbms_common.py,v 1.74 2004-01-20 05:55:51 richard Exp $ +# $Id: rdbms_common.py,v 1.75 2004-02-11 23:55:09 richard Exp $ ''' Relational database (SQL) backend common code. Basics: @@ -20,6 +20,7 @@ probably a bit of work to be done if a database is used that actually honors column typing, since the initial databases don't (sqlite stores everything as a string.) ''' +__docformat__ = 'restructuredtext' # standard python modules import sys, os, time, re, errno, weakref, copy @@ -490,10 +491,10 @@ class Database(FileStorage, hyperdb.Database, roundupdb.Database): raise KeyError, 'There is no class called "%s"'%classname def clear(self): - ''' Delete all database contents. + '''Delete all database contents. - Note: I don't commit here, which is different behaviour to the - "nuke from orbit" behaviour in the *dbms. + Note: I don't commit here, which is different behaviour to the + "nuke from orbit" behaviour in the dbs. ''' if __debug__: print >>hyperdb.DEBUG, 'clear', (self,) @@ -1649,8 +1650,11 @@ class Class(hyperdb.Class): WARNING: this method should never be used except in extremely rare situations where there could never be links to the node being deleted + WARNING: use retire() instead + WARNING: the properties of this node will not be available ever again + WARNING: really, use retire() instead Well, I think that's enough warnings. This method exists mostly to @@ -1706,14 +1710,15 @@ class Class(hyperdb.Class): return self.key def labelprop(self, default_to_id=0): - ''' Return the property name for a label for the given node. + '''Return the property name for a label for the given node. This method attempts to generate a consistent label for the node. It tries the following in order: - 1. key property - 2. "name" property - 3. "title" property - 4. first property from the sorted property name list + + 1. key property + 2. "name" property + 3. "title" property + 4. first property from the sorted property name list ''' k = self.getkey() if k: @@ -1897,18 +1902,20 @@ class Class(hyperdb.Class): def filter(self, search_matches, filterspec, sort=(None,None), group=(None,None)): - ''' Return a list of the ids of the active nodes in this class that - match the 'filter' spec, sorted by the group spec and then the - sort spec - - "filterspec" is {propname: value(s)} - "sort" and "group" are (dir, prop) where dir is '+', '-' or None - and prop is a prop name or None - "search_matches" is {nodeid: marker} - - The filter must match all properties specificed - but if the - property value to match is a list, any one of the values in the - list may match for that property to match. + '''Return a list of the ids of the active nodes in this class that + match the 'filter' spec, sorted by the group spec and then the + sort spec + + "filterspec" is {propname: value(s)} + + "sort" and "group" are (dir, prop) where dir is '+', '-' or None + and prop is a prop name or None + + "search_matches" is {nodeid: marker} + + The filter must match all properties specificed - but if the + property value to match is a list, any one of the values in the + list may match for that property to match. ''' # just don't bother if the full-text search matched diddly if search_matches == {}: diff --git a/roundup/backends/sessions.py b/roundup/backends/sessions.py index 99b4655..addeb90 100644 --- a/roundup/backends/sessions.py +++ b/roundup/backends/sessions.py @@ -1,12 +1,11 @@ -#$Id: sessions.py,v 1.6 2003-09-05 21:05:18 jlgijsbers Exp $ -""" -This module defines a very basic store that's used by the CGI interface +#$Id: sessions.py,v 1.7 2004-02-11 23:55:09 richard Exp $ +"""This module defines a very basic store that's used by the CGI interface to store session and one-time-key information. Yes, it's called "sessions" - because originally it only defined a session class. It's now also used for One Time Key handling too. - """ +__docformat__ = 'restructuredtext' import anydbm, whichdb, os, marshal diff --git a/roundup/cgi/PageTemplates/Expressions.py b/roundup/cgi/PageTemplates/Expressions.py index 8a391b6..ba315d3 100644 --- a/roundup/cgi/PageTemplates/Expressions.py +++ b/roundup/cgi/PageTemplates/Expressions.py @@ -24,8 +24,9 @@ Modified for Roundup 0.5 release: - Made traceback info more informative """ +__docformat__ = 'restructuredtext' -__version__='$Revision: 1.8 $'[11:-2] +__version__='$Revision: 1.9 $'[11:-2] import re, sys from TALES import Engine, CompilerError, _valid_name, NAME_RE, \ diff --git a/roundup/cgi/PageTemplates/PageTemplate.py b/roundup/cgi/PageTemplates/PageTemplate.py index 91d66d7..ddb097c 100755 --- a/roundup/cgi/PageTemplates/PageTemplate.py +++ b/roundup/cgi/PageTemplates/PageTemplate.py @@ -20,8 +20,9 @@ Modified for Roundup 0.5 release: - changed imports to import from roundup.cgi """ +__docformat__ = 'restructuredtext' -__version__='$Revision: 1.3 $'[11:-2] +__version__='$Revision: 1.4 $'[11:-2] import sys diff --git a/roundup/cgi/PageTemplates/PathIterator.py b/roundup/cgi/PageTemplates/PathIterator.py index ded1d29..4e6bd76 100644 --- a/roundup/cgi/PageTemplates/PathIterator.py +++ b/roundup/cgi/PageTemplates/PathIterator.py @@ -16,8 +16,9 @@ A TALES Iterator with the ability to use first() and last() on subpaths of elements. """ +__docformat__ = 'restructuredtext' -__version__='$Revision: 1.1 $'[11:-2] +__version__='$Revision: 1.2 $'[11:-2] import TALES from Expressions import restrictedTraverse, Undefs, getSecurityManager diff --git a/roundup/cgi/PageTemplates/PythonExpr.py b/roundup/cgi/PageTemplates/PythonExpr.py index 0bfe400..44a0491 100644 --- a/roundup/cgi/PageTemplates/PythonExpr.py +++ b/roundup/cgi/PageTemplates/PythonExpr.py @@ -18,8 +18,9 @@ Modified for Roundup 0.5 release: - more informative traceback info """ +__docformat__ = 'restructuredtext' -__version__='$Revision: 1.4 $'[11:-2] +__version__='$Revision: 1.5 $'[11:-2] from TALES import CompilerError from string import strip, split, join, replace, lstrip diff --git a/roundup/cgi/PageTemplates/TALES.py b/roundup/cgi/PageTemplates/TALES.py index ef13436..ac8aec9 100644 --- a/roundup/cgi/PageTemplates/TALES.py +++ b/roundup/cgi/PageTemplates/TALES.py @@ -18,8 +18,9 @@ Modified for Roundup 0.5 release: - changed imports to import from roundup.cgi """ +__docformat__ = 'restructuredtext' -__version__='$Revision: 1.5 $'[11:-2] +__version__='$Revision: 1.6 $'[11:-2] import re, sys from roundup.cgi import ZTUtils diff --git a/roundup/cgi/PageTemplates/__init__.py b/roundup/cgi/PageTemplates/__init__.py index 3d58de0..c0677c9 100644 --- a/roundup/cgi/PageTemplates/__init__.py +++ b/roundup/cgi/PageTemplates/__init__.py @@ -15,7 +15,8 @@ __doc__='''Package wrapper for Page Templates This wrapper allows the Page Template modules to be segregated in a separate package. -$Id: __init__.py,v 1.1 2002-09-05 00:37:09 richard Exp $''' +$Id: __init__.py,v 1.2 2004-02-11 23:55:09 richard Exp $''' +__docformat__ = 'restructuredtext' __version__='$$'[11:-2] diff --git a/roundup/cgi/TAL/HTMLParser.py b/roundup/cgi/TAL/HTMLParser.py index 5ab076b..e8ae444 100644 --- a/roundup/cgi/TAL/HTMLParser.py +++ b/roundup/cgi/TAL/HTMLParser.py @@ -1,4 +1,5 @@ """A parser for HTML and XHTML.""" +__docformat__ = 'restructuredtext' # This file is based on sgmllib.py, but the API is slightly different. diff --git a/roundup/cgi/TAL/HTMLTALParser.py b/roundup/cgi/TAL/HTMLTALParser.py index 8d7f0db..f1582f2 100644 --- a/roundup/cgi/TAL/HTMLTALParser.py +++ b/roundup/cgi/TAL/HTMLTALParser.py @@ -11,9 +11,9 @@ # FOR A PARTICULAR PURPOSE # ############################################################################## +"""Parse HTML and compile to TALInterpreter intermediate code. """ -Parse HTML and compile to TALInterpreter intermediate code. -""" +__docformat__ = 'restructuredtext' import sys import string diff --git a/roundup/cgi/TAL/TALDefs.py b/roundup/cgi/TAL/TALDefs.py index dbc0443..f49622f 100644 --- a/roundup/cgi/TAL/TALDefs.py +++ b/roundup/cgi/TAL/TALDefs.py @@ -11,9 +11,9 @@ # FOR A PARTICULAR PURPOSE # ############################################################################## +"""Common definitions used by TAL and METAL compilation an transformation. """ -Common definitions used by TAL and METAL compilation an transformation. -""" +__docformat__ = 'restructuredtext' from types import ListType, TupleType diff --git a/roundup/cgi/TAL/TALGenerator.py b/roundup/cgi/TAL/TALGenerator.py index 5317255..8a4f55b 100644 --- a/roundup/cgi/TAL/TALGenerator.py +++ b/roundup/cgi/TAL/TALGenerator.py @@ -11,9 +11,9 @@ # FOR A PARTICULAR PURPOSE # ############################################################################## +"""Code generator for TALInterpreter intermediate code. """ -Code generator for TALInterpreter intermediate code. -""" +__docformat__ = 'restructuredtext' import string import re diff --git a/roundup/cgi/TAL/TALInterpreter.py b/roundup/cgi/TAL/TALInterpreter.py index 341b861..5f9c67f 100644 --- a/roundup/cgi/TAL/TALInterpreter.py +++ b/roundup/cgi/TAL/TALInterpreter.py @@ -11,9 +11,9 @@ # FOR A PARTICULAR PURPOSE # ############################################################################## +"""Interpreter for a pre-compiled TAL program. """ -Interpreter for a pre-compiled TAL program. -""" +__docformat__ = 'restructuredtext' import sys import getopt diff --git a/roundup/cgi/TAL/TALParser.py b/roundup/cgi/TAL/TALParser.py index f75414e..c0c0b9f 100644 --- a/roundup/cgi/TAL/TALParser.py +++ b/roundup/cgi/TAL/TALParser.py @@ -11,9 +11,9 @@ # FOR A PARTICULAR PURPOSE # ############################################################################## +"""Parse XML and compile to TALInterpreter intermediate code. """ -Parse XML and compile to TALInterpreter intermediate code. -""" +__docformat__ = 'restructuredtext' import string from XMLParser import XMLParser diff --git a/roundup/cgi/TAL/XMLParser.py b/roundup/cgi/TAL/XMLParser.py index e16869d..00ffdc8 100644 --- a/roundup/cgi/TAL/XMLParser.py +++ b/roundup/cgi/TAL/XMLParser.py @@ -11,14 +11,14 @@ # FOR A PARTICULAR PURPOSE # ############################################################################## -""" -Generic expat-based XML parser base class. +"""Generic expat-based XML parser base class. Modified for Roundup 0.5 release: - removed dependency on zLOG """ +__docformat__ = 'restructuredtext' class XMLParser: diff --git a/roundup/cgi/TAL/__init__.py b/roundup/cgi/TAL/__init__.py index 080ed5d..4f2a609 100644 --- a/roundup/cgi/TAL/__init__.py +++ b/roundup/cgi/TAL/__init__.py @@ -11,4 +11,5 @@ # FOR A PARTICULAR PURPOSE # ############################################################################## -""" Template Attribute Language package """ +"""Template Attribute Language package """ +__docformat__ = 'restructuredtext' diff --git a/roundup/cgi/TAL/markupbase.py b/roundup/cgi/TAL/markupbase.py index eab134c..2bcf6a7 100644 --- a/roundup/cgi/TAL/markupbase.py +++ b/roundup/cgi/TAL/markupbase.py @@ -1,4 +1,6 @@ -"""Shared support for scanning document type declarations in HTML and XHTML.""" +"""Shared support for scanning document type declarations in HTML and XHTML. +""" +__docformat__ = 'restructuredtext' import re import string diff --git a/roundup/cgi/ZTUtils/Batch.py b/roundup/cgi/ZTUtils/Batch.py index 3dfa9b1..66dde68 100644 --- a/roundup/cgi/ZTUtils/Batch.py +++ b/roundup/cgi/ZTUtils/Batch.py @@ -12,8 +12,9 @@ ############################################################################## __doc__='''Batch class, for iterating over a sequence in batches -$Id: Batch.py,v 1.2 2002-09-11 23:54:26 richard Exp $''' -__version__='$Revision: 1.2 $'[11:-2] +$Id: Batch.py,v 1.3 2004-02-11 23:55:09 richard Exp $''' +__docformat__ = 'restructuredtext' +__version__='$Revision: 1.3 $'[11:-2] class LazyPrevBatch: def __of__(self, parent): diff --git a/roundup/cgi/ZTUtils/Iterator.py b/roundup/cgi/ZTUtils/Iterator.py index b6c7a6f..96a64ba 100644 --- a/roundup/cgi/ZTUtils/Iterator.py +++ b/roundup/cgi/ZTUtils/Iterator.py @@ -18,8 +18,9 @@ The Iterator() function accepts either a sequence or a Python iterator. The next() method fetches the next item, and returns true if it succeeds. -$Id: Iterator.py,v 1.2 2002-09-26 21:54:17 richard Exp $''' -__version__='$Revision: 1.2 $'[11:-2] +$Id: Iterator.py,v 1.3 2004-02-11 23:55:09 richard Exp $''' +__docformat__ = 'restructuredtext' +__version__='$Revision: 1.3 $'[11:-2] import string diff --git a/roundup/cgi/ZTUtils/__init__.py b/roundup/cgi/ZTUtils/__init__.py index 6ee1ca4..6473733 100644 --- a/roundup/cgi/ZTUtils/__init__.py +++ b/roundup/cgi/ZTUtils/__init__.py @@ -16,8 +16,9 @@ Modified for Roundup 0.5 release: - removed Zope imports -$Id: __init__.py,v 1.2 2002-09-07 22:42:47 richard Exp $''' -__version__='$Revision: 1.2 $'[11:-2] +$Id: __init__.py,v 1.3 2004-02-11 23:55:09 richard Exp $''' +__docformat__ = 'restructuredtext' +__version__='$Revision: 1.3 $'[11:-2] from Batch import Batch from Iterator import Iterator diff --git a/roundup/cgi/__init__.py b/roundup/cgi/__init__.py index bfcbcfc..87081fe 100644 --- a/roundup/cgi/__init__.py +++ b/roundup/cgi/__init__.py @@ -1 +1,2 @@ -' CGI interface modules ' +''' CGI interface modules ''' +__docformat__ = 'restructuredtext' diff --git a/roundup/cgi/cgitb.py b/roundup/cgi/cgitb.py index 7435eea..a78188a 100644 --- a/roundup/cgi/cgitb.py +++ b/roundup/cgi/cgitb.py @@ -1,11 +1,11 @@ # # This module was written by Ka-Ping Yee, . # -# $Id: cgitb.py,v 1.9 2003-12-05 03:36:34 richard Exp $ +# $Id: cgitb.py,v 1.10 2004-02-11 23:55:09 richard Exp $ -__doc__ = """ -Extended CGI traceback handler by Ka-Ping Yee, . +"""Extended CGI traceback handler by Ka-Ping Yee, . """ +__docformat__ = 'restructuredtext' import sys, os, types, string, keyword, linecache, tokenize, inspect, cgi import pydoc, traceback diff --git a/roundup/cgi/client.py b/roundup/cgi/client.py index ace158e..f02e62f 100644 --- a/roundup/cgi/client.py +++ b/roundup/cgi/client.py @@ -1,8 +1,8 @@ -# $Id: client.py,v 1.155 2004-02-11 21:34:31 jlgijsbers Exp $ +# $Id: client.py,v 1.156 2004-02-11 23:55:09 richard Exp $ -__doc__ = """ -WWW request handler (also used in the stand-alone server). +"""WWW request handler (also used in the stand-alone server). """ +__docformat__ = 'restructuredtext' import os, os.path, cgi, StringIO, urlparse, re, traceback, mimetypes, urllib import binascii, Cookie, time, random, stat, rfc822 @@ -16,10 +16,10 @@ from roundup.cgi.form_parser import FormParser from roundup.mailer import Mailer, MessageSendError def initialiseSecurity(security): - ''' Create some Permissions and Roles on the security object + '''Create some Permissions and Roles on the security object - This function is directly invoked by security.Security.__init__() - as a part of the Security object instantiation. + This function is directly invoked by security.Security.__init__() + as a part of the Security object instantiation. ''' security.addPermission(name="Web Registration", description="User may register through the web") @@ -46,28 +46,30 @@ def clean_message_callback(match, ok={'a':1,'i':1,'b':1,'br':1}): return '<%s>'%match.group(2) class Client: - ''' Instantiate to handle one CGI request. + '''Instantiate to handle one CGI request. See inner_main for request processing. Client attributes at instantiation: - "path" is the PATH_INFO inside the instance (with no leading '/') - "base" is the base URL for the instance - "form" is the cgi form, an instance of FieldStorage from the standard - cgi module - "additional_headers" is a dictionary of additional HTTP headers that - should be sent to the client - "response_code" is the HTTP response code to send to the client + + - "path" is the PATH_INFO inside the instance (with no leading '/') + - "base" is the base URL for the instance + - "form" is the cgi form, an instance of FieldStorage from the standard + cgi module + - "additional_headers" is a dictionary of additional HTTP headers that + should be sent to the client + - "response_code" is the HTTP response code to send to the client During the processing of a request, the following attributes are used: - "error_message" holds a list of error messages - "ok_message" holds a list of OK messages - "session" is the current user session id - "user" is the current user's name - "userid" is the current user's id - "template" is the current :template context - "classname" is the current class context name - "nodeid" is the current context item id + + - "error_message" holds a list of error messages + - "ok_message" holds a list of OK messages + - "session" is the current user session id + - "user" is the current user's name + - "userid" is the current user's id + - "template" is the current :template context + - "classname" is the current class context name + - "nodeid" is the current context item id User Identification: If the user has no login cookie, then they are anonymous and are logged @@ -77,7 +79,6 @@ class Client: Once a user logs in, they are assigned a session. The Client instance keeps the nodeid of the session as the "session" attribute. - Special form variables: Note that in various places throughout this code, special form variables of the form : are used. The colon (":") part may @@ -146,32 +147,34 @@ class Client: self.db.close() def inner_main(self): - ''' Process a request. - - The most common requests are handled like so: - 1. figure out who we are, defaulting to the "anonymous" user - see determine_user - 2. figure out what the request is for - the context - see determine_context - 3. handle any requested action (item edit, search, ...) - see handle_action - 4. render a template, resulting in HTML output - - In some situations, exceptions occur: - - HTTP Redirect (generally raised by an action) - - SendFile (generally raised by determine_context) - serve up a FileClass "content" property - - SendStaticFile (generally raised by determine_context) - serve up a file from the tracker "html" directory - - Unauthorised (generally raised by an action) - the action is cancelled, the request is rendered and an error - message is displayed indicating that permission was not - granted for the action to take place - - templating.Unauthorised (templating action not permitted) - raised by an attempted rendering of a template when the user - doesn't have permission - - NotFound (raised wherever it needs to be) - percolates up to the CGI interface that called the client + '''Process a request. + + The most common requests are handled like so: + + 1. figure out who we are, defaulting to the "anonymous" user + see determine_user + 2. figure out what the request is for - the context + see determine_context + 3. handle any requested action (item edit, search, ...) + see handle_action + 4. render a template, resulting in HTML output + + In some situations, exceptions occur: + + - HTTP Redirect (generally raised by an action) + - SendFile (generally raised by determine_context) + serve up a FileClass "content" property + - SendStaticFile (generally raised by determine_context) + serve up a file from the tracker "html" directory + - Unauthorised (generally raised by an action) + the action is cancelled, the request is rendered and an error + message is displayed indicating that permission was not + granted for the action to take place + - templating.Unauthorised (templating action not permitted) + raised by an attempted rendering of a template when the user + doesn't have permission + - NotFound (raised wherever it needs to be) + percolates up to the CGI interface that called the client ''' self.ok_message = [] self.error_message = [] @@ -262,22 +265,25 @@ class Client: sessions.set('last_clean', last_use=time.time()) def determine_user(self): - '''Determine who the user is. + ''' Determine who the user is ''' - # open the database as admin + # determine the uid to use self.opendb('admin') - # clean age sessions - self.clean_sessions() - # make sure we have the session Class + self.clean_sessions() sessions = self.db.sessions - # look up the user session cookie - cookie = Cookie.SimpleCookie(self.env.get('HTTP_COOKIE', '')) - user = 'anonymous' + # first up, try the REMOTE_USER var (from HTTP Basic Auth handled + # by a front-end HTTP server) + try: + user = os.getenv('REMOTE_USER') + except KeyError: + pass - # bump the "revision" of the cookie since the format changed + # look up the user session cookie (may override the REMOTE_USER) + cookie = Cookie.Cookie(self.env.get('HTTP_COOKIE', '')) + user = 'anonymous' if (cookie.has_key(self.cookie_name) and cookie[self.cookie_name].value != 'deleted'): @@ -290,7 +296,8 @@ class Client: sessions.commit() user = sessions.get(self.session, 'user') except KeyError: - user = 'anonymous' + # not valid, ignore id + pass # sanity check on the user still being valid, getting the userid # at the same time @@ -309,40 +316,43 @@ class Client: self.opendb(self.user) def determine_context(self, dre=re.compile(r'([^\d]+)(\d+)')): - """ Determine the context of this page from the URL: - - The URL path after the instance identifier is examined. The path - is generally only one entry long. - - - if there is no path, then we are in the "home" context. - * if the path is "_file", then the additional path entry - specifies the filename of a static file we're to serve up - from the instance "html" directory. Raises a SendStaticFile - exception. - - if there is something in the path (eg "issue"), it identifies - the tracker class we're to display. - - if the path is an item designator (eg "issue123"), then we're - to display a specific item. - * if the path starts with an item designator and is longer than - one entry, then we're assumed to be handling an item of a - FileClass, and the extra path information gives the filename - that the client is going to label the download with (ie - "file123/image.png" is nicer to download than "file123"). This - raises a SendFile exception. - - Both of the "*" types of contexts stop before we bother to - determine the template we're going to use. That's because they - don't actually use templates. - - The template used is specified by the :template CGI variable, - which defaults to: - - only classname suplied: "index" - full item designator supplied: "item" - - We set: + """Determine the context of this page from the URL: + + The URL path after the instance identifier is examined. The path + is generally only one entry long. + + - if there is no path, then we are in the "home" context. + - if the path is "_file", then the additional path entry + specifies the filename of a static file we're to serve up + from the instance "html" directory. Raises a SendStaticFile + exception.(*) + - if there is something in the path (eg "issue"), it identifies + the tracker class we're to display. + - if the path is an item designator (eg "issue123"), then we're + to display a specific item. + - if the path starts with an item designator and is longer than + one entry, then we're assumed to be handling an item of a + FileClass, and the extra path information gives the filename + that the client is going to label the download with (ie + "file123/image.png" is nicer to download than "file123"). This + raises a SendFile exception.(*) + + Both of the "*" types of contexts stop before we bother to + determine the template we're going to use. That's because they + don't actually use templates. + + The template used is specified by the :template CGI variable, + which defaults to: + + - only classname suplied: "index" + - full item designator supplied: "item" + + We set: + self.classname - the class to display, can be None + self.template - the template to render the current context with + self.nodeid - the nodeid of the class we're displaying """ # default the optional variables diff --git a/roundup/cgi/templating.py b/roundup/cgi/templating.py index 1305cd9..aab6a95 100644 --- a/roundup/cgi/templating.py +++ b/roundup/cgi/templating.py @@ -1,3 +1,7 @@ +"""Implements the API used in the HTML templating for the web interface. +""" +__docformat__ = 'restructuredtext' + from __future__ import nested_scopes import sys, cgi, urllib, os, re, os.path, time, errno, mimetypes @@ -143,35 +147,37 @@ class Templates: raise KeyError, message class RoundupPageTemplate(PageTemplate.PageTemplate): - ''' A Roundup-specific PageTemplate. - - Interrogate the client to set up the various template variables to - be available: - - *context* - this is one of three things: - 1. None - we're viewing a "home" page - 2. The current class of item being displayed. This is an HTMLClass - instance. - 3. The current item from the database, if we're viewing a specific - item, as an HTMLItem instance. - *request* - Includes information about the current request, including: - - the url - - the current index information (``filterspec``, ``filter`` args, - ``properties``, etc) parsed out of the form. - - methods for easy filterspec link generation - - *user*, the current user node as an HTMLItem instance - - *form*, the current CGI form information as a FieldStorage - *config* - The current tracker config. - *db* - The current database, used to access arbitrary database items. - *utils* - This is a special class that has its base in the TemplatingUtils - class in this file. If the tracker interfaces module defines a - TemplatingUtils class then it is mixed in, overriding the methods - in the base class. + '''A Roundup-specific PageTemplate. + + Interrogate the client to set up the various template variables to + be available: + + *context* + this is one of three things: + + 1. None - we're viewing a "home" page + 2. The current class of item being displayed. This is an HTMLClass + instance. + 3. The current item from the database, if we're viewing a specific + item, as an HTMLItem instance. + *request* + Includes information about the current request, including: + + - the url + - the current index information (``filterspec``, ``filter`` args, + ``properties``, etc) parsed out of the form. + - methods for easy filterspec link generation + - *user*, the current user node as an HTMLItem instance + - *form*, the current CGI form information as a FieldStorage + *config* + The current tracker config. + *db* + The current database, used to access arbitrary database items. + *utils* + This is a special class that has its base in the TemplatingUtils + class in this file. If the tracker interfaces module defines a + TemplatingUtils class then it is mixed in, overriding the methods + in the base class. ''' def getContext(self, client, classname, request): # construct the TemplatingUtils class @@ -962,11 +968,11 @@ class StringHTMLProperty(HTMLProperty): return self.plain(hyperlink=1) def plain(self, escape=0, hyperlink=0): - ''' Render a "plain" representation of the property + '''Render a "plain" representation of the property - "escape" turns on/off HTML quoting - "hyperlink" turns on/off in-text hyperlinking of URLs, email - addresses and designators + - "escape" turns on/off HTML quoting + - "hyperlink" turns on/off in-text hyperlinking of URLs, email + addresses and designators ''' self.view_check() @@ -1441,7 +1447,7 @@ class MultilinkHTMLProperty(HTMLProperty): def __contains__(self, value): ''' Support the "in" operator. We have to make sure the passed-in - value is a string first, not a *HTMLProperty. + value is a string first, not a HTMLProperty. ''' return str(value) in self._value @@ -1601,25 +1607,25 @@ class ShowDict: return self.columns.has_key(name) class HTMLRequest(HTMLInputMixin): - ''' The *request*, holding the CGI form and environment. - - "form" the CGI form as a cgi.FieldStorage - "env" the CGI environment variables - "base" the base URL for this instance - "user" a HTMLUser instance for this user - "classname" the current classname (possibly None) - "template" the current template (suffix, also possibly None) - - Index args: - "columns" dictionary of the columns to display in an index page - "show" a convenience access to columns - request/show/colname will - be true if the columns should be displayed, false otherwise - "sort" index sort column (direction, column name) - "group" index grouping property (direction, column name) - "filter" properties to filter the index on - "filterspec" values to filter the index on - "search_text" text to perform a full-text search on for an index - + '''The *request*, holding the CGI form and environment. + + - "form" the CGI form as a cgi.FieldStorage + - "env" the CGI environment variables + - "base" the base URL for this instance + - "user" a HTMLUser instance for this user + - "classname" the current classname (possibly None) + - "template" the current template (suffix, also possibly None) + + Index args: + + - "columns" dictionary of the columns to display in an index page + - "show" a convenience access to columns - request/show/colname will + be true if the columns should be displayed, false otherwise + - "sort" index sort column (direction, column name) + - "group" index grouping property (direction, column name) + - "filter" properties to filter the index on + - "filterspec" values to filter the index on + - "search_text" text to perform a full-text search on for an index ''' def __init__(self, client): # _client is needed by HTMLInputMixin diff --git a/roundup/date.py b/roundup/date.py index 4915176..8f60a72 100644 --- a/roundup/date.py +++ b/roundup/date.py @@ -15,11 +15,11 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: date.py,v 1.59 2003-12-05 03:28:38 richard Exp $ +# $Id: date.py,v 1.60 2004-02-11 23:55:08 richard Exp $ -__doc__ = """ -Date, time and time interval handling. +"""Date, time and time interval handling. """ +__docformat__ = 'restructuredtext' import time, re, calendar, types from i18n import _ @@ -51,6 +51,7 @@ class Date: care of these conversions. In the following examples, suppose that yyyy is the current year, mm is the current month, and dd is the current day of the month; and suppose that the user is on Eastern Standard Time. + Examples:: "2000-04-17" means "01-25" means @@ -69,9 +70,8 @@ class Date: separately. For example, when evaluating "2000-06-25 + 1m 10d", we first add one month to get 2000-07-25, then add 10 days to get 2000-08-04 (rather than trying to decide whether 1m 10d means 38 or 40 - or 41 days). + or 41 days). Example usage:: - Example usage: >>> Date(".") >>> _.local(-5) @@ -95,9 +95,11 @@ class Date: def __init__(self, spec='.', offset=0, add_granularity=0): """Construct a date given a specification and a time zone offset. - 'spec' is a full date or a partial form, with an optional - added or subtracted interval. Or a date 9-tuple. - 'offset' is the local time zone offset from GMT in hours. + 'spec' + is a full date or a partial form, with an optional added or + subtracted interval. Or a date 9-tuple. + 'offset' + is the local time zone offset from GMT in hours. """ if type(spec) == type(''): self.set(spec, offset=offset, add_granularity=add_granularity) @@ -660,20 +662,24 @@ def fixTimeOverflow(time): return (sign, y, m, d, H, M, S) class Range: - """ - Represents range between two values + """Represents range between two values Ranges can be created using one of theese two alternative syntaxes: - 1. Native english syntax: + 1. Native english syntax:: + [[From] ][ To ] - Keywords "From" and "To" are case insensitive. Keyword "From" is optional. - 2. "Geek" syntax: - [][; ] + Keywords "From" and "To" are case insensitive. Keyword "From" is + optional. + + 2. "Geek" syntax:: + + [][; ] Either first or second can be omitted in both syntaxes. - Examples (consider local time is Sat Mar 8 22:07:48 EET 2003): + Examples (consider local time is Sat Mar 8 22:07:48 EET 2003):: + >>> Range("from 2-12 to 4-2") diff --git a/roundup/hyperdb.py b/roundup/hyperdb.py index c8ca0a5..4bac87f 100644 --- a/roundup/hyperdb.py +++ b/roundup/hyperdb.py @@ -15,11 +15,11 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: hyperdb.py,v 1.95 2003-11-16 22:56:46 jlgijsbers Exp $ +# $Id: hyperdb.py,v 1.96 2004-02-11 23:55:08 richard Exp $ +"""Hyperdatabase implementation, especially field types. """ -Hyperdatabase implementation, especially field types. -""" +__docformat__ = 'restructuredtext' # standard python modules import sys, os, time, re @@ -250,19 +250,19 @@ All methods except __repr__ must be implemented by a concrete backend Database. ''' return node - def getnode(self, classname, nodeid, db=None, cache=1): + def getnode(self, classname, nodeid): '''Get a node from the database. 'cache' exists for backwards compatibility, and is not used. ''' raise NotImplementedError - def hasnode(self, classname, nodeid, db=None): + def hasnode(self, classname, nodeid): '''Determine if the database has a given node. ''' raise NotImplementedError - def countnodes(self, classname, db=None): + def countnodes(self, classname): '''Count the number of nodes that exist for a particular Class. ''' raise NotImplementedError @@ -374,7 +374,7 @@ class Class: raise NotImplementedError # not in spec - def getnode(self, nodeid, cache=1): + def getnode(self, nodeid): ''' Return a convenience wrapper for the node. 'nodeid' must be the id of an existing node of this class or an @@ -384,7 +384,7 @@ class Class: ''' return Node(self, nodeid) - def getnodeids(self, db=None): + def getnodeids(self, retired=None): '''Retrieve all the ids of the nodes for a particular Class. ''' raise NotImplementedError @@ -438,8 +438,11 @@ class Class: WARNING: this method should never be used except in extremely rare situations where there could never be links to the node being deleted + WARNING: use retire() instead + WARNING: the properties of this node will not be available ever again + WARNING: really, use retire() instead Well, I think that's enough warnings. This method exists mostly to @@ -485,15 +488,16 @@ class Class: raise NotImplementedError def labelprop(self, default_to_id=0): - ''' Return the property name for a label for the given node. + """Return the property name for a label for the given node. This method attempts to generate a consistent label for the node. It tries the following in order: - 1. key property - 2. "name" property - 3. "title" property - 4. first property from the sorted property name list - ''' + + 1. key property + 2. "name" property + 3. "title" property + 4. first property from the sorted property name list + """ raise NotImplementedError def lookup(self, keyvalue): @@ -525,19 +529,21 @@ class Class: def filter(self, search_matches, filterspec, sort=(None,None), group=(None,None)): - ''' Return a list of the ids of the active nodes in this class that - match the 'filter' spec, sorted by the group spec and then the - sort spec. - - "filterspec" is {propname: value(s)} - "sort" and "group" are (dir, prop) where dir is '+', '-' or None - and prop is a prop name or None - "search_matches" is {nodeid: marker} - - The filter must match all properties specificed - but if the - property value to match is a list, any one of the values in the - list may match for that property to match. - ''' + """Return a list of the ids of the active nodes in this class that + match the 'filter' spec, sorted by the group spec and then the + sort spec. + + "filterspec" is {propname: value(s)} + + "sort" and "group" are (dir, prop) where dir is '+', '-' or None + and prop is a prop name or None + + "search_matches" is {nodeid: marker} + + The filter must match all properties specificed - but if the + property value to match is a list, any one of the values in the + list may match for that property to match. + """ raise NotImplementedError def count(self): diff --git a/roundup/i18n.py b/roundup/i18n.py index 8203d95..378d593 100644 --- a/roundup/i18n.py +++ b/roundup/i18n.py @@ -15,12 +15,12 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: i18n.py,v 1.3 2002-09-10 00:18:20 richard Exp $ +# $Id: i18n.py,v 1.4 2004-02-11 23:55:08 richard Exp $ -__doc__ = """ +""" RoundUp Internationalization (I18N) -To use this module, the following code should be used: +To use this module, the following code should be used:: from roundup.i18n import _ ... @@ -28,14 +28,14 @@ To use this module, the following code should be used: Note that to enable re-ordering of inserted texts in formatting strings (which can easily happen if a sentence has to be re-ordered due to -grammatical changes), translatable formats should use named format specs: +grammatical changes), translatable formats should use named format specs:: ... _('Index of %(classname)s') % {'classname': cn} ... Also, this eases the job of translators since they have some context what the dynamic portion of a message really means. - """ +__docformat__ = 'restructuredtext' # first, we try to import gettext; this probably never fails, but we make # sure we survive this anyway diff --git a/roundup/indexer.py b/roundup/indexer.py index 9bee8bd..4cd5d24 100644 --- a/roundup/indexer.py +++ b/roundup/indexer.py @@ -14,24 +14,27 @@ # that promote freedom, but obviously am giving up any rights # to compel such. # -#$Id: indexer.py,v 1.17 2004-01-20 03:58:38 richard Exp $ -''' -This module provides an indexer class, RoundupIndexer, that stores text +#$Id: indexer.py,v 1.18 2004-02-11 23:55:08 richard Exp $ +'''This module provides an indexer class, RoundupIndexer, that stores text indices in a roundup instance. This class makes searching the content of messages, string properties and text files possible. ''' +__docformat__ = 'restructuredtext' + import os, shutil, re, mimetypes, marshal, zlib, errno from hyperdb import Link, Multilink class Indexer: - ''' Indexes information from roundup's hyperdb to allow efficient - searching. + '''Indexes information from roundup's hyperdb to allow efficient + searching. + + Three structures are created by the indexer:: - Three structures are created by the indexer: files {identifier: (fileid, wordcount)} words {word: {fileid: count}} fileids {fileid: identifier} - where identifier is (classname, nodeid, propertyname) + + where identifier is (classname, nodeid, propertyname) ''' def __init__(self, db_path): self.indexdb_path = os.path.join(db_path, 'indexes') @@ -69,8 +72,8 @@ class Indexer: return self.reindex def add_text(self, identifier, text, mime_type='text/plain'): - ''' Add some text associated with the (classname, nodeid, property) - identifier. + '''Add some text associated with the (classname, nodeid, property) + identifier. ''' # make sure the index is loaded self.load_index() @@ -114,7 +117,7 @@ class Indexer: self.changed = 1 def splitter(self, text, ftype): - ''' Split the contents of a text string into a list of 'words' + '''Split the contents of a text string into a list of 'words' ''' if ftype == 'text/plain': words = self.text_splitter(text) @@ -136,10 +139,10 @@ class Indexer: def search(self, search_terms, klass, ignore={}, dre=re.compile(r'([^\d]+)(\d+)')): - ''' Display search results looking for [search, terms] associated - with the hyperdb Class "klass". Ignore hits on {class: property}. + '''Display search results looking for [search, terms] associated + with the hyperdb Class "klass". Ignore hits on {class: property}. - "dre" is a helper, not an argument. + "dre" is a helper, not an argument. ''' # do the index lookup hits = self.find(search_terms) @@ -201,7 +204,7 @@ class Indexer: # we override this to ignore not 2 < word < 25 and also to fix a bug - # the (fail) case. def find(self, wordlist): - ''' Locate files that match ALL the words in wordlist + '''Locate files that match ALL the words in wordlist ''' if not hasattr(self, 'words'): self.load_index() @@ -315,7 +318,7 @@ class Indexer: self.changed = 0 def purge_entry(self, identifier): - ''' Remove a file from file index and word index + '''Remove a file from file index and word index ''' self.load_index() diff --git a/roundup/init.py b/roundup/init.py index 25668c5..b334c08 100644 --- a/roundup/init.py +++ b/roundup/init.py @@ -15,11 +15,11 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: init.py,v 1.28 2003-11-13 04:12:10 richard Exp $ +# $Id: init.py,v 1.29 2004-02-11 23:55:08 richard Exp $ -__doc__ = """ -Init (create) a roundup instance. +"""Init (create) a roundup instance. """ +__docformat__ = 'restructuredtext' import os, sys, errno, rfc822 @@ -57,31 +57,32 @@ def copytree(src, dst, symlinks=0): def install(instance_home, template): '''Install an instance using the named template and backend. - instance_home - the directory to place the instance data in - template - the directory holding the template to use in creating - the instance data + 'instance_home' + the directory to place the instance data in + 'template' + the directory holding the template to use in creating the instance data The instance_home directory will be created using the files found in the named template (roundup.templates.). A standard instance_home contains: - . config.py - - simple configuration of things like the email address for the - mail gateway, the mail domain, the mail host, ... - . dbinit.py and select_db.py - - defines the schema for the hyperdatabase and indicates which - backend to use. - . interfaces.py - - defines the CGI Client and mail gateway MailGW classes that are - used by roundup.cgi, roundup-server and roundup-mailgw. - . __init__.py - - ties together all the instance information into one interface - . db/ - - the actual database that stores the instance's data - . html/ - - the html templates that are used by the CGI Client - . detectors/ - - the auditor and reactor modules for this instance + config.py + simple configuration of things like the email address for the + mail gateway, the mail domain, the mail host, ... + dbinit.py and select_db.py + defines the schema for the hyperdatabase and indicates which + backend to use. + interfaces.py + defines the CGI Client and mail gateway MailGW classes that are + used by roundup.cgi, roundup-server and roundup-mailgw. + __init__.py + ties together all the instance information into one interface + db/ + the actual database that stores the instance's data + html/ + the html templates that are used by the CGI Client + detectors/ + the auditor and reactor modules for this instance ''' # At the moment, it's just a copy copytree(template, instance_home) diff --git a/roundup/install_util.py b/roundup/install_util.py index 4e07a5b..97c16f4 100644 --- a/roundup/install_util.py +++ b/roundup/install_util.py @@ -15,11 +15,11 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: install_util.py,v 1.9 2003-11-11 22:37:25 richard Exp $ +# $Id: install_util.py,v 1.10 2004-02-11 23:55:08 richard Exp $ -__doc__ = """ -Support module to generate and check fingerprints of installed files. +"""Support module to generate and check fingerprints of installed files. """ +__docformat__ = 'restructuredtext' import os, sha, shutil diff --git a/roundup/instance.py b/roundup/instance.py index 3c85b6d..81c9461 100644 --- a/roundup/instance.py +++ b/roundup/instance.py @@ -15,13 +15,13 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: instance.py,v 1.11 2003-12-06 02:46:34 richard Exp $ +# $Id: instance.py,v 1.12 2004-02-11 23:55:08 richard Exp $ -__doc__ = ''' -Tracker handling (open tracker). +'''Tracker handling (open tracker). Backwards compatibility for the old-style "imported" trackers. ''' +__docformat__ = 'restructuredtext' import os diff --git a/roundup/mailer.py b/roundup/mailer.py index ddfc109..ec5951e 100644 --- a/roundup/mailer.py +++ b/roundup/mailer.py @@ -1,5 +1,7 @@ -"""Sending Roundup-specific mail over SMTP.""" -# $Id: mailer.py,v 1.4 2004-01-20 00:05:46 richard Exp $ +"""Sending Roundup-specific mail over SMTP. +""" +__docformat__ = 'restructuredtext' +# $Id: mailer.py,v 1.5 2004-02-11 23:55:08 richard Exp $ import time, quopri, os, socket, smtplib, re diff --git a/roundup/mailgw.py b/roundup/mailgw.py index 208cbb8..f45eedc 100644 --- a/roundup/mailgw.py +++ b/roundup/mailgw.py @@ -16,8 +16,7 @@ # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -""" -An e-mail gateway for Roundup. +"""An e-mail gateway for Roundup. Incoming messages are examined for multiple parts: . In a multipart/mixed message or part, each subpart is extracted and @@ -73,8 +72,9 @@ are calling the create() method to create a new node). If an auditor raises an exception, the original message is bounced back to the sender with the explanatory message given in the exception. -$Id: mailgw.py,v 1.142 2004-01-20 00:06:09 richard Exp $ +$Id: mailgw.py,v 1.143 2004-02-11 23:55:08 richard Exp $ """ +__docformat__ = 'restructuredtext' import string, re, os, mimetools, cStringIO, smtplib, socket, binascii, quopri import time, random, sys diff --git a/roundup/password.py b/roundup/password.py index 97de75d..a267e42 100644 --- a/roundup/password.py +++ b/roundup/password.py @@ -15,11 +15,11 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: password.py,v 1.10 2003-11-11 00:35:13 richard Exp $ +# $Id: password.py,v 1.11 2004-02-11 23:55:08 richard Exp $ -__doc__ = """ -Password handling (encoding, decoding). +"""Password handling (encoding, decoding). """ +__docformat__ = 'restructuredtext' import sha, re, string, random try: diff --git a/roundup/rcsv.py b/roundup/rcsv.py index 8957e35..91a8125 100644 --- a/roundup/rcsv.py +++ b/roundup/rcsv.py @@ -1,8 +1,7 @@ -""" -Supplies a Python-2.3 Object Craft csv module work-alike to the extent +"""Supplies a Python-2.3 Object Craft csv module work-alike to the extent needed by Roundup using the Python 2.3 csv module. - """ +__docformat__ = 'restructuredtext' from roundup.i18n import _ from cStringIO import StringIO diff --git a/roundup/rfc2822.py b/roundup/rfc2822.py index 0faa833..a54d34f 100644 --- a/roundup/rfc2822.py +++ b/roundup/rfc2822.py @@ -1,3 +1,7 @@ +"""Some rfc822 functions taken from the new (python2.3) "email" module. +""" +__docformat__ = 'restructuredtext' + import re from string import letters, digits from binascii import b2a_base64, a2b_base64 @@ -37,7 +41,8 @@ def base64_decode(s, convert_eols=None): return dec def unquote_match(match): - """Turn a match in the form =AB to the ASCII character with value 0xab + """Turn a match in the form ``=AB`` to the ASCII character with value + 0xab. Taken from 'email' module """ @@ -45,7 +50,7 @@ def unquote_match(match): return chr(int(s[1:3], 16)) def qp_decode(s): - """Decode a string encoded with RFC 2045 MIME header `Q' encoding. + """Decode a string encoded with RFC 2045 MIME header 'Q' encoding. This function does not parse a full MIME header value encoded with quoted-printable (like =?iso-8895-1?q?Hello_World?=) -- please use diff --git a/roundup/roundupdb.py b/roundup/roundupdb.py index 178552f..761f1ae 100644 --- a/roundup/roundupdb.py +++ b/roundup/roundupdb.py @@ -15,11 +15,12 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: roundupdb.py,v 1.96 2003-12-05 04:43:30 richard Exp $ +# $Id: roundupdb.py,v 1.97 2004-02-11 23:55:08 richard Exp $ -__doc__ = """ -Extending hyperdb with types specific to issue-tracking. +"""Extending hyperdb with types specific to issue-tracking. """ +__docformat__ = 'restructuredtext' + from __future__ import nested_scopes import re, os, smtplib, socket, time, random @@ -95,15 +96,16 @@ class DetectorError(RuntimeError): # deviation from spec - was called IssueClass class IssueClass: - """ This class is intended to be mixed-in with a hyperdb backend - implementation. The backend should provide a mechanism that - enforces the title, messages, files, nosy and superseder - properties: - properties['title'] = hyperdb.String(indexme='yes') - properties['messages'] = hyperdb.Multilink("msg") - properties['files'] = hyperdb.Multilink("file") - properties['nosy'] = hyperdb.Multilink("user") - properties['superseder'] = hyperdb.Multilink(classname) + """This class is intended to be mixed-in with a hyperdb backend + implementation. The backend should provide a mechanism that + enforces the title, messages, files, nosy and superseder + properties: + + - title = hyperdb.String(indexme='yes') + - messages = hyperdb.Multilink("msg") + - files = hyperdb.Multilink("file") + - nosy = hyperdb.Multilink("user") + - superseder = hyperdb.Multilink(classname) """ # New methods: diff --git a/roundup/scripts/__init__.py b/roundup/scripts/__init__.py index a64069f..f791def 100644 --- a/roundup/scripts/__init__.py +++ b/roundup/scripts/__init__.py @@ -15,10 +15,12 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: __init__.py,v 1.2 2002-09-10 01:07:05 richard Exp $ +# $Id: __init__.py,v 1.3 2004-02-11 23:55:10 richard Exp $ + +'''Subpackage containing the modules that implement the command +line tools. -__doc__ = ''' -Subpackage containing the modules that implement the command line tools. Note that these are imported by script stubs generated by "setup.py". ''' +__docformat__ = 'restructuredtext' # vim: set filetype=python ts=4 sw=4 et si diff --git a/roundup/scripts/roundup_admin.py b/roundup/scripts/roundup_admin.py index d4866f8..47db75e 100644 --- a/roundup/scripts/roundup_admin.py +++ b/roundup/scripts/roundup_admin.py @@ -14,7 +14,11 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: roundup_admin.py,v 1.5 2003-04-24 04:27:32 richard Exp $ +# $Id: roundup_admin.py,v 1.6 2004-02-11 23:55:10 richard Exp $ + +"""Command-line script stub that calls the roundup.admin functions. +""" +__docformat__ = 'restructuredtext' # python version check from roundup import version_check diff --git a/roundup/scripts/roundup_mailgw.py b/roundup/scripts/roundup_mailgw.py index 65163d8..5b6905c 100644 --- a/roundup/scripts/roundup_mailgw.py +++ b/roundup/scripts/roundup_mailgw.py @@ -14,7 +14,11 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: roundup_mailgw.py,v 1.10 2003-04-24 04:27:32 richard Exp $ +# $Id: roundup_mailgw.py,v 1.11 2004-02-11 23:55:10 richard Exp $ + +"""Command-line script stub that calls the roundup.mailgw. +""" +__docformat__ = 'restructuredtext' # python version check from roundup import version_check diff --git a/roundup/scripts/roundup_server.py b/roundup/scripts/roundup_server.py index 2039e96..6f58a60 100644 --- a/roundup/scripts/roundup_server.py +++ b/roundup/scripts/roundup_server.py @@ -14,10 +14,12 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -""" HTTP Server that serves roundup. -$Id: roundup_server.py,v 1.36 2003-12-06 02:46:34 richard Exp $ +"""Command-line script that runs a server over roundup.cgi.client. + +$Id: roundup_server.py,v 1.37 2004-02-11 23:55:10 richard Exp $ """ +__docformat__ = 'restructuredtext' # python version check from roundup import version_check diff --git a/roundup/security.py b/roundup/security.py index 241715d..58496f4 100644 --- a/roundup/security.py +++ b/roundup/security.py @@ -1,3 +1,7 @@ +"""Handle the security declarations used in Roundup trackers. +""" +__docformat__ = 'restructuredtext' + import weakref from roundup import hyperdb diff --git a/roundup/token.py b/roundup/token.py index 4ba5103..cdebffc 100644 --- a/roundup/token.py +++ b/roundup/token.py @@ -8,23 +8,25 @@ # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # -# $Id: token.py,v 1.3 2002-09-10 00:18:20 richard Exp $ +# $Id: token.py,v 1.4 2004-02-11 23:55:08 richard Exp $ # -__doc__ = """ -This module provides the tokeniser used by roundup-admin. +"""This module provides the tokeniser used by roundup-admin. """ +__docformat__ = 'restructuredtext' def token_split(s, whitespace=' \r\n\t', quotes='\'"', escaped={'r':'\r', 'n':'\n', 't':'\t'}): - '''Split the string up into tokens. An occurence of a ' or " in the - input will cause the splitter to ignore whitespace until a matching - quote char is found. Embedded non-matching quote chars are also - skipped. - Whitespace and quoting characters may be escaped using a backslash. - \r, \n and \t are converted to carriage-return, newline and tab. - All other backslashed characters are left as-is. - Valid: + '''Split the string up into tokens. An occurence of a ``'`` or ``"`` in + the input will cause the splitter to ignore whitespace until a matching + quote char is found. Embedded non-matching quote chars are also skipped. + + Whitespace and quoting characters may be escaped using a backslash. + ``\r``, ``\n`` and ``\t`` are converted to carriage-return, newline and + tab. All other backslashed characters are left as-is. + + Valid examples:: + hello world (2 tokens: hello, world) "hello world" (1 token: hello world) "Roch'e" Compaan (2 tokens: Roch'e Compaan) @@ -33,7 +35,9 @@ def token_split(s, whitespace=' \r\n\t', quotes='\'"', \\ (1 token: \) \n (1 token: a newline) \o (1 token: \o) - Invalid: + + Invalid examples:: + "hello world (no matching quote) Roch'e Compaan (no matching quote) ''' diff --git a/roundup/version_check.py b/roundup/version_check.py index 20ef7d9..5f6f2be 100644 --- a/roundup/version_check.py +++ b/roundup/version_check.py @@ -16,7 +16,11 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: version_check.py,v 1.3 2002-09-10 00:18:20 richard Exp $ +# $Id: version_check.py,v 1.4 2004-02-11 23:55:08 richard Exp $ + +"""Enforces the minimum Python version that Roundup requires. +""" +__docformat__ = 'restructuredtext' import sys if not hasattr(sys, 'version_info') or sys.version_info[:3] < (2,1,1): -- 2.30.2