changeset 229:85340bec3a97

Fix tests broken by [233], and add new tests.
author cmlenz
date Fri, 20 Jul 2007 16:20:43 +0000
parents 629357c88d59
children aaf36f409166
files babel/messages/catalog.py babel/messages/pofile.py babel/messages/tests/catalog.py babel/util.py
diffstat 4 files changed, 49 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/babel/messages/catalog.py
+++ b/babel/messages/catalog.py
@@ -28,7 +28,7 @@
 from babel.core import Locale
 from babel.dates import format_datetime
 from babel.messages.plurals import PLURALS
-from babel.util import odict, LOCALTZ, UTC, FixedOffsetTimezone
+from babel.util import odict, distinct, LOCALTZ, UTC, FixedOffsetTimezone
 
 __all__ = ['Message', 'Catalog', 'TranslationError']
 __docformat__ = 'restructuredtext en'
@@ -66,8 +66,8 @@
             self.flags.add('python-format')
         else:
             self.flags.discard('python-format')
-        self.auto_comments = list(set(auto_comments))
-        self.user_comments = list(set(user_comments))
+        self.auto_comments = list(distinct(auto_comments))
+        self.user_comments = list(distinct(user_comments))
         if isinstance(previous_id, basestring):
             self.previous_id = [previous_id]
         else:
--- a/babel/messages/pofile.py
+++ b/babel/messages/pofile.py
@@ -122,7 +122,7 @@
                    if the catalog is not bound to a locale (which basically
                    means it's a template)
     :param domain: the message domain
-    :ignore_obsolete: whether to ignore obsolete messages in the input
+    :param ignore_obsolete: whether to ignore obsolete messages in the input
     :return: an iterator over ``(message, translation, location)`` tuples
     :rtype: ``iterator``
     """
@@ -151,8 +151,7 @@
         else:
             string = denormalize(translations[0][1])
         message = Message(msgid, string, list(locations), set(flags),
-                          list(set(auto_comments)), list(set(user_comments)),
-                          lineno=offset[0] + 1)
+                          auto_comments, user_comments, lineno=offset[0] + 1)
         if obsolete[0]:
             if not ignore_obsolete:
                 catalog.obsolete[msgid] = message
@@ -350,10 +349,12 @@
     :param no_location: do not emit a location comment for every message
     :param omit_header: do not include the ``msgid ""`` entry at the top of the
                         output
-    :sort_output: whether to sort the messages in the output by msgid
-    :sort_by_file: whether to sort the messages in the output by their locations
-    :ignore_obsolete: whether to ignore obsolete messages and not include them
-                      in the output; by default they are included as comments
+    :param sort_output: whether to sort the messages in the output by msgid
+    :param sort_by_file: whether to sort the messages in the output by their
+                         locations
+    :param ignore_obsolete: whether to ignore obsolete messages and not include
+                            them in the output; by default they are included as
+                            comments
     :param include_previous: include the old msgid as a comment when
                               updating the catalog
     """
@@ -408,9 +409,9 @@
                 comment_header = u'\n'.join(lines) + u'\n'
             _write(comment_header)
 
-        for comment in list(set(message.user_comments)):
+        for comment in message.user_comments:
             _write_comment(comment)
-        for comment in list(set(message.auto_comments)):
+        for comment in message.auto_comments:
             _write_comment(comment, prefix='.')
 
         if not no_location:
@@ -433,7 +434,7 @@
 
     if not ignore_obsolete:
         for message in catalog.obsolete.values():
-            for comment in list(set(message.user_comments)):
+            for comment in message.user_comments:
                 _write_comment(comment)
             _write_message(message, prefix='#~ ')
             _write('\n')
--- a/babel/messages/tests/catalog.py
+++ b/babel/messages/tests/catalog.py
@@ -53,6 +53,14 @@
         cat.add(('foo', 'foos'))
         self.assertEqual(1, len(cat))
 
+    def test_duplicate_auto_comment(self):
+        msg = catalog.Message('foo', auto_comments=['A comment', 'A comment'])
+        self.assertEqual(['A comment'], msg.auto_comments)
+
+    def test_duplicate_user_comment(self):
+        msg = catalog.Message('foo', user_comments=['A comment', 'A comment'])
+        self.assertEqual(['A comment'], msg.user_comments)
+
     def test_update_message_updates_comments(self):
         cat = catalog.Catalog()
         cat[u'foo'] = catalog.Message('foo', locations=[('main.py', 5)])
--- a/babel/util.py
+++ b/babel/util.py
@@ -18,11 +18,36 @@
 import os
 import parser
 import re
+try:
+    set
+except NameError:
+    from sets import Set as set
 import time
 
-__all__ = ['pathmatch', 'relpath', 'UTC', 'LOCALTZ']
+__all__ = ['distinct', 'pathmatch', 'relpath', 'odict', 'UTC', 'LOCALTZ']
 __docformat__ = 'restructuredtext en'
 
+def distinct(iterable):
+    """Yield all items in an iterable collection that are distinct.
+
+    Unlike when using sets for a similar effect, the original ordering of the
+    items in the collection is preserved by this function.
+
+    >>> print list(distinct([1, 2, 1, 3, 4, 4]))
+    [1, 2, 3, 4]
+    >>> print list(distinct('foobar'))
+    ['f', 'o', 'b', 'a', 'r']
+
+    :param iterable: the iterable collection providing the data
+    :return: the distinct items in the collection
+    :rtype: ``iterator``
+    """
+    seen = set()
+    for item in iter(iterable):
+        if item not in seen:
+            yield item
+            seen.add(item)
+
 # Regexp to match python magic encoding line
 PYTHON_MAGIC_COMMENT_re = re.compile(
     r'[ \t\f]* \# .* coding[=:][ \t]*([-\w.]+)', re.VERBOSE)
@@ -123,7 +148,7 @@
 class odict(dict):
     """Ordered dict implementation.
     
-    :see: `http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/107747`
+    :see: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/107747
     """
     def __init__(self, data=None):
         dict.__init__(self, data or {})
Copyright (C) 2012-2017 Edgewall Software