summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 4977519)
raw | patch | inline | side by side (parent: 4977519)
author | richard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2> | |
Tue, 10 Dec 2002 00:11:16 +0000 (00:11 +0000) | ||
committer | richard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2> | |
Tue, 10 Dec 2002 00:11:16 +0000 (00:11 +0000) |
- fixed Date.local()
- email quoted text stripping is controllable again (sf bug 650742)
- extract attachment name from content-disposition if name is missing (sf
bug 637278)
- removed FILTER_POSITION from bundled configs
- reverse message listing in issue display (reversion of recent change)
- bad entries for multilink editing in cgi don't traceback now (sf bug 640310)
git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@1394 57a73879-2fb5-44c3-a270-3262357dd7e2
- email quoted text stripping is controllable again (sf bug 650742)
- extract attachment name from content-disposition if name is missing (sf
bug 637278)
- removed FILTER_POSITION from bundled configs
- reverse message listing in issue display (reversion of recent change)
- bad entries for multilink editing in cgi don't traceback now (sf bug 640310)
git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@1394 57a73879-2fb5-44c3-a270-3262357dd7e2
12 files changed:
diff --git a/CHANGES.txt b/CHANGES.txt
index 2077d29efd7ff9e09f6093262f127e0582da558f..6f7e5db8466745bb94d6bd2fea82a47382530bcd 100644 (file)
--- a/CHANGES.txt
+++ b/CHANGES.txt
- removed use of string/strop from TAL/TALInterpreter
- handle KeyboardInterrupt nicely
- fixed Date and Interval form value handling
+- fixed Date.local()
+- email quoted text stripping is controllable again (sf bug 650742)
+- extract attachment name from content-disposition if name is missing (sf
+ bug 637278)
+- removed FILTER_POSITION from bundled configs
+- reverse message listing in issue display (reversion of recent change)
+- bad entries for multilink editing in cgi don't traceback now (sf bug 640310)
2002-11-07 0.5.2
diff --git a/TODO.txt b/TODO.txt
index e37e0a63c20afa17b6592e6b0fd77e1b9b4a490e..88a53357146d0c8da328a1917e843f2377e9aa69 100644 (file)
--- a/TODO.txt
+++ b/TODO.txt
[value, value, ...] implies "in"
pending hyperdb migrate "id" property to be Number type
pending hyperdb multilink sorting by length is dumb
+pending hyperdb lastchangedby auto-property giving last user to change an
+ item
pending tracker split instance.open() into open() and login()
pending mailgw allow commands (feature request #556996)
like "help", "dump issue123" (would send all info about
strictness (ie. turn off username==address matching)
pending mailgw Use in-reply-to for determining message lineage when subject
line lets us down
+pending mailgw Allow different brackets delimiting [issueNNN] in Subject
+pending email email sig could use a "remove me from this list"
pending messages Snarf the first whole sentence, or full first line of
messages for the summary - whichever is longer.
pending project switch to a Roundup instance for Roundup bug/feature tracking
pending web automagically link designators
pending web add checkbox-based removal/addition for multilink entries
(eg "add me"/"remove me" for nosy list)
-pending web multilink item removal action (with retirement)
pending web search "refinement" - pre-fill the search page with the
current search parameters
pending web column-heading sort stuff isn't implemented
+pending web multilink item removal action with retirement
+pending web implement a python dict version of the form values
active web UNIX init.d script for roundup-server
bug web query editing isn't fully implemented
bug web no testing for parsePropsFromForm
active web revert to showing entire message in classic issue display
+bug hyperdb pysqlite and locks
+ http://www.hwaci.com/sw/sqlite/c_interface.html
+bug web implement the request.url attribute?
======= ========= =============================================================
diff --git a/doc/customizing.txt b/doc/customizing.txt
index d67e395895341bfa14bb1f1deca2daa94ea0f960..068e9076244f7e1096625e299bebd443f584b10c 100644 (file)
--- a/doc/customizing.txt
+++ b/doc/customizing.txt
Customising Roundup
===================
-:Version: $Revision: 1.63 $
+:Version: $Revision: 1.64 $
.. This document borrows from the ZopeBook section on ZPT. The original is at:
http://www.zope.org/Documentation/Books/ZopeBook/current/ZPT.stx
Searching Views
---------------
+Note: if you add a new column to the ``:columns`` form variable potentials
+ then you will need to add the column to the `index view`_
+ template so it is actually displayed.
+
This is one of the class context views. The template used is typically
"*classname*.search". The form on this page should have "search" as its
``:action`` variable. The "search" action:
template schema does not.
-
Item Views
----------
diff --git a/roundup/__init__.py b/roundup/__init__.py
index b5440b9ff9d47a21325025bb8b3a1ded5d48aac9..9935146fe39af1b47adb8e6087e84597cb1ac5da 100644 (file)
--- a/roundup/__init__.py
+++ b/roundup/__init__.py
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#
-# $Id: __init__.py,v 1.16 2002-11-06 11:38:42 richard Exp $
+# $Id: __init__.py,v 1.17 2002-12-10 00:11:14 richard Exp $
''' Roundup - issue tracking for knowledge workers.
much prettier cake :)
'''
-__version__ = '0.5.2'
+__version__ = '0.5.3'
# vim: set filetype=python ts=4 sw=4 et si
diff --git a/roundup/cgi/client.py b/roundup/cgi/client.py
index 77e625d68b080cc32d9944ea4d66c2fc14eff76e..f45b3366a9950c39abe711591c2a3cadaf04a10d 100644 (file)
--- a/roundup/cgi/client.py
+++ b/roundup/cgi/client.py
-# $Id: client.py,v 1.58 2002-11-28 07:08:39 richard Exp $
+# $Id: client.py,v 1.59 2002-12-10 00:11:15 richard Exp $
__doc__ = """
WWW request handler (also used in the stand-alone server).
props = self._changenode(props)
# handle linked nodes
self._post_editnode(self.nodeid)
- except (ValueError, KeyError), message:
+ except (ValueError, KeyError, IndexError), message:
self.error_message.append(_('Error: ') + str(message))
return
try:
# do the create
nid = self._createnode(props)
+ except (ValueError, KeyError, IndexError), message:
+ # these errors might just be indicative of user dumbness
+ self.error_message.append(_('Error: ') + str(message))
+ return
+ except:
+ # oops
+ self.db.rollback()
+ s = StringIO.StringIO()
+ traceback.print_exc(None, s)
+ self.error_message.append('<pre>%s</pre>'%cgi.escape(s.getvalue()))
+ return
+ try:
# handle linked nodes
self._post_editnode(nid)
# and some nice feedback for the user
message = _('%(classname)s created ok')%self.__dict__ + xtra
- except (ValueError, KeyError), message:
- self.error_message.append(_('Error: ') + str(message))
- return
except:
# oops
self.db.rollback()
index cd315297c16a3485c06b20803cc2cec63ad18c22..35bc234b290eb86615a6dcc2b526c9f65bc3b8c0 100644 (file)
'''
return self._value.pretty()
+ def local(self, offset):
+ ''' Return the date/time as a local (timezone offset) date/time.
+ '''
+ return DateHTMLProperty(self._client, self._nodeid, self._prop,
+ self._name, self._value.local())
+
class IntervalHTMLProperty(HTMLProperty):
def plain(self):
''' Render a "plain" representation of the property
else:
s = ''
l.append(_('<option %svalue="-1">- no selection -</option>')%s)
+ # XXX if the current value is retired, then list it explicitly
for optionid in options:
# get the option value, and if it's None use an empty string
option = linkcl.get(optionid, k) or ''
else:
sort_on = ('+', linkcl.labelprop())
options = linkcl.filter(None, conditions, sort_on, (None, None))
+ # XXX if the current value is retired, then list it explicitly
for optionid in options:
# get the option value, and if it's None use an empty string
option = linkcl.get(optionid, k) or ''
height = height or min(len(options), 7)
l = ['<select multiple name="%s" size="%s">'%(self._name, height)]
k = linkcl.labelprop(1)
+ # XXX if any of the current values are retired, then list them
for optionid in options:
# get the option value, and if it's None use an empty string
option = linkcl.get(optionid, k) or ''
diff --git a/roundup/mailgw.py b/roundup/mailgw.py
index 8b4f95e6de567160cee5a5f0b85788fb3f455a9e..3f62e415520b3f5a44d69007cd398380a15e51a0 100644 (file)
--- a/roundup/mailgw.py
+++ b/roundup/mailgw.py
an exception, the original message is bounced back to the sender with the
explanatory message given in the exception.
-$Id: mailgw.py,v 1.99 2002-11-05 22:59:46 richard Exp $
+$Id: mailgw.py,v 1.100 2002-12-10 00:11:15 richard Exp $
'''
import string, re, os, mimetools, cStringIO, smtplib, socket, binascii, quopri
attachments.append((name, 'message/rfc822', part.fp.read()))
else:
# try name on Content-Type
- name = part.getparam('name')
+ name = part.getparam('name').strip()
+ if not name:
+ disp = part.getheader('content-disposition', None)
+ if disp:
+ name = disp.getparam('filename').strip()
# this is just an attachment
data = self.get_part_data_decoded(part)
attachments.append((name, part.gettype(), data))
content = self.get_part_data_decoded(message)
# figure how much we should muck around with the email body
- keep_citations = getattr(self.instance, 'EMAIL_KEEP_QUOTED_TEXT',
+ keep_citations = getattr(self.instance.config, 'EMAIL_KEEP_QUOTED_TEXT',
'no') == 'yes'
- keep_body = getattr(self.instance, 'EMAIL_LEAVE_BODY_UNCHANGED',
+ keep_body = getattr(self.instance.config, 'EMAIL_LEAVE_BODY_UNCHANGED',
'no') == 'yes'
# parse the body of the message, stripping out bits as appropriate
index 9683b40991083fdcfa25fed2b2242f64e2227881..c312b58f97134825fa042ccb7f2fd9371356c9a6 100644 (file)
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#
-# $Id: config.py,v 1.4 2002-11-07 21:17:44 richard Exp $
+# $Id: config.py,v 1.5 2002-12-10 00:11:16 richard Exp $
import os
# The email address that roundup will complain to if it runs into trouble
ADMIN_EMAIL = 'roundup-admin@%s'%MAIL_DOMAIN
-# Where to place the web filtering HTML on the index page
-FILTER_POSITION = 'bottom' # one of 'top', 'bottom', 'top and bottom'
-
#
# SECURITY DEFINITIONS
#
index d4e4e1f9f49299e7d4bcb6f6589b7ac639fd3f3e..dcba3e0646f5620d834c412188a52b63f598b228 100644 (file)
<table class="messages" tal:condition="context/messages">
<tr><th colspan="4" class="header">Messages</th></tr>
- <tal:block tal:repeat="msg context/messages">
+ <tal:block tal:repeat="msg context/messages/reverse">
<tr>
<th><a tal:attributes="href string:msg${msg/id}"
tal:content="string:msg${msg/id}"></a></th>
index 2987ed6ee8a94da07fb25f856231d5641be1365d..94e76e3ab4a349b06d58ef078223b82a91b03503 100644 (file)
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#
-# $Id: config.py,v 1.2 2002-11-07 21:17:44 richard Exp $
+# $Id: config.py,v 1.3 2002-12-10 00:11:16 richard Exp $
import os
# The email address that roundup will complain to if it runs into trouble
ADMIN_EMAIL = 'roundup-admin@%s'%MAIL_DOMAIN
-# Where to place the web filtering HTML on the index page
-FILTER_POSITION = 'bottom' # one of 'top', 'bottom', 'top and bottom'
-
#
# SECURITY DEFINITIONS
#
diff --git a/setup.py b/setup.py
index 64176b8785e2f45bdcd5189854319d9019e65fc0..800603e61903817a2db4eefc82788b831965b1a8 100644 (file)
--- a/setup.py
+++ b/setup.py
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#
-# $Id: setup.py,v 1.40 2002-10-17 00:22:16 richard Exp $
+# $Id: setup.py,v 1.41 2002-12-10 00:11:13 richard Exp $
from distutils.core import setup, Extension
from distutils.util import get_platform
import sys, os, string
from glob import glob
+# patch distutils if it can't cope with the "classifiers" keyword
+if sys.version < '2.2.3':
+ from distutils.dist import DistributionMetadata
+ DistributionMetadata.classifiers = None
+
from roundup.templates.builder import makeHtmlBase
author_email = "richard@users.sourceforge.net",
url = 'http://sourceforge.net/projects/roundup/',
packages = packagelist,
+ classifiers = [
+ 'Development Status :: 4 - Beta',
+ 'Environment :: Console',
+ 'Environment :: Web Environment',
+ 'Intended Audience :: End Users/Desktop',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: System Administrators',
+ 'License :: OSI Approved :: Python Software Foundation License',
+ 'Operating System :: MacOS :: MacOS X',
+ 'Operating System :: Microsoft :: Windows',
+ 'Operating System :: POSIX',
+ 'Programming Language :: Python',
+ 'Topic :: Communications :: Email',
+ 'Topic :: Office/Business',
+ 'Topic :: Software Development :: Bug Tracking',
+ ],
# Override certain command classes with our own ones
cmdclass = {
diff --git a/test/test_mailgw.py b/test/test_mailgw.py
index f8332b618c3f8d9605bb6781302d818ad8fdd8c5..918f431396773b0077205e62d9b2b63796714d64 100644 (file)
--- a/test/test_mailgw.py
+++ b/test/test_mailgw.py
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
-# $Id: test_mailgw.py,v 1.33 2002-11-05 22:59:46 richard Exp $
+# $Id: test_mailgw.py,v 1.34 2002-12-10 00:11:16 richard Exp $
import unittest, cStringIO, tempfile, os, shutil, errno, imp, sys, difflib
l = self.db.issue.get(nodeid, 'nosy')
l.sort()
self.assertEqual(l, ['3', '4'])
+ return nodeid
def testNewIssue(self):
self.doNewIssue()
_______________________________________________________________________
''')
+ def testEmailQuoting(self):
+ self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'no'
+ self.innerTestQuoting('''This is a followup
+''')
+
+ def testEmailQuotingRemove(self):
+ self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'yes'
+ self.innerTestQuoting('''Blah blah wrote:
+> Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
+> skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
+>
+
+This is a followup
+''')
+
+ def innerTestQuoting(self, expect):
+ nodeid = self.doNewIssue()
+
+ messages = self.db.issue.get(nodeid, 'messages')
+
+ message = cStringIO.StringIO('''Content-Type: text/plain;
+ charset="iso-8859-1"
+From: richard <richard@test>
+To: issue_tracker@your.tracker.email.domain.example
+Message-Id: <followup_dummy_id>
+In-Reply-To: <dummy_test_message_id>
+Subject: Re: [issue1] Testing...
+
+Blah blah wrote:
+> Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
+> skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
+>
+
+This is a followup
+''')
+ handler = self.instance.MailGW(self.instance, self.db)
+ handler.trapExceptions = 0
+ handler.main(message)
+
+ # figure the new message id
+ newmessages = self.db.issue.get(nodeid, 'messages')
+ for msg in messages:
+ newmessages.remove(msg)
+ messageid = newmessages[0]
+
+ self.compareStrings(self.db.msg.get(messageid, 'content'), expect)
+
def suite():
l = [unittest.makeSuite(MailgwTestCase),
]