mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	Merged revisions 61038,61042-61045,61047,61050,61053,61055-61056,61061-61062,61066,61068,61070,61083,61085,61092-61097,61103-61108 via svnmerge from
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. ........
This commit is contained in:
		
							parent
							
								
									9e7f1d2e96
								
							
						
					
					
						commit
						70e7ea23f1
					
				
					 5 changed files with 99 additions and 33 deletions
				
			
		|  | @ -74,17 +74,30 @@ loops that truncate the stream. | ||||||
|                   yield element |                   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) | .. function:: combinations(iterable, r) | ||||||
| 
 | 
 | ||||||
|    Return successive *r* length combinations of elements in the *iterable*. |    Return successive *r* length combinations of elements in the *iterable*. | ||||||
| 
 | 
 | ||||||
|    Combinations are emitted in a 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 |    input *iterable* is sorted, the combination tuples will be produced | ||||||
|    in sorted order.   |    in sorted order.   | ||||||
| 
 | 
 | ||||||
|    Elements are treated as unique based on their position, not on their |    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 |    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 |    Each result tuple is ordered to match the input order.  So, every | ||||||
|    combination is a subsequence of the input *iterable*. |    combination is a subsequence of the input *iterable*. | ||||||
|  | @ -327,6 +340,26 @@ loops that truncate the stream. | ||||||
|    example :func:`islice` or :func:`takewhile`). |    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]) | .. function:: product(*iterables[, repeat]) | ||||||
| 
 | 
 | ||||||
|    Cartesian product of input iterables. |    Cartesian product of input iterables. | ||||||
|  | @ -553,13 +586,13 @@ which incur interpreter overhead. :: | ||||||
| 
 | 
 | ||||||
|    def ncycles(seq, n): |    def ncycles(seq, n): | ||||||
|        "Returns the sequence elements n times" |        "Returns the sequence elements n times" | ||||||
|        return chain(*repeat(seq, n)) |        return chain.from_iterable(repeat(seq, n)) | ||||||
| 
 | 
 | ||||||
|    def dotproduct(vec1, vec2): |    def dotproduct(vec1, vec2): | ||||||
|        return sum(imap(operator.mul, vec1, vec2)) |        return sum(imap(operator.mul, vec1, vec2)) | ||||||
| 
 | 
 | ||||||
|    def flatten(listOfLists): |    def flatten(listOfLists): | ||||||
|        return list(chain(*listOfLists)) |        return list(chain.from_iterable(listOfLists)) | ||||||
| 
 | 
 | ||||||
|    def repeatfunc(func, times=None, *args): |    def repeatfunc(func, times=None, *args): | ||||||
|        """Repeat calls to func with specified arguments. |        """Repeat calls to func with specified arguments. | ||||||
|  | @ -568,8 +601,7 @@ which incur interpreter overhead. :: | ||||||
|        """ |        """ | ||||||
|        if times is None: |        if times is None: | ||||||
|            return starmap(func, repeat(args)) |            return starmap(func, repeat(args)) | ||||||
|        else: |        return starmap(func, repeat(args, times)) | ||||||
|            return starmap(func, repeat(args, times)) |  | ||||||
| 
 | 
 | ||||||
|    def pairwise(iterable): |    def pairwise(iterable): | ||||||
|        "s -> (s0,s1), (s1,s2), (s2, s3), ..." |        "s -> (s0,s1), (s1,s2), (s2, s3), ..." | ||||||
|  | @ -583,7 +615,7 @@ which incur interpreter overhead. :: | ||||||
| 
 | 
 | ||||||
|    def roundrobin(*iterables): |    def roundrobin(*iterables): | ||||||
|        "roundrobin('abc', 'd', 'ef') --> 'a', 'd', 'e', 'b', 'f', 'c'" |        "roundrobin('abc', 'd', 'ef') --> 'a', 'd', 'e', 'b', 'f', 'c'" | ||||||
|        # Recipe contributed by George Sakkis |        # Recipe credited to George Sakkis | ||||||
|        pending = len(iterables) |        pending = len(iterables) | ||||||
|        nexts = cycle(iter(it).next for it in iterables) |        nexts = cycle(iter(it).next for it in iterables) | ||||||
|        while pending: |        while pending: | ||||||
|  | @ -595,8 +627,9 @@ which incur interpreter overhead. :: | ||||||
|                nexts = cycle(islice(nexts, pending)) |                nexts = cycle(islice(nexts, pending)) | ||||||
| 
 | 
 | ||||||
