As described in the bug report
(https://bugs.launchpad.net/bzr-gtk/+bug/373157), gannotate gives a
traceback if you don't have a gannotate.conf file (try deleting
yours :).

It turns out that configobj 4.6.0 changes something in the way
the configspec is handled and that triggers the bug (for the
curious, I encountered the problem while shuffling around my
bazaar conf files).

Now, the problem is not really related to configobj, it's really
an old bug. I don't remember gannotate ever being able to really
restore the window position or size and I've been using it for
quite some years now.

The bug is that the config file was in fact ignored because we
override the values with some defaults, always.

I add a test for it, upgrading our test loading to bzr standards.

With this patch, we now install default values only if no config
values can be found.

Doing so I deleted the 'spans' section that nobody seems to use
these days. I also noticed that the annotate/spanselectory.py
doesn't seem to be used either (but I didn't delete it, we may
want to do that though).

I also deleted the 'gannotate_configspec' attribute, it
duplicates the default value declaration while serving no purpose
in our case (AFAICS, configspec are used only for validation and
bzr doesn't include that part of configobj anyway).

I also update all uses of the config values as configobj always
returns strings, not proper ints or booleans (this was also
masked by installing fresh default values of the correct types).

Finally, the FSF address is out of date in all the files, we may
want to update it as bzr.dev did.

     Vincent

# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: [email protected]
# target_branch: http://bazaar.launchpad.net/%7Ebzr-gtk/bzr-gtk/trunk
# testament_sha1: 4a9369738272af90e7b47ba3b84189a589a71b28
# timestamp: 2009-05-07 13:51:01 +0200
# base_revision_id: [email protected]\
#   7abxvg2qz4gzraup
# 
# Begin patch
=== modified file '__init__.py'
--- __init__.py	2009-05-04 07:01:58 +0000
+++ __init__.py	2009-05-07 09:41:56 +0000
@@ -102,21 +102,21 @@
             raise NoDisplayError
     set_ui_factory()
     return gtk
- 
+
 
 commands = {
     "gannotate": ["gblame", "gpraise"],
     "gbranch": [],
-    "gcheckout": [], 
-    "gcommit": ["gci"], 
-    "gconflicts": [], 
+    "gcheckout": [],
+    "gcommit": ["gci"],
+    "gconflicts": [],
     "gdiff": [],
     "ginit": [],
     "ginfo": [],
     "gmerge": [],
-    "gmissing": [], 
-    "gpreferences": [], 
-    "gpush": [], 
+    "gmissing": [],
+    "gpreferences": [],
+    "gpush": [],
     "gselftest": [],
     "gsend": [],
     "gstatus": ["gst"],
@@ -132,7 +132,8 @@
     commands["gloom"] = []
 
 for cmd, aliases in commands.iteritems():
-    plugin_cmds.register_lazy("cmd_%s" % cmd, aliases, "bzrlib.plugins.gtk.commands")
+    plugin_cmds.register_lazy("cmd_%s" % cmd, aliases,
+                              "bzrlib.plugins.gtk.commands")
 
 
 import gettext
@@ -149,20 +150,22 @@
         return "No DISPLAY. Unable to run GTK+ application."
 
 
-def test_suite():
-    from unittest import TestSuite
-    import tests
+def load_tests(basic_tests, module, loader):
+    testmod_names = [
+        'tests',
+        ]
     import sys
     default_encoding = sys.getdefaultencoding()
     try:
-        result = TestSuite()
+        result = basic_tests
         try:
             import_pygtk()
         except errors.BzrCommandError:
-            return result
-        result.addTest(tests.test_suite())
+            return basic_tests
+        basic_tests.addTest(loader.loadTestsFromModuleNames(
+                ["%s.%s" % (__name__, tmn) for tmn in testmod_names]))
     finally:
         if sys.getdefaultencoding() != default_encoding:
             reload(sys)
             sys.setdefaultencoding(default_encoding)
-    return result
+    return basic_tests

=== modified file 'annotate/config.py'
--- annotate/config.py	2007-01-17 06:42:55 +0000
+++ annotate/config.py	2009-05-07 11:48:03 +0000
@@ -18,24 +18,12 @@
 
 import gtk.gdk
 
-from bzrlib.config import config_dir
+from bzrlib import config
 import bzrlib.util.configobj.configobj as configobj
 
 
-gannotate_configspec = (
-    "[window]",
-    "width = integer(default=750)",
-    "height = integer(default=550)",
-    "maximized = boolean(default=False)",
-    "x = integer(default=0)",
-    "y = integer(default=0)",
-    "pane_position = integer(default=325)",
-    "[spans]",
-    "max_custom_spans = integer(default=4)",
-    "custom_spans = float_list()"
-)
-
-gannotate_config_filename = os.path.join(config_dir(), "gannotate.conf")
+def gannotate_config_filename():
+    return os.path.join(config.config_dir(), "gannotate.conf")
 
 
 class GAnnotateConfig(configobj.ConfigObj):
@@ -47,20 +35,20 @@
     """
 
     def __init__(self, window):
-        configobj.ConfigObj.__init__(self, gannotate_config_filename,
-                                     configspec=gannotate_configspec)
+        configobj.ConfigObj.__init__(self, gannotate_config_filename())
         self.window = window
         self.pane = window.pane
-        
-        self.initial_comment = ["gannotate plugin configuration"]
-        self['window']['width'] = 750
-        self['window']['height'] = 550
-        self['window']['maximized'] = False
-        self['window']['x'] = 0
-        self['window']['y'] = 0
-        self['window']['pane_position'] = 325
-        self['spans']['max_custom_spans'] = 4
-        self['spans']['custom_spans'] = []
+
+        if 'window' not in self:
+            # Set default values, configobj expects strings here
+            self.initial_comment = ["gannotate plugin configuration"]
+            self['window'] = {}
+            self['window']['width'] = '750'
+            self['window']['height'] = '550'
+            self['window']['maximized'] = 'False'
+            self['window']['x'] = '0'
+            self['window']['y'] = '0'
+            self['window']['pane_position'] = '325'
 
         self.apply()
         self._connect_signals()
@@ -68,16 +56,14 @@
     def apply(self):
         """Apply properties and such from gannotate.conf, or
         gannotate_configspec defaults."""
-        self.pane.set_position(self["window"]["pane_position"])
-        self.window.set_default_size(self["window"]["width"],
-                                     self["window"]["height"])
-        self.window.move(self["window"]["x"], self["window"]["y"])
+        self.pane.set_position(self['window'].as_int('pane_position'))
+        self.window.set_default_size(self['window'].as_int('width'),
+                                     self['window'].as_int('height'))
+        self.window.move(self['window'].as_int('x'), self['window'].as_int('y'))
 
-        if self["window"]["maximized"]:
+        if self['window'].as_bool('maximized'):
             self.window.maximize()
 
-        # XXX Don't know how to set an empty list as default in
-        # gannotate_configspec.
     def _connect_signals(self):
         self.window.connect("destroy", self._write)
         self.window.connect("configure-event", self._save_window_props)
@@ -91,9 +77,7 @@
             self["window"]["width"], self["window"]["height"] = w.get_size()
             self["window"]["x"], self["window"]["y"] = w.get_position()
             maximized = False
-
         self["window"]["maximized"] = maximized
-        
         return False
 
     def _save_pane_props(self, w, gparam):
@@ -102,11 +86,6 @@
 
         return False
 
-    def _save_custom_spans(self, w, *args):
-        self["spans"]["custom_spans"] = w.custom_spans
-
-        return False
-
     def _write(self, *args):
         self.write()
 

=== modified file 'tests/__init__.py'
--- tests/__init__.py	2008-11-13 06:55:41 +0000
+++ tests/__init__.py	2009-05-07 09:54:50 +0000
@@ -14,17 +14,11 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
-from unittest import TestLoader, TestSuite
-from bzrlib.tests import TestUtil
-
-import os
-
-def test_suite():
-    result = TestSuite()
-
-    loader = TestUtil.TestLoader()
-
+from bzrlib import tests
+
+def load_tests(basic_tests, module, loader):
     testmod_names = [
+        'test_annotate_config',
         'test_commit',
         'test_diff',
         'test_history',
@@ -33,6 +27,6 @@
         'test_revisionview',
         ]
 
-    result.addTest(loader.loadTestsFromModuleNames(["%s.%s" % (__name__, i) for i in testmod_names]))
-    return result
-
+    basic_tests.addTest(loader.loadTestsFromModuleNames(
+            ["%s.%s" % (__name__, tmn) for tmn in testmod_names]))
+    return basic_tests

=== added file 'tests/test_annotate_config.py'
--- tests/test_annotate_config.py	1970-01-01 00:00:00 +0000
+++ tests/test_annotate_config.py	2009-05-07 11:48:03 +0000
@@ -0,0 +1,40 @@
+# Copyright (C) 2009 Canonical Ltd
+#
+# 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+"""Test the annotate configuration functionality."""
+
+from bzrlib import (
+    tests,
+    )
+
+from bzrlib.plugins.gtk.annotate import (
+    config,
+    gannotate,
+    )
+
+class TestConfig(tests.TestCaseInTempDir):
+
+    def setUp(self):
+        super(TestConfig, self).setUp()
+        self.window = gannotate.GAnnotateWindow()
+
+    def test_create_initial_config(self):
+        """We can create a config even without a prior conf file"""
+        conf = config.GAnnotateConfig(self.window)
+        # We can access the default values (we just pick a random one)
+        width = conf['window']['width']
+        # configobj presents attributes as strings only
+        self.assertIsInstance(width, str)

# Begin bundle
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
U4FaIpv+/8XckU4UJDGImkzA
-- 
bzr-gtk mailing list
[email protected]
Modify settings or unsubscribe at: 
https://lists.canonical.com/mailman/listinfo/bzr-gtk

Reply via email to