Commit 7d2ff884 authored by Christian Heimes's avatar Christian Heimes

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.
........
parent 2e510fb9
...@@ -41,6 +41,7 @@ docs@python.org), and we'll be glad to correct the problem. ...@@ -41,6 +41,7 @@ docs@python.org), and we'll be glad to correct the problem.
* L. Peter Deutsch * L. Peter Deutsch
* Robert Donohue * Robert Donohue
* Fred L. Drake, Jr. * Fred L. Drake, Jr.
* Josip Dzolonga
* Jeff Epler * Jeff Epler
* Michael Ernst * Michael Ernst
* Blame Andy Eskilsson * Blame Andy Eskilsson
......
...@@ -112,6 +112,30 @@ parameter expect a WSGI-compliant dictionary to be supplied; please see ...@@ -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 applications to set up dummy environments. It should NOT be used by actual WSGI
servers or applications, since the data is fake! 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 In addition to the environment functions above, the :mod:`wsgiref.util` module
also provides these miscellaneous utilities: also provides these miscellaneous utilities:
...@@ -135,6 +159,19 @@ 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` :meth:`close` method, and it will invoke the *filelike* object's :meth:`close`
method when called. 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 :mod:`wsgiref.headers` -- WSGI response header tools
---------------------------------------------------- ----------------------------------------------------
...@@ -250,7 +287,7 @@ request. (E.g., using the :func:`shift_path_info` function from ...@@ -250,7 +287,7 @@ request. (E.g., using the :func:`shift_path_info` function from
httpd.serve_forever() httpd.serve_forever()
# Alternative: serve one request, then exit # Alternative: serve one request, then exit
##httpd.handle_request() httpd.handle_request()
.. function:: demo_app(environ, start_response) .. function:: demo_app(environ, start_response)
...@@ -371,6 +408,29 @@ Paste" library. ...@@ -371,6 +408,29 @@ Paste" library.
``sys.stderr`` (*not* ``wsgi.errors``, unless they happen to be the same ``sys.stderr`` (*not* ``wsgi.errors``, unless they happen to be the same
object). 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 :mod:`wsgiref.handlers` -- server/gateway base classes
------------------------------------------------------ ------------------------------------------------------
...@@ -637,3 +697,30 @@ input, output, and error streams. ...@@ -637,3 +697,30 @@ input, output, and error streams.
If :attr:`origin_server` is true, this string attribute is used to set the HTTP 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"``. 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()
...@@ -202,6 +202,40 @@ class ThreadTests(unittest.TestCase): ...@@ -202,6 +202,40 @@ class ThreadTests(unittest.TestCase):
t.join() t.join()
# else the thread is still running, and we have no way to kill it # 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): class ThreadingExceptionTests(unittest.TestCase):
# A RuntimeError should be raised if Thread.start() is called # A RuntimeError should be raised if Thread.start() is called
# multiple times. # multiple times.
......
Microsoft Visual Studio Solution File, Format Version 10.00 Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008 # 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}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "python", "python.vcproj", "{B11D750F-CD1F-4A96-85CE-E69A5C5259F9}"
ProjectSection(ProjectDependencies) = postProject ProjectSection(ProjectDependencies) = postProject
{CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} = {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}
{E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058} = {E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058} {E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058} = {E9E0A1F6-0009-4E8C-B8F8-1B8F5D49A058}
EndProjectSection EndProjectSection
EndProject 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}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pythoncore", "pythoncore.vcproj", "{CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}"
ProjectSection(ProjectDependencies) = postProject ProjectSection(ProjectDependencies) = postProject
{F0E0541E-F17D-430B-97C4-93ADF0DD284E} = {F0E0541E-F17D-430B-97C4-93ADF0DD284E} {F0E0541E-F17D-430B-97C4-93ADF0DD284E} = {F0E0541E-F17D-430B-97C4-93ADF0DD284E}
......
...@@ -467,11 +467,6 @@ Py_Finalize(void) ...@@ -467,11 +467,6 @@ Py_Finalize(void)
_Py_PrintReferences(stderr); _Py_PrintReferences(stderr);
#endif /* Py_TRACE_REFS */ #endif /* Py_TRACE_REFS */
/* Cleanup auto-thread-state */
#ifdef WITH_THREAD
_PyGILState_Fini();
#endif /* WITH_THREAD */
/* Clear interpreter state */ /* Clear interpreter state */
PyInterpreterState_Clear(interp); PyInterpreterState_Clear(interp);
...@@ -483,6 +478,11 @@ Py_Finalize(void) ...@@ -483,6 +478,11 @@ Py_Finalize(void)
_PyExc_Fini(); _PyExc_Fini();
/* Cleanup auto-thread-state */
#ifdef WITH_THREAD
_PyGILState_Fini();
#endif /* WITH_THREAD */
/* Delete current thread */ /* Delete current thread */
PyThreadState_Swap(NULL); PyThreadState_Swap(NULL);
PyInterpreterState_Delete(interp); PyInterpreterState_Delete(interp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment