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

Merged revisions...

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.
........
parent 493bfe92
...@@ -74,17 +74,30 @@ loops that truncate the stream. ...@@ -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. ...@@ -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. :: ...@@ -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. :: ...@@ -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. :: ...@@ -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. :: ...@@ -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 @@ class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): ...@@ -109,8 +109,9 @@ class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
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 @@ class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): ...@@ -124,7 +125,7 @@ class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
# 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: ...@@ -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 @@ ...@@ -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 ServerThread(threading.Thread): ...@@ -109,6 +110,18 @@ class ServerThread(threading.Thread):
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 @@ class SocketServerTest(unittest.TestCase): ...@@ -211,10 +224,11 @@ class SocketServerTest(unittest.TestCase):
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 @@ class SocketServerTest(unittest.TestCase): ...@@ -229,9 +243,10 @@ class SocketServerTest(unittest.TestCase):
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 @@ class SocketServerTest(unittest.TestCase): ...@@ -245,9 +260,10 @@ class SocketServerTest(unittest.TestCase):
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 @@ product_codes = { ...@@ -37,6 +37,10 @@ product_codes = {
'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
......
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