|    def powerset(iterable): |    def powerset(iterable): | ||||||
|        "powerset('ab') --> set([]), set(['b']), set(['a']), set(['a', 'b'])" |        "powerset('ab') --> set([]), set(['a']), set(['b']), set(['a', 'b'])" | ||||||
|        skip = object() |        # Recipe credited to Eric Raymond | ||||||
|        for t in product(*izip(repeat(skip), iterable)): |        pairs = [(2**i, x) for i, x in enumerate(iterable)] | ||||||
|            yield set(e for e in t if e is not skip) |        for n in xrange(2**len(pairs)): | ||||||
|  |            yield set(x for m, x in pairs if m&n) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -109,8 +109,9 @@ def list_directory(self, path): | ||||||
|         list.sort(key=lambda a: a.lower()) |         list.sort(key=lambda a: a.lower()) | ||||||
|         f = StringIO() |         f = StringIO() | ||||||
|         displaypath = cgi.escape(urllib.unquote(self.path)) |         displaypath = cgi.escape(urllib.unquote(self.path)) | ||||||
|         f.write("<title>Directory listing for %s</title>\n" % displaypath) |         f.write('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">') | ||||||
|         f.write("<h2>Directory listing for %s</h2>\n" % displaypath) |         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") |         f.write("<hr>\n<ul>\n") | ||||||
|         for name in list: |         for name in list: | ||||||
|             fullname = os.path.join(path, name) |             fullname = os.path.join(path, name) | ||||||
|  | @ -124,7 +125,7 @@ def list_directory(self, path): | ||||||
|                 # Note: a link to a directory displays with @ and links with / |                 # Note: a link to a directory displays with @ and links with / | ||||||
|             f.write('<li><a href="%s">%s</a>\n' |             f.write('<li><a href="%s">%s</a>\n' | ||||||
|                     % (urllib.quote(linkname), cgi.escape(displayname))) |                     % (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() |         length = f.tell() | ||||||
|         f.seek(0) |         f.seek(0) | ||||||
|         self.send_response(200) |         self.send_response(200) | ||||||
|  |  | ||||||
|  | @ -440,18 +440,30 @@ class ForkingMixIn: | ||||||
| 
 | 
 | ||||||
|     def collect_children(self): |     def collect_children(self): | ||||||
|         """Internal routine to wait for children that have exited.""" |         """Internal routine to wait for children that have exited.""" | ||||||
|         while self.active_children: |         if self.active_children is None: return | ||||||
|             if len(self.active_children) < self.max_children: |         while len(self.active_children) >= self.max_children: | ||||||
|                 options = os.WNOHANG |             # XXX: This will wait for any child process, not just ones | ||||||
|             else: |             # spawned by this library. This could confuse other | ||||||
|                 # If the maximum number of children are already |             # libraries that expect to be able to wait for their own | ||||||
|                 # running, block while waiting for a child to exit |             # children. | ||||||
|                 options = 0 |  | ||||||
|             try: |             try: | ||||||
|                 pid, status = os.waitpid(0, options) |                 pid, status = os.waitpid(0, options=0) | ||||||
|             except os.error: |             except os.error: | ||||||
|                 pid = None |                 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: |             try: | ||||||
|                 self.active_children.remove(pid) |                 self.active_children.remove(pid) | ||||||
|             except ValueError as e: |             except ValueError as e: | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
| Test suite for SocketServer.py. | Test suite for SocketServer.py. | ||||||
| """ | """ | ||||||
| 
 | 
 | ||||||
|  | import contextlib | ||||||
| import errno | import errno | ||||||
| import imp | import imp | ||||||
| import os | import os | ||||||
|  | @ -109,6 +110,18 @@ class svrcls(MyMixinServer, self.__svrcls): | ||||||
|         if verbose: print("thread: done") |         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): | class SocketServerTest(unittest.TestCase): | ||||||
|     """Test all socket servers.""" |     """Test all socket servers.""" | ||||||
| 
 | 
 | ||||||
|  | @ -211,10 +224,11 @@ def test_ThreadingTCPServer(self): | ||||||
|                         self.stream_examine) |                         self.stream_examine) | ||||||
| 
 | 
 | ||||||
