From 13925008dc11f2a235627dc8c0440c0ce99171d9 Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Wed, 16 Mar 2011 11:05:33 +0200 Subject: #11565: Fix several typos. Patch by Piotr Kasprzyk. --- Demo/turtle/tdemo_bytedesign.py | 2 +- Doc/includes/sqlite3/shared_cache.py | 2 +- Include/abstract.h | 4 ++-- Include/pymacconfig.h | 2 +- Lib/csv.py | 2 +- Lib/ctypes/test/test_arrays.py | 2 +- Lib/ctypes/test/test_init.py | 2 +- Lib/ctypes/test/test_numbers.py | 2 +- Lib/ctypes/test/test_win32.py | 2 +- Lib/difflib.py | 2 +- Lib/distutils/cmd.py | 2 +- Lib/distutils/cygwinccompiler.py | 2 +- Lib/distutils/tests/test_clean.py | 2 +- Lib/distutils/tests/test_install.py | 2 +- Lib/distutils/tests/test_sdist.py | 2 +- Lib/doctest.py | 4 ++-- Lib/email/header.py | 2 +- Lib/idlelib/FormatParagraph.py | 2 +- Lib/idlelib/extend.txt | 2 +- Lib/idlelib/macosxSupport.py | 4 ++-- Lib/lib2to3/fixes/fix_metaclass.py | 2 +- Lib/lib2to3/pgen2/conv.py | 4 ++-- Lib/lib2to3/pytree.py | 4 ++-- Lib/lib2to3/tests/data/py2_test_grammar.py | 2 +- Lib/lib2to3/tests/data/py3_test_grammar.py | 2 +- Lib/ntpath.py | 2 +- Lib/pickletools.py | 2 +- Lib/platform.py | 2 +- Lib/pstats.py | 2 +- Lib/subprocess.py | 2 +- Lib/test/pyclbr_input.py | 2 +- Lib/test/test_capi.py | 2 +- Lib/test/test_datetime.py | 2 +- Lib/test/test_decimal.py | 2 +- Lib/test/test_descr.py | 2 +- Lib/test/test_doctest.py | 10 +++++----- Lib/test/test_extcall.py | 2 +- Lib/test/test_float.py | 4 ++-- Lib/test/test_grammar.py | 2 +- Lib/test/test_httpservers.py | 2 +- Lib/test/test_iterlen.py | 4 ++-- Lib/test/test_itertools.py | 2 +- Lib/test/test_marshal.py | 2 +- Lib/test/test_math.py | 2 +- Lib/test/test_mmap.py | 2 +- Lib/test/test_multiprocessing.py | 4 ++-- Lib/test/test_pkg.py | 2 +- Lib/test/test_print.py | 2 +- Lib/test/test_strlit.py | 2 +- Lib/test/test_strptime.py | 2 +- Lib/test/test_struct.py | 2 +- Lib/test/test_syntax.py | 2 +- Lib/test/test_sys.py | 2 +- Lib/test/test_threading.py | 2 +- Lib/test/test_trace.py | 2 +- Lib/test/test_urllib.py | 2 +- Lib/test/test_warnings.py | 2 +- Lib/tkinter/test/test_ttk/test_functions.py | 2 +- Lib/tkinter/tix.py | 8 ++++---- Lib/tkinter/ttk.py | 2 +- Lib/turtle.py | 12 ++++++------ Lib/xml/dom/minicompat.py | 2 +- Lib/xml/dom/minidom.py | 2 +- Lib/xmlrpc/server.py | 2 +- Mac/BuildScript/build-installer.py | 2 +- Modules/_ctypes/_ctypes.c | 2 +- Modules/_ctypes/callbacks.c | 2 +- Modules/_ctypes/callproc.c | 2 +- Modules/_functoolsmodule.c | 2 +- Modules/_io/iobase.c | 2 +- Modules/_io/stringio.c | 2 +- Modules/_pickle.c | 2 +- Modules/_sqlite/connection.h | 2 +- Modules/cmathmodule.c | 2 +- Modules/socketmodule.c | 12 ++++++------ Modules/timemodule.c | 2 +- Modules/zipimport.c | 2 +- Modules/zlib/deflate.h | 2 +- Modules/zlib/gzio.c | 4 ++-- Objects/dictobject.c | 2 +- Objects/listobject.c | 2 +- Objects/longobject.c | 4 ++-- Objects/typeobject.c | 4 ++-- PC/bdist_wininst/extract.c | 4 ++-- PC/bdist_wininst/install.c | 4 ++-- PC/os2emx/dlfcn.c | 2 +- PC/os2emx/dlfcn.h | 2 +- Python/ceval.c | 4 ++-- Python/pystate.c | 2 +- Python/thread.c | 2 +- Tools/freeze/checkextensions_win32.py | 2 +- Tools/scripts/fixcid.py | 2 +- Tools/unicode/makeunicodedata.py | 2 +- setup.py | 4 ++-- 94 files changed, 126 insertions(+), 126 deletions(-) diff --git a/Demo/turtle/tdemo_bytedesign.py b/Demo/turtle/tdemo_bytedesign.py index 2e2ac62..85f2887 100644 --- a/Demo/turtle/tdemo_bytedesign.py +++ b/Demo/turtle/tdemo_bytedesign.py @@ -4,7 +4,7 @@ tdemo_bytedesign.py An example adapted from the example-suite -of PythonCard's turtle graphcis. +of PythonCard's turtle graphics. It's based on an article in BYTE magazine Problem Solving with Logo: Using Turtle diff --git a/Doc/includes/sqlite3/shared_cache.py b/Doc/includes/sqlite3/shared_cache.py index bf1d7b4..30e71c9 100644 --- a/Doc/includes/sqlite3/shared_cache.py +++ b/Doc/includes/sqlite3/shared_cache.py @@ -1,6 +1,6 @@ import sqlite3 # The shared cache is only available in SQLite versions 3.3.3 or later -# See the SQLite documentaton for details. +# See the SQLite documentation for details. sqlite3.enable_shared_cache(True) diff --git a/Include/abstract.h b/Include/abstract.h index e9d1729..bbc0092 100644 --- a/Include/abstract.h +++ b/Include/abstract.h @@ -466,7 +466,7 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/ arbitrary data. 0 is returned on success. buffer and buffer_len are only - set in case no error occurrs. Otherwise, -1 is returned and + set in case no error occurs. Otherwise, -1 is returned and an exception set. */ @@ -480,7 +480,7 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/ writable memory location in buffer of size buffer_len. 0 is returned on success. buffer and buffer_len are only - set in case no error occurrs. Otherwise, -1 is returned and + set in case no error occurs. Otherwise, -1 is returned and an exception set. */ diff --git a/Include/pymacconfig.h b/Include/pymacconfig.h index 9e058c1..9dd9317 100644 --- a/Include/pymacconfig.h +++ b/Include/pymacconfig.h @@ -55,7 +55,7 @@ # endif # if defined(__LP64__) - /* MacOSX 10.4 (the first release to suppport 64-bit code + /* MacOSX 10.4 (the first release to support 64-bit code * at all) only supports 64-bit in the UNIX layer. * Therefore surpress the toolbox-glue in 64-bit mode. */ diff --git a/Lib/csv.py b/Lib/csv.py index 59ec372..dbe6db7 100644 --- a/Lib/csv.py +++ b/Lib/csv.py @@ -270,7 +270,7 @@ class Sniffer: an all or nothing approach, so we allow for small variations in this number. 1) build a table of the frequency of each character on every line. - 2) build a table of freqencies of this frequency (meta-frequency?), + 2) build a table of frequencies of this frequency (meta-frequency?), e.g. 'x occurred 5 times in 10 rows, 6 times in 1000 rows, 7 times in 2 rows' 3) use the mode of the meta-frequency to determine the /expected/ diff --git a/Lib/ctypes/test/test_arrays.py b/Lib/ctypes/test/test_arrays.py index c0cdfd5..d11de28 100644 --- a/Lib/ctypes/test/test_arrays.py +++ b/Lib/ctypes/test/test_arrays.py @@ -37,7 +37,7 @@ class ArrayTestCase(unittest.TestCase): values = [ia[i] for i in range(len(init))] self.assertEqual(values, [0] * len(init)) - # Too many in itializers should be caught + # Too many initializers should be caught self.assertRaises(IndexError, int_array, *range(alen*2)) CharArray = ARRAY(c_char, 3) diff --git a/Lib/ctypes/test/test_init.py b/Lib/ctypes/test/test_init.py index 94928c8..75fad11 100644 --- a/Lib/ctypes/test/test_init.py +++ b/Lib/ctypes/test/test_init.py @@ -27,7 +27,7 @@ class InitTest(unittest.TestCase): self.assertEqual((y.x.a, y.x.b), (0, 0)) self.assertEqual(y.x.new_was_called, False) - # But explicitely creating an X structure calls __new__ and __init__, of course. + # But explicitly creating an X structure calls __new__ and __init__, of course. x = X() self.assertEqual((x.a, x.b), (9, 12)) self.assertEqual(x.new_was_called, True) diff --git a/Lib/ctypes/test/test_numbers.py b/Lib/ctypes/test/test_numbers.py index 24d7293..244dbaf 100644 --- a/Lib/ctypes/test/test_numbers.py +++ b/Lib/ctypes/test/test_numbers.py @@ -157,7 +157,7 @@ class NumberTestCase(unittest.TestCase): def test_int_from_address(self): from array import array for t in signed_types + unsigned_types: - # the array module doesn't suppport all format codes + # the array module doesn't support all format codes # (no 'q' or 'Q') try: array(t._type_) diff --git a/Lib/ctypes/test/test_win32.py b/Lib/ctypes/test/test_win32.py index 5dedd9f..2534a74 100644 --- a/Lib/ctypes/test/test_win32.py +++ b/Lib/ctypes/test/test_win32.py @@ -17,7 +17,7 @@ if sys.platform == "win32" and sizeof(c_void_p) == sizeof(c_int): # ValueError: Procedure probably called with not enough arguments (4 bytes missing) self.assertRaises(ValueError, IsWindow) - # This one should succeeed... + # This one should succeed... self.assertEqual(0, IsWindow(0)) # ValueError: Procedure probably called with too many arguments (8 bytes in excess) diff --git a/Lib/difflib.py b/Lib/difflib.py index 264860e..24a58a6 100644 --- a/Lib/difflib.py +++ b/Lib/difflib.py @@ -1712,7 +1712,7 @@ class HtmlDiff(object): line = line.replace(' ','\0') # expand tabs into spaces line = line.expandtabs(self._tabsize) - # relace spaces from expanded tabs back into tab characters + # replace spaces from expanded tabs back into tab characters # (we'll replace them with markup after we do differencing) line = line.replace(' ','\t') return line.replace('\0',' ').rstrip('\n') diff --git a/Lib/distutils/cmd.py b/Lib/distutils/cmd.py index ae4efc7..5b1d085 100644 --- a/Lib/distutils/cmd.py +++ b/Lib/distutils/cmd.py @@ -359,7 +359,7 @@ class Command: not self.force, dry_run=self.dry_run) def move_file (self, src, dst, level=1): - """Move a file respectin dry-run flag.""" + """Move a file respecting dry-run flag.""" return file_util.move_file(src, dst, dry_run=self.dry_run) def spawn(self, cmd, search_path=1, level=1): diff --git a/Lib/distutils/cygwinccompiler.py b/Lib/distutils/cygwinccompiler.py index 95fa3ed..536aa6b 100644 --- a/Lib/distutils/cygwinccompiler.py +++ b/Lib/distutils/cygwinccompiler.py @@ -155,7 +155,7 @@ class CygwinCCompiler(UnixCCompiler): self.dll_libraries = get_msvcr() def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts): - """Compiles the source by spawing GCC and windres if needed.""" + """Compiles the source by spawning GCC and windres if needed.""" if ext == '.rc' or ext == '.res': # gcc needs '.res' and '.rc' compiled to object files !!! try: diff --git a/Lib/distutils/tests/test_clean.py b/Lib/distutils/tests/test_clean.py index 649855f..eb8958b 100755 --- a/Lib/distutils/tests/test_clean.py +++ b/Lib/distutils/tests/test_clean.py @@ -39,7 +39,7 @@ class cleanTestCase(support.TempdirManager, self.assertTrue(not os.path.exists(path), '%s was not removed' % path) - # let's run the command again (should spit warnings but suceed) + # let's run the command again (should spit warnings but succeed) cmd.all = 1 cmd.ensure_finalized() cmd.run() diff --git a/Lib/distutils/tests/test_install.py b/Lib/distutils/tests/test_install.py index a76e3e7..ed69b0c 100644 --- a/Lib/distutils/tests/test_install.py +++ b/Lib/distutils/tests/test_install.py @@ -62,7 +62,7 @@ class InstallTestCase(support.TempdirManager, if sys.version < '2.6': return - # preparing the environement for the test + # preparing the environment for the test self.old_user_base = site.USER_BASE self.old_user_site = site.USER_SITE self.tmpdir = self.mkdtemp() diff --git a/Lib/distutils/tests/test_sdist.py b/Lib/distutils/tests/test_sdist.py index eaf39a4..c7dd47f 100644 --- a/Lib/distutils/tests/test_sdist.py +++ b/Lib/distutils/tests/test_sdist.py @@ -311,7 +311,7 @@ class SDistTestCase(PyPIRCCommandTestCase): # adding a file self.write_file((self.tmp_dir, 'somecode', 'doc2.txt'), '#') - # make sure build_py is reinitinialized, like a fresh run + # make sure build_py is reinitialized, like a fresh run build_py = dist.get_command_obj('build_py') build_py.finalized = False build_py.ensure_finalized() diff --git a/Lib/doctest.py b/Lib/doctest.py index 7554a1f..fae333e 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -1210,7 +1210,7 @@ class DocTestRunner: # Process each example. for examplenum, example in enumerate(test.examples): - # If REPORT_ONLY_FIRST_FAILURE is set, then supress + # If REPORT_ONLY_FIRST_FAILURE is set, then suppress # reporting after the first failure. quiet = (self.optionflags & REPORT_ONLY_FIRST_FAILURE and failures > 0) @@ -2132,7 +2132,7 @@ class DocTestCase(unittest.TestCase): caller can catch the errors and initiate post-mortem debugging. The DocTestCase provides a debug method that raises - UnexpectedException errors if there is an unexepcted + UnexpectedException errors if there is an unexpected exception: >>> test = DocTestParser().get_doctest('>>> raise KeyError\n42', diff --git a/Lib/email/header.py b/Lib/email/header.py index a391255..43220df 100644 --- a/Lib/email/header.py +++ b/Lib/email/header.py @@ -46,7 +46,7 @@ ecre = re.compile(r''' # For use with .match() fcre = re.compile(r'[\041-\176]+:$') -# Find a header embeded in a putative header value. Used to check for +# Find a header embedded in a putative header value. Used to check for # header injection attack. _embeded_header = re.compile(r'\n[^ \t]+:') diff --git a/Lib/idlelib/FormatParagraph.py b/Lib/idlelib/FormatParagraph.py index 02f96d4..6a5f9b5 100644 --- a/Lib/idlelib/FormatParagraph.py +++ b/Lib/idlelib/FormatParagraph.py @@ -54,7 +54,7 @@ class FormatParagraph: # If the block ends in a \n, we dont want the comment # prefix inserted after it. (Im not sure it makes sense to # reformat a comment block that isnt made of complete - # lines, but whatever!) Can't think of a clean soltution, + # lines, but whatever!) Can't think of a clean solution, # so we hack away block_suffix = "" if not newdata[-1]: diff --git a/Lib/idlelib/extend.txt b/Lib/idlelib/extend.txt index f5fb3e0..165e044 100644 --- a/Lib/idlelib/extend.txt +++ b/Lib/idlelib/extend.txt @@ -18,7 +18,7 @@ window. An IDLE extension class is instantiated with a single argument, `editwin', an EditorWindow instance. The extension cannot assume much -about this argument, but it is guarateed to have the following instance +about this argument, but it is guaranteed to have the following instance variables: text a Text instance (a widget) diff --git a/Lib/idlelib/macosxSupport.py b/Lib/idlelib/macosxSupport.py index 9b677e1..da519f7 100644 --- a/Lib/idlelib/macosxSupport.py +++ b/Lib/idlelib/macosxSupport.py @@ -15,8 +15,8 @@ def runningAsOSXApp(): def addOpenEventSupport(root, flist): """ - This ensures that the application will respont to open AppleEvents, which - makes is feaseable to use IDLE as the default application for python files. + This ensures that the application will respond to open AppleEvents, which + makes is feasible to use IDLE as the default application for python files. """ def doOpenFile(*args): for fn in args: diff --git a/Lib/lib2to3/fixes/fix_metaclass.py b/Lib/lib2to3/fixes/fix_metaclass.py index f924ace..7d4d002 100644 --- a/Lib/lib2to3/fixes/fix_metaclass.py +++ b/Lib/lib2to3/fixes/fix_metaclass.py @@ -48,7 +48,7 @@ def fixup_parse_tree(cls_node): """ for node in cls_node.children: if node.type == syms.suite: - # already in the prefered format, do nothing + # already in the preferred format, do nothing return # !%@#! oneliners have no suite node, we have to fake one up diff --git a/Lib/lib2to3/pgen2/conv.py b/Lib/lib2to3/pgen2/conv.py index 1d648d6..bf49762 100644 --- a/Lib/lib2to3/pgen2/conv.py +++ b/Lib/lib2to3/pgen2/conv.py @@ -51,7 +51,7 @@ class Converter(grammar.Grammar): self.finish_off() def parse_graminit_h(self, filename): - """Parse the .h file writen by pgen. (Internal) + """Parse the .h file written by pgen. (Internal) This file is a sequence of #define statements defining the nonterminals of the grammar as numbers. We build two tables @@ -82,7 +82,7 @@ class Converter(grammar.Grammar): return True def parse_graminit_c(self, filename): - """Parse the .c file writen by pgen. (Internal) + """Parse the .c file written by pgen. (Internal) The file looks as follows. The first two lines are always this: diff --git a/Lib/lib2to3/pytree.py b/Lib/lib2to3/pytree.py index 100232b..fa4942f3 100644 --- a/Lib/lib2to3/pytree.py +++ b/Lib/lib2to3/pytree.py @@ -658,8 +658,8 @@ class WildcardPattern(BasePattern): content: optional sequence of subsequences of patterns; if absent, matches one node; if present, each subsequence is an alternative [*] - min: optinal minumum number of times to match, default 0 - max: optional maximum number of times tro match, default HUGE + min: optional minimum number of times to match, default 0 + max: optional maximum number of times to match, default HUGE name: optional name assigned to this match [*] Thus, if content is [[a, b, c], [d, e], [f, g, h]] this is diff --git a/Lib/lib2to3/tests/data/py2_test_grammar.py b/Lib/lib2to3/tests/data/py2_test_grammar.py index 17f9f4c..b5a4137 100644 --- a/Lib/lib2to3/tests/data/py2_test_grammar.py +++ b/Lib/lib2to3/tests/data/py2_test_grammar.py @@ -316,7 +316,7 @@ class GrammarTests(unittest.TestCase): ### simple_stmt: small_stmt (';' small_stmt)* [';'] x = 1; pass; del x def foo(): - # verify statments that end with semi-colons + # verify statements that end with semi-colons x = 1; pass; del x; foo() diff --git a/Lib/lib2to3/tests/data/py3_test_grammar.py b/Lib/lib2to3/tests/data/py3_test_grammar.py index 977f0b8..c0bf7f2 100644 --- a/Lib/lib2to3/tests/data/py3_test_grammar.py +++ b/Lib/lib2to3/tests/data/py3_test_grammar.py @@ -356,7 +356,7 @@ class GrammarTests(unittest.TestCase): ### simple_stmt: small_stmt (';' small_stmt)* [';'] x = 1; pass; del x def foo(): - # verify statments that end with semi-colons + # verify statements that end with semi-colons x = 1; pass; del x; foo() diff --git a/Lib/ntpath.py b/Lib/ntpath.py index 9e4cff7..ae9dcf2 100644 --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -389,7 +389,7 @@ def expanduser(path): # - $varname is accepted. # - %varname% is accepted. # - varnames can be made out of letters, digits and the characters '_-' -# (though is not verifed in the ${varname} and %varname% cases) +# (though is not verified in the ${varname} and %varname% cases) # XXX With COMMAND.COM you can use any characters in a variable name, # XXX except '^|<>='. diff --git a/Lib/pickletools.py b/Lib/pickletools.py index dc40810..0af2fdb 100644 --- a/Lib/pickletools.py +++ b/Lib/pickletools.py @@ -1406,7 +1406,7 @@ opcodes = [ proto=0, doc="""Read an object from the memo and push it on the stack. - The index of the memo object to push is given by the newline-teriminated + The index of the memo object to push is given by the newline-terminated decimal string following. BINGET and LONG_BINGET are space-optimized versions. """), diff --git a/Lib/platform.py b/Lib/platform.py index 780301d..2294604 100755 --- a/Lib/platform.py +++ b/Lib/platform.py @@ -476,7 +476,7 @@ def _syscmd_ver(system='', release='', version='', info = pipe.read() if pipe.close(): raise os.error('command failed') - # XXX How can I supress shell errors from being written + # XXX How can I suppress shell errors from being written # to stderr ? except os.error as why: #print 'Command %s failed: %s' % (cmd,why) diff --git a/Lib/pstats.py b/Lib/pstats.py index db16628..566272d 100644 --- a/Lib/pstats.py +++ b/Lib/pstats.py @@ -71,7 +71,7 @@ class Stats: """ def __init__(self, *args, **kwds): - # I can't figure out how to explictly specify a stream keyword arg + # I can't figure out how to explicitly specify a stream keyword arg # with *args: # def __init__(self, *args, stream=sys.stdout): ... # so I use **kwds and sqauwk if something unexpected is passed in. diff --git a/Lib/subprocess.py b/Lib/subprocess.py index b8e3c0e..97792db 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -858,7 +858,7 @@ class Popen(object): except pywintypes.error as e: # Translate pywintypes.error to WindowsError, which is # a subclass of OSError. FIXME: We should really - # translate errno using _sys_errlist (or simliar), but + # translate errno using _sys_errlist (or similar), but # how can this be done from Python? raise WindowsError(*e.args) finally: diff --git a/Lib/test/pyclbr_input.py b/Lib/test/pyclbr_input.py index 8efc9de..19ccd62 100644 --- a/Lib/test/pyclbr_input.py +++ b/Lib/test/pyclbr_input.py @@ -19,7 +19,7 @@ class C (B): # XXX: This causes test_pyclbr.py to fail, but only because the # introspection-based is_method() code in the test can't - # distinguish between this and a geniune method function like m(). + # distinguish between this and a genuine method function like m(). # The pyclbr.py module gets this right as it parses the text. # #f = f diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py index 0460679..3f1d63c 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -106,7 +106,7 @@ class TestPendingCalls(unittest.TestCase): context.event.set() def test_pendingcalls_non_threaded(self): - #again, just using the main thread, likely they will all be dispathced at + #again, just using the main thread, likely they will all be dispatched at #once. It is ok to ask for too many, because we loop until we find a slot. #the loop can be interrupted to dispatch. #there are only 32 dispatch slots, so we go for twice that! diff --git a/Lib/test/test_datetime.py b/Lib/test/test_datetime.py index d983d6e..ea1e4d5 100644 --- a/Lib/test/test_datetime.py +++ b/Lib/test/test_datetime.py @@ -3120,7 +3120,7 @@ class TestTimezoneConversions(unittest.TestCase): self.assertEqual(dt, there_and_back) # Because we have a redundant spelling when DST begins, there is - # (unforunately) an hour when DST ends that can't be spelled at all in + # (unfortunately) an hour when DST ends that can't be spelled at all in # local time. When DST ends, the clock jumps from 1:59 back to 1:00 # again. The hour 1:MM DST has no spelling then: 1:MM is taken to be # standard time. 1:MM DST == 0:MM EST, but 0:MM is taken to be diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py index 9467191..ec381e4 100644 --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -225,7 +225,7 @@ class DecimalTest(unittest.TestCase): try: t = self.eval_line(line) except DecimalException as exception: - #Exception raised where there shoudn't have been one. + #Exception raised where there shouldn't have been one. self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line) return diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 6b9e30d..bd88f45 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -3976,7 +3976,7 @@ order (MRO) for bases """ except TypeError: pass else: - self.fail("Carlo Verre __setattr__ suceeded!") + self.fail("Carlo Verre __setattr__ succeeded!") try: object.__delattr__(str, "lower") except TypeError: diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py index 0cb4f18..de85758 100644 --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -1222,7 +1222,7 @@ marking, as well as interline differences. ? + ++ ^ TestResults(failed=1, attempted=1) -The REPORT_ONLY_FIRST_FAILURE supresses result output after the first +The REPORT_ONLY_FIRST_FAILURE suppresses result output after the first failing example: >>> def f(x): @@ -1252,7 +1252,7 @@ failing example: 2 TestResults(failed=3, attempted=5) -However, output from `report_start` is not supressed: +However, output from `report_start` is not suppressed: >>> doctest.DocTestRunner(verbose=True, optionflags=flags).run(test) ... # doctest: +ELLIPSIS @@ -2199,7 +2199,7 @@ We don't want `-v` in sys.argv for these tests. >>> doctest.master = None # Reset master. (Note: we'll be clearing doctest.master after each call to -`doctest.testfile`, to supress warnings about multiple tests with the +`doctest.testfile`, to suppress warnings about multiple tests with the same name.) Globals may be specified with the `globs` and `extraglobs` parameters: @@ -2235,7 +2235,7 @@ optional `module_relative` parameter: TestResults(failed=0, attempted=2) >>> doctest.master = None # Reset master. -Verbosity can be increased with the optional `verbose` paremter: +Verbosity can be increased with the optional `verbose` parameter: >>> doctest.testfile('test_doctest.txt', globs=globs, verbose=True) Trying: @@ -2272,7 +2272,7 @@ parameter: TestResults(failed=1, attempted=2) >>> doctest.master = None # Reset master. -The summary report may be supressed with the optional `report` +The summary report may be suppressed with the optional `report` parameter: >>> doctest.testfile('test_doctest.txt', report=False) diff --git a/Lib/test/test_extcall.py b/Lib/test/test_extcall.py index f1fff0a..ce9ac5e 100644 --- a/Lib/test/test_extcall.py +++ b/Lib/test/test_extcall.py @@ -227,7 +227,7 @@ Another helper function >>> Foo.method(1, *[2, 3]) 5 -A PyCFunction that takes only positional parameters shoud allow an +A PyCFunction that takes only positional parameters should allow an empty keyword dictionary to pass without a complaint, but raise a TypeError if te dictionary is not empty diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py index b5b6b65..2b250df 100644 --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -121,7 +121,7 @@ class GeneralFloatCases(unittest.TestCase): def test_float_with_comma(self): # set locale to something that doesn't use '.' for the decimal point # float must not accept the locale specific decimal point but - # it still has to accept the normal python syntac + # it still has to accept the normal python syntax import locale if not locale.localeconv()['decimal_point'] == ',': return @@ -243,7 +243,7 @@ class GeneralFloatCases(unittest.TestCase): def assertEqualAndEqualSign(self, a, b): # fail unless a == b and a and b have the same sign bit; # the only difference from assertEqual is that this test - # distingishes -0.0 and 0.0. + # distinguishes -0.0 and 0.0. self.assertEqual((a, copysign(1.0, a)), (b, copysign(1.0, b))) @requires_IEEE_754 diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py index ff8dc93..df224fd 100644 --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -356,7 +356,7 @@ class GrammarTests(unittest.TestCase): ### simple_stmt: small_stmt (';' small_stmt)* [';'] x = 1; pass; del x def foo(): - # verify statments that end with semi-colons + # verify statements that end with semi-colons x = 1; pass; del x; foo() diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py index 4f1ecff..2825697 100644 --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -83,7 +83,7 @@ class BaseTestCase(unittest.TestCase): return self.connection.getresponse() class BaseHTTPRequestHandlerTestCase(unittest.TestCase): - """Test the functionaility of the BaseHTTPServer.""" + """Test the functionality of the BaseHTTPServer.""" HTTPResponseMatch = re.compile(b'HTTP/1.[0-9]+ 200 OK') diff --git a/Lib/test/test_iterlen.py b/Lib/test/test_iterlen.py index cd92801..7469a31 100644 --- a/Lib/test/test_iterlen.py +++ b/Lib/test/test_iterlen.py @@ -20,11 +20,11 @@ This is the case for tuples, range objects, and itertools.repeat(). Some containers become temporarily immutable during iteration. This includes dicts, sets, and collections.deque. Their implementation is equally simple -though they need to permantently set their length to zero whenever there is +though they need to permanently set their length to zero whenever there is an attempt to iterate after a length mutation. The situation slightly more involved whenever an object allows length mutation -during iteration. Lists and sequence iterators are dynanamically updatable. +during iteration. Lists and sequence iterators are dynamically updatable. So, if a list is extended during iteration, the iterator will continue through the new items. If it shrinks to a point before the most recent iteration, then no further items are available and the length is reported at zero. diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py index a1875ff..da101e1 100644 --- a/Lib/test/test_itertools.py +++ b/Lib/test/test_itertools.py @@ -1490,7 +1490,7 @@ Samuele ... return chain(iterable, repeat(None)) >>> def ncycles(iterable, n): -... "Returns the seqeuence elements n times" +... "Returns the sequence elements n times" ... return chain(*repeat(iterable, n)) >>> def dotproduct(vec1, vec2): diff --git a/Lib/test/test_marshal.py b/Lib/test/test_marshal.py index 20f53b8..5e1cdd5 100644 --- a/Lib/test/test_marshal.py +++ b/Lib/test/test_marshal.py @@ -200,7 +200,7 @@ class BugsTestCase(unittest.TestCase): # >>> type(loads(dumps(Int()))) # for typ in (int, float, complex, tuple, list, dict, set, frozenset): - # Note: str sublclasses are not tested because they get handled + # Note: str subclasses are not tested because they get handled # by marshal's routines for objects supporting the buffer API. subtyp = type('subtyp', (typ,), {}) self.assertRaises(ValueError, marshal.dumps, subtyp()) diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py index e53bf2e..9a87d5d 100644 --- a/Lib/test/test_math.py +++ b/Lib/test/test_math.py @@ -697,7 +697,7 @@ class MathTests(unittest.TestCase): # the following tests have been commented out since they don't # really belong here: the implementation of ** for floats is - # independent of the implemention of math.pow + # independent of the implementation of math.pow #self.assertEqual(1**NAN, 1) #self.assertEqual(1**INF, 1) #self.assertEqual(1**NINF, 1) diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py index 0822cc1..7c51085 100644 --- a/Lib/test/test_mmap.py +++ b/Lib/test/test_mmap.py @@ -599,7 +599,7 @@ class MmapTests(unittest.TestCase): m2.close() m1.close() - # Test differnt tag + # Test different tag m1 = mmap.mmap(-1, len(data1), tagname="foo") m1[:] = data1 m2 = mmap.mmap(-1, len(data2), tagname="boo") diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py index aa0e1d8..d1ac4b7 100644 --- a/Lib/test/test_multiprocessing.py +++ b/Lib/test/test_multiprocessing.py @@ -780,7 +780,7 @@ class _TestEvent(BaseTestCase): event = self.Event() wait = TimingWrapper(event.wait) - # Removed temporaily, due to API shear, this does not + # Removed temporarily, due to API shear, this does not # work with threading._Event objects. is_set == isSet self.assertEqual(event.is_set(), False) @@ -1671,7 +1671,7 @@ class _TestFinalize(BaseTestCase): util.Finalize(None, conn.send, args=('STOP',), exitpriority=-100) - # call mutliprocessing's cleanup function then exit process without + # call multiprocessing's cleanup function then exit process without # garbage collecting locals util._exit_function() conn.close() diff --git a/Lib/test/test_pkg.py b/Lib/test/test_pkg.py index 2e293f4..4b48c04 100644 --- a/Lib/test/test_pkg.py +++ b/Lib/test/test_pkg.py @@ -55,7 +55,7 @@ class TestPkg(unittest.TestCase): support.modules_cleanup(*self.modules_before) cleanout(self.root) - # delete all modules concerning the tested hiearchy + # delete all modules concerning the tested hierarchy if self.pkgname: modules = [name for name in sys.modules if self.pkgname in name.split('.')] diff --git a/Lib/test/test_print.py b/Lib/test/test_print.py index f157bc7..b1ace4d 100644 --- a/Lib/test/test_print.py +++ b/Lib/test/test_print.py @@ -21,7 +21,7 @@ NotDefined = object() # A dispatch table all 8 combinations of providing # sep, end, and file # I use this machinery so that I'm not just passing default -# values to print, I'm eiher passing or not passing in the +# values to print, I'm either passing or not passing in the # arguments dispatch = { (False, False, False): diff --git a/Lib/test/test_strlit.py b/Lib/test/test_strlit.py index 23d96f8..9eb30e9 100644 --- a/Lib/test/test_strlit.py +++ b/Lib/test/test_strlit.py @@ -22,7 +22,7 @@ We have to test this with various file encodings. We also test it with exec()/eval(), which uses a different code path. This file is really about correct treatment of encodings and -backslashes. It doens't concern itself with issues like single +backslashes. It doesn't concern itself with issues like single vs. double quotes or singly- vs. triply-quoted strings: that's dealt with elsewhere (I assume). """ diff --git a/Lib/test/test_strptime.py b/Lib/test/test_strptime.py index e0263b4..f150546 100644 --- a/Lib/test/test_strptime.py +++ b/Lib/test/test_strptime.py @@ -541,7 +541,7 @@ class CacheTests(unittest.TestCase): self.assertIsNot(first_time_re, second_time_re) # Possible test locale is not supported while initial locale is. # If this is the case just suppress the exception and fall-through - # to the reseting to the original locale. + # to the resetting to the original locale. except locale.Error: pass # Make sure we don't trample on the locale setting once we leave the diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py index 0c19326..9ed3220 100644 --- a/Lib/test/test_struct.py +++ b/Lib/test/test_struct.py @@ -476,7 +476,7 @@ class StructTest(unittest.TestCase): test_string) def test_unpack_with_buffer(self): - # SF bug 1563759: struct.unpack doens't support buffer protocol objects + # SF bug 1563759: struct.unpack doesn't support buffer protocol objects data1 = array.array('B', b'\x12\x34\x56\x78') data2 = memoryview(b'\x12\x34\x56\x78') # XXX b'......XXXX......', 6, 4 for data in [data1, data2]: diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 2afbb61..202770a 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -237,7 +237,7 @@ SyntaxError: can't assign to function call Test continue in finally in weird combinations. -continue in for loop under finally shouuld be ok. +continue in for loop under finally should be ok. >>> def test(): ... try: diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index aa30923..11685a4 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -416,7 +416,7 @@ class SysModuleTest(unittest.TestCase): # provide too much opportunity for insane things to happen. # We don't want them in the interned dict and if they aren't # actually interned, we don't want to create the appearance - # that they are by allowing intern() to succeeed. + # that they are by allowing intern() to succeed. class S(str): def __hash__(self): return 123 diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index 2bf8437..f977a7f 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -543,7 +543,7 @@ class ThreadJoinOnShutdown(unittest.TestCase): # This acquires the lock and then waits until the child has forked # before returning, which will release the lock soon after. If # someone else tries to fix this test case by acquiring this lock - # before forking instead of reseting it, the test case will + # before forking instead of resetting it, the test case will # deadlock when it shouldn't. condition = w._block orig_acquire = condition.acquire diff --git a/Lib/test/test_trace.py b/Lib/test/test_trace.py index 07c5062..3697cbf 100644 --- a/Lib/test/test_trace.py +++ b/Lib/test/test_trace.py @@ -185,7 +185,7 @@ class TestRunExecCounts(unittest.TestCase): (self.my_py_filename, firstlineno + 4): 1, } - # When used through 'run', some other spurios counts are produced, like + # When used through 'run', some other spurious counts are produced, like # the settrace of threading, which we ignore, just making sure that the # counts fo traced_func_loop were right. # diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py index 2a9590a..422831e 100644 --- a/Lib/test/test_urllib.py +++ b/Lib/test/test_urllib.py @@ -1003,7 +1003,7 @@ class URLopener_Tests(unittest.TestCase): # Just commented them out. # Can't really tell why keep failing in windows and sparc. -# Everywhere else they work ok, but on those machines, someteimes +# Everywhere else they work ok, but on those machines, sometimes # fail in one of the tests, sometimes in other. I have a linux, and # the tests go ok. # If anybody has one of the problematic enviroments, please help! diff --git a/Lib/test/test_warnings.py b/Lib/test/test_warnings.py index 77f5be0..65a1a28 100644 --- a/Lib/test/test_warnings.py +++ b/Lib/test/test_warnings.py @@ -333,7 +333,7 @@ class WarnTests(unittest.TestCase): sys.argv = argv def test_warn_explicit_type_errors(self): - # warn_explicit() shoud error out gracefully if it is given objects + # warn_explicit() should error out gracefully if it is given objects # of the wrong types. # lineno is expected to be an integer. self.assertRaises(TypeError, self.module.warn_explicit, diff --git a/Lib/tkinter/test/test_ttk/test_functions.py b/Lib/tkinter/test/test_ttk/test_functions.py index f9b908e..df593cd 100644 --- a/Lib/tkinter/test/test_ttk/test_functions.py +++ b/Lib/tkinter/test/test_ttk/test_functions.py @@ -135,7 +135,7 @@ class InternalFunctionsTest(unittest.TestCase): # minimum acceptable for image type self.assertEqual(ttk._format_elemcreate('image', False, 'test'), ("test ", ())) - # specifiyng a state spec + # specifying a state spec self.assertEqual(ttk._format_elemcreate('image', False, 'test', ('', 'a')), ("test {} a", ())) # state spec with multiple states diff --git a/Lib/tkinter/tix.py b/Lib/tkinter/tix.py index 6458797..b105278 100644 --- a/Lib/tkinter/tix.py +++ b/Lib/tkinter/tix.py @@ -156,7 +156,7 @@ class tixCommand: return self.tk.call('tix', 'getimage', name) def tix_option_get(self, name): - """Gets the options manitained by the Tix + """Gets the options maintained by the Tix scheme mechanism. Available options include: active_bg active_fg bg @@ -561,7 +561,7 @@ class ButtonBox(TixWidget): class ComboBox(TixWidget): """ComboBox - an Entry field with a dropdown menu. The user can select a - choice by either typing in the entry subwdget or selecting from the + choice by either typing in the entry subwidget or selecting from the listbox subwidget. Subwidget Class @@ -854,7 +854,7 @@ class HList(TixWidget): """HList - Hierarchy display widget can be used to display any data that have a hierarchical structure, for example, file system directory trees. The list entries are indented and connected by branch lines - according to their places in the hierachy. + according to their places in the hierarchy. Subwidgets - None""" @@ -1509,7 +1509,7 @@ class TList(TixWidget): self.tk.call(self._w, 'yview', *args) class Tree(TixWidget): - """Tree - The tixTree widget can be used to display hierachical + """Tree - The tixTree widget can be used to display hierarchical data in a tree form. The user can adjust the view of the tree by opening or closing parts of the tree.""" diff --git a/Lib/tkinter/ttk.py b/Lib/tkinter/ttk.py index 1c7f11a..9213b62 100644 --- a/Lib/tkinter/ttk.py +++ b/Lib/tkinter/ttk.py @@ -707,7 +707,7 @@ class Combobox(Entry): textvariable, values, width """ # The "values" option may need special formatting, so leave to - # _format_optdict the responsability to format it + # _format_optdict the responsibility to format it if "values" in kw: kw["values"] = _format_optdict({'v': kw["values"]})[1] diff --git a/Lib/turtle.py b/Lib/turtle.py index 8146be6..0c439f1 100644 --- a/Lib/turtle.py +++ b/Lib/turtle.py @@ -1488,7 +1488,7 @@ class TurtleScreen(TurtleScreenBase): Optional arguments: canvwidth -- positive integer, new width of canvas in pixels canvheight -- positive integer, new height of canvas in pixels - bg -- colorstring or color-tupel, new backgroundcolor + bg -- colorstring or color-tuple, new backgroundcolor If no arguments are given, return current (canvaswidth, canvasheight) Do not alter the drawing window. To observe hidden parts of @@ -3242,9 +3242,9 @@ class RawTurtle(TPen, TNavigator): fill="", width=ps) # Turtle now at position old, self._position = old - ## if undo is done during crating a polygon, the last vertex - ## will be deleted. if the polygon is entirel deleted, - ## creatigPoly will be set to False. + ## if undo is done during creating a polygon, the last vertex + ## will be deleted. if the polygon is entirely deleted, + ## creatingPoly will be set to False. ## Polygons created before the last one will not be affected by undo() if self._creatingPoly: if len(self._poly) > 0: @@ -3796,7 +3796,7 @@ class _Screen(TurtleScreen): class Turtle(RawTurtle): - """RawTurtle auto-crating (scrolled) canvas. + """RawTurtle auto-creating (scrolled) canvas. When a Turtle object is created or a function derived from some Turtle method is called a TurtleScreen object is automatically created. @@ -3836,7 +3836,7 @@ def write_docstringdict(filename="turtle_docstringdict"): filename -- a string, used as filename default value is turtle_docstringdict - Has to be called explicitely, (not used by the turtle-graphics classes) + Has to be called explicitly, (not used by the turtle-graphics classes) The docstring dictionary will be written to the Python script .py It is intended to serve as a template for translation of the docstrings into different languages. diff --git a/Lib/xml/dom/minicompat.py b/Lib/xml/dom/minicompat.py index 2e6cc7e..62725c6 100644 --- a/Lib/xml/dom/minicompat.py +++ b/Lib/xml/dom/minicompat.py @@ -6,7 +6,7 @@ # # NodeList -- lightest possible NodeList implementation # -# EmptyNodeList -- lightest possible NodeList that is guarateed to +# EmptyNodeList -- lightest possible NodeList that is guaranteed to # remain empty (immutable) # # StringTypes -- tuple of defined string types diff --git a/Lib/xml/dom/minidom.py b/Lib/xml/dom/minidom.py index bc68cf8..d9c04d4 100644 --- a/Lib/xml/dom/minidom.py +++ b/Lib/xml/dom/minidom.py @@ -1893,7 +1893,7 @@ def _clone_node(node, deep, newOwnerDocument): e._call_user_data_handler(operation, n, entity) else: # Note the cloning of Document and DocumentType nodes is - # implemenetation specific. minidom handles those cases + # implementation specific. minidom handles those cases # directly in the cloneNode() methods. raise xml.dom.NotSupportedErr("Cannot clone node %s" % repr(node)) diff --git a/Lib/xmlrpc/server.py b/Lib/xmlrpc/server.py index 1cd45a9..24d8a6a 100644 --- a/Lib/xmlrpc/server.py +++ b/Lib/xmlrpc/server.py @@ -239,7 +239,7 @@ class SimpleXMLRPCDispatcher: marshalled data. For backwards compatibility, a dispatch function can be provided as an argument (see comment in SimpleXMLRPCRequestHandler.do_POST) but overriding the - existing method through subclassing is the prefered means + existing method through subclassing is the preferred means of changing method dispatch behavior. """ diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 08e64d9..02dbe13 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -354,7 +354,7 @@ def fileContents(fn): def runCommand(commandline): """ - Run a command and raise RuntimeError if it fails. Output is surpressed + Run a command and raise RuntimeError if it fails. Output is suppressed unless the command fails. """ fd = os.popen(commandline, 'r') diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 5643a65..04b07cc 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -3331,7 +3331,7 @@ PyCFuncPtr_new(PyTypeObject *type, PyObject *args, PyObject *kwds) /* XXX XXX This would allow to pass additional options. For COM method *implementations*, we would probably want different behaviour than in 'normal' callback functions: return a HRESULT if - an exception occurrs in the callback, and print the traceback not + an exception occurs in the callback, and print the traceback not only on the console, but also to OutputDebugString() or something like that. */ diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c index 5c82f77..490ada6 100644 --- a/Modules/_ctypes/callbacks.c +++ b/Modules/_ctypes/callbacks.c @@ -234,7 +234,7 @@ static void _CallPythonObject(void *mem, /* XXX XXX XX We have the problem that c_byte or c_short have dict->size of 1 resp. 4, but these parameters are pushed as sizeof(int) bytes. - BTW, the same problem occurrs when they are pushed as parameters + BTW, the same problem occurs when they are pushed as parameters */ } else if (dict) { /* Hm, shouldn't we use PyCData_AtAddress() or something like that instead? */ diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index d185fda..41a90f6 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -29,7 +29,7 @@ 4. _ctypes_callproc is then called with the 'callargs' tuple. _ctypes_callproc first allocates two arrays. The first is an array of 'struct argument' items, the - second array has 'void *' entried. + second array has 'void *' entries. 5. If 'converters' are present (converters is a sequence of argtypes' from_param methods), for each item in 'callargs' converter is called and the diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index 3437353..9aaa0f3 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -200,7 +200,7 @@ static PyGetSetDef partial_getsetlist[] = { __reduce__ by itself doesn't support getting kwargs in the unpickle operation so we define a __setstate__ that replaces all the information about the partial. If we only replaced part of it someone would use - it as a hook to do stange things. + it as a hook to do strange things. */ static PyObject * diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index dfc1a3a..84b560a 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -49,7 +49,7 @@ PyDoc_STRVAR(iobase_doc, "stream.\n" "\n" "IOBase also supports the :keyword:`with` statement. In this example,\n" - "fp is closed after the suite of the with statment is complete:\n" + "fp is closed after the suite of the with statement is complete:\n" "\n" "with open('spam.txt', 'r') as fp:\n" " fp.write('Spam and eggs!')\n"); diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c index 7e3730a..8d83f73 100644 --- a/Modules/_io/stringio.c +++ b/Modules/_io/stringio.c @@ -157,7 +157,7 @@ write_str(stringio *self, PyObject *obj) 0 lo string_size hi | |<---used--->|<----------available----------->| | | <--to pad-->|<---to write---> | - 0 buf positon + 0 buf position */ memset(self->buf + self->string_size, '\0', diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 4eb74ff..5102e24 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -4874,7 +4874,7 @@ initmodule(void) goto error; if (!PyDict_CheckExact(name_mapping_3to2)) { PyErr_Format(PyExc_RuntimeError, - "_compat_pickle.REVERSE_NAME_MAPPING shouldbe a dict, " + "_compat_pickle.REVERSE_NAME_MAPPING should be a dict, " "not %.200s", Py_TYPE(name_mapping_3to2)->tp_name); goto error; } diff --git a/Modules/_sqlite/connection.h b/Modules/_sqlite/connection.h index af414a0..fe05297 100644 --- a/Modules/_sqlite/connection.h +++ b/Modules/_sqlite/connection.h @@ -55,7 +55,7 @@ typedef struct /* None for autocommit, otherwise a PyString with the isolation level */ PyObject* isolation_level; - /* NULL for autocommit, otherwise a string with the BEGIN statment; will be + /* NULL for autocommit, otherwise a string with the BEGIN statement; will be * freed in connection destructor */ char* begin_statement; diff --git a/Modules/cmathmodule.c b/Modules/cmathmodule.c index 545e834..592b4ea 100644 --- a/Modules/cmathmodule.c +++ b/Modules/cmathmodule.c @@ -22,7 +22,7 @@ /* CM_LARGE_DOUBLE is used to avoid spurious overflow in the sqrt, log, inverse trig and inverse hyperbolic trig functions. Its log is used in the - evaluation of exp, cos, cosh, sin, sinh, tan, and tanh to avoid unecessary + evaluation of exp, cos, cosh, sin, sinh, tan, and tanh to avoid unnecessary overflow. */ diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 9bdca0c..b04d246 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -2151,7 +2151,7 @@ will allow before refusing new connections."); * This is the guts of the recv() and recv_into() methods, which reads into a * char buffer. If you have any inc/dec ref to do to the objects that contain * the buffer, do it in the caller. This function returns the number of bytes - * succesfully read. If there was an error, it returns -1. Note that it is + * successfully read. If there was an error, it returns -1. Note that it is * also possible that we return a number of bytes smaller than the request * bytes. */ @@ -2350,7 +2350,7 @@ See recv() for documentation about the flags."); * This is the guts of the recvfrom() and recvfrom_into() methods, which reads * into a char buffer. If you have any inc/def ref to do to the objects that * contain the buffer, do it in the caller. This function returns the number - * of bytes succesfully read. If there was an error, it returns -1. Note + * of bytes successfully read. If there was an error, it returns -1. Note * that it is also possible that we return a number of bytes smaller than the * request bytes. * @@ -2443,9 +2443,9 @@ sock_recvfrom(PySocketSockObject *s, PyObject *args) if (outlen != recvlen) { /* We did not read as many bytes as we anticipated, resize the - string if possible and be succesful. */ + string if possible and be successful. */ if (_PyBytes_Resize(&buf, outlen) < 0) - /* Oopsy, not so succesful after all. */ + /* Oopsy, not so successful after all. */ goto finally; } @@ -4162,7 +4162,7 @@ os_init(void) return 0; /* Failure */ #else - /* No need to initialise sockets with GCC/EMX */ + /* No need to initialize sockets with GCC/EMX */ return 1; /* Success */ #endif } @@ -4195,7 +4195,7 @@ PySocketModule_APIObject PySocketModuleAPI = "socket.py" which implements some additional functionality. The import of "_socket" may fail with an ImportError exception if os-specific initialization fails. On Windows, this does WINSOCK - initialization. When WINSOCK is initialized succesfully, a call to + initialization. When WINSOCK is initialized successfully, a call to WSACleanup() is scheduled to be made at exit time. */ diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 8c40d21..a24728a 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -706,7 +706,7 @@ time_mktime(PyObject *self, PyObject *tup) buf.tm_wday = -1; /* sentinel; original value ignored */ tt = mktime(&buf); /* Return value of -1 does not necessarily mean an error, but tm_wday - * cannot remain set to -1 if mktime succedded. */ + * cannot remain set to -1 if mktime succeeded. */ if (tt == (time_t)(-1) && buf.tm_wday == -1) { PyErr_SetString(PyExc_OverflowError, "mktime argument out of range"); diff --git a/Modules/zipimport.c b/Modules/zipimport.c index d3ca28d..fb5f42b 100644 --- a/Modules/zipimport.c +++ b/Modules/zipimport.c @@ -1049,7 +1049,7 @@ parse_dostime(int dostime, int dosdate) } /* Given a path to a .pyc or .pyo file in the archive, return the - modifictaion time of the matching .py file, or 0 if no source + modification time of the matching .py file, or 0 if no source is available. */ static time_t get_mtime_of_source(ZipImporter *self, char *path) diff --git a/Modules/zlib/deflate.h b/Modules/zlib/deflate.h index 05a5ab3..b16f7a7 100644 --- a/Modules/zlib/deflate.h +++ b/Modules/zlib/deflate.h @@ -188,7 +188,7 @@ typedef struct internal_state { int nice_match; /* Stop searching when current match exceeds this */ /* used by trees.c: */ - /* Didn't use ct_data typedef below to supress compiler warning */ + /* Didn't use ct_data typedef below to suppress compiler warning */ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ diff --git a/Modules/zlib/gzio.c b/Modules/zlib/gzio.c index 7e90f49..5cf50e0 100644 --- a/Modules/zlib/gzio.c +++ b/Modules/zlib/gzio.c @@ -256,7 +256,7 @@ int ZEXPORT gzsetparams (file, level, strategy) /* =========================================================================== Read a byte from a gz_stream; update next_in and avail_in. Return EOF for end of file. - IN assertion: the stream s has been sucessfully opened for reading. + IN assertion: the stream s has been successfully opened for reading. */ local int get_byte(s) gz_stream *s; @@ -281,7 +281,7 @@ local int get_byte(s) mode to transparent if the gzip magic header is not present; set s->err to Z_DATA_ERROR if the magic header is present but the rest of the header is incorrect. - IN assertion: the stream s has already been created sucessfully; + IN assertion: the stream s has already been created successfully; s->stream.avail_in is zero for the first time, but may be non-zero for concatenated .gz files. */ diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 9c17be7..8492c61 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -2070,7 +2070,7 @@ dict_new(PyTypeObject *type, PyObject *args, PyObject *kwds) assert(d->ma_table == NULL && d->ma_fill == 0 && d->ma_used == 0); INIT_NONZERO_DICT_SLOTS(d); d->ma_lookup = lookdict_unicode; - /* The object has been implicitely tracked by tp_alloc */ + /* The object has been implicitly tracked by tp_alloc */ if (type == &PyDict_Type) _PyObject_GC_UNTRACK(d); #ifdef SHOW_CONVERSION_COUNTS diff --git a/Objects/listobject.c b/Objects/listobject.c index e8b21f1..b3bb21d 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -11,7 +11,7 @@ /* Ensure ob_item has room for at least newsize elements, and set * ob_size to newsize. If newsize > ob_size on entry, the content * of the new slots at exit is undefined heap trash; it's the caller's - * responsiblity to overwrite them with sane values. + * responsibility to overwrite them with sane values. * The number of allocated elements may grow, shrink, or stay the same. * Failure is impossible if newsize <= self.allocated on entry, although * that partly relies on an assumption that the system realloc() never diff --git a/Objects/longobject.c b/Objects/longobject.c index 7af5caf..6f998ce 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -712,7 +712,7 @@ _PyLong_FromByteArray(const unsigned char* bytes, size_t n, is_signed = *pendbyte >= 0x80; /* Compute numsignificantbytes. This consists of finding the most - significant byte. Leading 0 bytes are insignficant if the number + significant byte. Leading 0 bytes are insignificant if the number is positive, and leading 0xff bytes if negative. */ { size_t i; @@ -3196,7 +3196,7 @@ long_true_divide(PyObject *a, PyObject *b) if (failed) return NULL; /* 'aexp' and 'bexp' were initialized to -1 to silence gcc-4.0.x, - but should really be set correctly after sucessful calls to + but should really be set correctly after successful calls to _PyLong_AsScaledDouble() */ assert(aexp >= 0 && bexp >= 0); diff --git a/Objects/typeobject.c b/Objects/typeobject.c index caa405b..310a56c 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1008,7 +1008,7 @@ subtype_dealloc(PyObject *self) self has a refcount of 0, and if gc ever gets its hands on it (which can happen if any weakref callback gets invoked), it looks like trash to gc too, and gc also tries to delete self - then. But we're already deleting self. Double dealloction is + then. But we're already deleting self. Double deallocation is a subtle disaster. Q. Why the bizarre (net-zero) manipulation of @@ -5872,7 +5872,7 @@ recurse_down_subclasses(PyTypeObject *type, PyObject *name, slots compete for the same descriptor (for example both sq_item and mp_subscript generate a __getitem__ descriptor). - In the latter case, the first slotdef entry encoutered wins. Since + In the latter case, the first slotdef entry encountered wins. Since slotdef entries are sorted by the offset of the slot in the PyHeapTypeObject, this gives us some control over disambiguating between competing slots: the members of PyHeapTypeObject are listed diff --git a/PC/bdist_wininst/extract.c b/PC/bdist_wininst/extract.c index fc2d2b9..c900f23 100644 --- a/PC/bdist_wininst/extract.c +++ b/PC/bdist_wininst/extract.c @@ -54,7 +54,7 @@ BOOL ensure_directory(char *pathname, char *new_part, NOTIFYPROC notify) return TRUE; } -/* XXX Should better explicitely specify +/* XXX Should better explicitly specify * uncomp_size and file_times instead of pfhdr! */ char *map_new_file(DWORD flags, char *filename, @@ -164,7 +164,7 @@ extract_file(char *dst, char *src, int method, int comp_size, zstream.avail_out = uncomp_size; /* Apparently an undocumented feature of zlib: Set windowsize - to negative values to supress the gzip header and be compatible with + to negative values to suppress the gzip header and be compatible with zip! */ result = TRUE; if (Z_OK != (x = inflateInit2(&zstream, -15))) { diff --git a/PC/bdist_wininst/install.c b/PC/bdist_wininst/install.c index 8601ddd..771922c 100644 --- a/PC/bdist_wininst/install.c +++ b/PC/bdist_wininst/install.c @@ -148,7 +148,7 @@ BOOL pyc_compile, pyo_compile; the permissions of the current user. */ HKEY hkey_root = (HKEY)-1; -BOOL success; /* Installation successfull? */ +BOOL success; /* Installation successful? */ char *failure_reason = NULL; HANDLE hBitmap; @@ -797,7 +797,7 @@ run_installscript(char *pathname, int argc, char **argv, char **pOutput) tempname = tempnam(NULL, NULL); // We use a static CRT while the Python version we load uses - // the CRT from one of various possibile DLLs. As a result we + // the CRT from one of various possible DLLs. As a result we // need to redirect the standard handles using the API rather // than the CRT. redirected = CreateFile( diff --git a/PC/os2emx/dlfcn.c b/PC/os2emx/dlfcn.c index 47c046c..ebda9cd 100644 --- a/PC/os2emx/dlfcn.c +++ b/PC/os2emx/dlfcn.c @@ -188,7 +188,7 @@ inv_handle: return NULL; } -/* free dynamicaly-linked library */ +/* free dynamically-linked library */ int dlclose(void *handle) { int rc; diff --git a/PC/os2emx/dlfcn.h b/PC/os2emx/dlfcn.h index 49abecf..f73ae69 100644 --- a/PC/os2emx/dlfcn.h +++ b/PC/os2emx/dlfcn.h @@ -42,7 +42,7 @@ void *dlopen(char *filename, int flags); /* return a pointer to the `symbol' in DLL */ void *dlsym(void *handle, char *symbol); -/* free dynamicaly-linked library */ +/* free dynamically-linked library */ int dlclose(void *handle); /* return a string describing last occurred dl error */ diff --git a/Python/ceval.c b/Python/ceval.c index f3433f1..d3ed871 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -27,7 +27,7 @@ typedef unsigned long long uint64; -/* PowerPC suppport. +/* PowerPC support. "__ppc__" appears to be the preprocessor definition to detect on OS X, whereas "__powerpc__" appears to be the correct one for Linux with GCC */ @@ -1169,7 +1169,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) if (--_Py_Ticker < 0) { if (*next_instr == SETUP_FINALLY) { /* Make the last opcode before - a try: finally: block uninterruptable. */ + a try: finally: block uninterruptible. */ goto fast_next_opcode; } _Py_Ticker = _Py_CheckInterval; diff --git a/Python/pystate.c b/Python/pystate.c index f1eb6d9..ea0d05d 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -503,7 +503,7 @@ _PyThread_CurrentFrames(void) /* for i in all interpreters: * for t in all of i's thread states: * if t's frame isn't NULL, map t's id to its frame - * Because these lists can mutute even when the GIL is held, we + * Because these lists can mutate even when the GIL is held, we * need to grab head_mutex for the duration. */ HEAD_LOCK(); diff --git a/Python/thread.c b/Python/thread.c index b4e3ad0..4a9b436 100644 --- a/Python/thread.c +++ b/Python/thread.c @@ -46,7 +46,7 @@ #endif /* Check if we're running on HP-UX and _SC_THREADS is defined. If so, then - enough of the Posix threads package is implimented to support python + enough of the Posix threads package is implemented to support python threads. This is valid for HP-UX 11.23 running on an ia64 system. If needed, add diff --git a/Tools/freeze/checkextensions_win32.py b/Tools/freeze/checkextensions_win32.py index ba3853c..a41542f 100644 --- a/Tools/freeze/checkextensions_win32.py +++ b/Tools/freeze/checkextensions_win32.py @@ -7,7 +7,7 @@ I dont consider it worth parsing the MSVC makefiles for compiler options. Even we get it just right, a specific freeze application may have specific compiler options anyway (eg, to enable or disable specific functionality) -So my basic stragtegy is: +So my basic strategy is: * Have some Windows INI files which "describe" one or more extension modules. (Freeze comes with a default one for all known modules - but you can specify diff --git a/Tools/scripts/fixcid.py b/Tools/scripts/fixcid.py index c9d3a29..b21a836 100755 --- a/Tools/scripts/fixcid.py +++ b/Tools/scripts/fixcid.py @@ -188,7 +188,7 @@ def fix(filename): except os.error as msg: err(filename + ': rename failed (' + str(msg) + ')\n') return 1 - # Return succes + # Return success return 0 # Tokenizing ANSI C (partly) diff --git a/Tools/unicode/makeunicodedata.py b/Tools/unicode/makeunicodedata.py index 52cb365..c35170c 100644 --- a/Tools/unicode/makeunicodedata.py +++ b/Tools/unicode/makeunicodedata.py @@ -866,7 +866,7 @@ class Hash: poly = size + poly break else: - raise AssertionError("ran out of polynominals") + raise AssertionError("ran out of polynomials") print(size, "slots in hash table") diff --git a/setup.py b/setup.py index 54400cb..51f8fde 100644 --- a/setup.py +++ b/setup.py @@ -993,8 +993,8 @@ class PyBuildExt(build_ext): if sys.platform == 'darwin': # In every directory on the search path search for a dynamic # library and then a static library, instead of first looking - # for dynamic libraries on the entiry path. - # This way a staticly linked custom sqlite gets picked up + # for dynamic libraries on the entire path. + # This way a statically linked custom sqlite gets picked up # before the dynamic library in /usr/lib. sqlite_extra_link_args = ('-Wl,-search_paths_first',) else: -- cgit v0.12 From 9465d424ec2c880486514736c321f589878fa870 Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Wed, 16 Mar 2011 12:48:54 +0200 Subject: Revert typo fixes in zlib/* --- Modules/zlib/deflate.h | 2 +- Modules/zlib/gzio.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/zlib/deflate.h b/Modules/zlib/deflate.h index b16f7a7..05a5ab3 100644 --- a/Modules/zlib/deflate.h +++ b/Modules/zlib/deflate.h @@ -188,7 +188,7 @@ typedef struct internal_state { int nice_match; /* Stop searching when current match exceeds this */ /* used by trees.c: */ - /* Didn't use ct_data typedef below to suppress compiler warning */ + /* Didn't use ct_data typedef below to supress compiler warning */ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ diff --git a/Modules/zlib/gzio.c b/Modules/zlib/gzio.c index 5cf50e0..7e90f49 100644 --- a/Modules/zlib/gzio.c +++ b/Modules/zlib/gzio.c @@ -256,7 +256,7 @@ int ZEXPORT gzsetparams (file, level, strategy) /* =========================================================================== Read a byte from a gz_stream; update next_in and avail_in. Return EOF for end of file. - IN assertion: the stream s has been successfully opened for reading. + IN assertion: the stream s has been sucessfully opened for reading. */ local int get_byte(s) gz_stream *s; @@ -281,7 +281,7 @@ local int get_byte(s) mode to transparent if the gzip magic header is not present; set s->err to Z_DATA_ERROR if the magic header is present but the rest of the header is incorrect. - IN assertion: the stream s has already been created successfully; + IN assertion: the stream s has already been created sucessfully; s->stream.avail_in is zero for the first time, but may be non-zero for concatenated .gz files. */ -- cgit v0.12 From 0b8753d24b9a37834c23faa1da705f4ed222d928 Mon Sep 17 00:00:00 2001 From: Ronald Oussoren Date: Wed, 16 Mar 2011 09:41:32 -0400 Subject: Issue #11569: use absolute path to the sysctl command in multiprocessing to ensure that it will be found regardless of the shell PATH. This ensures that multiprocessing.cpu_count works on default installs of MacOSX. --- Lib/multiprocessing/__init__.py | 5 ++++- Misc/ACKS | 1 + Misc/NEWS | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Lib/multiprocessing/__init__.py b/Lib/multiprocessing/__init__.py index 28a5eec..fdd012e 100644 --- a/Lib/multiprocessing/__init__.py +++ b/Lib/multiprocessing/__init__.py @@ -115,8 +115,11 @@ def cpu_count(): except (ValueError, KeyError): num = 0 elif 'bsd' in sys.platform or sys.platform == 'darwin': + comm = '/sbin/sysctl -n hw.ncpu' + if sys.platform == 'darwin': + comm = '/usr' + comm try: - with os.popen('sysctl -n hw.ncpu') as p: + with os.popen(comm) as p: num = int(p.read()) except ValueError: num = 0 diff --git a/Misc/ACKS b/Misc/ACKS index c7fd2ff..e5ee871 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -583,6 +583,7 @@ Tim Northover Joe Norton Neal Norwitz Michal Nowikowski +Steffen Daode Nurpmeso Nigel O'Brian Kevin O'Connor Tim O'Malley diff --git a/Misc/NEWS b/Misc/NEWS index c4627fa..d5c4699 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -40,6 +40,10 @@ Core and Builtins Library ------- +- Issue #11569: use absolute path to the sysctl command in multiprocessing to + ensure that it will be found regardless of the shell PATH. This ensures + that multiprocessing.cpu_count works on default installs of MacOSX. + - Issue #11501: disutils.archive_utils.make_zipfile no longer fails if zlib is not installed. Instead, the zipfile.ZIP_STORED compression is used to create the ZipFile. Patch by Natalia B. Bidart. -- cgit v0.12 From c1577902c62dd14e43ba37662a31d76addd4ac7e Mon Sep 17 00:00:00 2001 From: Ronald Oussoren Date: Wed, 16 Mar 2011 10:03:10 -0400 Subject: Fix typo in subprocess documentation. --- Doc/library/subprocess.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index 6ea3c10..4a12b76 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -387,7 +387,7 @@ All of the functions and methods that accept a *timeout* parameter, such as :func:`call` and :meth:`Popen.communicate` will raise :exc:`TimeoutExpired` if the timeout expires before the process exits. -Exceptions defined in this module all inherit from :ext:`SubprocessError`. +Exceptions defined in this module all inherit from :exc:`SubprocessError`. .. versionadded:: 3.3 The :exc:`SubprocessError` base class was added. -- cgit v0.12 From a78e4e6daf0b5623ce71966ef32a275ebce708fc Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 16 Mar 2011 10:29:19 -0500 Subject: correct patch ack (#11133) --- Misc/NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS b/Misc/NEWS index bd21c5c..ff5d749 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -41,7 +41,7 @@ Library ------- - Issue #11133: fix two cases where inspect.getattr_static can trigger code - execution. Patch by Daniel Urban. + execution. Patch by Andreas Stührk. - Issue #11569: use absolute path to the sysctl command in multiprocessing to ensure that it will be found regardless of the shell PATH. This ensures -- cgit v0.12 From ba102ec10d953af825e0da4c3cff02a701d3ca81 Mon Sep 17 00:00:00 2001 From: Ross Lagerwall Date: Wed, 16 Mar 2011 18:40:25 +0200 Subject: Issue #5870: Add subprocess.DEVNULL constant. --- Doc/library/subprocess.rst | 23 +++++++++++++++++------ Lib/subprocess.py | 23 ++++++++++++++++++++++- Lib/test/test_subprocess.py | 25 +++++++++++++++++++++++++ Misc/NEWS | 2 ++ 4 files changed, 66 insertions(+), 7 deletions(-) diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index 4a12b76..88eb784 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -125,12 +125,14 @@ This module defines one class called :class:`Popen`: *stdin*, *stdout* and *stderr* specify the executed programs' standard input, standard output and standard error file handles, respectively. Valid values - are :data:`PIPE`, an existing file descriptor (a positive integer), an - existing :term:`file object`, and ``None``. :data:`PIPE` indicates that a - new pipe to the child should be created. With ``None``, no redirection will - occur; the child's file handles will be inherited from the parent. Additionally, - *stderr* can be :data:`STDOUT`, which indicates that the stderr data from the - applications should be captured into the same file handle as for stdout. + are :data:`PIPE`, :data:`DEVNULL`, an existing file descriptor (a positive + integer), an existing :term:`file object`, and ``None``. :data:`PIPE` + indicates that a new pipe to the child should be created. :data:`DEVNULL` + indicates that the special file :data:`os.devnull` will be used. With ``None``, + no redirection will occur; the child's file handles will be inherited from + the parent. Additionally, *stderr* can be :data:`STDOUT`, which indicates + that the stderr data from the applications should be captured into the same + file handle as for stdout. If *preexec_fn* is set to a callable object, this object will be called in the child process just before the child is executed. @@ -229,6 +231,15 @@ This module defines one class called :class:`Popen`: Added context manager support. +.. data:: DEVNULL + + Special value that can be used as the *stdin*, *stdout* or *stderr* argument + to :class:`Popen` and indicates that the special file :data:`os.devnull` + will be used. + + .. versionadded:: 3.3 + + .. data:: PIPE Special value that can be used as the *stdin*, *stdout* or *stderr* argument diff --git a/Lib/subprocess.py b/Lib/subprocess.py index cc08945..0e15f10 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -431,7 +431,7 @@ else: return fds __all__ = ["Popen", "PIPE", "STDOUT", "call", "check_call", "getstatusoutput", - "getoutput", "check_output", "CalledProcessError"] + "getoutput", "check_output", "CalledProcessError", "DEVNULL"] if mswindows: from _subprocess import CREATE_NEW_CONSOLE, CREATE_NEW_PROCESS_GROUP @@ -456,6 +456,7 @@ def _cleanup(): PIPE = -1 STDOUT = -2 +DEVNULL = -3 def _eintr_retry_call(func, *args): @@ -800,6 +801,10 @@ class Popen(object): # Child is still running, keep us alive until we can wait on it. _active.append(self) + def _get_devnull(self): + if not hasattr(self, '_devnull'): + self._devnull = os.open(os.devnull, os.O_RDWR) + return self._devnull def communicate(self, input=None, timeout=None): """Interact with process: Send data to stdin. Read data from @@ -889,6 +894,8 @@ class Popen(object): p2cread, _ = _subprocess.CreatePipe(None, 0) elif stdin == PIPE: p2cread, p2cwrite = _subprocess.CreatePipe(None, 0) + elif stdin == DEVNULL: + p2cread = msvcrt.get_osfhandle(self._get_devnull()) elif isinstance(stdin, int): p2cread = msvcrt.get_osfhandle(stdin) else: @@ -902,6 +909,8 @@ class Popen(object): _, c2pwrite = _subprocess.CreatePipe(None, 0) elif stdout == PIPE: c2pread, c2pwrite = _subprocess.CreatePipe(None, 0) + elif stdout == DEVNULL: + c2pwrite = msvcrt.get_osfhandle(self._get_devnull()) elif isinstance(stdout, int): c2pwrite = msvcrt.get_osfhandle(stdout) else: @@ -917,6 +926,8 @@ class Popen(object): errread, errwrite = _subprocess.CreatePipe(None, 0) elif stderr == STDOUT: errwrite = c2pwrite + elif stderr == DEVNULL: + errwrite = msvcrt.get_osfhandle(self._get_devnull()) elif isinstance(stderr, int): errwrite = msvcrt.get_osfhandle(stderr) else: @@ -1026,6 +1037,8 @@ class Popen(object): c2pwrite.Close() if errwrite != -1: errwrite.Close() + if hasattr(self, '_devnull'): + os.close(self._devnull) # Retain the process handle, but close the thread handle self._child_created = True @@ -1159,6 +1172,8 @@ class Popen(object): pass elif stdin == PIPE: p2cread, p2cwrite = _create_pipe() + elif stdin == DEVNULL: + p2cread = self._get_devnull() elif isinstance(stdin, int): p2cread = stdin else: @@ -1169,6 +1184,8 @@ class Popen(object): pass elif stdout == PIPE: c2pread, c2pwrite = _create_pipe() + elif stdout == DEVNULL: + c2pwrite = self._get_devnull() elif isinstance(stdout, int): c2pwrite = stdout else: @@ -1181,6 +1198,8 @@ class Popen(object): errread, errwrite = _create_pipe() elif stderr == STDOUT: errwrite = c2pwrite + elif stderr == DEVNULL: + errwrite = self._get_devnull() elif isinstance(stderr, int): errwrite = stderr else: @@ -1374,6 +1393,8 @@ class Popen(object): os.close(c2pwrite) if errwrite != -1 and errread != -1: os.close(errwrite) + if hasattr(self, '_devnull'): + os.close(self._devnull) # Wait for exec to fail or succeed; possibly raising an # exception (limited in size) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 5f158b9..3156543 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -323,6 +323,31 @@ class ProcessTestCase(BaseTestCase): rc = subprocess.call([sys.executable, "-c", cmd], stdout=1) self.assertEqual(rc, 2) + def test_stdout_devnull(self): + p = subprocess.Popen([sys.executable, "-c", + 'for i in range(10240):' + 'print("x" * 1024)'], + stdout=subprocess.DEVNULL) + p.wait() + self.assertEqual(p.stdout, None) + + def test_stderr_devnull(self): + p = subprocess.Popen([sys.executable, "-c", + 'import sys\n' + 'for i in range(10240):' + 'sys.stderr.write("x" * 1024)'], + stderr=subprocess.DEVNULL) + p.wait() + self.assertEqual(p.stderr, None) + + def test_stdin_devnull(self): + p = subprocess.Popen([sys.executable, "-c", + 'import sys;' + 'sys.stdin.read(1)'], + stdin=subprocess.DEVNULL) + p.wait() + self.assertEqual(p.stdin, None) + def test_cwd(self): tmpdir = tempfile.gettempdir() # We cannot use os.path.realpath to canonicalize the path, diff --git a/Misc/NEWS b/Misc/NEWS index a5d1bfe..e3c0453 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -72,6 +72,8 @@ Core and Builtins Library ------- +- Issue #5870: Add `subprocess.DEVNULL` constant. + - Issue #11133: fix two cases where inspect.getattr_static can trigger code execution. Patch by Andreas Stührk. -- cgit v0.12 From abf202d798fec4cbe90a46d3fdba761ef6be0b85 Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Wed, 16 Mar 2011 13:52:20 -0400 Subject: Close #11548: Correctly handle format argument in shutil.unpack_archive --- Lib/shutil.py | 4 ++-- Lib/test/test_shutil.py | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Lib/shutil.py b/Lib/shutil.py index d47c67c..aafe04e 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -737,8 +737,8 @@ def unpack_archive(filename, extract_dir=None, format=None): except KeyError: raise ValueError("Unknown unpack format '{0}'".format(format)) - func = format_info[0] - func(filename, extract_dir, **dict(format_info[1])) + func = format_info[1] + func(filename, extract_dir, **dict(format_info[2])) else: # we need to look at the registered unpackers supported extensions format = _find_unpack_format(filename) diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index 30d9e07..8d003a8 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -645,6 +645,14 @@ class TestShutil(unittest.TestCase): diff = self._compare_dirs(tmpdir, tmpdir2) self.assertEqual(diff, []) + # and again, this time with the format specified + tmpdir3 = self.mkdtemp() + unpack_archive(filename, tmpdir3, format=format) + diff = self._compare_dirs(tmpdir, tmpdir3) + self.assertEqual(diff, []) + self.assertRaises(shutil.ReadError, unpack_archive, TESTFN) + self.assertRaises(ValueError, unpack_archive, TESTFN, format='xxx') + def test_unpack_registery(self): formats = get_unpack_formats() -- cgit v0.12 From 8ed3cf3a4bdaab9d338667e37a262eba2aa52920 Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Wed, 16 Mar 2011 14:05:35 -0400 Subject: Close #11560: Improve test coverage of shutil --- Lib/test/test_shutil.py | 100 +++++++++++++++++++++++++++++++----------------- 1 file changed, 64 insertions(+), 36 deletions(-) diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index 8d003a8..5252d4d 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -7,6 +7,7 @@ import sys import stat import os import os.path +import functools from test import support from test.support import TESTFN from os.path import splitdrive @@ -48,6 +49,21 @@ try: except ImportError: ZIP_SUPPORT = find_executable('zip') +def _fake_rename(*args, **kwargs): + # Pretend the destination path is on a different filesystem. + raise OSError() + +def mock_rename(func): + @functools.wraps(func) + def wrap(*args, **kwargs): + try: + builtin_rename = os.rename + os.rename = _fake_rename + return func(*args, **kwargs) + finally: + os.rename = builtin_rename + return wrap + class TestShutil(unittest.TestCase): def setUp(self): @@ -393,6 +409,41 @@ class TestShutil(unittest.TestCase): shutil.copytree(src_dir, dst_dir, symlinks=True) self.assertIn('test.txt', os.listdir(dst_dir)) + def _copy_file(self, method): + fname = 'test.txt' + tmpdir = self.mkdtemp() + self.write_file([tmpdir, fname]) + file1 = os.path.join(tmpdir, fname) + tmpdir2 = self.mkdtemp() + method(file1, tmpdir2) + file2 = os.path.join(tmpdir2, fname) + return (file1, file2) + + @unittest.skipUnless(hasattr(os, 'chmod'), 'requires os.chmod') + def test_copy(self): + # Ensure that the copied file exists and has the same mode bits. + file1, file2 = self._copy_file(shutil.copy) + self.assertTrue(os.path.exists(file2)) + self.assertEqual(os.stat(file1).st_mode, os.stat(file2).st_mode) + + @unittest.skipUnless(hasattr(os, 'chmod'), 'requires os.chmod') + @unittest.skipUnless(hasattr(os, 'chmod'), 'requires os.utime') + def test_copy2(self): + # Ensure that the copied file exists and has the same mode and + # modification time bits. + file1, file2 = self._copy_file(shutil.copy2) + self.assertTrue(os.path.exists(file2)) + file1_stat = os.stat(file1) + file2_stat = os.stat(file2) + self.assertEqual(file1_stat.st_mode, file2_stat.st_mode) + for attr in 'st_atime', 'st_mtime': + # The modification times may be truncated in the new file. + self.assertLessEqual(getattr(file1_stat, attr), + getattr(file2_stat, attr) + 1) + if hasattr(os, 'chflags') and hasattr(file1_stat, 'st_flags'): + self.assertEqual(getattr(file1_stat, 'st_flags'), + getattr(file2_stat, 'st_flags')) + @unittest.skipUnless(zlib, "requires zlib") def test_make_tarball(self): # creating something to tar @@ -403,6 +454,8 @@ class TestShutil(unittest.TestCase): self.write_file([tmpdir, 'sub', 'file3'], 'xxx') tmpdir2 = self.mkdtemp() + # force shutil to create the directory + os.rmdir(tmpdir2) unittest.skipUnless(splitdrive(tmpdir)[0] == splitdrive(tmpdir2)[0], "source and target should be on same drive") @@ -518,6 +571,8 @@ class TestShutil(unittest.TestCase): self.write_file([tmpdir, 'file2'], 'xxx') tmpdir2 = self.mkdtemp() + # force shutil to create the directory + os.rmdir(tmpdir2) base_name = os.path.join(tmpdir2, 'archive') _make_zipfile(base_name, tmpdir) @@ -688,20 +743,11 @@ class TestMove(unittest.TestCase): self.dst_dir = tempfile.mkdtemp() self.src_file = os.path.join(self.src_dir, filename) self.dst_file = os.path.join(self.dst_dir, filename) - # Try to create a dir in the current directory, hoping that it is - # not located on the same filesystem as the system tmp dir. - try: - self.dir_other_fs = tempfile.mkdtemp( - dir=os.path.dirname(__file__)) - self.file_other_fs = os.path.join(self.dir_other_fs, - filename) - except OSError: - self.dir_other_fs = None with open(self.src_file, "wb") as f: f.write(b"spam") def tearDown(self): - for d in (self.src_dir, self.dst_dir, self.dir_other_fs): + for d in (self.src_dir, self.dst_dir): try: if d: shutil.rmtree(d) @@ -730,21 +776,15 @@ class TestMove(unittest.TestCase): # Move a file inside an existing dir on the same filesystem. self._check_move_file(self.src_file, self.dst_dir, self.dst_file) + @mock_rename def test_move_file_other_fs(self): # Move a file to an existing dir on another filesystem. - if not self.dir_other_fs: - # skip - return - self._check_move_file(self.src_file, self.file_other_fs, - self.file_other_fs) + self.test_move_file() + @mock_rename def test_move_file_to_dir_other_fs(self): # Move a file to another location on another filesystem. - if not self.dir_other_fs: - # skip - return - self._check_move_file(self.src_file, self.dir_other_fs, - self.file_other_fs) + self.test_move_file_to_dir() def test_move_dir(self): # Move a dir to another location on the same filesystem. @@ -757,32 +797,20 @@ class TestMove(unittest.TestCase): except: pass + @mock_rename def test_move_dir_other_fs(self): # Move a dir to another location on another filesystem. - if not self.dir_other_fs: - # skip - return - dst_dir = tempfile.mktemp(dir=self.dir_other_fs) - try: - self._check_move_dir(self.src_dir, dst_dir, dst_dir) - finally: - try: - shutil.rmtree(dst_dir) - except: - pass + self.test_move_dir() def test_move_dir_to_dir(self): # Move a dir inside an existing dir on the same filesystem. self._check_move_dir(self.src_dir, self.dst_dir, os.path.join(self.dst_dir, os.path.basename(self.src_dir))) + @mock_rename def test_move_dir_to_dir_other_fs(self): # Move a dir inside an existing dir on another filesystem. - if not self.dir_other_fs: - # skip - return - self._check_move_dir(self.src_dir, self.dir_other_fs, - os.path.join(self.dir_other_fs, os.path.basename(self.src_dir))) + self.test_move_dir_to_dir() def test_existing_file_inside_dest_dir(self): # A file with the same name inside the destination dir already exists. -- cgit v0.12 From 296d9a6f85f4315ce492650dbca8de34c700c277 Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Wed, 16 Mar 2011 14:14:18 -0400 Subject: Add missing NEWS entries --- Misc/NEWS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Misc/NEWS b/Misc/NEWS index ff5d749..738b9c1 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -40,6 +40,9 @@ Core and Builtins Library ------- +- Issue #11548: shutil.unpack_archive now correctly handles the format + parameter. Patch by Evan Dandrea. + - Issue #11133: fix two cases where inspect.getattr_static can trigger code execution. Patch by Andreas Stührk. @@ -119,6 +122,9 @@ Tools/Demos Tests ----- +- Issue #11548: Improve test coverage of the shutil module. Patch by + Evan Dandrea. + - Issue #11554: Reactivated test_email_codecs. - Issue #11490: test_subprocess:test_leaking_fds_on_error no longer gives a -- cgit v0.12 From 454e11d874055f200bee84002447e50d5d467bf2 Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Wed, 16 Mar 2011 14:19:22 -0400 Subject: Fix typo in NEWS --- Misc/NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS b/Misc/NEWS index 738b9c1..b44650c 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -40,7 +40,7 @@ Core and Builtins Library ------- -- Issue #11548: shutil.unpack_archive now correctly handles the format +- Issue #11560: shutil.unpack_archive now correctly handles the format parameter. Patch by Evan Dandrea. - Issue #11133: fix two cases where inspect.getattr_static can trigger code -- cgit v0.12 From 7462fa654ba50b3ab19f3bea37816b5894990618 Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Wed, 16 Mar 2011 14:30:45 -0400 Subject: Backport improved test coverage for string.py --- Lib/test/test_pep292.py | 13 +++++++++++++ Lib/test/test_string.py | 24 ++++++++++++++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 3 +++ 4 files changed, 41 insertions(+) diff --git a/Lib/test/test_pep292.py b/Lib/test/test_pep292.py index a967649..119c7ea 100644 --- a/Lib/test/test_pep292.py +++ b/Lib/test/test_pep292.py @@ -42,6 +42,19 @@ class TestTemplate(unittest.TestCase): s = Template('$who likes $$') eq(s.substitute(dict(who='tim', what='ham')), 'tim likes $') + def test_invalid(self): + class MyPattern(Template): + pattern = r""" + (?: + (?P) | + (?P%(delim)s) | + @(?P%(id)s) | + @{(?P%(id)s)} + ) + """ + s = MyPattern('$') + self.assertRaises(ValueError, s.substitute, dict()) + def test_percents(self): eq = self.assertEqual s = Template('%(foo)s $foo ${foo}') diff --git a/Lib/test/test_string.py b/Lib/test/test_string.py index f46be63..a352ee3 100644 --- a/Lib/test/test_string.py +++ b/Lib/test/test_string.py @@ -112,6 +112,30 @@ class ModuleTest(unittest.TestCase): self.assertRaises(ValueError, fmt.format, "{0}", 10, 20, i=100) self.assertRaises(ValueError, fmt.format, "{i}", 10, 20, i=100) + def test_vformat_assert(self): + cls = string.Formatter() + kwargs = { + "i": 100 + } + self.assertRaises(ValueError, cls._vformat, + cls.format, "{0}", kwargs, set(), -2) + + def test_convert_field(self): + cls = string.Formatter() + self.assertEqual(cls.format("{0!s}", 'foo'), 'foo') + self.assertRaises(ValueError, cls.format, "{0!h}", 'foo') + + def test_get_field(self): + cls = string.Formatter() + class MyClass: + name = 'lumberjack' + x = MyClass() + self.assertEqual(cls.format("{0.name}", x), 'lumberjack') + + lookup = ["eggs", "and", "spam"] + self.assertEqual(cls.format("{0[2]}", lookup), 'spam') + + def test_main(): support.run_unittest(ModuleTest) diff --git a/Misc/ACKS b/Misc/ACKS index 5c1bdc5..1e2b83d 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -32,6 +32,7 @@ Oliver Andrich Ross Andrus Jon Anglin Éric Araujo +Alicia Arlen Jason Asbahr David Ascher Chris AtLee diff --git a/Misc/NEWS b/Misc/NEWS index b44650c..419b0d5 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -122,6 +122,9 @@ Tools/Demos Tests ----- +- Issue #11505: improves test coverage of string.py. Patch by Alicia + Arlen. + - Issue #11548: Improve test coverage of the shutil module. Patch by Evan Dandrea. -- cgit v0.12 From d3b7a55f543bf1c3ea6bcf10dd03b0919822f993 Mon Sep 17 00:00:00 2001 From: Jesus Cea Date: Wed, 16 Mar 2011 20:37:54 +0100 Subject: Close Issue 11570: Lib/test/test_distutils.py tries to mix 32 and 64 bits object files, doesn't obey LDFLAGS --- configure | 7 ++++--- configure.in | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/configure b/configure index 1ef57d0..90ad156 100755 --- a/configure +++ b/configure @@ -769,7 +769,8 @@ CFLAGS LDFLAGS LIBS CPPFLAGS -CPP' +CPP +CPPFLAGS' # Initialize some variables set by options. @@ -7551,8 +7552,8 @@ then IRIX*/6*) LDSHARED="ld ${SGI_ABI} -shared -all";; SunOS/5*) if test "$GCC" = "yes" - then LDSHARED='$(CC) -shared' - else LDSHARED='$(CC) -G'; + then LDSHARED='$(CC) -shared $(LDFLAGS)' + else LDSHARED='$(CC) -G $(LDFLAGS)'; fi ;; hp*|HP*) if test "$GCC" = "yes" diff --git a/configure.in b/configure.in index 3c6bd6f..9b7a5a7 100644 --- a/configure.in +++ b/configure.in @@ -1758,8 +1758,8 @@ then IRIX*/6*) LDSHARED="ld ${SGI_ABI} -shared -all";; SunOS/5*) if test "$GCC" = "yes" - then LDSHARED='$(CC) -shared' - else LDSHARED='$(CC) -G'; + then LDSHARED='$(CC) -shared $(LDFLAGS)' + else LDSHARED='$(CC) -G $(LDFLAGS)'; fi ;; hp*|HP*) if test "$GCC" = "yes" -- cgit v0.12 From 6d94bd470e3f4aa1dc7295b034553509ace2c654 Mon Sep 17 00:00:00 2001 From: R David Murray Date: Wed, 16 Mar 2011 15:52:22 -0400 Subject: #9298: restore proper folding of base64 encoded bodies. Patch by Yves Dorfsman. --- Lib/email/encoders.py | 2 +- Lib/email/test/test_email.py | 20 +++++++++++++++----- Misc/ACKS | 1 + Misc/NEWS | 4 ++++ 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/Lib/email/encoders.py b/Lib/email/encoders.py index 0ea441d..dfaac58 100644 --- a/Lib/email/encoders.py +++ b/Lib/email/encoders.py @@ -12,7 +12,7 @@ __all__ = [ ] -from base64 import b64encode as _bencode +from base64 import encodebytes as _bencode from quopri import encodestring as _encodestring diff --git a/Lib/email/test/test_email.py b/Lib/email/test/test_email.py index 0f28a9c..6a88b16 100644 --- a/Lib/email/test/test_email.py +++ b/Lib/email/test/test_email.py @@ -553,9 +553,18 @@ class TestMessageAPI(TestEmailBase): msg['Dummy'] = 'dummy\nX-Injected-Header: test' self.assertRaises(errors.HeaderParseError, msg.as_string) - # Test the email.encoders module class TestEncoders(unittest.TestCase): + + def test_EncodersEncode_base64(self): + with openfile('PyBanner048.gif', 'rb') as fp: + bindata = fp.read() + mimed = email.mime.image.MIMEImage(bindata) + base64ed = mimed.get_payload() + # the transfer-encoded body lines should all be <=76 characters + lines = base64ed.split('\n') + self.assertLessEqual(max([ len(x) for x in lines ]), 76) + def test_encode_empty_payload(self): eq = self.assertEqual msg = Message() @@ -1107,10 +1116,11 @@ class TestMIMEApplication(unittest.TestCase): def test_body(self): eq = self.assertEqual - bytes = b'\xfa\xfb\xfc\xfd\xfe\xff' - msg = MIMEApplication(bytes) - eq(msg.get_payload(), '+vv8/f7/') - eq(msg.get_payload(decode=True), bytes) + bytesdata = b'\xfa\xfb\xfc\xfd\xfe\xff' + msg = MIMEApplication(bytesdata) + # whitespace in the cte encoded block is RFC-irrelevant. + eq(msg.get_payload().strip(), '+vv8/f7/') + eq(msg.get_payload(decode=True), bytesdata) diff --git a/Misc/ACKS b/Misc/ACKS index e5ee871..5d9b198 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -202,6 +202,7 @@ Daniel Dittmar Jaromir Dolecek Ismail Donmez Dima Dorfman +Yves Dorfsman Cesar Douady Dean Draayer Fred L. Drake, Jr. diff --git a/Misc/NEWS b/Misc/NEWS index d5c4699..beb6ec1 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -40,6 +40,10 @@ Core and Builtins Library ------- +- Issue #9298: base64 bodies weren't being folded to line lengths less than 78, + which was a regression relative to Python2. Unlike Python2, the last line + of the folded body now ends with a carriage return. + - Issue #11569: use absolute path to the sysctl command in multiprocessing to ensure that it will be found regardless of the shell PATH. This ensures that multiprocessing.cpu_count works on default installs of MacOSX. -- cgit v0.12 From 2b228f0d9b3bc5ed99162b052c5eae515f55f3b8 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Wed, 16 Mar 2011 16:57:54 -0400 Subject: Include the timeout value in TimeoutExpired. This was the original intention, but it wasn't threaded all the way through due to 'endtime'. Also added a trivial assertion to get coverage of __str__. --- Lib/subprocess.py | 54 +++++++++++++++++++++++++++------------------ Lib/test/test_subprocess.py | 4 +++- 2 files changed, 35 insertions(+), 23 deletions(-) diff --git a/Lib/subprocess.py b/Lib/subprocess.py index 0e15f10..4a8adcf 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -371,8 +371,9 @@ class TimeoutExpired(SubprocessError): """This exception is raised when the timeout expires while waiting for a child process. """ - def __init__(self, cmd, output=None): + def __init__(self, cmd, timeout, output=None): self.cmd = cmd + self.timeout = timeout self.output = output def __str__(self): @@ -533,7 +534,7 @@ def check_output(*popenargs, timeout=None, **kwargs): except TimeoutExpired: process.kill() output, unused_err = process.communicate() - raise TimeoutExpired(process.args, output=output) + raise TimeoutExpired(process.args, timeout, output=output) retcode = process.poll() if retcode: raise CalledProcessError(retcode, process.args, output=output) @@ -844,7 +845,7 @@ class Popen(object): return (stdout, stderr) try: - stdout, stderr = self._communicate(input, endtime) + stdout, stderr = self._communicate(input, endtime, timeout) finally: self._communication_started = True @@ -865,12 +866,12 @@ class Popen(object): return endtime - time.time() - def _check_timeout(self, endtime): + def _check_timeout(self, endtime, orig_timeout): """Convenience for checking if a timeout has expired.""" if endtime is None: return if time.time() > endtime: - raise TimeoutExpired(self.args) + raise TimeoutExpired(self.args, orig_timeout) if mswindows: @@ -1063,9 +1064,11 @@ class Popen(object): return self.returncode - def wait(self, timeout=None): + def wait(self, timeout=None, endtime=None): """Wait for child process to terminate. Returns returncode attribute.""" + if endtime is not None: + timeout = self._remaining_time(endtime) if timeout is None: timeout = _subprocess.INFINITE else: @@ -1073,7 +1076,7 @@ class Popen(object): if self.returncode is None: result = _subprocess.WaitForSingleObject(self._handle, timeout) if result == _subprocess.WAIT_TIMEOUT: - raise TimeoutExpired(self.args) + raise TimeoutExpired(self.args, timeout) self.returncode = _subprocess.GetExitCodeProcess(self._handle) return self.returncode @@ -1083,7 +1086,7 @@ class Popen(object): fh.close() - def _communicate(self, input, endtime): + def _communicate(self, input, endtime, orig_timeout): # Start reader threads feeding into a list hanging off of this # object, unless they've already been started. if self.stdout and not hasattr(self, "_stdout_buff"): @@ -1489,13 +1492,18 @@ class Popen(object): def wait(self, timeout=None, endtime=None): """Wait for child process to terminate. Returns returncode attribute.""" - # If timeout was passed but not endtime, compute endtime in terms of - # timeout. - if endtime is None and timeout is not None: - endtime = time.time() + timeout if self.returncode is not None: return self.returncode - elif endtime is not None: + + # endtime is preferred to timeout. timeout is only used for + # printing. + if endtime is not None or timeout is not None: + if endtime is None: + endtime = time.time() + timeout + elif timeout is None: + timeout = self._remaining_time(endtime) + + if endtime is not None: # Enter a busy loop if we have a timeout. This busy loop was # cribbed from Lib/threading.py in Thread.wait() at r71065. delay = 0.0005 # 500 us -> initial delay of 1 ms @@ -1507,7 +1515,7 @@ class Popen(object): break remaining = self._remaining_time(endtime) if remaining <= 0: - raise TimeoutExpired(self.args) + raise TimeoutExpired(self.args, timeout) delay = min(delay * 2, remaining, .05) time.sleep(delay) elif self.returncode is None: @@ -1516,7 +1524,7 @@ class Popen(object): return self.returncode - def _communicate(self, input, endtime): + def _communicate(self, input, endtime, orig_timeout): if self.stdin and not self._communication_started: # Flush stdio buffer. This might block, if the user has # been writing to .stdin in an uncontrolled fashion. @@ -1525,9 +1533,11 @@ class Popen(object): self.stdin.close() if _has_poll: - stdout, stderr = self._communicate_with_poll(input, endtime) + stdout, stderr = self._communicate_with_poll(input, endtime, + orig_timeout) else: - stdout, stderr = self._communicate_with_select(input, endtime) + stdout, stderr = self._communicate_with_select(input, endtime, + orig_timeout) self.wait(timeout=self._remaining_time(endtime)) @@ -1550,7 +1560,7 @@ class Popen(object): return (stdout, stderr) - def _communicate_with_poll(self, input, endtime): + def _communicate_with_poll(self, input, endtime, orig_timeout): stdout = None # Return stderr = None # Return @@ -1601,7 +1611,7 @@ class Popen(object): if e.args[0] == errno.EINTR: continue raise - self._check_timeout(endtime) + self._check_timeout(endtime, orig_timeout) # XXX Rewrite these to use non-blocking I/O on the # file objects; they are no longer using C stdio! @@ -1625,7 +1635,7 @@ class Popen(object): return (stdout, stderr) - def _communicate_with_select(self, input, endtime): + def _communicate_with_select(self, input, endtime, orig_timeout): if not self._communication_started: self._read_set = [] self._write_set = [] @@ -1667,9 +1677,9 @@ class Popen(object): # According to the docs, returning three empty lists indicates # that the timeout expired. if not (rlist or wlist or xlist): - raise TimeoutExpired(self.args) + raise TimeoutExpired(self.args, orig_timeout) # We also check what time it is ourselves for good measure. - self._check_timeout(endtime) + self._check_timeout(endtime, orig_timeout) # XXX Rewrite these to use non-blocking I/O on the # file objects; they are no longer using C stdio! diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 3156543..00cf0d5 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -651,7 +651,9 @@ class ProcessTestCase(BaseTestCase): def test_wait_timeout(self): p = subprocess.Popen([sys.executable, "-c", "import time; time.sleep(0.1)"]) - self.assertRaises(subprocess.TimeoutExpired, p.wait, timeout=0.01) + with self.assertRaises(subprocess.TimeoutExpired) as c: + p.wait(timeout=0.01) + self.assertIn("0.01", str(c.exception)) # For coverage of __str__. self.assertEqual(p.wait(timeout=2), 0) -- cgit v0.12 From da9ac728a84778317e1d529f88e47b6d34a5a6b6 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Wed, 16 Mar 2011 17:08:21 -0400 Subject: Bump up the subprocess timeouts even more. :( --- Lib/test/test_subprocess.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 00cf0d5..2dde245 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -130,7 +130,9 @@ class ProcessTestCase(BaseTestCase): "import sys; sys.stdout.write('BDFL')\n" "sys.stdout.flush()\n" "while True: pass"], - timeout=1.5) + # Some heavily loaded buildbots (sparc Debian 3.x) require + # this much time to start and print. + timeout=3) self.fail("Expected TimeoutExpired.") self.assertEqual(c.exception.output, b'BDFL') @@ -647,15 +649,15 @@ class ProcessTestCase(BaseTestCase): # Subsequent invocations should just return the returncode self.assertEqual(p.wait(), 0) - def test_wait_timeout(self): p = subprocess.Popen([sys.executable, "-c", "import time; time.sleep(0.1)"]) with self.assertRaises(subprocess.TimeoutExpired) as c: p.wait(timeout=0.01) self.assertIn("0.01", str(c.exception)) # For coverage of __str__. - self.assertEqual(p.wait(timeout=2), 0) - + # Some heavily loaded buildbots (sparc Debian 3.x) require this much + # time to start. + self.assertEqual(p.wait(timeout=3), 0) def test_invalid_bufsize(self): # an invalid type of the bufsize argument should raise -- cgit v0.12 From 07926f024a9dd0fab190273ed84f5f1a8667308f Mon Sep 17 00:00:00 2001 From: Michael Foord Date: Wed, 16 Mar 2011 17:19:16 -0400 Subject: Closes issue 11503. Improves test coverage of posixpath. --- Lib/test/test_posixpath.py | 63 ++++++++++++++++++++++++++++++++++++++++++++++ Misc/NEWS | 2 ++ 2 files changed, 65 insertions(+) diff --git a/Lib/test/test_posixpath.py b/Lib/test/test_posixpath.py index f045b0b..bb4559c 100644 --- a/Lib/test/test_posixpath.py +++ b/Lib/test/test_posixpath.py @@ -6,6 +6,11 @@ import os import sys from posixpath import realpath, abspath, dirname, basename +try: + import posix +except ImportError: + posix = None + # An absolute path to a temporary filename for testing. We can't rely on TESTFN # being an absolute path, so we need this. @@ -150,6 +155,7 @@ class PosixPathTest(unittest.TestCase): def test_islink(self): self.assertIs(posixpath.islink(support.TESTFN + "1"), False) + self.assertIs(posixpath.lexists(support.TESTFN + "2"), False) f = open(support.TESTFN + "1", "wb") try: f.write(b"foo") @@ -225,6 +231,44 @@ class PosixPathTest(unittest.TestCase): def test_ismount(self): self.assertIs(posixpath.ismount("/"), True) + self.assertIs(posixpath.ismount(b"/"), True) + + def test_ismount_non_existent(self): + # Non-existent mountpoint. + self.assertIs(posixpath.ismount(ABSTFN), False) + try: + os.mkdir(ABSTFN) + self.assertIs(posixpath.ismount(ABSTFN), False) + finally: + safe_rmdir(ABSTFN) + + @unittest.skipUnless(support.can_symlink(), + "Test requires symlink support") + def test_ismount_symlinks(self): + # Symlinks are never mountpoints. + try: + os.symlink("/", ABSTFN) + self.assertIs(posixpath.ismount(ABSTFN), False) + finally: + os.unlink(ABSTFN) + + @unittest.skipIf(posix is None, "Test requires posix module") + def test_ismount_different_device(self): + # Simulate the path being on a different device from its parent by + # mocking out st_dev. + save_lstat = os.lstat + def fake_lstat(path): + st_ino = 0 + st_dev = 0 + if path == ABSTFN: + st_dev = 1 + st_ino = 1 + return posix.stat_result((0, st_ino, st_dev, 0, 0, 0, 0, 0, 0, 0)) + try: + os.lstat = fake_lstat + self.assertIs(posixpath.ismount(ABSTFN), True) + finally: + os.lstat = save_lstat def test_expanduser(self): self.assertEqual(posixpath.expanduser("foo"), "foo") @@ -254,6 +298,10 @@ class PosixPathTest(unittest.TestCase): with support.EnvironmentVarGuard() as env: env['HOME'] = '/' self.assertEqual(posixpath.expanduser("~"), "/") + # expanduser should fall back to using the password database + del env['HOME'] + home = pwd.getpwuid(os.getuid()).pw_dir + self.assertEqual(posixpath.expanduser("~"), home) def test_normpath(self): self.assertEqual(posixpath.normpath(""), ".") @@ -289,6 +337,16 @@ class PosixPathTest(unittest.TestCase): @unittest.skipUnless(hasattr(os, "symlink"), "Missing symlink implementation") @skip_if_ABSTFN_contains_backslash + def test_realpath_relative(self): + try: + os.symlink(posixpath.relpath(ABSTFN+"1"), ABSTFN) + self.assertEqual(realpath(ABSTFN), ABSTFN+"1") + finally: + support.unlink(ABSTFN) + + @unittest.skipUnless(hasattr(os, "symlink"), + "Missing symlink implementation") + @skip_if_ABSTFN_contains_backslash def test_realpath_symlink_loops(self): # Bug #930024, return the path unchanged if we get into an infinite # symlink loop. @@ -443,6 +501,11 @@ class PosixPathTest(unittest.TestCase): finally: os.getcwdb = real_getcwdb + def test_sameopenfile(self): + fname = support.TESTFN + "1" + with open(fname, "wb") as a, open(fname, "wb") as b: + self.assertTrue(posixpath.sameopenfile(a.fileno(), b.fileno())) + class PosixCommonTest(test_genericpath.CommonTest): pathmodule = posixpath diff --git a/Misc/NEWS b/Misc/NEWS index 9af1442..eeea4ba 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -126,6 +126,8 @@ Tools/Demos Tests ----- +- Issue #11503: improve test coverage of posixpath.py. Patch by Evan Dandrea. + - Issue #11505: improves test coverage of string.py. Patch by Alicia Arlen. -- cgit v0.12 From a88da67bcbf8b87af613751796998538afb26be0 Mon Sep 17 00:00:00 2001 From: R David Murray Date: Wed, 16 Mar 2011 17:32:27 -0400 Subject: #11578: add unit tests for timeit module. Patch by Michael Henry. --- Lib/test/test_sundry.py | 1 - Lib/test/test_timeit.py | 305 ++++++++++++++++++++++++++++++++++++++++++++++++ Lib/timeit.py | 10 +- Misc/NEWS | 2 + 4 files changed, 315 insertions(+), 3 deletions(-) create mode 100644 Lib/test/test_timeit.py diff --git a/Lib/test/test_sundry.py b/Lib/test/test_sundry.py index 4dacb9d..07802d6 100644 --- a/Lib/test/test_sundry.py +++ b/Lib/test/test_sundry.py @@ -54,7 +54,6 @@ class TestUntestedModules(unittest.TestCase): import py_compile import sndhdr import tabnanny - import timeit try: import tty # not available on Windows except ImportError: diff --git a/Lib/test/test_timeit.py b/Lib/test/test_timeit.py new file mode 100644 index 0000000..eb3b1a1 --- /dev/null +++ b/Lib/test/test_timeit.py @@ -0,0 +1,305 @@ +import timeit +import unittest +import sys +import io +import time +from textwrap import dedent + +from test.support import run_unittest +from test.support import captured_stdout +from test.support import captured_stderr + +# timeit's default number of iterations. +DEFAULT_NUMBER = 1000000 + +# timeit's default number of repetitions. +DEFAULT_REPEAT = 3 + +# XXX: some tests are commented out that would improve the coverage but take a +# long time to run because they test the default number of loops, which is +# large. The tests could be enabled if there was a way to override the default +# number of loops during testing, but this would require changing the signature +# of some functions that use the default as a default argument. + +class FakeTimer: + BASE_TIME = 42.0 + def __init__(self, seconds_per_increment=1.0): + self.count = 0 + self.setup_calls = 0 + self.seconds_per_increment=seconds_per_increment + timeit._fake_timer = self + + def __call__(self): + return self.BASE_TIME + self.count * self.seconds_per_increment + + def inc(self): + self.count += 1 + + def setup(self): + self.setup_calls += 1 + + def wrap_timer(self, timer): + """Records 'timer' and returns self as callable timer.""" + self.saved_timer = timer + return self + +class TestTimeit(unittest.TestCase): + + def tearDown(self): + try: + del timeit._fake_timer + except AttributeError: + pass + + def test_reindent_empty(self): + self.assertEqual(timeit.reindent("", 0), "") + self.assertEqual(timeit.reindent("", 4), "") + + def test_reindent_single(self): + self.assertEqual(timeit.reindent("pass", 0), "pass") + self.assertEqual(timeit.reindent("pass", 4), "pass") + + def test_reindent_multi_empty(self): + self.assertEqual(timeit.reindent("\n\n", 0), "\n\n") + self.assertEqual(timeit.reindent("\n\n", 4), "\n \n ") + + def test_reindent_multi(self): + self.assertEqual(timeit.reindent( + "print()\npass\nbreak", 0), + "print()\npass\nbreak") + self.assertEqual(timeit.reindent( + "print()\npass\nbreak", 4), + "print()\n pass\n break") + + def test_timer_invalid_stmt(self): + self.assertRaises(ValueError, timeit.Timer, stmt=None) + + def test_timer_invalid_setup(self): + self.assertRaises(ValueError, timeit.Timer, setup=None) + + fake_setup = "import timeit; timeit._fake_timer.setup()" + fake_stmt = "import timeit; timeit._fake_timer.inc()" + + def fake_callable_setup(self): + self.fake_timer.setup() + + def fake_callable_stmt(self): + self.fake_timer.inc() + + def timeit(self, stmt, setup, number=None): + self.fake_timer = FakeTimer() + t = timeit.Timer(stmt=stmt, setup=setup, timer=self.fake_timer) + kwargs = {} + if number is None: + number = DEFAULT_NUMBER + else: + kwargs['number'] = number + delta_time = t.timeit(**kwargs) + self.assertEqual(self.fake_timer.setup_calls, 1) + self.assertEqual(self.fake_timer.count, number) + self.assertEqual(delta_time, number) + + # Takes too long to run in debug build. + #def test_timeit_default_iters(self): + # self.timeit(self.fake_stmt, self.fake_setup) + + def test_timeit_zero_iters(self): + self.timeit(self.fake_stmt, self.fake_setup, number=0) + + def test_timeit_few_iters(self): + self.timeit(self.fake_stmt, self.fake_setup, number=3) + + def test_timeit_callable_stmt(self): + self.timeit(self.fake_callable_stmt, self.fake_setup, number=3) + + def test_timeit_callable_stmt_and_setup(self): + self.timeit(self.fake_callable_stmt, + self.fake_callable_setup, number=3) + + # Takes too long to run in debug build. + #def test_timeit_function(self): + # delta_time = timeit.timeit(self.fake_stmt, self.fake_setup, + # timer=FakeTimer()) + # self.assertEqual(delta_time, DEFAULT_NUMBER) + + def test_timeit_function_zero_iters(self): + delta_time = timeit.timeit(self.fake_stmt, self.fake_setup, number=0, + timer=FakeTimer()) + self.assertEqual(delta_time, 0) + + def repeat(self, stmt, setup, repeat=None, number=None): + self.fake_timer = FakeTimer() + t = timeit.Timer(stmt=stmt, setup=setup, timer=self.fake_timer) + kwargs = {} + if repeat is None: + repeat = DEFAULT_REPEAT + else: + kwargs['repeat'] = repeat + if number is None: + number = DEFAULT_NUMBER + else: + kwargs['number'] = number + delta_times = t.repeat(**kwargs) + self.assertEqual(self.fake_timer.setup_calls, repeat) + self.assertEqual(self.fake_timer.count, repeat * number) + self.assertEqual(delta_times, repeat * [float(number)]) + + # Takes too long to run in debug build. + #def test_repeat_default(self): + # self.repeat(self.fake_stmt, self.fake_setup) + + def test_repeat_zero_reps(self): + self.repeat(self.fake_stmt, self.fake_setup, repeat=0) + + def test_repeat_zero_iters(self): + self.repeat(self.fake_stmt, self.fake_setup, number=0) + + def test_repeat_few_reps_and_iters(self): + self.repeat(self.fake_stmt, self.fake_setup, repeat=3, number=5) + + def test_repeat_callable_stmt(self): + self.repeat(self.fake_callable_stmt, self.fake_setup, + repeat=3, number=5) + + def test_repeat_callable_stmt_and_setup(self): + self.repeat(self.fake_callable_stmt, self.fake_callable_setup, + repeat=3, number=5) + + # Takes too long to run in debug build. + #def test_repeat_function(self): + # delta_times = timeit.repeat(self.fake_stmt, self.fake_setup, + # timer=FakeTimer()) + # self.assertEqual(delta_times, DEFAULT_REPEAT * [float(DEFAULT_NUMBER)]) + + def test_repeat_function_zero_reps(self): + delta_times = timeit.repeat(self.fake_stmt, self.fake_setup, repeat=0, + timer=FakeTimer()) + self.assertEqual(delta_times, []) + + def test_repeat_function_zero_iters(self): + delta_times = timeit.repeat(self.fake_stmt, self.fake_setup, number=0, + timer=FakeTimer()) + self.assertEqual(delta_times, DEFAULT_REPEAT * [0.0]) + + def assert_exc_string(self, exc_string, expected_exc_name): + exc_lines = exc_string.splitlines() + self.assertGreater(len(exc_lines), 2) + self.assertTrue(exc_lines[0].startswith('Traceback')) + self.assertTrue(exc_lines[-1].startswith(expected_exc_name)) + + def test_print_exc(self): + s = io.StringIO() + t = timeit.Timer("1/0") + try: + t.timeit() + except: + t.print_exc(s) + self.assert_exc_string(s.getvalue(), 'ZeroDivisionError') + + MAIN_DEFAULT_OUTPUT = "10 loops, best of 3: 1 sec per loop\n" + + def run_main(self, seconds_per_increment=1.0, switches=None, timer=None): + if timer is None: + timer = FakeTimer(seconds_per_increment=seconds_per_increment) + if switches is None: + args = [] + else: + args = switches[:] + args.append(self.fake_stmt) + # timeit.main() modifies sys.path, so save and restore it. + orig_sys_path = sys.path[:] + with captured_stdout() as s: + timeit.main(args=args, _wrap_timer=timer.wrap_timer) + sys.path[:] = orig_sys_path[:] + return s.getvalue() + + def test_main_bad_switch(self): + s = self.run_main(switches=['--bad-switch']) + self.assertEqual(s, dedent("""\ + option --bad-switch not recognized + use -h/--help for command line help + """)) + + def test_main_seconds(self): + s = self.run_main(seconds_per_increment=5.5) + self.assertEqual(s, "10 loops, best of 3: 5.5 sec per loop\n") + + def test_main_milliseconds(self): + s = self.run_main(seconds_per_increment=0.0055) + self.assertEqual(s, "100 loops, best of 3: 5.5 msec per loop\n") + + def test_main_microseconds(self): + s = self.run_main(seconds_per_increment=0.0000025, switches=['-n100']) + self.assertEqual(s, "100 loops, best of 3: 2.5 usec per loop\n") + + def test_main_fixed_iters(self): + s = self.run_main(seconds_per_increment=2.0, switches=['-n35']) + self.assertEqual(s, "35 loops, best of 3: 2 sec per loop\n") + + def test_main_setup(self): + s = self.run_main(seconds_per_increment=2.0, + switches=['-n35', '-s', 'print("CustomSetup")']) + self.assertEqual(s, "CustomSetup\n" * 3 + + "35 loops, best of 3: 2 sec per loop\n") + + def test_main_fixed_reps(self): + s = self.run_main(seconds_per_increment=60.0, switches=['-r9']) + self.assertEqual(s, "10 loops, best of 9: 60 sec per loop\n") + + def test_main_negative_reps(self): + s = self.run_main(seconds_per_increment=60.0, switches=['-r-5']) + self.assertEqual(s, "10 loops, best of 1: 60 sec per loop\n") + + def test_main_help(self): + s = self.run_main(switches=['-h']) + # Note: It's not clear that the trailing space was intended as part of + # the help text, but since it's there, check for it. + self.assertEqual(s, timeit.__doc__ + ' ') + + def test_main_using_time(self): + fake_timer = FakeTimer() + s = self.run_main(switches=['-t'], timer=fake_timer) + self.assertEqual(s, self.MAIN_DEFAULT_OUTPUT) + self.assertIs(fake_timer.saved_timer, time.time) + + def test_main_using_clock(self): + fake_timer = FakeTimer() + s = self.run_main(switches=['-c'], timer=fake_timer) + self.assertEqual(s, self.MAIN_DEFAULT_OUTPUT) + self.assertIs(fake_timer.saved_timer, time.clock) + + def test_main_verbose(self): + s = self.run_main(switches=['-v']) + self.assertEqual(s, dedent("""\ + 10 loops -> 10 secs + raw times: 10 10 10 + 10 loops, best of 3: 1 sec per loop + """)) + + def test_main_very_verbose(self): + s = self.run_main(seconds_per_increment=0.000050, switches=['-vv']) + self.assertEqual(s, dedent("""\ + 10 loops -> 0.0005 secs + 100 loops -> 0.005 secs + 1000 loops -> 0.05 secs + 10000 loops -> 0.5 secs + raw times: 0.5 0.5 0.5 + 10000 loops, best of 3: 50 usec per loop + """)) + + def test_main_exception(self): + with captured_stderr() as error_stringio: + s = self.run_main(switches=['1/0']) + self.assert_exc_string(error_stringio.getvalue(), 'ZeroDivisionError') + + def test_main_exception_fixed_reps(self): + with captured_stderr() as error_stringio: + s = self.run_main(switches=['-n1', '1/0']) + self.assert_exc_string(error_stringio.getvalue(), 'ZeroDivisionError') + + +def test_main(): + run_unittest(TestTimeit) + +if __name__ == '__main__': + test_main() diff --git a/Lib/timeit.py b/Lib/timeit.py index 5c613fc..8e04645 100644 --- a/Lib/timeit.py +++ b/Lib/timeit.py @@ -232,10 +232,10 @@ def repeat(stmt="pass", setup="pass", timer=default_timer, """Convenience function to create Timer object and call repeat method.""" return Timer(stmt, setup, timer).repeat(repeat, number) -def main(args=None): +def main(args=None, *, _wrap_timer=None): """Main program, used when run as a script. - The optional argument specifies the command line to be parsed, + The optional 'args' argument specifies the command line to be parsed, defaulting to sys.argv[1:]. The return value is an exit code to be passed to sys.exit(); it @@ -244,6 +244,10 @@ def main(args=None): When an exception happens during timing, a traceback is printed to stderr and the return value is 1. Exceptions at other times (including the template compilation) are not caught. + + '_wrap_timer' is an internal interface used for unit testing. If it + is not None, it must be a callable that accepts a timer function + and returns another timer function (used for unit testing). """ if args is None: args = sys.argv[1:] @@ -289,6 +293,8 @@ def main(args=None): # directory) import os sys.path.insert(0, os.curdir) + if _wrap_timer is not None: + timer = _wrap_timer(timer) t = Timer(stmt, setup, timer) if number == 0: # determine number so that 0.2 <= total time < 2.0 diff --git a/Misc/NEWS b/Misc/NEWS index eeea4ba..781f943 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -126,6 +126,8 @@ Tools/Demos Tests ----- +- Issue #11578: added test for the timeit module. Patch Michael Henry. + - Issue #11503: improve test coverage of posixpath.py. Patch by Evan Dandrea. - Issue #11505: improves test coverage of string.py. Patch by Alicia -- cgit v0.12 From de91276a5c90b9d3e42866054e48d255a37981b3 Mon Sep 17 00:00:00 2001 From: R David Murray Date: Wed, 16 Mar 2011 18:26:23 -0400 Subject: #11401: handle headers with no value. --- Lib/email/header.py | 2 +- Lib/email/test/test_email.py | 7 +++++++ Misc/NEWS | 3 +++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Lib/email/header.py b/Lib/email/header.py index 43220df..da739d5 100644 --- a/Lib/email/header.py +++ b/Lib/email/header.py @@ -304,7 +304,7 @@ class Header: self._continuation_ws, splitchars) for string, charset in self._chunks: lines = string.splitlines() - formatter.feed(lines[0], charset) + formatter.feed(lines[0] if lines else '', charset) for line in lines[1:]: formatter.newline() if charset.header_encoding is not None: diff --git a/Lib/email/test/test_email.py b/Lib/email/test/test_email.py index 6a88b16..4268a25 100644 --- a/Lib/email/test/test_email.py +++ b/Lib/email/test/test_email.py @@ -3296,6 +3296,13 @@ A very long line that must get split to something other than at the h = Header('文', charset='shift_jis') self.assertEqual(h.encode(), '=?iso-2022-jp?b?GyRCSjgbKEI=?=') + def test_flatten_header_with_no_value(self): + # Issue 11401 (regression from email 4.x) Note that the space after + # the header doesn't reflect the input, but this is also the way + # email 4.x behaved. At some point it would be nice to fix that. + msg = email.message_from_string("EmptyHeader:") + self.assertEqual(str(msg), "EmptyHeader: \n\n") + # Test RFC 2231 header parameters (en/de)coding diff --git a/Misc/NEWS b/Misc/NEWS index beb6ec1..58eea2d 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -40,6 +40,9 @@ Core and Builtins Library ------- +- Issue #11401: fix handling of headers with no value; this fixes a regression + relative to Python2 and the result is now the same as it was in Python2. + - Issue #9298: base64 bodies weren't being folded to line lengths less than 78, which was a regression relative to Python2. Unlike Python2, the last line of the folded body now ends with a carriage return. -- cgit v0.12 From c95ec3d560dd21e678958016aa46313f619b83e7 Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Wed, 16 Mar 2011 19:52:14 -0400 Subject: Exercise crashers to ensure they are still covering known error cases --- Lib/test/crashers/README | 4 ++++ Lib/test/test_crashers.py | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 Lib/test/test_crashers.py diff --git a/Lib/test/crashers/README b/Lib/test/crashers/README index 2a73e1b..0259a06 100644 --- a/Lib/test/crashers/README +++ b/Lib/test/crashers/README @@ -14,3 +14,7 @@ note if the cause is system or environment dependent and what the variables are. Once the crash is fixed, the test case should be moved into an appropriate test (even if it was originally from the test suite). This ensures the regression doesn't happen again. And if it does, it should be easier to track down. + +Also see Lib/test_crashers.py which exercises the crashers in this directory. +In particular, make sure to add any new infinite loop crashers to the black +list so it doesn't try to run them. diff --git a/Lib/test/test_crashers.py b/Lib/test/test_crashers.py new file mode 100644 index 0000000..ee612c2 --- /dev/null +++ b/Lib/test/test_crashers.py @@ -0,0 +1,35 @@ +# Tests that the crashers in the Lib/test/crashers directory actually +# do crash the interpreter as expected +# +# If a crasher is fixed, it should be moved elsewhere in the test suite to +# ensure it continues to work correctly. + +import unittest +import glob +import os.path +import test.support +from test.script_helper import assert_python_failure + +CRASHER_DIR = os.path.join(os.path.dirname(__file__), "crashers") +CRASHER_FILES = os.path.join(CRASHER_DIR, "*.py") + +infinite_loops = ["infinite_loop_re.py", "nasty_eq_vs_dict.py"] + +class CrasherTest(unittest.TestCase): + + @test.support.cpython_only + def test_crashers_crash(self): + for fname in glob.glob(CRASHER_FILES): + if os.path.basename(fname) in infinite_loops: + continue + # Some "crashers" only trigger an exception rather than a + # segfault. Consider that an acceptable outcome. + assert_python_failure(fname) + + +def test_main(): + test.support.run_unittest(CrasherTest) + test.support.reap_children() + +if __name__ == "__main__": + test_main() -- cgit v0.12 From ecc2db515202456a67e9702ed94ce19fe5b4711f Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Wed, 16 Mar 2011 20:11:52 -0400 Subject: Remove an overly specific exception message test. --- Lib/test/test_import.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py index cf17c96..ebcc2ca 100644 --- a/Lib/test/test_import.py +++ b/Lib/test/test_import.py @@ -283,8 +283,6 @@ class ImportTests(unittest.TestCase): self.skipTest('path is not encodable to {}'.format(encoding)) with self.assertRaises(ImportError) as c: __import__(path) - self.assertEqual("Import by filename is not supported.", - c.exception.args[0]) def test_import_in_del_does_not_crash(self): # Issue 4236 -- cgit v0.12 From 49cb9593a0ae4da35c44fa46636e4a11acd2581a Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Wed, 16 Mar 2011 20:23:58 -0400 Subject: Add missing NEWS item for previous commit --- Misc/NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Misc/NEWS b/Misc/NEWS index 4b2aa59..e158d56 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -239,6 +239,9 @@ Tools/Demos Tests ----- +- New test_crashers added to exercise the scripts in the Lib/test/crashers + directory and confirm they fail as expected + - Issue #11578: added test for the timeit module. Patch Michael Henry. - Issue #11503: improve test coverage of posixpath.py. Patch by Evan Dandrea. -- cgit v0.12 From a215023b784eb1e23b2e91a007bc9a19750ed3c0 Mon Sep 17 00:00:00 2001 From: R David Murray Date: Wed, 16 Mar 2011 21:11:23 -0400 Subject: #11243: tests and fixes for handling of 'dirty data' in additional methods --- Lib/email/message.py | 13 ++++++----- Lib/email/test/test_email.py | 52 ++++++++++++++++++++++++++++++++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 63 insertions(+), 5 deletions(-) diff --git a/Lib/email/message.py b/Lib/email/message.py index 2713bc5..922617a 100644 --- a/Lib/email/message.py +++ b/Lib/email/message.py @@ -48,9 +48,9 @@ def _sanitize_header(name, value): def _splitparam(param): # Split header parameters. BAW: this may be too simple. It isn't # strictly RFC 2045 (section 5.1) compliant, but it catches most headers - # found in the wild. We may eventually need a full fledged parser - # eventually. - a, sep, b = param.partition(';') + # found in the wild. We may eventually need a full fledged parser. + # RDM: we might have a Header here; for now just stringify it. + a, sep, b = str(param).partition(';') if not sep: return a.strip(), None return a.strip(), b.strip() @@ -90,6 +90,8 @@ def _formatparam(param, value=None, quote=True): return param def _parseparam(s): + # RDM This might be a Header, so for now stringify it. + s = ';' + str(s) plist = [] while s[:1] == ';': s = s[1:] @@ -240,7 +242,8 @@ class Message: if i is not None and not isinstance(self._payload, list): raise TypeError('Expected list, got %s' % type(self._payload)) payload = self._payload - cte = self.get('content-transfer-encoding', '').lower() + # cte might be a Header, so for now stringify it. + cte = str(self.get('content-transfer-encoding', '')).lower() # payload may be bytes here. if isinstance(payload, str): if _has_surrogates(payload): @@ -561,7 +564,7 @@ class Message: if value is missing: return failobj params = [] - for p in _parseparam(';' + value): + for p in _parseparam(value): try: name, val = p.split('=', 1) name = name.strip() diff --git a/Lib/email/test/test_email.py b/Lib/email/test/test_email.py index dcb2e95..9f64e09 100644 --- a/Lib/email/test/test_email.py +++ b/Lib/email/test/test_email.py @@ -2995,6 +2995,58 @@ class Test8BitBytesHandling(unittest.TestCase): ['foo@bar.com', 'g\uFFFD\uFFFDst']) + def test_get_content_type_with_8bit(self): + msg = email.message_from_bytes(textwrap.dedent("""\ + Content-Type: text/pl\xA7in; charset=utf-8 + """).encode('latin-1')) + self.assertEqual(msg.get_content_type(), "text/pl\uFFFDin") + self.assertEqual(msg.get_content_maintype(), "text") + self.assertEqual(msg.get_content_subtype(), "pl\uFFFDin") + + def test_get_params_with_8bit(self): + msg = email.message_from_bytes( + 'X-Header: foo=\xa7ne; b\xa7r=two; baz=three\n'.encode('latin-1')) + self.assertEqual(msg.get_params(header='x-header'), + [('foo', '\uFFFDne'), ('b\uFFFDr', 'two'), ('baz', 'three')]) + self.assertEqual(msg.get_param('Foo', header='x-header'), '\uFFFdne') + # XXX: someday you might be able to get 'b\xa7r', for now you can't. + self.assertEqual(msg.get_param('b\xa7r', header='x-header'), None) + + def test_get_rfc2231_params_with_8bit(self): + msg = email.message_from_bytes(textwrap.dedent("""\ + Content-Type: text/plain; charset=us-ascii; + title*=us-ascii'en'This%20is%20not%20f\xa7n""" + ).encode('latin-1')) + self.assertEqual(msg.get_param('title'), + ('us-ascii', 'en', 'This is not f\uFFFDn')) + + def test_set_rfc2231_params_with_8bit(self): + msg = email.message_from_bytes(textwrap.dedent("""\ + Content-Type: text/plain; charset=us-ascii; + title*=us-ascii'en'This%20is%20not%20f\xa7n""" + ).encode('latin-1')) + msg.set_param('title', 'test') + self.assertEqual(msg.get_param('title'), 'test') + + def test_del_rfc2231_params_with_8bit(self): + msg = email.message_from_bytes(textwrap.dedent("""\ + Content-Type: text/plain; charset=us-ascii; + title*=us-ascii'en'This%20is%20not%20f\xa7n""" + ).encode('latin-1')) + msg.del_param('title') + self.assertEqual(msg.get_param('title'), None) + self.assertEqual(msg.get_content_maintype(), 'text') + + def test_get_payload_with_8bit_cte_header(self): + msg = email.message_from_bytes(textwrap.dedent("""\ + Content-Transfer-Encoding: b\xa7se64 + Content-Type: text/plain; charset=latin-1 + + payload + """).encode('latin-1')) + self.assertEqual(msg.get_payload(), 'payload\n') + self.assertEqual(msg.get_payload(decode=True), b'payload\n') + non_latin_bin_msg = textwrap.dedent("""\ From: foo@bar.com To: báz diff --git a/Misc/NEWS b/Misc/NEWS index c787ece..c787fed 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -40,6 +40,9 @@ Core and Builtins Library ------- +- Issue #11243: fix the parameter querying methods of Message to work if + the headers contain un-encoded non-ASCII data. + - Issue #11401: fix handling of headers with no value; this fixes a regression relative to Python2 and the result is now the same as it was in Python2. -- cgit v0.12 From b3c728fd8924f271c708ea8ae6692ae5cb484a34 Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Wed, 16 Mar 2011 21:26:40 -0400 Subject: Close #11577: Improve binhex test coverage and fix ResourceWarning --- Lib/binhex.py | 42 ++++++++++++++++++++++++------------------ Lib/test/test_binhex.py | 11 +++++++++++ Misc/ACKS | 1 + Misc/NEWS | 4 ++++ 4 files changed, 40 insertions(+), 18 deletions(-) diff --git a/Lib/binhex.py b/Lib/binhex.py index 4b7997a..999a675 100644 --- a/Lib/binhex.py +++ b/Lib/binhex.py @@ -52,14 +52,13 @@ class FInfo: def getfileinfo(name): finfo = FInfo() - fp = io.open(name, 'rb') - # Quick check for textfile - data = fp.read(512) - if 0 not in data: - finfo.Type = 'TEXT' - fp.seek(0, 2) - dsize = fp.tell() - fp.close() + with io.open(name, 'rb') as fp: + # Quick check for textfile + data = fp.read(512) + if 0 not in data: + finfo.Type = 'TEXT' + fp.seek(0, 2) + dsize = fp.tell() dir, file = os.path.split(name) file = file.replace(':', '-', 1) return file, finfo, dsize, 0 @@ -140,19 +139,26 @@ class _Rlecoderengine: class BinHex: def __init__(self, name_finfo_dlen_rlen, ofp): name, finfo, dlen, rlen = name_finfo_dlen_rlen + close_on_error = False if isinstance(ofp, str): ofname = ofp ofp = io.open(ofname, 'wb') - ofp.write(b'(This file must be converted with BinHex 4.0)\r\r:') - hqxer = _Hqxcoderengine(ofp) - self.ofp = _Rlecoderengine(hqxer) - self.crc = 0 - if finfo is None: - finfo = FInfo() - self.dlen = dlen - self.rlen = rlen - self._writeinfo(name, finfo) - self.state = _DID_HEADER + close_on_error = True + try: + ofp.write(b'(This file must be converted with BinHex 4.0)\r\r:') + hqxer = _Hqxcoderengine(ofp) + self.ofp = _Rlecoderengine(hqxer) + self.crc = 0 + if finfo is None: + finfo = FInfo() + self.dlen = dlen + self.rlen = rlen + self._writeinfo(name, finfo) + self.state = _DID_HEADER + except: + if close_on_error: + ofp.close() + raise def _writeinfo(self, name, finfo): nl = len(name) diff --git a/Lib/test/test_binhex.py b/Lib/test/test_binhex.py index d6ef84a..a807bca 100755 --- a/Lib/test/test_binhex.py +++ b/Lib/test/test_binhex.py @@ -15,10 +15,12 @@ class BinHexTestCase(unittest.TestCase): def setUp(self): self.fname1 = support.TESTFN + "1" self.fname2 = support.TESTFN + "2" + self.fname3 = support.TESTFN + "very_long_filename__very_long_filename__very_long_filename__very_long_filename__" def tearDown(self): support.unlink(self.fname1) support.unlink(self.fname2) + support.unlink(self.fname3) DATA = b'Jack is my hero' @@ -37,6 +39,15 @@ class BinHexTestCase(unittest.TestCase): self.assertEqual(self.DATA, finish) + def test_binhex_error_on_long_filename(self): + """ + The testcase fails if no exception is raised when a filename parameter provided to binhex.binhex() + is too long, or if the exception raised in binhex.binhex() is not an instance of binhex.Error. + """ + f3 = open(self.fname3, 'wb') + f3.close() + + self.assertRaises(binhex.Error, binhex.binhex, self.fname3, self.fname2) def test_main(): support.run_unittest(BinHexTestCase) diff --git a/Misc/ACKS b/Misc/ACKS index 0cbc670..f2bf3cd 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -447,6 +447,7 @@ Tamito Kajiyama Peter van Kampen Rafe Kaplan Jacob Kaplan-Moss +Arkady Koplyarov Lou Kates Hiroaki Kawai Sebastien Keim diff --git a/Misc/NEWS b/Misc/NEWS index c787ece..f2d0d76 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -40,6 +40,8 @@ Core and Builtins Library ------- +- Issue #11577: fix ResourceWarning triggered by improved binhex test coverage + - Issue #11401: fix handling of headers with no value; this fixes a regression relative to Python2 and the result is now the same as it was in Python2. @@ -129,6 +131,8 @@ Tools/Demos Tests ----- +- Issue #11577: improve test coverage of binhex.py. Patch by Arkady Koplyarov. + - Issue #11578: added test for the timeit module. Patch Michael Henry. - Issue #11503: improve test coverage of posixpath.py. Patch by Evan Dandrea. -- cgit v0.12 From b253c9f66de1226ad6b72d79af70563671fe4320 Mon Sep 17 00:00:00 2001 From: Senthil Kumaran Date: Thu, 17 Mar 2011 16:43:22 +0800 Subject: Fix issue11567: http.server DEFAULT_ERROR_MESSAGE format. Patch by Gennadiy Zlobin. --- Lib/http/server.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/Lib/http/server.py b/Lib/http/server.py index 543abe0..c0245ec 100644 --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -103,15 +103,20 @@ import copy # Default error message template DEFAULT_ERROR_MESSAGE = """\ - -Error response - - -

