]> granicus.if.org Git - python/commitdiff
Merged revisions 61038,61042-61045,61047,61050,61053,61055-61056,61061-61062,61066...
authorChristian Heimes <christian@cheimes.de>
Thu, 28 Feb 2008 20:02:27 +0000 (20:02 +0000)
committerChristian Heimes <christian@cheimes.de>
Thu, 28 Feb 2008 20:02:27 +0000 (20:02 +0000)
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r61105 | andrew.kuchling | 2008-02-28 15:03:03 +0100 (Thu, 28 Feb 2008) | 1 line

  #2169: make generated HTML more valid
........
  r61106 | jeffrey.yasskin | 2008-02-28 19:03:15 +0100 (Thu, 28 Feb 2008) | 4 lines

  Prevent SocketServer.ForkingMixIn from waiting on child processes that it
  didn't create, in most cases. When there are max_children handlers running, it
  will still wait for any child process, not just handler processes.
........
  r61107 | raymond.hettinger | 2008-02-28 20:41:24 +0100 (Thu, 28 Feb 2008) | 1 line

  Document impending updates to itertools.
........
  r61108 | martin.v.loewis | 2008-02-28 20:44:22 +0100 (Thu, 28 Feb 2008) | 1 line

  Add 2.6aN uuids.
........

Doc/library/itertools.rst
Lib/SimpleHTTPServer.py
Lib/SocketServer.py
Lib/test/test_socketserver.py
Tools/msi/uuids.py

index 73abb89d651cc9fa13a364a6a6387ab2736fe331..098972de8fb96ce93ca70a2658a666baae3e8633 100644 (file)
@@ -74,17 +74,30 @@ loops that truncate the stream.
                   yield element
 
 
+.. function:: itertools.chain.from_iterable(iterable)
+
+   Alternate constructor for :func:`chain`.  Gets chained inputs from a 
+   single iterable argument that is evaluated lazily.  Equivalent to::
+
+      @classmethod
+      def from_iterable(iterables):
+          for it in iterables:
+              for element in it:
+                  yield element
+
+   .. versionadded:: 2.6
+
 .. function:: combinations(iterable, r)
 
    Return successive *r* length combinations of elements in the *iterable*.
 
-   Combinations are emitted in lexicographic sort order.  So, if the 
+   Combinations are emitted in lexicographic sort order.  So, if the 
    input *iterable* is sorted, the combination tuples will be produced
    in sorted order.  
 
    Elements are treated as unique based on their position, not on their
    value.  So if the input elements are unique, there will be no repeat
-   values within a single combination.
+   values in each combination.
 
    Each result tuple is ordered to match the input order.  So, every
    combination is a subsequence of the input *iterable*.
@@ -327,6 +340,26 @@ loops that truncate the stream.
    example :func:`islice` or :func:`takewhile`).
 
 
+.. function:: permutations(iterable[, r])
+
+   Return successive *r* length permutations of elements in the *iterable*.
+
+   If *r* is not specified or is ``None``, then *r* defaults to the length
+   of the *iterable* and all possible full-length permutations 
+   are generated.
+
+   Permutations are emitted in lexicographic sort order.  So, if the 
+   input *iterable* is sorted, the permutation tuples will be produced
+   in sorted order.  
+
+   Elements are treated as unique based on their position, not on their
+   value.  So if the input elements are unique, there will be no repeat
+   values in each permutation.
+
+   Example:  ``permutations(range(3),2) --> (1,2) (1,3) (2,1) (2,3) (3,1) (3,2)``
+
+   .. versionadded:: 2.6
+
 .. function:: product(*iterables[, repeat])
 
    Cartesian product of input iterables.
@@ -553,13 +586,13 @@ which incur interpreter overhead. ::
 
    def ncycles(seq, n):
        "Returns the sequence elements n times"
-       return chain(*repeat(seq, n))
+       return chain.from_iterable(repeat(seq, n))
 
    def dotproduct(vec1, vec2):
        return sum(imap(operator.mul, vec1, vec2))
 
    def flatten(listOfLists):
-       return list(chain(*listOfLists))
+       return list(chain.from_iterable(listOfLists))
 
    def repeatfunc(func, times=None, *args):
        """Repeat calls to func with specified arguments.
@@ -568,8 +601,7 @@ which incur interpreter overhead. ::
        """
        if times is None:
            return starmap(func, repeat(args))