|     if HAVE_FORKING: |     if HAVE_FORKING: | ||||||
|         def test_ThreadingTCPServer(self): |         def test_ForkingTCPServer(self): | ||||||
|             self.run_server(SocketServer.ForkingTCPServer, |             with simple_subprocess(self): | ||||||
|                             SocketServer.StreamRequestHandler, |                 self.run_server(SocketServer.ForkingTCPServer, | ||||||
|                             self.stream_examine) |                                 SocketServer.StreamRequestHandler, | ||||||
|  |                                 self.stream_examine) | ||||||
| 
 | 
 | ||||||
|     if HAVE_UNIX_SOCKETS: |     if HAVE_UNIX_SOCKETS: | ||||||
|         def test_UnixStreamServer(self): |         def test_UnixStreamServer(self): | ||||||
|  | @ -229,9 +243,10 @@ def test_ThreadingUnixStreamServer(self): | ||||||
| 
 | 
 | ||||||
|         if HAVE_FORKING: |         if HAVE_FORKING: | ||||||
|             def test_ForkingUnixStreamServer(self): |             def test_ForkingUnixStreamServer(self): | ||||||
|                 self.run_server(ForkingUnixStreamServer, |                 with simple_subprocess(self): | ||||||
|                                 SocketServer.StreamRequestHandler, |                     self.run_server(ForkingUnixStreamServer, | ||||||
|                                 self.stream_examine) |                                     SocketServer.StreamRequestHandler, | ||||||
|  |                                     self.stream_examine) | ||||||
| 
 | 
 | ||||||
|     def test_UDPServer(self): |     def test_UDPServer(self): | ||||||
|         self.run_server(SocketServer.UDPServer, |         self.run_server(SocketServer.UDPServer, | ||||||
|  | @ -245,9 +260,10 @@ def test_ThreadingUDPServer(self): | ||||||
| 
 | 
 | ||||||
|     if HAVE_FORKING: |     if HAVE_FORKING: | ||||||
|         def test_ForkingUDPServer(self): |         def test_ForkingUDPServer(self): | ||||||
|             self.run_server(SocketServer.ForkingUDPServer, |             with simple_subprocess(self): | ||||||
|                             SocketServer.DatagramRequestHandler, |                 self.run_server(SocketServer.ForkingUDPServer, | ||||||
|                             self.dgram_examine) |                                 SocketServer.DatagramRequestHandler, | ||||||
|  |                                 self.dgram_examine) | ||||||
| 
 | 
 | ||||||
|     # Alas, on Linux (at least) recvfrom() doesn't return a meaningful |     # Alas, on Linux (at least) recvfrom() doesn't return a meaningful | ||||||
|     # client address so this cannot work: |     # client address so this cannot work: | ||||||
|  |  | ||||||
|  | @ -37,6 +37,10 @@ | ||||||
|     '2.5.1150':'{31800004-6386-4999-a519-518f2d78d8f0}', # 2.5.1 |     '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':'{6304a7da-1132-4e91-a343-a296269eab8a}', # 2.5.2c1 | ||||||
|     '2.5.2150':'{6b976adf-8ae8-434e-b282-a06c7f624d2f}', # 2.5.2 |     '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.101': '{8554263a-3242-4857-9359-aa87bc2c58c2}', # 3.0a1 | ||||||
|     '3.0.102': '{692d6e2c-f0ac-40b8-a133-7191aeeb67f9}', # 3.0a2 |     '3.0.102': '{692d6e2c-f0ac-40b8-a133-7191aeeb67f9}', # 3.0a2 | ||||||
|     '3.0.103': '{49cb2995-751a-4753-be7a-d0b1bb585e06}', # 3.0a3 |     '3.0.103': '{49cb2995-751a-4753-be7a-d0b1bb585e06}', # 3.0a3 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Christian Heimes
						Christian Heimes