From eca20b611433fac88057da092efc0b6d6d2a7fb3 Mon Sep 17 00:00:00 2001 From: Alexandre Vassalotti Date: Fri, 16 May 2008 02:54:33 +0000 Subject: Merged revisions 63119-63128,63130-63131,63133,63135-63144,63146-63148,63151-63152,63155-63165,63167-63176,63181-63186,63188-63189 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r63119 | benjamin.peterson | 2008-05-11 20:41:23 -0400 (Sun, 11 May 2008) | 2 lines #2196 hasattr now allows SystemExit and KeyboardInterrupt to propagate ........ r63122 | benjamin.peterson | 2008-05-11 20:46:49 -0400 (Sun, 11 May 2008) | 2 lines make message slightly more informative, so there's no chance of misunderstanding it ........ r63158 | ronald.oussoren | 2008-05-12 07:24:33 -0400 (Mon, 12 May 2008) | 5 lines Remove references to platform 'mac' The 'mac' platform (that is, os.name == 'mac') was used for the MacOS 9 port, which is no longer supported (as of Python 2.4 IIRC). ........ r63159 | ronald.oussoren | 2008-05-12 07:31:05 -0400 (Mon, 12 May 2008) | 8 lines MacOSX: remove dependency on Carbon package for urllib This patch removes the dependency on the Carbon package from urllib. The mac-specific code for getting proxy configuration is now writting in Python using ctypes and uses the SystemConfiguration framework instead of InternetConfig. Also provides a mac-specific implementation of proxy_bypass. ........ r63162 | eric.smith | 2008-05-12 10:00:01 -0400 (Mon, 12 May 2008) | 1 line Added 'n' presentation type for integers. ........ r63164 | georg.brandl | 2008-05-12 12:26:52 -0400 (Mon, 12 May 2008) | 2 lines #1713041: fix pprint's handling of maximum depth. ........ r63170 | georg.brandl | 2008-05-12 12:53:42 -0400 (Mon, 12 May 2008) | 2 lines Fix parameter name for enumerate(). ........ r63173 | georg.brandl | 2008-05-12 13:01:58 -0400 (Mon, 12 May 2008) | 2 lines #2766: remove code without effect. ........ r63174 | georg.brandl | 2008-05-12 13:04:10 -0400 (Mon, 12 May 2008) | 3 lines #2767: don't clear globs in run() call, since they could be needed in tearDown, which clears them at the end. ........ r63175 | georg.brandl | 2008-05-12 13:14:51 -0400 (Mon, 12 May 2008) | 2 lines #1760: try-except-finally is one statement since PEP 341. ........ r63186 | amaury.forgeotdarc | 2008-05-12 17:30:24 -0400 (Mon, 12 May 2008) | 2 lines Sync code with documentation, and remove Win95 support in winsound module. ........ r63189 | amaury.forgeotdarc | 2008-05-12 18:21:39 -0400 (Mon, 12 May 2008) | 3 lines Adapt test_pyclbr to the new version of urllib.py: The new mac-specific functions must be ignored. ........ --- Doc/library/functions.rst | 17 +-- Doc/library/pprint.rst | 5 +- Doc/reference/executionmodel.rst | 8 +- Doc/whatsnew/2.6.rst | 6 +- Lib/doctest.py | 4 +- Lib/os.py | 20 +--- Lib/pprint.py | 8 +- Lib/tempfile.py | 14 +-- Lib/test/test_builtin.py | 10 ++ Lib/test/test_pprint.py | 15 +++ Lib/test/test_pyclbr.py | 6 +- Lib/urllib.py | 218 ++++++++++++++++++++++++++++++++++----- Makefile.pre.in | 2 +- Misc/NEWS | 7 ++ PC/winsound.c | 78 ++------------ Python/bltinmodule.c | 10 +- 16 files changed, 277 insertions(+), 151 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 9ccc59c..582abbf 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -325,14 +325,15 @@ are always available. They are listed here in alphabetical order. < abs(b)``. -.. function:: enumerate(iterable) - - Return an enumerate object. *iterable* must be a sequence, an :term:`iterator`, or some - other object which supports iteration. The :meth:`__next__` method of the - iterator returned by :func:`enumerate` returns a tuple containing a count (from - zero) and the corresponding value obtained from iterating over *iterable*. - :func:`enumerate` is useful for obtaining an indexed series: ``(0, seq[0])``, - ``(1, seq[1])``, ``(2, seq[2])``, .... For example: +.. function:: enumerate(sequence) + + Return an enumerate object. *sequence* must be a sequence, an + :term:`iterator`, or some other object which supports iteration. The + :meth:`__next__` method of the iterator returned by :func:`enumerate` returns a + tuple containing a count (from zero) and the corresponding value obtained + from iterating over *iterable*. :func:`enumerate` is useful for obtaining an + indexed series: ``(0, seq[0])``, ``(1, seq[1])``, ``(2, seq[2])``, .... For + example: >>> for i, season in enumerate(['Spring', 'Summer', 'Fall', 'Winter')]: ... print(i, season) diff --git a/Doc/library/pprint.rst b/Doc/library/pprint.rst index 8c28879..940e4c4 100644 --- a/Doc/library/pprint.rst +++ b/Doc/library/pprint.rst @@ -60,8 +60,7 @@ The :mod:`pprint` module defines one class: ... ('parrot', ('fresh fruit',)))))))) >>> pp = pprint.PrettyPrinter(depth=6) >>> pp.pprint(tup) - ('spam', - ('eggs', ('lumberjack', ('knights', ('ni', ('dead', ('parrot', (...,)))))))) + ('spam', ('eggs', ('lumberjack', ('knights', ('ni', ('dead', (...))))))) The :class:`PrettyPrinter` class supports several derivative functions: @@ -208,7 +207,7 @@ This example demonstrates several uses of the :func:`pprint` function and its pa ['cccccccccccccccccccc', 'dddddddddddddddddddd']] >>> pprint.pprint(stuff, depth=3) ['aaaaaaaaaa', - ('spam', ('eggs', ('lumberjack', (...)))), + ('spam', ('eggs', (...))), ['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'], ['cccccccccccccccccccc', 'dddddddddddddddddddd']] >>> pprint.pprint(stuff, width=60) diff --git a/Doc/reference/executionmodel.rst b/Doc/reference/executionmodel.rst index 43515d9..fefc146 100644 --- a/Doc/reference/executionmodel.rst +++ b/Doc/reference/executionmodel.rst @@ -198,10 +198,10 @@ the code block where the error occurred. The Python interpreter raises an exception when it detects a run-time error (such as division by zero). A Python program can also explicitly raise an exception with the :keyword:`raise` statement. Exception handlers are specified -with the :keyword:`try` ... :keyword:`except` statement. The :keyword:`try` ... -:keyword:`finally` statement specifies cleanup code which does not handle the -exception, but is executed whether an exception occurred or not in the preceding -code. +with the :keyword:`try` ... :keyword:`except` statement. The :keyword:`finally` +clause of such a statement can be used to specify cleanup code which does not +handle the exception, but is executed whether an exception occurred or not in +the preceding code. .. index:: single: termination model diff --git a/Doc/whatsnew/2.6.rst b/Doc/whatsnew/2.6.rst index 9708c67..c39c80a 100644 --- a/Doc/whatsnew/2.6.rst +++ b/Doc/whatsnew/2.6.rst @@ -627,9 +627,9 @@ docs), but here's a sample:: 'g' - General format. This prints the number as a fixed-point number, unless the number is too large, in which case it switches to 'e' exponent notation. - 'n' - Number. This is the same as 'g', except that it uses the - current locale setting to insert the appropriate - number separator characters. + 'n' - Number. This is the same as 'g' (for floats) or 'd' (for + integers), except that it uses the current locale setting to + insert the appropriate number separator characters. '%' - Percentage. Multiplies the number by 100 and displays in fixed ('f') format, followed by a percent sign. diff --git a/Lib/doctest.py b/Lib/doctest.py index 0322612..dad8333 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -2137,7 +2137,7 @@ class DocTestCase(unittest.TestCase): self.setUp() runner = DebugRunner(optionflags=self._dt_optionflags, checker=self._dt_checker, verbose=False) - runner.run(self._dt_test) + runner.run(self._dt_test, clear_globs=False) self.tearDown() def id(self): @@ -2194,8 +2194,6 @@ def DocTestSuite(module=None, globs=None, extraglobs=None, test_finder=None, module = _normalize_module(module) tests = test_finder.find(module, globs=globs, extraglobs=extraglobs) - if globs is None: - globs = module.__dict__ if not tests: # Why do we want to do this? Because it reveals a bug that might # otherwise be hidden. diff --git a/Lib/os.py b/Lib/os.py index b5ade28..a04aa7f 100644 --- a/Lib/os.py +++ b/Lib/os.py @@ -1,9 +1,9 @@ r"""OS routines for Mac, NT, or Posix depending on what system we're on. This exports: - - all functions from posix, nt, os2, mac, or ce, e.g. unlink, stat, etc. - - os.path is one of the modules posixpath, ntpath, or macpath - - os.name is 'posix', 'nt', 'os2', 'mac' or 'ce' + - all functions from posix, nt, os2, or ce, e.g. unlink, stat, etc. + - os.path is either posixpath or ntpath + - os.name is either 'posix', 'nt', 'os2' or 'ce'. - os.curdir is a string representing the current directory ('.' or ':') - os.pardir is a string representing the parent directory ('..' or '::') - os.sep is the (or a most common) pathname separator ('/' or ':' or '\\') @@ -83,20 +83,6 @@ elif 'os2' in _names: __all__.extend(_get_exports_list(os2)) del os2 -elif 'mac' in _names: - name = 'mac' - linesep = '\r' - from mac import * - try: - from mac import _exit - except ImportError: - pass - import macpath as path - - import mac - __all__.extend(_get_exports_list(mac)) - del mac - elif 'ce' in _names: name = 'ce' linesep = '\r\n' diff --git a/Lib/pprint.py b/Lib/pprint.py index 43b6b0d..8bbc845 100644 --- a/Lib/pprint.py +++ b/Lib/pprint.py @@ -131,6 +131,10 @@ class PrettyPrinter: sepLines = _len(rep) > (self._width - 1 - indent - allowance) write = stream.write + if self._depth and level > self._depth: + write(rep) + return + if sepLines: r = getattr(typ, "__repr__", None) if issubclass(typ, dict) and r is dict.__repr__: @@ -252,7 +256,7 @@ def _safe_repr(object, context, maxlevels, level): if not object: return "{}", True, False objid = _id(object) - if maxlevels and level > maxlevels: + if maxlevels and level >= maxlevels: return "{...}", False, objid in context if objid in context: return _recursion(object), False, True @@ -294,7 +298,7 @@ def _safe_repr(object, context, maxlevels, level): return "()", True, False format = "(%s)" objid = _id(object) - if maxlevels and level > maxlevels: + if maxlevels and level >= maxlevels: return format % "...", False, objid in context if objid in context: return _recursion(object), False, True diff --git a/Lib/tempfile.py b/Lib/tempfile.py index 0e2a460..1041c14 100644 --- a/Lib/tempfile.py +++ b/Lib/tempfile.py @@ -34,10 +34,6 @@ import os as _os import errno as _errno from random import Random as _Random -if _os.name == 'mac': - import Carbon.Folder as _Folder - import Carbon.Folders as _Folders - try: import fcntl as _fcntl except ImportError: @@ -149,15 +145,7 @@ def _candidate_tempdir_list(): if dirname: dirlist.append(dirname) # Failing that, try OS-specific locations. - if _os.name == 'mac': - try: - fsr = _Folder.FSFindFolder(_Folders.kOnSystemDisk, - _Folders.kTemporaryFolderType, 1) - dirname = fsr.as_pathname() - dirlist.append(dirname) - except _Folder.error: - pass - elif _os.name == 'nt': + if _os.name == 'nt': dirlist.extend([ r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ]) else: dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ]) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 52b337c..a74cc84 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -499,6 +499,16 @@ class BuiltinTest(unittest.TestCase): self.assertRaises(TypeError, hasattr) self.assertEqual(False, hasattr(sys, chr(sys.maxunicode))) + # Check that hasattr allows SystemExit and KeyboardInterrupts by + class A: + def __getattr__(self, what): + raise KeyboardInterrupt + self.assertRaises(KeyboardInterrupt, hasattr, A(), "b") + class B: + def __getattr__(self, what): + raise SystemExit + self.assertRaises(SystemExit, hasattr, B(), "b") + def test_hash(self): hash(None) self.assertEqual(hash(1), hash(1)) diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py index a0cd01a..ed35287 100644 --- a/Lib/test/test_pprint.py +++ b/Lib/test/test_pprint.py @@ -381,6 +381,21 @@ class QueryTestCase(unittest.TestCase): cubo = test.test_set.linegraph(cube) self.assertEqual(pprint.pformat(cubo), cubo_repr_tgt) + def test_depth(self): + nested_tuple = (1, (2, (3, (4, (5, 6))))) + nested_dict = {1: {2: {3: {4: {5: {6: 6}}}}}} + nested_list = [1, [2, [3, [4, [5, [6, []]]]]]] + self.assertEqual(pprint.pformat(nested_tuple), repr(nested_tuple)) + self.assertEqual(pprint.pformat(nested_dict), repr(nested_dict)) + self.assertEqual(pprint.pformat(nested_list), repr(nested_list)) + + lv1_tuple = '(1, (...))' + lv1_dict = '{1: {...}}' + lv1_list = '[1, [...]]' + self.assertEqual(pprint.pformat(nested_tuple, depth=1), lv1_tuple) + self.assertEqual(pprint.pformat(nested_dict, depth=1), lv1_dict) + self.assertEqual(pprint.pformat(nested_list, depth=1), lv1_list) + class DottedPrettyPrinter(pprint.PrettyPrinter): diff --git a/Lib/test/test_pyclbr.py b/Lib/test/test_pyclbr.py index 64c8f18..57ede89 100644 --- a/Lib/test/test_pyclbr.py +++ b/Lib/test/test_pyclbr.py @@ -156,10 +156,14 @@ class PyclbrTest(TestCase): # These were once about the 10 longest modules cm('random', ignore=('Random',)) # from _random import Random as CoreGenerator cm('cgi', ignore=('log',)) # set with = in module - cm('urllib', ignore=('getproxies_registry', + cm('urllib', ignore=('_CFNumberToInt32', + '_CStringFromCFString', + 'getproxies_registry', 'proxy_bypass_registry', + 'proxy_bypass_macosx_sysconf', 'open_https', '_https_connection', + 'getproxies_macosx_sysconf', 'getproxies_internetconfig',)) # not on all platforms cm('pickle') cm('aifc', ignore=('openfp',)) # set with = in module diff --git a/Lib/urllib.py b/Lib/urllib.py index 0b66e59..f610e4b 100644 --- a/Lib/urllib.py +++ b/Lib/urllib.py @@ -1271,44 +1271,214 @@ def proxy_bypass_environment(host): if sys.platform == 'darwin': - def getproxies_internetconfig(): - """Return a dictionary of scheme -> proxy server URL mappings. - - By convention the mac uses Internet Config to store - proxies. An HTTP proxy, for instance, is stored under - the HttpProxy key. + def _CStringFromCFString(sc, value): + from ctypes import create_string_buffer + length = sc.CFStringGetLength(value) + 1 + buff = create_string_buffer(length) + sc.CFStringGetCString(value, buff, length, 0) + return buff.value + + def _CFNumberToInt32(sc, cfnum): + from ctypes import byref, c_int + val = c_int() + kCFNumberSInt32Type = 3 + sc.CFNumberGetValue(cfnum, kCFNumberSInt32Type, byref(val)) + return val.value + + + 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. """ - try: - import ic - except ImportError: - return {} + from ctypes import cdll + from ctypes.util import find_library + import re + import socket + from fnmatch import fnmatch + + def ip2num(ipAddr): + parts = ipAddr.split('.') + parts = 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] + + sc = cdll.LoadLibrary(find_library("SystemConfiguration")) + + hostIP = None + + if not sc: + return False + + kSCPropNetProxiesExceptionsList = sc.CFStringCreateWithCString(0, "ExceptionsList", 0) + kSCPropNetProxiesExcludeSimpleHostnames = sc.CFStringCreateWithCString(0, + "ExcludeSimpleHostnames", 0) + + + proxyDict = sc.SCDynamicStoreCopyProxies(None) try: - config = ic.IC() - except ic.error: + # Check for simple host names: + if '.' not in host: + exclude_simple = sc.CFDictionaryGetValue(proxyDict, + kSCPropNetProxiesExcludeSimpleHostnames) + if exclude_simple and _CFNumberToInt32(sc, exclude_simple): + return True + + + # Check the exceptions list: + exceptions = sc.CFDictionaryGetValue(proxyDict, kSCPropNetProxiesExceptionsList) + if exceptions: + # Items in the list are strings like these: *.local, 169.254/16 + for index in xrange(sc.CFArrayGetCount(exceptions)): + value = sc.CFArrayGetValueAtIndex(exceptions, index) + if not value: continue + value = _CStringFromCFString(sc, value) + + m = re.match(r"(\d+(?:\.\d+)*)(/\d+)?", value) + if m is not None: + if hostIP is None: + hostIP = socket.gethostbyname(host) + hostIP = ip2num(hostIP) + + base = ip2num(m.group(1)) + mask = int(m.group(2)[1:]) + mask = 32 - mask + + if (hostIP >> mask) == (base >> mask): + return True + + elif fnmatch(host, value): + return True + + return False + + finally: + sc.CFRelease(kSCPropNetProxiesExceptionsList) + sc.CFRelease(kSCPropNetProxiesExcludeSimpleHostnames) + + + + def getproxies_macosx_sysconf(): + """Return a dictionary of scheme -> proxy server URL mappings. + + This function uses the MacOSX framework SystemConfiguration + to fetch the proxy information. + """ + from ctypes import cdll + from ctypes.util import find_library + + sc = cdll.LoadLibrary(find_library("SystemConfiguration")) + + if not sc: return {} + + + kSCPropNetProxiesHTTPEnable = sc.CFStringCreateWithCString(0, "HTTPEnable", 0) + kSCPropNetProxiesHTTPProxy = sc.CFStringCreateWithCString(0, "HTTPProxy", 0) + kSCPropNetProxiesHTTPPort = sc.CFStringCreateWithCString(0, "HTTPPort", 0) + + kSCPropNetProxiesHTTPSEnable = sc.CFStringCreateWithCString(0, "HTTPSEnable", 0) + kSCPropNetProxiesHTTPSProxy = sc.CFStringCreateWithCString(0, "HTTPSProxy", 0) + kSCPropNetProxiesHTTPSPort = sc.CFStringCreateWithCString(0, "HTTPSPort", 0) + + kSCPropNetProxiesFTPEnable = sc.CFStringCreateWithCString(0, "FTPEnable", 0) + kSCPropNetProxiesFTPPassive = sc.CFStringCreateWithCString(0, "FTPPassive", 0) + kSCPropNetProxiesFTPPort = sc.CFStringCreateWithCString(0, "FTPPort", 0) + kSCPropNetProxiesFTPProxy = sc.CFStringCreateWithCString(0, "FTPProxy", 0) + + kSCPropNetProxiesGopherEnable = sc.CFStringCreateWithCString(0, "GopherEnable", 0) + kSCPropNetProxiesGopherPort = sc.CFStringCreateWithCString(0, "GopherPort", 0) + kSCPropNetProxiesGopherProxy = sc.CFStringCreateWithCString(0, "GopherProxy", 0) + proxies = {} - # HTTP: - if 'UseHTTPProxy' in config and config['UseHTTPProxy']: - try: - value = config['HTTPProxyHost'] - except ic.error: - pass - else: - proxies['http'] = 'http://%s' % value - # FTP: XXX To be done. - # Gopher: XXX To be done. + proxyDict = sc.SCDynamicStoreCopyProxies(None) + + try: + # HTTP: + enabled = sc.CFDictionaryGetValue(proxyDict, kSCPropNetProxiesHTTPEnable) + if enabled and _CFNumberToInt32(sc, enabled): + proxy = sc.CFDictionaryGetValue(proxyDict, kSCPropNetProxiesHTTPProxy) + port = sc.CFDictionaryGetValue(proxyDict, kSCPropNetProxiesHTTPPort) + + if proxy: + proxy = _CStringFromCFString(sc, proxy) + if port: + port = _CFNumberToInt32(sc, port) + proxies["http"] = "http://%s:%i" % (proxy, port) + else: + proxies["http"] = "http://%s" % (proxy, ) + + # HTTPS: + enabled = sc.CFDictionaryGetValue(proxyDict, kSCPropNetProxiesHTTPSEnable) + if enabled and _CFNumberToInt32(sc, enabled): + proxy = sc.CFDictionaryGetValue(proxyDict, kSCPropNetProxiesHTTPSProxy) + port = sc.CFDictionaryGetValue(proxyDict, kSCPropNetProxiesHTTPSPort) + + if proxy: + proxy = _CStringFromCFString(sc, proxy) + if port: + port = _CFNumberToInt32(sc, port) + proxies["https"] = "http://%s:%i" % (proxy, port) + else: + proxies["https"] = "http://%s" % (proxy, ) + + # FTP: + enabled = sc.CFDictionaryGetValue(proxyDict, kSCPropNetProxiesFTPEnable) + if enabled and _CFNumberToInt32(sc, enabled): + proxy = sc.CFDictionaryGetValue(proxyDict, kSCPropNetProxiesFTPProxy) + port = sc.CFDictionaryGetValue(proxyDict, kSCPropNetProxiesFTPPort) + + if proxy: + proxy = _CStringFromCFString(sc, proxy) + if port: + port = _CFNumberToInt32(sc, port) + proxies["ftp"] = "http://%s:%i" % (proxy, port) + else: + proxies["ftp"] = "http://%s" % (proxy, ) + + # Gopher: + enabled = sc.CFDictionaryGetValue(proxyDict, kSCPropNetProxiesGopherEnable) + if enabled and _CFNumberToInt32(sc, enabled): + proxy = sc.CFDictionaryGetValue(proxyDict, kSCPropNetProxiesGopherProxy) + port = sc.CFDictionaryGetValue(proxyDict, kSCPropNetProxiesGopherPort) + + if proxy: + proxy = _CStringFromCFString(sc, proxy) + if port: + port = _CFNumberToInt32(sc, port) + proxies["gopher"] = "http://%s:%i" % (proxy, port) + else: + proxies["gopher"] = "http://%s" % (proxy, ) + finally: + sc.CFRelease(proxyDict) + + sc.CFRelease(kSCPropNetProxiesHTTPEnable) + sc.CFRelease(kSCPropNetProxiesHTTPProxy) + sc.CFRelease(kSCPropNetProxiesHTTPPort) + sc.CFRelease(kSCPropNetProxiesFTPEnable) + sc.CFRelease(kSCPropNetProxiesFTPPassive) + sc.CFRelease(kSCPropNetProxiesFTPPort) + sc.CFRelease(kSCPropNetProxiesFTPProxy) + sc.CFRelease(kSCPropNetProxiesGopherEnable) + sc.CFRelease(kSCPropNetProxiesGopherPort) + sc.CFRelease(kSCPropNetProxiesGopherProxy) + return proxies + + def proxy_bypass(host): if getproxies_environment(): return proxy_bypass_environment(host) else: - return 0 + return proxy_bypass_macosx_sysconf(host) def getproxies(): - return getproxies_environment() or getproxies_internetconfig() + return getproxies_environment() or getproxies_macosx_sysconf() elif os.name == 'nt': def getproxies_registry(): diff --git a/Makefile.pre.in b/Makefile.pre.in index 9131a8d..b82bd5e 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -475,7 +475,7 @@ Modules/Setup: $(srcdir)/Modules/Setup.dist echo "Modules/Setup.dist is newer than Modules/Setup;"; \ echo "check to make sure you have all the updates you"; \ echo "need in your Modules/Setup file."; \ - echo "Usually, copying Setup.dist to Setup will work."; \ + echo "Usually, copying Modules/Setup.dist to Modules/Setup will work."; \ echo "-----------------------------------------------"; \ fi diff --git a/Misc/NEWS b/Misc/NEWS index 851974b..2dbd2fd 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -22,14 +22,21 @@ Core and Builtins - The --with-toolbox-glue option (and the associated pymactoolbox.h) have been removed. +- Issue #2196: hasattr now lets exceptions which do not inherit Exception + (KeyboardInterrupt, and SystemExit) propagate instead of ignoring them + Extension Modules ----------------- +- Support for Windows9x has been removed from the winsound module. + Library ------- - The statvfs module has been removed. +- #1713041: fix pprint's handling of maximum depth. + - #2250: Exceptions raised during evaluation of names in rlcompleter's ``Completer.complete()`` method are now caught and ignored. diff --git a/PC/winsound.c b/PC/winsound.c index 9fc7f6f..62e87ae 100644 --- a/PC/winsound.c +++ b/PC/winsound.c @@ -38,9 +38,6 @@ #include #include #include -#ifdef HAVE_CONIO_H -#include /* port functions on Win9x */ -#endif PyDoc_STRVAR(sound_playsound_doc, "PlaySound(sound, flags) - a wrapper around the Windows PlaySound API\n" @@ -53,10 +50,7 @@ PyDoc_STRVAR(sound_beep_doc, "\n" "The frequency argument specifies frequency, in hertz, of the sound.\n" "This parameter must be in the range 37 through 32,767.\n" -"The duration argument specifies the number of milliseconds.\n" -"On WinNT and 2000, the platform Beep API is used directly. Else funky\n" -"code doing direct port manipulation is used; it's unknown whether that\n" -"will work on all systems."); +"The duration argument specifies the number of milliseconds.\n"); PyDoc_STRVAR(sound_msgbeep_doc, "MessageBeep(x) - call Windows MessageBeep(x). x defaults to MB_OK."); @@ -107,14 +101,12 @@ sound_playsound(PyObject *s, PyObject *args) return Py_None; } -enum OSType {Win9X, WinNT2000}; -static enum OSType whichOS; /* set by module init */ - static PyObject * sound_beep(PyObject *self, PyObject *args) { int freq; int dur; + BOOL ok; if (!PyArg_ParseTuple(args, "ii:Beep", &freq, &dur)) return NULL; @@ -125,57 +117,14 @@ sound_beep(PyObject *self, PyObject *args) return NULL; } - /* On NT and 2000, the SDK Beep() function does the whole job. - * But while Beep() exists before NT, it ignores its arguments and - * plays the system default sound. Sheesh ... - * The Win9X code is mondo bizarre. I (Tim) pieced it together from - * crap all over the web. The original IBM PC used some particular - * pieces of hardware (Intel 8255 and 8254 chips) hardwired to - * particular port addresses and running at particular clock speeds, - * and the poor sound card folks have been forced to emulate that in - * all particulars ever since. But NT and 2000 don't support port - * manipulation. Don't know about WinME; guessing it's like 98. - */ - - if (whichOS == WinNT2000) { - BOOL ok; - Py_BEGIN_ALLOW_THREADS - ok = Beep(freq, dur); - Py_END_ALLOW_THREADS - if (!ok) { - PyErr_SetString(PyExc_RuntimeError,"Failed to beep"); - return NULL; - } - } -#if defined(_M_IX86) && defined(HAVE_CONIO_H) - else if (whichOS == Win9X) { - int speaker_state; - /* Force timer into oscillator mode via timer control port. */ - _outp(0x43, 0xb6); - /* Compute ratio of ancient hardcoded timer frequency to - * frequency we want. Then feed that ratio (lowest byte - * first) into timer data port. - */ - freq = 1193180 / freq; - _outp(0x42, freq & 0xff); - _outp(0x42, (freq >> 8) & 0xff); - /* Get speaker control state. */ - speaker_state = _inp(0x61); - /* Turn the speaker on (bit 1) - * and drive speaker from timer (bit 0). - */ - _outp(0x61, speaker_state | 0x3); - /* Let it blast in peace for the duration. */ - Py_BEGIN_ALLOW_THREADS - Sleep(dur); - Py_END_ALLOW_THREADS - /* Restore speaker control to original state. */ - _outp(0x61, speaker_state); - } -#endif /* _M_IX86 && HAVE_CONIO_H */ - else { - assert(!"winsound's whichOS has insane value"); + Py_BEGIN_ALLOW_THREADS + ok = Beep(freq, dur); + Py_END_ALLOW_THREADS + if (!ok) { + PyErr_SetString(PyExc_RuntimeError,"Failed to beep"); + return NULL; } + Py_INCREF(Py_None); return Py_None; } @@ -217,8 +166,6 @@ add_define(PyObject *dict, const char *key, long value) PyMODINIT_FUNC initwinsound(void) { - OSVERSIONINFO version; - PyObject *dict; PyObject *module = Py_InitModule3("winsound", sound_methods, @@ -243,11 +190,4 @@ initwinsound(void) ADD_DEFINE(MB_ICONEXCLAMATION); ADD_DEFINE(MB_ICONHAND); ADD_DEFINE(MB_ICONQUESTION); - - version.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&version); - whichOS = Win9X; - if (version.dwPlatformId != VER_PLATFORM_WIN32s && - version.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) - whichOS = WinNT2000; } diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 585059f..de3f0f4 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -861,9 +861,13 @@ builtin_hasattr(PyObject *self, PyObject *args) } v = PyObject_GetAttr(v, name); if (v == NULL) { - PyErr_Clear(); - Py_INCREF(Py_False); - return Py_False; + if (!PyErr_ExceptionMatches(PyExc_Exception)) + return NULL; + else { + PyErr_Clear(); + Py_INCREF(Py_False); + return Py_False; + } } Py_DECREF(v); Py_INCREF(Py_True); -- cgit v0.12