]> granicus.if.org Git - python/commitdiff
Issue #7080: locale.strxfrm() raises a MemoryError on 64-bit non-Windows
authorAntoine Pitrou <solipsis@pitrou.net>
Mon, 19 Oct 2009 19:43:09 +0000 (19:43 +0000)
committerAntoine Pitrou <solipsis@pitrou.net>
Mon, 19 Oct 2009 19:43:09 +0000 (19:43 +0000)
platforms, and assorted locale fixes by Derk Drukker.

Lib/locale.py
Lib/test/test_locale.py
Misc/NEWS
Modules/_localemodule.c
PC/pyconfig.h

index b7aaa52f041990ebee8356566727274130cf8ff9..c50af53f7345d8aa42244646e1ca4f5ed21e3f53 100644 (file)
@@ -578,14 +578,13 @@ else:
                     # returning nothing will crash the
                     # interpreter.
                     result = 'UTF-8'
-
                 setlocale(LC_CTYPE, oldloc)
-                return result
             else:
                 result = nl_langinfo(CODESET)
                 if not result and sys.platform == 'darwin':
                     # See above for explanation
                     result = 'UTF-8'
+            return result
 
 
 ### Database
index 65639ad014ee5b627bd88e761b99dbc275f5dec3..8dfaf9052d75bb6923c52e9e6598467d44aad49e 100644 (file)
@@ -8,12 +8,10 @@ enUS_locale = None
 
 def get_enUS_locale():
     global enUS_locale
-    if sys.platform == 'darwin':
-        raise unittest.SkipTest("Locale support on MacOSX is minimal")
     if sys.platform.startswith("win"):
         tlocs = ("En", "English")
     else:
-        tlocs = ("en_US.UTF-8", "en_US.US-ASCII", "en_US")
+        tlocs = ("en_US.UTF-8", "en_US.ISO8859-1", "en_US.US-ASCII", "en_US")
     oldlocale = locale.setlocale(locale.LC_NUMERIC)
     for tloc in tlocs:
         try:
@@ -309,6 +307,39 @@ class TestFrFRNumberFormatting(FrFRCookedTest, BaseFormattingTest):
             grouping=True, international=True)
 
 
+class TestCollation(unittest.TestCase):
+    # Test string collation functions
+
+    def test_strcoll(self):
+        self.assertLess(locale.strcoll('a', 'b'), 0)
+        self.assertEqual(locale.strcoll('a', 'a'), 0)
+        self.assertGreater(locale.strcoll('b', 'a'), 0)
+
+    def test_strxfrm(self):
+        self.assertLess(locale.strxfrm('a'), locale.strxfrm('b'))
+
+
+class TestEnUSCollation(BaseLocalizedTest, TestCollation):
+    # Test string collation functions with a real English locale
+
+    locale_type = locale.LC_ALL
+
+    def setUp(self):
+        BaseLocalizedTest.setUp(self)
+        enc = codecs.lookup(locale.getpreferredencoding(False) or 'ascii').name
+        if enc not in ('utf-8', 'iso8859-1', 'cp1252'):
+            raise unittest.SkipTest('encoding not suitable')
+        if enc != 'iso8859-1' and (sys.platform == 'darwin' or
+                                   sys.platform.startswith('freebsd')):
+            raise unittest.SkipTest('wcscoll/wcsxfrm have known bugs')
+
+    def test_strcoll_with_diacritic(self):
+        self.assertLess(locale.strcoll('à', 'b'), 0)
+
+    def test_strxfrm_with_diacritic(self):
+        self.assertLess(locale.strxfrm('à'), locale.strxfrm('b'))
+
+
 class TestMiscellaneous(unittest.TestCase):
     def test_getpreferredencoding(self):
         # Invoke getpreferredencoding to make sure it does not cause exceptions.
@@ -317,11 +348,10 @@ class TestMiscellaneous(unittest.TestCase):
             # If encoding non-empty, make sure it is valid
             codecs.lookup(enc)
 
-    if hasattr(locale, "strcoll"):
-        def test_strcoll_3303(self):
-            # test crasher from bug #3303
-            self.assertRaises(TypeError, locale.strcoll, "a", None)
-            self.assertRaises(TypeError, locale.strcoll, b"a", None)
+    def test_strcoll_3303(self):
+        # test crasher from bug #3303
+        self.assertRaises(TypeError, locale.strcoll, "a", None)
+        self.assertRaises(TypeError, locale.strcoll, b"a", None)
 
 
 def test_main():
@@ -331,6 +361,7 @@ def test_main():
         TestEnUSNumberFormatting,
         TestCNumberFormatting,
         TestFrFRNumberFormatting,
+        TestCollation
     ]
     # SkipTest can't be raised inside unittests, handle it manually instead
     try:
@@ -339,7 +370,7 @@ def test_main():
         if verbose:
             print("Some tests will be disabled: %s" % e)
     else:
-        tests += [TestNumberFormatting]
+        tests += [TestNumberFormatting, TestEnUSCollation]
     run_unittest(*tests)
 
 if __name__ == '__main__':
index b088fe014237e068f8df1030d336368838086972..a42a132e06378b7303793c316a3ee88041e62b5b 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -100,6 +100,9 @@ C-API
 Library
 -------
 
+- Issue #7080: locale.strxfrm() raises a MemoryError on 64-bit non-Windows
+  platforms, and assorted locale fixes by Derk Drukker.
+
 - Issue #5833: Fix extra space character in readline completion with the
   GNU readline library version 6.0.
 
@@ -118,7 +121,7 @@ Library
   is too large to fit in the current precision.
 
 - Issue #6236, #6348: Fix various failures in the I/O library under AIX
-  and other platforms, when using a non-gcc compiler. Patch by egreen.
+  and other platforms, when using a non-gcc compiler. Patch by Derk Drukker.
 
 - Issue #4606: Passing 'None' if ctypes argtype is set to POINTER(...)
   does now always result in NULL.
index 8bcdb102ae44f987a597fb35c8e56f41ee23cf67..d90a49df969339fa10663962da8eaa3f5f6b602b 100644 (file)
@@ -9,6 +9,7 @@ This software comes with no warranty. Use at your own risk.
 
 ******************************************************************/
 
+#define PY_SSIZE_T_CLEAN
 #include "Python.h"
 
 #include <stdio.h>
@@ -315,7 +316,7 @@ PyLocale_strxfrm(PyObject* self, PyObject* args)
     result = PyUnicode_FromWideChar(buf, n2);
  exit:
     if (buf) PyMem_Free(buf);
-#ifdef HAVE_USABLE_WCHAR_T
+#ifndef HAVE_USABLE_WCHAR_T
     PyMem_Free(s);
 #endif
     return result;
index fb2aaf6953fc429b50650f7ba3a72fdae5ec2c3e..176538ea792ace06b61b1dda177338d37f663b10 100644 (file)
@@ -641,6 +641,11 @@ Py_NO_ENABLE_SHARED to find out.  Also support MS_NO_COREDLL for b/w compat */
 #define HAVE_WCSCOLL 1
 #endif
 
+/* Define to 1 if you have the `wcsxfrm' function. */
+#ifndef MS_WINCE
+#define HAVE_WCSXFRM 1
+#endif
+
 /* Define if you have the <dlfcn.h> header file.  */
 /* #undef HAVE_DLFCN_H */