Error response

-

Error code %(code)d. -

Message: %(message)s. -

Error code explanation: %(code)s = %(explain)s. - + + + + + Error response + + +

Error response

+

Error code: %(code)d

+

Message: %(message)s.

+

Error code explanation: %(code)s - %(explain)s.

+ + """ DEFAULT_ERROR_CONTENT_TYPE = "text/html;charset=utf-8" -- cgit v0.12 From 9f9193ec375ed0f366b4aabfe210e7fdc3eb6b7d Mon Sep 17 00:00:00 2001 From: Senthil Kumaran Date: Thu, 17 Mar 2011 17:01:45 +0800 Subject: Error message in http.server code. Missed to update in 3.1 branch initially. --- Lib/http/server.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/Lib/http/server.py b/Lib/http/server.py index 8de604a..0cd8d35 100644 --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -103,15 +103,20 @@ import copy # Default error message template DEFAULT_ERROR_MESSAGE = """\ - -Error response - - -

Error response

-

Error code %(code)d. -

Message: %(message)s. -

Error code explanation: %(code)s = %(explain)s. - + + + + + Error response + + +

Error response

+

Error code: %(code)d

+

Message: %(message)s.

+

Error code explanation: %(code)s - %(explain)s.

+ + """ DEFAULT_ERROR_CONTENT_TYPE = "text/html;charset=utf-8" -- cgit v0.12 From f694a409aadf04e67d4e72a6f8e45dcbe34ab6e5 Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Thu, 17 Mar 2011 11:04:34 -0400 Subject: Give more info in verbose mode when checking crashers, and stress the stack even more in the compiler crasher --- Lib/test/crashers/compiler_recursion.py | 4 ++-- Lib/test/test_crashers.py | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Lib/test/crashers/compiler_recursion.py b/Lib/test/crashers/compiler_recursion.py index 8fd93fc..c00cd6e 100644 --- a/Lib/test/crashers/compiler_recursion.py +++ b/Lib/test/crashers/compiler_recursion.py @@ -9,5 +9,5 @@ Recorded on the tracker as http://bugs.python.org/issue11383 # e.g. '1*'*10**5+'1' will die in compiler_visit_expr # The exact limit to destroy the stack will vary by platform -# but 100k should do the trick most places -compile('()'*10**5, '?', 'exec') +# but 1M should do the trick most places +compile('()'*10**6, '?', 'exec') diff --git a/Lib/test/test_crashers.py b/Lib/test/test_crashers.py index ee612c2..86f88f7 100644 --- a/Lib/test/test_crashers.py +++ b/Lib/test/test_crashers.py @@ -24,6 +24,8 @@ class CrasherTest(unittest.TestCase): continue # Some "crashers" only trigger an exception rather than a # segfault. Consider that an acceptable outcome. + if test.support.verbose: + print("Checking crasher:", fname) assert_python_failure(fname) -- cgit v0.12 From 42ec7cb1050c5d1bdf5d504903fabe8bb372b5da Mon Sep 17 00:00:00 2001 From: Michael Foord Date: Thu, 17 Mar 2011 13:44:18 -0400 Subject: Issue #10979. unittest stdout buffering now works with class and module setup and teardown. --- Lib/unittest/result.py | 8 ++++- Lib/unittest/suite.py | 18 ++++++++++- Lib/unittest/test/test_result.py | 67 ++++++++++++++++++++++++++++++++++++++++ Misc/NEWS | 3 ++ 4 files changed, 94 insertions(+), 2 deletions(-) diff --git a/Lib/unittest/result.py b/Lib/unittest/result.py index 3dc7154..44bf186 100644 --- a/Lib/unittest/result.py +++ b/Lib/unittest/result.py @@ -59,6 +59,9 @@ class TestResult(object): "Called when the given test is about to be run" self.testsRun += 1 self._mirrorOutput = False + self._setupStdout() + + def _setupStdout(self): if self.buffer: if self._stderr_buffer is None: self._stderr_buffer = io.StringIO() @@ -74,6 +77,10 @@ class TestResult(object): def stopTest(self, test): """Called when the given test has been run""" + self._restoreStdout() + self._mirrorOutput = False + + def _restoreStdout(self): if self.buffer: if self._mirrorOutput: output = sys.stdout.getvalue() @@ -93,7 +100,6 @@ class TestResult(object): self._stdout_buffer.truncate() self._stderr_buffer.seek(0) self._stderr_buffer.truncate() - self._mirrorOutput = False def stopTestRun(self): """Called once after all tests are executed. diff --git a/Lib/unittest/suite.py b/Lib/unittest/suite.py index 77ce089..38bd6b8 100644 --- a/Lib/unittest/suite.py +++ b/Lib/unittest/suite.py @@ -8,6 +8,11 @@ from . import util __unittest = True +def _call_if_exists(parent, attr): + func = getattr(parent, attr, lambda: None) + func() + + class BaseTestSuite(object): """A simple test suite that doesn't provide class or module shared fixtures. """ @@ -133,6 +138,7 @@ class TestSuite(BaseTestSuite): setUpClass = getattr(currentClass, 'setUpClass', None) if setUpClass is not None: + _call_if_exists(result, '_setupStdout') try: setUpClass() except Exception as e: @@ -142,6 +148,8 @@ class TestSuite(BaseTestSuite): className = util.strclass(currentClass) errorName = 'setUpClass (%s)' % className self._addClassOrModuleLevelException(result, e, errorName) + finally: + _call_if_exists(result, '_restoreStdout') def _get_previous_module(self, result): previousModule = None @@ -167,6 +175,7 @@ class TestSuite(BaseTestSuite): return setUpModule = getattr(module, 'setUpModule', None) if setUpModule is not None: + _call_if_exists(result, '_setupStdout') try: setUpModule() except Exception as e: @@ -175,6 +184,8 @@ class TestSuite(BaseTestSuite): result._moduleSetUpFailed = True errorName = 'setUpModule (%s)' % currentModule self._addClassOrModuleLevelException(result, e, errorName) + finally: + _call_if_exists(result, '_restoreStdout') def _addClassOrModuleLevelException(self, result, exception, errorName): error = _ErrorHolder(errorName) @@ -198,6 +209,7 @@ class TestSuite(BaseTestSuite): tearDownModule = getattr(module, 'tearDownModule', None) if tearDownModule is not None: + _call_if_exists(result, '_setupStdout') try: tearDownModule() except Exception as e: @@ -205,6 +217,8 @@ class TestSuite(BaseTestSuite): raise errorName = 'tearDownModule (%s)' % previousModule self._addClassOrModuleLevelException(result, e, errorName) + finally: + _call_if_exists(result, '_restoreStdout') def _tearDownPreviousClass(self, test, result): previousClass = getattr(result, '_previousTestClass', None) @@ -220,6 +234,7 @@ class TestSuite(BaseTestSuite): tearDownClass = getattr(previousClass, 'tearDownClass', None) if tearDownClass is not None: + _call_if_exists(result, '_setupStdout') try: tearDownClass() except Exception as e: @@ -228,7 +243,8 @@ class TestSuite(BaseTestSuite): className = util.strclass(previousClass) errorName = 'tearDownClass (%s)' % className self._addClassOrModuleLevelException(result, e, errorName) - + finally: + _call_if_exists(result, '_restoreStdout') class _ErrorHolder(object): diff --git a/Lib/unittest/test/test_result.py b/Lib/unittest/test/test_result.py index 64798a1..1c58e61 100644 --- a/Lib/unittest/test/test_result.py +++ b/Lib/unittest/test/test_result.py @@ -497,5 +497,72 @@ class TestOutputBuffering(unittest.TestCase): self.assertEqual(result._original_stderr.getvalue(), expectedErrMessage) self.assertMultiLineEqual(message, expectedFullMessage) + def testBufferSetupClass(self): + result = unittest.TestResult() + result.buffer = True + + class Foo(unittest.TestCase): + @classmethod + def setUpClass(cls): + 1/0 + def test_foo(self): + pass + suite = unittest.TestSuite([Foo('test_foo')]) + suite(result) + self.assertEqual(len(result.errors), 1) + + def testBufferTearDownClass(self): + result = unittest.TestResult() + result.buffer = True + + class Foo(unittest.TestCase): + @classmethod + def tearDownClass(cls): + 1/0 + def test_foo(self): + pass + suite = unittest.TestSuite([Foo('test_foo')]) + suite(result) + self.assertEqual(len(result.errors), 1) + + def testBufferSetUpModule(self): + result = unittest.TestResult() + result.buffer = True + + class Foo(unittest.TestCase): + def test_foo(self): + pass + class Module(object): + @staticmethod + def setUpModule(): + 1/0 + + Foo.__module__ = 'Module' + sys.modules['Module'] = Module + self.addCleanup(sys.modules.pop, 'Module') + suite = unittest.TestSuite([Foo('test_foo')]) + suite(result) + self.assertEqual(len(result.errors), 1) + + def testBufferTearDownModule(self): + result = unittest.TestResult() + result.buffer = True + + class Foo(unittest.TestCase): + def test_foo(self): + pass + class Module(object): + @staticmethod + def tearDownModule(): + 1/0 + + Foo.__module__ = 'Module' + sys.modules['Module'] = Module + self.addCleanup(sys.modules.pop, 'Module') + suite = unittest.TestSuite([Foo('test_foo')]) + suite(result) + self.assertEqual(len(result.errors), 1) + + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS index 1bce668..6d6ba33 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ What's New in Python 3.2.1? Core and Builtins ----------------- +- Issue #10979: unittest stdout buffering now works with class and module + setup and teardown. + - Issue #11510: Fixed optimizer bug which turned "a,b={1,1}" into "a,b=(1,1)". - Issue #11432: A bug was introduced in subprocess.Popen on posix systems with -- cgit v0.12 From f40834f39b7bf1e667fbe040fe869232d2488f60 Mon Sep 17 00:00:00 2001 From: Michael Foord Date: Thu, 17 Mar 2011 13:47:12 -0400 Subject: Move NEWS entry to correct place --- Misc/NEWS | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS index 6d6ba33..432441a 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,9 +10,6 @@ What's New in Python 3.2.1? Core and Builtins ----------------- -- Issue #10979: unittest stdout buffering now works with class and module - setup and teardown. - - Issue #11510: Fixed optimizer bug which turned "a,b={1,1}" into "a,b=(1,1)". - Issue #11432: A bug was introduced in subprocess.Popen on posix systems with @@ -43,6 +40,10 @@ Core and Builtins Library ------- + +- Issue #10979: unittest stdout buffering now works with class and module + setup and teardown. + - Issue #11577: fix ResourceWarning triggered by improved binhex test coverage - Issue #11243: fix the parameter querying methods of Message to work if -- cgit v0.12 From 7807c3545d9a6176ac0908a269481cf0eb3a60e6 Mon Sep 17 00:00:00 2001 From: Ross Lagerwall Date: Thu, 17 Mar 2011 20:20:30 +0200 Subject: Issue #10812: Add some extra posix functions to the os module. --- Doc/library/os.rst | 238 +++++++++++ Lib/test/test_posix.py | 152 ++++++- Misc/NEWS | 1 + Modules/posixmodule.c | 1074 ++++++++++++++++++++++++++++++++++++++---------- configure | 17 +- configure.in | 14 +- pyconfig.h.in | 39 ++ 7 files changed, 1313 insertions(+), 222 deletions(-) diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 2950f7f..eca51dc 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -743,6 +743,17 @@ as internal buffering of data. .. versionadded:: 3.3 +.. function:: fexecve(fd, args, env) + + Execute the program specified by a file descriptor *fd* with arguments given + by *args* and environment given by *env*, replacing the current process. + *args* and *env* are given as in :func:`execve`. + + Availability: Unix. + + .. versionadded:: 3.3 + + .. function:: fpathconf(fd, name) Return system configuration information relevant to an open file. *name* @@ -819,6 +830,45 @@ as internal buffering of data. .. versionadded:: 3.3 +.. function:: futimens(fd, (atime_sec, atime_nsec), (mtime_sec, mtime_nsec)) + futimens(fd, None, None) + + Updates the timestamps of a file specified by the file descriptor *fd*, with + nanosecond precision. + The second form sets *atime* and *mtime* to the current time. + If *atime_nsec* or *mtime_nsec* is specified as :data:`UTIME_NOW`, the corresponding + timestamp is updated to the current time. + If *atime_nsec* or *mtime_nsec* is specified as :data:`UTIME_OMIT`, the corresponding + timestamp is not updated. + + Availability: Unix. + + .. versionadded:: 3.3 + + +.. data:: UTIME_NOW + UTIME_OMIT + + Flags used with :func:`futimens` to specify that the timestamp must be + updated either to the current time or not updated at all. + + Availability: Unix. + + .. versionadded:: 3.3 + + +.. function:: futimes(fd, (atime, mtime)) + futimes(fd, None) + + Set the access and modified time of the file specified by the file + descriptor *fd* to the given values. If the second form is used, set the + access and modified times to the current time. + + Availability: Unix. + + .. versionadded:: 3.3 + + .. function:: isatty(fd) Return ``True`` if the file descriptor *fd* is open and connected to a @@ -841,6 +891,30 @@ as internal buffering of data. .. versionadded:: 3.3 +.. function:: lockf(fd, cmd, len) + + Apply, test or remove a POSIX lock on an open file descriptor. + *fd* is an open file descriptor. + *cmd* specifies the command to use - one of :data:`F_LOCK`, :data:`F_TLOCK`, + :data:`F_ULOCK` or :data:`F_TEST`. + *len* specifies the section of the file to lock. + + Availability: Unix. + + .. versionadded:: 3.3 + + +.. data:: F_LOCK + F_TLOCK + F_ULOCK + F_TEST + + Flags that specify what action :func:`lockf` will take. + + Availability: Unix. + + .. versionadded:: 3.3 + .. function:: lseek(fd, pos, how) Set the current position of file descriptor *fd* to position *pos*, modified @@ -945,6 +1019,66 @@ as internal buffering of data. Availability: Unix, Windows. +.. function:: posix_fallocate(fd, offset, len) + + Ensures that enough disk space is allocated for the file specified by *fd* + starting from *offset* and continuing for *len* bytes. + + Availability: Unix. + + .. versionadded:: 3.3 + + +.. function:: posix_fadvise(fd, offset, len, advice) + + Announces an intention to access data in a specific pattern thus allowing + the kernel to make optimizations. + The advice applies to the region of the file specified by *fd* starting at + *offset* and continuing for *len* bytes. + *advice* is one of :data:`POSIX_FADV_NORMAL`, :data:`POSIX_FADV_SEQUENTIAL`, + :data:`POSIX_FADV_RANDOM`, :data:`POSIX_FADV_NOREUSE`, + :data:`POSIX_FADV_WILLNEED` or :data:`POSIX_FADV_DONTNEED`. + + Availability: Unix. + + .. versionadded:: 3.3 + + +.. data:: POSIX_FADV_NORMAL + POSIX_FADV_SEQUENTIAL + POSIX_FADV_RANDOM + POSIX_FADV_NOREUSE + POSIX_FADV_WILLNEED + POSIX_FADV_DONTNEED + + Flags that can be used in *advice* in :func:`posix_fadvise` that specify + the access pattern that is likely to be used. + + Availability: Unix. + + .. versionadded:: 3.3 + + +.. function:: pread(fd, buffersize, offset) + + Read from a file descriptor, *fd*, at a position of *offset*. It will read up + to *buffersize* number of bytes. The file offset remains unchanged. + + Availability: Unix. + + .. versionadded:: 3.3 + + +.. function:: pwrite(fd, string, offset) + + Write *string* to a file descriptor, *fd*, from *offset*, leaving the file + offset unchanged. + + Availability: Unix. + + .. versionadded:: 3.3 + + .. function:: read(fd, n) Read at most *n* bytes from file descriptor *fd*. Return a bytestring containing the @@ -1038,6 +1172,17 @@ as internal buffering of data. .. versionadded:: 3.3 +.. function:: readv(fd, buffers) + + Read from a file descriptor into a number of writable buffers. *buffers* is + an arbitrary sequence of writable buffers. Returns the total number of bytes + read. + + Availability: Unix. + + .. versionadded:: 3.3 + + .. function:: tcgetpgrp(fd) Return the process group associated with the terminal given by *fd* (an open @@ -1111,6 +1256,17 @@ as internal buffering of data. :meth:`~file.write` method. +.. function:: writev(fd, buffers) + + Write the the contents of *buffers* to file descriptor *fd*, where *buffers* + is an arbitrary sequence of buffers. + Returns the total number of bytes written. + + Availability: Unix. + + .. versionadded:: 3.3 + + .. _open-constants: ``open()`` flag constants @@ -1384,6 +1540,17 @@ Files and Directories Added support for Windows 6.0 (Vista) symbolic links. +.. function:: lutimes(path, (atime, mtime)) + lutimes(path, None) + + Like :func:`utime`, but if *path* is a symbolic link, it is not + dereferenced. + + Availability: Unix. + + .. versionadded:: 3.3 + + .. function:: mkfifo(path[, mode]) Create a FIFO (a named pipe) named *path* with numeric mode *mode*. The @@ -1727,6 +1894,25 @@ Files and Directories Added support for Windows 6.0 (Vista) symbolic links. +.. function:: sync() + + Force write of everything to disk. + + Availability: Unix. + + .. versionadded:: 3.3 + + +.. function:: truncate(path, length) + + Truncate the file corresponding to *path*, so that it is at most + *length* bytes in size. + + Availability: Unix. + + .. versionadded:: 3.3 + + .. function:: unlink(path) Remove (delete) the file *path*. This is the same function as @@ -2306,6 +2492,58 @@ written in Python, such as a mail server's external command delivery program. Availability: Unix. +.. function:: waitid(idtype, id, options) + + Wait for the completion of one or more child processes. + *idtype* can be :data:`P_PID`, :data:`P_PGID` or :data:`P_ALL`. + *id* specifies the pid to wait on. + *options* is constructed from the ORing of one or more of :data:`WEXITED`, + :data:`WSTOPPED` or :data:`WCONTINUED` and additionally may be ORed with + :data:`WNOHANG` or :data:`WNOWAIT`. The return value is an object + representing the data contained in the :c:type:`siginfo_t` structure, namely: + :attr:`si_pid`, :attr:`si_uid`, :attr:`si_signo`, :attr:`si_status`, + :attr:`si_code` or ``None`` if :data:`WNOHANG` is specified and there are no + children in a waitable state. + + Availability: Unix. + + .. versionadded:: 3.3 + +.. data:: P_PID + P_PGID + P_ALL + + These are the possible values for *idtype* in :func:`waitid`. They affect + how *id* is interpreted. + + Availability: Unix. + + .. versionadded:: 3.3 + +.. data:: WEXITED + WSTOPPED + WNOWAIT + + Flags that can be used in *options* in :func:`waitid` that specify what + child signal to wait for. + + Availability: Unix. + + .. versionadded:: 3.3 + + +.. data:: CLD_EXITED + CLD_DUMPED + CLD_TRAPPED + CLD_CONTINUED + + These are the possible values for :attr:`si_code` in the result returned by + :func:`waitid`. + + Availability: Unix. + + .. versionadded:: 3.3 + .. function:: waitpid(pid, options) diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py index 23c2100..72bc1de 100644 --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -37,7 +37,7 @@ class PosixTester(unittest.TestCase): NO_ARG_FUNCTIONS = [ "ctermid", "getcwd", "getcwdb", "uname", "times", "getloadavg", "getegid", "geteuid", "getgid", "getgroups", - "getpid", "getpgrp", "getppid", "getuid", + "getpid", "getpgrp", "getppid", "getuid", "sync", ] for name in NO_ARG_FUNCTIONS: @@ -132,6 +132,156 @@ class PosixTester(unittest.TestCase): finally: fp.close() + @unittest.skipUnless(hasattr(posix, 'truncate'), "test needs posix.truncate()") + def test_truncate(self): + with open(support.TESTFN, 'w') as fp: + fp.write('test') + fp.flush() + posix.truncate(support.TESTFN, 0) + + @unittest.skipUnless(hasattr(posix, 'fexecve'), "test needs posix.fexecve()") + @unittest.skipUnless(hasattr(os, 'fork'), "test needs os.fork()") + @unittest.skipUnless(hasattr(os, 'wait'), "test needs os.wait()") + def test_fexecve(self): + fp = os.open(sys.executable, os.O_RDONLY) + try: + pid = os.fork() + if pid == 0: + os.chdir(os.path.split(sys.executable)[0]) + posix.fexecve(fp, [sys.executable, '-c', 'pass'], os.environ) + else: + self.assertEqual(os.wait(), (pid, 0)) + finally: + os.close(fp) + + @unittest.skipUnless(hasattr(posix, 'waitid'), "test needs posix.waitid()") + @unittest.skipUnless(hasattr(os, 'fork'), "test needs os.fork()") + def test_waitid(self): + pid = os.fork() + if pid == 0: + os.chdir(os.path.split(sys.executable)[0]) + posix.execve(sys.executable, [sys.executable, '-c', 'pass'], os.environ) + else: + res = posix.waitid(posix.P_PID, pid, posix.WEXITED) + self.assertEqual(pid, res.si_pid) + + @unittest.skipUnless(hasattr(posix, 'lockf'), "test needs posix.lockf()") + def test_lockf(self): + fd = os.open(support.TESTFN, os.O_WRONLY | os.O_CREAT) + try: + os.write(fd, b'test') + os.lseek(fd, 0, os.SEEK_SET) + posix.lockf(fd, posix.F_LOCK, 4) + # section is locked + posix.lockf(fd, posix.F_ULOCK, 4) + finally: + os.close(fd) + + @unittest.skipUnless(hasattr(posix, 'pread'), "test needs posix.pread()") + def test_pread(self): + fd = os.open(support.TESTFN, os.O_RDWR | os.O_CREAT) + try: + os.write(fd, b'test') + os.lseek(fd, 0, os.SEEK_SET) + self.assertEqual(b'es', posix.pread(fd, 2, 1)) + # the first pread() shoudn't disturb the file offset + self.assertEqual(b'te', posix.read(fd, 2)) + finally: + os.close(fd) + + @unittest.skipUnless(hasattr(posix, 'pwrite'), "test needs posix.pwrite()") + def test_pwrite(self): + fd = os.open(support.TESTFN, os.O_RDWR | os.O_CREAT) + try: + os.write(fd, b'test') + os.lseek(fd, 0, os.SEEK_SET) + posix.pwrite(fd, b'xx', 1) + self.assertEqual(b'txxt', posix.read(fd, 4)) + finally: + os.close(fd) + + @unittest.skipUnless(hasattr(posix, 'posix_fallocate'), + "test needs posix.posix_fallocate()") + def test_posix_fallocate(self): + fd = os.open(support.TESTFN, os.O_WRONLY | os.O_CREAT) + try: + posix.posix_fallocate(fd, 0, 10) + except OSError as inst: + # issue10812, ZFS doesn't appear to support posix_fallocate, + # so skip Solaris-based since they are likely to have ZFS. + if inst.errno != errno.EINVAL or not sys.platform.startswith("sunos"): + raise + finally: + os.close(fd) + + @unittest.skipUnless(hasattr(posix, 'posix_fadvise'), + "test needs posix.posix_fadvise()") + def test_posix_fadvise(self): + fd = os.open(support.TESTFN, os.O_RDONLY) + try: + posix.posix_fadvise(fd, 0, 0, posix.POSIX_FADV_WILLNEED) + finally: + os.close(fd) + + @unittest.skipUnless(hasattr(posix, 'futimes'), "test needs posix.futimes()") + def test_futimes(self): + now = time.time() + fd = os.open(support.TESTFN, os.O_RDONLY) + try: + posix.futimes(fd, None) + self.assertRaises(TypeError, posix.futimes, fd, (None, None)) + self.assertRaises(TypeError, posix.futimes, fd, (now, None)) + self.assertRaises(TypeError, posix.futimes, fd, (None, now)) + posix.futimes(fd, (int(now), int(now))) + posix.futimes(fd, (now, now)) + finally: + os.close(fd) + + @unittest.skipUnless(hasattr(posix, 'lutimes'), "test needs posix.lutimes()") + def test_lutimes(self): + now = time.time() + posix.lutimes(support.TESTFN, None) + self.assertRaises(TypeError, posix.lutimes, support.TESTFN, (None, None)) + self.assertRaises(TypeError, posix.lutimes, support.TESTFN, (now, None)) + self.assertRaises(TypeError, posix.lutimes, support.TESTFN, (None, now)) + posix.lutimes(support.TESTFN, (int(now), int(now))) + posix.lutimes(support.TESTFN, (now, now)) + + @unittest.skipUnless(hasattr(posix, 'futimens'), "test needs posix.futimens()") + def test_futimens(self): + now = time.time() + fd = os.open(support.TESTFN, os.O_RDONLY) + try: + self.assertRaises(TypeError, posix.futimens, fd, (None, None), (None, None)) + self.assertRaises(TypeError, posix.futimens, fd, (now, 0), None) + self.assertRaises(TypeError, posix.futimens, fd, None, (now, 0)) + posix.futimens(fd, (int(now), int((now - int(now)) * 1e9)), + (int(now), int((now - int(now)) * 1e9))) + finally: + os.close(fd) + + @unittest.skipUnless(hasattr(posix, 'writev'), "test needs posix.writev()") + def test_writev(self): + fd = os.open(support.TESTFN, os.O_RDWR | os.O_CREAT) + try: + os.writev(fd, (b'test1', b'tt2', b't3')) + os.lseek(fd, 0, os.SEEK_SET) + self.assertEqual(b'test1tt2t3', posix.read(fd, 10)) + finally: + os.close(fd) + + @unittest.skipUnless(hasattr(posix, 'readv'), "test needs posix.readv()") + def test_readv(self): + fd = os.open(support.TESTFN, os.O_RDWR | os.O_CREAT) + try: + os.write(fd, b'test1tt2t3') + os.lseek(fd, 0, os.SEEK_SET) + buf = [bytearray(i) for i in [5, 3, 2]] + self.assertEqual(posix.readv(fd, buf), 10) + self.assertEqual([b'test1', b'tt2', b't3'], [bytes(i) for i in buf]) + finally: + os.close(fd) + def test_dup(self): if hasattr(posix, 'dup'): fp = open(support.TESTFN) diff --git a/Misc/NEWS b/Misc/NEWS index a5cf8be..d8e05fb 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -72,6 +72,7 @@ Core and Builtins Library ------- +- Issue #10812: Add some extra posix functions to the os module. - Issue #10979: unittest stdout buffering now works with class and module setup and teardown. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 8332cfe..cc908e2 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1503,6 +1503,33 @@ static PyStructSequence_Desc statvfs_result_desc = { 10 }; +#if defined(HAVE_WAITID) && !defined(__APPLE__) +PyDoc_STRVAR(waitid_result__doc__, +"waitid_result: Result from waitid.\n\n\ +This object may be accessed either as a tuple of\n\ + (si_pid, si_uid, si_signo, si_status, si_code),\n\ +or via the attributes si_pid, si_uid, and so on.\n\ +\n\ +See os.waitid for more information."); + +static PyStructSequence_Field waitid_result_fields[] = { + {"si_pid", }, + {"si_uid", }, + {"si_signo", }, + {"si_status", }, + {"si_code", }, + {0} +}; + +static PyStructSequence_Desc waitid_result_desc = { + "waitid_result", /* name */ + waitid_result__doc__, /* doc */ + waitid_result_fields, + 5 +}; +static PyTypeObject WaitidResultType; +#endif + static int initialized; static PyTypeObject StatResultType; static PyTypeObject StatVFSResultType; @@ -2102,6 +2129,21 @@ posix_fsync(PyObject *self, PyObject *fdobj) } #endif /* HAVE_FSYNC */ +#ifdef HAVE_SYNC +PyDoc_STRVAR(posix_sync__doc__, +"sync()\n\n\ +Force write of everything to disk."); + +static PyObject * +posix_sync(PyObject *self, PyObject *noargs) +{ + Py_BEGIN_ALLOW_THREADS + sync(); + Py_END_ALLOW_THREADS + Py_RETURN_NONE; +} +#endif + #ifdef HAVE_FDATASYNC #ifdef __hpux @@ -3488,6 +3530,167 @@ done: #endif /* MS_WINDOWS */ } +#ifdef HAVE_FUTIMES +PyDoc_STRVAR(posix_futimes__doc__, +"futimes(fd, (atime, mtime))\n\ +futimes(fd, None)\n\n\ +Set the access and modified time of the file specified by the file\n\ +descriptor fd to the given values. If the second form is used, set the\n\ +access and modified times to the current time."); + +static PyObject * +posix_futimes(PyObject *self, PyObject *args) +{ + int res, fd; + PyObject* arg; + struct timeval buf[2]; + long ausec, musec; + + if (!PyArg_ParseTuple(args, "iO:futimes", &fd, &arg)) + return NULL; + + if (arg == Py_None) { + /* optional time values not given */ + Py_BEGIN_ALLOW_THREADS + res = futimes(fd, NULL); + Py_END_ALLOW_THREADS + } + else if (!PyTuple_Check(arg) || PyTuple_Size(arg) != 2) { + PyErr_SetString(PyExc_TypeError, + "futimes() arg 2 must be a tuple (atime, mtime)"); + return NULL; + } + else { + if (extract_time(PyTuple_GET_ITEM(arg, 0), + &(buf[0].tv_sec), &ausec) == -1) { + return NULL; + } + if (extract_time(PyTuple_GET_ITEM(arg, 1), + &(buf[1].tv_sec), &musec) == -1) { + return NULL; + } + buf[0].tv_usec = ausec; + buf[1].tv_usec = musec; + Py_BEGIN_ALLOW_THREADS + res = futimes(fd, buf); + Py_END_ALLOW_THREADS + } + if (res < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif + +#ifdef HAVE_LUTIMES +PyDoc_STRVAR(posix_lutimes__doc__, +"lutimes(path, (atime, mtime))\n\ +lutimes(path, None)\n\n\ +Like utime(), but if path is a symbolic link, it is not dereferenced."); + +static PyObject * +posix_lutimes(PyObject *self, PyObject *args) +{ + PyObject *opath, *arg; + const char *path; + int res; + struct timeval buf[2]; + long ausec, musec; + + if (!PyArg_ParseTuple(args, "O&O:lutimes", + PyUnicode_FSConverter, &opath, &arg)) + return NULL; + path = PyBytes_AsString(opath); + if (arg == Py_None) { + /* optional time values not given */ + Py_BEGIN_ALLOW_THREADS + res = lutimes(path, NULL); + Py_END_ALLOW_THREADS + } + else if (!PyTuple_Check(arg) || PyTuple_Size(arg) != 2) { + PyErr_SetString(PyExc_TypeError, + "lutimes() arg 2 must be a tuple (atime, mtime)"); + Py_DECREF(opath); + return NULL; + } + else { + if (extract_time(PyTuple_GET_ITEM(arg, 0), + &(buf[0].tv_sec), &ausec) == -1) { + Py_DECREF(opath); + return NULL; + } + if (extract_time(PyTuple_GET_ITEM(arg, 1), + &(buf[1].tv_sec), &musec) == -1) { + Py_DECREF(opath); + return NULL; + } + buf[0].tv_usec = ausec; + buf[1].tv_usec = musec; + Py_BEGIN_ALLOW_THREADS + res = lutimes(path, buf); + Py_END_ALLOW_THREADS + } + Py_DECREF(opath); + if (res < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif + +#ifdef HAVE_FUTIMENS +PyDoc_STRVAR(posix_futimens__doc__, +"futimens(fd, (atime_sec, atime_nsec), (mtime_sec, mtime_nsec))\n\ +futimens(fd, None, None)\n\n\ +Updates the timestamps of a file specified by the file descriptor fd, with\n\ +nanosecond precision.\n\ +The second form sets atime and mtime to the current time.\n\ +If *_nsec is specified as UTIME_NOW, the timestamp is updated to the\n\ +current time.\n\ +If *_nsec is specified as UTIME_OMIT, the timestamp is not updated."); + +static PyObject * +posix_futimens(PyObject *self, PyObject *args) +{ + int res, fd; + PyObject *atime, *mtime; + struct timespec buf[2]; + + if (!PyArg_ParseTuple(args, "iOO:futimens", + &fd, &atime, &mtime)) + return NULL; + if (atime == Py_None && mtime == Py_None) { + /* optional time values not given */ + Py_BEGIN_ALLOW_THREADS + res = futimens(fd, NULL); + Py_END_ALLOW_THREADS + } + else if (!PyTuple_Check(atime) || PyTuple_Size(atime) != 2) { + PyErr_SetString(PyExc_TypeError, + "futimens() arg 2 must be a tuple (atime_sec, atime_nsec)"); + return NULL; + } + else if (!PyTuple_Check(mtime) || PyTuple_Size(mtime) != 2) { + PyErr_SetString(PyExc_TypeError, + "futimens() arg 3 must be a tuple (mtime_sec, mtime_nsec)"); + return NULL; + } + else { + if (!PyArg_ParseTuple(atime, "ll:futimens", + &(buf[0].tv_sec), &(buf[0].tv_nsec))) { + return NULL; + } + if (!PyArg_ParseTuple(mtime, "ll:futimens", + &(buf[1].tv_sec), &(buf[1].tv_nsec))) { + return NULL; + } + Py_BEGIN_ALLOW_THREADS + res = futimens(fd, buf); + Py_END_ALLOW_THREADS + } + if (res < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif /* Process operations */ @@ -3532,79 +3735,7 @@ int fsconvert_strdup(PyObject *o, char**out) } #endif - -#ifdef HAVE_EXECV -PyDoc_STRVAR(posix_execv__doc__, -"execv(path, args)\n\n\ -Execute an executable path with arguments, replacing current process.\n\ -\n\ - path: path of executable file\n\ - args: tuple or list of strings"); - -static PyObject * -posix_execv(PyObject *self, PyObject *args) -{ - PyObject *opath; - char *path; - PyObject *argv; - char **argvlist; - Py_ssize_t i, argc; - PyObject *(*getitem)(PyObject *, Py_ssize_t); - - /* execv has two arguments: (path, argv), where - argv is a list or tuple of strings. */ - - if (!PyArg_ParseTuple(args, "O&O:execv", - PyUnicode_FSConverter, - &opath, &argv)) - return NULL; - path = PyBytes_AsString(opath); - if (PyList_Check(argv)) { - argc = PyList_Size(argv); - getitem = PyList_GetItem; - } - else if (PyTuple_Check(argv)) { - argc = PyTuple_Size(argv); - getitem = PyTuple_GetItem; - } - else { - PyErr_SetString(PyExc_TypeError, "execv() arg 2 must be a tuple or list"); - Py_DECREF(opath); - return NULL; - } - if (argc < 1) { - PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty"); - Py_DECREF(opath); - return NULL; - } - - argvlist = PyMem_NEW(char *, argc+1); - if (argvlist == NULL) { - Py_DECREF(opath); - return PyErr_NoMemory(); - } - for (i = 0; i < argc; i++) { - if (!fsconvert_strdup((*getitem)(argv, i), - &argvlist[i])) { - free_string_array(argvlist, i); - PyErr_SetString(PyExc_TypeError, - "execv() arg 2 must contain only strings"); - Py_DECREF(opath); - return NULL; - - } - } - argvlist[argc] = NULL; - - execv(path, argvlist); - - /* If we get here it's definitely an error */ - - free_string_array(argvlist, argc); - Py_DECREF(opath); - return posix_error(); -} - +#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) static char** parse_envlist(PyObject* env, Py_ssize_t *envc_ptr) { @@ -3686,6 +3817,84 @@ error: return NULL; } +static char** +parse_arglist(PyObject* argv, Py_ssize_t *argc) +{ + int i; + char **argvlist = PyMem_NEW(char *, *argc+1); + if (argvlist == NULL) { + PyErr_NoMemory(); + return NULL; + } + for (i = 0; i < *argc; i++) { + if (!fsconvert_strdup(PySequence_ITEM(argv, i), + &argvlist[i])) + { + *argc = i; + goto fail; + } + } + argvlist[*argc] = NULL; + return argvlist; +fail: + free_string_array(argvlist, *argc); + return NULL; +} +#endif + +#ifdef HAVE_EXECV +PyDoc_STRVAR(posix_execv__doc__, +"execv(path, args)\n\n\ +Execute an executable path with arguments, replacing current process.\n\ +\n\ + path: path of executable file\n\ + args: tuple or list of strings"); + +static PyObject * +posix_execv(PyObject *self, PyObject *args) +{ + PyObject *opath; + char *path; + PyObject *argv; + char **argvlist; + Py_ssize_t argc; + + /* execv has two arguments: (path, argv), where + argv is a list or tuple of strings. */ + + if (!PyArg_ParseTuple(args, "O&O:execv", + PyUnicode_FSConverter, + &opath, &argv)) + return NULL; + path = PyBytes_AsString(opath); + if (!PyList_Check(argv) && !PyTuple_Check(argv)) { + PyErr_SetString(PyExc_TypeError, + "execv() arg 2 must be a tuple or list"); + Py_DECREF(opath); + return NULL; + } + argc = PySequence_Size(argv); + if (argc < 1) { + PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty"); + Py_DECREF(opath); + return NULL; + } + + argvlist = parse_arglist(argv, &argc); + if (argvlist == NULL) { + Py_DECREF(opath); + return NULL; + } + + execv(path, argvlist); + + /* If we get here it's definitely an error */ + + free_string_array(argvlist, argc); + Py_DECREF(opath); + return posix_error(); +} + PyDoc_STRVAR(posix_execve__doc__, "execve(path, args, env)\n\n\ Execute a path with arguments and environment, replacing current process.\n\ @@ -3702,9 +3911,7 @@ posix_execve(PyObject *self, PyObject *args) PyObject *argv, *env; char **argvlist; char **envlist; - Py_ssize_t i, argc, envc; - PyObject *(*getitem)(PyObject *, Py_ssize_t); - Py_ssize_t lastarg = 0; + Py_ssize_t argc, envc; /* execve has three arguments: (path, argv, env), where argv is a list or tuple of strings and env is a dictionary @@ -3715,40 +3922,22 @@ posix_execve(PyObject *self, PyObject *args) &opath, &argv, &env)) return NULL; path = PyBytes_AsString(opath); - if (PyList_Check(argv)) { - argc = PyList_Size(argv); - getitem = PyList_GetItem; - } - else if (PyTuple_Check(argv)) { - argc = PyTuple_Size(argv); - getitem = PyTuple_GetItem; - } - else { + if (!PyList_Check(argv) && !PyTuple_Check(argv)) { PyErr_SetString(PyExc_TypeError, "execve() arg 2 must be a tuple or list"); goto fail_0; } + argc = PySequence_Size(argv); if (!PyMapping_Check(env)) { PyErr_SetString(PyExc_TypeError, "execve() arg 3 must be a mapping object"); goto fail_0; } - argvlist = PyMem_NEW(char *, argc+1); + argvlist = parse_arglist(argv, &argc); if (argvlist == NULL) { - PyErr_NoMemory(); goto fail_0; } - for (i = 0; i < argc; i++) { - if (!fsconvert_strdup((*getitem)(argv, i), - &argvlist[i])) - { - lastarg = i; - goto fail_1; - } - } - lastarg = argc; - argvlist[argc] = NULL; envlist = parse_envlist(env, &envc); if (envlist == NULL) @@ -3764,13 +3953,69 @@ posix_execve(PyObject *self, PyObject *args) PyMem_DEL(envlist[envc]); PyMem_DEL(envlist); fail_1: - free_string_array(argvlist, lastarg); + free_string_array(argvlist, argc); fail_0: Py_DECREF(opath); return NULL; } #endif /* HAVE_EXECV */ +#ifdef HAVE_FEXECVE +PyDoc_STRVAR(posix_fexecve__doc__, +"fexecve(fd, args, env)\n\n\ +Execute the program specified by a file descriptor with arguments and\n\ +environment, replacing the current process.\n\ +\n\ + fd: file descriptor of executable\n\ + args: tuple or list of arguments\n\ + env: dictionary of strings mapping to strings"); + +static PyObject * +posix_fexecve(PyObject *self, PyObject *args) +{ + int fd; + PyObject *argv, *env; + char **argvlist; + char **envlist; + Py_ssize_t argc, envc; + + if (!PyArg_ParseTuple(args, "iOO:fexecve", + &fd, &argv, &env)) + return NULL; + if (!PyList_Check(argv) && !PyTuple_Check(argv)) { + PyErr_SetString(PyExc_TypeError, + "fexecve() arg 2 must be a tuple or list"); + return NULL; + } + argc = PySequence_Size(argv); + if (!PyMapping_Check(env)) { + PyErr_SetString(PyExc_TypeError, + "fexecve() arg 3 must be a mapping object"); + return NULL; + } + + argvlist = parse_arglist(argv, &argc); + if (argvlist == NULL) + return NULL; + + envlist = parse_envlist(env, &envc); + if (envlist == NULL) + goto fail; + + fexecve(fd, argvlist, envlist); + + /* If we get here it's definitely an error */ + + (void) posix_error(); + + while (--envc >= 0) + PyMem_DEL(envlist[envc]); + PyMem_DEL(envlist); + fail: + free_string_array(argvlist, argc); + return NULL; +} +#endif /* HAVE_FEXECVE */ #ifdef HAVE_SPAWNV PyDoc_STRVAR(posix_spawnv__doc__, @@ -4337,6 +4582,7 @@ posix_forkpty(PyObject *self, PyObject *noargs) } #endif + #ifdef HAVE_GETEGID PyDoc_STRVAR(posix_getegid__doc__, "getegid() -> egid\n\n\ @@ -5127,6 +5373,55 @@ posix_wait4(PyObject *self, PyObject *args) } #endif /* HAVE_WAIT4 */ +#if defined(HAVE_WAITID) && !defined(__APPLE__) +PyDoc_STRVAR(posix_waitid__doc__, +"waitid(idtype, id, options) -> waitid_result\n\n\ +Wait for the completion of one or more child processes.\n\n\ +idtype can be P_PID, P_PGID or P_ALL.\n\ +id specifies the pid to wait on.\n\ +options is constructed from the ORing of one or more of WEXITED, WSTOPPED\n\ +or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.\n\ +Returns either waitid_result or None if WNOHANG is specified and there are\n\ +no children in a waitable state."); + +static PyObject * +posix_waitid(PyObject *self, PyObject *args) +{ + PyObject *result; + idtype_t idtype; + id_t id; + int options, res; + siginfo_t si; + si.si_pid = 0; + if (!PyArg_ParseTuple(args, "i" _Py_PARSE_PID "i:waitid", &idtype, &id, &options)) + return NULL; + Py_BEGIN_ALLOW_THREADS + res = waitid(idtype, id, &si, options); + Py_END_ALLOW_THREADS + if (res == -1) + return posix_error(); + + if (si.si_pid == 0) + Py_RETURN_NONE; + + result = PyStructSequence_New(&WaitidResultType); + if (!result) + return NULL; + + PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid)); + PyStructSequence_SET_ITEM(result, 1, PyLong_FromPid(si.si_uid)); + PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo))); + PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status))); + PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code))); + if (PyErr_Occurred()) { + Py_DECREF(result); + return NULL; + } + + return result; +} +#endif + #ifdef HAVE_WAITPID PyDoc_STRVAR(posix_waitpid__doc__, "waitpid(pid, options) -> (pid, status)\n\n\ @@ -5742,72 +6037,223 @@ posix_dup2(PyObject *self, PyObject *args) return Py_None; } +#ifdef HAVE_LOCKF +PyDoc_STRVAR(posix_lockf__doc__, +"lockf(fd, cmd, len)\n\n\ +Apply, test or remove a POSIX lock on an open file descriptor.\n\n\ +fd is an open file descriptor.\n\ +cmd specifies the command to use - one of F_LOCK, F_TLOCK, F_ULOCK or\n\ +F_TEST.\n\ +len specifies the section of the file to lock."); + +static PyObject * +posix_lockf(PyObject *self, PyObject *args) +{ + int fd, cmd, res; + off_t len; + if (!PyArg_ParseTuple(args, "iiO&:lockf", + &fd, &cmd, _parse_off_t, &len)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + res = lockf(fd, cmd, len); + Py_END_ALLOW_THREADS + + if (res < 0) + return posix_error(); + + Py_RETURN_NONE; +} +#endif + + +PyDoc_STRVAR(posix_lseek__doc__, +"lseek(fd, pos, how) -> newpos\n\n\ +Set the current position of a file descriptor."); + +static PyObject * +posix_lseek(PyObject *self, PyObject *args) +{ + int fd, how; +#if defined(MS_WIN64) || defined(MS_WINDOWS) + PY_LONG_LONG pos, res; +#else + off_t pos, res; +#endif + if (!PyArg_ParseTuple(args, "iO&i:lseek", &fd, _parse_off_t, &pos, &how)) + return NULL; +#ifdef SEEK_SET + /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */ + switch (how) { + case 0: how = SEEK_SET; break; + case 1: how = SEEK_CUR; break; + case 2: how = SEEK_END; break; + } +#endif /* SEEK_END */ + + if (PyErr_Occurred()) + return NULL; + + if (!_PyVerify_fd(fd)) + return posix_error(); + Py_BEGIN_ALLOW_THREADS +#if defined(MS_WIN64) || defined(MS_WINDOWS) + res = _lseeki64(fd, pos, how); +#else + res = lseek(fd, pos, how); +#endif + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error(); + +#if !defined(HAVE_LARGEFILE_SUPPORT) + return PyLong_FromLong(res); +#else + return PyLong_FromLongLong(res); +#endif +} + + +PyDoc_STRVAR(posix_read__doc__, +"read(fd, buffersize) -> string\n\n\ +Read a file descriptor."); + +static PyObject * +posix_read(PyObject *self, PyObject *args) +{ + int fd, size; + Py_ssize_t n; + PyObject *buffer; + if (!PyArg_ParseTuple(args, "ii:read", &fd, &size)) + return NULL; + if (size < 0) { + errno = EINVAL; + return posix_error(); + } + buffer = PyBytes_FromStringAndSize((char *)NULL, size); + if (buffer == NULL) + return NULL; + if (!_PyVerify_fd(fd)) { + Py_DECREF(buffer); + return posix_error(); + } + Py_BEGIN_ALLOW_THREADS + n = read(fd, PyBytes_AS_STRING(buffer), size); + Py_END_ALLOW_THREADS + if (n < 0) { + Py_DECREF(buffer); + return posix_error(); + } + if (n != size) + _PyBytes_Resize(&buffer, n); + return buffer; +} + +#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \ + || defined(__APPLE__))) || defined(HAVE_READV) || defined(HAVE_WRITEV) +static Py_ssize_t +iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, int cnt, int type) +{ + int i, j; + Py_ssize_t blen, total = 0; + + *iov = PyMem_New(struct iovec, cnt); + if (*iov == NULL) { + PyErr_NoMemory(); + return total; + } + + *buf = PyMem_New(Py_buffer, cnt); + if (*buf == NULL) { + PyMem_Del(*iov); + PyErr_NoMemory(); + return total; + } + + for (i = 0; i < cnt; i++) { + if (PyObject_GetBuffer(PySequence_GetItem(seq, i), + &(*buf)[i], type) == -1) { + PyMem_Del(*iov); + for (j = 0; j < i; j++) { + PyBuffer_Release(&(*buf)[j]); + } + PyMem_Del(*buf); + total = 0; + return total; + } + (*iov)[i].iov_base = (*buf)[i].buf; + blen = (*buf)[i].len; + (*iov)[i].iov_len = blen; + total += blen; + } + return total; +} + +static void +iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt) +{ + int i; + PyMem_Del(iov); + for (i = 0; i < cnt; i++) { + PyBuffer_Release(&buf[i]); + } + PyMem_Del(buf); +} +#endif -PyDoc_STRVAR(posix_lseek__doc__, -"lseek(fd, pos, how) -> newpos\n\n\ -Set the current position of a file descriptor."); +#ifdef HAVE_READV +PyDoc_STRVAR(posix_readv__doc__, +"readv(fd, buffers) -> bytesread\n\n\ +Read from a file descriptor into a number of writable buffers. buffers\n\ +is an arbitrary sequence of writable buffers.\n\ +Returns the total number of bytes read."); static PyObject * -posix_lseek(PyObject *self, PyObject *args) +posix_readv(PyObject *self, PyObject *args) { - int fd, how; -#if defined(MS_WIN64) || defined(MS_WINDOWS) - PY_LONG_LONG pos, res; -#else - off_t pos, res; -#endif - PyObject *posobj; - if (!PyArg_ParseTuple(args, "iOi:lseek", &fd, &posobj, &how)) + int fd, cnt; + Py_ssize_t n; + PyObject *seq; + struct iovec *iov; + Py_buffer *buf; + + if (!PyArg_ParseTuple(args, "iO:readv", &fd, &seq)) + return NULL; + if (!PySequence_Check(seq)) { + PyErr_SetString(PyExc_TypeError, + "readv() arg 2 must be a sequence"); return NULL; -#ifdef SEEK_SET - /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */ - switch (how) { - case 0: how = SEEK_SET; break; - case 1: how = SEEK_CUR; break; - case 2: how = SEEK_END; break; } -#endif /* SEEK_END */ + cnt = PySequence_Size(seq); -#if !defined(HAVE_LARGEFILE_SUPPORT) - pos = PyLong_AsLong(posobj); -#else - pos = PyLong_AsLongLong(posobj); -#endif - if (PyErr_Occurred()) + if (!iov_setup(&iov, &buf, seq, cnt, PyBUF_WRITABLE)) return NULL; - if (!_PyVerify_fd(fd)) - return posix_error(); Py_BEGIN_ALLOW_THREADS -#if defined(MS_WIN64) || defined(MS_WINDOWS) - res = _lseeki64(fd, pos, how); -#else - res = lseek(fd, pos, how); -#endif + n = readv(fd, iov, cnt); Py_END_ALLOW_THREADS - if (res < 0) - return posix_error(); -#if !defined(HAVE_LARGEFILE_SUPPORT) - return PyLong_FromLong(res); -#else - return PyLong_FromLongLong(res); -#endif + iov_cleanup(iov, buf, cnt); + return PyLong_FromSsize_t(n); } +#endif - -PyDoc_STRVAR(posix_read__doc__, -"read(fd, buffersize) -> string\n\n\ -Read a file descriptor."); +#ifdef HAVE_PREAD +PyDoc_STRVAR(posix_pread__doc__, +"pread(fd, buffersize, offset) -> string\n\n\ +Read from a file descriptor, fd, at a position of offset. It will read up\n\ +to buffersize number of bytes. The file offset remains unchanged."); static PyObject * -posix_read(PyObject *self, PyObject *args) +posix_pread(PyObject *self, PyObject *args) { int fd, size; + off_t offset; Py_ssize_t n; PyObject *buffer; - if (!PyArg_ParseTuple(args, "ii:read", &fd, &size)) + if (!PyArg_ParseTuple(args, "iiO&:pread", &fd, &size, _parse_off_t, &offset)) return NULL; + if (size < 0) { errno = EINVAL; return posix_error(); @@ -5820,7 +6266,7 @@ posix_read(PyObject *self, PyObject *args) return posix_error(); } Py_BEGIN_ALLOW_THREADS - n = read(fd, PyBytes_AS_STRING(buffer), size); + n = pread(fd, PyBytes_AS_STRING(buffer), size, offset); Py_END_ALLOW_THREADS if (n < 0) { Py_DECREF(buffer); @@ -5830,7 +6276,7 @@ posix_read(PyObject *self, PyObject *args) _PyBytes_Resize(&buffer, n); return buffer; } - +#endif PyDoc_STRVAR(posix_write__doc__, "write(fd, string) -> byteswritten\n\n\ @@ -5866,57 +6312,6 @@ posix_write(PyObject *self, PyObject *args) } #ifdef HAVE_SENDFILE -#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__) -static Py_ssize_t -iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, int cnt, int type) -{ - int i, j; - Py_ssize_t blen, total = 0; - - *iov = PyMem_New(struct iovec, cnt); - if (*iov == NULL) { - PyErr_NoMemory(); - return total; - } - - *buf = PyMem_New(Py_buffer, cnt); - if (*buf == NULL) { - PyMem_Del(*iov); - PyErr_NoMemory(); - return total; - } - - for (i = 0; i < cnt; i++) { - if (PyObject_GetBuffer(PySequence_GetItem(seq, i), - &(*buf)[i], type) == -1) { - PyMem_Del(*iov); - for (j = 0; j < i; j++) { - PyBuffer_Release(&(*buf)[j]); - } - PyMem_Del(*buf); - total = 0; - return total; - } - (*iov)[i].iov_base = (*buf)[i].buf; - blen = (*buf)[i].len; - (*iov)[i].iov_len = blen; - total += blen; - } - return total; -} - -static void -iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt) -{ - int i; - PyMem_Del(iov); - for (i = 0; i < cnt; i++) { - PyBuffer_Release(&buf[i]); - } - PyMem_Del(buf); -} -#endif - PyDoc_STRVAR(posix_sendfile__doc__, "sendfile(out, in, offset, nbytes) -> byteswritten\n\ sendfile(out, in, offset, nbytes, headers=None, trailers=None, flags=0)\n\ @@ -6150,6 +6545,73 @@ posix_pipe(PyObject *self, PyObject *noargs) } #endif /* HAVE_PIPE */ +#ifdef HAVE_WRITEV +PyDoc_STRVAR(posix_writev__doc__, +"writev(fd, buffers) -> byteswritten\n\n\ +Write the contents of buffers to a file descriptor, where buffers is an\n\ +arbitrary sequence of buffers.\n\ +Returns the total bytes written."); + +static PyObject * +posix_writev(PyObject *self, PyObject *args) +{ + int fd, cnt; + Py_ssize_t res; + PyObject *seq; + struct iovec *iov; + Py_buffer *buf; + if (!PyArg_ParseTuple(args, "iO:writev", &fd, &seq)) + return NULL; + if (!PySequence_Check(seq)) { + PyErr_SetString(PyExc_TypeError, + "writev() arg 2 must be a sequence"); + return NULL; + } + cnt = PySequence_Size(seq); + + if (!iov_setup(&iov, &buf, seq, cnt, PyBUF_SIMPLE)) { + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + res = writev(fd, iov, cnt); + Py_END_ALLOW_THREADS + + iov_cleanup(iov, buf, cnt); + return PyLong_FromSsize_t(res); +} +#endif + +#ifdef HAVE_PWRITE +PyDoc_STRVAR(posix_pwrite__doc__, +"pwrite(fd, string, offset) -> byteswritten\n\n\ +Write string to a file descriptor, fd, from offset, leaving the file\n\ +offset unchanged."); + +static PyObject * +posix_pwrite(PyObject *self, PyObject *args) +{ + Py_buffer pbuf; + int fd; + off_t offset; + Py_ssize_t size; + + if (!PyArg_ParseTuple(args, "iy*O&:pwrite", &fd, &pbuf, _parse_off_t, &offset)) + return NULL; + + if (!_PyVerify_fd(fd)) { + PyBuffer_Release(&pbuf); + return posix_error(); + } + Py_BEGIN_ALLOW_THREADS + size = pwrite(fd, pbuf.buf, (size_t)pbuf.len, offset); + Py_END_ALLOW_THREADS + PyBuffer_Release(&pbuf); + if (size < 0) + return posix_error(); + return PyLong_FromSsize_t(size); +} +#endif #ifdef HAVE_MKFIFO PyDoc_STRVAR(posix_mkfifo__doc__, @@ -6266,18 +6728,8 @@ posix_ftruncate(PyObject *self, PyObject *args) int fd; off_t length; int res; - PyObject *lenobj; - - if (!PyArg_ParseTuple(args, "iO:ftruncate", &fd, &lenobj)) - return NULL; -#if !defined(HAVE_LARGEFILE_SUPPORT) - length = PyLong_AsLong(lenobj); -#else - length = PyLong_Check(lenobj) ? - PyLong_AsLongLong(lenobj) : PyLong_AsLong(lenobj); -#endif - if (PyErr_Occurred()) + if (!PyArg_ParseTuple(args, "iO&:ftruncate", &fd, _parse_off_t, &length)) return NULL; Py_BEGIN_ALLOW_THREADS @@ -6290,6 +6742,93 @@ posix_ftruncate(PyObject *self, PyObject *args) } #endif +#ifdef HAVE_TRUNCATE +PyDoc_STRVAR(posix_truncate__doc__, +"truncate(path, length)\n\n\ +Truncate the file given by path to length bytes."); + +static PyObject * +posix_truncate(PyObject *self, PyObject *args) +{ + PyObject *opath; + const char *path; + off_t length; + int res; + + if (!PyArg_ParseTuple(args, "O&O&:truncate", + PyUnicode_FSConverter, &opath, _parse_off_t, &length)) + return NULL; + path = PyBytes_AsString(opath); + + Py_BEGIN_ALLOW_THREADS + res = truncate(path, length); + Py_END_ALLOW_THREADS + Py_DECREF(opath); + if (res < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif + +#ifdef HAVE_POSIX_FALLOCATE +PyDoc_STRVAR(posix_posix_fallocate__doc__, +"posix_fallocate(fd, offset, len)\n\n\ +Ensures that enough disk space is allocated for the file specified by fd\n\ +starting from offset and continuing for len bytes."); + +static PyObject * +posix_posix_fallocate(PyObject *self, PyObject *args) +{ + off_t len, offset; + int res, fd; + + if (!PyArg_ParseTuple(args, "iO&O&:posix_fallocate", + &fd, _parse_off_t, &offset, _parse_off_t, &len)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + res = posix_fallocate(fd, offset, len); + Py_END_ALLOW_THREADS + if (res != 0) { + errno = res; + return posix_error(); + } + Py_RETURN_NONE; +} +#endif + +#ifdef HAVE_POSIX_FADVISE +PyDoc_STRVAR(posix_posix_fadvise__doc__, +"posix_fadvise(fd, offset, len, advice)\n\n\ +Announces an intention to access data in a specific pattern thus allowing\n\ +the kernel to make optimizations.\n\ +The advice applies to the region of the file specified by fd starting at\n\ +offset and continuing for len bytes.\n\ +advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,\n\ +POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED or\n\ +POSIX_FADV_DONTNEED."); + +static PyObject * +posix_posix_fadvise(PyObject *self, PyObject *args) +{ + off_t len, offset; + int res, fd, advice; + + if (!PyArg_ParseTuple(args, "iO&O&i:posix_fadvise", + &fd, _parse_off_t, &offset, _parse_off_t, &len, &advice)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + res = posix_fadvise(fd, offset, len, advice); + Py_END_ALLOW_THREADS + if (res != 0) { + errno = res; + return posix_error(); + } + Py_RETURN_NONE; +} +#endif + #ifdef HAVE_PUTENV PyDoc_STRVAR(posix_putenv__doc__, "putenv(key, value)\n\n\ @@ -8725,6 +9264,15 @@ static PyMethodDef posix_methods[] = { {"unlink", posix_unlink, METH_VARARGS, posix_unlink__doc__}, {"remove", posix_unlink, METH_VARARGS, posix_remove__doc__}, {"utime", posix_utime, METH_VARARGS, posix_utime__doc__}, +#ifdef HAVE_FUTIMES + {"futimes", posix_futimes, METH_VARARGS, posix_futimes__doc__}, +#endif +#ifdef HAVE_LUTIMES + {"lutimes", posix_lutimes, METH_VARARGS, posix_lutimes__doc__}, +#endif +#ifdef HAVE_FUTIMENS + {"futimens", posix_futimens, METH_VARARGS, posix_futimens__doc__}, +#endif #ifdef HAVE_TIMES {"times", posix_times, METH_NOARGS, posix_times__doc__}, #endif /* HAVE_TIMES */ @@ -8733,6 +9281,9 @@ static PyMethodDef posix_methods[] = { {"execv", posix_execv, METH_VARARGS, posix_execv__doc__}, {"execve", posix_execve, METH_VARARGS, posix_execve__doc__}, #endif /* HAVE_EXECV */ +#ifdef HAVE_FEXECVE + {"fexecve", posix_fexecve, METH_VARARGS, posix_fexecve__doc__}, +#endif #ifdef HAVE_SPAWNV {"spawnv", posix_spawnv, METH_VARARGS, posix_spawnv__doc__}, {"spawnve", posix_spawnve, METH_VARARGS, posix_spawnve__doc__}, @@ -8831,6 +9382,9 @@ static PyMethodDef posix_methods[] = { #ifdef HAVE_WAIT4 {"wait4", posix_wait4, METH_VARARGS, posix_wait4__doc__}, #endif /* HAVE_WAIT4 */ +#if defined(HAVE_WAITID) && !defined(__APPLE__) + {"waitid", posix_waitid, METH_VARARGS, posix_waitid__doc__}, +#endif #if defined(HAVE_WAITPID) || defined(HAVE_CWAIT) {"waitpid", posix_waitpid, METH_VARARGS, posix_waitpid__doc__}, #endif /* HAVE_WAITPID */ @@ -8855,9 +9409,24 @@ static PyMethodDef posix_methods[] = { {"device_encoding", device_encoding, METH_VARARGS, device_encoding__doc__}, {"dup", posix_dup, METH_VARARGS, posix_dup__doc__}, {"dup2", posix_dup2, METH_VARARGS, posix_dup2__doc__}, +#ifdef HAVE_LOCKF + {"lockf", posix_lockf, METH_VARARGS, posix_lockf__doc__}, +#endif {"lseek", posix_lseek, METH_VARARGS, posix_lseek__doc__}, {"read", posix_read, METH_VARARGS, posix_read__doc__}, +#ifdef HAVE_READV + {"readv", posix_readv, METH_VARARGS, posix_readv__doc__}, +#endif +#ifdef HAVE_PREAD + {"pread", posix_pread, METH_VARARGS, posix_pread__doc__}, +#endif {"write", posix_write, METH_VARARGS, posix_write__doc__}, +#ifdef HAVE_WRITEV + {"writev", posix_writev, METH_VARARGS, posix_writev__doc__}, +#endif +#ifdef HAVE_PWRITE + {"pwrite", posix_pwrite, METH_VARARGS, posix_pwrite__doc__}, +#endif #ifdef HAVE_SENDFILE {"sendfile", (PyCFunction)posix_sendfile, METH_VARARGS | METH_KEYWORDS, posix_sendfile__doc__}, @@ -8881,6 +9450,15 @@ static PyMethodDef posix_methods[] = { #ifdef HAVE_FTRUNCATE {"ftruncate", posix_ftruncate, METH_VARARGS, posix_ftruncate__doc__}, #endif +#ifdef HAVE_TRUNCATE + {"truncate", posix_truncate, METH_VARARGS, posix_truncate__doc__}, +#endif +#ifdef HAVE_POSIX_FALLOCATE + {"posix_fallocate", posix_posix_fallocate, METH_VARARGS, posix_posix_fallocate__doc__}, +#endif +#ifdef HAVE_POSIX_FADVISE + {"posix_fadvise", posix_posix_fadvise, METH_VARARGS, posix_posix_fadvise__doc__}, +#endif #ifdef HAVE_PUTENV {"putenv", posix_putenv, METH_VARARGS, posix_putenv__doc__}, #endif @@ -8894,6 +9472,9 @@ static PyMethodDef posix_methods[] = { #ifdef HAVE_FSYNC {"fsync", posix_fsync, METH_O, posix_fsync__doc__}, #endif +#ifdef HAVE_SYNC + {"sync", posix_sync, METH_NOARGS, posix_sync__doc__}, +#endif #ifdef HAVE_FDATASYNC {"fdatasync", posix_fdatasync, METH_O, posix_fdatasync__doc__}, #endif @@ -9342,6 +9923,76 @@ all_ins(PyObject *d) if (ins(d, "SF_SYNC", (long)SF_SYNC)) return -1; #endif + /* constants for posix_fadvise */ +#ifdef POSIX_FADV_NORMAL + if (ins(d, "POSIX_FADV_NORMAL", (long)POSIX_FADV_NORMAL)) return -1; +#endif +#ifdef POSIX_FADV_SEQUENTIAL + if (ins(d, "POSIX_FADV_SEQUENTIAL", (long)POSIX_FADV_SEQUENTIAL)) return -1; +#endif +#ifdef POSIX_FADV_RANDOM + if (ins(d, "POSIX_FADV_RANDOM", (long)POSIX_FADV_RANDOM)) return -1; +#endif +#ifdef POSIX_FADV_NOREUSE + if (ins(d, "POSIX_FADV_NOREUSE", (long)POSIX_FADV_NOREUSE)) return -1; +#endif +#ifdef POSIX_FADV_WILLNEED + if (ins(d, "POSIX_FADV_WILLNEED", (long)POSIX_FADV_WILLNEED)) return -1; +#endif +#ifdef POSIX_FADV_DONTNEED + if (ins(d, "POSIX_FADV_DONTNEED", (long)POSIX_FADV_DONTNEED)) return -1; +#endif + + /* constants for waitid */ +#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID) + if (ins(d, "P_PID", (long)P_PID)) return -1; + if (ins(d, "P_PGID", (long)P_PGID)) return -1; + if (ins(d, "P_ALL", (long)P_ALL)) return -1; +#endif +#ifdef WEXITED + if (ins(d, "WEXITED", (long)WEXITED)) return -1; +#endif +#ifdef WNOWAIT + if (ins(d, "WNOWAIT", (long)WNOWAIT)) return -1; +#endif +#ifdef WSTOPPED + if (ins(d, "WSTOPPED", (long)WSTOPPED)) return -1; +#endif +#ifdef CLD_EXITED + if (ins(d, "CLD_EXITED", (long)CLD_EXITED)) return -1; +#endif +#ifdef CLD_DUMPED + if (ins(d, "CLD_DUMPED", (long)CLD_DUMPED)) return -1; +#endif +#ifdef CLD_TRAPPED + if (ins(d, "CLD_TRAPPED", (long)CLD_TRAPPED)) return -1; +#endif +#ifdef CLD_CONTINUED + if (ins(d, "CLD_CONTINUED", (long)CLD_CONTINUED)) return -1; +#endif + + /* constants for lockf */ +#ifdef F_LOCK + if (ins(d, "F_LOCK", (long)F_LOCK)) return -1; +#endif +#ifdef F_TLOCK + if (ins(d, "F_TLOCK", (long)F_TLOCK)) return -1; +#endif +#ifdef F_ULOCK + if (ins(d, "F_ULOCK", (long)F_ULOCK)) return -1; +#endif +#ifdef F_TEST + if (ins(d, "F_TEST", (long)F_TEST)) return -1; +#endif + + /* constants for futimens */ +#ifdef UTIME_NOW + if (ins(d, "UTIME_NOW", (long)UTIME_NOW)) return -1; +#endif +#ifdef UTIME_OMIT + if (ins(d, "UTIME_OMIT", (long)UTIME_OMIT)) return -1; +#endif + #ifdef HAVE_SPAWNV #if defined(PYOS_OS2) && defined(PYCC_GCC) if (ins(d, "P_WAIT", (long)P_WAIT)) return -1; @@ -9441,6 +10092,11 @@ INITFUNC(void) #endif if (!initialized) { +#if defined(HAVE_WAITID) && !defined(__APPLE__) + waitid_result_desc.name = MODNAME ".waitid_result"; + PyStructSequence_InitType(&WaitidResultType, &waitid_result_desc); +#endif + stat_result_desc.name = MODNAME ".stat_result"; stat_result_desc.fields[7].name = PyStructSequence_UnnamedField; stat_result_desc.fields[8].name = PyStructSequence_UnnamedField; @@ -9461,6 +10117,10 @@ INITFUNC(void) # endif #endif } +#if defined(HAVE_WAITID) && !defined(__APPLE__) + Py_INCREF((PyObject*) &WaitidResultType); + PyModule_AddObject(m, "waitid_result", (PyObject*) &WaitidResultType); +#endif Py_INCREF((PyObject*) &StatResultType); PyModule_AddObject(m, "stat_result", (PyObject*) &StatResultType); Py_INCREF((PyObject*) &StatVFSResultType); diff --git a/configure b/configure index 4b69f3a..4b69292 100755 --- a/configure +++ b/configure @@ -776,8 +776,7 @@ CFLAGS LDFLAGS LIBS CPPFLAGS -CPP -CPPFLAGS' +CPP' # Initialize some variables set by options. @@ -9251,19 +9250,21 @@ $as_echo "MACHDEP_OBJS" >&6; } # checks for library functions for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \ clock confstr ctermid execv faccessat fchmod fchmodat fchown fchownat \ - fdopendir fork fpathconf fstatat ftime ftruncate futimesat \ + fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \ + futimens futimes \ gai_strerror getgroups getlogin getloadavg getpeername getpgid getpid \ getpriority getresuid getresgid getpwent getspnam getspent getsid getwd \ - initgroups kill killpg lchmod lchown linkat lstat mbrtowc mkdirat mkfifo \ + initgroups kill killpg lchmod lchown lockf linkat lstat lutimes mbrtowc mkdirat mkfifo \ mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \ - pthread_init putenv readlink readlinkat realpath renameat \ + posix_fallocate posix_fadvise pread \ + pthread_init putenv pwrite readlink readlinkat readv realpath renameat \ select sem_open sem_timedwait sem_getvalue sem_unlink sendfile setegid seteuid \ setgid sethostname \ setlocale setregid setreuid setresuid setresgid setsid setpgid setpgrp setpriority setuid setvbuf \ - sigaction siginterrupt sigrelse snprintf strftime strlcpy symlinkat \ + sigaction siginterrupt sigrelse snprintf strftime strlcpy symlinkat sync \ sysconf tcgetpgrp tcsetpgrp tempnam timegm times tmpfile tmpnam tmpnam_r \ - truncate uname unlinkat unsetenv utimensat utimes waitpid wait3 wait4 \ - wcscoll wcsftime wcsxfrm _getpty + truncate uname unlinkat unsetenv utimensat utimes waitid waitpid wait3 wait4 \ + wcscoll wcsftime wcsxfrm writev _getpty do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" diff --git a/configure.in b/configure.in index c6c884c..b41a4b6 100644 --- a/configure.in +++ b/configure.in @@ -2496,19 +2496,21 @@ AC_MSG_RESULT(MACHDEP_OBJS) # checks for library functions AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \ clock confstr ctermid execv faccessat fchmod fchmodat fchown fchownat \ - fdopendir fork fpathconf fstatat ftime ftruncate futimesat \ + fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \ + futimens futimes \ gai_strerror getgroups getlogin getloadavg getpeername getpgid getpid \ getpriority getresuid getresgid getpwent getspnam getspent getsid getwd \ - initgroups kill killpg lchmod lchown linkat lstat mbrtowc mkdirat mkfifo \ + initgroups kill killpg lchmod lchown lockf linkat lstat lutimes mbrtowc mkdirat mkfifo \ mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll \ - pthread_init putenv readlink readlinkat realpath renameat \ + posix_fallocate posix_fadvise pread \ + pthread_init putenv pwrite readlink readlinkat readv realpath renameat \ select sem_open sem_timedwait sem_getvalue sem_unlink sendfile setegid seteuid \ setgid sethostname \ setlocale setregid setreuid setresuid setresgid setsid setpgid setpgrp setpriority setuid setvbuf \ - sigaction siginterrupt sigrelse snprintf strftime strlcpy symlinkat \ + sigaction siginterrupt sigrelse snprintf strftime strlcpy symlinkat sync \ sysconf tcgetpgrp tcsetpgrp tempnam timegm times tmpfile tmpnam tmpnam_r \ - truncate uname unlinkat unsetenv utimensat utimes waitpid wait3 wait4 \ - wcscoll wcsftime wcsxfrm _getpty) + truncate uname unlinkat unsetenv utimensat utimes waitid waitpid wait3 wait4 \ + wcscoll wcsftime wcsxfrm writev _getpty) # For some functions, having a definition is not sufficient, since # we want to take their address. diff --git a/pyconfig.h.in b/pyconfig.h.in index 3eedd4b..7320260 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -232,6 +232,9 @@ /* Define to 1 if you have the `fdopendir' function. */ #undef HAVE_FDOPENDIR +/* Define to 1 if you have the `fexecve' function. */ +#undef HAVE_FEXECVE + /* Define to 1 if you have the `finite' function. */ #undef HAVE_FINITE @@ -274,6 +277,12 @@ /* Define to 1 if you have the `ftruncate' function. */ #undef HAVE_FTRUNCATE +/* Define to 1 if you have the `futimens' function. */ +#undef HAVE_FUTIMENS + +/* Define to 1 if you have the `futimes' function. */ +#undef HAVE_FUTIMES + /* Define to 1 if you have the `futimesat' function. */ #undef HAVE_FUTIMESAT @@ -461,6 +470,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_TIPC_H +/* Define to 1 if you have the `lockf' function. */ +#undef HAVE_LOCKF + /* Define to 1 if you have the `log1p' function. */ #undef HAVE_LOG1P @@ -473,6 +485,9 @@ /* Define to 1 if you have the `lstat' function. */ #undef HAVE_LSTAT +/* Define to 1 if you have the `lutimes' function. */ +#undef HAVE_LUTIMES + /* Define this if you have the makedev macro. */ #undef HAVE_MAKEDEV @@ -545,6 +560,15 @@ /* Define to 1 if you have the header file. */ #undef HAVE_POLL_H +/* Define to 1 if you have the `posix_fadvise' function. */ +#undef HAVE_POSIX_FADVISE + +/* Define to 1 if you have the `posix_fallocate' function. */ +#undef HAVE_POSIX_FALLOCATE + +/* Define to 1 if you have the `pread' function. */ +#undef HAVE_PREAD + /* Define to 1 if you have the header file. */ #undef HAVE_PROCESS_H @@ -569,12 +593,18 @@ /* Define to 1 if you have the `putenv' function. */ #undef HAVE_PUTENV +/* Define to 1 if you have the `pwrite' function. */ +#undef HAVE_PWRITE + /* Define to 1 if you have the `readlink' function. */ #undef HAVE_READLINK /* Define to 1 if you have the `readlinkat' function. */ #undef HAVE_READLINKAT +/* Define to 1 if you have the `readv' function. */ +#undef HAVE_READV + /* Define to 1 if you have the `realpath' function. */ #undef HAVE_REALPATH @@ -775,6 +805,9 @@ /* Define to 1 if you have the `symlinkat' function. */ #undef HAVE_SYMLINKAT +/* Define to 1 if you have the `sync' function. */ +#undef HAVE_SYNC + /* Define to 1 if you have the `sysconf' function. */ #undef HAVE_SYSCONF @@ -952,6 +985,9 @@ /* Define to 1 if you have the `wait4' function. */ #undef HAVE_WAIT4 +/* Define to 1 if you have the `waitid' function. */ +#undef HAVE_WAITID + /* Define to 1 if you have the `waitpid' function. */ #undef HAVE_WAITPID @@ -971,6 +1007,9 @@ */ #undef HAVE_WORKING_TZSET +/* Define to 1 if you have the `writev' function. */ +#undef HAVE_WRITEV + /* Define if the zlib library has inflateCopy */ #undef HAVE_ZLIB_COPY -- cgit v0.12 From 8e7496785563411d0488ffa3718b265ee24322d3 Mon Sep 17 00:00:00 2001 From: Ross Lagerwall Date: Thu, 17 Mar 2011 21:54:07 +0200 Subject: Issue #10812: Revert os.lseek change. --- Modules/posixmodule.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index cc908e2..0de6fdf 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -6080,7 +6080,8 @@ posix_lseek(PyObject *self, PyObject *args) #else off_t pos, res; #endif - if (!PyArg_ParseTuple(args, "iO&i:lseek", &fd, _parse_off_t, &pos, &how)) + PyObject *posobj; + if (!PyArg_ParseTuple(args, "iOi:lseek", &fd, &posobj, &how)) return NULL; #ifdef SEEK_SET /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */ @@ -6091,6 +6092,11 @@ posix_lseek(PyObject *self, PyObject *args) } #endif /* SEEK_END */ +#if !defined(HAVE_LARGEFILE_SUPPORT) + pos = PyLong_AsLong(posobj); +#else + pos = PyLong_AsLongLong(posobj); +#endif if (PyErr_Occurred()) return NULL; -- cgit v0.12 From 5e98141f9f576934fe5635c66614f82be1ee0a9a Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Thu, 17 Mar 2011 22:38:37 +0100 Subject: Issue #5421: Fix misleading error message when one of socket.sendto()'s arguments has the wrong type. Patch by Nikita Vetoshkin. --- Misc/ACKS | 1 + Misc/NEWS | 3 +++ Modules/socketmodule.c | 23 +++++++++++++++++------ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS index 5d9b198..99554da 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -823,6 +823,7 @@ Alexandre Vassalotti Frank Vercruesse Mike Verdone Jaap Vermeulen +Nikita Vetoshkin Al Vezza Jacques A. Vidrine John Viega diff --git a/Misc/NEWS b/Misc/NEWS index 58eea2d..f18e557 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -40,6 +40,9 @@ Core and Builtins Library ------- +- Issue #5421: Fix misleading error message when one of socket.sendto()'s + arguments has the wrong type. Patch by Nikita Vetoshkin. + - Issue #11401: fix handling of headers with no value; this fixes a regression relative to Python2 and the result is now the same as it was in Python2. diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index b04d246..5e911e0 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -2647,17 +2647,28 @@ sock_sendto(PySocketSockObject *s, PyObject *args) Py_buffer pbuf; PyObject *addro; char *buf; - Py_ssize_t len; + Py_ssize_t len, arglen; sock_addr_t addrbuf; int addrlen, n = -1, flags, timeout; flags = 0; - if (!PyArg_ParseTuple(args, "y*O:sendto", &pbuf, &addro)) { - PyErr_Clear(); - if (!PyArg_ParseTuple(args, "y*iO:sendto", - &pbuf, &flags, &addro)) - return NULL; + arglen = PyTuple_Size(args); + switch (arglen) { + case 2: + PyArg_ParseTuple(args, "y*O:sendto", &pbuf, &addro); + break; + case 3: + PyArg_ParseTuple(args, "y*iO:sendto", + &pbuf, &flags, &addro); + break; + default: + PyErr_Format(PyExc_TypeError, + "sendto() takes 2 or 3 arguments (%d given)", + arglen); } + if (PyErr_Occurred()) + return NULL; + buf = pbuf.buf; len = pbuf.len; -- cgit v0.12 From bb6eb857cf055079b1108a2afd5a434433c97e90 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Thu, 17 Mar 2011 23:34:33 +0100 Subject: Issue #10914: fix bogus memory management in Modules/getpath.c, leading to a possible crash when calling Py_SetPath() --- Modules/getpath.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Modules/getpath.c b/Modules/getpath.c index 59623d7..b7f9573 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -134,6 +134,7 @@ static wchar_t prefix[MAXPATHLEN+1]; static wchar_t exec_prefix[MAXPATHLEN+1]; static wchar_t progpath[MAXPATHLEN+1]; static wchar_t *module_search_path = NULL; +static int module_search_path_malloced = 0; static wchar_t *lib_python = L"lib/python" VERSION; static void @@ -634,7 +635,6 @@ calculate_path(void) bufsz += wcslen(zip_path) + 1; bufsz += wcslen(exec_prefix) + 1; - /* This is the only malloc call in this file */ buf = (wchar_t *)PyMem_Malloc(bufsz*sizeof(wchar_t)); if (buf == NULL) { @@ -687,6 +687,7 @@ calculate_path(void) /* And publish the results */ module_search_path = buf; + module_search_path_malloced = 1; } /* Reduce prefix and exec_prefix to their essence, @@ -726,15 +727,18 @@ void Py_SetPath(const wchar_t *path) { if (module_search_path != NULL) { - free(module_search_path); + if (module_search_path_malloced) + PyMem_Free(module_search_path); module_search_path = NULL; + module_search_path_malloced = 0; } if (path != NULL) { extern wchar_t *Py_GetProgramName(void); wchar_t *prog = Py_GetProgramName(); wcsncpy(progpath, prog, MAXPATHLEN); exec_prefix[0] = prefix[0] = L'\0'; - module_search_path = malloc((wcslen(path) + 1) * sizeof(wchar_t)); + module_search_path = PyMem_Malloc((wcslen(path) + 1) * sizeof(wchar_t)); + module_search_path_malloced = 1; if (module_search_path != NULL) wcscpy(module_search_path, path); } -- cgit v0.12 From 819be3406d2311347838a413f1893e4f20b3159c Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Thu, 17 Mar 2011 23:36:13 +0100 Subject: Add news entry for a791dd7d51f3 --- Misc/NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Misc/NEWS b/Misc/NEWS index 328e44d..5732a0d 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ What's New in Python 3.2.1? Core and Builtins ----------------- +- Issue #10914: fix bogus memory management in Modules/getpath.c, leading to + a possible crash when calling Py_SetPath(). + - Issue #11510: Fixed optimizer bug which turned "a,b={1,1}" into "a,b=(1,1)". - Issue #11432: A bug was introduced in subprocess.Popen on posix systems with -- cgit v0.12 From e147484666bae5ce0d9972ba898c406c80d3ccd8 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Thu, 17 Mar 2011 23:40:53 +0100 Subject: Oops, wrong issue number in NEWS --- Misc/NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS b/Misc/NEWS index 5732a0d..156ad78 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,7 +10,7 @@ What's New in Python 3.2.1? Core and Builtins ----------------- -- Issue #10914: fix bogus memory management in Modules/getpath.c, leading to +- Issue #11320: fix bogus memory management in Modules/getpath.c, leading to a possible crash when calling Py_SetPath(). - Issue #11510: Fixed optimizer bug which turned "a,b={1,1}" into "a,b=(1,1)". -- cgit v0.12 From 4d076da4dee054c83cfd851a2f49a1bb40eaf638 Mon Sep 17 00:00:00 2001 From: Ross Lagerwall Date: Fri, 18 Mar 2011 06:56:53 +0200 Subject: Issue #11592: Fix compilation warnings in os module. --- Modules/posixmodule.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 0de6fdf..f873a7a 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -59,6 +59,10 @@ corresponding Unix manual entries for more information on calls."); #include "osdefs.h" #endif +#ifdef HAVE_SYS_UIO_H +#include +#endif + #ifdef HAVE_SYS_TYPES_H #include #endif /* HAVE_SYS_TYPES_H */ @@ -103,10 +107,6 @@ corresponding Unix manual entries for more information on calls."); #ifdef HAVE_SYS_SOCKET_H #include #endif - -#ifdef HAVE_SYS_UIO_H -#include -#endif #endif /* Various compilers have only certain posix functions */ -- cgit v0.12 From 6827294e0501096fe99da1cf7fc92397e6939502 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Fri, 18 Mar 2011 02:22:15 -0700 Subject: Speed-up search for hidden names by using a set instead of a tuple. --- Lib/pydoc.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/pydoc.py b/Lib/pydoc.py index 9d3cdd5..9f8f120 100755 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -168,11 +168,11 @@ def _split_list(s, predicate): def visiblename(name, all=None): """Decide whether to show documentation on a variable.""" # Certain special names are redundant. - _hidden_names = ('__builtins__', '__doc__', '__file__', '__path__', + if name in {'__builtins__', '__doc__', '__file__', '__path__', '__module__', '__name__', '__slots__', '__package__', '__cached__', '__author__', '__credits__', '__date__', - '__version__') - if name in _hidden_names: return 0 + '__version__'}: + return 0 # Private names are hidden, but special names are displayed. if name.startswith('__') and name.endswith('__'): return 1 if all is not None: -- cgit v0.12 From f84f3c3d2dd02fa667ee8c89b9285e72a0d25aac Mon Sep 17 00:00:00 2001 From: briancurtin Date: Fri, 18 Mar 2011 13:03:17 -0500 Subject: Fix #11596. When bz2 isn't available, skip test_bz2_ext_fake. --- Lib/test/test_fileinput.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_fileinput.py b/Lib/test/test_fileinput.py index 27ceaf6..76e4d16 100644 --- a/Lib/test/test_fileinput.py +++ b/Lib/test/test_fileinput.py @@ -8,11 +8,15 @@ import re import fileinput import collections import gzip -import bz2 import types import codecs import unittest +try: + import bz2 +except ImportError: + bz2 = None + from io import StringIO from fileinput import FileInput, hook_encoded @@ -765,6 +769,7 @@ class Test_hook_compressed(unittest.TestCase): self.assertEqual(self.fake_open.invocation_count, 1) self.assertEqual(self.fake_open.last_invocation, (("test.gz", 3), {})) + @unittest.skipUnless(bz2, "Requires bz2") def test_bz2_ext_fake(self): original_open = bz2.BZ2File bz2.BZ2File = self.fake_open -- cgit v0.12 From 7e4c168385b5f723dbeb340abe51f7b99399e1c7 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Fri, 18 Mar 2011 15:09:10 -0700 Subject: Minor optimization -- factor a constant expression out of the inner-loop. --- Lib/functools.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py index 03de69a..fdc9c79 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -140,7 +140,7 @@ def lru_cache(maxsize=100): tuple=tuple, sorted=sorted, len=len, KeyError=KeyError): hits = misses = 0 - kwd_mark = object() # separates positional and keyword args + kwd_mark = (object(),) # separates positional and keyword args lock = Lock() # needed because ordereddicts aren't threadsafe if maxsize is None: @@ -151,7 +151,7 @@ def lru_cache(maxsize=100): nonlocal hits, misses key = args if kwds: - key += (kwd_mark,) + tuple(sorted(kwds.items())) + key += kwd_mark + tuple(sorted(kwds.items())) try: result = cache[key] hits += 1 @@ -170,7 +170,7 @@ def lru_cache(maxsize=100): nonlocal hits, misses key = args if kwds: - key += (kwd_mark,) + tuple(sorted(kwds.items())) + key += kwd_mark + tuple(sorted(kwds.items())) try: with lock: result = cache[key] -- cgit v0.12 From af9be06b3c82766110d9d4cc1e8bc3ad7fcfbf84 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Fri, 18 Mar 2011 18:22:28 -0700 Subject: Issue 7391: Remove questionable and outdated HOWTO document with permission from its author. --- Doc/howto/doanddont.rst | 290 ------------------------------------------------ Doc/howto/index.rst | 1 - 2 files changed, 291 deletions(-) delete mode 100644 Doc/howto/doanddont.rst diff --git a/Doc/howto/doanddont.rst b/Doc/howto/doanddont.rst deleted file mode 100644 index 6fc0d6e..0000000 --- a/Doc/howto/doanddont.rst +++ /dev/null @@ -1,290 +0,0 @@ -************************************ - Idioms and Anti-Idioms in Python -************************************ - -:Author: Moshe Zadka - -This document is placed in the public domain. - - -.. topic:: Abstract - - This document can be considered a companion to the tutorial. It shows how to use - Python, and even more importantly, how *not* to use Python. - - -Language Constructs You Should Not Use -====================================== - -While Python has relatively few gotchas compared to other languages, it still -has some constructs which are only useful in corner cases, or are plain -dangerous. - - -from module import \* ---------------------- - - -Inside Function Definitions -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -``from module import *`` is *invalid* inside function definitions. While many -versions of Python do not check for the invalidity, it does not make it more -valid, no more than having a smart lawyer makes a man innocent. Do not use it -like that ever. Even in versions where it was accepted, it made the function -execution slower, because the compiler could not be certain which names are -local and which are global. In Python 2.1 this construct causes warnings, and -sometimes even errors. - - -At Module Level -^^^^^^^^^^^^^^^ - -While it is valid to use ``from module import *`` at module level it is usually -a bad idea. For one, this loses an important property Python otherwise has --- -you can know where each toplevel name is defined by a simple "search" function -in your favourite editor. You also open yourself to trouble in the future, if -some module grows additional functions or classes. - -One of the most awful question asked on the newsgroup is why this code:: - - f = open("www") - f.read() - -does not work. Of course, it works just fine (assuming you have a file called -"www".) But it does not work if somewhere in the module, the statement ``from -os import *`` is present. The :mod:`os` module has a function called -:func:`open` which returns an integer. While it is very useful, shadowing a -builtin is one of its least useful properties. - -Remember, you can never know for sure what names a module exports, so either -take what you need --- ``from module import name1, name2``, or keep them in the -module and access on a per-need basis --- ``import module; print(module.name)``. - - -When It Is Just Fine -^^^^^^^^^^^^^^^^^^^^ - -There are situations in which ``from module import *`` is just fine: - -* The interactive prompt. For example, ``from math import *`` makes Python an - amazing scientific calculator. - -* When extending a module in C with a module in Python. - -* When the module advertises itself as ``from import *`` safe. - - -from module import name1, name2 -------------------------------- - -This is a "don't" which is much weaker than the previous "don't"s but is still -something you should not do if you don't have good reasons to do that. The -reason it is usually bad idea is because you suddenly have an object which lives -in two separate namespaces. When the binding in one namespace changes, the -binding in the other will not, so there will be a discrepancy between them. This -happens when, for example, one module is reloaded, or changes the definition of -a function at runtime. - -Bad example:: - - # foo.py - a = 1 - - # bar.py - from foo import a - if something(): - a = 2 # danger: foo.a != a - -Good example:: - - # foo.py - a = 1 - - # bar.py - import foo - if something(): - foo.a = 2 - - -except: -------- - -Python has the ``except:`` clause, which catches all exceptions. Since *every* -error in Python raises an exception, using ``except:`` can make many -programming errors look like runtime problems, which hinders the debugging -process. - -The following code shows a great example of why this is bad:: - - try: - foo = opne("file") # misspelled "open" - except: - sys.exit("could not open file!") - -The second line triggers a :exc:`NameError`, which is caught by the except -clause. The program will exit, and the error message the program prints will -make you think the problem is the readability of ``"file"`` when in fact -the real error has nothing to do with ``"file"``. - -A better way to write the above is :: - - try: - foo = opne("file") - except IOError: - sys.exit("could not open file") - -When this is run, Python will produce a traceback showing the :exc:`NameError`, -and it will be immediately apparent what needs to be fixed. - -.. index:: bare except, except; bare - -Because ``except:`` catches *all* exceptions, including :exc:`SystemExit`, -:exc:`KeyboardInterrupt`, and :exc:`GeneratorExit` (which is not an error and -should not normally be caught by user code), using a bare ``except:`` is almost -never a good idea. In situations where you need to catch all "normal" errors, -such as in a framework that runs callbacks, you can catch the base class for -all normal exceptions, :exc:`Exception`. - - -Exceptions -========== - -Exceptions are a useful feature of Python. You should learn to raise them -whenever something unexpected occurs, and catch them only where you can do -something about them. - -The following is a very popular anti-idiom :: - - def get_status(file): - if not os.path.exists(file): - print("file not found") - sys.exit(1) - return open(file).readline() - -Consider the case where the file gets deleted between the time the call to -:func:`os.path.exists` is made and the time :func:`open` is called. In that -case the last line will raise an :exc:`IOError`. The same thing would happen -if *file* exists but has no read permission. Since testing this on a normal -machine on existent and non-existent files makes it seem bugless, the test -results will seem fine, and the code will get shipped. Later an unhandled -:exc:`IOError` (or perhaps some other :exc:`EnvironmentError`) escapes to the -user, who gets to watch the ugly traceback. - -Here is a somewhat better way to do it. :: - - def get_status(file): - try: - return open(file).readline() - except EnvironmentError as err: - print("Unable to open file: {}".format(err)) - sys.exit(1) - -In this version, *either* the file gets opened and the line is read (so it -works even on flaky NFS or SMB connections), or an error message is printed -that provides all the available information on why the open failed, and the -application is aborted. - -However, even this version of :func:`get_status` makes too many assumptions --- -that it will only be used in a short running script, and not, say, in a long -running server. Sure, the caller could do something like :: - - try: - status = get_status(log) - except SystemExit: - status = None - -But there is a better way. You should try to use as few ``except`` clauses in -your code as you can --- the ones you do use will usually be inside calls which -should always succeed, or a catch-all in a main function. - -So, an even better version of :func:`get_status()` is probably :: - - def get_status(file): - return open(file).readline() - -The caller can deal with the exception if it wants (for example, if it tries -several files in a loop), or just let the exception filter upwards to *its* -caller. - -But the last version still has a serious problem --- due to implementation -details in CPython, the file would not be closed when an exception is raised -until the exception handler finishes; and, worse, in other implementations -(e.g., Jython) it might not be closed at all regardless of whether or not -an exception is raised. - -The best version of this function uses the ``open()`` call as a context -manager, which will ensure that the file gets closed as soon as the -function returns:: - - def get_status(file): - with open(file) as fp: - return fp.readline() - - -Using the Batteries -=================== - -Every so often, people seem to be writing stuff in the Python library again, -usually poorly. While the occasional module has a poor interface, it is usually -much better to use the rich standard library and data types that come with -Python than inventing your own. - -A useful module very few people know about is :mod:`os.path`. It always has the -correct path arithmetic for your operating system, and will usually be much -better than whatever you come up with yourself. - -Compare:: - - # ugh! - return dir+"/"+file - # better - return os.path.join(dir, file) - -More useful functions in :mod:`os.path`: :func:`basename`, :func:`dirname` and -:func:`splitext`. - -There are also many useful built-in functions people seem not to be aware of -for some reason: :func:`min` and :func:`max` can find the minimum/maximum of -any sequence with comparable semantics, for example, yet many people write -their own :func:`max`/:func:`min`. Another highly useful function is -:func:`functools.reduce` which can be used to repeatly apply a binary -operation to a sequence, reducing it to a single value. For example, compute -a factorial with a series of multiply operations:: - - >>> n = 4 - >>> import operator, functools - >>> functools.reduce(operator.mul, range(1, n+1)) - 24 - -When it comes to parsing numbers, note that :func:`float`, :func:`int` and -:func:`long` all accept string arguments and will reject ill-formed strings -by raising an :exc:`ValueError`. - - -Using Backslash to Continue Statements -====================================== - -Since Python treats a newline as a statement terminator, and since statements -are often more than is comfortable to put in one line, many people do:: - - if foo.bar()['first'][0] == baz.quux(1, 2)[5:9] and \ - calculate_number(10, 20) != forbulate(500, 360): - pass - -You should realize that this is dangerous: a stray space after the ``\`` would -make this line wrong, and stray spaces are notoriously hard to see in editors. -In this case, at least it would be a syntax error, but if the code was:: - - value = foo.bar()['first'][0]*baz.quux(1, 2)[5:9] \ - + calculate_number(10, 20)*forbulate(500, 360) - -then it would just be subtly wrong. - -It is usually much better to use the implicit continuation inside parenthesis: - -This version is bulletproof:: - - value = (foo.bar()['first'][0]*baz.quux(1, 2)[5:9] - + calculate_number(10, 20)*forbulate(500, 360)) - diff --git a/Doc/howto/index.rst b/Doc/howto/index.rst index 94ecc9a..11fe108 100644 --- a/Doc/howto/index.rst +++ b/Doc/howto/index.rst @@ -18,7 +18,6 @@ Currently, the HOWTOs are: cporting.rst curses.rst descriptor.rst - doanddont.rst functional.rst logging.rst logging-cookbook.rst -- cgit v0.12 From 952c0782b39d2112c648f0731abf5e566fa20c37 Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Sat, 19 Mar 2011 15:22:59 +1000 Subject: Last attempt to get compiler recursion crasher to fail reliably across platforms before giving up and skipping it as unreliably platform dependent --- Lib/test/crashers/compiler_recursion.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/crashers/compiler_recursion.py b/Lib/test/crashers/compiler_recursion.py index c00cd6e..31f28a9 100644 --- a/Lib/test/crashers/compiler_recursion.py +++ b/Lib/test/crashers/compiler_recursion.py @@ -9,5 +9,5 @@ Recorded on the tracker as http://bugs.python.org/issue11383 # e.g. '1*'*10**5+'1' will die in compiler_visit_expr # The exact limit to destroy the stack will vary by platform -# but 1M should do the trick most places -compile('()'*10**6, '?', 'exec') +# but 10M should do the trick even with huge stack allocations +compile('()'*10**7, '?', 'exec') -- cgit v0.12 From 9ad63e091448d8778cde67fce8619baaab7cf10b Mon Sep 17 00:00:00 2001 From: Ross Lagerwall Date: Sat, 19 Mar 2011 09:11:14 +0200 Subject: Fix refleak introduced by #10812. --- Modules/posixmodule.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index f873a7a..8f17bf4 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -3827,16 +3827,19 @@ parse_arglist(PyObject* argv, Py_ssize_t *argc) return NULL; } for (i = 0; i < *argc; i++) { - if (!fsconvert_strdup(PySequence_ITEM(argv, i), - &argvlist[i])) - { - *argc = i; + PyObject* item = PySequence_ITEM(argv, i); + if (item == NULL) + goto fail; + if (!fsconvert_strdup(item, &argvlist[i])) { + Py_DECREF(item); goto fail; } + Py_DECREF(item); } argvlist[*argc] = NULL; return argvlist; fail: + *argc = i; free_string_array(argvlist, *argc); return NULL; } @@ -6177,22 +6180,28 @@ iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, int cnt, int type) } for (i = 0; i < cnt; i++) { - if (PyObject_GetBuffer(PySequence_GetItem(seq, i), - &(*buf)[i], type) == -1) { - PyMem_Del(*iov); - for (j = 0; j < i; j++) { - PyBuffer_Release(&(*buf)[j]); - } - PyMem_Del(*buf); - total = 0; - return total; + PyObject *item = PySequence_GetItem(seq, i); + if (item == NULL) + goto fail; + if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) { + Py_DECREF(item); + goto fail; } + Py_DECREF(item); (*iov)[i].iov_base = (*buf)[i].buf; blen = (*buf)[i].len; (*iov)[i].iov_len = blen; total += blen; } return total; + +fail: + PyMem_Del(*iov); + for (j = 0; j < i; j++) { + PyBuffer_Release(&(*buf)[j]); + } + PyMem_Del(*buf); + return 0; } static void -- cgit v0.12 From d91ffcafcb39a5426e73ce9ec4b15077662ec571 Mon Sep 17 00:00:00 2001 From: Senthil Kumaran Date: Sat, 19 Mar 2011 17:25:27 +0800 Subject: Closes issue11563 - test_urllibnet ResourceWarning. Patch by Jeff McNeil. --- Lib/test/test_urllib.py | 7 ++++++- Lib/urllib/request.py | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py index 673afc4..074d833 100644 --- a/Lib/test/test_urllib.py +++ b/Lib/test/test_urllib.py @@ -91,7 +91,7 @@ class urlopen_FileTests(unittest.TestCase): "did not return the expected text") def test_close(self): - # Test close() by calling it hear and then having it be called again + # Test close() by calling it here and then having it be called again # by the tearDown() method for the test self.returned_obj.close() @@ -174,6 +174,11 @@ class urlopen_HttpTests(unittest.TestCase): finally: self.unfakehttp() + def test_willclose(self): + self.fakehttp(b"HTTP/1.1 200 OK\r\n\r\nHello!") + resp = urlopen("http://www.python.org") + self.assertTrue(resp.fp.will_close) + def test_read_0_9(self): # "0.9" response accepted (but not "simple responses" without # a status line) diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py index 1e437b5..4d3648d 100644 --- a/Lib/urllib/request.py +++ b/Lib/urllib/request.py @@ -1657,6 +1657,12 @@ class URLopener: headers["Authorization"] = "Basic %s" % auth if realhost: headers["Host"] = realhost + + # Add Connection:close as we don't support persistent connections yet. + # This helps in closing the socket and avoiding ResourceWarning + + headers["Connection"] = "close" + for header, value in self.addheaders: headers[header] = value -- cgit v0.12