-       else:
-           return starmap(func, repeat(args, times))
+       return starmap(func, repeat(args, times))
 
    def pairwise(iterable):
        "s -> (s0,s1), (s1,s2), (s2, s3), ..."
@@ -583,7 +615,7 @@ which incur interpreter overhead. ::
 
    def roundrobin(*iterables):
        "roundrobin('abc', 'd', 'ef') --> 'a', 'd', 'e', 'b', 'f', 'c'"
-       # Recipe contributed by George Sakkis
+       # Recipe credited to George Sakkis
        pending = len(iterables)
        nexts = cycle(iter(it).next for it in iterables)
        while pending:
@@ -595,8 +627,9 @@ which incur interpreter overhead. ::
                nexts = cycle(islice(nexts, pending))
 
    def powerset(iterable):
-       "powerset('ab') --> set([]), set(['b']), set(['a']), set(['a', 'b'])"
-       skip = object()
-       for t in product(*izip(repeat(skip), iterable)):
-           yield set(e for e in t if e is not skip)
+       "powerset('ab') --> set([]), set(['a']), set(['b']), set(['a', 'b'])"
+       # Recipe credited to Eric Raymond
+       pairs = [(2**i, x) for i, x in enumerate(iterable)]
+       for n in xrange(2**len(pairs)):
+           yield set(x for m, x in pairs if m&n)
 
index deedd4b77221ac142c4b60edbb7d01a38fda4550..beb0a392e0f4a97b02809cbf9229c5fc625951b9 100644 (file)
@@ -109,8 +109,9 @@ class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
         list.sort(key=lambda a: a.lower())
         f = StringIO()
         displaypath = cgi.escape(urllib.unquote(self.path))
-        f.write("<title>Directory listing for %s</title>\n" % displaypath)
-        f.write("<h2>Directory listing for %s</h2>\n" % displaypath)
+        f.write('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">')
+        f.write("<html>\n<title>Directory listing for %s</title>\n" % displaypath)
+        f.write("<body>\n<h2>Directory listing for %s</h2>\n" % displaypath)
         f.write("<hr>\n<ul>\n")
         for name in list:
             fullname = os.path.join(path, name)
@@ -124,7 +125,7 @@ class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
                 # Note: a link to a directory displays with @ and links with /
             f.write('<li><a href="%s">%s</a>\n'
                     % (urllib.quote(linkname), cgi.escape(displayname)))
-        f.write("</ul>\n<hr>\n")
+        f.write("</ul>\n<hr>\n</body>\n</html>\n")
         length = f.tell()
         f.seek(0)
         self.send_response(200)
index 9c5d4c2b7162d72b23aeac45ed5e09a9a7ed9a40..47d87285f6b1c38d5afd94e793e373e084697ba6 100644 (file)
@@ -440,18 +440,30 @@ class ForkingMixIn:
 
     def collect_children(self):
         """Internal routine to wait for children that have exited."""
-        while self.active_children:
-            if len(self.active_children) < self.max_children:
-                options = os.WNOHANG
-            else:
-                # If the maximum number of children are already
-                # running, block while waiting for a child to exit
-                options = 0
+        if self.active_children is None: return
+        while len(self.active_children) >= self.max_children:
+            # XXX: This will wait for any child process, not just ones
+            # spawned by this library. This could confuse other
+            # libraries that expect to be able to wait for their own
+            # children.
             try:
-                pid, status = os.waitpid(0, options)
+                pid, status = os.waitpid(0, options=0)
             except os.error:
                 pid = None
-            if not pid: break
+            if pid not in self.active_children: continue
+            self.active_children.remove(pid)
+
+        # XXX: This loop runs more system calls than it ought
+        # to. There should be a way to put the active_children into a
+        # process group and then use os.waitpid(-pgid) to wait for any
+        # of that set, but I couldn't find a way to allocate pgids
+        # that couldn't collide.
+        for child in self.active_children:
+            try:
+                pid, status = os.waitpid(child, os.WNOHANG)
+            except os.error:
+                pid = None
+            if not pid: continue
             try:
                 self.active_children.remove(pid)
             except ValueError as e:
index 25734fdf4a220ca61c1cb6ca79f9999a2fb6bab9..658056c968401ce3811dc156d900580860588b14 100644 (file)
@@ -2,6 +2,7 @@
 Test suite for SocketServer.py.
 """
 
+import contextlib
 import errno
 import imp
 import os
@@ -109,6 +110,18 @@ class ServerThread(threading.Thread):
         if verbose: print("thread: done")
 
 
+@contextlib.contextmanager
+def simple_subprocess(testcase):
+    pid = os.fork()
+    if pid == 0:
+        # Don't throw an exception; it would be caught by the test harness.
+        os._exit(72)
+    yield None
+    pid2, status = os.waitpid(pid, 0)
+    testcase.assertEquals(pid2, pid)
+    testcase.assertEquals(72 << 8, status)
+
+
 class SocketServerTest(unittest.TestCase):
     """Test all socket servers."""
 
@@ -211,10 +224,11 @@ class SocketServerTest(unittest.TestCase):
                         self.stream_examine)
 
     if HAVE_FORKING:
-        def test_ThreadingTCPServer(self):
-            self.run_server(SocketServer.ForkingTCPServer,
-                            SocketServer.StreamRequestHandler,
-                            self.stream_examine)
+        def test_ForkingTCPServer(self):
+            with simple_subprocess(self):
+                self.run_server(SocketServer.ForkingTCPServer,
+                                SocketServer.StreamRequestHandler,
+                                self.stream_examine)
 
     if HAVE_UNIX_SOCKETS:
         def test_UnixStreamServer(self):
@@ -229,9 +243,10 @@ class SocketServerTest(unittest.TestCase):
 
         if HAVE_FORKING:
             def test_ForkingUnixStreamServer(self):
-                self.run_server(ForkingUnixStreamServer,
-                                SocketServer.StreamRequestHandler,
-                                self.stream_examine)
+                with simple_subprocess(self):
+                    self.run_server(ForkingUnixStreamServer,
+                                    SocketServer.StreamRequestHandler,
+                                    self.stream_examine)
 
     def test_UDPServer(self):
         self.run_server(SocketServer.UDPServer,
@@ -245,9 +260,10 @@ class SocketServerTest(unittest.TestCase):
 
     if HAVE_FORKING:
         def test_ForkingUDPServer(self):
-            self.run_server(SocketServer.ForkingUDPServer,
-                            SocketServer.DatagramRequestHandler,
-                            self.dgram_examine)
+            with simple_subprocess(self):
+                self.run_server(SocketServer.ForkingUDPServer,
+                                SocketServer.DatagramRequestHandler,
+                                self.dgram_examine)
 
     # Alas, on Linux (at least) recvfrom() doesn't return a meaningful
     # client address so this cannot work:
index 20517fc519e721d2bc38c25e2c7c09f9c79af3e5..aa320308748e2cf3d4fd5a2071b6d0ee3d082810 100644 (file)
@@ -37,6 +37,10 @@ product_codes = {
     '2.5.1150':'{31800004-6386-4999-a519-518f2d78d8f0}', # 2.5.1
     '2.5.2150':'{6304a7da-1132-4e91-a343-a296269eab8a}', # 2.5.2c1
     '2.5.2150':'{6b976adf-8ae8-434e-b282-a06c7f624d2f}', # 2.5.2
+    '2.6.101': '{0ba82e1b-52fd-4e03-8610-a6c76238e8a8}', # 2.6a1
+    '2.6.102': '{3b27e16c-56db-4570-a2d3-e9a26180c60b}', # 2.6a2
+    '2.6.103': '{cd06a9c5-bde5-4bd7-9874-48933997122a}', # 2.6a3
+    '2.6.104': '{dc6ed634-474a-4a50-a547-8de4b7491e53}', # 2.6a4
     '3.0.101': '{8554263a-3242-4857-9359-aa87bc2c58c2}', # 3.0a1
     '3.0.102': '{692d6e2c-f0ac-40b8-a133-7191aeeb67f9}', # 3.0a2
     '3.0.103': '{49cb2995-751a-4753-be7a-d0b1bb585e06}', # 3.0a3