aboutsummaryrefslogtreecommitdiffstats
path: root/interfaces
diff options
context:
space:
mode:
authorW. Trevor King <wking@drexel.edu>2009-12-31 15:54:12 -0500
committerW. Trevor King <wking@drexel.edu>2009-12-31 15:54:12 -0500
commitb0b5341c4045dd27cfbb3e2585cb2614ed9ad903 (patch)
tree37c7c2d011617ccd7a6f28a24ea77bb1b3cddfe7 /interfaces
parenta06030436d3940dddfba37b344f90651366d67e1 (diff)
parent2d1562d951e763fed71fe60e77cc9921be9abdc9 (diff)
downloadbugseverywhere-b0b5341c4045dd27cfbb3e2585cb2614ed9ad903.tar.gz
Merged be.restructure, major internal reorganization.
Added a bunch of classes to make the commands, user interfaces, and storage backends more abstract and distinct. This should make it much easier to extend and maintain BE. Features: * Directory restructured: becommands/ -> libbe/commands submods sorted by functionality. * Lots of new classes: Option, Argument, Command InputOutput, StorageCallbacks, UserInterface Storage * Consolidated ID handling in libbe.util.id * Transitioned VCS backends for Python-based VCSs from subprocess calss to internal python calls. Plus the user-visible changes: * New bugdir/bug/comment ID format replaces old bug:comment format. * Deprecated support for `be diff` on Arch and Darcs <= 2.3.1. A new backend abstraction (Storage) makes the former implementation ungainly. * Improved command completion. * Removed commands close, open, email_bugs, * Flipped some arguments `be assign BUG-ID [ASSIGNEE]` -> `be status ASSIGNED BUG-ID ...` `be severity BUG-ID SEVERITY` -> `be severity SEVERITY BUG-ID ...` `be status BUG-ID STATUS` -> `be status STATUS BUG-ID ...` In the merge: * Added 'commit' to list of pagerless commands. * Updated doc/README.dev See #bea86499-824e-4e77-b085-2d581fa9ccab/1100c966-9671-4bc6-8b68-6d408a910da1# for a discussion of why the changes were made and some of the difficulties en-route.
Diffstat (limited to 'interfaces')
-rw-r--r--interfaces/README34
-rwxr-xr-xinterfaces/email/catmutt59
-rwxr-xr-xinterfaces/email/interactive/be-handle-mail491
l---------interfaces/email/interactive/becommands1
-rwxr-xr-xinterfaces/gui/beg/beg12
-rw-r--r--interfaces/gui/beg/table.py97
-rwxr-xr-xinterfaces/gui/wxbe/wxbe87
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/Bugs-Everywhere-Web.egg-info/SOURCES.txt36
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/Bugs-Everywhere-Web.egg-info/not-zip-safe0
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/Bugs-Everywhere-Web.egg-info/requires.txt1
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/Bugs-Everywhere-Web.egg-info/sqlobject.txt2
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/Bugs-Everywhere-Web.egg-info/top_level.txt2
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/PKG-INFO15
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/SOURCES.txt44
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/dependency_links.txt1
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/not-zip-safe1
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/paster_plugins.txt2
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/requires.txt1
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/sqlobject.txt2
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/top_level.txt1
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/README60
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/__init__.py0
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/app.cfg120
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/config.py.example10
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/config/app.cfg92
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/config/log.cfg29
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/controllers.py240
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/formatting.py76
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/json.py13
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/model.py107
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/prest.py168
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/release.py14
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/css/style.css116
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-b.pngbin213 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-bl.pngbin327 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-br.pngbin365 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-l.pngbin197 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-r.pngbin214 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-t.pngbin200 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-tl.pngbin240 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-tr.pngbin311 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds2-b.pngbin206 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds2-r.pngbin204 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/favicon.icobin318 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/favicon.pngbin267 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/half-spiral.pngbin1112 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/header_inner.pngbin37537 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/info.pngbin2889 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-b.pngbin200 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-bl.pngbin408 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-br.pngbin304 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-l.pngbin214 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-r.pngbin197 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-t.pngbin213 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-tl.pngbin413 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-tr.pngbin414 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ok.pngbin25753 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/shadows.pngbin3960 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/spiral.pngbin2120 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/tg_under_the_hood.pngbin4010 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/static/images/under_the_hood_blue.pngbin2667 -> 0 bytes
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/templates/__init__.py0
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/templates/about.kid21
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/templates/bugs.kid52
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/templates/edit_bug.kid52
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/templates/edit_comment.kid26
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/templates/error.kid14
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/templates/login.kid113
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/templates/master.kid71
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/templates/projects.kid32
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/templates/welcome.kid50
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/tests/__init__.py0
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/tests/test_controllers.py16
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/beweb/tests/test_model.py23
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/dev.cfg71
l---------interfaces/web/Bugs-Everywhere-Web/libbe1
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/prod.cfg41
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/sample-prod.cfg71
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/setup-tables.py34
-rw-r--r--interfaces/web/Bugs-Everywhere-Web/setup.py62
-rwxr-xr-xinterfaces/web/Bugs-Everywhere-Web/start-beweb.py28
-rwxr-xr-xinterfaces/xml/be-mbox-to-xml154
-rwxr-xr-xinterfaces/xml/be-xml-to-mbox208
83 files changed, 229 insertions, 2845 deletions
diff --git a/interfaces/README b/interfaces/README
deleted file mode 100644
index 4d74580..0000000
--- a/interfaces/README
+++ /dev/null
@@ -1,34 +0,0 @@
-Removing spam commits from the history
-======================================
-
-arch bzr darcs git hg none
-
-In the case that some spam or inappropriate comment makes its way
-through you interface, you can remove the offending commit XYZ with:
-
- If the offending commit is the last commit:
-
- arch:
- bzr: bzr uncommit && bzr revert
- darcs: darcs obliterate --last=1
- git: git reset --hard HEAD^
- hg: hg rollback && hg revert
-
- If the offending commit is not the last commit:
-
- arch:
- bzr: bzr rebase -r <XYZ+1>..-1 --onto before:XYZ .
- (requires bzr-rebase plugin, note, you have to increment XYZ by
- hand for <XYZ+1>, because bzr does not support "after:XYZ".)
- darcs: darcs obliterate --matches 'name XYZ'
- git: git rebase --onto XYZ~1 XYZ
- hg: -not-supported-
- (From http://hgbook.red-bean.com/read/finding-and-fixing-mistakes.html#id394667
- "Mercurial also does not provide a way to make a file or
- changeset completely disappear from history, because there is no
- way to enforce its disappearance")
-
-Note that all of these _change_the_repo_history_, so only do this on
-your interface-specific repo before it interacts with any other repo.
-Otherwise, you'll have to survive by cherry-picking only the good
-commits.
diff --git a/interfaces/email/catmutt b/interfaces/email/catmutt
deleted file mode 100755
index 601f14f..0000000
--- a/interfaces/email/catmutt
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/bin/sh
-
-# catmutt - wrap mutt allowing mboxes read from stdin.
-#
-# Copyright (C) 1998-1999 Moritz Barsnick <barsnick (at) gmx (dot) net>,
-# 2009 William Trevor King <wking (at) drexel (dot) edu>
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# version 2 as published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-# developed from grepm-0.6
-# http://www.barsnick.net/sw/grepm.html
-
-PROGNAME=`basename "$0"`
-export TMPDIR="${TMPDIR-/tmp}" # used by mktemp
-umask 077
-
-if [ $# -gt 0 ] && [ "$1" = "--help" ]; then
- echo 1>&2 "Usage: ${PROGNAME} [--help] mutt-arguments"
- echo 1>&2 ""
- echo 1>&2 "Read a mailbox file from stdin and opens it with mutt."
- echo 1>&2 "For example: cat somefile.mbox | ${PROGNAME}"
- exit 0
-fi
-
-# Note: the -t/-p options to mktemp are deprecated for mktemp (GNU
-# coreutils) 7.1 in favor of --tmpdir but the --tmpdir option does not
-# exist yet for my 6.10-3ubuntu2 coreutils
-TMPFILE=`mktemp -t catmutt.XXXXXX` || exit 1
-
-trap "rm -f ${TMPFILE}; exit 1" 1 2 3 13 15
-
-cat > "${TMPFILE}" || exit 1
-
-# Now that we've read in the mailbox file, reopen stdin for mutt/user
-# interaction. When in a pipe we're not technically in a tty, so use
-# a little hack from "greno" at
-# http://www.linuxforums.org/forum/linux-programming-scripting/98607-bash-stdin-problem.html
-tty="/dev/`ps -p$$ --no-heading | awk '{print $2}'`"
-exec < ${tty}
-
-if [ `wc -c "${TMPFILE}" | awk '{print $1}'` -gt 0 ]; then
- echo 1>&2 "Calling mutt on temporary mailbox file (${TMPFILE})."
- mutt -R -f "${TMPFILE}" "$@"
-else
- echo 1>&2 "Empty mailbox input."
-fi
-
-rm -f "${TMPFILE}" && echo 1>&2 "Deleted temporary mailbox file (${TMPFILE})."
diff --git a/interfaces/email/interactive/be-handle-mail b/interfaces/email/interactive/be-handle-mail
index 10f6884..f8792f1 100755
--- a/interfaces/email/interactive/be-handle-mail
+++ b/interfaces/email/interactive/be-handle-mail
@@ -58,45 +58,51 @@ import shlex
import sys
import time
import traceback
+import types
import doctest
import unittest
-from becommands import subscribe
-import libbe.cmdutil, libbe.encoding, libbe.utility, libbe.diff, \
- libbe.bugdir, libbe.bug, libbe.comment
+import libbe.bugdir
+import libbe.bug
+import libbe.comment
+import libbe.diff
+import libbe.command
+import libbe.command.subscribe as subscribe
+import libbe.storage
+import libbe.ui.command_line
+import libbe.util.encoding
+import libbe.util.utility
import send_pgp_mime
-THIS_SERVER = u"thor.physics.drexel.edu"
-THIS_ADDRESS = u"BE Bugs <wking@thor.physics.drexel.edu>"
-
+THIS_SERVER = u'thor.physics.drexel.edu'
+THIS_ADDRESS = u'BE Bugs <wking@thor.physics.drexel.edu>'
+UI = None
_THIS_DIR = os.path.abspath(os.path.dirname(__file__))
-BE_DIR = _THIS_DIR
-LOGPATH = os.path.join(_THIS_DIR, u"be-handle-mail.log")
+LOGPATH = os.path.join(_THIS_DIR, u'be-handle-mail.log')
LOGFILE = None
# Tag strings generated by generate_global_tags()
-SUBJECT_TAG_BASE = u"be-bug"
+SUBJECT_TAG_BASE = u'be-bug'
SUBJECT_TAG_RESPONSE = None
SUBJECT_TAG_START = None
SUBJECT_TAG_NEW = None
SUBJECT_TAG_COMMENT = None
SUBJECT_TAG_CONTROL = None
-SUBJECT_TAG_XML = None
-
-BREAK = u"--"
-NEW_REQUIRED_PSEUDOHEADERS = [u"Version"]
-NEW_OPTIONAL_PSEUDOHEADERS = [u"Reporter", u"Assign", u"Depend", u"Severity",
- u"Status", u"Tag", u"Target",
- u"Confirm", u"Subscribe"]
-CONTROL_COMMENT = u"#"
-ALLOWED_COMMANDS = [u"assign", u"comment", u"commit", u"depend", u"help",
- u"list", u"merge", u"new", u"open", u"severity", u"show",
- u"status", u"subscribe", u"tag", u"target", u"import-xml"]
+
+BREAK = u'--'
+NEW_REQUIRED_PSEUDOHEADERS = [u'Version']
+NEW_OPTIONAL_PSEUDOHEADERS = [u'Reporter', u'Assign', u'Depend', u'Severity',
+ u'Status', u'Tag', u'Target',
+ u'Confirm', u'Subscribe']
+CONTROL_COMMENT = u'#'
+ALLOWED_COMMANDS = [u'assign', u'comment', u'commit', u'depend', u'diff',
+ u'due', u'help', u'list', u'merge', u'new', u'severity',
+ u'show', u'status', u'subscribe', u'tag', u'target']
AUTOCOMMIT = True
-libbe.encoding.ENCODING = u"utf-8" # force default encoding
-ENCODING = libbe.encoding.get_encoding()
+ENCODING = u'utf-8'
+libbe.util.encoding.ENCODING = ENCODING # force default encoding
class InvalidEmail (ValueError):
def __init__(self, msg, message):
@@ -104,10 +110,10 @@ class InvalidEmail (ValueError):
self.msg = msg
def response(self):
header = self.msg.response_header
- body = [u"Error processing email:\n",
- self.response_body(), u""]
+ body = [u'Error processing email:\n',
+ self.response_body(), u'']
response_generator = \
- send_pgp_mime.PGPMimeMessageFactory(u"\n".join(body))
+ send_pgp_mime.PGPMimeMessageFactory(u'\n'.join(body))
response = MIMEMultipart()
response.attach(response_generator.plain())
response.attach(self.msg.msg)
@@ -115,44 +121,44 @@ class InvalidEmail (ValueError):
return ret
def response_body(self):
err_text = [unicode(self)]
- return u"\n".join(err_text)
+ return u'\n'.join(err_text)
class InvalidSubject (InvalidEmail):
def __init__(self, msg, message=None):
if message == None:
- message = u"Invalid subject"
+ message = u'Invalid subject'
InvalidEmail.__init__(self, msg, message)
def response_body(self):
- err_text = u"\n".join([unicode(self), u"",
- u"full subject was:",
+ err_text = u'\n'.join([unicode(self), u'',
+ u'full subject was:',
self.msg.subject()])
return err_text
class InvalidPseudoHeader (InvalidEmail):
def response_body(self):
- err_text = [u"Invalid pseudo-header:\n",
+ err_text = [u'Invalid pseudo-header:\n',
unicode(self)]
- return u"\n".join(err_text)
+ return u'\n'.join(err_text)
class InvalidCommand (InvalidEmail):
def __init__(self, msg, command, message=None):
- bigmessage = u"Invalid execution command '%s'" % command
+ bigmessage = u'Invalid execution command "%s"' % command
if message != None:
- bigmessage += u"\n%s" % message
+ bigmessage += u'\n%s' % message
InvalidEmail.__init__(self, msg, bigmessage)
self.command = command
class InvalidOption (InvalidCommand):
def __init__(self, msg, option, message=None):
- bigmessage = u"Invalid option '%s'" % (option)
+ bigmessage = u'Invalid option "%s"' % (option)
if message != None:
- bigmessage += u"\n%s" % message
+ bigmessage += u'\n%s' % message
InvalidCommand.__init__(self, msg, info, command, bigmessage)
self.option = option
class NotificationFailed (Exception):
def __init__(self, msg):
- bigmessage = "Notification failed: %s" % msg
+ bigmessage = 'Notification failed: %s' % msg
Exception.__init__(self, bigmessage)
self.short_msg = msg
@@ -166,11 +172,11 @@ class ID (object):
def __init__(self, command):
self.command = command
def extract_id(self):
- if hasattr(self, "cached_id"):
+ if hasattr(self, 'cached_id'):
return self._cached_id
assert self.command.ret == 0, self.command.ret
- if self.command.command == u"new":
- regexp = re.compile(u"Created bug with ID (.*)")
+ if self.command.command.name == u'new':
+ regexp = re.compile(u'Created bug with ID (.*)')
else:
raise NotImplementedError, self.command.command
match = regexp.match(self.command.stdout)
@@ -179,13 +185,12 @@ class ID (object):
return self._cached_id
def __str__(self):
if self.command.ret != 0:
- return "<id for %s>" % repr(self.command)
- return "<id %s>" % self.extract_id()
+ return '<id for %s>' % repr(self.command)
+ return '<id %s>' % self.extract_id()
class Command (object):
"""
- A becommands command wrapper.
- Doesn't validate input, so do that before initializing.
+ A libbe.command.Command handler.
Initialize with
Command(msg, command, args=None, stdin=None)
@@ -197,18 +202,17 @@ class Command (object):
"""
def __init__(self, msg, command, args=None, stdin=None):
self.msg = msg
- self.command = command
if args == None:
self.args = []
else:
self.args = args
- self.stdin = stdin
+ self.command = libbe.command.get_command_class(command_name=command)()
+ self.command._setup_io = lambda i_enc,o_enc : None
self.ret = None
+ self.stdin = stdin
self.stdout = None
- self.stderr = None
- self.err = None
def __str__(self):
- return "<command: %s %s>" % (self.command, " ".join([str(s) for s in self.args]))
+ return '<command: %s %s>' % (self.command, ' '.join([str(s) for s in self.args]))
def normalize_args(self):
"""
Expand any ID placeholders in self.args.
@@ -222,61 +226,25 @@ class Command (object):
info. Returns the exit code, stdout, and stderr produced by the
command.
"""
- if self.command in [None, u""]: # don't accept blank commands
- raise InvalidCommand(self.msg, self, "Blank")
- elif self.command not in ALLOWED_COMMANDS:
- raise InvalidCommand(self.msg, self, "Not allowed")
- assert self.ret == None, u"running %s twice!" % unicode(self)
+ if self.command.name in [None, u'']: # don't accept blank commands
+ raise InvalidCommand(self.msg, self, 'Blank')
+ elif self.command.name not in ALLOWED_COMMANDS:
+ raise InvalidCommand(self.msg, self, 'Not allowed')
+ assert self.ret == None, u'running %s twice!' % unicode(self)
self.normalize_args()
- # set stdin and catch stdout and stderr
- if self.stdin != None:
- orig_stdin = sys.stdin
- sys.stdin = StringIO.StringIO(self.stdin)
- new_stdout = codecs.getwriter(ENCODING)(StringIO.StringIO())
- new_stderr = codecs.getwriter(ENCODING)(StringIO.StringIO())
- orig_stdout = sys.stdout
- orig_stderr = sys.stderr
- sys.stdout = new_stdout
- sys.stderr = new_stderr
- # run the command
- os.chdir(BE_DIR)
- try:
- self.ret = libbe.cmdutil.execute(self.command, self.args,
- manipulate_encodings=False,
- restrict_file_access=True)
- except libbe.cmdutil.GetHelp:
- print libbe.cmdutil.help(command)
- except libbe.cmdutil.GetCompletions:
- self.err = InvalidOption(self.msg, self.command, u"--complete")
- except libbe.cmdutil.UsageError, e:
- self.err = InvalidCommand(self.msg, self,
- "%s\n%s" % (type(e), unicode(e)))
- except libbe.cmdutil.UserError, e:
- self.err = InvalidCommand(self.msg, self,
- "%s\n%s" % (type(e), unicode(e)))
- # restore stdin, stdout, and stderr
- if self.stdin != None:
- sys.stdin = orig_stdin
- sys.stdout.flush()
- sys.stderr.flush()
- sys.stdout = orig_stdout
- sys.stderr = orig_stderr
- self.stdout = codecs.decode(new_stdout.getvalue(), ENCODING)
- self.stderr = codecs.decode(new_stderr.getvalue(), ENCODING)
- if self.err != None:
- raise self.err
- return (self.ret, self.stdout, self.stderr)
+ UI.io.set_stdin(self.stdin)
+ self.ret = libbe.ui.command_line.dispatch(UI, self.command, self.args)
+ self.stdout = UI.io.get_stdout()
+ return (self.ret, self.stdout)
def response_msg(self):
if self.ret == None: self.ret = -1
- response_body = [u"Results of running: (exit code %d)" % self.ret,
- u" %s %s" % (self.command, u" ".join(self.args))]
+ response_body = [u'Results of running: (exit code %d)' % self.ret,
+ u' %s %s' % (self.command.name,u' '.join(self.args))]
if self.stdout != None and len(self.stdout) > 0:
- response_body.extend([u"", u"stdout:", u"", self.stdout])
- if self.stderr != None and len(self.stderr) > 0:
- response_body.extend([u"", u"stderr:", u"", self.stderr])
- response_body.append(u"") # trailing endline
+ response_body.extend([u'', u'output:', u'', self.stdout])
+ response_body.append(u'') # trailing endline
response_generator = \
- send_pgp_mime.PGPMimeMessageFactory(u"\n".join(response_body))
+ send_pgp_mime.PGPMimeMessageFactory(u'\n'.join(response_body))
return response_generator.plain()
class DiffTree (libbe.diff.DiffTree):
@@ -315,27 +283,27 @@ class DiffTree (libbe.diff.DiffTree):
def report_string(self):
report = self.report_or_none()
if report == None:
- return "No changes"
+ return 'No changes'
else:
return send_pgp_mime.flatten(report, to_unicode=True)
def make_root(self):
return MIMEMultipart()
def join(self, root, parent, data_part):
- if hasattr(parent, "attach_child_text"):
+ if hasattr(parent, 'attach_child_text'):
self.attach_child_text = True
if data_part != None:
- send_pgp_mime.append_text(parent.data_mime_part, u"\n\n%s" % (data_part))
+ send_pgp_mime.append_text(parent.data_mime_part, u'\n\n%s' % (data_part))
self.data_mime_part = parent.data_mime_part
else:
self.data_mime_part = None
if data_part != None:
self.data_mime_part = send_pgp_mime.encodedMIMEText(data_part)
- if parent != None and parent.name in [u"new", u"rem", u"mod"]:
+ if parent != None and parent.name in [u'new', u'rem', u'mod']:
self.attach_child_text = True
if data_part == None: # make blank data_mime_part for children's appends
- self.data_mime_part = send_pgp_mime.encodedMIMEText(u"")
+ self.data_mime_part = send_pgp_mime.encodedMIMEText(u'')
if self.data_mime_part != None:
- self.data_mime_part[u"Content-Description"] = self.name
+ self.data_mime_part[u'Content-Description'] = self.name
root.attach(self.data_mime_part)
def data_part(self, depth, indent=False):
return libbe.diff.DiffTree.data_part(self, depth, indent=indent)
@@ -357,19 +325,19 @@ class Message (object):
p=email.Parser.Parser()
self.msg=p.parsestr(self.text)
if LOGFILE != None:
- LOGFILE.write(u"handling %s\n" % self.author_addr())
- LOGFILE.write(u"\n%s\n\n" % self.text)
+ LOGFILE.write(u'handling %s\n' % self.author_addr())
+ LOGFILE.write(u'\n%s\n\n' % self.text)
self.confirm = True # enable/disable confirmation email
def _yes_no(self, boolean):
if boolean == True:
- return "yes"
- return "no"
+ return 'yes'
+ return 'no'
def author_tuple(self):
"""
Extract and normalize the sender's email address. Returns a
(name, email) tuple.
"""
- if not hasattr(self, "author_tuple_cache"):
+ if not hasattr(self, 'author_tuple_cache'):
self._author_tuple_cache = \
send_pgp_mime.source_email(self.msg, return_realname=True)
return self._author_tuple_cache
@@ -384,24 +352,24 @@ class Message (object):
return self.msg[attr_name]
return default
def message_id(self, default=None):
- return self.default_msg_attribute_access("message-id", default=default)
+ return self.default_msg_attribute_access('message-id', default=default)
def subject(self):
- if "subject" not in self.msg:
- raise InvalidSubject(self, u"Email must contain a subject")
- return self.msg["subject"]
+ if 'subject' not in self.msg:
+ raise InvalidSubject(self, u'Email must contain a subject')
+ return self.msg['subject']
def _split_subject(self):
"""
Returns (tag, subject), with missing values replaced by None.
"""
- if hasattr(self, "_split_subject_cache"):
+ if hasattr(self, '_split_subject_cache'):
return self._split_subject_cache
- args = self.subject().split(u"]",1)
+ args = self.subject().split(u']',1)
if len(args) < 1:
self._split_subject_cache = (None, None)
elif len(args) < 2:
- self._split_subject_cache = (args[0]+u"]", None)
+ self._split_subject_cache = (args[0]+u']', None)
else:
- self._split_subject_cache = (args[0]+u"]", args[1].strip())
+ self._split_subject_cache = (args[0]+u']', args[1].strip())
return self._split_subject_cache
def _subject_tag_type(self):
"""
@@ -414,15 +382,13 @@ class Message (object):
type = None
value = None
if tag == SUBJECT_TAG_NEW:
- type = u"new"
+ type = u'new'
elif tag == SUBJECT_TAG_CONTROL:
- type = u"control"
- elif tag == SUBJECT_TAG_XML:
- type = u"xml"
+ type = u'control'
else:
match = SUBJECT_TAG_COMMENT.match(tag)
if len(match.groups()) == 1:
- type = u"comment"
+ type = u'comment'
value = match.group(1)
return (type, value)
def validate_subject(self):
@@ -432,14 +398,14 @@ class Message (object):
tag,subject = self._split_subject()
if not tag.startswith(SUBJECT_TAG_START):
raise InvalidSubject(
- self, u"Subject must start with '%s'" % SUBJECT_TAG_START)
+ self, u'Subject must start with "%s"' % SUBJECT_TAG_START)
tag_type,value = self._subject_tag_type()
if tag_type == None:
- raise InvalidSubject(self, u"Invalid tag '%s'" % tag)
- elif tag_type == u"new" and len(subject) == 0:
- raise InvalidSubject(self, u"Cannot create a bug with blank title")
- elif tag_type == u"comment" and len(value) == 0:
- raise InvalidSubject(self, u"Must specify a bug ID to comment")
+ raise InvalidSubject(self, u'Invalid tag "%s"' % tag)
+ elif tag_type == u'new' and len(subject) == 0:
+ raise InvalidSubject(self, u'Cannot create a bug with blank title')
+ elif tag_type == u'comment' and len(value) == 0:
+ raise InvalidSubject(self, u'Must specify a bug ID to comment')
def _get_bodies_and_mime_types(self):
"""
Traverse the email message returning (body, mime_type) for
@@ -451,7 +417,7 @@ class Message (object):
continue
body,mime_type=(part.get_payload(decode=True),part.get_content_type())
charset = part.get_content_charset(msg_charset).lower()
- if mime_type.startswith("text/"):
+ if mime_type.startswith('text/'):
body = unicode(body, charset) # convert text types to unicode
yield (body, mime_type)
def _parse_body_pseudoheaders(self, body, required, optional,
@@ -471,15 +437,15 @@ class Message (object):
line = line.strip()
if len(line) == 0:
break
- if ":" not in line:
+ if ':' not in line:
raise InvalidPseudoheader(self, line)
- key,value = line.split(":", 1)
+ key,value = line.split(':', 1)
value = value.strip()
if key not in all:
raise InvalidPseudoHeader(self, key)
if len(value) == 0:
raise InvalidEmail(
- self, u"Blank value for: %s" % key)
+ self, u'Blank value for: %s' % key)
dictionary[key] = value
missing = []
for key in required:
@@ -487,9 +453,9 @@ class Message (object):
missing.append(key)
if len(missing) > 0:
raise InvalidPseudoHeader(self,
- u"Missing required pseudo-headers:\n%s"
- % u", ".join(missing))
- remaining_body = u"\n".join(body_lines[i:]).strip()
+ u'Missing required pseudo-headers:\n%s'
+ % u', '.join(missing))
+ remaining_body = u'\n'.join(body_lines[i:]).strip()
return (remaining_body, dictionary)
def _strip_footer(self, body):
body_lines = body.splitlines()
@@ -497,7 +463,7 @@ class Message (object):
if line.startswith(BREAK):
break
i += 1 # increment past the current valid line.
- return u"\n".join(body_lines[:i]).strip()
+ return u'\n'.join(body_lines[:i]).strip()
def parse(self):
"""
Parse the commands given in the email. Raises assorted
@@ -506,24 +472,22 @@ class Message (object):
"""
self.validate_subject()
tag_type,value = self._subject_tag_type()
- if tag_type == u"new":
+ if tag_type == u'new':
commands = self.parse_new()
- elif tag_type == u"comment":
+ elif tag_type == u'comment':
commands = self.parse_comment(value)
- elif tag_type == u"control":
+ elif tag_type == u'control':
commands = self.parse_control()
- elif tag_type == u"xml":
- commands = self.parse_xml()
else:
- raise Exception, u"Unrecognized tag type '%s'" % tag_type
+ raise Exception, u'Unrecognized tag type "%s"' % tag_type
return commands
def parse_new(self):
- command = u"new"
+ command = u'new'
tag,subject = self._split_subject()
summary = subject
- options = {u"Reporter": self.author_addr(),
- u"Confirm": self._yes_no(self.confirm),
- u"Subscribe": "no",
+ options = {u'Reporter': self.author_addr(),
+ u'Confirm': self._yes_no(self.confirm),
+ u'Subscribe': 'no',
}
body,mime_type = list(self._get_bodies_and_mime_types())[0]
comment_body,options = \
@@ -531,51 +495,54 @@ class Message (object):
NEW_REQUIRED_PSEUDOHEADERS,
NEW_OPTIONAL_PSEUDOHEADERS,
options)
- if options[u"Confirm"].lower() == "no":
+ if options[u'Confirm'].lower() == 'no':
self.confirm = False
- if options[u"Subscribe"].lower() == "yes" and self.confirm == True:
+ if options[u'Subscribe'].lower() == 'yes' and self.confirm == True:
# respond with the subscription format rather than the
# normal command-output format, because the subscription
# format is more user-friendly.
self.confirm = False
- args = [u"--reporter", options[u"Reporter"]]
+ args = [u'--reporter', options[u'Reporter']]
args.append(summary)
commands = [Command(self, command, args)]
id = ID(commands[0])
comment_body = self._strip_footer(comment_body)
if len(comment_body) > 0:
- command = u"comment"
- comment = u"Version: %s\n\n"%options[u"Version"] + comment_body
- args = [u"--author", self.author_addr(),
- u"--alt-id", self.message_id(),
- u"--content-type", mime_type]
+ command = u'comment'
+ comment = u'Version: %s\n\n'%options[u'Version'] + comment_body
+ args = [u'--author', self.author_addr(),
+ u'--alt-id', self.message_id(),
+ u'--content-type', mime_type]
args.append(id)
- args.append(u"-")
- commands.append(Command(self, u"comment", args, stdin=comment))
+ args.append(u'-')
+ commands.append(Command(self, u'comment', args, stdin=comment))
for key,value in options.items():
- if key in [u"Version", u"Reporter", u"Confirm"]:
+ if key in [u'Version', u'Reporter', u'Confirm']:
continue # we've already handled these options
command = key.lower()
- args = [id, value]
- if key == u"Subscribe":
- if value.lower() != "yes":
+ if key in [u'Depend', u'Tag', u'Target', u'Subscribe']:
+ args = [id, value]
+ else:
+ args = [value, id]
+ if key == u'Subscribe':
+ if value.lower() != 'yes':
continue
- args = ["--subscriber", self.author_addr(), id]
+ args = ['--subscriber', self.author_addr(), id]
commands.append(Command(self, command, args))
return commands
def parse_comment(self, bug_uuid):
- command = u"comment"
+ command = u'comment'
bug_id = bug_uuid
author = self.author_addr()
alt_id = self.message_id()
body,mime_type = list(self._get_bodies_and_mime_types())[0]
- if mime_type == "text/plain":
+ if mime_type == 'text/plain':
body = self._strip_footer(body)
content_type = mime_type
- args = [u"--author", author]
+ args = [u'--author', author]
if alt_id != None:
- args.extend([u"--alt-id", alt_id])
- args.extend([u"--content-type", content_type, bug_id, u"-"])
+ args.extend([u'--alt-id', alt_id])
+ args.extend([u'--content-type', content_type, bug_id, u'-'])
commands = [Command(self, command, args, stdin=body)]
return commands
def parse_control(self):
@@ -587,49 +554,46 @@ class Message (object):
continue
if line.startswith(BREAK):
break
+ if type(line) == types.UnicodeType:
+ # work around http://bugs.python.org/issue1170
+ line = line.encode('unicode escape')
fields = shlex.split(line)
+ if type(line) == types.UnicodeType:
+ # work around http://bugs.python.org/issue1170
+ for field in fields:
+ field = unicode(field, 'unicode escape')
command,args = (fields[0], fields[1:])
commands.append(Command(self, command, args))
if len(commands) == 0:
- raise InvalidEmail(self, u"No commands in control email.")
+ raise InvalidEmail(self, u'No commands in control email.')
return commands
- def parse_xml(self):
- command = u"import-xml"
- body,mime_type = list(self._get_bodies_and_mime_types())[0]
- if mime_type != "text/xml":
- raise InvalidEmail(self,
- u"Emails to %s must have MIME type 'text/xml', not '%s'."
- % (SUBJECT_TAG_XML, mime_type))
- args = [u"--add-only", u"-"]
- commands = [Command(self, command, args, stdin=body)]
- return commands
- def run(self):
+ def run(self, repo='.'):
self._begin_response()
commands = self.parse()
try:
- for command in commands:
+ for i,command in enumerate(commands):
command.run()
self._add_response(command.response_msg())
finally:
if AUTOCOMMIT == True:
tag,subject = self._split_subject()
- self.commit_command = Command(self, "commit", [subject])
+ self.commit_command = Command(self, 'commit', [subject])
self.commit_command.run()
if LOGFILE != None:
- LOGFILE.write(u"Autocommit:\n%s\n\n" %
+ LOGFILE.write(u'Autocommit:\n%s\n\n' %
send_pgp_mime.flatten(self.commit_command.response_msg(),
to_unicode=True))
def _begin_response(self):
tag,subject = self._split_subject()
- response_header = [u"From: %s" % THIS_ADDRESS,
- u"To: %s" % self.author_addr(),
- u"Date: %s" % libbe.utility.time_to_str(time.time()),
- u"Subject: %s Re: %s"%(SUBJECT_TAG_RESPONSE,subject)
+ response_header = [u'From: %s' % THIS_ADDRESS,
+ u'To: %s' % self.author_addr(),
+ u'Date: %s' % libbe.util.utility.time_to_str(time.time()),
+ u'Subject: %s Re: %s'%(SUBJECT_TAG_RESPONSE,subject)
]
if self.message_id() != None:
- response_header.append(u"In-reply-to: %s" % self.message_id())
+ response_header.append(u'In-reply-to: %s' % self.message_id())
self.response_header = \
- send_pgp_mime.header_from_text(text=u"\n".join(response_header))
+ send_pgp_mime.header_from_text(text=u'\n'.join(response_header))
self._response_messages = []
def _add_response(self, response_message):
self._response_messages.append(response_message)
@@ -645,22 +609,24 @@ class Message (object):
def subscriber_emails(self, previous_revision=None):
if previous_revision == None:
if AUTOCOMMIT != True: # no way to tell what's changed
- raise NotificationFailed("Autocommit dissabled")
+ raise NotificationFailed('Autocommit dissabled')
if len(self._response_messages) == 0:
- raise NotificationFailed("Initial email failed.")
+ raise NotificationFailed('Initial email failed.')
if self.commit_command.ret != 0:
# commit failed. Error already logged.
- raise NotificationFailed("Commit failed")
+ raise NotificationFailed('Commit failed')
- # read only bugdir.
- bd = libbe.bugdir.BugDir(from_disk=True,
- manipulate_encodings=False)
+ bd = UI.storage_callbacks.get_bugdir()
+ writeable = bd.storage.writeable
+ bd.storage.writeable = False
if bd.vcs.versioned == False: # no way to tell what's changed
- raise NotificationFailed("Not versioned")
+ bd.storage.writeable = writeable
+ raise NotificationFailed('Not versioned')
bd.load_all_bugs()
subscribers = subscribe.get_bugdir_subscribers(bd, THIS_SERVER)
if len(subscribers) == 0:
+ bd.storage.writeable = writeable
return []
for subscriber,subscriptions in subscribers.items():
subscribers[subscriber] = []
@@ -676,19 +642,20 @@ class Message (object):
emails = []
for subscriber,subscriptions in subscribers.items():
- header.replace_header("to", subscriber)
+ header.replace_header('to', subscriber)
report = diff.report_tree(subscriptions, diff_tree=DiffTree)
root = report.report_or_none()
if root != None:
emails.append(send_pgp_mime.attach_root(header, root))
if LOGFILE != None:
- LOGFILE.write(u"Preparing to notify %s of changes\n" % subscriber)
+ LOGFILE.write(u'Preparing to notify %s of changes\n' % subscriber)
+ bd.storage.writeable = writeable
return emails
def _get_before_and_after_bugdirs(self, bd, previous_revision=None):
if previous_revision == None:
commit_msg = self.commit_command.stdout
- assert commit_msg.startswith("Committed "), commit_msg
- after_revision = commit_msg[len("Committed "):]
+ assert commit_msg.startswith('Committed '), commit_msg
+ after_revision = commit_msg[len('Committed '):]
before_revision = bd.vcs.revision_id(-2)
else:
before_revision = previous_revision
@@ -704,32 +671,30 @@ class Message (object):
def _subscriber_header(self, bd, previous_revision=None):
root_dir = os.path.basename(bd.root)
if previous_revision == None:
- subject = "Changes to %s on %s by %s" \
+ subject = 'Changes to %s on %s by %s' \
% (root_dir, THIS_SERVER, self.author_addr())
else:
- subject = "Changes to %s on %s since revision %s" \
+ subject = 'Changes to %s on %s since revision %s' \
% (root_dir, THIS_SERVER, previous_revision)
- header = [u"From: %s" % THIS_ADDRESS,
- u"To: %s" % u"DUMMY-AUTHOR",
- u"Date: %s" % libbe.utility.time_to_str(time.time()),
- u"Subject: %s Re: %s" % (SUBJECT_TAG_RESPONSE, subject)
+ header = [u'From: %s' % THIS_ADDRESS,
+ u'To: %s' % u'DUMMY-AUTHOR',
+ u'Date: %s' % libbe.util.utility.time_to_str(time.time()),
+ u'Subject: %s Re: %s' % (SUBJECT_TAG_RESPONSE, subject)
]
- return send_pgp_mime.header_from_text(text=u"\n".join(header))
+ return send_pgp_mime.header_from_text(text=u'\n'.join(header))
-def generate_global_tags(tag_base=u"be-bug"):
+def generate_global_tags(tag_base=u'be-bug'):
"""
Generate a series of tags from a base tag string.
"""
global SUBJECT_TAG_BASE, SUBJECT_TAG_START, SUBJECT_TAG_RESPONSE, \
- SUBJECT_TAG_NEW, SUBJECT_TAG_COMMENT, SUBJECT_TAG_CONTROL, \
- SUBJECT_TAG_XML
+ SUBJECT_TAG_NEW, SUBJECT_TAG_COMMENT, SUBJECT_TAG_CONTROL
SUBJECT_TAG_BASE = tag_base
- SUBJECT_TAG_START = u"[%s" % tag_base
- SUBJECT_TAG_RESPONSE = u"[%s]" % tag_base
- SUBJECT_TAG_NEW = u"[%s:submit]" % tag_base
- SUBJECT_TAG_COMMENT = re.compile(u"\[%s:([\-0-9a-z]*)]" % tag_base)
+ SUBJECT_TAG_START = u'[%s' % tag_base
+ SUBJECT_TAG_RESPONSE = u'[%s]' % tag_base
+ SUBJECT_TAG_NEW = u'[%s:submit]' % tag_base
+ SUBJECT_TAG_COMMENT = re.compile(u'\[%s:([\-0-9a-z]*)]' % tag_base)
SUBJECT_TAG_CONTROL = SUBJECT_TAG_RESPONSE
- SUBJECT_TAG_XML = u"[%s:xml]" % tag_base
def open_logfile(logpath=None):
"""
@@ -741,27 +706,28 @@ def open_logfile(logpath=None):
"""
global LOGPATH, LOGFILE
if logpath != None:
- if logpath == u"-":
- LOGPATH = u"stderr"
+ if logpath == u'-':
+ LOGPATH = u'stderr'
LOGFILE = sys.stderr
- elif logpath == u"none":
- LOGPATH = u"none"
+ elif logpath == u'none':
+ LOGPATH = u'none'
LOGFILE = None
elif os.path.isabs(logpath):
LOGPATH = logpath
else:
LOGPATH = os.path.join(_THIS_DIR, logpath)
- if LOGFILE == None and LOGPATH != u"none":
- LOGFILE = codecs.open(LOGPATH, u"a+", ENCODING)
- LOGFILE.write(u"Default encoding: %s\n" % ENCODING)
+ if LOGFILE == None and LOGPATH != u'none':
+ LOGFILE = codecs.open(LOGPATH, u'a+',
+ libbe.utuil.encoding.get_filesystem_encoding())
def close_logfile():
- if LOGFILE != None and LOGPATH not in [u"stderr", u"none"]:
+ if LOGFILE != None and LOGPATH not in [u'stderr', u'none']:
LOGFILE.close()
+unitsuite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])
+suite = unittest.TestSuite([unitsuite, doctest.DocTestSuite()])
+
def test():
- unitsuite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])
- suite = unittest.TestSuite([unitsuite, doctest.DocTestSuite()])
result = unittest.TextTestRunner(verbosity=2).run(suite)
num_errors = len(result.errors)
num_failures = len(result.failures)
@@ -770,15 +736,15 @@ def test():
def main(args):
from optparse import OptionParser
- global AUTOCOMMIT, BE_DIR
+ global AUTOCOMMIT, UI
- usage="be-handle-mail [options]\n\n%s" % (__doc__)
+ usage='be-handle-mail [options]\n\n%s' % (__doc__)
parser = OptionParser(usage=usage)
- parser.add_option('-b', '--be-dir', dest='be_dir', default=BE_DIR,
- metavar="DIR",
- help='Select the BE directory to serve (%default).')
+ parser.add_option('-r', '--repo', dest='repo', default=_THIS_DIR,
+ metavar='REPO',
+ help='Select the BE repository to serve (%default).')
parser.add_option('-t', '--tag-base', dest='tag_base',
- default=SUBJECT_TAG_BASE, metavar="TAG",
+ default=SUBJECT_TAG_BASE, metavar='TAG',
help='Set the subject tag base (%default).')
parser.add_option('-o', '--output', dest='output', action='store_true',
help="Don't mail the generated message, print it to stdout instead. Useful for testing be-handle-mail functionality without the whole mail transfer agent and procmail setup.")
@@ -804,40 +770,44 @@ def main(args):
num_bad = 1
sys.exit(num_bad)
- BE_DIR = options.be_dir
AUTOCOMMIT = options.autocommit
if options.notify_since == None:
msg_text = sys.stdin.read()
- libbe.encoding.set_IO_stream_encodings(ENCODING) # _after_ reading message
open_logfile(options.logfile)
generate_global_tags(options.tag_base)
+ io = libbe.command.StringInputOutput()
+ UI = libbe.command.UserInterface(io, location=options.repo)
+
if options.notify_since != None:
if options.subscribers == True:
if LOGFILE != None:
- LOGFILE.write(u"Checking for subscribers to notify since revision %s\n"
+ LOGFILE.write(u'Checking for subscribers to notify since revision %s\n'
% options.notify_since)
try:
m = Message(disable_parsing=True)
emails = m.subscriber_emails(options.notify_since)
except NotificationFailed, e:
if LOGFILE != None:
- LOGFILE.write(unicode(e) + u"\n")
+ LOGFILE.write(unicode(e) + u'\n')
else:
for msg in emails:
if options.output == True:
print send_pgp_mime.flatten(msg, to_unicode=True)
else:
send_pgp_mime.mail(msg, send_pgp_mime.sendmail)
+ self.commit_command.cleanup()
close_logfile()
+ UI.cleanup()
sys.exit(0)
if len(msg_text.strip()) == 0: # blank email!?
if LOGFILE != None:
- LOGFILE.write(u"Blank email!\n")
+ LOGFILE.write(u'Blank email!\n')
close_logfile()
+ UI.cleanup()
sys.exit(1)
try:
m = Message(msg_text)
@@ -846,9 +816,10 @@ def main(args):
response = e.response()
except Exception, e:
if LOGFILE != None:
- LOGFILE.write(u"Uncaught exception:\n%s\n" % (e,))
+ LOGFILE.write(u'Uncaught exception:\n%s\n' % (e,))
traceback.print_tb(sys.exc_traceback, file=LOGFILE)
close_logfile()
+ UI.cleanup()
sys.exit(1)
else:
response = m.response_email()
@@ -856,21 +827,21 @@ def main(args):
print send_pgp_mime.flatten(response, to_unicode=True)
elif m.confirm == True:
if LOGFILE != None:
- LOGFILE.write(u"Sending response to %s\n" % m.author_addr())
- LOGFILE.write(u"\n%s\n\n" % send_pgp_mime.flatten(response,
+ LOGFILE.write(u'Sending response to %s\n' % m.author_addr())
+ LOGFILE.write(u'\n%s\n\n' % send_pgp_mime.flatten(response,
to_unicode=True))
send_pgp_mime.mail(response, send_pgp_mime.sendmail)
else:
if LOGFILE != None:
- LOGFILE.write(u"Response declined by %s\n" % m.author_addr())
+ LOGFILE.write(u'Response declined by %s\n' % m.author_addr())
if options.subscribers == True:
if LOGFILE != None:
- LOGFILE.write(u"Checking for subscribers\n")
+ LOGFILE.write(u'Checking for subscribers\n')
try:
emails = m.subscriber_emails()
except NotificationFailed, e:
if LOGFILE != None:
- LOGFILE.write(unicode(e) + u"\n")
+ LOGFILE.write(unicode(e) + u'\n')
else:
for msg in emails:
if options.output == True:
@@ -879,7 +850,7 @@ def main(args):
send_pgp_mime.mail(msg, send_pgp_mime.sendmail)
close_logfile()
-
+ UI.cleanup()
class GenerateGlobalTagsTestCase (unittest.TestCase):
def setUp(self):
@@ -901,41 +872,37 @@ class GenerateGlobalTagsTestCase (unittest.TestCase):
def test_restore_global_tags(self):
"Test global tag restoration by teardown function."
global SUBJECT_TAG_BASE
- self.failUnlessEqual(SUBJECT_TAG_BASE, u"be-bug")
- SUBJECT_TAG_BASE = "projectX-bug"
- self.failUnlessEqual(SUBJECT_TAG_BASE, u"projectX-bug")
+ self.failUnlessEqual(SUBJECT_TAG_BASE, u'be-bug')
+ SUBJECT_TAG_BASE = 'projectX-bug'
+ self.failUnlessEqual(SUBJECT_TAG_BASE, u'projectX-bug')
self.restore_global_tags()
- self.failUnlessEqual(SUBJECT_TAG_BASE, u"be-bug")
+ self.failUnlessEqual(SUBJECT_TAG_BASE, u'be-bug')
def test_subject_tag_base(self):
"Should set SUBJECT_TAG_BASE global correctly"
- generate_global_tags(u"projectX-bug")
- self.failUnlessEqual(SUBJECT_TAG_BASE, u"projectX-bug")
+ generate_global_tags(u'projectX-bug')
+ self.failUnlessEqual(SUBJECT_TAG_BASE, u'projectX-bug')
def test_subject_tag_start(self):
"Should set SUBJECT_TAG_START global correctly"
- generate_global_tags(u"projectX-bug")
- self.failUnlessEqual(SUBJECT_TAG_START, u"[projectX-bug")
+ generate_global_tags(u'projectX-bug')
+ self.failUnlessEqual(SUBJECT_TAG_START, u'[projectX-bug')
def test_subject_tag_response(self):
"Should set SUBJECT_TAG_RESPONSE global correctly"
- generate_global_tags(u"projectX-bug")
- self.failUnlessEqual(SUBJECT_TAG_RESPONSE, u"[projectX-bug]")
+ generate_global_tags(u'projectX-bug')
+ self.failUnlessEqual(SUBJECT_TAG_RESPONSE, u'[projectX-bug]')
def test_subject_tag_new(self):
"Should set SUBJECT_TAG_NEW global correctly"
- generate_global_tags(u"projectX-bug")
- self.failUnlessEqual(SUBJECT_TAG_NEW, u"[projectX-bug:submit]")
+ generate_global_tags(u'projectX-bug')
+ self.failUnlessEqual(SUBJECT_TAG_NEW, u'[projectX-bug:submit]')
def test_subject_tag_control(self):
"Should set SUBJECT_TAG_CONTROL global correctly"
- generate_global_tags(u"projectX-bug")
- self.failUnlessEqual(SUBJECT_TAG_CONTROL, u"[projectX-bug]")
+ generate_global_tags(u'projectX-bug')
+ self.failUnlessEqual(SUBJECT_TAG_CONTROL, u'[projectX-bug]')
def test_subject_tag_comment(self):
"Should set SUBJECT_TAG_COMMENT global correctly"
- generate_global_tags(u"projectX-bug")
- m = SUBJECT_TAG_COMMENT.match("[projectX-bug:xyz-123]")
+ generate_global_tags(u'projectX-bug')
+ m = SUBJECT_TAG_COMMENT.match('[projectX-bug:xyz-123]')
self.failUnlessEqual(len(m.groups()), 1)
- self.failUnlessEqual(m.group(1), u"xyz-123")
- def test_subject_tag_xml(self):
- "Should set SUBJECT_TAG_XML global correctly"
- generate_global_tags(u"projectX-bug")
- self.failUnlessEqual(SUBJECT_TAG_XML, u"[projectX-bug:xml]")
+ self.failUnlessEqual(m.group(1), u'xyz-123')
if __name__ == "__main__":
main(sys.argv)
diff --git a/interfaces/email/interactive/becommands b/interfaces/email/interactive/becommands
deleted file mode 120000
index 8af773c..0000000
--- a/interfaces/email/interactive/becommands
+++ /dev/null
@@ -1 +0,0 @@
-../../../becommands \ No newline at end of file
diff --git a/interfaces/gui/beg/beg b/interfaces/gui/beg/beg
deleted file mode 100755
index 55e537d..0000000
--- a/interfaces/gui/beg/beg
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/env python
-import table
-from Tkinter import *
-from libbe import bugdir
-
-tk = Tk()
-Label(tk, text="Bug list").pack()
-mlb = table.MultiListbox(tk, (('Severity', 4), ('Creator', 8), ('Summary', 40)))
-for bug in [b for b in bugdir.tree_root(".").list() if b.active]:
- mlb.insert(END, (bug.severity, bug.creator, bug.summary))
-mlb.pack(expand=YES,fill=BOTH)
-tk.mainloop()
diff --git a/interfaces/gui/beg/table.py b/interfaces/gui/beg/table.py
deleted file mode 100644
index 2865f28..0000000
--- a/interfaces/gui/beg/table.py
+++ /dev/null
@@ -1,97 +0,0 @@
-from Tkinter import *
-
-class MultiListbox(Frame):
- def __init__(self, master, lists):
- Frame.__init__(self, master)
- self.lists = []
- for l,w in lists:
- frame = Frame(self); frame.pack(side=LEFT, expand=YES, fill=BOTH)
- Label(frame, text=l, borderwidth=1, relief=RAISED).pack(fill=X)
- lb = Listbox(frame, width=w, borderwidth=0, selectborderwidth=0,
- relief=FLAT, exportselection=FALSE)
- lb.pack(expand=YES, fill=BOTH)
- self.lists.append(lb)
- lb.bind('<B1-Motion>', lambda e, s=self: s._select(e.y))
- lb.bind('<Button-1>', lambda e, s=self: s._select(e.y))
- lb.bind('<Leave>', lambda e: 'break')
- lb.bind('<B2-Motion>', lambda e, s=self: s._b2motion(e.x, e.y))
- lb.bind('<Button-2>', lambda e, s=self: s._button2(e.x, e.y))
- frame = Frame(self); frame.pack(side=LEFT, fill=Y)
- Label(frame, borderwidth=1, relief=RAISED).pack(fill=X)
- sb = Scrollbar(frame, orient=VERTICAL, command=self._scroll)
- sb.pack(expand=YES, fill=Y)
- self.lists[0]['yscrollcommand']=sb.set
-
- def _select(self, y):
- row = self.lists[0].nearest(y)
- self.selection_clear(0, END)
- self.selection_set(row)
- return 'break'
-
- def _button2(self, x, y):
- for l in self.lists: l.scan_mark(x, y)
- return 'break'
-
- def _b2motion(self, x, y):
- for l in self.lists: l.scan_dragto(x, y)
- return 'break'
-
- def _scroll(self, *args):
- for l in self.lists:
- apply(l.yview, args)
-
- def curselection(self):
- return self.lists[0].curselection()
-
- def delete(self, first, last=None):
- for l in self.lists:
- l.delete(first, last)
-
- def get(self, first, last=None):
- result = []
- for l in self.lists:
- result.append(l.get(first,last))
- if last: return apply(map, [None] + result)
- return result
-
- def index(self, index):
- self.lists[0].index(index)
-
- def insert(self, index, *elements):
- for e in elements:
- i = 0
- for l in self.lists:
- l.insert(index, e[i])
- i = i + 1
-
- def size(self):
- return self.lists[0].size()
-
- def see(self, index):
- for l in self.lists:
- l.see(index)
-
- def selection_anchor(self, index):
- for l in self.lists:
- l.selection_anchor(index)
-
- def selection_clear(self, first, last=None):
- for l in self.lists:
- l.selection_clear(first, last)
-
- def selection_includes(self, index):
- return self.lists[0].selection_includes(index)
-
- def selection_set(self, first, last=None):
- for l in self.lists:
- l.selection_set(first, last)
-
-if __name__ == '__main__':
- tk = Tk()
- Label(tk, text='MultiListbox').pack()
- mlb = MultiListbox(tk, (('Subject', 40), ('Sender', 20), ('Date', 10)))
- for i in range(1000):
- mlb.insert(END, ('Important Message: %d' % i, 'John Doe', '10/10/%04d' % (1900+i)))
- mlb.pack(expand=YES,fill=BOTH)
- tk.mainloop()
-
diff --git a/interfaces/gui/wxbe/wxbe b/interfaces/gui/wxbe/wxbe
deleted file mode 100755
index e71ae0c..0000000
--- a/interfaces/gui/wxbe/wxbe
+++ /dev/null
@@ -1,87 +0,0 @@
-#!/usr/bin/env python
-import wx
-from wx.lib.mixins.listctrl import ListCtrlAutoWidthMixin
-import sys, os.path
-from libbe import bugdir, names
-from libbe.bug import cmp_status, cmp_severity, cmp_time, cmp_full
-
-class MyApp(wx.App):
- def OnInit(self):
- frame = BugListFrame(None, title="Bug List")
- frame.Show(True)
- self.SetTopWindow(frame)
- return True
-
-class BugListFrame(wx.Frame):
- def __init__(self, *args, **kwargs):
- wx.Frame.__init__(self, *args, **kwargs)
- bugs = BugList(self)
-
- # Widgets to display/sort/edit will go in this panel
- # for now it is just a placeholder
- panel = wx.Panel(self)
- panel.SetBackgroundColour("RED")
-
- vbox = wx.BoxSizer(wx.VERTICAL)
- vbox.Add(panel, 0, wx.EXPAND)
- vbox.Add(bugs, 1, wx.EXPAND)
-
- self.SetAutoLayout(True)
- self.SetSizer(vbox)
- self.Layout()
-
-class BugList(wx.ListCtrl, ListCtrlAutoWidthMixin):
- def __init__(self, parent):
- wx.ListCtrl.__init__(self, parent,
- style=wx.LC_REPORT)
- ListCtrlAutoWidthMixin.__init__(self)
-
- self.bugdir = bugdir.tree_root(".")
- self.buglist = list(self.bugdir.list())
- self.buglist.sort()
- self.columns = ("id", "status", "severity", "summary")
-
- dataIndex = 0
- for x in range(len(self.columns)):
- self.InsertColumn(x, self.columns[x].capitalize())
- self.SetColumnWidth(x, wx.LIST_AUTOSIZE_USEHEADER)
- for bug in [b for b in self.buglist if b.active]:
- name = names.unique_name(bug, self.buglist)
- id = self.InsertStringItem(self.GetItemCount(), name)
- self.SetStringItem(id, 1, bug.status)
- self.SetStringItem(id, 2, bug.severity)
- self.SetStringItem(id, 3, bug.summary)
- self.SetItemData(id, dataIndex) # set keys for each line
- dataIndex += 1
- self.EnsureVisible(id)
- for x in range(len(self.columns)):
- self.SetColumnWidth(x, wx.LIST_AUTOSIZE)
- conts_width = self.GetColumnWidth(x)
- self.SetColumnWidth(x, wx.LIST_AUTOSIZE_USEHEADER)
- if conts_width > self.GetColumnWidth(x):
- self.SetColumnWidth(x, conts_width)
-
- self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColumnClick)
- self.bugcmp_fn = cmp_full
- # For reasons I don't understant, sorting is broken...
- #self.SortItems(self.Sorter)
- #self.Refresh()
- def Sorter(self, key1, key2):
- """Get bug info from the keys and pass to self.bugcmp_fn"""
- bug1 = self.buglist[key1-1]
- bug2 = self.buglist[key2-1]
- # Another way of getting bug information
- #bug1uuid = self.GetItem(key1, 0).GetText()
- #bug2uuid = self.GetItem(key2, 0).GetText()
- #print bug1uuid, bug2uuid
- #bug1 = self.bugdir.get_bug(bug1uuid)
- #bug2 = self.bugdir.get_bug(bug1uuid)
- print self.bugcmp_fn(bug1,bug2)
- return self.bugcmp_fn(bug1,bug2)
- def OnColumnClick(self, event):
- """Resort bug list depending on which column was clicked"""
- print "TODO: sort by column %d" % event.Column
- # change self.bugcmp_fn and resort, but I can't get it working
-
-app = MyApp()
-app.MainLoop()
diff --git a/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/Bugs-Everywhere-Web.egg-info/SOURCES.txt b/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/Bugs-Everywhere-Web.egg-info/SOURCES.txt
deleted file mode 100644
index def18b1..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/Bugs-Everywhere-Web.egg-info/SOURCES.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-README.txt
-setup.py
-start-beweb.py
-Bugs-Everywhere-Web.egg-info/PKG-INFO
-Bugs-Everywhere-Web.egg-info/SOURCES.txt
-Bugs-Everywhere-Web.egg-info/not-zip-safe
-Bugs-Everywhere-Web.egg-info/requires.txt
-Bugs-Everywhere-Web.egg-info/sqlobject.txt
-Bugs-Everywhere-Web.egg-info/top_level.txt
-beweb/__init__.py
-beweb/config.py
-beweb/controllers.py
-beweb/formatting.py
-beweb/model.py
-beweb/prest.py
-beweb/release.py
-beweb/config/__init__.py
-beweb/templates/__init__.py
-beweb/tests/__init__.py
-beweb/tests/test_controllers.py
-beweb/tests/test_model.py
-libbe/__init__.py
-libbe/arch.py
-libbe/bugdir.py
-libbe/bzr.py
-libbe/cmdutil.py
-libbe/config.py
-libbe/diff.py
-libbe/mapfile.py
-libbe/names.py
-libbe/no_rcs.py
-libbe/plugin.py
-libbe/rcs.py
-libbe/restconvert.py
-libbe/tests.py
-libbe/utility.py
diff --git a/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/Bugs-Everywhere-Web.egg-info/not-zip-safe b/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/Bugs-Everywhere-Web.egg-info/not-zip-safe
deleted file mode 100644
index e69de29..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/Bugs-Everywhere-Web.egg-info/not-zip-safe
+++ /dev/null
diff --git a/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/Bugs-Everywhere-Web.egg-info/requires.txt b/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/Bugs-Everywhere-Web.egg-info/requires.txt
deleted file mode 100644
index 88b15cb..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/Bugs-Everywhere-Web.egg-info/requires.txt
+++ /dev/null
@@ -1 +0,0 @@
-TurboGears >= 0.9a4 \ No newline at end of file
diff --git a/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/Bugs-Everywhere-Web.egg-info/sqlobject.txt b/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/Bugs-Everywhere-Web.egg-info/sqlobject.txt
deleted file mode 100644
index 7f7cbad..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/Bugs-Everywhere-Web.egg-info/sqlobject.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-db_module=beweb.model
-history_dir=$base/beweb/sqlobject-history
diff --git a/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/Bugs-Everywhere-Web.egg-info/top_level.txt b/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/Bugs-Everywhere-Web.egg-info/top_level.txt
deleted file mode 100644
index 6455be9..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/Bugs-Everywhere-Web.egg-info/top_level.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-beweb
-libbe
diff --git a/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/PKG-INFO b/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/PKG-INFO
deleted file mode 100644
index 6cb6ad2..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/PKG-INFO
+++ /dev/null
@@ -1,15 +0,0 @@
-Metadata-Version: 1.0
-Name: Bugs-Everywhere-Web
-Version: 1.0
-Summary: UNKNOWN
-Home-page: UNKNOWN
-Author: UNKNOWN
-Author-email: UNKNOWN
-License: UNKNOWN
-Description: UNKNOWN
-Platform: UNKNOWN
-Classifier: Development Status :: 3 - Alpha
-Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python
-Classifier: Topic :: Software Development :: Libraries :: Python Modules
-Classifier: Framework :: TurboGears
diff --git a/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/SOURCES.txt b/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/SOURCES.txt
deleted file mode 100644
index ab62ee4..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/SOURCES.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-README.txt
-setup.py
-start-beweb.py
-Bugs_Everywhere_Web.egg-info/PKG-INFO
-Bugs_Everywhere_Web.egg-info/SOURCES.txt
-Bugs_Everywhere_Web.egg-info/dependency_links.txt
-Bugs_Everywhere_Web.egg-info/not-zip-safe
-Bugs_Everywhere_Web.egg-info/paster_plugins.txt
-Bugs_Everywhere_Web.egg-info/requires.txt
-Bugs_Everywhere_Web.egg-info/sqlobject.txt
-Bugs_Everywhere_Web.egg-info/top_level.txt
-Bugs_Everywhere_Web.egg-info/Bugs-Everywhere-Web.egg-info/SOURCES.txt
-Bugs_Everywhere_Web.egg-info/Bugs-Everywhere-Web.egg-info/not-zip-safe
-Bugs_Everywhere_Web.egg-info/Bugs-Everywhere-Web.egg-info/requires.txt
-Bugs_Everywhere_Web.egg-info/Bugs-Everywhere-Web.egg-info/sqlobject.txt
-Bugs_Everywhere_Web.egg-info/Bugs-Everywhere-Web.egg-info/top_level.txt
-beweb/__init__.py
-beweb/config.py
-beweb/controllers.py
-beweb/formatting.py
-beweb/json.py
-beweb/model.py
-beweb/prest.py
-beweb/release.py
-beweb/config/__init__.py
-beweb/templates/__init__.py
-beweb/tests/__init__.py
-beweb/tests/test_controllers.py
-beweb/tests/test_model.py
-libbe/__init__.py
-libbe/arch.py
-libbe/bugdir.py
-libbe/bzr.py
-libbe/cmdutil.py
-libbe/config.py
-libbe/diff.py
-libbe/mapfile.py
-libbe/names.py
-libbe/no_rcs.py
-libbe/plugin.py
-libbe/rcs.py
-libbe/restconvert.py
-libbe/tests.py
-libbe/utility.py
diff --git a/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/dependency_links.txt b/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/dependency_links.txt
deleted file mode 100644
index 8b13789..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/dependency_links.txt
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/not-zip-safe b/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/not-zip-safe
deleted file mode 100644
index 8b13789..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/not-zip-safe
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/paster_plugins.txt b/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/paster_plugins.txt
deleted file mode 100644
index 14fec70..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/paster_plugins.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-TurboGears
-PasteScript
diff --git a/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/requires.txt b/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/requires.txt
deleted file mode 100644
index 5fd6f71..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/requires.txt
+++ /dev/null
@@ -1 +0,0 @@
-TurboGears >= 1.0b1 \ No newline at end of file
diff --git a/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/sqlobject.txt b/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/sqlobject.txt
deleted file mode 100644
index 7f7cbad..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/sqlobject.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-db_module=beweb.model
-history_dir=$base/beweb/sqlobject-history
diff --git a/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/top_level.txt b/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/top_level.txt
deleted file mode 100644
index 74a8358..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/Bugs_Everywhere_Web.egg-info/top_level.txt
+++ /dev/null
@@ -1 +0,0 @@
-beweb
diff --git a/interfaces/web/Bugs-Everywhere-Web/README b/interfaces/web/Bugs-Everywhere-Web/README
deleted file mode 100644
index c152757..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/README
+++ /dev/null
@@ -1,60 +0,0 @@
-Using BeWeb, the web UI
-=======================
-BeWeb uses the Turbogears framework: http://www.turbogears.org/
-Please ensure you have Turbogears 0.8a5 or a compatible release installed.
-Because it uses BE data, the web UI does not require a database.
-
-To use BeWeb, first create a configuration file, telling it which projects
-to track, and what to call them. An example configuration file
-(beweb/beweb/config.py.example) is provided.
-
-Next, cd to this directory, and run ./start-beweb.py
-
-BeWeb allows you to create, view and edit bugs, but it is in an early stage of
-development, so some features are missing.
-
-Configuration file
-------------------
-
-Configure by creating an appropriate beweb/config.py from
-beweb/config.py.example. The server will edit the repositories that
-it manages, so you should probably have it running on a seperate
-branch than your working repository. You can then merge/push
-as you require to keep the branches in sync.
-
-See
- http://docs.turbogears.org/1.0/Configuration
-For standard turbogears configuration information.
-
-Actions
--------
-
-Currently, you need to login for any methods with a
-@identity.require() decorator. The only group in the current
-implementation is 'editbugs'. Basically, anyone can browse around,
-but only registered 'editbugs' members can change things.
-
-Anonymous actions:
- * See project tree
- * See buglist
- * See comments
-Editbugs required actions:
- * Create new comments
- * Reply to comments
- * Update comment info
-
-Users
------
-
-All login attempts will fail unless you have added some valid users. See
- http://docs.turbogears.org/1.0/GettingStartedWithIdentity
-For a good intro. For the impatient, try something like
- Bugs-Everywhere-Web$ tg-admin toolbox
- browse to 'CatWalk' -> 'User' -> 'Add User+'
-or
- Bugs-Everywhere-Web$ tg-admin sholl
- >>> u = User(user_name=u'jdoe', email_address=u'jdoe@example.com',
- display_name=u'Jane Doe', password=u'xxx')
- >>> g = Group(group_name=u'editbugs', display_name=u'Edit Bugs')
- >>> g.addUser(u) # BE-Web uses SQLObject
-Exit the tg-admin shell with Ctrl-Z on MS Windows, Ctrl-D on other systems.
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/__init__.py b/interfaces/web/Bugs-Everywhere-Web/beweb/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/__init__.py
+++ /dev/null
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/app.cfg b/interfaces/web/Bugs-Everywhere-Web/beweb/app.cfg
deleted file mode 100644
index 024fa8a..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/app.cfg
+++ /dev/null
@@ -1,120 +0,0 @@
-[global]
-# The settings in this file should not vary depending on the deployment
-# environment. devcfg.py and prodcfg.py are the locations for
-# the different deployment settings. Settings in this file will
-# be overridden by settings in those other files.
-
-# The commented out values below are the defaults
-
-# VIEW
-
-# which view (template engine) to use if one is not specified in the
-# template name
-# tg.defaultview = "kid"
-
-# kid.outputformat="html"
-# kid.encoding="utf-8"
-
-# The sitetemplate is used for overall styling of a site that
-# includes multiple TurboGears applications
-# tg.sitetemplate="<packagename.templates.templatename>"
-
-# Allow every exposed function to be called as json,
-# tg.allow_json = False
-
-# Set to True if you'd like all of your pages to include MochiKit
-# tg.mochikit_all = False
-
-# VISIT TRACKING
-# Each visit to your application will be assigned a unique visit ID tracked via
-# a cookie sent to the visitor's browser.
-# --------------
-
-# Enable Visit tracking
-visit.on=True
-
-# Number of minutes a visit may be idle before it expires.
-# visit.timeout=20
-
-# The name of the cookie to transmit to the visitor's browser.
-# visit.cookie.name="tg-visit"
-
-# Domain name to specify when setting the cookie (must begin with . according to
-# RFC 2109). The default (None) should work for most cases and will default to
-# the machine to which the request was made. NOTE: localhost is NEVER a valid
-# value and will NOT WORK.
-# visit.cookie.domain=None
-
-# Specific path for the cookie
-# visit.cookie.path="/"
-
-# The name of the VisitManager plugin to use for visitor tracking.
-# visit.manager="sqlobject"
-
-
-# IDENTITY
-# General configuration of the TurboGears Identity management module
-# --------
-
-# Switch to turn on or off the Identity management module
-identity.on=True
-
-# [REQUIRED] URL to which CherryPy will internally redirect when an access
-# control check fails. If Identity management is turned on, a value for this
-# option must be specified.
-identity.failure_url="/login"
-
-# The IdentityProvider to use -- defaults to the SqlObjectIdentityProvider which
-# pulls User, Group, and Permission data out of your model database.
-identity.provider="sqlobject"
-
-# The names of the fields on the login form containing the visitor's user ID
-# and password. In addition, the submit button is specified simply so its
-# existence may be stripped out prior to passing the form data to the target
-# controller.
-identity.form.user_name="user_name"
-identity.form.password="password"
-identity.form.submit="login"
-
-# What sources should the identity provider consider when determining the
-# identity associated with a request? Comma separated list of identity sources.
-# Valid sources: form, visit, http_auth
-identity.source="form,http_auth,visit"
-
-
-# SqlObjectIdentityProvider
-# Configuration options for the default IdentityProvider
-# -------------------------
-
-# The classes you wish to use for your Identity model. Leave these commented out
-# to use the default classes for SqlObjectIdentityProvider. Or set them to the
-# classes in your model. NOTE: These aren't TG_* because the TG prefix is
-# reserved for classes created by TurboGears.
-# identity.soprovider.model.user="beweb.model.User"
-# identity.soprovider.model.group="beweb.model.Group"
-# identity.soprovider.model.permission="beweb.model.Permission"
-
-# The password encryption algorithm used when comparing passwords against what's
-# stored in the database. Valid values are 'md5' or 'sha1'. If you do not
-# specify an encryption algorithm, passwords are expected to be clear text.
-#
-# The SqlObjectProvider *will* encrypt passwords supplied as part of your login
-# form. If you set the password through the password property, like:
-# my_user.password = 'secret'
-# the password will be encrypted in the database, provided identity is up and
-# running, or you have loaded the configuration specifying what encryption to
-# use (in situations where identity may not yet be running, like tests).
-
-# identity.soprovider.encryption_algorithm=None
-
-[/static]
-static_filter.on = True
-static_filter.dir = "."
-
-[/favicon.ico]
-static_filter.on = True
-static_filter.file = "images/favicon.ico"
-
-[/]
-decodingFilter.on = True
-static_filter.root = '%(package_dir)s/static'
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/config.py.example b/interfaces/web/Bugs-Everywhere-Web/beweb/config.py.example
deleted file mode 100644
index 8745c6d..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/config.py.example
+++ /dev/null
@@ -1,10 +0,0 @@
-# This is an example beweb configuration file.
-
-# One thing we need is a map of projects. Projects have a beweb ID, a path,
-# and a display name.
-
-# In this example, the 'be' beweb ID is assigned the display name "Bugs
-# Everywhere" and the path "/home/abentley/be"
-
-projects = {"be": ("Bugs Everywhere","/home/abentley/be"),
- }
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/config/app.cfg b/interfaces/web/Bugs-Everywhere-Web/beweb/config/app.cfg
deleted file mode 100644
index 15555b7..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/config/app.cfg
+++ /dev/null
@@ -1,92 +0,0 @@
-[global]
-# The settings in this file should not vary depending on the deployment
-# environment. dev.cfg and prod.cfg are the locations for
-# the different deployment settings. Settings in this file will
-# be overridden by settings in those other files.
-
-# The commented out values below are the defaults
-
-# VIEW
-
-# which view (template engine) to use if one is not specified in the
-# template name
-# tg.defaultview = "kid"
-
-# The following kid settings determine the settings used by the kid serializer.
-
-# One of (html|xml|json)
-# kid.outputformat="html"
-
-# kid.encoding="utf-8"
-
-# The sitetemplate is used for overall styling of a site that
-# includes multiple TurboGears applications
-# tg.sitetemplate="<packagename.templates.templatename>"
-
-# Allow every exposed function to be called as json,
-# tg.allow_json = False
-
-# List of Widgets to include on every page.
-# for exemple ['turbogears.mochikit']
-# tg.include_widgets = []
-
-# Set to True if the scheduler should be started
-# tg.scheduler = False
-
-# IDENTITY
-# General configuration of the TurboGears Identity management module
-# --------
-
-# Switch to turn on or off the Identity management module
-identity.on=True
-
-# [REQUIRED] URL to which CherryPy will internally redirect when an access
-# control check fails. If Identity management is turned on, a value for this
-# option must be specified.
-identity.failure_url="/login"
-
-# identity.provider='sqlobject'
-
-# The names of the fields on the login form containing the visitor's user ID
-# and password. In addition, the submit button is specified simply so its
-# existence may be stripped out prior to passing the form data to the target
-# controller.
-# identity.form.user_name="user_name"
-# identity.form.password="password"
-# identity.form.submit="login"
-
-# What sources should the identity provider consider when determining the
-# identity associated with a request? Comma separated list of identity sources.
-# Valid sources: form, visit, http_auth
-# identity.source="form,http_auth,visit"
-
-# SqlObjectIdentityProvider
-# Configuration options for the default IdentityProvider
-# -------------------------
-
-# The classes you wish to use for your Identity model. Remember to not use reserved
-# SQL keywords for class names (at least unless you specify a different table
-# name using sqlmeta).
-identity.soprovider.model.user="stfa.model.User"
-identity.soprovider.model.group="stfa.model.Group"
-identity.soprovider.model.permission="stfa.model.Permission"
-
-# The password encryption algorithm used when comparing passwords against what's
-# stored in the database. Valid values are 'md5' or 'sha1'. If you do not
-# specify an encryption algorithm, passwords are expected to be clear text.
-# The SqlObjectProvider *will* encrypt passwords supplied as part of your login
-# form. If you set the password through the password property, like:
-# my_user.password = 'secret'
-# the password will be encrypted in the database, provided identity is up and
-# running, or you have loaded the configuration specifying what encryption to
-# use (in situations where identity may not yet be running, like tests).
-
-# identity.soprovider.encryption_algorithm=None
-
-[/static]
-static_filter.on = True
-static_filter.dir = "%(top_level_dir)s/static"
-
-[/favicon.ico]
-static_filter.on = True
-static_filter.file = "%(top_level_dir)s/static/images/favicon.ico"
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/config/log.cfg b/interfaces/web/Bugs-Everywhere-Web/beweb/config/log.cfg
deleted file mode 100644
index ce776f8..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/config/log.cfg
+++ /dev/null
@@ -1,29 +0,0 @@
-# LOGGING
-# Logging is often deployment specific, but some handlers and
-# formatters can be defined here.
-
-[logging]
-[[formatters]]
-[[[message_only]]]
-format='*(message)s'
-
-[[[full_content]]]
-format='*(asctime)s *(name)s *(levelname)s *(message)s'
-
-[[handlers]]
-[[[debug_out]]]
-class='StreamHandler'
-level='DEBUG'
-args='(sys.stdout,)'
-formatter='full_content'
-
-[[[access_out]]]
-class='StreamHandler'
-level='INFO'
-args='(sys.stdout,)'
-formatter='message_only'
-
-[[[error_out]]]
-class='StreamHandler'
-level='ERROR'
-args='(sys.stdout,)'
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/controllers.py b/interfaces/web/Bugs-Everywhere-Web/beweb/controllers.py
deleted file mode 100644
index 50cc754..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/controllers.py
+++ /dev/null
@@ -1,240 +0,0 @@
-import logging
-
-import cherrypy
-import turbogears
-from turbogears import controllers, expose, validate, redirect, identity
-
-from libbe.bugdir import tree_root, NoRootEntry
-from config import projects
-from prest import PrestHandler, provide_action
-
-
-from beweb import json
-
-log = logging.getLogger("beweb.controllers")
-
-def project_tree(project):
- try:
- return tree_root(projects[project][1])
- except KeyError:
- raise Exception("Unknown project %s" % project)
-
-def comment_url(project, bug, comment, **kwargs):
- return turbogears.url("/project/%s/bug/%s/comment/%s" %
- (project, bug, comment), kwargs)
-
-class Comment(PrestHandler):
- @identity.require( identity.has_permission("editbugs"))
- @provide_action("action", "New comment")
- def new_comment(self, comment_data, comment, *args, **kwargs):
- bug_tree = project_tree(comment_data['project'])
- bug = bug_tree.get_bug(comment_data['bug'])
- comment = new_comment(bug, "")
- comment.From = identity.current.user.userId
- comment.content_type = "text/restructured"
- comment.save()
- raise cherrypy.HTTPRedirect(comment_url(comment=comment.uuid,
- **comment_data))
-
- @identity.require( identity.has_permission("editbugs"))
- @provide_action("action", "Reply")
- def reply_comment(self, comment_data, comment, *args, **kwargs):
- bug_tree = project_tree(comment_data['project'])
- bug = bug_tree.get_bug(comment_data['bug'])
- reply_comment = new_comment(bug, "")
- reply_comment.From = identity.current.user.userId
- reply_comment.in_reply_to = comment.uuid
- reply_comment.save()
- reply_data = dict(comment_data)
- del reply_data["comment"]
- raise cherrypy.HTTPRedirect(comment_url(comment=reply_comment.uuid,
- **reply_data))
-
- @identity.require( identity.has_permission("editbugs"))
- @provide_action("action", "Update")
- def update(self, comment_data, comment, comment_body, *args, **kwargs):
- comment.body = comment_body
- comment.save()
- raise cherrypy.HTTPRedirect(bug_url(comment_data['project'],
- comment_data['bug']))
-
- def instantiate(self, project, bug, comment):
- bug_tree = project_tree(project)
- bug = bug_tree.get_bug(bug)
- return bug.get_comment(comment)
-
- def dispatch(self, comment_data, comment, *args, **kwargs):
- return self.edit_comment(comment_data['project'], comment)
-
- @turbogears.expose(html="beweb.templates.edit_comment")
- def edit_comment(self, project, comment):
- return {"comment": comment, "project_id": project}
-
-class Bug(PrestHandler):
- comment = Comment()
- @turbogears.expose(html="beweb.templates.edit_bug")
- def index(self, project, bug):
- return {"bug": bug, "project_id": project}
-
- def dispatch(self, bug_data, bug, *args, **kwargs):
- if bug is None:
- return self.list(bug_data['project'], **kwargs)
- else:
- return self.index(bug_data['project'], bug)
-
- @turbogears.expose(html="beweb.templates.bugs")
- def list(self, project, sort_by=None, show_closed=False, action=None,
- search=None):
- if action == "New bug":
- self.new_bug()
- if show_closed == "False":
- show_closed = False
- bug_tree = project_tree(project)
- bugs = list(bug_tree.list())
- if sort_by is None:
- bugs.sort()
- return {"project_id" : project,
- "project_name" : projects[project][0],
- "bugs" : bugs,
- "show_closed" : show_closed,
- "search" : search,
- }
-
- @identity.require( identity.has_permission("editbugs"))
- @provide_action("action", "New bug")
- def new_bug(self, bug_data, bug, **kwargs):
- bug = project_tree(bug_data['project']).new_bug()
- bug.creator = identity.current.user.userId
- bug.save()
- raise cherrypy.HTTPRedirect(bug_url(bug_data['project'], bug.uuid))
-
- @identity.require( identity.has_permission("editbugs"))
- @provide_action("action", "Update")
- def update(self, bug_data, bug, status, severity, summary, assigned,
- action):
- bug.status = status
- bug.severity = severity
- bug.summary = summary
- if assigned == "":
- assigned = None
- bug.assigned = assigned
- bug.save()
-# bug.vcs.precommit(bug.path)
-# bug.vcs.commit(bug.path, "Auto-commit")
-# bug.vcs.postcommit(bug.path)
- raise cherrypy.HTTPRedirect(bug_list_url(bug_data["project"]))
-
- def instantiate(self, project, bug):
- return project_tree(project).get_bug(bug)
-
- @provide_action("action", "New comment")
- def new_comment(self, bug_data, bug, *args, **kwargs):
- try:
- self.update(bug_data, bug, *args, **kwargs)
- except cherrypy.HTTPRedirect:
- pass
- return self.comment.new_comment(bug_data, comment=None, *args,
- **kwargs)
-
-
-def project_url(project_id=None):
- project_url = "/project/"
- if project_id is not None:
- project_url += "%s/" % project_id
- return turbogears.url(project_url)
-
-def bug_url(project_id, bug_uuid=None):
- bug_url = "/project/%s/bug/" % project_id
- if bug_uuid is not None:
- bug_url += "%s/" % bug_uuid
- return turbogears.url(bug_url)
-
-def bug_list_url(project_id, show_closed=False, search=None):
- bug_url = "/project/%s/bug/?show_closed=%s" % (project_id,
- str(show_closed))
- if search is not None:
- bug_url = "%s&search=%s" % (bug_url, search)
- return turbogears.url(str(bug_url))
-
-
-class Project(PrestHandler):
- bug = Bug()
- @turbogears.expose(html="beweb.templates.projects")
- def dispatch(self, project_data, project, *args, **kwargs):
- if project is not None:
- raise cherrypy.HTTPRedirect(bug_url(project))
- else:
- return {"projects": projects}
-
- def instantiate(self, project):
- return project
-
-
-class Root(controllers.Root):
- prest = PrestHandler()
- prest.project = Project()
- @turbogears.expose()
- def index(self):
- raise cherrypy.HTTPRedirect(project_url())
-
- @expose(template="beweb.templates.login")
- def login(self, forward_url=None, previous_url=None, *args, **kw):
-
- if not identity.current.anonymous and identity.was_login_attempted():
- raise redirect(forward_url)
-
- forward_url=None
- previous_url= cherrypy.request.path
-
- if identity.was_login_attempted():
- msg=_("The credentials you supplied were not correct or "\
- "did not grant access to this resource.")
- elif identity.get_identity_errors():
- msg=_("You must provide your credentials before accessing "\
- "this resource.")
- else:
- msg=_("Please log in.")
- forward_url= cherrypy.request.headers.get("Referer", "/")
- cherrypy.response.status=403
- return dict(message=msg, previous_url=previous_url, logging_in=True,
- original_parameters=cherrypy.request.params,
- forward_url=forward_url)
-
- @expose()
- def logout(self):
- identity.current.logout()
- raise redirect("/")
-
- @turbogears.expose('beweb.templates.about')
- def about(self, *paths, **kwargs):
- return {}
-
- @turbogears.expose()
- def default(self, *args, **kwargs):
- return self.prest.default(*args, **kwargs)
-
- def _cp_on_error(self):
- import traceback, StringIO
- bodyFile = StringIO.StringIO()
- traceback.print_exc(file = bodyFile)
- trace_text = bodyFile.getvalue()
- try:
- raise
- except cherrypy.NotFound:
- self.handle_error('Not Found', str(e), trace_text, '404 Not Found')
-
- except NoRootEntry, e:
- self.handle_error('Project Misconfiguration', str(e), trace_text)
-
- except Exception, e:
- self.handle_error('Internal server error', str(e), trace_text)
-
- def handle_error(self, heading, body, traceback=None,
- status='500 Internal Server Error'):
- cherrypy.response.headerMap['Status'] = status
- cherrypy.response.body = [self.errorpage(heading, body, traceback)]
-
-
- @turbogears.expose(html='beweb.templates.error')
- def errorpage(self, heading, body, traceback):
- return {'heading': heading, 'body': body, 'traceback': traceback}
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/formatting.py b/interfaces/web/Bugs-Everywhere-Web/beweb/formatting.py
deleted file mode 100644
index 1278414..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/formatting.py
+++ /dev/null
@@ -1,76 +0,0 @@
-from StringIO import StringIO
-
-try :
- from xml.etree.ElementTree import XML # Python 2.5 (and greater?)
-except ImportError :
- from elementtree.ElementTree import XML
-from libbe.restconvert import rest_xml
-
-def to_unix(text):
- skip_newline = False
- for ch in text:
- if ch not in ('\r', '\n'):
- yield ch
- else:
- if ch == '\n':
- if skip_newline:
- continue
- else:
- skip_newline = True
- yield '\n'
-
-
-def soft_text(text):
- first_space = False
- translations = {'\n': '<br />\n', '&': '&amp;', '\x3c': '&lt;',
- '\x3e': '&gt;'}
- for ch in to_unix(text):
- if ch == ' ' and first_space is True:
- yield '&#160;'
- first_space = ch in (' ')
- try:
- yield translations[ch]
- except KeyError:
- yield ch
-
-
-def soft_pre(text):
- return XML('<div style="font-family: monospace">'+
- ''.join(soft_text(text)).encode('utf-8')+'</div>')
-
-
-def get_rest_body(rest):
- xml, warnings = rest_xml(StringIO(rest))
- return xml.find('{http://www.w3.org/1999/xhtml}body'), warnings
-
-
-def comment_body_xhtml(comment):
- if comment.content_type == "text/restructured":
- return get_rest_body(comment.body)[0]
- else:
- return soft_pre(comment.body)
-
-
-def select_among(name, options, default, display_names=None):
- output = ['<select name="%s">' % name]
- for option in options:
- if option == default:
- selected = ' selected="selected"'
- else:
- selected = ""
- if display_names is None:
- display_name = None
- else:
- display_name = display_names.get(option)
-
- if option is None:
- option = ""
- if display_name is None:
- display_name = option
- value = ""
- else:
- value = ' value="%s"' % option
- output.append("<option%s%s>%s</option>" % (selected, value,
- display_name))
- output.append("</select>")
- return XML("".join(output))
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/json.py b/interfaces/web/Bugs-Everywhere-Web/beweb/json.py
deleted file mode 100644
index 6e100c3..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/json.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# This module provides helper functions for the JSON part of your
-# view, if you are providing a JSON-based API for your app.
-
-# Here's what most rules would look like:
-# @jsonify.when("isinstance(obj, YourClass)")
-# def jsonify_yourclass(obj):
-# return [obj.val1, obj.val2]
-#
-# The goal is to break your objects down into simple values:
-# lists, dicts, numbers and strings
-
-from turbojson.jsonify import jsonify
-
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/model.py b/interfaces/web/Bugs-Everywhere-Web/beweb/model.py
deleted file mode 100644
index aa4b6b6..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/model.py
+++ /dev/null
@@ -1,107 +0,0 @@
-from datetime import datetime
-
-from sqlobject import *
-from turbogears.database import PackageHub
-from turbogears import identity
-
-hub = PackageHub("beweb")
-__connection__ = hub
-
-class Visit(SQLObject):
- class sqlmeta:
- table = "visit"
-
- visit_key = StringCol(length=40, alternateID=True,
- alternateMethodName="by_visit_key")
- created = DateTimeCol(default=datetime.now)
- expiry = DateTimeCol()
-
- def lookup_visit(cls, visit_key):
- try:
- return cls.by_visit_key(visit_key)
- except SQLObjectNotFound:
- return None
- lookup_visit = classmethod(lookup_visit)
-
-class VisitIdentity(SQLObject):
- visit_key = StringCol(length=40, alternateID=True,
- alternateMethodName="by_visit_key")
- user_id = IntCol()
-
-
-class Group(SQLObject):
- """
- An ultra-simple group definition.
- """
-
- # names like "Group", "Order" and "User" are reserved words in SQL
- # so we set the name to something safe for SQL
- class sqlmeta:
- table = "tg_group"
-
- group_name = UnicodeCol(length=16, alternateID=True,
- alternateMethodName="by_group_name")
- display_name = UnicodeCol(length=255)
- created = DateTimeCol(default=datetime.now)
-
- # collection of all users belonging to this group
- users = RelatedJoin("User", intermediateTable="user_group",
- joinColumn="group_id", otherColumn="user_id")
-
- # collection of all permissions for this group
- permissions = RelatedJoin("Permission", joinColumn="group_id",
- intermediateTable="group_permission",
- otherColumn="permission_id")
-
-
-class User(SQLObject):
- """
- Reasonably basic User definition. Probably would want additional attributes.
- """
- # names like "Group", "Order" and "User" are reserved words in SQL
- # so we set the name to something safe for SQL
- class sqlmeta:
- table = "tg_user"
-
- child_name = UnicodeCol(length=255)
- user_name = UnicodeCol(length=16, alternateID=True,
- alternateMethodName="by_user_name")
- email_address = UnicodeCol(length=255, alternateID=True,
- alternateMethodName="by_email_address")
- display_name = UnicodeCol(length=255)
- password = UnicodeCol(length=40)
- created = DateTimeCol(default=datetime.now)
-
- # groups this user belongs to
- groups = RelatedJoin("Group", intermediateTable="user_group",
- joinColumn="user_id", otherColumn="group_id")
-
- def _get_permissions(self):
- perms = set()
- for g in self.groups:
- perms = perms | set(g.permissions)
- return perms
-
- def _set_password(self, cleartext_password):
- "Runs cleartext_password through the hash algorithm before saving."
- hash = identity.encrypt_password(cleartext_password)
- self._SO_set_password(hash)
-
- def set_password_raw(self, password):
- "Saves the password as-is to the database."
- self._SO_set_password(password)
-
-
-
-class Permission(SQLObject):
- permission_name = UnicodeCol(length=16, alternateID=True,
- alternateMethodName="by_permission_name")
- description = UnicodeCol(length=255)
-
- groups = RelatedJoin("Group",
- intermediateTable="group_permission",
- joinColumn="permission_id",
- otherColumn="group_id")
-
-def people_map():
- return dict((u.user_name, u.display_name) for u in User.select())
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/prest.py b/interfaces/web/Bugs-Everywhere-Web/beweb/prest.py
deleted file mode 100644
index 9a6505d..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/prest.py
+++ /dev/null
@@ -1,168 +0,0 @@
-from unittest import TestCase
-import unittest
-from cherrypy import NotFound
-"""A pseudo-REST dispatching method in which only the noun comes from the path.
-The action performed will depend on kwargs.
-"""
-
-class AmbiguousAction(Exception):
- def __init__(self, actions):
- Exception.__init__(self, "Supplied action is ambiguous.")
- self.actions = actions
-
-
-def provide_action(name, value):
- def provider(func):
- func._action_desc = (name, value)
- return func
- return provider
-
-class PrestHandler(object):
- def __init__(self):
- object.__init__(self)
- self.actions = {}
- for member in (getattr(self, m) for m in dir(self)):
- if not hasattr(member, '_action_desc'):
- continue
- name, value = member._action_desc
- if name not in self.actions:
- self.actions[name] = {}
- self.actions[name][value] = member
-
- @classmethod
- def add_action(klass, name, value, function):
- if name not in klass.actions:
- klass.actions[name] = {}
- klass.actions[name][value] = function
-
-
- def decode(self, path, data=None):
- """Convert the path into a handler, a resource, data, and extra_path"""
- if data is None:
- data = {}
- if len(path) < 2 or not (hasattr(self, path[1])):
- if len(path) == 0:
- resource = None
- else:
- try:
- resource = self.instantiate(**data)
- except NotImplementedError, e:
- if e.args[0] is not PrestHandler.instantiate:
- raise NotFound()
-
- return self, resource, data, path[1:]
- if len(path) > 2:
- data[path[1]] = path[2]
- return getattr(self, path[1]).decode(path[2:], data)
-
- def instantiate(self, **date):
- raise NotImplementedError(PrestHandler.instantiate)
-
- def default(self, *args, **kwargs):
- child, resource, data, extra = self.decode([None,] + list(args))
- action = child.get_action(**kwargs)
- new_args = ([data, resource]+extra)
- if action is not None:
- return action(*new_args, **kwargs)
- else:
- return child.dispatch(*new_args, **kwargs)
-
- def get_action(self, **kwargs):
- """Return the action requested by kwargs, if any.
-
- Raises AmbiguousAction if more than one action matches.
- """
- actions = []
- for key in kwargs:
- if key in self.actions:
- if kwargs[key] in self.actions[key]:
- actions.append(self.actions[key][kwargs[key]])
- if len(actions) == 0:
- return None
- elif len(actions) == 1:
- return actions[0]
- else:
- raise AmbiguousAction(actions)
-
-
-class PrestTester(TestCase):
- def test_decode(self):
- class ProjectHandler(PrestHandler):
- actions = {}
- def dispatch(self, project_data, project, *args, **kwargs):
- self.project_id = project_data['project']
- self.project_data = project_data
- self.resource = project
- self.args = args
- self.kwargs = kwargs
-
- def instantiate(self, project):
- return [project]
-
- @provide_action('action', 'Save')
- def save(self, project_data, project, *args, **kwargs):
- self.action = "save"
-
- @provide_action('behavior', 'Update')
- def update(self, project_data, project, *args, **kwargs):
- self.action = "update"
-
- foo = PrestHandler()
- foo.project = ProjectHandler()
- handler, resource, data, extra = foo.decode([None, 'project', '83',
- 'bloop', 'yeah'])
- assert handler is foo.project
- self.assertEqual({'project': '83'}, data)
- self.assertEqual(['bloop', 'yeah'], extra)
- foo.default(*['project', '27', 'extra'], **{'a':'b', 'b':'97'})
- self.assertEqual(foo.project.args, ('extra',))
- self.assertEqual(foo.project.kwargs, {'a':'b', 'b':'97'})
- self.assertEqual(foo.project.project_data, {'project': '27'})
- self.assertEqual(foo.project.resource, ['27'])
- foo.default(*['project', '27', 'extra'], **{'action':'Save', 'b':'97'})
- self.assertEqual(foo.project.action, 'save')
- foo.default(*['project', '27', 'extra'],
- **{'behavior':'Update', 'b':'97'})
- self.assertEqual(foo.project.action, 'update')
- self.assertRaises(AmbiguousAction, foo.default,
- *['project', '27', 'extra'],
- **{'behavior':'Update', 'action':'Save', 'b':'97'})
-
- class BugHandler(PrestHandler):
- actions = {}
- def dispatch(self, bug_data, bug, *args, **kwargs):
- self.project_id = project_data['project']
- self.project_data = project_data
- self.resource = project
- self.args = args
- self.kwargs = kwargs
-
- def instantiate(self, project, bug):
- return [project, bug]
-
- @provide_action('action', 'Save')
- def save(self, project_data, project, *args, **kwargs):
- self.action = "save"
-
- @provide_action('behavior', 'Update')
- def update(self, project_data, project, *args, **kwargs):
- self.action = "update"
-
- foo.project.bug = BugHandler()
- handler, resource, data, extra = foo.decode([None, 'project', '83',
- 'bug', '92'])
- assert handler is foo.project.bug
- self.assertEqual(resource[0], '83')
- self.assertEqual(resource[1], '92')
- self.assertEqual([], extra)
- self.assertEqual(data['project'], '83')
- self.assertEqual(data['bug'], '92')
-
-def test():
- patchesTestSuite = unittest.makeSuite(PrestTester,'test')
- runner = unittest.TextTestRunner(verbosity=0)
- return runner.run(patchesTestSuite)
-
-
-if __name__ == "__main__":
- test()
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/release.py b/interfaces/web/Bugs-Everywhere-Web/beweb/release.py
deleted file mode 100644
index 9d64bf7..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/release.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Release information about Bugs-Everywhere-Web
-
-version = "1.0"
-
-# description = "Your plan to rule the world"
-# long_description = "More description about your plan"
-# author = "Your Name Here"
-# email = "YourEmail@YourDomain"
-# copyright = "Vintage 2006 - a good year indeed"
-
-# if it's open source, you might want to specify these
-# url = "http://yourcool.site/"
-# download_url = "http://yourcool.site/download"
-# license = "MIT"
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/css/style.css b/interfaces/web/Bugs-Everywhere-Web/beweb/static/css/style.css
deleted file mode 100644
index 6fe197f..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/css/style.css
+++ /dev/null
@@ -1,116 +0,0 @@
-table
-{
- background-color: black;
-}
-td
-{
- background-color: white;
-}
-h1
-{
- font-family: "Verdana";
- font-weight: bold;
- font-size: 120%;
- margin-bottom:0;
- color: #990;
-}
-
-tr.closed td
-{
- background-color: #ccc;
-}
-tr.closedeven td
-{
- background-color: #ccc;
-}
-tr.closedodd td
-{
- background-color: #dda;
-}
-
-a:visited, a:link
-{
- color: #990;
- text-decoration: None;
-}
-td a:visited, td a:link
-{
- display: block;
-}
-a:visited:hover, a:link:hover
-{
- text-decoration: underline;
-}
-td a:visited:hover, td a:link:hover
-{
- color:black;
- background-color:#dda;
- text-decoration: None;
- display: block;
-}
-
-body
-{
- font-family: "Verdana";
- font-size:11pt;
- background-color: white;
-}
-.comment
-{
-}
-.comment table
-{
- background-color: transparent;
-}
-.comment td
-{
- background-color: transparent;
-}
-.comment pre
-{
- font-family: "Verdana";
-}
-#header
-{
- color: black;
- font-weight: bold;
- background-image: url(/static/images/half-spiral.png);
- background-position: right center;
- background-repeat: no-repeat;
- background-color: #ff0;
-}
-#header ul.navoption
-{
- display: block;
- float: right;
- margin: 0;
- padding-right: 30px;
-}
-#header li
-{
- display: inline;
- margin:0;
- padding:0;
-}
-table.insetbox
-{
- margin-top: 0.5em;
- margin-bottom: 0.5em;
-}
-.insetbox tr, .insetbox td
-{
- margin: 0;
- padding: 0;
-}
-pre.traceback
-{
- font-family: Verdana, Ariel, Helvetica, sanserif;
-}
-tr.even td
-{
- background-color: #eee;
-}
-tr.odd td
-{
- background-color: #ffe;
-}
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-b.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-b.png
deleted file mode 100644
index 790e438..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-b.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-bl.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-bl.png
deleted file mode 100644
index 5b43259..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-bl.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-br.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-br.png
deleted file mode 100644
index 6cfd62c..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-br.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-l.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-l.png
deleted file mode 100644
index a6ce3ce..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-l.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-r.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-r.png
deleted file mode 100644
index 1ffd6f8..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-r.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-t.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-t.png
deleted file mode 100644
index 0129b0c..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-t.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-tl.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-tl.png
deleted file mode 100644
index d616b77..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-tl.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-tr.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-tr.png
deleted file mode 100644
index 18e542e..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds-tr.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds2-b.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds2-b.png
deleted file mode 100644
index 05a190e..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds2-b.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds2-r.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds2-r.png
deleted file mode 100644
index 0c3ea4c..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ds2-r.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/favicon.ico b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/favicon.ico
deleted file mode 100644
index 339d09c..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/favicon.ico
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/favicon.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/favicon.png
deleted file mode 100644
index 6dc53ee..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/favicon.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/half-spiral.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/half-spiral.png
deleted file mode 100644
index cb4b56c..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/half-spiral.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/header_inner.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/header_inner.png
deleted file mode 100644
index 2b2d87d..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/header_inner.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/info.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/info.png
deleted file mode 100644
index 329c523..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/info.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-b.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-b.png
deleted file mode 100644
index 25d3cfa..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-b.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-bl.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-bl.png
deleted file mode 100644
index f496223..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-bl.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-br.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-br.png
deleted file mode 100644
index 74cbd91..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-br.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-l.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-l.png
deleted file mode 100644
index dd567fa..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-l.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-r.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-r.png
deleted file mode 100644
index 9ac4486..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-r.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-t.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-t.png
deleted file mode 100644
index fbb06c8..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-t.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-tl.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-tl.png
deleted file mode 100644
index 9336290..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-tl.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-tr.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-tr.png
deleted file mode 100644
index de74808..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/is-tr.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ok.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ok.png
deleted file mode 100644
index fee6751..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/ok.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/shadows.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/shadows.png
deleted file mode 100644
index 9ddc676..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/shadows.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/spiral.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/spiral.png
deleted file mode 100644
index b4bcb1e..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/spiral.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/tg_under_the_hood.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/tg_under_the_hood.png
deleted file mode 100644
index bc9c79c..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/tg_under_the_hood.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/under_the_hood_blue.png b/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/under_the_hood_blue.png
deleted file mode 100644
index 90e84b7..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/static/images/under_the_hood_blue.png
+++ /dev/null
Binary files differ
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/templates/__init__.py b/interfaces/web/Bugs-Everywhere-Web/beweb/templates/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/templates/__init__.py
+++ /dev/null
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/templates/about.kid b/interfaces/web/Bugs-Everywhere-Web/beweb/templates/about.kid
deleted file mode 100644
index fa3548a..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/templates/about.kid
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#"
- py:extends="'master.kid'">
-<head>
- <meta content="text/html; charset=UTF-8" http-equiv="content-type" py:replace="''"/>
- <title>About Bugs Everywhere</title>
-</head>
-
-<body>
-<h1>About Bugs Everywhere</h1>
-<p>Bugs Everywhere is a "distributed bugtracker", designed to complement distributed revision control systems.
-</p>
-<p>
-Bugs Everywhere was conceived and written by developers at <a href="http://panoramicfeedback.com/">Panoramic Feedback</a>, primarily Aaron Bentley. <a href="http://panoramicfeedback.com/">Panoramic Feedback</a> is no longer developing BE, and the current maintainer is <a href="http://bugseverywhere.org/be/show/ChrisBall">Chris Ball</a>.
-</p>
-<p>
- Bugs Everywhere <a href="http://bugseverywhere.org/">web site</a>
-</p>
-<a href="/">Project List</a>
-</body>
-</html>
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/templates/bugs.kid b/interfaces/web/Bugs-Everywhere-Web/beweb/templates/bugs.kid
deleted file mode 100644
index 198aa94..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/templates/bugs.kid
+++ /dev/null
@@ -1,52 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<?python
-from libbe.names import unique_name
-from beweb.controllers import bug_url, project_url, bug_list_url
-from beweb.model import people_map
-people = people_map()
-def row_class(bug, num):
- if not bug.active is True:
- extra = "closed"
- else:
- extra = ""
- if num % 2 == 0:
- return extra+"even"
- else:
- return extra+"odd"
-
-
-def match(bug, show_closed, search):
- if not show_closed and not bug.active:
- return False
- elif search is None:
- return True
- else:
- return search.lower() in bug.summary.lower()
-?>
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#"
- py:extends="'master.kid'">
-
-<head>
- <meta content="text/html; charset=UTF-8" http-equiv="content-type" py:replace="''"/>
- <title>Bugs for $project_name</title>
-</head>
-
-<body>
-<h1>Bug list for ${project_name}</h1>
-<table>
-<tr><td>ID</td><td>Status</td><td>Severity</td><td>Assigned To</td><td>Comments</td><td>Summary</td></tr>
-<div py:for="num, bug in enumerate([b for b in bugs if match(b, show_closed, search)])" py:strip="True"><tr class="${row_class(bug, num)}"><td><a href="${bug_url(project_id, bug.uuid)}">${unique_name(bug, bugs[:])}</a></td><td>${bug.status}</td><td>${bug.severity}</td><td>${people.get(bug.assigned, bug.assigned)}</td><td>${len(list(bug.iter_comment_ids()))}</td><td>${bug.summary}</td></tr>
-</div>
-</table>
-<a href="${project_url()}">Project list</a>
-<a href="${bug_list_url(project_id, not show_closed, search)}">Toggle closed</a>
-<form action="${bug_list_url(project_id)}" method="post">
-<input type="submit" name="action" value="New bug"/>
-</form>
-<form action="${bug_list_url(project_id)}" method="get">
-<input type="hidden" name="show_closed" value="False" />
-<input name="search" value="$search"/>
-<input type="submit" name="action" value="Search" />
-</form>
-</body>
-</html>
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/templates/edit_bug.kid b/interfaces/web/Bugs-Everywhere-Web/beweb/templates/edit_bug.kid
deleted file mode 100644
index 276f610..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/templates/edit_bug.kid
+++ /dev/null
@@ -1,52 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<?python
-from libbe.bug import severity_values, status_values, thread_comments
-from libbe.utility import time_to_str
-from beweb.controllers import bug_list_url, comment_url
-from beweb.formatting import comment_body_xhtml, select_among
-from beweb.model import people_map
-people = people_map()
-?>
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#"
- py:extends="'master.kid'">
-
-<head>
- <meta content="text/html; charset=UTF-8" http-equiv="content-type" py:replace="''"/>
- <title>Edit bug</title>
-</head>
-
-<body>
-<h1>Edit bug</h1>
-<form method="post" action=".">
-<table>
-<tr><td>Status</td><td>Severity</td><td>Assigned To</td><td>Summary</td></tr>
-<tr><td>${select_among("status", status_values, bug.status)}</td><td>${select_among("severity", severity_values, bug.severity)}</td>
-<td>${select_among("assigned", people.keys()+[None], bug.assigned, people)}</td><td><input name="summary" value="${bug.summary}" size="80" /></td></tr>
-</table>
-<div py:def="show_comment(comment, children)" class="comment">
- <insetbox>
- <table>
- <tr><td>From</td><td>${comment.From}</td></tr>
- <tr><td>Date</td><td>${time_to_str(comment.time)}</td></tr>
- </table>
- <div py:content="comment_body_xhtml(comment)" py:strip="True"></div>
- <a href="${comment_url(project_id, bug.uuid, comment.uuid)}">Edit</a>
- <a href="${comment_url(project_id, bug.uuid, comment.uuid,
- action='Reply')}">Reply</a>
- </insetbox>
- <div style="margin-left:20px;">
- <div py:for="child, grandchildren in children" py:strip="True">
- ${show_comment(child, grandchildren)}
- </div>
- </div>
-</div>
-<div py:for="comment, children in thread_comments(bug.list_comments())"
- py:strip="True">
- ${show_comment(comment, children)}
-</div>
-<p><input type="submit" name="action" value="Update"/></p>
-<p><input type="submit" name="action" value="New comment"/></p>
-</form>
-<a href="${bug_list_url(project_id)}">Bug List</a>
-</body>
-</html>
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/templates/edit_comment.kid b/interfaces/web/Bugs-Everywhere-Web/beweb/templates/edit_comment.kid
deleted file mode 100644
index 2b522d4..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/templates/edit_comment.kid
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<?python
-from libbe.utility import time_to_str
-from beweb.controllers import bug_list_url, bug_url
-?>
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#"
- py:extends="'master.kid'">
-
-<head>
- <meta content="text/html; charset=UTF-8" http-equiv="content-type" py:replace="''"/>
- <title>Edit comment</title>
-</head>
-
-<body>
-<h1>Edit comment</h1>
-<form method="post">
-<table>
- <tr><td>From</td><td>${comment.From}</td></tr>
- <tr><td>Date</td><td>${time_to_str(comment.time)}</td></tr>
-</table>
-<insetbox><textarea rows="15" cols="80" py:content="comment.body" name="comment_body" style="border-style: none"/></insetbox>
-<p><input type="submit" name="action" value="Update"/></p>
-</form>
-<a href="${bug_url(project_id, comment.bug.uuid)}">Up to Bug</a>
-</body>
-</html>
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/templates/error.kid b/interfaces/web/Bugs-Everywhere-Web/beweb/templates/error.kid
deleted file mode 100644
index bc55615..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/templates/error.kid
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#"
- py:extends="'master.kid'">
-<head>
- <meta content="text/html; charset=UTF-8" http-equiv="content-type" py:replace="''"/>
- <title>BE Error: ${heading}</title>
-</head>
-
-<body>
-<h1 py:content="heading">Error heading</h1>
-<div py:replace="body" >Error Body</div>
-<pre py:content="traceback" class="traceback">Traceback</pre>
-</body>
-</html>
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/templates/login.kid b/interfaces/web/Bugs-Everywhere-Web/beweb/templates/login.kid
deleted file mode 100644
index e7ad852..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/templates/login.kid
+++ /dev/null
@@ -1,113 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml"
- xmlns:py="http://purl.org/kid/ns#"
- py:extends="'master.kid'">
-
-<head>
- <meta content="text/html; charset=UTF-8"
- http-equiv="content-type" py:replace="''"/>
- <title>Login</title>
- <style type="text/css">
- #loginBox
- {
- width: 30%;
- margin: auto;
- margin-top: 10%;
- padding-left: 10%;
- padding-right: 10%;
- padding-top: 5%;
- padding-bottom: 5%;
- font-family: verdana;
- font-size: 10px;
- background-color: #eee;
- border: 2px solid #ccc;
- }
-
- #loginBox h1
- {
- font-size: 42px;
- font-family: "Trebuchet MS";
- margin: 0;
- color: #ddd;
- }
-
- #loginBox p
- {
- position: relative;
- top: -1.5em;
- padding-left: 4em;
- font-size: 12px;
- margin: 0;
- color: #666;
- }
-
- #loginBox table
- {
- table-layout: fixed;
- border-spacing: 0;
- width: 100%;
- }
-
- #loginBox td.label
- {
- width: 33%;
- text-align: right;
- }
-
- #loginBox td.field
- {
- width: 66%;
- }
-
- #loginBox td.field input
- {
- width: 100%;
- }
-
- #loginBox td.buttons
- {
- text-align: right;
- }
-
- </style>
-</head>
-
-<body>
- <div id="loginBox">
- <h1>Login</h1>
- <p>${message}</p>
- <form action="${previous_url}" method="POST">
- <table>
- <tr>
- <td class="label">
- <label for="user_name">User Name:</label>
- </td>
- <td class="field">
- <input type="text" id="user_name" name="user_name"/>
- </td>
- </tr>
- <tr>
- <td class="label">
- <label for="password">Password:</label>
- </td>
- <td class="field">
- <input type="password" id="password" name="password"/>
- </td>
- </tr>
- <tr>
- <td colspan="2" class="buttons">
- <input type="submit" name="login" value="Login"/>
- </td>
- </tr>
- </table>
-
- <input py:if="forward_url" type="hidden" name="forward_url"
- value="${forward_url}"/>
-
- <input py:for="name,value in original_parameters.items()"
- type="hidden" name="${name}" value="${value}"/>
- </form>
- </div>
-</body>
-</html>
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/templates/master.kid b/interfaces/web/Bugs-Everywhere-Web/beweb/templates/master.kid
deleted file mode 100644
index 0772524..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/templates/master.kid
+++ /dev/null
@@ -1,71 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<?python import sitetemplate ?>
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#" py:extends="sitetemplate">
-
-<head py:match="item.tag=='{http://www.w3.org/1999/xhtml}head'" py:attrs="item.items()">
- <meta content="text/html; charset=UTF-8" http-equiv="content-type" py:replace="''"/>
- <title py:if="False">Your title goes here</title>
- <link rel="stylesheet" type="text/css" href="/static/css/style.css"/>
- <meta py:replace="item[:]"/>
- <style type="text/css">
- #pageLogin
- {
- font-size: 10px;
- font-family: verdana;
- text-align: right;
- }
- </style>
-</head>
-
-<body py:match="item.tag=='{http://www.w3.org/1999/xhtml}body'" py:attrs="item.items()">
-<div id="header"><div style="float: left">b u g s e v r y w h e r e</div><ul class="navoption"><li><a href="/about/">About</a></li></ul>&#160;</div>
- <div py:if="tg.config('identity.on',False) and not 'logging_in' in locals()"
- id="pageLogin">
- <span py:if="tg.identity.anonymous">
- <a href="/login">Login</a>
- </span>
- <span py:if="not tg.identity.anonymous">
- Welcome ${tg.identity.user.display_name}.
- <a href="/logout">Logout</a>
- </span>
- </div>
-
- <div py:if="tg_flash" class="flash" py:content="tg_flash"></div>
-
- <div py:replace="[item.text]+item[:]"/>
-
-<table py:match="item.tag=='{http://www.w3.org/1999/xhtml}insetbox'" cellspacing="0" cellpadding="0" border="0" class="insetbox">
-<tr height="19"><td background="/static/images/is-tl.png" width="19"/>
- <td background="/static/images/is-t.png" />
- <td background="/static/images/is-tr.png" width="11"></td>
-</tr>
-<tr>
- <td background="/static/images/is-l.png"/>
- <td py:content="item[:]"> Hello, this is some random text</td>
- <td background="/static/images/is-r.png"/>
-</tr>
-<tr height="11">
- <td background="/static/images/is-bl.png"/>
- <td background="/static/images/is-b.png" />
- <td background="/static/images/is-br.png"/>
-</tr>
-</table>
-<table py:match="item.tag=='{http://www.w3.org/1999/xhtml}dsbox'" cellspacing="0" cellpadding="0" border="0" class="dsbox">
-<tr height="11"><td background="/static/images/ds-tl.png" width="11"/>
- <td background="/static/images/ds-t.png" />
- <td background="/static/images/ds-tr.png" width="19"></td>
-</tr>
-<tr>
- <td background="/static/images/ds-l.png"/>
- <td py:content="item[:]"> Hello, this is some random text</td>
- <td background="/static/images/ds2-r.png"/>
-</tr>
-<tr height="19">
- <td background="/static/images/ds-bl.png"/>
- <td background="/static/images/ds2-b.png" />
- <td background="/static/images/ds-br.png"/>
-</tr>
-</table>
-</body>
-
-</html>
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/templates/projects.kid b/interfaces/web/Bugs-Everywhere-Web/beweb/templates/projects.kid
deleted file mode 100644
index d5f9fd3..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/templates/projects.kid
+++ /dev/null
@@ -1,32 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<?python
-from libbe.bug import severity_values
-def select_among(name, options, default):
- output = ['<select name="%s">' % name]
- for option in options:
- if option == default:
- selected = ' selected="selected"'
- else:
- selected = ""
- output.append("<option%s>%s</option>" % (selected, option))
- output.append("</select>")
- return XML("".join(output))
-?>
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#"
- py:extends="'master.kid'">
-<?python
-project_triples = [(pn, pid, pl) for pid,(pn, pl) in projects.iteritems()]
-project_triples.sort()
-?>
-<head>
- <meta content="text/html; charset=UTF-8" http-equiv="content-type" py:replace="''"/>
- <title>Project List</title>
-</head>
-
-<body>
-<h1>Project List</h1>
-<table>
-<tr py:for="project_name, project_id, project_loc in project_triples"><td><a href="/project/${project_id}/">${project_name}</a></td></tr>
-</table>
-</body>
-</html>
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/templates/welcome.kid b/interfaces/web/Bugs-Everywhere-Web/beweb/templates/welcome.kid
deleted file mode 100644
index 08abd21..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/templates/welcome.kid
+++ /dev/null
@@ -1,50 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#"
- py:extends="'master.kid'">
-<head>
-<meta content="text/html; charset=utf-8" http-equiv="Content-Type" py:replace="''"/>
-<title>Welcome to TurboGears</title>
-</head>
-<body>
-<div id="header">&nbsp;</div>
-<div id="main_content">
- <div id="status_block">Your TurboGears application is now running.</div>
- <!--h1>Take steps to dive right in:</h1-->
- <div id="sidebar">
- <h2>Learn more</h2>
- Learn more about TurboGears and take part in its
- development
- <ul class="links">
- <li><a href="http://www.turbogears.org">Official website</a></li>
- <li><a href="http://docs.turbogears.org">Documentation</a></li>
- <li><a href="http://trac.turbogears.org/turbogears/">Trac
- (bugs/suggestions)</a></li>
- <li><a href="http://groups.google.com/group/turbogears"> Mailing list</a> </li>
- </ul>
- </div>
- <div id="getting_started">
- <ol id="getting_started_steps">
- <li class="getting_started">
- <h3>Model</h3>
- <p> <a href="http://docs.turbogears.org/1.0/GettingStarted/DefineDatabase">Design models</a> in the <span class="code">model.py</span>.<br/>
- Edit <span class="code">dev.cfg</span> to <a href="http://docs.turbogears.org/1.0/GettingStarted/UseDatabase">use a different backend</a>, or start with a pre-configured SQLite database. <br/>
- Use script <span class="code">tg-admin sql create</span> to create the database tables.</p>
- </li>
- <li class="getting_started">
- <h3>View</h3>
- <p> Edit <a href="http://docs.turbogears.org/1.0/GettingStarted/Kid">html-like templates</a> in the <span class="code">/templates</span> folder;<br/>
- Put all <a href="http://docs.turbogears.org/1.0/StaticFiles">static contents</a> in the <span class="code">/static</span> folder. </p>
- </li>
- <li class="getting_started">
- <h3>Controller</h3>
- <p> Edit <span class="code"> controllers.py</span> and <a href="http://docs.turbogears.org/1.0/GettingStarted/CherryPy">build your
- website structure</a> with the simplicity of Python objects. <br/>
- TurboGears will automatically reload itself when you modify your project. </p>
- </li>
- </ol>
- <div class="notice"> If you create something cool, please <a href="http://groups.google.com/group/turbogears">let people know</a>, and consider contributing something back to the <a href="http://groups.google.com/group/turbogears">community</a>.</div>
- </div>
- <!-- End of getting_started -->
-</div>
-</body>
-</html>
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/tests/__init__.py b/interfaces/web/Bugs-Everywhere-Web/beweb/tests/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/tests/__init__.py
+++ /dev/null
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/tests/test_controllers.py b/interfaces/web/Bugs-Everywhere-Web/beweb/tests/test_controllers.py
deleted file mode 100644
index 0c77afe..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/tests/test_controllers.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from turbogears import testutil
-from beweb.controllers import Root
-import cherrypy
-
-cherrypy.root = Root()
-
-def test_method():
- "the index method should return a string called now"
- import types
- result = testutil.call(cherrypy.root.index)
- assert type(result["now"]) == types.StringType
-
-def test_indextitle():
- "The mainpage should have the right title"
- testutil.createRequest("/")
- assert "<TITLE>Welcome to TurboGears</TITLE>" in cherrypy.response.body[0]
diff --git a/interfaces/web/Bugs-Everywhere-Web/beweb/tests/test_model.py b/interfaces/web/Bugs-Everywhere-Web/beweb/tests/test_model.py
deleted file mode 100644
index 74c4e83..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/beweb/tests/test_model.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# If your project uses a database, you can set up database tests
-# similar to what you see below. Be sure to set the db_uri to
-# an appropriate uri for your testing database. sqlite is a good
-# choice for testing, because you can use an in-memory database
-# which is very fast.
-
-from turbogears import testutil, database
-# from beweb.model import YourDataClass, User
-
-# database.set_db_uri("sqlite:///:memory:")
-
-# class TestUser(testutil.DBTest):
-# def get_model(self):
-# return User
-#
-# def test_creation(self):
-# "Object creation should set the name"
-# obj = User(user_name = "creosote",
-# email_address = "spam@python.not",
-# display_name = "Mr Creosote",
-# password = "Wafer-thin Mint")
-# assert obj.display_name == "Mr Creosote"
-
diff --git a/interfaces/web/Bugs-Everywhere-Web/dev.cfg b/interfaces/web/Bugs-Everywhere-Web/dev.cfg
deleted file mode 100644
index eda9e6c..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/dev.cfg
+++ /dev/null
@@ -1,71 +0,0 @@
-[global]
-# This is where all of your settings go for your development environment
-# Settings that are the same for both development and production
-# (such as template engine, encodings, etc.) all go in
-# beweb/config/app.cfg
-
-# DATABASE
-
-# pick the form for your database
-# sqlobject.dburi="postgres://username@hostname/databasename"
-# sqlobject.dburi="mysql://username:password@hostname:port/databasename"
-# sqlobject.dburi="sqlite://%(package_dir)s/database.sqlite"
-
-# If you have sqlite, here's a simple default to get you started
-# in development
-sqlobject.dburi="sqlite://%(current_dir_uri)s/devdata.sqlite"
-
-
-# if you are using a database or table type without transactions
-# (MySQL default, for example), you should turn off transactions
-# by prepending notrans_ on the uri
-# sqlobject.dburi="notrans_mysql://username:password@hostname:port/databasename"
-
-# for Windows users, sqlite URIs look like:
-# sqlobject.dburi="sqlite:///drive_letter:/path/to/file"
-
-# SERVER
-
-# Some server parameters that you may want to tweak
-# server.socket_port=8080
-
-# Enable the debug output at the end on pages.
-# log_debug_info_filter.on = False
-
-server.environment="development"
-autoreload.package="beweb"
-
-# session_filter.on = True
-
-# Set to True if you'd like to abort execution if a controller gets an
-# unexpected parameter. False by default
-tg.strict_parameters = True
-identity.on = True
-visit.on = True
-identity.soprovider.model.user="beweb.model.User"
-identity.soprovider.model.group="beweb.model.Group"
-identity.soprovider.model.permission="beweb.model.Permission"
-
-
-# LOGGING
-# Logging configuration generally follows the style of the standard
-# Python logging module configuration. Note that when specifying
-# log format messages, you need to use *() for formatting variables.
-# Deployment independent log configuration is in beweb/config/log.cfg
-[logging]
-
-[[loggers]]
-[[[beweb]]]
-level='DEBUG'
-qualname='beweb'
-handlers=['debug_out']
-
-[[[allinfo]]]
-level='INFO'
-handlers=['debug_out']
-
-[[[access]]]
-level='INFO'
-qualname='turbogears.access'
-handlers=['access_out']
-propagate=0
diff --git a/interfaces/web/Bugs-Everywhere-Web/libbe b/interfaces/web/Bugs-Everywhere-Web/libbe
deleted file mode 120000
index 7d18612..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/libbe
+++ /dev/null
@@ -1 +0,0 @@
-../../../libbe \ No newline at end of file
diff --git a/interfaces/web/Bugs-Everywhere-Web/prod.cfg b/interfaces/web/Bugs-Everywhere-Web/prod.cfg
deleted file mode 100644
index c0d4aca..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/prod.cfg
+++ /dev/null
@@ -1,41 +0,0 @@
-[global]
-# This is where all of your settings go for your production environment.
-# You'll copy this file over to your production server and provide it
-# as a command-line option to your start script.
-# Settings that are the same for both development and production
-# (such as template engine, encodings, etc.) all go in
-# yourpackage/config/app.cfg
-
-# DATABASE
-
-# pick the form for your database
-# sqlobject.dburi="postgres://username@hostname/databasename"
-# sqlobject.dburi="mysql://username:password@hostname:port/databasename"
-# sqlobject.dburi="sqlite:///file_name_and_path"
-
-# if you are using a database or table type without transactions
-# (MySQL default, for example), you should turn off transactions
-# by prepending notrans_ on the uri
-# sqlobject.dburi="notrans_mysql://username:password@hostname:port/databasename"
-
-# for Windows users, sqlite URIs look like:
-# sqlobject.dburi="sqlite:///drive_letter|/path/to/file"
-
-
-# SERVER
-
-server.environment="production"
-server.log_file="server.log"
-server.log_to_screen=False
-
-# Sets the number of threads the server uses
-# server.thread_pool = 1
-
-# if this is part of a larger site, you can set the path
-# to the TurboGears instance here
-# server.webpath=""
-
-# Set to True if you'd like to abort execution if a controller gets an
-# unexpected parameter. False by default
-# tg.strict_parameters = False
-
diff --git a/interfaces/web/Bugs-Everywhere-Web/sample-prod.cfg b/interfaces/web/Bugs-Everywhere-Web/sample-prod.cfg
deleted file mode 100644
index d1052f8..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/sample-prod.cfg
+++ /dev/null
@@ -1,71 +0,0 @@
-[global]
-# This is where all of your settings go for your production environment.
-# You'll copy this file over to your production server and provide it
-# as a command-line option to your start script.
-# Settings that are the same for both development and production
-# (such as template engine, encodings, etc.) all go in
-# beweb/config/app.cfg
-
-# pick the form for your database
-# sqlobject.dburi="postgres://username@hostname/databasename"
-# sqlobject.dburi="mysql://username:password@hostname:port/databasename"
-# sqlobject.dburi="sqlite:///file_name_and_path"
-
-# If you have sqlite, here's a simple default to get you started
-# in development
-sqlobject.dburi="sqlite://%(current_dir_uri)s/devdata.sqlite"
-
-
-# if you are using a database or table type without transactions
-# (MySQL default, for example), you should turn off transactions
-# by prepending notrans_ on the uri
-# sqlobject.dburi="notrans_mysql://username:password@hostname:port/databasename"
-
-# for Windows users, sqlite URIs look like:
-# sqlobject.dburi="sqlite:///drive_letter:/path/to/file"
-
-
-# SERVER
-
-server.environment="production"
-
-# Sets the number of threads the server uses
-# server.thread_pool = 1
-
-# if this is part of a larger site, you can set the path
-# to the TurboGears instance here
-# server.webpath=""
-
-# session_filter.on = True
-
-# Set to True if you'd like to abort execution if a controller gets an
-# unexpected parameter. False by default
-# tg.strict_parameters = False
-
-# LOGGING
-# Logging configuration generally follows the style of the standard
-# Python logging module configuration. Note that when specifying
-# log format messages, you need to use *() for formatting variables.
-# Deployment independent log configuration is in beweb/config/log.cfg
-[logging]
-
-[[handlers]]
-
-[[[access_out]]]
-# set the filename as the first argument below
-args="('server.log',)"
-class='FileHandler'
-level='INFO'
-formatter='message_only'
-
-[[loggers]]
-[[[beweb]]]
-level='ERROR'
-qualname='beweb'
-handlers=['error_out']
-
-[[[access]]]
-level='INFO'
-qualname='turbogears.access'
-handlers=['access_out']
-propagate=0
diff --git a/interfaces/web/Bugs-Everywhere-Web/setup-tables.py b/interfaces/web/Bugs-Everywhere-Web/setup-tables.py
deleted file mode 100644
index 161d7c7..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/setup-tables.py
+++ /dev/null
@@ -1,34 +0,0 @@
-import pkg_resources
-pkg_resources.require("TurboGears")
-
-import turbogears
-import cherrypy
-cherrypy.lowercase_api = True
-
-from os.path import *
-import sys
-
-# first look on the command line for a desired config file,
-# if it's not on the command line, then
-# look for setup.py in this directory. If it's not there, this script is
-# probably installed
-if len(sys.argv) > 1:
- turbogears.update_config(configfile=sys.argv[1],
- modulename="beweb.config.app")
-elif exists(join(dirname(__file__), "setup.py")):
- turbogears.update_config(configfile="dev.cfg",
- modulename="beweb.config.app")
-else:
- turbogears.update_config(configfile="prod.cfg",
- modulename="beweb.config.app")
-
-from beweb.controllers import Root
-
-cherrypy.root = Root()
-
-
-from beweb.model import TG_Group, TG_Permission
-g = TG_Group(groupId="editors", displayName="Editors")
-p = TG_Permission(permissionId="editbugs",
- description="Ability to create and edit bugs")
-g.addTG_Permission(p)
diff --git a/interfaces/web/Bugs-Everywhere-Web/setup.py b/interfaces/web/Bugs-Everywhere-Web/setup.py
deleted file mode 100644
index 8ba3da2..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/setup.py
+++ /dev/null
@@ -1,62 +0,0 @@
-from setuptools import setup, find_packages
-from turbogears.finddata import find_package_data
-
-import os
-execfile(os.path.join("beweb", "release.py"))
-
-setup(
- name="Bugs-Everywhere-Web",
- version=version,
-
- # uncomment the following lines if you fill them out in release.py
- #description=description,
- #author=author,
- #author_email=email,
- #url=url,
- #download_url=download_url,
- #license=license,
-
- install_requires = [
- "TurboGears >= 1.0b1",
- ],
- scripts = ["start-beweb.py"],
- zip_safe=False,
- packages=find_packages(),
- package_data = find_package_data(where='beweb',
- package='beweb'),
- keywords = [
- # Use keywords if you'll be adding your package to the
- # Python Cheeseshop
-
- # if this has widgets, uncomment the next line
- # 'turbogears.widgets',
-
- # if this has a tg-admin command, uncomment the next line
- # 'turbogears.command',
-
- # if this has identity providers, uncomment the next line
- # 'turbogears.identity.provider',
-
- # If this is a template plugin, uncomment the next line
- # 'python.templating.engines',
-
- # If this is a full application, uncomment the next line
- # 'turbogears.app',
- ],
- classifiers = [
- 'Development Status :: 3 - Alpha',
- 'Operating System :: OS Independent',
- 'Programming Language :: Python',
- 'Topic :: Software Development :: Libraries :: Python Modules',
- 'Framework :: TurboGears',
- # if this is an application that you'll distribute through
- # the Cheeseshop, uncomment the next line
- # 'Framework :: TurboGears :: Applications',
-
- # if this is a package that includes widgets that you'll distribute
- # through the Cheeseshop, uncomment the next line
- # 'Framework :: TurboGears :: Widgets',
- ],
- test_suite = 'nose.collector',
- )
-
diff --git a/interfaces/web/Bugs-Everywhere-Web/start-beweb.py b/interfaces/web/Bugs-Everywhere-Web/start-beweb.py
deleted file mode 100755
index 4070abd..0000000
--- a/interfaces/web/Bugs-Everywhere-Web/start-beweb.py
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/env python
-import pkg_resources
-pkg_resources.require("TurboGears")
-
-import turbogears
-import cherrypy
-cherrypy.lowercase_api = True
-
-from os.path import *
-import sys
-
-# first look on the command line for a desired config file,
-# if it's not on the command line, then
-# look for setup.py in this directory. If it's not there, this script is
-# probably installed
-if len(sys.argv) > 1:
- turbogears.update_config(configfile=sys.argv[1],
- modulename="beweb.config")
-elif exists(join(dirname(__file__), "setup.py")):
- turbogears.update_config(configfile="dev.cfg",
- modulename="beweb.config")
-else:
- turbogears.update_config(configfile="prod.cfg",
- modulename="beweb.config")
-
-from beweb.controllers import Root
-
-turbogears.start_server(Root())
diff --git a/interfaces/xml/be-mbox-to-xml b/interfaces/xml/be-mbox-to-xml
deleted file mode 100755
index eda6d6e..0000000
--- a/interfaces/xml/be-mbox-to-xml
+++ /dev/null
@@ -1,154 +0,0 @@
-#!/usr/bin/env python
-# Copyright (C) 2009 W. Trevor King <wking@drexel.edu>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-"""
-Convert an mbox into xml suitable for input into be.
- $ be-mbox-to-xml file.mbox | be import-xml -c <ID> -
-mbox is a flat-file format, consisting of a series of messages.
-Messages begin with a a From_ line, followed by RFC 822 email,
-followed by a blank line.
-"""
-
-import base64
-import email.utils
-from libbe.encoding import get_encoding, set_IO_stream_encodings
-from libbe.utility import time_to_str
-from mailbox import mbox, Message # the mailbox people really want an on-disk copy
-from time import asctime, gmtime, mktime
-import types
-from xml.sax.saxutils import escape
-
-DEFAULT_ENCODING = get_encoding()
-set_IO_stream_encodings(DEFAULT_ENCODING)
-
-KNOWN_IDS = []
-
-def normalize_email_address(address):
- """
- Standardize whitespace, etc.
- """
- addr = email.utils.formataddr(email.utils.parseaddr(address))
- if len(addr) == 0:
- return None
- return addr
-
-def normalize_RFC_2822_date(date):
- """
- Some email clients write non-RFC 2822-compliant date tags like:
- Fri, 18 Sep 2009 08:49:02 -0400 (EDT)
- with the non-standard (EDT) timezone name. This funtion attempts
- to deal with such inconsistencies.
- """
- time_tuple = email.utils.parsedate(date)
- assert time_tuple != None, \
- 'unparsable date: "%s"' % date
- return time_to_str(mktime(time_tuple))
-
-def comment_message_to_xml(message, fields=None):
- if fields == None:
- fields = {}
- new_fields = {}
- new_fields[u'alt-id'] = message[u'message-id']
- new_fields[u'in-reply-to'] = message[u'in-reply-to']
- new_fields[u'author'] = normalize_email_address(message[u'from'])
- new_fields[u'date'] = message[u'date']
- if new_fields[u'date'] != None:
- new_fields[u'date'] = normalize_RFC_2822_date(new_fields[u'date'])
- new_fields[u'content-type'] = message.get_content_type()
- for k,v in new_fields.items():
- if v != None and type(v) != types.UnicodeType:
- fields[k] = unicode(v, encoding=DEFAULT_ENCODING)
- elif v == None and k in fields:
- new_fields[k] = fields[k]
- for k,v in fields.items():
- if k not in new_fields:
- new_fields.k = fields[k]
- fields = new_fields
-
- if fields[u'in-reply-to'] == None:
- if message[u'references'] != None:
- refs = message[u'references'].split()
- for ref in refs: # search for a known reference id.
- if ref in KNOWN_IDS:
- fields[u'in-reply-to'] = ref
- break
- if fields[u'in-reply-to'] == None and len(refs) > 0:
- fields[u'in-reply-to'] = refs[0] # default to the first
- else: # check for mutliple in-reply-to references.
- refs = fields[u'in-reply-to'].split()
- found_ref = False
- for ref in refs: # search for a known reference id.
- if ref in KNOWN_IDS:
- fields[u'in-reply-to'] = ref
- found_ref = True
- break
- if found_ref == False and len(refs) > 0:
- fields[u'in-reply-to'] = refs[0] # default to the first
-
- if fields[u'alt-id'] != None:
- KNOWN_IDS.append(fields[u'alt-id'])
-
- if message.is_multipart():
- ret = []
- alt_id = fields[u'alt-id']
- from_str = fields[u'author']
- date = fields[u'date']
- for m in message.walk():
- if m == message:
- continue
- fields[u'author'] = from_str
- fields[u'date'] = date
- if len(ret) > 0: # we've added one part already
- fields.pop(u'alt-id') # don't pass alt-id to other parts
- fields[u'in-reply-to'] = alt_id # others respond to first
- ret.append(comment_message_to_xml(m, fields))
- return u'\n'.join(ret)
-
- charset = message.get_content_charset(DEFAULT_ENCODING).lower()
- #assert charset == DEFAULT_ENCODING.lower(), \
- # u"Unknown charset: %s" % charset
-
- if message[u'content-transfer-encoding'] == None:
- encoding = DEFAULT_ENCODING
- else:
- encoding = message[u'content-transfer-encoding'].lower()
- body = message.get_payload(decode=True) # attempt to decode
- assert body != None, "Unable to decode?"
- if fields[u'content-type'].startswith(u"text/"):
- body = unicode(body, encoding=charset).rstrip(u'\n')
- else:
- body = base64.encode(body)
- fields[u'body'] = body
- lines = [u"<comment>"]
- for tag,body in fields.items():
- if body != None:
- ebody = escape(body)
- lines.append(u" <%s>%s</%s>" % (tag, ebody, tag))
- lines.append(u"</comment>")
- return u'\n'.join(lines)
-
-def main(mbox_filename):
- mb = mbox(mbox_filename)
- print u'<?xml version="1.0" encoding="%s" ?>' % DEFAULT_ENCODING
- print u"<be-xml>"
- for message in mb:
- print comment_message_to_xml(message)
- print u"</be-xml>"
-
-
-if __name__ == "__main__":
- import sys
- main(sys.argv[1])
diff --git a/interfaces/xml/be-xml-to-mbox b/interfaces/xml/be-xml-to-mbox
deleted file mode 100755
index ef7b714..0000000
--- a/interfaces/xml/be-xml-to-mbox
+++ /dev/null
@@ -1,208 +0,0 @@
-#!/usr/bin/env python
-# Copyright (C) 2009 W. Trevor King <wking@drexel.edu>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-"""
-Convert xml output of `be list --xml` into mbox format for browsing
-with a mail reader. For example
- $ be list --xml --status=all | be-xml-to-mbox | catmutt
-
-mbox is a flat-file format, consisting of a series of messages.
-Messages begin with a a From_ line, followed by RFC 822 email,
-followed by a blank line.
-"""
-
-#from mailbox import mbox, Message # the mailbox people really want an on-disk copy
-import codecs
-import email.utils
-from libbe.encoding import get_encoding, set_IO_stream_encodings
-from libbe.utility import str_to_time as rfc2822_to_gmtime_integer
-from time import asctime, gmtime
-import types
-try: # import core module, Python >= 2.5
- from xml.etree import ElementTree
-except ImportError: # look for non-core module
- from elementtree import ElementTree
-from xml.sax.saxutils import unescape
-
-
-DEFAULT_DOMAIN = "invalid.com"
-DEFAULT_EMAIL = "dummy@" + DEFAULT_DOMAIN
-DEFAULT_ENCODING = get_encoding()
-set_IO_stream_encodings(DEFAULT_ENCODING)
-
-def rfc2822_to_asctime(rfc2822_string):
- """Convert an RFC 2822-fomatted string into a asctime string.
- >>> rfc2822_to_asctime("Thu, 01 Jan 1970 00:00:00 +0000")
- "Thu Jan 01 00:00:00 1970"
- """
- if rfc2822_string == "":
- return asctime(gmtime(0))
- return asctime(gmtime(rfc2822_to_gmtime_integer(rfc2822_string)))
-
-class LimitedAttrDict (dict):
- """
- Dict with error checking, to avoid invalid bug/comment fields.
- """
- _attrs = [] # override with list of valid attribute names
- def __init__(self, **kwargs):
- dict.__init__(self)
- for key,value in kwargs.items():
- self[key] = value
- def __setitem__(self, key, item):
- self._validate_key(key)
- dict.__setitem__(self, key, item)
- def _validate_key(self, key):
- if key in self._attrs:
- return
- elif type(key) not in types.StringTypes:
- raise TypeError, "Invalid attribute type %s for '%s'" % (type(key), key)
- else:
- raise ValueError, "Invalid attribute name '%s'" % key
-
-class Bug (LimitedAttrDict):
- _attrs = [u"uuid",
- u"short-name",
- u"severity",
- u"status",
- u"assigned",
- u"reporter",
- u"creator",
- u"created",
- u"summary",
- u"comments",
- u"extra-strings"]
- def print_to_mbox(self):
- if "creator" in self:
- # otherwise, probably a `be show` uuid-only bug to avoid
- # root comments.
- name,addr = email.utils.parseaddr(self["creator"])
- print "From %s %s" % (addr, rfc2822_to_asctime(self["created"]))
- print "Message-id: <%s@%s>" % (self["uuid"], DEFAULT_DOMAIN)
- print "Date: %s" % self["created"]
- print "From: %s" % self["creator"]
- print "Content-Type: %s; charset=%s" % ("text/plain", DEFAULT_ENCODING)
- print "Content-Transfer-Encoding: 8bit"
- print "Subject: %s: %s" % (self["short-name"], self["summary"])
- if "extra-strings" in self:
- for estr in self["extra_strings"]:
- print "X-Extra-String: %s" % estr
- print ""
- print self["summary"]
- print ""
- if "comments" in self:
- for comment in self["comments"]:
- comment.print_to_mbox(self)
- def init_from_etree(self, element):
- assert element.tag == "bug", element.tag
- for field in element.getchildren():
- text = unescape(unicode(field.text).decode("unicode_escape").strip())
- if field.tag == "comment":
- comm = Comment()
- comm.init_from_etree(field)
- if "comments" in self:
- self["comments"].append(comm)
- else:
- self["comments"] = [comm]
- elif field.tag == "extra-string":
- if "extra-strings" in self:
- self["extra-strings"].append(text)
- else:
- self["extra-strings"] = [text]
- else:
- self[field.tag] = text
-
-class Comment (LimitedAttrDict):
- _attrs = [u"uuid",
- u"alt-id",
- u"short-name",
- u"in-reply-to",
- u"author",
- u"date",
- u"content-type",
- u"body",
- u"extra-strings"]
- def print_to_mbox(self, bug=None):
- if bug == None:
- bug = Bug()
- bug[u"uuid"] = u"no-uuid"
- name,addr = email.utils.parseaddr(self["author"])
- print "From %s %s" % (addr, rfc2822_to_asctime(self["date"]))
- if "uuid" in self: id = self["uuid"]
- elif "alt-id" in self: id = self["alt-id"]
- else: id = None
- if id != None:
- print "Message-id: <%s@%s>" % (id, DEFAULT_DOMAIN)
- print "Date: %s" % self["date"]
- print "From: %s" % self["author"]
- subject = ""
- if "short-name" in self:
- subject += self["short-name"]+u": "
- if "summary" in bug:
- subject += bug["summary"]
- else:
- subject += u"no-subject"
- print "Subject: %s" % subject
- if "in-reply-to" not in self.keys():
- self["in-reply-to"] = bug["uuid"]
- print "In-Reply-To: <%s@%s>" % (self["in-reply-to"], DEFAULT_DOMAIN)
- if "extra-strings" in self:
- for estr in self["extra_strings"]:
- print "X-Extra-String: %s" % estr
- if self["content-type"].startswith("text/"):
- print "Content-Transfer-Encoding: 8bit"
- print "Content-Type: %s; charset=%s" % (self["content-type"], DEFAULT_ENCODING)
- print ""
- print self["body"]
- else: # content type and transfer encoding already in XML MIME output
- print self["body"]
- print ""
- def init_from_etree(self, element):
- assert element.tag == "comment", element.tag
- for field in element.getchildren():
- text = unescape(unicode(field.text).decode("unicode_escape").strip())
- if field.tag == "extra-string":
- if "extra-strings" in self:
- self["extra-strings"].append(text)
- else:
- self["extra-strings"] = [text]
- else:
- if field.tag == "body":
- text+="\n"
- self[field.tag] = text
-
-def print_to_mbox(element):
- if element.tag == "bug":
- b = Bug()
- b.init_from_etree(element)
- b.print_to_mbox()
- elif element.tag == "comment":
- c = Comment()
- c.init_from_etree(element)
- c.print_to_mbox()
- elif element.tag in ["be-xml"]:
- for elt in element.getchildren():
- print_to_mbox(elt)
-
-if __name__ == "__main__":
- import sys
-
- if len(sys.argv) == 1: # no filename given, use stdin
- xml_unicode = sys.stdin.read()
- else:
- xml_unicode = codecs.open(sys.argv[1], "r", DEFAULT_ENCODING).read()
- xml_str = xml_unicode.encode("unicode_escape").replace(r"\n", "\n")
- elist = ElementTree.XML(xml_str)
- print_to_mbox(elist)