The Malone (Launchpad) XMLRPC Interface

Malone currently provides an XML-RPC interface for filing bugs.

Synopsis

from xmlrpclib import ServerProxy

s = ServerProxy("https://test@canonical.com:test@xmlrpc.launchpad.net/bugs/")
s.filebug(dict(
    distro="ubuntu", package="mozilla-firefox",
    summary="the summary", comment="the description",
    subscribers=["foo.bar@canonical.com"]))

For the truly interested

The filebug API

The filebug API is:

    filebug_api.filebug(params)

params is a dict, with the following keys:

Either product or distro must be provided. The bug owner is the currently authenticated user, taken from the request. The return value is the bug URL, in short form, e.g.:

Examples

First, let's define a simple event listener to show that the ISQLObjectCreatedEvent is being published when a bug is reported through the XML-RPC interface.

    >>> from canonical.launchpad.event.interfaces import ISQLObjectCreatedEvent
    >>> from canonical.launchpad.ftests.event import TestEventListener
    >>> from canonical.launchpad.interfaces import IBug

    >>> def on_created_event(obj, event):
    ...     print "SQLObjectCreatedEvent: %r" % obj

    >>> on_created_listener = TestEventListener(
    ...     IBug, ISQLObjectCreatedEvent, on_created_event)

Reporting a product bug

(We'll define a simple function to extract the bug ID from the URL return value.)

    >>> def get_bug_id_from_url(url):
    ...     return int(url.split("/")[-1])

    >>> login("test@canonical.com")

    >>> params = dict(
    ...     product='firefox', summary='the summary', comment='the comment')
    >>> bug_url = filebug_api.filebug(params)
    SQLObjectCreatedEvent: <Bug ...>
    >>> print bug_url
    http://launchpad.dev/bugs/...

    >>> from zope.component import getUtility
    >>> from canonical.launchpad.interfaces import IBugSet

    >>> bugset = getUtility(IBugSet)
    >>> bug = bugset.get(get_bug_id_from_url(bug_url))

    >>> print bug.title
    the summary
    >>> print bug.description
    the comment
    >>> print bug.owner.name
    name12

    >>> firefox_bug = bug.bugtasks[0]

    >>> print firefox_bug.product.name
    firefox

Reporting a distro bug

    >>> params = dict(
    ...     distro='ubuntu', summary='another bug', comment='another comment')
    >>> bug_url = filebug_api.filebug(params)
    SQLObjectCreatedEvent: <Bug ...>
    >>> print bug_url
    http://launchpad.dev/bugs/...

    >>> bug = bugset.get(get_bug_id_from_url(bug_url))

    >>> print bug.title
    another bug
    >>> print bug.description
    another comment
    >>> print bug.owner.name
    name12

    >>> ubuntu_bug = bug.bugtasks[0]

    >>> print ubuntu_bug.distribution.name
    ubuntu
    >>> ubuntu_bug.sourcepackagename is None
    True

Reporting a package bug

    >>> params = dict(
    ...     distro='ubuntu', package='evolution', summary='email is cool',
    ...     comment='email is nice', security_related=True,
    ...     subscribers=["no-priv@canonical.com"])
    >>> bug_url = filebug_api.filebug(params)
    SQLObjectCreatedEvent: <Bug ...>
    >>> print bug_url
    http://launchpad.dev/bugs/...

    >>> bug = bugset.get(get_bug_id_from_url(bug_url))

    >>> print bug.title
    email is cool
    >>> print bug.description
    email is nice
    >>> bug.security_related
    True
    >>> bug.private
    True
    >>> sorted(p.name for p in bug.getDirectSubscribers())
    [u'name12', u'no-priv', u'ubuntu-team']
    >>> bug.getIndirectSubscribers()
    []

    >>> evolution_bug = bug.bugtasks[0]

    >>> print evolution_bug.distribution.name
    ubuntu
    >>> print evolution_bug.sourcepackagename.name
    evolution

Error Handling

Malone's xmlrpc interface provides extensive error handling. The various error conditions it recognizes are:

Failing to specify a product or distribution.

    >>> params = dict()
    >>> filebug_api.filebug(params)
    <Fault 60: 'Required arguments missing. You must specify either a product or distrubtion in which the bug exists.'>

Specifying *both* a product and distribution.

    >>> params = dict(product='firefox', distro='ubuntu')
    >>> filebug_api.filebug(params)
    <Fault 70: 'Too many arguments. You may specify either a product or a distribution, but not both.'>

Specifying a non-existent product.

    >>> params = dict(product='nosuchproduct')
    >>> filebug_api.filebug(params)
    <Fault 10: 'No such product: nosuchproduct'>

Specifying a non-existent distribution.

    >>> params = dict(distro='nosuchdistro')
    >>> filebug_api.filebug(params)
    <Fault 80: 'No such distribution: nosuchdistro'>

Specifying a non-existent package.

    >>> params = dict(distro='ubuntu', package='nosuchpackage')
    >>> filebug_api.filebug(params)
    <Fault 90: 'No such package: nosuchpackage'>

Missing summary.

    >>> params = dict(product='firefox')
    >>> filebug_api.filebug(params)
    <Fault 100: 'Required parameter missing: summary'>

Missing comment.

    >>> params = dict(product='firefox', summary='the summary')
    >>> filebug_api.filebug(params)
    <Fault 100: 'Required parameter missing: comment'>

Invalid subscriber.

    >>> params = dict(
    ...     product='firefox', summary='summary', comment='comment',
    ...     subscribers=["foo.bar@canonical.com", "nosuch@subscriber.com"])
    >>> filebug_api.filebug(params)
    <Fault 20: 'Invalid subscriber: No user with the email address
    "nosuch@subscriber.com" was found'>

    >>> on_created_listener.unregister()

MaloneXMLRPC (last edited 2008-06-17 14:21:16 by localhost)