util:http: special handling for HTTP_USER_ERROR in get_post_url().
[be.git] / libbe / comment.py
index 3527d50ab887a18ff6530cb2591c67143ea90fd0..a669e4e5012e180f229ca324426dbee53d64994b 100644 (file)
@@ -1,24 +1,25 @@
-# Copyright (C) 2008-2011 Chris Ball <cjb@laptop.org>
+# Copyright (C) 2008-2012 Chris Ball <cjb@laptop.org>
 #                         Gianluca Montecchi <gian@grys.it>
+#                         Niall Douglas (s_sourceforge@nedprod.com) <spam@spamtrap.com>
 #                         Thomas Habets <thomas@habets.pp.se>
-#                         W. Trevor King <wking@drexel.edu>
+#                         W. Trevor King <wking@tremily.us>
 #
 # This file is part of Bugs Everywhere.
 #
-# Bugs Everywhere is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation, either version 2 of the License, or (at your
-# option) any later version.
+# Bugs Everywhere is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 2 of the License, or (at your option) any
+# later version.
 #
 # Bugs Everywhere is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# General Public License for more details.
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+# more details.
 #
-# You should have received a copy of the GNU General Public License
-# along with Bugs Everywhere.  If not, see <http://www.gnu.org/licenses/>.
+# You should have received a copy of the GNU General Public License along with
+# Bugs Everywhere.  If not, see <http://www.gnu.org/licenses/>.
 
-"""Define the :class:`Comment` class for representing bug comments.
+"""Define :py:class:`Comment` for representing bug comments.
 """
 
 import base64
@@ -86,11 +87,13 @@ def load_comments(bug, load_full=False):
 
 def save_comments(bug):
     for comment in bug.comment_root.traverse():
+        comment.bug = bug
+        comment.storage = bug.storage
         comment.save()
 
 
 class Comment (Tree, settings_object.SavedSettingsObject):
-    """Comments are a notes that attach to :class:`~libbe.bug.Bug`\s in
+    """Comments are a notes that attach to :py:class:`~libbe.bug.Bug`\s in
     threaded trees.  In mailing-list terms, a comment is analogous to
     a single part of an email.
 
@@ -156,7 +159,8 @@ class Comment (Tree, settings_object.SavedSettingsObject):
         assert self.uuid != INVALID_UUID, self
         if self.content_type.startswith('text/') \
                 and self.bug != None and self.bug.bugdir != None:
-            new = libbe.util.id.short_to_long_text([self.bug.bugdir], new)
+            new = libbe.util.id.short_to_long_text(
+                {self.bug.bugdir.uuid: self.bug.bugdir}, new)
         if (self.storage != None and self.storage.writeable == True) \
                 or force==True:
             assert new != None, "Can't save empty comment"
@@ -195,8 +199,8 @@ class Comment (Tree, settings_object.SavedSettingsObject):
         if ``from_storage==False`` (the default).  When
         ``from_storage==True``, they are loaded from the bug database.
         ``content_type`` decides if the body should be run through
-        :func:`util.id.short_to_long_text` before saving.  See
-        :meth:`_set_comment_body` for details.
+        :py:func:`util.id.short_to_long_text` before saving.  See
+        :py:meth:`_set_comment_body` for details.
 
         ``in_reply_to`` should be the uuid string of the parent comment.
         """
@@ -377,7 +381,9 @@ class Comment (Tree, settings_object.SavedSettingsObject):
                     text = settings_object.EMPTY
                 else:
                     text = xml.sax.saxutils.unescape(child.text)
-                    text = text.decode('unicode_escape').strip()
+                    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 comment's uuid tag.
@@ -456,16 +462,17 @@ class Comment (Tree, settings_object.SavedSettingsObject):
           <extra-string>TAG: very helpful</extra-string>
         </comment>
         """
-        for attr in other.explicit_attrs:
-            old = getattr(self, attr)
-            new = getattr(other, attr)
-            if old != new:
-                if accept_changes == True:
-                    setattr(self, attr, new)
-                elif change_exception == True:
-                    raise ValueError, \
-                        'Merge would change %s "%s"->"%s" for comment %s' \
-                        % (attr, old, new, self.uuid)
+        if hasattr(other, 'explicit_attrs'):
+            for attr in other.explicit_attrs:
+                old = getattr(self, attr)
+                new = getattr(other, attr)
+                if old != new:
+                    if accept_changes:
+                        setattr(self, attr, new)
+                    elif change_exception:
+                        raise ValueError(
+                            ('Merge would change {} "{}"->"{}" for comment {}'
+                             ).format(attr, old, new, self.uuid))
         if self.alt_id == self.uuid:
             self.alt_id = None
         for estr in other.extra_strings:
@@ -501,7 +508,8 @@ class Comment (Tree, settings_object.SavedSettingsObject):
         if self.content_type.startswith("text/"):
             body = (self.body or "")
             if self.bug != None and self.bug.bugdir != None:
-                body = libbe.util.id.long_to_short_text([self.bug.bugdir], body)
+                body = libbe.util.id.long_to_short_text(
+                    {self.bug.bugdir.uuid: self.bug.bugdir}, body)
             lines.extend(body.splitlines())
         else:
             lines.append("Content type %s not printable.  Try XML output instead" % self.content_type)
@@ -601,7 +609,7 @@ class Comment (Tree, settings_object.SavedSettingsObject):
             return
         if settings_mapfile == None:
             settings_mapfile = self.storage.get(
-                self.id.storage('values'), '\n')
+                self.id.storage('values'), '{}\n')
         try:
             settings = mapfile.parse(settings_mapfile)
         except mapfile.InvalidMapfileContents, e: