+ def xml(self, 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)) # doctest: +REPORT_UDIFF
+ <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))
+ ... # doctest: +REPORT_UDIFF
+ <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>
+ """
+ if self.time == None:
+ timestring = ""
+ else:
+ timestring = utility.time_to_str(self.time)
+
+ info = [('uuid', self.uuid),
+ ('short-name', self.id.user()),
+ ('severity', self.severity),
+ ('status', self.status),
+ ('assigned', self.assigned),
+ ('reporter', self.reporter),
+ ('creator', self.creator),
+ ('created', timestring),
+ ('summary', self.summary)]
+ lines = ['<bug>']
+ for (k,v) in info:
+ if v is not None:
+ lines.append(' <%s>%s</%s>' % (k,xml.sax.saxutils.escape(v),k))
+ for estr in self.extra_strings:
+ lines.append(' <extra-string>%s</extra-string>' % estr)
+ if show_comments == True:
+ comout = self.comment_root.xml_thread(indent=indent+2)
+ if comout:
+ comout = comout[indent:] # strip leading indent spaces
+ lines.append(comout)
+ lines.append('</bug>')
+ istring = ' '*indent
+ sep = '\n' + istring
+ return istring + sep.join(lines).rstrip('\n')
+
+ def from_xml(self, xml_string, preserve_uuids=False):
+ u"""
+ 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\xe7ois'
+ >>> 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)
+ >>> 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
+ """
+ if type(xml_string) == types.UnicodeType:
+ xml_string = xml_string.strip().encode('unicode_escape')
+ if hasattr(xml_string, 'getchildren'): # already an ElementTree Element
+ bug = xml_string
+ else:
+ bug = ElementTree.XML(xml_string)
+ if bug.tag != 'bug':
+ raise utility.InvalidXML( \
+ 'bug', bug, 'root element must be <bug>')
+ tags=['uuid','short-name','severity','status','assigned',
+ 'reporter', 'creator','created','summary','extra-string']
+ self.explicit_attrs = []
+ uuid = None
+ estrs = []
+ comments = []
+ for child in bug.getchildren():
+ if child.tag == 'short-name':
+ pass
+ elif child.tag == 'comment':
+ comm = comment.Comment(bug=self)
+ comm.from_xml(child, preserve_uuids=preserve_uuids)
+ comments.append(comm)
+ continue
+ elif child.tag in tags:
+ if child.text == None or len(child.text) == 0:
+ text = settings_object.EMPTY
+ else:
+ text = xml.sax.saxutils.unescape(child.text)
+ if not isinstance(text, unicode):
+ text = text.decode('unicode_escape')
+ text = text.strip()
+ if child.tag == 'uuid' and not preserve_uuids:
+ uuid = text
+ continue # don't set the bug's uuid tag.
+ elif child.tag == 'created':
+ if text is not settings_object.EMPTY:
+ self.time = utility.str_to_time(text)
+ self.explicit_attrs.append('time')
+ continue
+ elif child.tag == 'extra-string':
+ estrs.append(text)
+ continue # don't set the bug's extra_string yet.
+ attr_name = child.tag.replace('-','_')
+ self.explicit_attrs.append(attr_name)
+ setattr(self, attr_name, text)
+ else:
+ libbe.LOG.warning(
+ 'ignoring unknown tag {0} in {1}'.format(
+ child.tag, comment.tag))
+ if uuid != self.uuid:
+ if not hasattr(self, 'alt_id') or self.alt_id == None:
+ self.alt_id = uuid
+ self.extra_strings = estrs
+ self.add_comments(comments, ignore_missing_references=True)
+
+ def add_comment(self, 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) # doctest: +ELLIPSIS
+ <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>
+ """
+ self.add_comments([comment], **kwargs)