Merged revisions 60210-60233 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r60213 | christian.heimes | 2008-01-23 15:00:25 +0100 (Wed, 23 Jan 2008) | 1 line

  Use Py_TYPE() instead of ->ob_type
........
  r60214 | armin.rigo | 2008-01-23 15:07:13 +0100 (Wed, 23 Jan 2008) | 3 lines

  patch 1754489 by vlahan:
  improve portability of address length calculation for AF_UNIX sockets
........
  r60216 | christian.heimes | 2008-01-23 15:20:50 +0100 (Wed, 23 Jan 2008) | 1 line

  Fixed bug #1915: Python compiles with --enable-unicode=no again. However several extension methods and modules do not work without unicode support.
........
  r60221 | christian.heimes | 2008-01-23 18:15:06 +0100 (Wed, 23 Jan 2008) | 2 lines

  Applied #1069410
  The "can't load dll" message box on Windows is suppressed while an extension is loaded by calling SetErrorMode in dynload_win.c. The error is still reported properly.
........
  r60224 | guido.van.rossum | 2008-01-23 21:19:01 +0100 (Wed, 23 Jan 2008) | 2 lines

  Fix two crashers.
........
  r60225 | kurt.kaiser | 2008-01-23 23:19:23 +0100 (Wed, 23 Jan 2008) | 3 lines

  Could not open files in .idlerc directory if latter was hidden on Windows.
  Issue 1743, Issue 1862.
........
  r60226 | guido.van.rossum | 2008-01-23 23:43:27 +0100 (Wed, 23 Jan 2008) | 2 lines

  Fix misleading comment reported in issue #1917.
........
  r60227 | kurt.kaiser | 2008-01-23 23:55:26 +0100 (Wed, 23 Jan 2008) | 2 lines

  There was an error on exit if no sys.exitfunc was defined. Issue 1647.
........
  r60228 | guido.van.rossum | 2008-01-24 00:23:43 +0100 (Thu, 24 Jan 2008) | 2 lines

  Turn three recently fixed crashers into regular tests.
........
  r60229 | raymond.hettinger | 2008-01-24 01:54:21 +0100 (Thu, 24 Jan 2008) | 1 line

  Add first-cut at an approximation function (still needs rounding tweaks).  Add continued fraction conversions.
........
  r60230 | raymond.hettinger | 2008-01-24 03:00:25 +0100 (Thu, 24 Jan 2008) | 1 line

  Minor clean-up and more tests.
........
  r60231 | raymond.hettinger | 2008-01-24 03:05:06 +0100 (Thu, 24 Jan 2008) | 1 line

  Cleanup
........
  r60232 | neal.norwitz | 2008-01-24 05:14:50 +0100 (Thu, 24 Jan 2008) | 1 line

  Fix the tests by restoring __import__.  I think the test is still valid.
........
  r60233 | neal.norwitz | 2008-01-24 08:40:51 +0100 (Thu, 24 Jan 2008) | 4 lines

  Fix the test_urllib2net failures that were caused by r58067.
  I'm not sure this is the correct fix, but at least the test passes
  now and should be closer to correct.
........
diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt
index 12a0c6f..d51d94e 100644
--- a/Lib/idlelib/NEWS.txt
+++ b/Lib/idlelib/NEWS.txt
@@ -45,6 +45,11 @@
 
 *Release date: XX-XXX-200X*  UNRELEASED, but merged into 3.0
 
+- There was an error on exit if no sys.exitfunc was defined. Issue 1647.
+
+- Could not open files in .idlerc directory if latter was hidden on Windows.
+  Issue 1743, Issue 1862.
+
 - Configure Dialog: improved layout for keybinding.  Patch 1457 Tal Einat.
 
 - tabpage.py updated: tabbedPages.py now supports multiple dynamic rows
