libbe.bug

Define Bug for representing bugs.

class libbe.bug.Bug(bugdir=None, uuid=None, from_storage=False, load_comments=False, summary=None)

A bug (or issue) is a place to store attributes and attach Comments. In mailing-list terms, a bug is analogous to a thread. Bugs are normally stored in BugDirs.

>>> b = Bug()
>>> print b.status
open
>>> print b.severity
minor

There are two formats for time, int and string. Setting either one will adjust the other appropriately. The string form is the one stored in the bug’s settings file on disk.

>>> print type(b.time)
<type 'int'>
>>> print type(b.time_string)
<type 'str'>
>>> b.time = 0
>>> print b.time_string
Thu, 01 Jan 1970 00:00:00 +0000
>>> b.time_string="Thu, 01 Jan 1970 00:01:00 +0000"
>>> b.time
60
>>> print b.settings["time"]
Thu, 01 Jan 1970 00:01:00 +0000

Methods

add_comment(comment, *args, **kwargs) Add a comment too the current bug, under the parent specified by comment.in_reply_to.
add_comments(comments[, default_parent, ...]) Convert a raw list of comments to single root comment.
clear_cached_setting([setting]) If setting=None, clear all cached settings
comment_from_uuid(uuid, *args, **kwargs)
comments()
from_xml(xml_string[, preserve_uuids, verbose]) Note: If a bug uuid is given, set .alt_id to it’s value.
load_comments([load_full])
load_settings([settings_mapfile])
merge(other[, accept_changes, ...]) Merge info from other into this bug.
new_comment([body])
remove()
save() Save any loaded contents to storage.
save_settings()
sibling_uuids()
string([shortlist, show_comments])
uuids()
xml([indent, show_comments])
>>> bugA = Bug(uuid='0123', summary='Need to test Bug.xml()')
active
add_comment(comment, *args, **kwargs)

Add a comment too the current bug, under the parent specified by comment.in_reply_to. Note: If a bug uuid is given, set .alt_id to it’s value.

>>> bugA = Bug(uuid='0123', summary='Need to test Bug.add_comment()')
>>> bugA.creator = 'Jack'
>>> commA = bugA.comment_root.new_reply(body='comment A')
>>> commA.uuid = 'commA'
>>> commB = comment.Comment(body='comment B')
>>> commB.uuid = 'commB'
>>> bugA.add_comment(commB)
>>> commC = comment.Comment(body='comment C')
>>> commC.uuid = 'commC'
>>> commC.in_reply_to = commA.uuid
>>> bugA.add_comment(commC)
>>> print bugA.xml(show_comments=True)  
<bug>
  <uuid>0123</uuid>
  <short-name>/012</short-name>
  <severity>minor</severity>
  <status>open</status>
  <creator>Jack</creator>
  <created>...</created>
  <summary>Need to test Bug.add_comment()</summary>
  <comment>
    <uuid>commA</uuid>
    <short-name>/012/commA</short-name>
    <author></author>
    <date>...</date>
    <content-type>text/plain</content-type>
    <body>comment A</body>
  </comment>
  <comment>
    <uuid>commC</uuid>
    <short-name>/012/commC</short-name>
    <in-reply-to>commA</in-reply-to>
    <author></author>
    <date>...</date>
    <content-type>text/plain</content-type>
    <body>comment C</body>
  </comment>
  <comment>
    <uuid>commB</uuid>
    <short-name>/012/commB</short-name>
    <author></author>
    <date>...</date>
    <content-type>text/plain</content-type>
    <body>comment B</body>
  </comment>
</bug>
add_comments(comments, default_parent=None, ignore_missing_references=False)

Convert a raw list of comments to single root comment. If a comment does not specify a parent with .in_reply_to, the parent defaults to .comment_root, but you can specify another default parent via default_parent.

assigned

The developer in charge of the bug

This property defaults to None.

comment_from_uuid(uuid, *args, **kwargs)
comment_root

The trunk of the comment tree. We use a dummy root comment by default, because there can be several comment threads rooted on the same parent bug. To simplify comment interaction, we condense these threads into a single thread with a Comment dummy root.

comments()
creator

The user who entered the bug into the system

This property defaults to None.

extra_strings

Space for an array of extra strings. Useful for storing state for functionality implemented purely in becommands/<some_function>.py.

