[Python-checkins] cpython (merge default -> default): Merge with hg.python.org.

reid.kleckner python-checkins at python.org
Tue Mar 15 00:34:28 CET 2011


http://hg.python.org/cpython/rev/213705ca8ba7
changeset:   68482:213705ca8ba7
parent:      68481:1e578e964c14
parent:      68480:2a584412d541
user:        Reid Kleckner <reid at kleckner.net>
date:        Mon Mar 14 19:34:13 2011 -0400
summary:
  Merge with hg.python.org.

files:
  

diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst
--- a/Doc/library/subprocess.rst
+++ b/Doc/library/subprocess.rst
@@ -387,6 +387,11 @@
 :func:`call` and :meth:`Popen.communicate` will raise :exc:`TimeoutExpired` if
 the timeout expires before the process exits.
 
+Exceptions defined in this module all inherit from :ext:`SubprocessError`.
+
+   .. versionadded:: 3.3
+      The :exc:`SubprocessError` base class was added.
+
 
 Security
 ^^^^^^^^
diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst
--- a/Doc/library/unittest.rst
+++ b/Doc/library/unittest.rst
@@ -723,7 +723,7 @@
    Here, we create two instances of :class:`WidgetTestCase`, each of which runs a
    single test.
 
-   .. versionchanged::
+   .. versionchanged:: 3.2
       `TestCase` can be instantiated successfully without providing a method
       name. This makes it easier to experiment with `TestCase` from the
       interactive interpreter.
@@ -792,11 +792,14 @@
       Run the test, collecting the result into the test result object passed as
       *result*.  If *result* is omitted or ``None``, a temporary result
       object is created (by calling the :meth:`defaultTestResult` method) and
-      used. The result object is not returned to :meth:`run`'s caller.
+      used. The result object is returned to :meth:`run`'s caller.
 
       The same effect may be had by simply calling the :class:`TestCase`
       instance.
 
+      .. versionchanged:: 3.3
+         Previous versions of ``run`` did not return the result. Neither did
+         calling an instance.
 
    .. method:: skipTest(reason)
 
diff --git a/Lib/dbm/__init__.py b/Lib/dbm/__init__.py
--- a/Lib/dbm/__init__.py
+++ b/Lib/dbm/__init__.py
@@ -67,10 +67,10 @@
         if not _defaultmod:
             raise ImportError("no dbm clone found; tried %s" % _names)
 
-    # guess the type of an existing database
-    result = whichdb(file)
+    # guess the type of an existing database, if not creating a new one
+    result = whichdb(file) if 'n' not in flag else None
     if result is None:
-        # db doesn't exist
+        # db doesn't exist or 'n' flag was specified to create a new db
         if 'c' in flag or 'n' in flag:
             # file doesn't exist and the new flag was used so use default type
             mod = _defaultmod
diff --git a/Lib/email/generator.py b/Lib/email/generator.py
--- a/Lib/email/generator.py
+++ b/Lib/email/generator.py
@@ -59,7 +59,7 @@
         self._fp.write(s)
 
     def flatten(self, msg, unixfrom=False, linesep='\n'):
-        """Print the message object tree rooted at msg to the output file
+        r"""Print the message object tree rooted at msg to the output file
         specified when the Generator instance was created.
 
         unixfrom is a flag that forces the printing of a Unix From_ delimiter
@@ -70,7 +70,10 @@
         Note that for subobjects, no From_ line is printed.
 
         linesep specifies the characters used to indicate a new line in
