[MERGE] Initial support for marking bugs as fixed using bzr
Jonathan Lange
jml at mumak.net
Mon Apr 23 01:56:17 BST 2007
On 4/19/07, Robert Collins <robertc at robertcollins.net> wrote:
> On Fri, 2007-04-13 at 17:33 +1000, Jonathan Lange wrote:
>
> --- /dev/null
> +++ bzrlib/bugtracker.py
> @@ -0,0 +1,148 @@
>
> ...
> ....+
> +Thus, this module provides a registry of types of bug tracker (e.g. Launchpad,
> +Trac). Given a short-hand tag (e.g. 'lp', 'twisted') and a branch with
> +configuration information, these tracker types can return an instance capable
> +of converting bug IDs into URLs.
> +"""
>
> I think referring to these as 'tags' is potentially confusing. Branch
> have tags. Chatting on IRC we came up with
> 'abbreviated_bugtracker_name'. While this is a mouthful, its clear what
> it refers to. I'd like you to look for 'tag' throughout this file and
> use a more precise name that isn't overloaded within bzrlib already.
> E.g. withing the tracker classes, perhaps 'abbreviation' is a good
> attribute name.
>
Changed to abbreviatied_bugtracker_name and abbreviation in code and docs.
> +
> +def get_bug_url(tag, branch, bug_id):
> + """Return a URL pointing to the bug identified by 'bug_id'."""
> + return tracker_registry.get_tracker(tag, branch).get_bug_url(bug_id)
>
> 'pointing to the bug' is a little misleading - surely its pointing to
> the webpage for the bug. (That is, we're not using URN style
> identification of the bug).
>
Changed.
> ...
> + for tracker_name, tracker_type in self.iteritems():
> + tracker = tracker_type.get(tag, branch)
> + if tracker is not None:
> + return tracker
> + raise KeyError("No tracker found for %r on %r" % (tag, branch))
>
> tracker_name is not used here. Why not use self.values() ? (Or isn't that defined).
values() isn't defined, and neither is __getitem__. I'll file a bug.
> +
> +tracker_registry = TrackerRegistry()
> +"""Registry of bug trackers."""
>
> Perhaps this docstring is better served by having a __doc__ on instances
> of TrackerRegistry - wouldn't that work for pydoc?
>
I copied what's done in other modules in bzrlib. I haven't changed this.
> +
> +class UniqueBugTracker(object):
> + """A style of bug tracker that exists in one place only, such as Launchpad.
> +
> + If you have one of these trackers then subclass this and add attributes
> + named 'tag' and 'base_url'. The former is the tag that the user will use
> + on the command line. The latter is the url that the bug ids will be
> + appended to.
> +
> + If the bug_id must have a special form then override check_bug_id and
> + raise an exception if the bug_id is not valid.
> + """
>
> As a side note, launchpad doesn't strictly exist in only one place - the
> demo and staging servers have different databases to the production
> server and can thus talk about different bug numbers. I'm not sure it
> matters - but perhaps for testing it would be nice to be able to have
> throwaway branches that you use with e.g. staging, and have the right
> urls created.
>
I haven't really done anything about this.
> +...
>
> I like that you supply trackers for Launchpad, Debian, and Trac.
> Bugzilla is another common tracker and its a simple integer tracker but
> like trac appears at many urls. I think it would be good for the code
> factoring to implement Bugzilla urls too. (giving us two 'singleton'
> trackers, and two 'many instance' trackers).
Added Buzilla tracker.
> I dont like that you have subclasses for Launchpad and Debian that vary
> solely in parameters. That to me cries out for instances. This would in
> principal allow configuring abbreviations for any tracker that we have
> the basic facility for via branch.conf - or any other config file in the
> configuration system.
Yeah, I don't like it either. I've changed them to instances, but not
updated their config mechanism -- they are just registered manually.
> I am not making configuration via branch.conf a requirement for getting
> +1 - a bug report is fine. But I do think getting rid of the spurious
> classes is important and want that changed to get +1.
>
> +++ bzrlib/tests/test_bugtracker.py
> @@ -0,0 +1,182 @@
>
> +class TestGetBugURL(TestCaseWithMemoryTransport):
> + """Tests for bugtracker.get_bug_url"""
> +
> + def test_get_launchpad_url(self):
> + """No matter the branch, lp:1234 should map to a Launchpad URL."""
> + branch = self.make_branch('some_branch')
> + self.assertEqual(
> + 'https://launchpad.net/bugs/1234',
> + bugtracker.get_bug_url('lp', branch, '1234'))
>
> This test claims to test a negative, which isn't really possible. I
> think its more accurate to test something like 'The launchpad tracker
> does not consult the branch for determining its urls', and test that
> passing in 'None' as the branch results in the right URL.
>
This test has been replaced entirely, see below.
> + def test_get_trac_url(self):
> + trac_url = 'http://twistedmatrix.com/trac'
> + branch = self.make_branch('some_branch')
> + config = branch.get_config()
> + config.set_user_option('trac_twisted_url', trac_url)
> + self.assertEqual('%s/ticket/1234' % trac_url,
> + bugtracker.get_bug_url('twisted', branch, '1234'))
>
> This tests that one branch has the right url, but you need two to tell
> that the parameterisation works. E.g. change the config option and test
> the result changes.
>
Based on some of your comments further below, I've rewritten this set
of test cases. They now work by preparing a transient tracker. Your
review comments on these two tests were applied as necessary for the
new tests.
> + def test_unrecognized_tag(self):
> + """If the tag is unrecognized, then raise a KeyError."""
> + branch = self.make_branch('some_branch')
> + self.assertRaises(KeyError,
> + bugtracker.get_bug_url, 'xxx', branch, '1234')
>
> I think we should have a better error than KeyError - one that has a good format string for the UI.
I've created a new error and put tests for it into test_errors.
>
> ...
>
>
> +class TestUniqueIntegerBugTracker(TestCaseWithMemoryTransport):
> +
> + def test_check_bug_id_only_accepts_integers(self):
> + """An UniqueIntegerBugTracker only accepts integers as bug IDs."""
> + tracker = bugtracker.UniqueIntegerBugTracker()
> + self.assertEqual(None, tracker.check_bug_id('1234'))
>
> Is the return code relevant? I would have written this as two separate tests:
> one that does
> --
> tracker.check_bug_id('1234')
> --
> and one that does
> + self.assertRaises(MalformedBugIdentifier, tracker.check_bug_id, 'red')
>
The return code is not relevant, but I have this twitch that flares up
when tests don't have calls to assert* methods. Changed.
>
> +class TestLaunchpadTracker(TestCaseWithMemoryTransport):
>
> I think all these tests can go with the refactoring I proposed earlier -
> all you need is a test that the launchpad_tracker is a registered
> instance with the right parameters.
>
Removed, replaced with thing that checks registration.
>
> +class TestDebianTracker(TestCaseWithMemoryTransport):
>
> Likewise.
>
Removed, replaced with thing that checks registration.
> +class TestTracTracker(TestCaseWithMemoryTransport):
> + def setUp(self):
> + TestCaseWithMemoryTransport.setUp(self)
> + self.trac_url = 'http://twistedmatrix.com/trac'
> +
> + def test_get_bug_url(self):
> + """A TracTracker should map a Trac bug to a URL for that instance."""
> + tracker = bugtracker.TracTracker(self.trac_url)
> + self.assertEqual(
> + '%s/ticket/1234' % self.trac_url, tracker.get_bug_url('1234'))
>
> This seems to be duplicated with the earlier trac test. I think the
> problem is that the first test is not clear about what its testing. Is
> it testing the convenience api or the underlying api. I think that as
> its claiming to test the convenience API, what you should be doing is
> registering transient bug trackers up there, and checking they get
> called into. That would reduce test duplication.
>
Changes made as recommended. See above comments for more details.
> --- NEWS
> +++ NEWS
> @@ -5,6 +5,9 @@
> * Merge directives can now be supplied as input to `merge` and `pull`,
> like bundles can. (Aaron Bentley)
>
> + * New option '--fixes' to commit, which stores bug fixing annotations as
> + revision properties. (Jonathan Lange, James Henstridge, Robert Collins)
> +
> INTERNALS:
>
> * bzrlib API compatability with 0.8 has been dropped, cleaning up some
>
> There should be an entry here talking about the new API as well - as
> plugins can now add bug trackers.
>
I've added another entry to Improvements for the API. It's scant, but
will be easier for me to expand after receiving comments.
> --- bzrlib/builtins.py
> +++ bzrlib/builtins.py
>
> @@ -2074,6 +2074,8 @@
> Option('strict',
> help="refuse to commit if there are unknown "
> "files in the working tree."),
> + ListOption('fixes', type=str,
> + help="XXX -- fix a bug"),
>
> This needs fixing.
Fixed. I'm adding a help topic, as discussed on #bzr, but at the
moment, it's also pretty short. Feedback will help expand it.
> @@ -2083,8 +2085,32 @@
> ]
> aliases = ['ci', 'checkin']
>
...
>
> === modified file bzrlib/errors.py // last-changed:jml at canonical.com-2007041305
> ... 1007-cq318kt5uj59k1ty
> --- bzrlib/errors.py
> +++ bzrlib/errors.py
> @@ -2046,3 +2046,12 @@
>
> def __init__(self, tag_name):
> self.tag_name = tag_name
> +
> +
> +class MalformedBugIdentifier(BzrError):
> +
> + _fmt = "Did not understand bug identifier %(bug_id)s: %(reason)s"
> +
> + def __init__(self, bug_id, reason):
> + self.bug_id = bug_id
> + self.reason = reason
>
> We have tests for error formatting in bzrlib/test_errors.py - can you add one please.
Added.
> --- bzrlib/option.py
> +++ bzrlib/option.py
> @@ -205,6 +205,26 @@
> yield self.name, self.short_name(), argname, self.help
>
>
> +class ListOption(Option):
> + def add_option(self, parser, short_name):
>
> class docstring please, and PEP8 vertical whitespace.
>
> IIRC Aaron had serious concerns about ListOption, have they been resolved?
>
> This also needs documentation in:
> doc/configuration.txt (for the trac bug tracker configuration). It might
> be nice to expand the tutorial (doc/tutorial.txt) to cover using this
> (perhaps using the launchpad tracker in the tutorial, as it does not
> need configuration).
>
Config docs added.
> I think theres a need for a 'managing a project with bzr' document - not
> one about centralised/decentralised etc, but about the features of bzr
> that are like this one, useful outside the strict 'I can commit code'
> space. Thats something I'll file a bug on though, its not needed for
> this to land.
>
> I'd like my points addressed and a re-review subsequently, because I
> think the incremental changes will be significant.
>
Points addressed. Thanks for the really helpful review.
cheers,
jml
-------------- next part --------------
A non-text attachment was scrubbed...
Name: bug-support.patch
Type: text/x-diff
Size: 615389 bytes
Desc: not available
Url : https://lists.ubuntu.com/archives/bazaar/attachments/20070423/b298956f/attachment-0001.bin
More information about the bazaar
mailing list