diff options
author | Christian Heimes <christian@cheimes.de> | 2007-11-30 14:35:04 (GMT) |
---|---|---|
committer | Christian Heimes <christian@cheimes.de> | 2007-11-30 14:35:04 (GMT) |
commit | 7d2ff884eeb636fcd30ebd2f9886c4b46e8545bc (patch) | |
tree | 464092cc4b9f9ef6b4a32c7fb5d5bfbfb1131c9d | |
parent | 2e510fb9202977d93cc364e0c661769ea4a8cbbc (diff) | |
download | cpython-7d2ff884eeb636fcd30ebd2f9886c4b46e8545bc.zip cpython-7d2ff884eeb636fcd30ebd2f9886c4b46e8545bc.tar.gz cpython-7d2ff884eeb636fcd30ebd2f9886c4b46e8545bc.tar.bz2 |
Merged revisions 59226-59233 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r59228 | amaury.forgeotdarc | 2007-11-29 21:24:36 +0100 (Thu, 29 Nov 2007) | 4 lines
vc2008: Move python.vcproj first in the solution file, so that
it becomes the default startup project when opening the file
for the first time.
........
r59230 | georg.brandl | 2007-11-30 00:00:03 +0100 (Fri, 30 Nov 2007) | 3 lines
Add more examples to the wsgiref docs.
From GHOP by Josip Dzolonga.
........
r59231 | amaury.forgeotdarc | 2007-11-30 00:35:25 +0100 (Fri, 30 Nov 2007) | 7 lines
Issue #1402: PyInterpreterState_Clear() may still invoke user code
(in deallocation of running threads, for example), so the PyGILState_Release()
function must still be functional.
On the other hand, _PyGILState_Fini() only frees memory, and can be called later.
Backport candidate, but only after some experts comment on it.
........
-rw-r--r-- | Doc/ACKS.txt | 1 | ||||
-rw-r--r-- | Doc/library/wsgiref.rst | 89 | ||||
-rw-r--r-- | Lib/test/test_threading.py | 34 | ||||
-rw-r--r-- | PCbuild9/pcbuild.sln | 4 | ||||
-rw-r--r-- | Python/pythonrun.c | 10 |
5 files changed, 130 insertions, 8 deletions
diff --git a/Doc/ACKS.txt b/Doc/ACKS.txt index 1e2c4ec..52aa794 100644 --- a/Doc/ACKS.txt +++ b/Doc/ACKS.txt @@ -41,6 +41,7 @@ docs@python.org), and we'll be glad to correct the problem. * L. Peter Deutsch * Robert Donohue * Fred L. Drake, Jr. +* Josip Dzolonga * Jeff Epler * Michael Ernst * Blame Andy Eskilsson diff --git a/Doc/library/wsgiref.rst b/Doc/library/wsgiref.rst index 73acf84..0118032 100644 --- a/Doc/library/wsgiref.rst +++ b/Doc/library/wsgiref.rst @@ -112,6 +112,30 @@ parameter expect a WSGI-compliant dictionary to be supplied; please see applications to set up dummy environments. It should NOT be used by actual WSGI servers or applications, since the data is fake! + Example usage:: + + from wsgiref.util import setup_testing_defaults + from wsgiref.simple_server import make_server + + # A relatively simple WSGI application. It's going to print out the + # environment dictionary after being updated by setup_testing_defaults + def simple_app(environ, start_response): + setup_testing_defaults(environ) + + status = '200 OK' + headers = [('Content-type', 'text/plain')] + + start_response(status, headers) + + ret = ["%s: %s\n" % (key, value) + for key, value in environ.iteritems()] + return ret + + httpd = make_server('', 8000, simple_app) + print "Serving on port 8000..." + httpd.serve_forever() + + In addition to the environment functions above, the :mod:`wsgiref.util` module also provides these miscellaneous utilities: @@ -135,6 +159,19 @@ also provides these miscellaneous utilities: :meth:`close` method, and it will invoke the *filelike* object's :meth:`close` method when called. + Example usage:: + + from StringIO import StringIO + from wsgiref.util import FileWrapper + + # We're using a StringIO-buffer for as the file-like object + filelike = StringIO("This is an example file-like object"*10) + wrapper = FileWrapper(filelike, blksize=5) + + for chunk in wrapper: + print chunk + + :mod:`wsgiref.headers` -- WSGI response header tools ---------------------------------------------------- @@ -250,7 +287,7 @@ request. (E.g., using the :func:`shift_path_info` function from httpd.serve_forever() # Alternative: serve one request, then exit - ##httpd.handle_request() + httpd.handle_request() .. function:: demo_app(environ, start_response) @@ -371,6 +408,29 @@ Paste" library. ``sys.stderr`` (*not* ``wsgi.errors``, unless they happen to be the same object). + Example usage:: + + from wsgiref.validate import validator + from wsgiref.simple_server import make_server + + # Our callable object which is intentionally not compilant to the + # standard, so the validator is going to break + def simple_app(environ, start_response): + status = '200 OK' # HTTP Status + headers = [('Content-type', 'text/plain')] # HTTP Headers + start_response(status, headers) + + # This is going to break because we need to return a list, and + # the validator is going to inform us + return "Hello World" + + # This is the application wrapped in a validator + validator_app = validator(simple_app) + + httpd = make_server('', 8000, validator_app) + print "Listening on port 8000...." + httpd.serve_forever() + :mod:`wsgiref.handlers` -- server/gateway base classes ------------------------------------------------------ @@ -637,3 +697,30 @@ input, output, and error streams. If :attr:`origin_server` is true, this string attribute is used to set the HTTP version of the response set to the client. It defaults to ``"1.0"``. + +Examples +-------- + +This is a working "Hello World" WSGI application:: + + from wsgiref.simple_server import make_server + + # Every WSGI application must have an application object - a callable + # object that accepts two arguments. For that purpose, we're going to + # use a function (note that you're not limited to a function, you can + # use a class for example). The first argument passed to the function + # is a dictionary containing CGI-style envrironment variables and the + # second variable is the callable object (see PEP333) + def hello_world_app(environ, start_response): + status = '200 OK' # HTTP Status + headers = [('Content-type', 'text/plain')] # HTTP Headers + start_response(status, headers) + + # The returned object is going to be printed + return ["Hello World"] + + httpd = make_server('', 8000, hello_world_app) + print "Serving on port 8000..." + + # Serve until process is killed + httpd.serve_forever() diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index b76cea1..e5ed201 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -202,6 +202,40 @@ class ThreadTests(unittest.TestCase): t.join() # else the thread is still running, and we have no way to kill it + def test_finalize_runnning_thread(self): + # Issue 1402: the PyGILState_Ensure / _Release functions may be called + # very late on python exit: on deallocation of a running thread for + # example. + try: + import ctypes + except ImportError: + if verbose: + print("test_finalize_with_runnning_thread can't import ctypes") + return # can't do anything + + import subprocess + rc = subprocess.call([sys.executable, "-c", """if 1: + import ctypes, sys, time, thread + + # Module globals are cleared before __del__ is run + # So we save the functions in class dict + class C: + ensure = ctypes.pythonapi.PyGILState_Ensure + release = ctypes.pythonapi.PyGILState_Release + def __del__(self): + state = self.ensure() + self.release(state) + + def waitingThread(): + x = C() + time.sleep(100) + + thread.start_new_thread(waitingThread, ()) + time.sleep(1) # be sure the other thread is waiting + sys.exit(42) + """]) + self.assertEqual(rc, 42) + class ThreadingExceptionTests(unittest.TestCase): # A RuntimeError should be raised if Thread.start() is called # multiple times. diff --git a/PCbuild9/pcbuild.sln b/PCbuild9/pcbuild.sln index 1625875..d81c3b4 100644 --- a/PCbuild9/pcbuild.sln +++ b/PCbuild9/pcbuild.sln @@ -1,13 +1,13 @@ Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "make_versioninfo", "make_versioninfo.vcproj", "{F0E0541E-F17D-430B-97C4-93ADF0DD284E}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "python", "python.vcproj", "{B11D750F-CD1F-4A96-85CE-E69A5C5259F9}" ProjectSection(ProjectDependencies) = postProject {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} {E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058} = {E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "make_versioninfo", "make_versioninfo.vcproj", "{F0E0541E-F17D-430B-97C4-93ADF0DD284E}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pythoncore", "pythoncore.vcproj", "{CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}" ProjectSection(ProjectDependencies) = postProject {F0E0541E-F17D-430B-97C4-93ADF0DD284E} = {F0E0541E-F17D-430B-97C4-93ADF0DD284E} diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 5766b23..08b0d83 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -467,11 +467,6 @@ Py_Finalize(void) _Py_PrintReferences(stderr); #endif /* Py_TRACE_REFS */ - /* Cleanup auto-thread-state */ -#ifdef WITH_THREAD - _PyGILState_Fini(); -#endif /* WITH_THREAD */ - /* Clear interpreter state */ PyInterpreterState_Clear(interp); @@ -483,6 +478,11 @@ Py_Finalize(void) _PyExc_Fini(); + /* Cleanup auto-thread-state */ +#ifdef WITH_THREAD + _PyGILState_Fini(); +#endif /* WITH_THREAD */ + /* Delete current thread */ PyThreadState_Swap(NULL); PyInterpreterState_Delete(interp); |