-        the output.
+        the output.  The default value is the most useful for typical
+        Python applications, but it can be set to \r\n to produce RFC-compliant
+        line separators when needed.
+
         """
         # We use the _XXX constants for operating on data that comes directly
         # from the msg, and _encoded_XXX constants for operating on data that
diff --git a/Lib/email/header.py b/Lib/email/header.py
--- a/Lib/email/header.py
+++ b/Lib/email/header.py
@@ -276,7 +276,7 @@
         self._chunks.append((s, charset))
 
     def encode(self, splitchars=';, \t', maxlinelen=None, linesep='\n'):
-        """Encode a message header into an RFC-compliant format.
+        r"""Encode a message header into an RFC-compliant format.
 
         There are many issues involved in converting a given string for use in
         an email header.  Only certain character sets are readable in most
diff --git a/Lib/subprocess.py b/Lib/subprocess.py
--- a/Lib/subprocess.py
+++ b/Lib/subprocess.py
@@ -191,8 +191,10 @@
 
 A ValueError will be raised if Popen is called with invalid arguments.
 
-check_call() and check_output() will raise CalledProcessError, if the
-called process returns a non-zero return code.
+Exceptions defined within this module inherit from SubprocessError.
+check_call() and check_output() will raise CalledProcessError if the
+called process returns a non-zero return code.  TimeoutExpired
+be raised if a timeout was specified and expired.
 
 
 Security
@@ -348,7 +350,10 @@
 import warnings
 
 # Exception classes used by this module.
-class CalledProcessError(Exception):
+class SubprocessError(Exception): pass
+
+
+class CalledProcessError(SubprocessError):
     """This exception is raised when a process run by check_call() or
     check_output() returns a non-zero exit status.
     The exit status will be stored in the returncode attribute;
@@ -362,7 +367,7 @@
         return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode)
 
 
-class TimeoutExpired(Exception):
+class TimeoutExpired(SubprocessError):
     """This exception is raised when the timeout expires while waiting for a
     child process.
     """
diff --git a/Lib/test/test_dbm.py b/Lib/test/test_dbm.py
--- a/Lib/test/test_dbm.py
+++ b/Lib/test/test_dbm.py
@@ -70,6 +70,14 @@
         self.read_helper(f)
         f.close()
 
+    def test_anydbm_creation_n_file_exists_with_invalid_contents(self):
+        with open(_fname, "w") as w:
+            pass # create an empty file
+
+        f = dbm.open(_fname, 'n')
+        self.addCleanup(f.close)
+        self.assertEqual(len(f), 0)
+
     def test_anydbm_modification(self):
         self.init_db()
         f = dbm.open(_fname, 'c')
diff --git a/Lib/test/test_pep292.py b/Lib/test/test_pep292.py
--- a/Lib/test/test_pep292.py
+++ b/Lib/test/test_pep292.py
@@ -42,6 +42,19 @@
         s = Template('$who likes $$')
         eq(s.substitute(dict(who='tim', what='ham')), 'tim likes $')
 
+    def test_invalid(self):
+        class MyPattern(Template):
+            pattern = r"""
+            (?:
+            (?P<invalid>)            |
+            (?P<escaped>%(delim)s)   |
+            @(?P<named>%(id)s)       |
+            @{(?P<braced>%(id)s)}
+            )
+            """
+        s = MyPattern('$')
+        self.assertRaises(ValueError, s.substitute, dict())
+
     def test_percents(self):
         eq = self.assertEqual
         s = Template('%(foo)s $foo ${foo}')
diff --git a/Lib/test/test_readline.py b/Lib/test/test_readline.py
--- a/Lib/test/test_readline.py
+++ b/Lib/test/test_readline.py
@@ -12,6 +12,10 @@
 readline = import_module('readline')
 
 class TestHistoryManipulation (unittest.TestCase):
+
+    @unittest.skipIf(not hasattr(readline, 'clear_history'),
+                     "The history update test cannot be run because the "
+                     "clear_history method is not available.")
     def testHistoryUpdates(self):
         readline.clear_history()
 
diff --git a/Lib/test/test_string.py b/Lib/test/test_string.py
--- a/Lib/test/test_string.py
+++ b/Lib/test/test_string.py
@@ -112,6 +112,30 @@
         self.assertRaises(ValueError, fmt.format, "{0}", 10, 20, i=100)
         self.assertRaises(ValueError, fmt.format, "{i}", 10, 20, i=100)
 
+    def test_vformat_assert(self):
+        cls = string.Formatter()
+        kwargs = {
+            "i": 100
+        }
+        self.assertRaises(ValueError, cls._vformat,
+                cls.format, "{0}", kwargs, set(), -2)
+
+    def test_convert_field(self):
+        cls = string.Formatter()
+        self.assertEqual(cls.format("{0!s}", 'foo'), 'foo')
+        self.assertRaises(ValueError, cls.format, "{0!h}", 'foo')
+
+    def test_get_field(self):
+        cls = string.Formatter()
+        class MyClass:
+            name = 'lumberjack'
+        x = MyClass()
+        self.assertEqual(cls.format("{0.name}", x), 'lumberjack')
+
+        lookup = ["eggs", "and", "spam"]
+        self.assertEqual(cls.format("{0[2]}", lookup), 'spam')
+
+
 def test_main():
     support.run_unittest(ModuleTest)
 
diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py
--- a/Lib/test/test_urllib2.py
+++ b/Lib/test/test_urllib2.py
@@ -7,7 +7,9 @@
 import array
 
 import urllib.request
-from urllib.request import Request, OpenerDirector
+# The proxy bypass method imported below has logic specific to the OSX
+# proxy config data structure but is testable on all platforms.
+from urllib.request import Request, OpenerDirector, _proxy_bypass_macosx_sysconf
 
 # XXX
 # Request
@@ -1076,6 +1078,17 @@
         self.assertEqual(req.get_host(), "www.python.org")
         del os.environ['no_proxy']
 
+    def test_proxy_no_proxy_all(self):
+        os.environ['no_proxy'] = '*'
+        o = OpenerDirector()
+        ph = urllib.request.ProxyHandler(dict(http="proxy.example.com"))
+        o.add_handler(ph)
+        req = Request("http://www.python.org")
+        self.assertEqual(req.get_host(), "www.python.org")
+        r = o.open(req)
+        self.assertEqual(req.get_host(), "www.python.org")
+        del os.environ['no_proxy']
+
 
     def test_proxy_https(self):
         o = OpenerDirector()
@@ -1116,6 +1129,26 @@
         self.assertEqual(req.get_host(), "proxy.example.com:3128")
         self.assertEqual(req.get_header("Proxy-authorization"),"FooBar")
 
+    def test_osx_proxy_bypass(self):
+        bypass = {
+            'exclude_simple': False,
+            'exceptions': ['foo.bar', '*.bar.com', '127.0.0.1', '10.10',
+                           '10.0/16']
+        }
+        # Check hosts that should trigger the proxy bypass
+        for host in ('foo.bar', 'www.bar.com', '127.0.0.1', '10.10.0.1',
+                     '10.0.0.1'):
+            self.assertTrue(_proxy_bypass_macosx_sysconf(host, bypass),
+                            'expected bypass of %s to be True' % host)
+        # Check hosts that should not trigger the proxy bypass
+        for host in ('abc.foo.bar', 'bar.com', '127.0.0.2', '10.11.0.1', 'test'):
+            self.assertFalse(_proxy_bypass_macosx_sysconf(host, bypass),
+                             'expected bypass of %s to be False' % host)
+
+        # Check the exclude_simple flag
+        bypass = {'exclude_simple': True, 'exceptions': []}
+        self.assertTrue(_proxy_bypass_macosx_sysconf('test', bypass))
+
     def test_basic_auth(self, quote_char='"'):
         opener = OpenerDirector()
         password_manager = MockPasswordManager()
diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py
--- a/Lib/unittest/case.py
+++ b/Lib/unittest/case.py
@@ -469,7 +469,7 @@
                         warnings.warn("TestResult has no addExpectedFailure method, reporting as passes",
                                       RuntimeWarning)
                         result.addSuccess(self)
