]> granicus.if.org Git - python/commitdiff
Merged revisions 59226-59233 via svnmerge from
authorChristian Heimes <christian@cheimes.de>
Fri, 30 Nov 2007 14:35:04 +0000 (14:35 +0000)
committerChristian Heimes <christian@cheimes.de>
Fri, 30 Nov 2007 14:35:04 +0000 (14:35 +0000)
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.
........

Doc/ACKS.txt
Doc/library/wsgiref.rst
Lib/test/test_threading.py
PCbuild9/pcbuild.sln
Python/pythonrun.c

index 1e2c4ec14e268a1720f32330d61eb0988936f291..52aa7947a7facb8247be07b111b81c25a2a2a5b3 100644 (file)
@@ -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
index 73acf84979f23e9bc344f6415e0fe5ad2cca4b90..0118032c9bc0673301d5c48c7f463a603aaf94fa 100644 (file)
@@ -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()
index b76cea14e0d3962aaaa4404fd94013bc6bab9d60..e5ed201b0afe679db3972fe987088a14ed6a9b71 100644 (file)
@@ -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.
index 1625875dd4b5edb5d5eab575cf9fbdc38d82eed7..d81c3b43d4e98b248cc1cefe8891b16a1321aef2 100644 (file)
@@ -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}
index 5766b2385e533f94f71c206e4a77d1c6044d47c6..08b0d834ce310afc8c137fb4370f36a8a3cb4722 100644 (file)
@@ -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);