aboutsummaryrefslogtreecommitdiffstats
path: root/libbe/bugdir.py
diff options
context:
space:
mode:
authorW. Trevor King <wking@drexel.edu>2008-11-25 15:47:19 -0500
committerW. Trevor King <wking@drexel.edu>2008-11-25 15:47:19 -0500
commit5699aef2a5741c5ffc24d9cb12d6bc9b085d484a (patch)
tree84ac8783ce2d1f9a28ba0bd0c256ae7179c68507 /libbe/bugdir.py
parented4d971d1375a692fbd3a394237f56e851bb5d0e (diff)
downloadbugseverywhere-5699aef2a5741c5ffc24d9cb12d6bc9b085d484a.tar.gz
Added libbe/encoding.py to wrap input/output/file access appropriately.
I borrowed most of the code for this. get_encoding() is from Trac http://trac.edgewall.org/browser/trunk/trac/util/datefmt.py format_datetime() Trac has a BSD license http://trac.edgewall.org/wiki/TracLicense I don't know if such a small snippet requires us to "reproduce the above copyright" or where we need to reproduce it if it is needed. The stdout/stdin replacement code follows http://wiki.python.org/moin/ShellRedirectionFails Because of the stdout replacement, the doctests executes now need an optional 'test' argument to turn off replacement during the doctests, otherwise doctest flips out (since it had set up stdout to catch output, and then we clobbered it's setup). References: http://wiki.python.org/moin/Unicode http://www.amk.ca/python/howto/unicode http://www.python.org/dev/peps/pep-0100/ I also split libbe/editor.py off from libbe.utility.py and started explaining the motivation for the BugDir init flags in it's docstring.
Diffstat (limited to 'libbe/bugdir.py')
-rw-r--r--libbe/bugdir.py123
1 files changed, 96 insertions, 27 deletions
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>"