From 19b153b9a86377a2b30cc80fa3f475fed892e2fe Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Tue, 18 Nov 2008 20:42:50 -0500 Subject: Major rewrite of RCS backends. RCS now represented as a class. Lots of changes and just one commit. This started with bug dac91856-cb6a-4f69-8c03-38ff0b29aab2, when I noticed that new bugs were not being added appropriately with the Git backend. I'd been working with Git trouble before with bug 0cad2ac6-76ef-4a88-abdf-b2e02de76f5c, and decided things would be better off if I just scrapped the current RCS architecture and went to a more object oriented setup. So I did. It's not clear how to add support for an RCS backend: * Create a new module that - defines an inheritor of rsc.RCS, overriding the _rcs_*() methods - provide a new() function for instantizating the new class - defines an inheritor of rcs.RCStestCase, overiding the Class attribute - defines 'suite' a unittest.TestSuite testing the module * Add your new module to the rest in rcs._get_matching_rcs() * Add your new module to the rest in libbe/tests.py Although I'm not sure libbe/tests.py is still usefull. The new framework clears out a bunch of hackery that used to be involved with supporting becommands/diff.py. There's still room for progress though. While implementing the new verision, I moved the testing framework over from doctest to a doctest/unittest combination. Longer tests that don't demonstrate a function's usage should be moved to unittests at the end of the module, since unittest has better support for setup/teardown, etc. The new framework also revealed some underimplented backends, most notably arch. These backends have now been fixed. I also tweaked the test_usage.sh script to run through all the backends if it is called with no arguments. The fix for the dac bug turned out to be an unflushed file write :p. --- libbe/utility.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'libbe/utility.py') diff --git a/libbe/utility.py b/libbe/utility.py index 1fd83da..f595bdb 100644 --- a/libbe/utility.py +++ b/libbe/utility.py @@ -18,6 +18,8 @@ import calendar import time import os import tempfile +import shutil +import doctest class FileString(object): """Bare-bones pseudo-file class @@ -69,6 +71,14 @@ def get_file(f): else: return f +class Dir: + "A temporary directory for testing use" + def __init__(self): + self.path = tempfile.mkdtemp(prefix="BEtest") + def __del__(self): + shutil.rmtree(self.path) + def __call__(self): + return self.path RFC_2822_TIME_FMT = "%a, %d %b %Y %H:%M:%S +0000" @@ -162,3 +172,5 @@ def trimmed_string(instring): break out.append(line) return ''.join(out) + +suite = doctest.DocTestSuite() -- cgit From 23179f50092d91dbeab97ad2b88cdaadb79b615f Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Fri, 21 Nov 2008 14:56:05 -0500 Subject: Another major rewrite. Now BugDir, Bug, and Comment are more distinct. I pushed a lot of the little helper functions into the main classes, which makes it easier for me to keep track of what's going on. I'm now at the point where I can run through `python test.py` with each of the backends (by changing the search order in rcs.py _get_matching_rcs) without any unexpected errors for each backend (except Arch). I can also run `test_usage.sh` without non-Arch errors either. However, don't consider this a stable commit yet. The bzr backend is *really*slow*, and the other's aren't blazingly fast either. I think I'm rewriting the entire database every time I save it :p. Still, it passes the checks. and I don't like it when zounds of changes build up. --- libbe/utility.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'libbe/utility.py') diff --git a/libbe/utility.py b/libbe/utility.py index f595bdb..81023cd 100644 --- a/libbe/utility.py +++ b/libbe/utility.py @@ -71,6 +71,32 @@ def get_file(f): else: return f +def search_parent_directories(path, filename): + """ + Find the file (or directory) named filename in path or in any + of path's parents. + + e.g. + search_parent_directories("/a/b/c", ".be") + will return the path to the first existing file from + /a/b/c/.be + /a/b/.be + /a/.be + /.be + or None if none of those files exist. + """ + path = os.path.realpath(path) + assert os.path.exists(path) + old_path = None + while True: + check_path = os.path.join(path, filename) + if os.path.exists(check_path): + return check_path + if path == old_path: + return None + old_path = path + path = os.path.dirname(path) + class Dir: "A temporary directory for testing use" def __init__(self): -- cgit From 9524d061aa93451a282f45150944878d6b5cf065 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sat, 22 Nov 2008 16:46:42 -0500 Subject: libbe.utility.Dir was complaining of a missing shutil in __del__(). Presumably the cleanup process removed shutil before cleaning up the Dir. Now Dir keeps a local reference. --- libbe/utility.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'libbe/utility.py') diff --git a/libbe/utility.py b/libbe/utility.py index 81023cd..972fe47 100644 --- a/libbe/utility.py +++ b/libbe/utility.py @@ -101,8 +101,9 @@ class Dir: "A temporary directory for testing use" def __init__(self): self.path = tempfile.mkdtemp(prefix="BEtest") + self.shutil = shutil # save local reference for __del__ def __del__(self): - shutil.rmtree(self.path) + self.shutil.rmtree(self.path) def __call__(self): return self.path -- cgit From 4a626e67b3f401b8e242a55571a802147123a196 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sat, 22 Nov 2008 19:45:37 -0500 Subject: Explicit rcs.cleanup() in bugdir test. Don't use del(rcs), because if there was an error, there is still a reference to rcs in the traceback, so it is never cleaned up. This can leave the external archive cluttering up your Arch install if you're using the Arch backend. See the __del__ documentation http://python.active-venture.com/ref/customization.html#l2h-175 for details. Also fixed some out-of-date method names in libbe.diff --- libbe/utility.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'libbe/utility.py') diff --git a/libbe/utility.py b/libbe/utility.py index 972fe47..f156ce9 100644 --- a/libbe/utility.py +++ b/libbe/utility.py @@ -97,12 +97,15 @@ def search_parent_directories(path, filename): old_path = path path = os.path.dirname(path) -class Dir: +class Dir (object): "A temporary directory for testing use" def __init__(self): self.path = tempfile.mkdtemp(prefix="BEtest") self.shutil = shutil # save local reference for __del__ def __del__(self): + self.cleanup() + def cleanup(self): + print "Removing", self.path self.shutil.rmtree(self.path) def __call__(self): return self.path -- cgit From 9e0a846ff4fdaac45665e5a1e085aa37e3fa135b Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sun, 23 Nov 2008 06:51:30 -0500 Subject: Added archive/project init code for `./test_usage.sh arch`. Also some minor cleanups. --- libbe/utility.py | 1 - 1 file changed, 1 deletion(-) (limited to 'libbe/utility.py') diff --git a/libbe/utility.py b/libbe/utility.py index f156ce9..3f69a95 100644 --- a/libbe/utility.py +++ b/libbe/utility.py @@ -105,7 +105,6 @@ class Dir (object): def __del__(self): self.cleanup() def cleanup(self): - print "Removing", self.path self.shutil.rmtree(self.path) def __call__(self): return self.path -- cgit From 1edae6ccd13951120b8347e97130de57a3d6f60e Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sun, 23 Nov 2008 07:19:36 -0500 Subject: Fixed "'NoneType' object is not callable" error in libbe/utility/Dir.__del__ --- libbe/utility.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'libbe/utility.py') diff --git a/libbe/utility.py b/libbe/utility.py index 3f69a95..7c1d10a 100644 --- a/libbe/utility.py +++ b/libbe/utility.py @@ -101,11 +101,14 @@ class Dir (object): "A temporary directory for testing use" def __init__(self): self.path = tempfile.mkdtemp(prefix="BEtest") - self.shutil = shutil # save local reference for __del__ + self.rmtree = shutil.rmtree # save local reference for __del__ + self.removed = False def __del__(self): self.cleanup() def cleanup(self): - self.shutil.rmtree(self.path) + if self.removed == False: + self.rmtree(self.path) + self.removed = True def __call__(self): return self.path -- cgit From d248dbca39e1e8a26a5aa9d39b28038690a406a0 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Mon, 24 Nov 2008 07:31:51 -0500 Subject: Replaced direct filesystem read from bugdir.py with RCS mediated read. Also replaced utility.FileString with StringIO() in cmdutil.py, which allowed the removal of utility.FileString and utility.get_file. The only remaining file().read() outside the RCS framework is the read in utility.editor_string(), but should probably not go through the RCS. --- libbe/utility.py | 51 +-------------------------------------------------- 1 file changed, 1 insertion(+), 50 deletions(-) (limited to 'libbe/utility.py') diff --git a/libbe/utility.py b/libbe/utility.py index 7c1d10a..1168580 100644 --- a/libbe/utility.py +++ b/libbe/utility.py @@ -21,55 +21,6 @@ import tempfile import shutil import doctest -class FileString(object): - """Bare-bones pseudo-file class - - >>> f = FileString("me\\nyou") - >>> len(list(f)) - 2 - >>> len(list(f)) - 0 - >>> f = FileString() - >>> f.write("hello\\nthere") - >>> "".join(list(f)) - 'hello\\nthere' - """ - def __init__(self, str=""): - object.__init__(self) - self.str = str - self._iter = None - - def __iter__(self): - if self._iter is None: - self._iter = self._get_iter() - return self._iter - - def _get_iter(self): - for line in self.str.splitlines(True): - yield line - - def write(self, line): - self.str += line - - -def get_file(f): - """ - Return a file-like object from input. This is a helper for functions that - can take either file or string parameters. - - :param f: file or string - :return: a FileString if input is a string, otherwise return the imput - object. - - >>> isinstance(get_file(file("/dev/null")), file) - True - >>> isinstance(get_file("f"), FileString) - True - """ - if isinstance(f, basestring): - return FileString(f) - else: - return f def search_parent_directories(path, filename): """ @@ -175,7 +126,7 @@ def editor_string(comment=None): os.close(fhandle) oldmtime = os.path.getmtime(fname) os.system("%s %s" % (editor, fname)) - output = trimmed_string(file(fname, "rb").read()) + output = trimmed_string(file(fname, "rb").read().decode("utf-8")) if output.rstrip('\n') == "": output = None finally: -- cgit From 5fd5bc89a2ec270d3e0b01f583012eaaf7750693 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Mon, 24 Nov 2008 07:47:06 -0500 Subject: Added Bug.comments(), BugDir.has_bug() & cleaned up diff.diff(). + some other minor fixes and cleanups. --- libbe/utility.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'libbe/utility.py') diff --git a/libbe/utility.py b/libbe/utility.py index 1168580..2c77fcf 100644 --- a/libbe/utility.py +++ b/libbe/utility.py @@ -104,10 +104,10 @@ def editor_string(comment=None): CantFindEditor: Can't find editor to get string from >>> os.environ["EDITOR"] = "echo bar > " >>> editor_string() - 'bar\\n' + u'bar\\n' >>> os.environ["VISUAL"] = "echo baz > " >>> editor_string() - 'baz\\n' + u'baz\\n' >>> del os.environ["EDITOR"] >>> del os.environ["VISUAL"] """ -- cgit