aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.be/bugs/f7ccd916-b5c7-4890-a2e3-8c8ace17ae3a/comments/028d2e8d-5b0f-4c43-a913-35a1709b2276/body5
-rw-r--r--.be/bugs/f7ccd916-b5c7-4890-a2e3-8c8ace17ae3a/comments/028d2e8d-5b0f-4c43-a913-35a1709b2276/values21
-rw-r--r--.be/bugs/f7ccd916-b5c7-4890-a2e3-8c8ace17ae3a/values2
-rwxr-xr-xbe5
-rw-r--r--becommands/assign.py14
-rw-r--r--becommands/close.py11
-rw-r--r--becommands/comment.py27
-rw-r--r--becommands/diff.py12
-rw-r--r--becommands/help.py15
-rw-r--r--becommands/list.py11
-rw-r--r--becommands/merge.py50
-rw-r--r--becommands/new.py8
-rw-r--r--becommands/open.py11
-rw-r--r--becommands/remove.py8
-rw-r--r--becommands/set.py17
-rw-r--r--becommands/set_root.py19
-rw-r--r--becommands/severity.py17
-rw-r--r--becommands/show.py10
-rw-r--r--becommands/status.py17
-rw-r--r--becommands/target.py23
-rw-r--r--libbe/arch.py26
-rw-r--r--libbe/bug.py5
-rw-r--r--libbe/bugdir.py123
-rw-r--r--libbe/bzr.py2
-rw-r--r--libbe/cmdutil.py26
-rw-r--r--libbe/comment.py14
-rw-r--r--libbe/config.py28
-rw-r--r--libbe/diff.py26
-rw-r--r--libbe/editor.py103
-rw-r--r--libbe/encoding.py53
-rw-r--r--libbe/git.py2
-rw-r--r--libbe/hg.py4
-rw-r--r--libbe/rcs.py37
-rw-r--r--libbe/utility.py73
34 files changed, 525 insertions, 300 deletions
diff --git a/.be/bugs/f7ccd916-b5c7-4890-a2e3-8c8ace17ae3a/comments/028d2e8d-5b0f-4c43-a913-35a1709b2276/body b/.be/bugs/f7ccd916-b5c7-4890-a2e3-8c8ace17ae3a/comments/028d2e8d-5b0f-4c43-a913-35a1709b2276/body
new file mode 100644
index 0000000..02bbe3a
--- /dev/null
+++ b/.be/bugs/f7ccd916-b5c7-4890-a2e3-8c8ace17ae3a/comments/028d2e8d-5b0f-4c43-a913-35a1709b2276/body
@@ -0,0 +1,5 @@
+Wrote/borrowed libbe/encoding.py.
+Now the following works:
+
+python -c 'import libbe.encoding as e; print e.get_encoding(); e.set_IO_stream_encodings(e.get_encoding()) ;print u"\u2019"' | cat
+
diff --git a/.be/bugs/f7ccd916-b5c7-4890-a2e3-8c8ace17ae3a/comments/028d2e8d-5b0f-4c43-a913-35a1709b2276/values b/.be/bugs/f7ccd916-b5c7-4890-a2e3-8c8ace17ae3a/comments/028d2e8d-5b0f-4c43-a913-35a1709b2276/values
new file mode 100644
index 0000000..eb56317
--- /dev/null
+++ b/.be/bugs/f7ccd916-b5c7-4890-a2e3-8c8ace17ae3a/comments/028d2e8d-5b0f-4c43-a913-35a1709b2276/values
@@ -0,0 +1,21 @@
+
+
+
+Content-type=text/plain
+
+
+
+
+
+
+Date=Tue, 25 Nov 2008 19:41:02 +0000
+
+
+
+
+
+
+From=W. Trevor King <wking@drexel.edu>
+
+
+
diff --git a/.be/bugs/f7ccd916-b5c7-4890-a2e3-8c8ace17ae3a/values b/.be/bugs/f7ccd916-b5c7-4890-a2e3-8c8ace17ae3a/values
index 40ac06d..e710d29 100644
--- a/.be/bugs/f7ccd916-b5c7-4890-a2e3-8c8ace17ae3a/values
+++ b/.be/bugs/f7ccd916-b5c7-4890-a2e3-8c8ace17ae3a/values
@@ -15,7 +15,7 @@ severity=minor
-status=open
+status=fixed
diff --git a/be b/be
index 1ef7b3a..6be236b 100755
--- a/be
+++ b/be
@@ -33,9 +33,12 @@ else:
except cmdutil.GetHelp:
print cmdutil.help(sys.argv[1])
sys.exit(0)
- except cmdutil.UsageError:
+ except cmdutil.UsageError, e:
+ print "Invalid usage:", e
+ print "\nArgs:", sys.argv[1:]
print cmdutil.help(sys.argv[1])
sys.exit(1)
except cmdutil.UserError, e:
+ print "ERROR:"
print e
sys.exit(1)
diff --git a/becommands/assign.py b/becommands/assign.py
index cb732b3..b00c5c2 100644
--- a/becommands/assign.py
+++ b/becommands/assign.py
@@ -18,7 +18,7 @@
from libbe import cmdutil, bugdir
__desc__ = __doc__
-def execute(args):
+def execute(args, test=False):
"""
>>> import os
>>> bd = bugdir.simple_bug_dir()
@@ -26,17 +26,17 @@ def execute(args):
>>> bd.bug_from_shortname("a").assigned is None
True
- >>> execute(["a"])
+ >>> execute(["a"], test=True)
>>> bd._clear_bugs()
>>> bd.bug_from_shortname("a").assigned == bd.user_id
True
- >>> execute(["a", "someone"])
+ >>> execute(["a", "someone"], test=True)
>>> bd._clear_bugs()
>>> print bd.bug_from_shortname("a").assigned
someone
- >>> execute(["a","none"])
+ >>> execute(["a","none"], test=True)
>>> bd._clear_bugs()
>>> bd.bug_from_shortname("a").assigned is None
True
@@ -44,11 +44,11 @@ def execute(args):
options, args = get_parser().parse_args(args)
assert(len(args) in (0, 1, 2))
if len(args) == 0:
- raise cmdutil.UserError("Please specify a bug id.")
+ raise cmdutil.UsageError("Please specify a bug id.")
if len(args) > 2:
help()
- raise cmdutil.UserError("Too many arguments.")
- bd = bugdir.BugDir(from_disk=True)
+ raise cmdutil.UsageError("Too many arguments.")
+ bd = bugdir.BugDir(from_disk=True, manipulate_encodings=not test)
bug = bd.bug_from_shortname(args[0])
if len(args) == 1:
bug.assigned = bd.user_id
diff --git a/becommands/close.py b/becommands/close.py
index 8d2ccdb..d125397 100644
--- a/becommands/close.py
+++ b/becommands/close.py
@@ -18,7 +18,7 @@
from libbe import cmdutil, bugdir
__desc__ = __doc__
-def execute(args):
+def execute(args, test=False):
"""
>>> from libbe import bugdir
>>> import os
@@ -26,18 +26,17 @@ def execute(args):
>>> os.chdir(bd.root)
>>> print bd.bug_from_shortname("a").status
open
- >>> execute(["a"])
+ >>> execute(["a"], test=True)
>>> bd._clear_bugs()
>>> print bd.bug_from_shortname("a").status
closed
"""
options, args = get_parser().parse_args(args)
if len(args) == 0:
- raise cmdutil.UserError("Please specify a bug id.")
+ raise cmdutil.UsageError("Please specify a bug id.")
if len(args) > 1:
- help()
- raise cmdutil.UserError("Too many arguments.")
- bd = bugdir.BugDir(from_disk=True)
+ raise cmdutil.UsageError("Too many arguments.")
+ bd = bugdir.BugDir(from_disk=True, manipulate_encodings=not test)
bug = bd.bug_from_shortname(args[0])
bug.status = "closed"
bd.save()
diff --git a/becommands/comment.py b/becommands/comment.py
index 172f818..c9c6b41 100644
--- a/becommands/comment.py
+++ b/becommands/comment.py
@@ -15,16 +15,16 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""Add a comment to a bug"""
-from libbe import cmdutil, bugdir, utility
+from libbe import cmdutil, bugdir, editor
import os
__desc__ = __doc__
-def execute(args):
+def execute(args, test=False):
"""
>>> import time
>>> bd = bugdir.simple_bug_dir()
>>> os.chdir(bd.root)
- >>> execute(["a", "This is a comment about a"])
+ >>> execute(["a", "This is a comment about a"], test=True)
>>> bd._clear_bugs()
>>> bug = bd.bug_from_shortname("a")
>>> bug.load_comments()
@@ -41,12 +41,12 @@ def execute(args):
>>> if 'EDITOR' in os.environ:
... del os.environ["EDITOR"]
- >>> execute(["b"])
+ >>> execute(["b"], test=True)
Traceback (most recent call last):
UserError: No comment supplied, and EDITOR not specified.
>>> os.environ["EDITOR"] = "echo 'I like cheese' > "
- >>> execute(["b"])
+ >>> execute(["b"], test=True)
>>> bd._clear_bugs()
>>> bug = bd.bug_from_shortname("b")
>>> bug.load_comments()
@@ -57,10 +57,9 @@ def execute(args):
"""
options, args = get_parser().parse_args(args)
if len(args) == 0:
- raise cmdutil.UserError("Please specify a bug or comment id.")
+ raise cmdutil.UsageError("Please specify a bug or comment id.")
if len(args) > 2:
- help()
- raise cmdutil.UserError("Too many arguments.")
+ raise cmdutil.UsageError("Too many arguments.")
shortname = args[0]
if shortname.count(':') > 1:
@@ -73,20 +72,20 @@ def execute(args):
bugname = shortname
is_reply = False
- bd = bugdir.BugDir(from_disk=True)
+ bd = bugdir.BugDir(from_disk=True, manipulate_encodings=not test)
bug = bd.bug_from_shortname(bugname)
bug.load_comments()
if is_reply:
- parent = bug.comment_root.comment_from_shortname(shortname, bug_shortname=bugname)
+ parent = bug.comment_root.comment_from_shortname(shortname,
+ bug_shortname=bugname)
else:
parent = bug.comment_root
if len(args) == 1:
try:
- body = utility.editor_string("Please enter your comment above")
- except utility.CantFindEditor:
- raise cmdutil.UserError(
- "No comment supplied, and EDITOR not specified.")
+ body = editor.editor_string("Please enter your comment above")
+ except editor.CantFindEditor, e:
+ raise cmdutil.UserError, "No comment supplied, and EDITOR not specified."
if body is None:
raise cmdutil.UserError("No comment entered.")
body = body.decode('utf-8')
diff --git a/becommands/diff.py b/becommands/diff.py
index 862afc5..8714d77 100644
--- a/becommands/diff.py
+++ b/becommands/diff.py
@@ -20,7 +20,7 @@ from libbe import cmdutil, bugdir, diff
import os
__desc__ = __doc__
-def execute(args):
+def execute(args, test=False):
"""
>>> import os
>>> bd = bugdir.simple_bug_dir()
@@ -31,7 +31,7 @@ def execute(args):
>>> changed = bd.rcs.commit("Closed bug a")
>>> os.chdir(bd.root)
>>> if bd.rcs.versioned == True:
- ... execute([original])
+ ... execute([original], test=True)
... else:
... print "a:cm: Bug A\\nstatus: open -> closed\\n"
Modified bug reports:
@@ -45,16 +45,14 @@ def execute(args):
if len(args) == 1:
revision = args[0]
if len(args) > 1:
- help()
- raise cmdutil.UserError("Too many arguments.")
- bd = bugdir.BugDir(from_disk=True)
+ raise cmdutil.UsageError("Too many arguments.")
+ bd = bugdir.BugDir(from_disk=True, manipulate_encodings=not test)
if bd.rcs.versioned == False:
print "This directory is not revision-controlled."
else:
old_bd = bd.duplicate_bugdir(revision)
r,m,a = diff.diff(old_bd, bd)
- diff.diff_report((r,m,a), bd)
- # TODO, string return from diff report
+ print diff.diff_report((r,m,a), bd).encode(bd.encoding)
bd.remove_duplicate_bugdir()
def get_parser():
diff --git a/becommands/help.py b/becommands/help.py
index bf0b4fc..1c99af5 100644
--- a/becommands/help.py
+++ b/becommands/help.py
@@ -21,20 +21,25 @@ __desc__ = __doc__
def execute(args):
"""
Print help of specified command.
+ >>> execute(["help"])
+ Usage: be help [COMMAND]
+ <BLANKLINE>
+ Options:
+ -h, --help Print a help message
+ <BLANKLINE>
+ Print help for specified command or list of all commands.
+ <BLANKLINE>
"""
options, args = get_parser().parse_args(args)
if len(args) > 1:
- raise cmdutil.UserError("Too many arguments.")
+ raise cmdutil.UsageError("Too many arguments.")
if len(args) == 0:
print cmdutil.help()
else:
try:
print cmdutil.help(args[0])
except AttributeError:
- print "No help available"
-
- return
-
+ print "No help available"
def get_parser():
parser = cmdutil.CmdOptionParser("be help [COMMAND]")
diff --git a/becommands/list.py b/becommands/list.py
index 63e1cd6..c63039d 100644
--- a/becommands/list.py
+++ b/becommands/list.py
@@ -21,22 +21,21 @@ from libbe.bug import cmp_full, severity_values, status_values, \
import os
__desc__ = __doc__
-def execute(args):
+def execute(args, test=False):
"""
>>> import os
>>> bd = bugdir.simple_bug_dir()
>>> os.chdir(bd.root)
- >>> execute([])
+ >>> execute([], test=True)
a:om: Bug A
- >>> execute(["--status", "all"])
+ >>> execute(["--status", "all"], test=True)
a:om: Bug A
b:cm: Bug B
"""
options, args = get_parser().parse_args(args)
if len(args) > 0:
- help()
- raise cmdutil.UserError("Too many arguments.")
- bd = bugdir.BugDir(from_disk=True)
+ raise cmdutil.UsageError("Too many arguments.")
+ bd = bugdir.BugDir(from_disk=True, manipulate_encodings=not test)
bd.load_all_bugs()
# select status
if options.status != None:
diff --git a/becommands/merge.py b/becommands/merge.py
index b079f2c..d1829d6 100644
--- a/becommands/merge.py
+++ b/becommands/merge.py
@@ -19,7 +19,7 @@ from libbe import cmdutil, bugdir
import os, copy
__desc__ = __doc__
-def execute(args):
+def execute(args, test=False):
"""
>>> from libbe import utility
>>> bd = bugdir.simple_bug_dir()
@@ -38,7 +38,7 @@ def execute(args):
>>> dummy.time = 2
>>> bd.save()
>>> os.chdir(bd.root)
- >>> execute(["a", "b"])
+ >>> execute(["a", "b"], test=True)
Merging bugs a and b
>>> bd._clear_bugs()
>>> a = bd.bug_from_shortname("a")
@@ -61,30 +61,30 @@ def execute(args):
Date: Thu, 01 Jan 1970 00:00:01 +0000
<BLANKLINE>
Testing
- --------- Comment ---------
- Name: a:2
- From: wking <wking@thor.yang.physics.drexel.edu>
- Date: Thu, 01 Jan 1970 00:00:02 +0000
+ --------- Comment ---------
+ Name: a:2
+ From: wking <wking@thor.yang.physics.drexel.edu>
+ Date: Thu, 01 Jan 1970 00:00:02 +0000
<BLANKLINE>
- Testing...
+ Testing...
--------- Comment ---------
Name: a:3
From: wking <wking@thor.yang.physics.drexel.edu>
Date: Thu, 01 Jan 1970 00:00:03 +0000
<BLANKLINE>
Merged from bug b
- --------- Comment ---------
- Name: a:4
- From: wking <wking@thor.yang.physics.drexel.edu>
- Date: Thu, 01 Jan 1970 00:00:01 +0000
+ --------- Comment ---------
+ Name: a:4
+ From: wking <wking@thor.yang.physics.drexel.edu>
+ Date: Thu, 01 Jan 1970 00:00:01 +0000
<BLANKLINE>
- 1 2
- --------- Comment ---------
- Name: a:5
- From: wking <wking@thor.yang.physics.drexel.edu>
- Date: Thu, 01 Jan 1970 00:00:02 +0000
+ 1 2
+ --------- Comment ---------
+ Name: a:5
+ From: wking <wking@thor.yang.physics.drexel.edu>
+ Date: Thu, 01 Jan 1970 00:00:02 +0000
<BLANKLINE>
- 1 2 3 4
+ 1 2 3 4
>>> b = bd.bug_from_shortname("b")
>>> b.load_comments()
>>> mergeB = b.comment_from_shortname(":3")
@@ -105,12 +105,12 @@ def execute(args):
Date: Thu, 01 Jan 1970 00:00:01 +0000
<BLANKLINE>
1 2
- --------- Comment ---------
- Name: b:2
- From: wking <wking@thor.yang.physics.drexel.edu>
- Date: Thu, 01 Jan 1970 00:00:02 +0000
+ --------- Comment ---------
+ Name: b:2
+ From: wking <wking@thor.yang.physics.drexel.edu>
+ Date: Thu, 01 Jan 1970 00:00:02 +0000
<BLANKLINE>
- 1 2 3 4
+ 1 2 3 4
--------- Comment ---------
Name: b:3
From: wking <wking@thor.yang.physics.drexel.edu>
@@ -122,12 +122,12 @@ def execute(args):
"""
options, args = get_parser().parse_args(args)
if len(args) < 2:
- raise cmdutil.UserError("Please two bug ids.")
+ raise cmdutil.UsageError("Please specify two bug ids.")
if len(args) > 2:
help()
- raise cmdutil.UserError("Too many arguments.")
+ raise cmdutil.UsageError("Too many arguments.")
- bd = bugdir.BugDir(from_disk=True)
+ bd = bugdir.BugDir(from_disk=True, manipulate_encodings=not test)
bugA = bd.bug_from_shortname(args[0])
bugA.load_comments()
bugB = bd.bug_from_shortname(args[1])
diff --git a/becommands/new.py b/becommands/new.py
index caa1549..bc17f83 100644
--- a/becommands/new.py
+++ b/becommands/new.py
@@ -18,14 +18,14 @@
from libbe import cmdutil, bugdir
__desc__ = __doc__
-def execute(args):
+def execute(args, test=False):
"""
>>> import os, time
>>> from libbe import bug
>>> bd = bugdir.simple_bug_dir()
>>> os.chdir(bd.root)
>>> bug.uuid_gen = lambda: "X"
- >>> execute (["this is a test",])
+ >>> execute (["this is a test",], test=True)
Created bug with ID X
>>> bd.load()
>>> bug = bd.bug_from_uuid("X")
@@ -40,8 +40,8 @@ def execute(args):
"""
options, args = get_parser().parse_args(args)
if len(args) != 1:
- raise cmdutil.UserError("Please supply a summary message")
- bd = bugdir.BugDir(from_disk=True)
+ raise cmdutil.UsageError("Please supply a summary message")
+ bd = bugdir.BugDir(from_disk=True, manipulate_encodings=not test)
bug = bd.new_bug(summary=args[0])
bd.save()
print "Created bug with ID %s" % bd.bug_shortname(bug)
diff --git a/becommands/open.py b/becommands/open.py
index 788a183..9a9667d 100644
--- a/becommands/open.py
+++ b/becommands/open.py
@@ -18,25 +18,24 @@
from libbe import cmdutil, bugdir
__desc__ = __doc__
-def execute(args):
+def execute(args, test=False):
"""
>>> import os
>>> bd = bugdir.simple_bug_dir()
>>> os.chdir(bd.root)
>>> print bd.bug_from_shortname("b").status
closed
- >>> execute(["b"])
+ >>> execute(["b"], test=True)
>>> bd._clear_bugs()
>>> print bd.bug_from_shortname("b").status
open
"""
options, args = get_parser().parse_args(args)
if len(args) == 0:
- raise cmdutil.UserError("Please specify a bug id.")
+ raise cmdutil.UsageError, "Please specify a bug id."
if len(args) > 1:
- help()
- raise cmdutil.UserError("Too many arguments.")
- bd = bugdir.BugDir(from_disk=True)
+ raise cmdutil.UsageError, "Too many arguments."
+ bd = bugdir.BugDir(from_disk=True, manipulate_encodings=not test)
bug = bd.bug_from_shortname(args[0])
bug.status = "open"
bd.save()
diff --git a/becommands/remove.py b/becommands/remove.py
index 8f7c2c6..386d9d4 100644
--- a/becommands/remove.py
+++ b/becommands/remove.py
@@ -18,7 +18,7 @@
from libbe import cmdutil, bugdir
__desc__ = __doc__
-def execute(args):
+def execute(args, test=False):
"""
>>> from libbe import mapfile
>>> import os
@@ -26,7 +26,7 @@ def execute(args):
>>> os.chdir(bd.root)
>>> print bd.bug_from_shortname("b").status
closed
- >>> execute (["b"])
+ >>> execute (["b"], test=True)
Removed bug b
>>> bd._clear_bugs()
>>> try:
@@ -37,8 +37,8 @@ def execute(args):
"""
options, args = get_parser().parse_args(args)
if len(args) != 1:
- raise cmdutil.UserError("Please specify a bug id.")
- bd = bugdir.BugDir(from_disk=True)
+ raise cmdutil.UsageError, "Please specify a bug id."
+ bd = bugdir.BugDir(from_disk=True, manipulate_encodings=not test)
bug = bd.bug_from_shortname(args[0])
bd.remove_bug(bug)
bd.save()
diff --git a/becommands/set.py b/becommands/set.py
index 24011f0..3904262 100644
--- a/becommands/set.py
+++ b/becommands/set.py
@@ -18,25 +18,24 @@
from libbe import cmdutil, bugdir
__desc__ = __doc__
-def execute(args):
+def execute(args, test=False):
"""
>>> import os
>>> bd = bugdir.simple_bug_dir()
>>> os.chdir(bd.root)
- >>> execute(["target"])
+ >>> execute(["target"], test=True)
None
- >>> execute(["target", "tomorrow"])
- >>> execute(["target"])
+ >>> execute(["target", "tomorrow"], test=True)
+ >>> execute(["target"], test=True)
tomorrow
- >>> execute(["target", "none"])
- >>> execute(["target"])
+ >>> execute(["target", "none"], test=True)
+ >>> execute(["target"], test=True)
None
"""
options, args = get_parser().parse_args(args)
if len(args) > 2:
- help()
- raise cmdutil.UserError("Too many arguments.")
- bd = bugdir.BugDir(from_disk=True)
+ raise cmdutil.UsageError, "Too many arguments"
+ bd = bugdir.BugDir(from_disk=True, manipulate_encodings=not test)
if len(args) == 0:
keys = bd.settings.keys()
keys.sort()
diff --git a/becommands/set_root.py b/becommands/set_root.py
index e17bd87..11f38b9 100644
--- a/becommands/set_root.py
+++ b/becommands/set_root.py
@@ -19,7 +19,7 @@ import os.path
from libbe import cmdutil, bugdir
__desc__ = __doc__
-def execute(args):
+def execute(args, test=False):
"""
>>> from libbe import utility, rcs
>>> import os
@@ -29,7 +29,7 @@ def execute(args):
... except bugdir.NoBugDir, e:
... True
True
- >>> execute([dir.path])
+ >>> execute([dir.path], test=True)
No revision control detected.
Directory initialized.
>>> del(dir)
@@ -40,34 +40,31 @@ def execute(args):
>>> rcs.init('.')
>>> print rcs.name
Arch
- >>> execute([])
+ >>> execute([], test=True)
Using Arch for revision control.
Directory initialized.
>>> rcs.cleanup()
>>> try:
- ... execute(['.'])
+ ... execute(['.'], test=True)
... except cmdutil.UserError, e:
... str(e).startswith("Directory already initialized: ")
True
- >>> execute(['/highly-unlikely-to-exist'])
+ >>> execute(['/highly-unlikely-to-exist'], test=True)
Traceback (most recent call last):
UserError: No such directory: /highly-unlikely-to-exist
>>> os.chdir('/')
"""
options, args = get_parser().parse_args(args)
if len(args) > 1:
- print help()
- raise cmdutil.UserError, "Too many arguments"
+ raise cmdutil.UsageError
if len(args) == 1:
basedir = args[0]
else:
basedir = "."
- if os.path.exists(basedir) == False:
- pass
- #raise cmdutil.UserError, "No such directory: %s" % basedir
try:
- bd = bugdir.BugDir(basedir, from_disk=False, sink_to_existing_root=False, assert_new_BugDir=True)
+ bd = bugdir.BugDir(basedir, from_disk=False, sink_to_existing_root=False, assert_new_BugDir=True,
+ manipulate_encodings=not test)
except bugdir.NoRootEntry:
raise cmdutil.UserError("No such directory: %s" % basedir)
except bugdir.AlreadyInitialized:
diff --git a/becommands/severity.py b/becommands/severity.py
index 3adefaa..3c856de 100644
--- a/becommands/severity.py
+++ b/becommands/severity.py
@@ -19,25 +19,24 @@ from libbe import cmdutil, bugdir
from libbe.bug import severity_values, severity_description
__desc__ = __doc__
-def execute(args):
+def execute(args, test=False):
"""
>>> import os
>>> bd = bugdir.simple_bug_dir()
>>> os.chdir(bd.root)
- >>> execute(["a"])
+ >>> execute(["a"], test=True)
minor
- >>> execute(["a", "wishlist"])
- >>> execute(["a"])
+ >>> execute(["a", "wishlist"], test=True)
+ >>> execute(["a"], test=True)
wishlist
- >>> execute(["a", "none"])
+ >>> execute(["a", "none"], test=True)
Traceback (most recent call last):
UserError: Invalid severity level: none
"""
options, args = get_parser().parse_args(args)
if len(args) not in (1,2):
- print help()
- return
- bd = bugdir.BugDir(from_disk=True)
+ raise cmdutil.UsageError
+ bd = bugdir.BugDir(from_disk=True, manipulate_encodings=not test)
bug = bd.bug_from_shortname(args[0])
if len(args) == 1:
print bug.severity
@@ -46,7 +45,7 @@ def execute(args):
bug.severity = args[1]
except ValueError, e:
if e.name != "severity":
- raise
+ raise e
raise cmdutil.UserError ("Invalid severity level: %s" % e.value)
bd.save()
diff --git a/becommands/show.py b/becommands/show.py
index 45cd6ad..3bd7e63 100644
--- a/becommands/show.py
+++ b/becommands/show.py
@@ -18,12 +18,12 @@
from libbe import cmdutil, bugdir
__desc__ = __doc__
-def execute(args):
+def execute(args, test=False):
"""
>>> import os
>>> bd = bugdir.simple_bug_dir()
>>> os.chdir(bd.root)
- >>> execute (["a",])
+ >>> execute (["a",], test=True)
ID : a
Short name : a
Severity : minor
@@ -37,11 +37,11 @@ def execute(args):
"""
options, args = get_parser().parse_args(args)
if len(args) == 0:
- raise cmdutil.UserError("Please specify a bug id.")
- bd = bugdir.BugDir(from_disk=True)
+ raise cmdutil.UsageError
+ bd = bugdir.BugDir(from_disk=True, manipulate_encodings=not test)
for bugid in args:
bug = bd.bug_from_shortname(bugid)
- print bug.string(show_comments=True).encode('utf-8')
+ print bug.string(show_comments=True)
def get_parser():
parser = cmdutil.CmdOptionParser("be show BUG-ID [BUG-ID ...]")
diff --git a/becommands/status.py b/becommands/status.py
index a30b3d6..73d43f8 100644
--- a/becommands/status.py
+++ b/becommands/status.py
@@ -19,29 +19,28 @@ from libbe import cmdutil, bugdir
from libbe.bug import status_values, status_description
__desc__ = __doc__
-def execute(args):
+def execute(args, test=False):
"""
>>> import os
>>> bd = bugdir.simple_bug_dir()
>>> os.chdir(bd.root)
- >>> execute(["a"])
+ >>> execute(["a"], test=True)
open
- >>> execute(["a", "closed"])
- >>> execute(["a"])
+ >>> execute(["a", "closed"], test=True)
+ >>> execute(["a"], test=True)
closed
- >>> execute(["a", "none"])
+ >>> execute(["a", "none"], test=True)
Traceback (most recent call last):
UserError: Invalid status: none
"""
options, args = get_parser().parse_args(args)
if len(args) not in (1,2):
- print help()
- return
- bd = bugdir.BugDir(from_disk=True)
+ raise cmdutil.UsageError
+ bd = bugdir.BugDir(from_disk=True, manipulate_encodings=not test)
bug = bd.bug_from_shortname(args[0])
if len(args) == 1:
print bug.status
- elif len(args) == 2:
+ else:
try:
bug.status = args[1]
except ValueError, e:
diff --git a/becommands/target.py b/becommands/target.py
index dce100f..4371ef0 100644
--- a/becommands/target.py
+++ b/becommands/target.py
@@ -18,33 +18,32 @@
from libbe import cmdutil, bugdir
__desc__ = __doc__
-def execute(args):
+def execute(args, test=False):
"""
>>> import os
>>> bd = bugdir.simple_bug_dir()
>>> os.chdir(bd.root)
- >>> execute(["a"])
+ >>> execute(["a"], test=True)
No target assigned.
- >>> execute(["a", "tomorrow"])
- >>> execute(["a"])
+ >>> execute(["a", "tomorrow"], test=True)
+ >>> execute(["a"], test=True)
tomorrow
- >>> execute(["a", "none"])
- >>> execute(["a"])
+ >>> execute(["a", "none"], test=True)
+ >>> execute(["a"], test=True)
No target assigned.
"""
options, args = get_parser().parse_args(args)
- assert(len(args) in (0, 1, 2))
- if len(args) == 0:
- print help()
- return
- bd = bugdir.BugDir(from_disk=True)
+ if len(args) not in (1, 2):
+ raise cmdutil.UsageError
+ bd = bugdir.BugDir(from_disk=True, manipulate_encodings=not test)
bug = bd.bug_from_shortname(args[0])
if len(args) == 1:
if bug.target is None:
print "No target assigned."
else:
print bug.target
- elif len(args) == 2:
+ else:
+ assert len(args) == 2
if args[1] == "none":
bug.target = None
else:
diff --git a/libbe/arch.py b/libbe/arch.py
index fd953a4..1173535 100644
--- a/libbe/arch.py
+++ b/libbe/arch.py
@@ -14,10 +14,11 @@
# 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
+import codecs
import os
+import re
import shutil
import time
-import re
import unittest
import doctest
@@ -133,13 +134,16 @@ class Arch(RCS):
"""
tagpath = os.path.join(path, "{arch}", "=tagging-method")
lines_out = []
- for line in file(tagpath, "rb"):
- line.decode("utf-8")
+ f = codecs.open(tagpath, "r", self.encoding)
+ for line in f:
if line.startswith("source "):
lines_out.append("source ^[._=a-zA-X0-9].*$\n")
else:
lines_out.append(line)
- file(tagpath, "wb").write("".join(lines_out).encode("utf-8"))
+ f.close()
+ f = codecs.open(tagpath, "w", self.encoding)
+ f.write("".join(lines_out))
+ f.close()
def _add_project_code(self, path):
# http://mwolson.org/projects/GettingStartedWithArch.html
@@ -215,7 +219,9 @@ class Arch(RCS):
return [os.path.join(root, p) for p in inv_str.split('\n')]
def _add_dir_rule(self, rule, dirname, root):
inv_path = os.path.join(dirname, '.arch-inventory')
- file(inv_path, "ab").write(rule)
+ f = codecs.open(inv_path, "a", self.encoding)
+ f.write(rule)
+ f.close()
if os.path.realpath(inv_path) not in self._list_added(root):
paranoid = self.paranoid
self.paranoid = False
@@ -233,12 +239,16 @@ class Arch(RCS):
pass
def _rcs_get_file_contents(self, path, revision=None):
if revision == None:
- return file(self._u_abspath(path), "rb").read()
+ return RCS._rcs_get_file_contents(self, path, revision)
else:
status,output,error = \
self._invoke_client("file-find", path, revision)
- path = output.rstrip('\n')
- return file(self._u_abspath(path), "rb").read()
+ relpath = output.rstrip('\n')
+ abspath = os.path.join(self.rootdir, relpath)
+ f = codecs.open(abspath, "r", self.encoding)
+ contents = f.read()
+ f.close()
+ return contents
def _rcs_duplicate_repo(self, directory, revision=None):
if revision == None:
RCS._rcs_duplicate_repo(self, directory, revision)
diff --git a/libbe/bug.py b/libbe/bug.py
index 68cff7b..67051f2 100644
--- a/libbe/bug.py
+++ b/libbe/bug.py
@@ -182,7 +182,10 @@ class Bug(object):
if show_comments == True:
if self._comments_loaded == False:
self.load_comments()
- comout = self.comment_root.string_thread(auto_name_map=True,
+ # take advantage of the string_thread(auto_name_map=True)
+ # SIDE-EFFECT of sorting by bug time.
+ comout = self.comment_root.string_thread(flatten=False,
+ auto_name_map=True,
bug_shortname=shortname)
output = bugout + '\n' + comout.rstrip('\n')
else :
diff --git a/libbe/bugdir.py b/libbe/bugdir.py
index 596922f..6bb6a43 100644
--- a/libbe/bugdir.py
+++ b/libbe/bugdir.py
@@ -24,8 +24,9 @@ import doctest
import mapfile
import bug
-import utility
import rcs
+import encoding
+import utility
class NoBugDir(Exception):
@@ -64,7 +65,9 @@ class MultipleBugMatches(ValueError):
TREE_VERSION_STRING = "Bugs Everywhere Tree 1 0\n"
-def setting_property(name, valid=None, doc=None):
+def setting_property(name, valid=None, default=None, doc=None):
+ if default != None:
+ raise NotImplementedError
def getter(self):
value = self.settings.get(name)
if valid is not None:
@@ -88,7 +91,27 @@ def setting_property(name, valid=None, doc=None):
class BugDir (list):
"""
- File-system access:
+ Sink to existing root
+ ======================
+
+ Consider the following usage case:
+ You have a bug directory rooted in
+ /path/to/source
+ by which I mean the '.be' directory is at
+ /path/to/source/.be
+ However, you're of in some subdirectory like
+ /path/to/source/GUI/testing
+ and you want to comment on a bug. Setting sink_to_root=True wen
+ you initialize your BugDir will cause it to search for the '.be'
+ file in the ancestors of the path you passed in as 'root'.
+ /path/to/source/GUI/testing/.be miss
+ /path/to/source/GUI/.be miss
+ /path/to/source/.be hit!
+ So it still roots itself appropriately without much work for you.
+
+ File-system access
+ ==================
+
When rooted in non-bugdir directory, BugDirs live completely in
memory until the first call to .save(). This creates a '.be'
sub-directory containing configurations options, bugs, comments,
@@ -98,12 +121,35 @@ class BugDir (list):
will only load information from the file system when it loads new
bugs/comments that it doesn't already have in memory, or when it
explicitly asked to do so (e.g. .load() or __init__(from_disk=True)).
+
+ Allow RCS initialization
+ ========================
+
+ This one is for testing purposes. Setting it to True allows the
+ BugDir to search for an installed RCS backend and initialize it in
+ the root directory. This is a convenience option for supporting
+ tests of versioning functionality (e.g. .duplicate_bugdir).
+
+ Disable encoding manipulation
+ =============================
+
+ This one is for testing purposed. You might have non-ASCII
+ Unicode in your bugs, comments, files, etc. BugDir instances try
+ and support your preferred encoding scheme (e.g. "utf-8") when
+ dealing with stream and file input/output. For stream output,
+ this involves replacing sys.stdout and sys.stderr
+ (libbe.encode.set_IO_stream_encodings). However this messes up
+ doctest's output catching. In order to support doctest tests
+ using BugDirs, set manipulate_encodings=False, and stick to ASCII
+ in your tests.
"""
def __init__(self, root=None, sink_to_existing_root=True,
assert_new_BugDir=False, allow_rcs_init=False,
+ manipulate_encodings=True,
from_disk=False, rcs=None):
list.__init__(self)
self._save_user_id = False
+ self._manipulate_encodings = manipulate_encodings
self.settings = {}
if root == None:
root = os.getcwd()
@@ -131,7 +177,8 @@ class BugDir (list):
"""
if not os.path.exists(path):
raise NoRootEntry(path)
- versionfile = utility.search_parent_directories(path, os.path.join(".be", "version"))
+ versionfile=utility.search_parent_directories(path,
+ os.path.join(".be", "version"))
if versionfile != None:
beroot = os.path.dirname(versionfile)
root = os.path.dirname(beroot)
@@ -142,11 +189,11 @@ class BugDir (list):
raise NoBugDir(path)
return beroot
- def get_version(self, path=None):
- if self.rcs_name == None:
- # Use a temporary RCS to check the version for the first time
+ def get_version(self, path=None, use_none_rcs=False):
+ if use_none_rcs == True:
RCS = rcs.rcs_by_name("None")
RCS.root(self.root)
+ RCS.encoding = encoding.get_encoding()
else:
RCS = self.rcs
@@ -159,47 +206,65 @@ class BugDir (list):
self.rcs.set_file_contents(self.get_path("version"),
TREE_VERSION_STRING)
- rcs_name = setting_property("rcs_name",
- ("None", "bzr", "git", "Arch", "hg"),
- doc=
-"""The name of the current RCS. Kept seperate to make saving/loading
-settings easy. Don't set this attribute. Set .rcs instead, and
-.rcs_name will be automatically adjusted.""")
-
- _rcs = None
+ def _get_encoding(self):
+ if self._encoding == None:
+ return encoding.get_encoding()
+ else:
+ return self._encoding
+ def _set_encoding(self, new_encoding):
+ if new_encoding != None:
+ if encoding.known_encoding(new_encoding) == False:
+ raise InvalidValue("encoding", new_encoding)
+ self._encoding = new_encoding
+ if self._manipulate_encodings == True:
+ encoding.set_IO_stream_encodings(self.encoding)
+ if hasattr(self, "rcs"):
+ if self.rcs != None:
+ self.rcs.encoding = self.encoding
+ _encoding = setting_property("encoding",
+ doc=
+"""The default input/output encoding to use (e.g. "utf-8").
+Dont' set this attribute, set .encoding instead.""")
+ encoding = property(_get_encoding, _set_encoding, doc=
+"""The default input/output encoding to use (e.g. "utf-8").""")
def _get_rcs(self):
return self._rcs
-
def _set_rcs(self, new_rcs):
if new_rcs == None:
new_rcs = rcs.rcs_by_name("None")
+ new_rcs.encoding = self.encoding
self._rcs = new_rcs
new_rcs.root(self.root)
self.rcs_name = new_rcs.name
-
+ _rcs = None
rcs = property(_get_rcs, _set_rcs,
doc="A revision control system (RCS) instance")
+ rcs_name = setting_property("rcs_name",
+ ("None", "bzr", "git", "Arch", "hg"),
+ doc=
+"""The name of the current RCS. Kept seperate to make saving/loading
+settings easy. Don't set this attribute. Set .rcs instead, and
+.rcs_name will be automatically adjusted.""")
- _user_id = setting_property("user_id", doc=
-"""The user's prefered name. Kept seperate to make saving/loading
-settings easy. Don't set this attribute. Set .user_id instead,
-and ._user_id will be automatically adjusted. This setting is
-only saved if ._save_user_id == True""")
def _get_user_id(self):
if self._user_id == None and self.rcs != None:
self._user_id = self.rcs.get_user_id()
return self._user_id
-
def _set_user_id(self, user_id):
if self.rcs != None:
self.rcs.user_id = user_id
self._user_id = user_id
-
user_id = property(_get_user_id, _set_user_id, doc=
"""The user's prefered name, e.g 'John Doe <jdoe@example.com>'. Note
that the Arch RCS backend *enforces* ids with this format.""")
+ _user_id = setting_property("user_id", doc=
+"""The user's prefered name. Kept seperate to make saving/loading
+settings easy. Don't set this attribute. Set .user_id instead,
+and ._user_id will be automatically adjusted. This setting is
+only saved if ._save_user_id == True""")
+
target = setting_property("target",
doc="The current project development target")
@@ -231,7 +296,7 @@ that the Arch RCS backend *enforces* ids with this format.""")
return new_rcs
def load(self):
- version = self.get_version()
+ version = self.get_version(use_none_rcs=True)
if version != TREE_VERSION_STRING:
raise NotImplementedError, \
"BugDir cannot handle version '%s' yet." % version
@@ -241,6 +306,7 @@ that the Arch RCS backend *enforces* ids with this format.""")
self.settings = self._get_settings(self.get_path("settings"))
self.rcs = rcs.rcs_by_name(self.rcs_name)
+ self.encoding = self.encoding # setup encoding, IO_stream_encoding...
if self.settings.get("user_id") != None:
self.save_user_id() # was a user name in the settings file
@@ -292,6 +358,8 @@ that the Arch RCS backend *enforces* ids with this format.""")
if "user_id" in settings:
settings = copy.copy(settings)
del settings["user_id"]
+ if settings.get("encoding") == encoding.get_encoding():
+ del settings["encoding"] # don't duplicate system default
allow_no_rcs = not self.rcs.path_in_root(settings_path)
# allow_no_rcs=True should only be for the special case of
# configuring duplicate bugdir settings
@@ -310,7 +378,7 @@ that the Arch RCS backend *enforces* ids with this format.""")
duplicate_settings["user_id"] = self.user_id
self._save_settings(duplicate_settings_path, duplicate_settings)
- return BugDir(duplicate_path, from_disk=True)
+ return BugDir(duplicate_path, from_disk=True, manipulate_encodings=self._manipulate_encodings)
def remove_duplicate_bugdir(self):
self.rcs.remove_duplicate_repo()
@@ -423,7 +491,8 @@ def simple_bug_dir():
"""
dir = utility.Dir()
assert os.path.exists(dir.path)
- bugdir = BugDir(dir.path, sink_to_existing_root=False, allow_rcs_init=True)
+ bugdir = BugDir(dir.path, sink_to_existing_root=False, allow_rcs_init=True,
+ manipulate_encodings=False)
bugdir._dir_ref = dir # postpone cleanup since dir.__del__() removes dir.
bug_a = bugdir.new_bug("a", summary="Bug A")
bug_a.creator = "John Doe <jdoe@example.com>"
diff --git a/libbe/bzr.py b/libbe/bzr.py
index a0ae715..38af6bb 100644
--- a/libbe/bzr.py
+++ b/libbe/bzr.py
@@ -55,7 +55,7 @@ class Bzr(RCS):
pass
def _rcs_get_file_contents(self, path, revision=None):
if revision == None:
- return file(os.path.join(self.rootdir, path), "rb").read()
+ return RCS._rcs_get_file_contents(self, path, revision)
else:
status,output,error = \
self._u_invoke_client("cat","-r",revision,path)
diff --git a/libbe/cmdutil.py b/libbe/cmdutil.py
index 6d7ab01..1a321e9 100644
--- a/libbe/cmdutil.py
+++ b/libbe/cmdutil.py
@@ -16,14 +16,14 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
import optparse
import os
-import locale
from textwrap import TextWrapper
from StringIO import StringIO
import doctest
import bugdir
import plugin
-import utility
+import encoding
+
class UserError(Exception):
def __init__(self, msg):
@@ -34,6 +34,13 @@ class UserErrorWrap(UserError):
UserError.__init__(self, str(exception))
self.exception = exception
+class GetHelp(Exception):
+ pass
+
+class UsageError(Exception):
+ pass
+
+
def iter_commands():
for name, module in plugin.iter_plugins("becommands"):
yield name.replace("_", "-"), module
@@ -52,9 +59,11 @@ def get_command(command_name):
raise UserError("Unknown command %s" % command_name)
return cmd
+
def execute(cmd, args):
- encoding = locale.getpreferredencoding() or 'ascii'
- return get_command(cmd).execute([a.decode(encoding) for a in args])
+ enc = encoding.get_encoding()
+ get_command(cmd).execute([a.decode(enc) for a in args])
+ return 0
def help(cmd=None):
if cmd != None:
@@ -71,17 +80,8 @@ def help(cmd=None):
ret.append("be %s%*s %s" % (name, numExtraSpaces, "", desc))
return "\n".join(ret)
-class GetHelp(Exception):
- pass
-
-
-class UsageError(Exception):
- pass
-
-
def raise_get_help(option, opt, value, parser):
raise GetHelp
-
class CmdOptionParser(optparse.OptionParser):
def __init__(self, usage):
diff --git a/libbe/comment.py b/libbe/comment.py
index 579e294..bd085fa 100644
--- a/libbe/comment.py
+++ b/libbe/comment.py
@@ -243,11 +243,19 @@ class Comment(Tree):
self.add_reply(reply)
return reply
- def string_thread(self, name_map={}, indent=0,
+ def string_thread(self, name_map={}, indent=0, flatten=True,
auto_name_map=False, bug_shortname=None):
"""
Return a sting displaying a thread of comments.
bug_shortname is only used if auto_name_map == True.
+
+ SIDE-EFFECT: if auto_name_map==True, calls comment_shornames()
+ which will sort the tree by comment.time. Avoid by calling
+ name_map = {}
+ for shortname,comment in comm.comment_shortnames(bug_shortname):
+ name_map[comment.uuid] = shortname
+ comm.sort(key=lambda c : c.From) # your sort
+ comm.string_thread(name_map=name_map)
>>> a = Comment(bug=None, uuid="a", body="Insightful remarks")
>>> a.time = utility.str_to_time("Thu, 20 Nov 2008 01:00:00 +0000")
@@ -261,7 +269,7 @@ class Comment(Tree):
>>> d.uuid = "d"
>>> d.time = utility.str_to_time("Thu, 20 Nov 2008 04:00:00 +0000")
>>> a.sort(key=lambda comm : comm.time)
- >>> print a.string_thread()
+ >>> print a.string_thread(flatten=True)
--------- Comment ---------
Name: a
From:
@@ -317,7 +325,7 @@ class Comment(Tree):
for shortname,comment in self.comment_shortnames(bug_shortname):
name_map[comment.uuid] = shortname
stringlist = []
- for depth,comment in self.thread(flatten=True):
+ for depth,comment in self.thread(flatten=flatten):
ind = 2*depth+indent
if comment.uuid in name_map:
sname = name_map[comment.uuid]
diff --git a/libbe/config.py b/libbe/config.py
index 79c0d6f..94c700e 100644
--- a/libbe/config.py
+++ b/libbe/config.py
@@ -15,30 +15,40 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
import ConfigParser
+import codecs
+import locale
import os.path
+import sys
import doctest
+default_encoding = sys.getfilesystemencoding() or locale.getpreferredencoding()
+
def path():
"""Return the path to the per-user config file"""
return os.path.expanduser("~/.bugs_everywhere")
-def set_val(name, value, section="DEFAULT"):
+def set_val(name, value, section="DEFAULT", encoding=None):
"""Set a value in the per-user config file
:param name: The name of the value to set
:param value: The new value to set (or None to delete the value)
:param section: The section to store the name/value in
"""
+ if encoding == None:
+ encoding = default_encoding
config = ConfigParser.ConfigParser()
- config.read(path())
+ f = codecs.open(path(), "r", encoding)
+ config.readfp(f, path())
+ f.close()
if value is not None:
config.set(section, name, value)
else:
config.remove_option(section, name)
- config.write(file(path(), "wb"))
- pass
+ f = codecs.open(path(), "w", encoding)
+ config.write(f)
+ f.close()
-def get_val(name, section="DEFAULT"):
+def get_val(name, section="DEFAULT", encoding=None):
"""
Get a value from the per-user config file
@@ -49,13 +59,17 @@ def get_val(name, section="DEFAULT"):
True
>>> set_val("junk", "random")
>>> get_val("junk")
- 'random'
+ u'random'
>>> set_val("junk", None)
>>> get_val("junk") is None
True
"""
+ if encoding == None:
+ encoding = default_encoding
config = ConfigParser.ConfigParser()
- config.read(path())
+ f = codecs.open(path(), "r", encoding)
+ config.readfp(f, path())
+ f.close()
try:
return config.get(section, name)
except ConfigParser.NoOptionError:
diff --git a/libbe/diff.py b/libbe/diff.py
index 86a91ca..5fc0166 100644
--- a/libbe/diff.py
+++ b/libbe/diff.py
@@ -46,12 +46,13 @@ def diff_report(diff_data, bug_dir):
added.sort(cmp_severity)
removed.sort(cmp_severity)
modified.sort(modified_cmp)
-
+ lines = []
+
if len(added) > 0:
- print "New bug reports:"
+ lines.append("New bug reports:")
for bug in added:
- print bug.string(shortlist=True)
- print ""
+ lines.extend(bug.string(shortlist=True).splitlines())
+ lines.append("")
if len(modified) > 0:
printed = False
@@ -61,15 +62,18 @@ def diff_report(diff_data, bug_dir):
continue
if not printed:
printed = True
- print "Modified bug reports:"
- print change_str
- print ""
+ lines.append("Modified bug reports:")
+ lines.extend(change_str.splitlines())
+ if printed == True:
+ lines.append("")
- if len(removed) > 0:
- print "Removed bug reports:"
+ if len(removed) > 0:
+ lines.append("Removed bug reports:")
for bug in removed:
- print bug.string(shortlist=True)
- print ""
+ lines.extend(bug.string(shortlist=True).splitlines())
+ lines.append("")
+
+ return '\n'.join(lines)
def change_lines(old, new, attributes):
change_list = []
diff --git a/libbe/editor.py b/libbe/editor.py
new file mode 100644
index 0000000..4a63e5c
--- /dev/null
+++ b/libbe/editor.py
@@ -0,0 +1,103 @@
+# Bugs Everywhere, a distributed bugtracker
+# Copyright (C) 2005 Aaron Bentley and Panometrics, Inc.
+# <abentley@panoramicfeedback.com>
+#
+# 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
+
+import codecs
+import locale
+import os
+import sys
+import tempfile
+import doctest
+
+default_encoding = sys.getfilesystemencoding() or locale.getpreferredencoding()
+
+comment_marker = u"== Anything below this line will be ignored\n"
+
+class CantFindEditor(Exception):
+ def __init__(self):
+ Exception.__init__(self, "Can't find editor to get string from")
+
+def editor_string(comment=None, encoding=None):
+ """Invokes the editor, and returns the user_produced text as a string
+
+ >>> if "EDITOR" in os.environ:
+ ... del os.environ["EDITOR"]
+ >>> if "VISUAL" in os.environ:
+ ... del os.environ["VISUAL"]
+ >>> editor_string()
+ Traceback (most recent call last):
+ CantFindEditor: Can't find editor to get string from
+ >>> os.environ["EDITOR"] = "echo bar > "
+ >>> editor_string()
+ u'bar\\n'
+ >>> os.environ["VISUAL"] = "echo baz > "
+ >>> editor_string()
+ u'baz\\n'
+ >>> del os.environ["EDITOR"]
+ >>> del os.environ["VISUAL"]
+ """
+ if encoding == None:
+ encoding = default_encoding
+ for name in ('VISUAL', 'EDITOR'):
+ try:
+ editor = os.environ[name]
+ break
+ except KeyError:
+ pass
+ else:
+ raise CantFindEditor()
+ fhandle, fname = tempfile.mkstemp()
+ try:
+ if comment is not None:
+ os.write(fhandle, '\n'+comment_string(comment))
+ os.close(fhandle)
+ oldmtime = os.path.getmtime(fname)
+ os.system("%s %s" % (editor, fname))
+ f = codecs.open(fname, "r", encoding)
+ output = trimmed_string(f.read())
+ f.close()
+ if output.rstrip('\n') == "":
+ output = None
+ finally:
+ os.unlink(fname)
+ return output
+
+
+def comment_string(comment):
+ """
+ >>> comment_string('hello') == comment_marker+"hello"
+ True
+ """
+ return comment_marker + comment
+
+
+def trimmed_string(instring):
+ """
+ >>> trimmed_string("hello\\n"+comment_marker)
+ u'hello\\n'
+ >>> trimmed_string("hi!\\n" + comment_string('Booga'))
+ u'hi!\\n'
+ """
+ out = []
+ for line in instring.splitlines(True):
+ if line.startswith(comment_marker):
+ break
+ out.append(line)
+ return ''.join(out)
+
+suite = doctest.DocTestSuite()
diff --git a/libbe/encoding.py b/libbe/encoding.py
new file mode 100644
index 0000000..8b0ef73
--- /dev/null
+++ b/libbe/encoding.py
@@ -0,0 +1,53 @@
+# Bugs Everywhere, a distributed bugtracker
+# Copyright (C) 2005 Aaron Bentley and Panometrics, Inc.
+# <abentley@panoramicfeedback.com>
+#
+# 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
+import codecs
+import locale
+import sys
+import doctest
+
+def get_encoding():
+ """
+ Guess a useful input/output/filesystem encoding... Maybe we nees
+ seperate encodings for input/output and filessytem? Hmm...
+ """
+ encoding = locale.getpreferredencoding() or sys.getdefaultencoding()
+ if sys.platform != 'win32' or sys.version_info[:2] > (2, 3):
+ encoding = locale.getlocale(locale.LC_TIME)[1] or encoding
+ # Python 2.3 on windows doesn't know about 'XYZ' alias for 'cpXYZ'
+ return encoding
+
+def known_encoding(encoding):
+ """
+ >>> known_encoding("highly-unlikely-encoding")
+ False
+ >>> known_encoding(get_encoding())
+ True
+ """
+ try:
+ codecs.lookup(encoding)
+ return True
+ except LookupError:
+ return False
+
+def set_IO_stream_encodings(encoding):
+ sys.stdin = codecs.getreader(encoding)(sys.__stdin__)
+ sys.stdout = codecs.getwriter(encoding)(sys.__stdout__)
+ sys.stderr = codecs.getwriter(encoding)(sys.__stderr__)
+
+suite = doctest.DocTestSuite()
diff --git a/libbe/git.py b/libbe/git.py
index 046e72e..98fda2b 100644
--- a/libbe/git.py
+++ b/libbe/git.py
@@ -69,7 +69,7 @@ class Git(RCS):
self._rcs_add(path)
def _rcs_get_file_contents(self, path, revision=None):
if revision == None:
- return file(self._u_abspath(path), "rb").read()
+ return RCS._rcs_get_file_contents(self, path, revision)
else:
arg = "%s:%s" % (revision,path)
status,output,error = self._u_invoke_client("show", arg)
diff --git a/libbe/hg.py b/libbe/hg.py
index 27cbb79..c00d7e2 100644
--- a/libbe/hg.py
+++ b/libbe/hg.py
@@ -58,14 +58,14 @@ class Hg(RCS):
pass
def _rcs_get_file_contents(self, path, revision=None):
if revision == None:
- return file(os.path.join(self.rootdir, path), "rb").read()
+ return RCS._rcs_get_file_contents(self, path, revision)
else:
status,output,error = \
self._u_invoke_client("cat","-r",revision,path)
return output
def _rcs_duplicate_repo(self, directory, revision=None):
if revision == None:
- RCS._rcs_duplicate_repo(self, directory, revision)
+ return RCS._rcs_duplicate_repo(self, directory, revision)
else:
self._u_invoke_client("archive", "--rev", revision, directory)
def _rcs_commit(self, commitfile):
diff --git a/libbe/rcs.py b/libbe/rcs.py
index 3519c3d..786f9dd 100644
--- a/libbe/rcs.py
+++ b/libbe/rcs.py
@@ -15,13 +15,14 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
from subprocess import Popen, PIPE
+import codecs
import os
import os.path
-from socket import gethostname
import re
+from socket import gethostname
+import shutil
import sys
import tempfile
-import shutil
import unittest
import doctest
@@ -77,8 +78,9 @@ class PathNotInRoot(Exception):
self.root = root
class NoSuchFile(Exception):
- def __init__(self, pathname):
- Exception.__init__(self, "No such file: %s" % pathname)
+ def __init__(self, pathname, root="."):
+ path = os.path.abspath(os.path.join(root, pathname))
+ Exception.__init__(self, "No such file: %s" % path)
def new():
@@ -97,12 +99,13 @@ class RCS(object):
name = "None"
client = "" # command-line tool for _u_invoke_client
versioned = False
- def __init__(self, paranoid=False):
+ def __init__(self, paranoid=False, encoding=sys.getdefaultencoding()):
self.paranoid = paranoid
self.verboseInvoke = False
self.rootdir = None
self._duplicateBasedir = None
self._duplicateDirname = None
+ self.encoding = encoding
def __del__(self):
self.cleanup()
@@ -171,15 +174,15 @@ class RCS(object):
pass
def _rcs_get_file_contents(self, path, revision=None):
"""
- Get the file contents as they were in a given revision. Don't
- worry about decoding the contents, the RCS.get_file_contents()
- method will handle that.
-
+ Get the file contents as they were in a given revision.
Revision==None specifies the current revision.
"""
assert revision == None, \
"The %s RCS does not support revision specifiers" % self.name
- return file(os.path.join(self.rootdir, path), "rb").read()
+ f = codecs.open(os.path.join(self.rootdir, path), "r", self.encoding)
+ contents = f.read()
+ f.close()
+ return contents
def _rcs_duplicate_repo(self, directory, revision=None):
"""
Get the repository as it was in a given revision.
@@ -297,14 +300,18 @@ class RCS(object):
relpath = self._u_rel_path(path)
contents = self._rcs_get_file_contents(relpath,revision)
else:
- contents = file(path, "rb").read()
- return contents.decode("utf-8")
+ f = codecs.open(path, "r", self.encoding)
+ contents = f.read()
+ f.close()
+ return contents
def set_file_contents(self, path, contents, allow_no_rcs=False):
"""
Set the file contents under version control.
"""
add = not os.path.exists(path)
- file(path, "wb").write(contents.encode("utf-8"))
+ f = codecs.open(path, "w", self.encoding)
+ f.write(contents)
+ f.close()
if self._use_rcs(path, allow_no_rcs):
if add:
@@ -537,13 +544,13 @@ class RCS(object):
Split the commitfile created in self.commit() back into
summary and header lines.
"""
- f = file(commitfile, "rb")
+ f = codecs.open(commitfile, "r", self.encoding)
summary = f.readline()
body = f.read()
body.lstrip('\n')
if len(body) == 0:
body = None
- f.close
+ f.close()
return (summary, body)
diff --git a/libbe/utility.py b/libbe/utility.py
index 2c77fcf..30240a9 100644
--- a/libbe/utility.py
+++ b/libbe/utility.py
@@ -15,10 +15,11 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
import calendar
-import time
+import codecs
import os
-import tempfile
import shutil
+import tempfile
+import time
import doctest
@@ -87,73 +88,5 @@ def str_to_time(str_time):
def handy_time(time_val):
return time.strftime("%a, %d %b %Y %H:%M", time.localtime(time_val))
-class CantFindEditor(Exception):
- def __init__(self):
- Exception.__init__(self, "Can't find editor to get string from")
-
-def editor_string(comment=None):
-
- """Invokes the editor, and returns the user_produced text as a string
-
- >>> if "EDITOR" in os.environ:
- ... del os.environ["EDITOR"]
- >>> if "VISUAL" in os.environ:
- ... del os.environ["VISUAL"]
- >>> editor_string()
- Traceback (most recent call last):
- CantFindEditor: Can't find editor to get string from
- >>> os.environ["EDITOR"] = "echo bar > "
- >>> editor_string()
- u'bar\\n'
- >>> os.environ["VISUAL"] = "echo baz > "
- >>> editor_string()
- u'baz\\n'
- >>> del os.environ["EDITOR"]
- >>> del os.environ["VISUAL"]
- """
- for name in ('VISUAL', 'EDITOR'):
- try:
- editor = os.environ[name]
- break
- except KeyError:
- pass
- else:
- raise CantFindEditor()
- fhandle, fname = tempfile.mkstemp()
- try:
- if comment is not None:
- os.write(fhandle, '\n'+comment_string(comment))
- os.close(fhandle)
- oldmtime = os.path.getmtime(fname)
- os.system("%s %s" % (editor, fname))
- output = trimmed_string(file(fname, "rb").read().decode("utf-8"))
- if output.rstrip('\n') == "":
- output = None
- finally:
- os.unlink(fname)
- return output
-
-
-def comment_string(comment):
- """
- >>> comment_string('hello')
- '== Anything below this line will be ignored ==\\nhello'
- """
- return '== Anything below this line will be ignored ==\n' + comment
-
-
-def trimmed_string(instring):
- """
- >>> trimmed_string("hello\\n== Anything below this line will be ignored")
- 'hello\\n'
- >>> trimmed_string("hi!\\n" + comment_string('Booga'))
- 'hi!\\n'
- """
- out = []
- for line in instring.splitlines(True):
- if line.startswith('== Anything below this line will be ignored'):
- break
- out.append(line)
- return ''.join(out)
suite = doctest.DocTestSuite()