This property defaults to [].

This property is checked with <function _extra_strings_check_fn at 0x9ec4454>.

from_xml(xml_string, preserve_uuids=False, verbose=True)

Note: If a bug uuid is given, set .alt_id to it’s value. >>> bugA = Bug(uuid=”0123”, summary=”Need to test Bug.from_xml()”) >>> bugA.date = “Thu, 01 Jan 1970 00:00:00 +0000” >>> bugA.creator = u’François’ >>> bugA.extra_strings += [‘TAG: very helpful’] >>> commA = bugA.comment_root.new_reply(body=’comment A’) >>> commB = bugA.comment_root.new_reply(body=’comment B’) >>> commC = commA.new_reply(body=’comment C’) >>> xml = bugA.xml(show_comments=True) >>> bugB = Bug() >>> bugB.from_xml(xml, verbose=True) >>> bugB.xml(show_comments=True) == xml False >>> bugB.uuid = bugB.alt_id >>> for comm in bugB.comments(): ... comm.uuid = comm.alt_id ... comm.alt_id = None >>> bugB.xml(show_comments=True) == xml True >>> bugB.explicit_attrs # doctest: +NORMALIZE_WHITESPACE [‘severity’, ‘status’, ‘creator’, ‘time’, ‘summary’] >>> len(list(bugB.comments())) 3 >>> bugC = Bug() >>> bugC.from_xml(xml, preserve_uuids=True) >>> bugC.uuid == bugA.uuid True

load_comments(load_full=True)
load_settings(settings_mapfile=None)
merge(other, accept_changes=True, accept_extra_strings=True, accept_comments=True, change_exception=False)

Merge info from other into this bug. Overrides any attributes in self that are listed in other.explicit_attrs.

>>> bugA = Bug(uuid='0123', summary='Need to test Bug.merge()')
>>> bugA.date = 'Thu, 01 Jan 1970 00:00:00 +0000'
>>> bugA.creator = 'Frank'
>>> bugA.extra_strings += ['TAG: very helpful']
>>> bugA.extra_strings += ['TAG: favorite']
>>> commA = bugA.comment_root.new_reply(body='comment A')
>>> commA.uuid = 'uuid-commA'
>>> bugB = Bug(uuid='3210', summary='More tests for Bug.merge()')
>>> bugB.date = 'Fri, 02 Jan 1970 00:00:00 +0000'
>>> bugB.creator = 'John'
>>> bugB.explicit_attrs = ['creator', 'summary']
>>> bugB.extra_strings += ['TAG: very helpful']
>>> bugB.extra_strings += ['TAG: useful']
>>> commB = bugB.comment_root.new_reply(body='comment B')
>>> commB.uuid = 'uuid-commB'
>>> bugA.merge(bugB, accept_changes=False, accept_extra_strings=False,
...            accept_comments=False, change_exception=False)
>>> print bugA.creator
Frank
>>> bugA.merge(bugB, accept_changes=False, accept_extra_strings=False,
...            accept_comments=False, change_exception=True)
Traceback (most recent call last):
  ...
ValueError: Merge would change creator "Frank"->"John" for bug 0123
>>> print bugA.creator
Frank
>>> bugA.merge(bugB, accept_changes=True, accept_extra_strings=False,
...            accept_comments=False, change_exception=True)
Traceback (most recent call last):
  ...
ValueError: Merge would add extra string "TAG: useful" for bug 0123
>>> print bugA.creator
John
>>> print bugA.extra_strings
['TAG: favorite', 'TAG: very helpful']
>>> bugA.merge(bugB, accept_changes=True, accept_extra_strings=True,
...            accept_comments=False, change_exception=True)
Traceback (most recent call last):
  ...
