Define the Bug class for representing bugs.
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[, 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]) |
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>
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.
The developer in charge of the bug
This property defaults to None.
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.
The user who entered the bug into the system
This property defaults to None.
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 0xaa6fae4>.
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’, ‘created’, ‘summary’] >>> len(list(bugB.comments())) 3
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>
The user who reported the bug
This property defaults to None.
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).
A measure of the bug’s importance
This property defaults to minor.
This property is checked with <function <lambda> at 0xaa6cf44>.
The bug’s current status
This property defaults to open.
This property is checked with <function <lambda> at 0xaa6cf7c>.
A one-line bug description
This property defaults to None.
An integer version of .time_string
An RFC 2822 timestamp for bug creation
This property defaults to None.
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
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.
Like cmp_time(), but use most recent comment instead of bug creation for the timestamp.
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
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