-
+            return result
         finally:
             result.stopTest(self)
             if orig_result is None:
diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py
--- a/Lib/unittest/test/test_case.py
+++ b/Lib/unittest/test/test_case.py
@@ -386,27 +386,62 @@
         self.assertIsInstance(Foo().id(), str)
 
 
-    # "If result is omitted or None, a temporary result object is created
-    # and used, but is not made available to the caller. As TestCase owns the
+    # "If result is omitted or None, a temporary result object is created,
+    # used, and is made available to the caller. As TestCase owns the
     # temporary result startTestRun and stopTestRun are called.
 
     def test_run__uses_defaultTestResult(self):
         events = []
+        defaultResult = LoggingResult(events)
 
         class Foo(unittest.TestCase):
             def test(self):
                 events.append('test')
 
             def defaultTestResult(self):
-                return LoggingResult(events)
+                return defaultResult
 
         # Make run() find a result object on its own
-        Foo('test').run()
+        result = Foo('test').run()
 
+        self.assertIs(result, defaultResult)
         expected = ['startTestRun', 'startTest', 'test', 'addSuccess',
             'stopTest', 'stopTestRun']
         self.assertEqual(events, expected)
 
+
+    # "The result object is returned to run's caller"
+    def test_run__returns_given_result(self):
+
+        class Foo(unittest.TestCase):
+            def test(self):
+                pass
+
+        result = unittest.TestResult()
+
+        retval = Foo('test').run(result)
+        self.assertIs(retval, result)
+
+
+    # "The same effect [as method run] may be had by simply calling the
+    # TestCase instance."
+    def test_call__invoking_an_instance_delegates_to_run(self):
+        resultIn = unittest.TestResult()
+        resultOut = unittest.TestResult()
+
+        class Foo(unittest.TestCase):
+            def test(self):
+                pass
+
+            def run(self, result):
+                self.assertIs(result, resultIn)
+                return resultOut
+
+        retval = Foo('test')(resultIn)
+
+        self.assertIs(retval, resultOut)
+
+
     def testShortDescriptionWithoutDocstring(self):
         self.assertIsNone(self.shortDescription())
 
diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py
--- a/Lib/urllib/request.py
+++ b/Lib/urllib/request.py
@@ -2208,68 +2208,76 @@
     return 0
 
 
+# This code tests an OSX specific data structure but is testable on all
+# platforms
+def _proxy_bypass_macosx_sysconf(host, proxy_settings):
+    """
+    Return True iff this host shouldn't be accessed using a proxy
+
+    This function uses the MacOSX framework SystemConfiguration
+    to fetch the proxy information.
+
+    proxy_settings come from _scproxy._get_proxy_settings or get mocked ie:
+    { 'exclude_simple': bool,
+      'exceptions': ['foo.bar', '*.bar.com', '127.0.0.1', '10.1', '10.0/16']
+    }
+    """
+    import re
+    import socket
+    from fnmatch import fnmatch
+
+    hostonly, port = splitport(host)
+
+    def ip2num(ipAddr):
+        parts = ipAddr.split('.')
+        parts = list(map(int, parts))
+        if len(parts) != 4:
+            parts = (parts + [0, 0, 0, 0])[:4]
+        return (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8) | parts[3]
+
+    # Check for simple host names:
+    if '.' not in host:
+        if proxy_settings['exclude_simple']:
+            return True
+
+    hostIP = None
+
+    for value in proxy_settings.get('exceptions', ()):
+        # Items in the list are strings like these: *.local, 169.254/16
+        if not value: continue
+
+        m = re.match(r"(\d+(?:\.\d+)*)(/\d+)?", value)
+        if m is not None:
+            if hostIP is None:
+                try:
+                    hostIP = socket.gethostbyname(hostonly)
+                    hostIP = ip2num(hostIP)
+                except socket.error:
+                    continue
+
+            base = ip2num(m.group(1))
+            mask = m.group(2)
+            if mask is None:
+                mask = 8 * (m.group(1).count('.') + 1)
+            else:
+                mask = int(mask[1:])
+            mask = 32 - mask
+
+            if (hostIP >> mask) == (base >> mask):
+                return True
+
+        elif fnmatch(host, value):
+            return True
+
+    return False
+
+
 if sys.platform == 'darwin':
     from _scproxy import _get_proxy_settings, _get_proxies
 
     def proxy_bypass_macosx_sysconf(host):