diff --git a/Lib/idlelib/configHandler.py b/Lib/idlelib/configHandler.py
index b5d9769..66bad74 100644
--- a/Lib/idlelib/configHandler.py
+++ b/Lib/idlelib/configHandler.py
@@ -139,7 +139,12 @@
 
         """
         if not self.IsEmpty():
-            cfgFile=open(self.file,'w')
+            fname = self.file
+            try:
+                cfgFile = open(fname, 'w')
+            except IOError:
+                fname.unlink()
+                cfgFile = open(fname, 'w')
             self.write(cfgFile)
         else:
             self.RemoveFile()
diff --git a/Lib/rational.py b/Lib/rational.py
index 71ffff7..4a56cf2 100755
--- a/Lib/rational.py
+++ b/Lib/rational.py
@@ -171,6 +171,42 @@
         else:
             return cls(digits, 10 ** -exp)
 
+    @classmethod
+    def from_continued_fraction(cls, seq):
+        'Build a Rational from a continued fraction expessed as a sequence'
+        n, d = 1, 0
+        for e in reversed(seq):
+            n, d = d, n
+            n += e * d
+        return cls(n, d) if seq else cls(0)
+
+    def as_continued_fraction(self):
+        'Return continued fraction expressed as a list'
+        n = self.numerator
+        d = self.denominator
+        cf = []
+        while d:
+            e = int(n // d)
+            cf.append(e)
+            n -= e * d
+            n, d = d, n
+        return cf
+
+    @classmethod
+    def approximate_from_float(cls, f, max_denominator):
+        'Best rational approximation to f with a denominator <= max_denominator'
+        # XXX First cut at algorithm
+        # Still needs rounding rules as specified at
+        #       http://en.wikipedia.org/wiki/Continued_fraction
+        cf = cls.from_float(f).as_continued_fraction()
+        result = Rational(0)
+        for i in range(1, len(cf)):
+            new = cls.from_continued_fraction(cf[:i])
+            if new.denominator > max_denominator:
+                break
+            result = new
+        return result
+
     @property
     def numerator(a):
         return a._numerator
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
index 8ccece1..7ef702b 100644
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -1,7 +1,7 @@
 # Test enhancements related to descriptors and new-style classes
 
-from test.test_support import verify, vereq, verbose, TestFailed, TESTFN
-from test.test_support import get_original_stdout
+# XXX Please, please, please, someone convert this to unittest style!
+from test.test_support import verify, vereq, verbose, TestFailed, TESTFN, get_original_stdout
 from copy import deepcopy
 import types
 
@@ -4173,6 +4173,8 @@
     # ceval.c's assign_slice used to check for
     # tp->tp_as_sequence->sq_slice instead of
     # tp->tp_as_sequence->sq_ass_slice
+    if verbose:
+        print("Testing assign_slice...")
 
     class C(object):
         def __setitem__(self, idx, value):
@@ -4182,8 +4184,72 @@
     c[1:2] = 3
     vereq(c.value, 3)
 
+def test_weakref_in_del_segfault():
+    # This used to segfault until r60057
+    if verbose:
+        print("Testing weakref in del segfault...")
+
+    import weakref
+    global ref
+
+    class Target():
+        def __del__(self):
+            global ref
+            ref = weakref.ref(self)
+
+    w = Target()
+    del w
+    del ref
+
+def test_borrowed_ref_3_segfault():
+    # This used to segfault until r60224
+    if verbose:
+        print("Testing borrowed ref 3 segfault...")
+
+    class KeyFunc(object):
+        def __call__(self, n):
+            del d['key']
+            return 1
+
+    d = {'key': KeyFunc()}
+    try:
+        min(range(10), **d)
+    except:
+        pass
+
+def test_borrowed_ref_4_segfault():
+    # This used to segfault until r60224
+    if verbose:
+        print("Testing borrowed ref 4 segfault...")
+
+    import types
+    import builtins
+
+    class X(object):
+        def __getattr__(self, name):
+            # this is called with name == '__bases__' by PyObject_IsInstance()
+            # during the unbound method call -- it frees the unbound method
+            # itself before it invokes its im_func.
+            del builtins.__import__
+            return ()
+
+    pseudoclass = X()
+
+    class Y(object):
+        def __call__(self, *args):
+            # 'self' was freed already
+            return (self, args)
+
+    # make an unbound method
+    orig_import = __import__
+    try:
+        builtins.__import__ = types.MethodType(Y(), (pseudoclass, str))
+        import spam
+    finally:
+        builtins.__import__ = orig_import
+
 def test_main():
-    weakref_segfault() # Must be first, somehow
+    #XXXweakref_segfault() # Must be first, somehow
     wrapper_segfault() # NB This one is slow
     do_this_first()
     class_docstrings()
@@ -4279,6 +4345,9 @@
     methodwrapper()
     notimplemented()
     test_assign_slice()
+    test_weakref_in_del_segfault()
+    test_borrowed_ref_3_segfault()
+    test_borrowed_ref_4_segfault()
 
     if verbose: print("All OK")
 
diff --git a/Lib/test/test_rational.py b/Lib/test/test_rational.py
index e57adce..1bd1814 100644
--- a/Lib/test/test_rational.py
+++ b/Lib/test/test_rational.py
@@ -135,6 +135,29 @@
             TypeError, "Cannot convert sNaN to Rational.",
             R.from_decimal, Decimal("snan"))
 
+    def testFromContinuedFraction(self):
+        self.assertRaises(TypeError, R.from_continued_fraction, None)
+        phi = R.from_continued_fraction([1]*100)
+        self.assertEquals(round(phi - (1 + 5 ** 0.5) / 2, 10), 0.0)
+
+        minusphi = R.from_continued_fraction([-1]*100)
+        self.assertEquals(round(minusphi + (1 + 5 ** 0.5) / 2, 10), 0.0)
+
+        self.assertEquals(R.from_continued_fraction([0]), R(0))
+        self.assertEquals(R.from_continued_fraction([]), R(0))
+
+    def testAsContinuedFraction(self):
+        self.assertEqual(R.from_float(math.pi).as_continued_fraction()[:15],
+                         [3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 3, 3])
+        self.assertEqual(R.from_float(-math.pi).as_continued_fraction()[:16],
+                         [-4, 1, 6, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 3, 3])
+        self.assertEqual(R(0).as_continued_fraction(), [0])
+
+    def testApproximateFromFloat(self):
+        self.assertEqual(R.approximate_from_float(math.pi, 10000), R(355, 113))
+        self.assertEqual(R.approximate_from_float(-math.pi, 10000), R(-355, 113))
+        self.assertEqual(R.approximate_from_float(0.0, 10000), R(0))
+
     def testConversions(self):
         self.assertTypedEquals(-1, trunc(R(-11, 10)))
         self.assertTypedEquals(-2, math.floor(R(-11, 10)))
diff --git a/Lib/urllib2.py b/Lib/urllib2.py
index fb2c303..3ad0b15 100644
--- a/Lib/urllib2.py
+++ b/Lib/urllib2.py
@@ -1286,7 +1286,7 @@
             headers = mimetools.Message(sf)
             return addinfourl(fp, headers, req.get_full_url())
         except ftplib.all_errors as msg:
-            raise URLError('ftp error %s' % msg).with_traceback(sys.exc_info()[2])
+            raise URLError('ftp error: %s' % msg).with_traceback(sys.exc_info()[2])
 
     def connect_ftp(self, user, passwd, host, port, dirs, timeout):
         fw = ftpwrapper(user, passwd, host, port, dirs, timeout)