From 9b513bf6ca704f465ec4030dc572bc5d627bafac Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Mon, 28 Oct 2013 08:06:50 +0100 Subject: [PATCH 01/11] Add news entry for 3.3.3 final. --- Misc/NEWS | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS index fe562528932..9872b309e14 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,11 +2,20 @@ Python News +++++++++++ +What's New in Python 3.3.3? +=========================== + +*Release date: XX-Nov-2013* + +Tests +----- + +- Issue #18964: Fix test_tcl when run with Tcl/Tk versions < 8.5. + + What's New in Python 3.3.3 release candidate 1? =============================================== -.. *Not yet released, see sections below for changes released in 3.3.2* - *Release date: 27-Oct-2013* Core and Builtins From 85b8be1ac88de7b2bbe06c47e45b9c0087e8037d Mon Sep 17 00:00:00 2001 From: Ned Deily Date: Tue, 5 Nov 2013 02:44:17 -0800 Subject: [PATCH 02/11] Issue #15663: Revert OS X installer built-in Tcl/Tk support for 3.3.3. Some third-party projects, such as matplotlib and PIL/Pillow, depended on being able to build with Tcl and Tk frameworks in /Library/Frameworks. They were unable to build with the built-in Tcl/Tk and/or execute correctly. --- Mac/BuildScript/README.txt | 29 +-------------------------- Mac/BuildScript/build-installer.py | 10 ++++----- Mac/BuildScript/resources/ReadMe.txt | 23 +++++++-------------- Mac/BuildScript/resources/Welcome.rtf | 10 ++++++--- Misc/NEWS | 8 ++++++++ 5 files changed, 28 insertions(+), 52 deletions(-) diff --git a/Mac/BuildScript/README.txt b/Mac/BuildScript/README.txt index 38470c5bb92..56c769af7bd 100644 --- a/Mac/BuildScript/README.txt +++ b/Mac/BuildScript/README.txt @@ -57,40 +57,13 @@ for each release. * NCurses 5.9 (http://bugs.python.org/issue15037) * SQLite 3.7.13 - * Tcl 8.5.15 - * Tk 8.5.15 * XZ 5.0.3 - uses system-supplied versions of third-party libraries * readline module links with Apple BSD editline (libedit) - - requires ActiveState Tcl/Tk 8.5.14 (or later) to be installed for building - - * Beginning with Python 3.3.3, this installer now includes its own - builtin copy of Tcl and Tk 8.5.15 libraries and thus is no longer - dependent on the buggy releases of Aqua Cocoa Tk 8.5 shipped with - OS X 10.6 or on installing a newer third-party version of Tcl/Tk - in /Library/Frameworks, such as from ActiveState. If it is - necessary to fallback to using a third-party Tcl/Tk because of - a problem with the builtin Tcl/Tk, there is a backup version of - the _tkinter extension included which will dynamically link to - Tcl and Tk frameworks in /Library/Frameworks as in previous releases. - To enable (for all users of this Python 3.3):: - - sudo bash - cd /Library/Frameworks/Python.framework/Versions/3.3 - cd ./lib/python3.3 - cp -p ./lib-tkinter/library/_tkinter.so ./lib-dynload - exit - - To restore using Python's builtin versions of Tcl and Tk:: - - sudo bash - cd /Library/Frameworks/Python.framework/Versions/3.3 - cd ./lib/python3.3 - cp -p ./lib-tkinter/builtin/_tkinter.so ./lib-dynload - exit + - requires ActiveState Tcl/Tk 8.5.9 (or later) to be installed for building - recommended build environment: diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 0859b3aa068..fd5d5c36a77 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -193,7 +193,7 @@ def library_recipes(): LT_10_5 = bool(DEPTARGET < '10.5') - if DEPTARGET > '10.5': + if (DEPTARGET > '10.5') and (getVersionTuple() >= (3, 4)): result.extend([ dict( name="Tcl 8.5.15", @@ -571,7 +571,7 @@ def checkEnvironment(): # - the traditional version (renamed to _tkinter_library.so) linked # with /Library/Frameworks/{Tcl,Tk}.framework # - the default version linked with our builtin copies of Tcl and Tk - if DEPTARGET > '10.5': + if (DEPTARGET > '10.5') and (getVersionTuple() >= (3, 4)): EXPECTED_SHARED_LIBS['_tkinter_library.so'] = \ EXPECTED_SHARED_LIBS['_tkinter.so'] EXPECTED_SHARED_LIBS['_tkinter.so'] = [ @@ -971,7 +971,7 @@ def buildPython(): # out-of-date and has critical bugs. Save the _tkinter.so that was # linked with /Library/Frameworks/{Tck,Tk}.framework and build # another _tkinter.so linked with our builtin Tcl and Tk libs. - if DEPTARGET > '10.5': + if (DEPTARGET > '10.5') and (getVersionTuple() >= (3, 4)): runCommand("find build -name '_tkinter.so' " " -execdir mv '{}' _tkinter_library.so \;") print("Running make to build builtin _tkinter") @@ -1012,7 +1012,7 @@ def buildPython(): # users to select which to import by manipulating sys.path # directly or with PYTHONPATH. - if DEPTARGET > '10.5': + if (DEPTARGET > '10.5') and (getVersionTuple() >= (3, 4)): TKINTERS = ['builtin', 'library'] tkinter_moves = [('_tkinter_' + tkn + '.so', os.path.join(path_to_lib, 'lib-tkinter', tkn)) @@ -1059,7 +1059,7 @@ def buildPython(): # The files are moved after the entire tree has been walked # since the shared library checking depends on the files # having unique names. - if DEPTARGET > '10.5': + if (DEPTARGET > '10.5') and (getVersionTuple() >= (3, 4)): for tkm in tkinter_moves: if fn == tkm[0]: moves_list.append( diff --git a/Mac/BuildScript/resources/ReadMe.txt b/Mac/BuildScript/resources/ReadMe.txt index e5c49f0a98c..212d963c641 100644 --- a/Mac/BuildScript/resources/ReadMe.txt +++ b/Mac/BuildScript/resources/ReadMe.txt @@ -17,27 +17,18 @@ instead of double-clicking, control-click or right click the "Python" installer package icon. Then select "Open using ... Installer" from the contextual menu that appears. - **** IMPORTANT changes if you use IDLE and Tkinter **** + **** IMPORTANT **** -Installing a third-party version of Tcl/Tk is no longer required -================================================================ +Update your version of Tcl/Tk to use IDLE or other Tk applications +================================================================== -As of Python 3.3.3, the 10.6+ 64-bit installer now -comes with its own private copy of Tcl and Tk 8.5 libraries. For -this version of Python, it is no longer necessary to install -a third-party version of Tcl/Tk 8.5, such as those from ActiveState, -to work around the problematic versions of Tcl/Tk 8.5 shipped by -Apple in OS X 10.6 and later. (This does not change the requirements -for older versions of Python installed from python.org.) By default, -this version of Python will always use its own private version, -regardless of whether a third-party Tcl/Tk is installed. -The 10.5+ 32-bit-only installer continues to use Tcl/Tk 8.4, -either a third-party or system-supplied version. - -Visit http://www.python.org/download/mac/tcltk/ +To use IDLE or other programs that use the Tkinter graphical user +interface toolkit, you may need to install a newer third-party version +of the Tcl/Tk frameworks. Visit http://www.python.org/download/mac/tcltk/ for current information about supported and recommended versions of Tcl/Tk for this version of Python and of Mac OS X. + Using this version of Python on OS X ==================================== diff --git a/Mac/BuildScript/resources/Welcome.rtf b/Mac/BuildScript/resources/Welcome.rtf index c3b4b7cbf38..239d76ecc2d 100644 --- a/Mac/BuildScript/resources/Welcome.rtf +++ b/Mac/BuildScript/resources/Welcome.rtf @@ -25,7 +25,11 @@ See the ReadMe file and the Python documentation for more information.\ \b0 at any time to make $FULL_VERSION the default Python 3 version. This version can co-exist with other installed versions of Python 3 and Python 2.\ \ -\b IMPORTANT for users of IDLE and tkinter: -\b0 As of Python 3.3.3, it is no longer necessary to install third-party versions of the +\b IMPORTANT: +\b0 +\b IDLE +\b0 and other programs using the +\b tkinter +\b0 graphical user interface toolkit require specific versions of the \b Tcl/Tk -\b0 platform independent windowing toolkit. Please read the ReadMe file and visit {\field{\*\fldinst{HYPERLINK "http://www.python.org/download/mac/tcltk/"}}{\fldrslt http://www.python.org/download/mac/tcltk/}} for more information on supported and recommended versions of Tcl/Tk for this version of Python and Mac OS X.} \ No newline at end of file +\b0 platform independent windowing toolkit. Visit {\field{\*\fldinst{HYPERLINK "http://www.python.org/download/mac/tcltk/"}}{\fldrslt http://www.python.org/download/mac/tcltk/}} for current information on supported and recommended versions of Tcl/Tk for this version of Python and Mac OS X.} \ No newline at end of file diff --git a/Misc/NEWS b/Misc/NEWS index 9872b309e14..9ff03c2825b 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,14 @@ Tests - Issue #18964: Fix test_tcl when run with Tcl/Tk versions < 8.5. +Build +----- + +- Issue #15663: Revert OS X installer built-in Tcl/Tk support for 3.3.3. + Some third-party projects, such as Matplotlib and PIL/Pillow, + depended on being able to build with Tcl and Tk frameworks in + /Library/Frameworks. + What's New in Python 3.3.3 release candidate 1? =============================================== From b3acaccf273feb720df10c2890d6c35ca8b62acd Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Mon, 11 Nov 2013 06:10:23 +0100 Subject: [PATCH 03/11] Transplant of rev 544b654d000c: directory traversal attack in CGIHttpRequestHandler. --- Lib/http/server.py | 9 ++++----- Lib/test/test_httpservers.py | 12 ++++++++++++ Misc/NEWS | 5 +++++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/Lib/http/server.py b/Lib/http/server.py index ebc2a8fcdc2..2bfda12df43 100644 --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -987,18 +987,17 @@ class CGIHTTPRequestHandler(SimpleHTTPRequestHandler): def run_cgi(self): """Execute a CGI script.""" - path = self.path dir, rest = self.cgi_info - i = path.find('/', len(dir) + 1) + i = rest.find('/') while i >= 0: - nextdir = path[:i] - nextrest = path[i+1:] + nextdir = rest[:i] + nextrest = rest[i+1:] scriptdir = self.translate_path(nextdir) if os.path.isdir(scriptdir): dir, rest = nextdir, nextrest - i = path.find('/', len(dir) + 1) + i = rest.find('/') else: break diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py index b8bbcb67348..9dd27788f75 100644 --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -325,6 +325,7 @@ class CGIHTTPServerTestCase(BaseTestCase): self.parent_dir = tempfile.mkdtemp() self.cgi_dir = os.path.join(self.parent_dir, 'cgi-bin') os.mkdir(self.cgi_dir) + self.nocgi_path = None self.file1_path = None self.file2_path = None @@ -345,6 +346,11 @@ class CGIHTTPServerTestCase(BaseTestCase): self.tearDown() self.skipTest("Python executable path is not encodable to utf-8") + self.nocgi_path = os.path.join(self.parent_dir, 'nocgi.py') + with open(self.nocgi_path, 'w') as fp: + fp.write(cgi_file1 % self.pythonexe) + os.chmod(self.nocgi_path, 0o777) + self.file1_path = os.path.join(self.cgi_dir, 'file1.py') with open(self.file1_path, 'w', encoding='utf-8') as file1: file1.write(cgi_file1 % self.pythonexe) @@ -362,6 +368,8 @@ class CGIHTTPServerTestCase(BaseTestCase): os.chdir(self.cwd) if self.pythonexe != sys.executable: os.remove(self.pythonexe) + if self.nocgi_path: + os.remove(self.nocgi_path) if self.file1_path: os.remove(self.file1_path) if self.file2_path: @@ -418,6 +426,10 @@ class CGIHTTPServerTestCase(BaseTestCase): self.assertEqual((b'Hello World' + self.linesep, 'text/html', 200), (res.read(), res.getheader('Content-type'), res.status)) + def test_issue19435(self): + res = self.request('///////////nocgi.py/../cgi-bin/nothere.sh') + self.assertEqual(res.status, 404) + def test_post(self): params = urllib.parse.urlencode( {'spam' : 1, 'eggs' : 'python', 'bacon' : 123456}) diff --git a/Misc/NEWS b/Misc/NEWS index 9ff03c2825b..dfb6068e8c1 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -7,6 +7,11 @@ What's New in Python 3.3.3? *Release date: XX-Nov-2013* +Library +------- + +- Issue #19435: Fix directory traversal attack on CGIHttpRequestHandler. + Tests ----- From 7e246179047d33bd467bcab673b3ecc1944f91a4 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Tue, 29 Oct 2013 20:50:01 +0100 Subject: [PATCH 04/11] Issue #19227 / Issue #18747: Remove pthread_atfork() handler to remove OpenSSL re-seeding It is causing trouble like e.g. hanging processes. --- Modules/_ssl.c | 67 -------------------------------------------------- 1 file changed, 67 deletions(-) diff --git a/Modules/_ssl.c b/Modules/_ssl.c index b791f28d087..374d930166f 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -19,9 +19,6 @@ #ifdef WITH_THREAD #include "pythread.h" -#ifdef HAVE_PTHREAD_ATFORK -# include -#endif #define PySSL_BEGIN_ALLOW_THREADS_S(save) \ do { if (_ssl_locks_count>0) { (save) = PyEval_SaveThread(); } } while (0) @@ -2584,65 +2581,6 @@ Queries the entropy gather daemon (EGD) on the socket named by 'path'.\n\ Returns number of bytes read. Raises SSLError if connection to EGD\n\ fails or if it does not provide enough data to seed PRNG."); -/* Seed OpenSSL's PRNG at fork(), http://bugs.python.org/issue18747 - * - * The prepare handler seeds the PRNG from pseudo-random data like pid, the - * current time (miliseconds or seconds) and an uninitialized array. - * The array contains stack variables that are impossible to predict - * on most systems, e.g. function return address (subject to ASLR), the - * stack protection canary and automatic variables. - * The code is inspired by Apache's ssl_rand_seed() function. - * - * Note: - * The code uses pthread_atfork() until Python has a proper atfork API. The - * handlers are not removed from the child process. A prepare handler is used - * instead of a child handler because fork() is supposed to be async-signal - * safe but the handler calls unsafe functions. A parent handler has caused - * other problems, see issue #19227. - */ - -#if defined(HAVE_PTHREAD_ATFORK) && defined(WITH_THREAD) -#define PYSSL_RAND_ATFORK 1 - -static void -PySSL_RAND_atfork_prepare(void) -{ - struct { - char stack[128]; /* uninitialized (!) stack data, 128 is an - arbitrary number. */ - pid_t pid; /* current pid */ - _PyTime_timeval tp; /* current time */ - } seed; - -#ifdef WITH_VALGRIND - VALGRIND_MAKE_MEM_DEFINED(seed.stack, sizeof(seed.stack)); -#endif - seed.pid = getpid(); - _PyTime_gettimeofday(&(seed.tp)); - RAND_add((unsigned char *)&seed, sizeof(seed), 0.0); -} - -static int -PySSL_RAND_atfork(void) -{ - static int registered = 0; - int retval; - - if (registered) - return 0; - - retval = pthread_atfork(PySSL_RAND_atfork_prepare, /* prepare */ - NULL, /* parent */ - NULL); /* child */ - if (retval != 0) { - PyErr_SetFromErrno(PyExc_OSError); - return -1; - } - registered = 1; - return 0; -} -#endif /* HAVE_PTHREAD_ATFORK */ - #endif /* HAVE_OPENSSL_RAND */ @@ -3022,10 +2960,5 @@ PyInit__ssl(void) if (r == NULL || PyModule_AddObject(m, "_OPENSSL_API_VERSION", r)) return NULL; -#ifdef PYSSL_RAND_ATFORK - if (PySSL_RAND_atfork() == -1) - return NULL; -#endif - return m; } From 4cf9b2047d0438b69f66b0c2fd48e6d7576eb1f1 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Mon, 11 Nov 2013 06:13:54 +0100 Subject: [PATCH 05/11] Bump to 3.3.3rc2. --- Include/patchlevel.h | 4 ++-- Lib/distutils/__init__.py | 2 +- Lib/idlelib/idlever.py | 2 +- Misc/NEWS | 9 ++++++--- Misc/RPM/python-3.3.spec | 2 +- README | 2 +- 6 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h index 658f0f5743f..3ae5dc93191 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -20,10 +20,10 @@ #define PY_MINOR_VERSION 3 #define PY_MICRO_VERSION 3 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA -#define PY_RELEASE_SERIAL 1 +#define PY_RELEASE_SERIAL 2 /* Version as a string */ -#define PY_VERSION "3.3.3rc1" +#define PY_VERSION "3.3.3rc2" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py index 812d8f35dcd..0650dd277a7 100644 --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -13,5 +13,5 @@ used from a setup script as # Updated automatically by the Python release process. # #--start constants-- -__version__ = "3.3.3rc1" +__version__ = "3.3.3rc2" #--end constants-- diff --git a/Lib/idlelib/idlever.py b/Lib/idlelib/idlever.py index 640e0080151..c1e6476111b 100644 --- a/Lib/idlelib/idlever.py +++ b/Lib/idlelib/idlever.py @@ -1 +1 @@ -IDLE_VERSION = "3.3.3rc1" +IDLE_VERSION = "3.3.3rc2" diff --git a/Misc/NEWS b/Misc/NEWS index dfb6068e8c1..21783ffe817 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,14 +2,17 @@ Python News +++++++++++ -What's New in Python 3.3.3? -=========================== +What's New in Python 3.3.3 release candidate 2? +=============================================== -*Release date: XX-Nov-2013* +*Release date: 11-Nov-2013* Library ------- +- Issue #19227: Any re-seeding of the OpenSSL RNG on fork has been removed; + this should be handled by OpenSSL itself or by the application. + - Issue #19435: Fix directory traversal attack on CGIHttpRequestHandler. Tests diff --git a/Misc/RPM/python-3.3.spec b/Misc/RPM/python-3.3.spec index c324559d72e..8e2a012db00 100644 --- a/Misc/RPM/python-3.3.spec +++ b/Misc/RPM/python-3.3.spec @@ -39,7 +39,7 @@ %define name python #--start constants-- -%define version 3.3.3rc1 +%define version 3.3.3rc2 %define libvers 3.3 #--end constants-- %define release 1pydotorg diff --git a/README b/README index 12548b767db..c9be112394e 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -This is Python version 3.3.3 release candidate 1 +This is Python version 3.3.3 release candidate 2 ================================================ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, From 53171b5987814166517d4ed25c4da2c98d1d1ac5 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Mon, 11 Nov 2013 06:16:15 +0100 Subject: [PATCH 06/11] Added tag v3.3.3rc2 for changeset d32442c0e60d --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 78b30dd17bd..df140ca083e 100644 --- a/.hgtags +++ b/.hgtags @@ -116,3 +116,4 @@ bd8afb90ebf28ba4edc901d4a235f75e7bbc79fd v3.3.0 d9893d13c6289aa03d33559ec67f97dcbf5c9e3c v3.3.1 d047928ae3f6314a13b6137051315453d0ae89b6 v3.3.2 fd53c500f8b80f54f3ecedec9da2e8c7e52a6888 v3.3.3rc1 +d32442c0e60dfbd71234e807d3d1dedd227495a9 v3.3.3rc2 From 2bbdfe7eda67e9bc53fb0b5a5eb65426e6b9400a Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Sun, 17 Nov 2013 02:47:12 +0200 Subject: [PATCH 07/11] #19238: fix typo in documentation. --- Doc/library/string.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/string.rst b/Doc/library/string.rst index e304c5d4ff7..e5bab684dfb 100644 --- a/Doc/library/string.rst +++ b/Doc/library/string.rst @@ -300,7 +300,7 @@ The general form of a *standard format specifier* is: precision: `integer` type: "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%" -If a valid *align* value is specified, it can be preceeded by a *fill* +If a valid *align* value is specified, it can be preceded by a *fill* character that can be any character and defaults to a space if omitted. Note that it is not possible to use ``{`` and ``}`` as *fill* char while using the :meth:`str.format` method; this limitation however doesn't From c610aba1ed57a30104a254ccd1f9fe07d02b1334 Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Sun, 17 Nov 2013 15:59:51 +1000 Subject: [PATCH 08/11] Close #19282: Native context management in dbm --- Doc/library/dbm.rst | 38 ++++++++++++++++++++++---------------- Lib/dbm/dumb.py | 6 ++++++ Lib/test/test_dbm_dumb.py | 13 +++++++++++++ Lib/test/test_dbm_gnu.py | 11 +++++++++++ Lib/test/test_dbm_ndbm.py | 13 +++++++++++++ Misc/NEWS | 3 +++ Modules/_dbmmodule.c | 17 +++++++++++++++++ Modules/_gdbmmodule.c | 16 ++++++++++++++++ 8 files changed, 101 insertions(+), 16 deletions(-) diff --git a/Doc/library/dbm.rst b/Doc/library/dbm.rst index 81a05c70734..f5496d5b99c 100644 --- a/Doc/library/dbm.rst +++ b/Doc/library/dbm.rst @@ -73,33 +73,39 @@ Key and values are always stored as bytes. This means that when strings are used they are implicitly converted to the default encoding before being stored. +These objects also support being used in a :keyword:`with` statement, which +will automatically close them when done. + +.. versionchanged:: 3.4 + Added native support for the context management protocol to the objects + returned by :func:`.open`. + The following example records some hostnames and a corresponding title, and then prints out the contents of the database:: import dbm # Open database, creating it if necessary. - db = dbm.open('cache', 'c') + with dbm.open('cache', 'c') as db: - # Record some values - db[b'hello'] = b'there' - db['www.python.org'] = 'Python Website' - db['www.cnn.com'] = 'Cable News Network' + # Record some values + db[b'hello'] = b'there' + db['www.python.org'] = 'Python Website' + db['www.cnn.com'] = 'Cable News Network' - # Note that the keys are considered bytes now. - assert db[b'www.python.org'] == b'Python Website' - # Notice how the value is now in bytes. - assert db['www.cnn.com'] == b'Cable News Network' + # Note that the keys are considered bytes now. + assert db[b'www.python.org'] == b'Python Website' + # Notice how the value is now in bytes. + assert db['www.cnn.com'] == b'Cable News Network' - # Often-used methods of the dict interface work too. - print(db.get('python.org', b'not present')) + # Often-used methods of the dict interface work too. + print(db.get('python.org', b'not present')) - # Storing a non-string key or value will raise an exception (most - # likely a TypeError). - db['www.yahoo.com'] = 4 + # Storing a non-string key or value will raise an exception (most + # likely a TypeError). + db['www.yahoo.com'] = 4 - # Close when done. - db.close() + # db is automatically closed when leaving the with statement. .. seealso:: diff --git a/Lib/dbm/dumb.py b/Lib/dbm/dumb.py index 9ac7852978f..ba6a20d0c9a 100644 --- a/Lib/dbm/dumb.py +++ b/Lib/dbm/dumb.py @@ -236,6 +236,12 @@ class _Database(collections.MutableMapping): if hasattr(self._os, 'chmod'): self._os.chmod(file, self._mode) + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + def open(file, flag=None, mode=0o666): """Open the database file, filename, and return corresponding object. diff --git a/Lib/test/test_dbm_dumb.py b/Lib/test/test_dbm_dumb.py index 208bc4c3823..9fd8cde59a8 100644 --- a/Lib/test/test_dbm_dumb.py +++ b/Lib/test/test_dbm_dumb.py @@ -184,6 +184,19 @@ class DumbDBMTestCase(unittest.TestCase): self.assertEqual(expected, got) f.close() + def test_context_manager(self): + with dumbdbm.open(_fname, 'c') as db: + db["dumbdbm context manager"] = "context manager" + + with dumbdbm.open(_fname, 'r') as db: + self.assertEqual(list(db.keys()), [b"dumbdbm context manager"]) + + # This currently just raises AttributeError rather than a specific + # exception like the GNU or NDBM based implementations. See + # http://bugs.python.org/issue19385 for details. + with self.assertRaises(Exception): + db.keys() + def tearDown(self): _delete_files() diff --git a/Lib/test/test_dbm_gnu.py b/Lib/test/test_dbm_gnu.py index 4fb66c54b8c..a7808f51c75 100755 --- a/Lib/test/test_dbm_gnu.py +++ b/Lib/test/test_dbm_gnu.py @@ -81,6 +81,17 @@ class TestGdbm(unittest.TestCase): size2 = os.path.getsize(filename) self.assertTrue(size1 > size2 >= size0) + def test_context_manager(self): + with gdbm.open(filename, 'c') as db: + db["gdbm context manager"] = "context manager" + + with gdbm.open(filename, 'r') as db: + self.assertEqual(list(db.keys()), [b"gdbm context manager"]) + + with self.assertRaises(gdbm.error) as cm: + db.keys() + self.assertEqual(str(cm.exception), + "GDBM object has already been closed") if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_dbm_ndbm.py b/Lib/test/test_dbm_ndbm.py index b57e1f06535..2291561defc 100755 --- a/Lib/test/test_dbm_ndbm.py +++ b/Lib/test/test_dbm_ndbm.py @@ -37,5 +37,18 @@ class DbmTestCase(unittest.TestCase): except error: self.fail() + def test_context_manager(self): + with dbm.ndbm.open(self.filename, 'c') as db: + db["ndbm context manager"] = "context manager" + + with dbm.ndbm.open(self.filename, 'r') as db: + self.assertEqual(list(db.keys()), [b"ndbm context manager"]) + + with self.assertRaises(dbm.ndbm.error) as cm: + db.keys() + self.assertEqual(str(cm.exception), + "DBM object has already been closed") + + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS index 89c37d9ba18..9dedb6aa51f 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -50,6 +50,9 @@ Core and Builtins Library ------- +- Issue #19282: dbm.open now supports the context manager protocol. (Inital + patch by Claudiu Popa) + - Issue #8311: Added support for writing any bytes-like objects in the aifc, sunau, and wave modules. diff --git a/Modules/_dbmmodule.c b/Modules/_dbmmodule.c index 60802b694a4..370f67039da 100644 --- a/Modules/_dbmmodule.c +++ b/Modules/_dbmmodule.c @@ -313,6 +313,21 @@ dbm_setdefault(dbmobject *dp, PyObject *args) return defvalue; } +static PyObject * +dbm__enter__(PyObject *self, PyObject *args) +{ + Py_INCREF(self); + return self; +} + +static PyObject * +dbm__exit__(PyObject *self, PyObject *args) +{ + _Py_IDENTIFIER(close); + return _PyObject_CallMethodId(self, &PyId_close, NULL); +} + + static PyMethodDef dbm_methods[] = { {"close", (PyCFunction)dbm__close, METH_NOARGS, "close()\nClose the database."}, @@ -325,6 +340,8 @@ static PyMethodDef dbm_methods[] = { "setdefault(key[, default]) -> value\n" "Return the value for key if present, otherwise default. If key\n" "is not in the database, it is inserted with default as the value."}, + {"__enter__", dbm__enter__, METH_NOARGS, NULL}, + {"__exit__", dbm__exit__, METH_VARARGS, NULL}, {NULL, NULL} /* sentinel */ }; diff --git a/Modules/_gdbmmodule.c b/Modules/_gdbmmodule.c index 36c06d13b79..229e16e627d 100644 --- a/Modules/_gdbmmodule.c +++ b/Modules/_gdbmmodule.c @@ -425,6 +425,20 @@ dbm_sync(dbmobject *dp, PyObject *unused) return Py_None; } +static PyObject * +dbm__enter__(PyObject *self, PyObject *args) +{ + Py_INCREF(self); + return self; +} + +static PyObject * +dbm__exit__(PyObject *self, PyObject *args) +{ + _Py_IDENTIFIER(close); + return _PyObject_CallMethodId(self, &PyId_close, NULL); +} + static PyMethodDef dbm_methods[] = { {"close", (PyCFunction)dbm_close, METH_NOARGS, dbm_close__doc__}, {"keys", (PyCFunction)dbm_keys, METH_NOARGS, dbm_keys__doc__}, @@ -434,6 +448,8 @@ static PyMethodDef dbm_methods[] = { {"sync", (PyCFunction)dbm_sync, METH_NOARGS, dbm_sync__doc__}, {"get", (PyCFunction)dbm_get, METH_VARARGS, dbm_get__doc__}, {"setdefault",(PyCFunction)dbm_setdefault,METH_VARARGS, dbm_setdefault__doc__}, + {"__enter__", dbm__enter__, METH_NOARGS, NULL}, + {"__exit__", dbm__exit__, METH_VARARGS, NULL}, {NULL, NULL} /* sentinel */ }; From 9e2043a5613a6423b7051b08a916b01969c179ed Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sun, 17 Nov 2013 07:58:22 +0100 Subject: [PATCH 09/11] Bump to 3.3.3 final. --- Include/patchlevel.h | 6 +++--- Lib/distutils/__init__.py | 2 +- Lib/idlelib/idlever.py | 2 +- Misc/NEWS | 8 ++++++++ Misc/RPM/python-3.3.spec | 2 +- README | 4 ++-- 6 files changed, 16 insertions(+), 8 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h index 3ae5dc93191..69ab168b5d6 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -19,11 +19,11 @@ #define PY_MAJOR_VERSION 3 #define PY_MINOR_VERSION 3 #define PY_MICRO_VERSION 3 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA -#define PY_RELEASE_SERIAL 2 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL +#define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "3.3.3rc2" +#define PY_VERSION "3.3.3" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py index 0650dd277a7..6747ab8677c 100644 --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -13,5 +13,5 @@ used from a setup script as # Updated automatically by the Python release process. # #--start constants-- -__version__ = "3.3.3rc2" +__version__ = "3.3.3" #--end constants-- diff --git a/Lib/idlelib/idlever.py b/Lib/idlelib/idlever.py index c1e6476111b..60f1d329aae 100644 --- a/Lib/idlelib/idlever.py +++ b/Lib/idlelib/idlever.py @@ -1 +1 @@ -IDLE_VERSION = "3.3.3rc2" +IDLE_VERSION = "3.3.3" diff --git a/Misc/NEWS b/Misc/NEWS index 21783ffe817..140b4878537 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,6 +2,14 @@ Python News +++++++++++ +What's New in Python 3.3.3? +=========================== + +*Release date: 17-Nov-2013* + +No changes from release candidate 2. + + What's New in Python 3.3.3 release candidate 2? =============================================== diff --git a/Misc/RPM/python-3.3.spec b/Misc/RPM/python-3.3.spec index 8e2a012db00..b8b57e2b9a6 100644 --- a/Misc/RPM/python-3.3.spec +++ b/Misc/RPM/python-3.3.spec @@ -39,7 +39,7 @@ %define name python #--start constants-- -%define version 3.3.3rc2 +%define version 3.3.3 %define libvers 3.3 #--end constants-- %define release 1pydotorg diff --git a/README b/README index c9be112394e..f6f8ea01249 100644 --- a/README +++ b/README @@ -1,5 +1,5 @@ -This is Python version 3.3.3 release candidate 2 -================================================ +This is Python version 3.3.3 +============================ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Python Software Foundation. All rights reserved. From 7a5cf6ce041fefd63ba8b088464901e6052bd9e7 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sun, 17 Nov 2013 07:59:06 +0100 Subject: [PATCH 10/11] Added tag v3.3.3 for changeset c3896275c0f6 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index df140ca083e..7801acf9549 100644 --- a/.hgtags +++ b/.hgtags @@ -117,3 +117,4 @@ d9893d13c6289aa03d33559ec67f97dcbf5c9e3c v3.3.1 d047928ae3f6314a13b6137051315453d0ae89b6 v3.3.2 fd53c500f8b80f54f3ecedec9da2e8c7e52a6888 v3.3.3rc1 d32442c0e60dfbd71234e807d3d1dedd227495a9 v3.3.3rc2 +c3896275c0f61b2510a6c7e6c458a750359a91b8 v3.3.3 From 1d2436a5814fdbfe5a032934fe09489a33f0fb0a Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sun, 17 Nov 2013 09:17:40 +0100 Subject: [PATCH 11/11] Post-release bump. --- Include/patchlevel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h index 69ab168b5d6..054b9eb5dbb 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -23,7 +23,7 @@ #define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "3.3.3" +#define PY_VERSION "3.3.3+" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2.