-        """
-        Return True iff this host shouldn't be accessed using a proxy
-
-        This function uses the MacOSX framework SystemConfiguration
-        to fetch the proxy information.
-        """
-        import re
-        import socket
-        from fnmatch import fnmatch
-
-        hostonly, port = splitport(host)
-
-        def ip2num(ipAddr):
-            parts = ipAddr.split('.')
-            parts = list(map(int, parts))
-            if len(parts) != 4:
-                parts = (parts + [0, 0, 0, 0])[:4]
-            return (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8) | parts[3]
-
         proxy_settings = _get_proxy_settings()
-
-        # Check for simple host names:
-        if '.' not in host:
-            if proxy_settings['exclude_simple']:
-                return True
-
-        hostIP = None
-
-        for value in proxy_settings.get('exceptions', ()):
-            # Items in the list are strings like these: *.local, 169.254/16
-            if not value: continue
-
-            m = re.match(r"(\d+(?:\.\d+)*)(/\d+)?", value)
-            if m is not None:
-                if hostIP is None:
-                    try:
-                        hostIP = socket.gethostbyname(hostonly)
-                        hostIP = ip2num(hostIP)
-                    except socket.error:
-                        continue
-
-                base = ip2num(m.group(1))
-                mask = m.group(2)
-                if mask is None:
-                    mask = 8 * (m.group(1).count('.') + 1)
-
-                else:
-                    mask = int(mask[1:])
-                    mask = 32 - mask
-
-                if (hostIP >> mask) == (base >> mask):
-                    return True
-
-            elif fnmatch(host, value):
-                return True
-
-        return False
-
+        return _proxy_bypass_macosx_sysconf(host, proxy_settings)
 
     def getproxies_macosx_sysconf():
         """Return a dictionary of scheme -> proxy server URL mappings.
diff --git a/Misc/ACKS b/Misc/ACKS
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -32,6 +32,7 @@
 Ross Andrus
 Jon Anglin
 Éric Araujo
+Alicia Arlen
 Jason Asbahr
 David Ascher
 Chris AtLee
@@ -171,6 +172,7 @@
 Jeffery Collins
 Robert Collins
 Paul Colomiets
+Denver Coneybeare
 Geremy Condra
 Juan José Conti
 Matt Conway
@@ -350,6 +352,7 @@
 Derek Harland
 Jason Harper
 Brian Harring
+Jonathan Hartley
 Larry Hastings
 Shane Hathaway
 Rycharde Hawkes
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -68,6 +68,16 @@
 Library
 -------
 
+- Issue #11407: `TestCase.run` returns the result object used or created.
+  Contributed by Janathan Hartley.
+
+- Issue #11500: Fixed a bug in the os x proxy bypass code for fully qualified 
+  IP addresses in the proxy exception list. 
+
+- Issue #11491: dbm.error is no longer raised when dbm.open is called with
+  the "n" as the flag argument and the file exists. The behavior matches
+  the documentation and general logic.
+
 - Issue #1162477: Postel Principal adjustment to email date parsing: handle the
   fact that some non-compliant MUAs use '.' instead of ':' in time specs.
 
@@ -193,6 +203,8 @@
 Tests
 -----
 
+- Issue #11505: improves test coverage of string.py
+
 - Issue #11490: test_subprocess:test_leaking_fds_on_error no longer gives a
   false positive if the last directory in the path is inaccessible.
 

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list