ValueError: Merge would add comment uuid-commB (alt: None) to bug 0123
>>> print bugA.extra_strings
['TAG: favorite', 'TAG: useful', 'TAG: very helpful']
>>> bugA.merge(bugB, accept_changes=True, accept_extra_strings=True,
...            accept_comments=True, change_exception=True)
>>> print bugA.xml(show_comments=True)  
<bug>
  <uuid>0123</uuid>
  <short-name>/012</short-name>
  <severity>minor</severity>
  <status>open</status>
  <creator>John</creator>
  <created>...</created>
  <summary>More tests for Bug.merge()</summary>
  <extra-string>TAG: favorite</extra-string>
  <extra-string>TAG: useful</extra-string>
  <extra-string>TAG: very helpful</extra-string>
  <comment>
    <uuid>uuid-commA</uuid>
    <short-name>/012/uuid-commA</short-name>
    <author></author>
    <date>...</date>
    <content-type>text/plain</content-type>
    <body>comment A</body>
  </comment>
  <comment>
    <uuid>uuid-commB</uuid>
    <short-name>/012/uuid-commB</short-name>
    <author></author>
    <date>...</date>
    <content-type>text/plain</content-type>
    <body>comment B</body>
  </comment>
</bug>
new_comment(body=None)
remove()
reporter

The user who reported the bug

This property defaults to None.

required_saved_properties = ['severity', 'status']
save()

Save any loaded contents to storage. Because of lazy loading of comments, this is actually not too inefficient.

However, if self.storage.is_writeable() == True, then any changes are automatically written to storage as soon as they happen, so calling this method will just waste time (unless something else has been messing with your stored files).

save_settings()
settings_properties = ['severity', 'status', 'creator', 'reporter', 'assigned', 'time', 'extra_strings', 'summary']
severity

A measure of the bug’s importance

This property defaults to minor.

This property is checked with <function <lambda> at 0x9ec43ac>.

sibling_uuids()
status

The bug’s current status

This property defaults to open.

This property is checked with <function <lambda> at 0x9ec43e4>.

string(shortlist=False, show_comments=False)
summary

A one-line bug description

This property defaults to None.

time

An integer version of .time_string

time_string

An RFC 2822 timestamp for bug creation

This property defaults to None.

uuids()
xml(indent=0, show_comments=False)
>>> bugA = Bug(uuid='0123', summary='Need to test Bug.xml()')
>>> bugA.uuid = 'bugA'
>>> bugA.time_string = 'Thu, 01 Jan 1970 00:00:00 +0000'
>>> bugA.creator = u'Frank'
>>> bugA.extra_strings += ['TAG: very helpful']
>>> commA = bugA.comment_root.new_reply(body='comment A')
>>> commA.uuid = 'commA'
>>> commA.date = 'Thu, 01 Jan 1970 00:01:00 +0000'
>>> commB = commA.new_reply(body='comment B')
>>> commB.uuid = 'commB'
>>> commB.date = 'Thu, 01 Jan 1970 00:02:00 +0000'
>>> commC = commB.new_reply(body='comment C')
>>> commC.uuid = 'commC'
>>> commC.date = 'Thu, 01 Jan 1970 00:03:00 +0000'
>>> print(bugA.xml(show_comments=True))  
<bug>
  <uuid>bugA</uuid>
  <short-name>/bug</short-name>
  <severity>minor</severity>
  <status>open</status>
  <creator>Frank</creator>
  <created>Thu, 01 Jan 1970 00:00:00 +0000</created>
  <summary>Need to test Bug.xml()</summary>
  <extra-string>TAG: very helpful</extra-string>
  <comment>
    <uuid>commA</uuid>
    <short-name>/bug/commA</short-name>
    <author></author>
    <date>Thu, 01 Jan 1970 00:01:00 +0000</date>
    <content-type>text/plain</content-type>
    <body>comment A</body>
  </comment>
  <comment>
    <uuid>commB</uuid>
    <short-name>/bug/commB</short-name>
    <in-reply-to>commA</in-reply-to>
    <author></author>
    <date>Thu, 01 Jan 1970 00:02:00 +0000</date>
    <content-type>text/plain</content-type>
    <body>comment B</body>
  </comment>
  <comment>
    <uuid>commC</uuid>
    <short-name>/bug/commC</short-name>
    <in-reply-to>commB</in-reply-to>
    <author></author>
    <date>Thu, 01 Jan 1970 00:03:00 +0000</date>
    <content-type>text/plain</content-type>
    <body>comment C</body>
  </comment>
</bug>
>>> print(bugA.xml(show_comments=True, indent=2))
... 
  <bug>
    <uuid>bugA</uuid>
    <short-name>/bug</short-name>
    <severity>minor</severity>
    <status>open</status>
    <creator>Frank</creator>
    <created>Thu, 01 Jan 1970 00:00:00 +0000</created>
    <summary>Need to test Bug.xml()</summary>
    <extra-string>TAG: very helpful</extra-string>
    <comment>
      <uuid>commA</uuid>
      <short-name>/bug/commA</short-name>
      <author></author>
      <date>Thu, 01 Jan 1970 00:01:00 +0000</date>
      <content-type>text/plain</content-type>
      <body>comment A</body>
    </comment>
    <comment>
      <uuid>commB</uuid>
      <short-name>/bug/commB</short-name>
      <in-reply-to>commA</in-reply-to>
      <author></author>
      <date>Thu, 01 Jan 1970 00:02:00 +0000</date>
      <content-type>text/plain</content-type>
      <body>comment B</body>
    </comment>
    <comment>
      <uuid>commC</uuid>
      <short-name>/bug/commC</short-name>
      <in-reply-to>commB</in-reply-to>
      <author></author>
      <date>Thu, 01 Jan 1970 00:03:00 +0000</date>
      <content-type>text/plain</content-type>
      <body>comment C</body>
    </comment>
  </bug>
class libbe.bug.BugCompoundComparator(cmp_list=(<function cmp_status at 0x9ceef0c>, <function cmp_severity at 0x9ceefb4>, <function <lambda> at 0x9ec587c>, <function <lambda> at 0x9ec595c>, <function <lambda> at 0x9ec433c>, <function <lambda> at 0x9ec58b4>, <function cmp_comments at 0x9ec59cc>, <function <lambda> at 0x9ec58ec>, <function <lambda> at 0x9bd6ca4>, <function <lambda> at 0x9ec5924>))
libbe.bug.cmp_assigned(bug_1, bug_2)
libbe.bug.cmp_attr(bug_1, bug_2, attr, invert=False)

Compare a general attribute between two bugs using the conventional comparison rule for that attribute type. If invert==True, sort against that convention.

>>> attr="severity"
>>> bugA = Bug()
>>> bugB = Bug()
>>> bugA.severity = "critical"
>>> bugB.severity = "wishlist"
>>> cmp_attr(bugA, bugB, attr) < 0
True
>>> cmp_attr(bugA, bugB, attr, invert=True) > 0
True
>>> bugB.severity = "critical"
>>> cmp_attr(bugA, bugB, attr) == 0
True
libbe.bug.cmp_comments(bug_1, bug_2)

Compare two bugs’ comments lists. Doesn’t load any new comments, so you should call each bug’s .load_comments() first if you want a full comparison.

libbe.bug.cmp_creator(bug_1, bug_2)
libbe.bug.cmp_extra_strings(bug_1, bug_2)
libbe.bug.cmp_last_modified(bug_1, bug_2)

Like cmp_time(), but use most recent comment instead of bug creation for the timestamp.

libbe.bug.cmp_mine(bug_1, bug_2)
libbe.bug.cmp_reporter(bug_1, bug_2)
libbe.bug.cmp_severity(bug_1, bug_2)

Compare the severity levels of two bugs, with more severe bugs comparing as less.

>>> bugA = Bug()
>>> bugB = Bug()
>>> bugA.severity = bugB.severity = "wishlist"
>>> cmp_severity(bugA, bugB) == 0
True
>>> bugB.severity = "minor"
>>> cmp_severity(bugA, bugB) > 0
True
>>> bugA.severity = "critical"
>>> cmp_severity(bugA, bugB) < 0
True
libbe.bug.cmp_status(bug_1, bug_2)

Compare the status levels of two bugs, with more “open” bugs comparing as less.

>>> bugA = Bug()
>>> bugB = Bug()
>>> bugA.status = bugB.status = "open"
>>> cmp_status(bugA, bugB) == 0
True
>>> bugB.status = "closed"
>>> cmp_status(bugA, bugB) < 0
True
>>> bugA.status = "fixed"
>>> cmp_status(bugA, bugB) > 0
True
libbe.bug.cmp_summary(bug_1, bug_2)
libbe.bug.cmp_time(bug_1, bug_2)
libbe.bug.cmp_uuid(bug_1, bug_2)
libbe.bug.load_severities(severity_def)
libbe.bug.load_status(active_status_def, inactive_status_def)

Previous topic

libbe._version

This Page