diff options
Diffstat (limited to 'Lib')
30 files changed, 371 insertions, 721 deletions
diff --git a/Lib/_pyio.py b/Lib/_pyio.py index d0947f0..569527b 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -635,7 +635,7 @@ class BufferedIOBase(IOBase): implementation, but wrap one. """ - def read(self, size=None): + def read(self, size=-1): """Read and return up to size bytes, where size is an int. If the argument is omitted, None, or negative, reads and @@ -655,7 +655,7 @@ class BufferedIOBase(IOBase): """ self._unsupported("read") - def read1(self, size=None): + def read1(self, size=-1): """Read up to size bytes with at most one read() system call, where size is an int. """ @@ -863,7 +863,7 @@ class BytesIO(BufferedIOBase): self._buffer.clear() super().close() - def read(self, size=None): + def read(self, size=-1): if self.closed: raise ValueError("read from closed file") if size is None: @@ -877,7 +877,7 @@ class BytesIO(BufferedIOBase): self._pos = newpos return bytes(b) - def read1(self, size): + def read1(self, size=-1): """This is the same as read. """ return self.read(size) @@ -1073,12 +1073,12 @@ class BufferedReader(_BufferedIOMixin): self._read_pos = 0 return self._read_buf[self._read_pos:] - def read1(self, size): + def read1(self, size=-1): """Reads up to size bytes, with at most one read() system call.""" # Returns up to size bytes. If at least one byte is buffered, we # only return buffered bytes. Otherwise, we do one raw read. if size < 0: - raise ValueError("number of bytes to read must be positive") + size = self.buffer_size if size == 0: return b"" with self._read_lock: @@ -1270,7 +1270,7 @@ class BufferedRWPair(BufferedIOBase): self.reader = BufferedReader(reader, buffer_size) self.writer = BufferedWriter(writer, buffer_size) - def read(self, size=None): + def read(self, size=-1): if size is None: size = -1 return self.reader.read(size) @@ -1284,7 +1284,7 @@ class BufferedRWPair(BufferedIOBase): def peek(self, size=0): return self.reader.peek(size) - def read1(self, size): + def read1(self, size=-1): return self.reader.read1(size) def readinto1(self, b): @@ -1370,7 +1370,7 @@ class BufferedRandom(BufferedWriter, BufferedReader): self.flush() return BufferedReader.peek(self, size) - def read1(self, size): + def read1(self, size=-1): self.flush() return BufferedReader.read1(self, size) diff --git a/Lib/calendar.py b/Lib/calendar.py index 07594f3..28ac56f 100644 --- a/Lib/calendar.py +++ b/Lib/calendar.py @@ -267,7 +267,7 @@ class TextCalendar(Calendar): """ Print a single week (no newline). """ - print(self.formatweek(theweek, width), end=' ') + print(self.formatweek(theweek, width), end='') def formatday(self, day, weekday, width): """ @@ -371,7 +371,7 @@ class TextCalendar(Calendar): def pryear(self, theyear, w=0, l=0, c=6, m=3): """Print a year's calendar.""" - print(self.formatyear(theyear, w, l, c, m)) + print(self.formatyear(theyear, w, l, c, m), end='') class HTMLCalendar(Calendar): diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py index 339ae8a..8856f65 100644 --- a/Lib/ctypes/util.py +++ b/Lib/ctypes/util.py @@ -318,10 +318,6 @@ def test(): print(find_library("c")) print(find_library("bz2")) - # getattr -## print cdll.m -## print cdll.bz2 - # load if sys.platform == "darwin": print(cdll.LoadLibrary("libm.dylib")) diff --git a/Lib/distutils/command/build_ext.py b/Lib/distutils/command/build_ext.py index 74de782..9155626 100644 --- a/Lib/distutils/command/build_ext.py +++ b/Lib/distutils/command/build_ext.py @@ -715,13 +715,6 @@ class build_ext(Command): return ext.libraries + [pythonlib] else: return ext.libraries - elif sys.platform[:6] == "cygwin": - template = "python%d.%d" - pythonlib = (template % - (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) - # don't extend ext.libraries, it may be shared with other - # extensions, it is a reference to the original list - return ext.libraries + [pythonlib] elif sys.platform[:6] == "atheos": from distutils import sysconfig diff --git a/Lib/distutils/command/sdist.py b/Lib/distutils/command/sdist.py index 4fd1d47..180e286 100644 --- a/Lib/distutils/command/sdist.py +++ b/Lib/distutils/command/sdist.py @@ -4,17 +4,19 @@ Implements the Distutils 'sdist' command (create a source distribution).""" import os import sys -from types import * from glob import glob from warnings import warn from distutils.core import Command -from distutils import dir_util, dep_util, file_util, archive_util +from distutils import dir_util +from distutils import file_util +from distutils import archive_util from distutils.text_file import TextFile -from distutils.errors import * from distutils.filelist import FileList from distutils import log from distutils.util import convert_path +from distutils.errors import DistutilsTemplateError, DistutilsOptionError + def show_formats(): """Print all possible values for the 'formats' option (used by @@ -30,6 +32,7 @@ def show_formats(): FancyGetopt(formats).print_help( "List of available source distribution formats:") + class sdist(Command): description = "create a source distribution (tarball, zip file, etc.)" @@ -93,6 +96,8 @@ class sdist(Command): sub_commands = [('check', checking_metadata)] + READMES = 'README', 'README.txt' + def initialize_options(self): # 'template' and 'manifest' are, respectively, the names of # the manifest template and manifest file. @@ -216,13 +221,39 @@ class sdist(Command): Warns if (README or README.txt) or setup.py are missing; everything else is optional. """ - standards = [('README', 'README.txt'), self.distribution.script_name] + self._add_defaults_standards() + self._add_defaults_optional() + self._add_defaults_python() + self._add_defaults_data_files() + self._add_defaults_ext() + self._add_defaults_c_libs() + self._add_defaults_scripts() + + @staticmethod + def _cs_path_exists(fspath): + """ + Case-sensitive path existence check + + >>> sdist._cs_path_exists(__file__) + True + >>> sdist._cs_path_exists(__file__.upper()) + False + """ + if not os.path.exists(fspath): + return False + # make absolute so we always have a directory + abspath = os.path.abspath(fspath) + directory, filename = os.path.split(abspath) + return filename in os.listdir(directory) + + def _add_defaults_standards(self): + standards = [self.READMES, self.distribution.script_name] for fn in standards: if isinstance(fn, tuple): alts = fn got_it = False for fn in alts: - if os.path.exists(fn): + if self._cs_path_exists(fn): got_it = True self.filelist.append(fn) break @@ -231,16 +262,18 @@ class sdist(Command): self.warn("standard file not found: should have one of " + ', '.join(alts)) else: - if os.path.exists(fn): + if self._cs_path_exists(fn): self.filelist.append(fn) else: self.warn("standard file '%s' not found" % fn) + def _add_defaults_optional(self): optional = ['test/test*.py', 'setup.cfg'] for pattern in optional: files = filter(os.path.isfile, glob(pattern)) self.filelist.extend(files) + def _add_defaults_python(self): # build_py is used to get: # - python modules # - files defined in package_data @@ -256,28 +289,34 @@ class sdist(Command): for filename in filenames: self.filelist.append(os.path.join(src_dir, filename)) + def _add_defaults_data_files(self): # getting distribution.data_files if self.distribution.has_data_files(): for item in self.distribution.data_files: - if isinstance(item, str): # plain file + if isinstance(item, str): + # plain file item = convert_path(item) if os.path.isfile(item): self.filelist.append(item) - else: # a (dirname, filenames) tuple + else: + # a (dirname, filenames) tuple dirname, filenames = item for f in filenames: f = convert_path(f) if os.path.isfile(f): self.filelist.append(f) + def _add_defaults_ext(self): if self.distribution.has_ext_modules(): build_ext = self.get_finalized_command('build_ext') self.filelist.extend(build_ext.get_source_files()) + def _add_defaults_c_libs(self): if self.distribution.has_c_libraries(): build_clib = self.get_finalized_command('build_clib') self.filelist.extend(build_clib.get_source_files()) + def _add_defaults_scripts(self): if self.distribution.has_scripts(): build_scripts = self.get_finalized_command('build_scripts') self.filelist.extend(build_scripts.get_source_files()) diff --git a/Lib/http/client.py b/Lib/http/client.py index a8e59b9..59237a3 100644 --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -642,14 +642,7 @@ class HTTPResponse(io.BufferedIOBase): return self._read1_chunked(n) if self.length is not None and (n < 0 or n > self.length): n = self.length - try: - result = self.fp.read1(n) - except ValueError: - if n >= 0: - raise - # some implementations, like BufferedReader, don't support -1 - # Read an arbitrarily selected largeish chunk. - result = self.fp.read1(16*1024) + result = self.fp.read1(n) if not result and n: self._close_conn() elif self.length is not None: diff --git a/Lib/http/server.py b/Lib/http/server.py index e12e45b..61ddecc 100644 --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -267,8 +267,8 @@ class BaseHTTPRequestHandler(socketserver.StreamRequestHandler): are in self.command, self.path, self.request_version and self.headers. - Return True for success, False for failure; on failure, an - error is sent back. + Return True for success, False for failure; on failure, any relevant + error response has already been sent back. """ self.command = None # set in case of error on the first line @@ -278,10 +278,13 @@ class BaseHTTPRequestHandler(socketserver.StreamRequestHandler): requestline = requestline.rstrip('\r\n') self.requestline = requestline words = requestline.split() - if len(words) == 3: - command, path, version = words + if len(words) == 0: + return False + + if len(words) >= 3: # Enough to determine protocol version + version = words[-1] try: - if version[:5] != 'HTTP/': + if not version.startswith('HTTP/'): raise ValueError base_version_number = version.split('/', 1)[1] version_number = base_version_number.split(".") @@ -306,22 +309,22 @@ class BaseHTTPRequestHandler(socketserver.StreamRequestHandler): HTTPStatus.HTTP_VERSION_NOT_SUPPORTED, "Invalid HTTP version (%s)" % base_version_number) return False - elif len(words) == 2: - command, path = words + self.request_version = version + + if not 2 <= len(words) <= 3: + self.send_error( + HTTPStatus.BAD_REQUEST, + "Bad request syntax (%r)" % requestline) + return False + command, path = words[:2] + if len(words) == 2: self.close_connection = True if command != 'GET': self.send_error( HTTPStatus.BAD_REQUEST, "Bad HTTP/0.9 request type (%r)" % command) return False - elif not words: - return False - else: - self.send_error( - HTTPStatus.BAD_REQUEST, - "Bad request syntax (%r)" % requestline) - return False - self.command, self.path, self.request_version = command, path, version + self.command, self.path = command, path # Examine the headers and look for a Connection directive. try: diff --git a/Lib/logging/config.py b/Lib/logging/config.py index 8a99923..917178e 100644 --- a/Lib/logging/config.py +++ b/Lib/logging/config.py @@ -1,4 +1,4 @@ -# Copyright 2001-2014 by Vinay Sajip. All Rights Reserved. +# Copyright 2001-2016 by Vinay Sajip. All Rights Reserved. # # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose and without fee is hereby granted, @@ -19,7 +19,7 @@ Configuration functions for the logging package for Python. The core package is based on PEP 282 and comments thereto in comp.lang.python, and influenced by Apache's log4j system. -Copyright (C) 2001-2014 Vinay Sajip. All Rights Reserved. +Copyright (C) 2001-2016 Vinay Sajip. All Rights Reserved. To use, simply 'import logging' and log away! """ @@ -509,21 +509,21 @@ class DictConfigurator(BaseConfigurator): handler.setLevel(logging._checkLevel(level)) except Exception as e: raise ValueError('Unable to configure handler ' - '%r: %s' % (name, e)) + '%r' % name) from e loggers = config.get('loggers', EMPTY_DICT) for name in loggers: try: self.configure_logger(name, loggers[name], True) except Exception as e: raise ValueError('Unable to configure logger ' - '%r: %s' % (name, e)) + '%r' % name) from e root = config.get('root', None) if root: try: self.configure_root(root, True) except Exception as e: raise ValueError('Unable to configure root ' - 'logger: %s' % e) + 'logger') from e else: disable_existing = config.pop('disable_existing_loggers', True) @@ -538,7 +538,7 @@ class DictConfigurator(BaseConfigurator): formatters[name]) except Exception as e: raise ValueError('Unable to configure ' - 'formatter %r: %s' % (name, e)) + 'formatter %r' % name) from e # Next, do filters - they don't refer to anything else, either filters = config.get('filters', EMPTY_DICT) for name in filters: @@ -546,7 +546,7 @@ class DictConfigurator(BaseConfigurator): filters[name] = self.configure_filter(filters[name]) except Exception as e: raise ValueError('Unable to configure ' - 'filter %r: %s' % (name, e)) + 'filter %r' % name) from e # Next, do handlers - they refer to formatters and filters # As handlers can refer to other handlers, sort the keys @@ -559,11 +559,11 @@ class DictConfigurator(BaseConfigurator): handler.name = name handlers[name] = handler except Exception as e: - if 'target not configured yet' in str(e): + if 'target not configured yet' in str(e.__cause__): deferred.append(name) else: raise ValueError('Unable to configure handler ' - '%r: %s' % (name, e)) + '%r' % name) from e # Now do any that were deferred for name in deferred: @@ -573,7 +573,7 @@ class DictConfigurator(BaseConfigurator): handlers[name] = handler except Exception as e: raise ValueError('Unable to configure handler ' - '%r: %s' % (name, e)) + '%r' % name) from e # Next, do loggers - they refer to handlers and filters @@ -612,7 +612,7 @@ class DictConfigurator(BaseConfigurator): self.configure_logger(name, loggers[name]) except Exception as e: raise ValueError('Unable to configure logger ' - '%r: %s' % (name, e)) + '%r' % name) from e #Disable any old loggers. There's no point deleting #them as other threads may continue to hold references @@ -637,7 +637,7 @@ class DictConfigurator(BaseConfigurator): self.configure_root(root) except Exception as e: raise ValueError('Unable to configure root ' - 'logger: %s' % e) + 'logger') from e finally: logging._releaseLock() @@ -684,7 +684,7 @@ class DictConfigurator(BaseConfigurator): try: filterer.addFilter(self.config['filters'][f]) except Exception as e: - raise ValueError('Unable to add filter %r: %s' % (f, e)) + raise ValueError('Unable to add filter %r' % f) from e def configure_handler(self, config): """Configure a handler from a dictionary.""" @@ -695,7 +695,7 @@ class DictConfigurator(BaseConfigurator): formatter = self.config['formatters'][formatter] except Exception as e: raise ValueError('Unable to set formatter ' - '%r: %s' % (formatter, e)) + '%r' % formatter) from e level = config.pop('level', None) filters = config.pop('filters', None) if '()' in config: @@ -717,7 +717,7 @@ class DictConfigurator(BaseConfigurator): config['target'] = th except Exception as e: raise ValueError('Unable to set target handler ' - '%r: %s' % (config['target'], e)) + '%r' % config['target']) from e elif issubclass(klass, logging.handlers.SMTPHandler) and\ 'mailhost' in config: config['mailhost'] = self.as_tuple(config['mailhost']) @@ -755,7 +755,7 @@ class DictConfigurator(BaseConfigurator): try: logger.addHandler(self.config['handlers'][h]) except Exception as e: - raise ValueError('Unable to add handler %r: %s' % (h, e)) + raise ValueError('Unable to add handler %r' % h) from e def common_logger_config(self, logger, config, incremental=False): """ diff --git a/Lib/macurl2path.py b/Lib/macurl2path.py deleted file mode 100644 index a68821d..0000000 --- a/Lib/macurl2path.py +++ /dev/null @@ -1,77 +0,0 @@ -"""Macintosh-specific module for conversion between pathnames and URLs. - -Do not import directly; use urllib instead.""" - -import urllib.parse -import os - -__all__ = ["url2pathname","pathname2url"] - -def url2pathname(pathname): - """OS-specific conversion from a relative URL of the 'file' scheme - to a file system path; not recommended for general use.""" - # - # XXXX The .. handling should be fixed... - # - tp = urllib.parse.splittype(pathname)[0] - if tp and tp != 'file': - raise RuntimeError('Cannot convert non-local URL to pathname') - # Turn starting /// into /, an empty hostname means current host - if pathname[:3] == '///': - pathname = pathname[2:] - elif pathname[:2] == '//': - raise RuntimeError('Cannot convert non-local URL to pathname') - components = pathname.split('/') - # Remove . and embedded .. - i = 0 - while i < len(components): - if components[i] == '.': - del components[i] - elif components[i] == '..' and i > 0 and \ - components[i-1] not in ('', '..'): - del components[i-1:i+1] - i = i-1 - elif components[i] == '' and i > 0 and components[i-1] != '': - del components[i] - else: - i = i+1 - if not components[0]: - # Absolute unix path, don't start with colon - rv = ':'.join(components[1:]) - else: - # relative unix path, start with colon. First replace - # leading .. by empty strings (giving ::file) - i = 0 - while i < len(components) and components[i] == '..': - components[i] = '' - i = i + 1 - rv = ':' + ':'.join(components) - # and finally unquote slashes and other funny characters - return urllib.parse.unquote(rv) - -def pathname2url(pathname): - """OS-specific conversion from a file system path to a relative URL - of the 'file' scheme; not recommended for general use.""" - if '/' in pathname: - raise RuntimeError("Cannot convert pathname containing slashes") - components = pathname.split(':') - # Remove empty first and/or last component - if components[0] == '': - del components[0] - if components[-1] == '': - del components[-1] - # Replace empty string ('::') by .. (will result in '/../' later) - for i in range(len(components)): - if components[i] == '': - components[i] = '..' - # Truncate names longer than 31 bytes - components = map(_pncomp2url, components) - - if os.path.isabs(pathname): - return '/' + '/'.join(components) - else: - return '/'.join(components) - -def _pncomp2url(component): - # We want to quote slashes - return urllib.parse.quote(component[:31], safe='') diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py index 914e818..3579484 100644 --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Mon Oct 31 20:37:53 2016 +# Autogenerated by Sphinx on Mon Sep 12 10:47:11 2016 topics = {'assert': '\n' 'The "assert" statement\n' '**********************\n' @@ -5066,9 +5066,9 @@ topics = {'assert': '\n' 'be formatted\n' 'with the floating point presentation types listed below ' '(except "\'n\'"\n' - 'and "None"). When doing so, "float()" is used to convert ' - 'the integer\n' - 'to a floating point number before formatting.\n' + 'and None). When doing so, "float()" is used to convert the ' + 'integer to\n' + 'a floating point number before formatting.\n' '\n' 'The available presentation types for floating point and ' 'decimal values\n' @@ -9626,7 +9626,7 @@ topics = {'assert': '\n' ' Unicode ordinals (integers) or characters (strings of ' 'length 1) to\n' ' Unicode ordinals, strings (of arbitrary lengths) or ' - '"None".\n' + 'None.\n' ' Character keys will then be converted to ordinals.\n' '\n' ' If there are two arguments, they must be strings of ' @@ -9637,7 +9637,7 @@ topics = {'assert': '\n' 'is a third\n' ' argument, it must be a string, whose characters will be ' 'mapped to\n' - ' "None" in the result.\n' + ' None in the result.\n' '\n' 'str.partition(sep)\n' '\n' @@ -11204,7 +11204,7 @@ topics = {'assert': '\n' 'the\n' ' order of their occurrence in the base class list; "__doc__" is ' 'the\n' - ' class\'s documentation string, or "None" if undefined;\n' + " class's documentation string, or None if undefined;\n" ' "__annotations__" (optional) is a dictionary containing ' '*variable\n' ' annotations* collected during class body execution.\n' diff --git a/Lib/subprocess.py b/Lib/subprocess.py index 0b880f6..c40f017 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -1027,15 +1027,9 @@ class Popen(object): return self.returncode - def wait(self, timeout=None, endtime=None): + def wait(self, timeout=None): """Wait for child process to terminate. Returns returncode attribute.""" - if endtime is not None: - warnings.warn( - "'endtime' argument is deprecated; use 'timeout'.", - DeprecationWarning, - stacklevel=2) - timeout = self._remaining_time(endtime) if timeout is None: timeout_millis = _winapi.INFINITE else: @@ -1390,24 +1384,14 @@ class Popen(object): return (pid, sts) - def wait(self, timeout=None, endtime=None): + def wait(self, timeout=None): """Wait for child process to terminate. Returns returncode attribute.""" if self.returncode is not None: return self.returncode - if endtime is not None: - warnings.warn( - "'endtime' argument is deprecated; use 'timeout'.", - DeprecationWarning, - stacklevel=2) - if endtime is not None or timeout is not None: - if endtime is None: - endtime = _time() + timeout - elif timeout is None: - timeout = self._remaining_time(endtime) - - if endtime is not None: + if timeout is not None: + endtime = _time() + timeout # 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 diff --git a/Lib/test/libregrtest/runtest_mp.py b/Lib/test/libregrtest/runtest_mp.py index 9604c16..74ac4fa 100644 --- a/Lib/test/libregrtest/runtest_mp.py +++ b/Lib/test/libregrtest/runtest_mp.py @@ -41,7 +41,7 @@ def run_test_in_subprocess(testname, ns): slaveargs = json.dumps(slaveargs) cmd = [sys.executable, *support.args_from_interpreter_flags(), - '-X', 'faulthandler', + '-u', # Unbuffered stdout and stderr '-m', 'test.regrtest', '--slaveargs', slaveargs] if ns.pgo: diff --git a/Lib/test/pystone.py b/Lib/test/pystone.py deleted file mode 100755 index cf1692e..0000000 --- a/Lib/test/pystone.py +++ /dev/null @@ -1,277 +0,0 @@ -#! /usr/bin/env python3 - -""" -"PYSTONE" Benchmark Program - -Version: Python/1.2 (corresponds to C/1.1 plus 3 Pystone fixes) - -Author: Reinhold P. Weicker, CACM Vol 27, No 10, 10/84 pg. 1013. - - Translated from ADA to C by Rick Richardson. - Every method to preserve ADA-likeness has been used, - at the expense of C-ness. - - Translated from C to Python by Guido van Rossum. - -Version History: - - Version 1.1 corrects two bugs in version 1.0: - - First, it leaked memory: in Proc1(), NextRecord ends - up having a pointer to itself. I have corrected this - by zapping NextRecord.PtrComp at the end of Proc1(). - - Second, Proc3() used the operator != to compare a - record to None. This is rather inefficient and not - true to the intention of the original benchmark (where - a pointer comparison to None is intended; the != - operator attempts to find a method __cmp__ to do value - comparison of the record). Version 1.1 runs 5-10 - percent faster than version 1.0, so benchmark figures - of different versions can't be compared directly. - - Version 1.2 changes the division to floor division. - - Under Python 3 version 1.1 would use the normal division - operator, resulting in some of the operations mistakenly - yielding floats. Version 1.2 instead uses floor division - making the benchmark an integer benchmark again. - -""" - -LOOPS = 50000 - -from time import time - -__version__ = "1.2" - -[Ident1, Ident2, Ident3, Ident4, Ident5] = range(1, 6) - -class Record: - - def __init__(self, PtrComp = None, Discr = 0, EnumComp = 0, - IntComp = 0, StringComp = 0): - self.PtrComp = PtrComp - self.Discr = Discr - self.EnumComp = EnumComp - self.IntComp = IntComp - self.StringComp = StringComp - - def copy(self): - return Record(self.PtrComp, self.Discr, self.EnumComp, - self.IntComp, self.StringComp) - -TRUE = 1 -FALSE = 0 - -def main(loops=LOOPS): - benchtime, stones = pystones(loops) - print("Pystone(%s) time for %d passes = %g" % \ - (__version__, loops, benchtime)) - print("This machine benchmarks at %g pystones/second" % stones) - - -def pystones(loops=LOOPS): - return Proc0(loops) - -IntGlob = 0 -BoolGlob = FALSE -Char1Glob = '\0' -Char2Glob = '\0' -Array1Glob = [0]*51 -Array2Glob = [x[:] for x in [Array1Glob]*51] -PtrGlb = None -PtrGlbNext = None - -def Proc0(loops=LOOPS): - global IntGlob - global BoolGlob - global Char1Glob - global Char2Glob - global Array1Glob - global Array2Glob - global PtrGlb - global PtrGlbNext - - starttime = time() - for i in range(loops): - pass - nulltime = time() - starttime - - PtrGlbNext = Record() - PtrGlb = Record() - PtrGlb.PtrComp = PtrGlbNext - PtrGlb.Discr = Ident1 - PtrGlb.EnumComp = Ident3 - PtrGlb.IntComp = 40 - PtrGlb.StringComp = "DHRYSTONE PROGRAM, SOME STRING" - String1Loc = "DHRYSTONE PROGRAM, 1'ST STRING" - Array2Glob[8][7] = 10 - - starttime = time() - - for i in range(loops): - Proc5() - Proc4() - IntLoc1 = 2 - IntLoc2 = 3 - String2Loc = "DHRYSTONE PROGRAM, 2'ND STRING" - EnumLoc = Ident2 - BoolGlob = not Func2(String1Loc, String2Loc) - while IntLoc1 < IntLoc2: - IntLoc3 = 5 * IntLoc1 - IntLoc2 - IntLoc3 = Proc7(IntLoc1, IntLoc2) - IntLoc1 = IntLoc1 + 1 - Proc8(Array1Glob, Array2Glob, IntLoc1, IntLoc3) - PtrGlb = Proc1(PtrGlb) - CharIndex = 'A' - while CharIndex <= Char2Glob: - if EnumLoc == Func1(CharIndex, 'C'): - EnumLoc = Proc6(Ident1) - CharIndex = chr(ord(CharIndex)+1) - IntLoc3 = IntLoc2 * IntLoc1 - IntLoc2 = IntLoc3 // IntLoc1 - IntLoc2 = 7 * (IntLoc3 - IntLoc2) - IntLoc1 - IntLoc1 = Proc2(IntLoc1) - - benchtime = time() - starttime - nulltime - if benchtime == 0.0: - loopsPerBenchtime = 0.0 - else: - loopsPerBenchtime = (loops / benchtime) - return benchtime, loopsPerBenchtime - -def Proc1(PtrParIn): - PtrParIn.PtrComp = NextRecord = PtrGlb.copy() - PtrParIn.IntComp = 5 - NextRecord.IntComp = PtrParIn.IntComp - NextRecord.PtrComp = PtrParIn.PtrComp - NextRecord.PtrComp = Proc3(NextRecord.PtrComp) - if NextRecord.Discr == Ident1: - NextRecord.IntComp = 6 - NextRecord.EnumComp = Proc6(PtrParIn.EnumComp) - NextRecord.PtrComp = PtrGlb.PtrComp - NextRecord.IntComp = Proc7(NextRecord.IntComp, 10) - else: - PtrParIn = NextRecord.copy() - NextRecord.PtrComp = None - return PtrParIn - -def Proc2(IntParIO): - IntLoc = IntParIO + 10 - while 1: - if Char1Glob == 'A': - IntLoc = IntLoc - 1 - IntParIO = IntLoc - IntGlob - EnumLoc = Ident1 - if EnumLoc == Ident1: - break - return IntParIO - -def Proc3(PtrParOut): - global IntGlob - - if PtrGlb is not None: - PtrParOut = PtrGlb.PtrComp - else: - IntGlob = 100 - PtrGlb.IntComp = Proc7(10, IntGlob) - return PtrParOut - -def Proc4(): - global Char2Glob - - BoolLoc = Char1Glob == 'A' - BoolLoc = BoolLoc or BoolGlob - Char2Glob = 'B' - -def Proc5(): - global Char1Glob - global BoolGlob - - Char1Glob = 'A' - BoolGlob = FALSE - -def Proc6(EnumParIn): - EnumParOut = EnumParIn - if not Func3(EnumParIn): - EnumParOut = Ident4 - if EnumParIn == Ident1: - EnumParOut = Ident1 - elif EnumParIn == Ident2: - if IntGlob > 100: - EnumParOut = Ident1 - else: - EnumParOut = Ident4 - elif EnumParIn == Ident3: - EnumParOut = Ident2 - elif EnumParIn == Ident4: - pass - elif EnumParIn == Ident5: - EnumParOut = Ident3 - return EnumParOut - -def Proc7(IntParI1, IntParI2): - IntLoc = IntParI1 + 2 - IntParOut = IntParI2 + IntLoc - return IntParOut - -def Proc8(Array1Par, Array2Par, IntParI1, IntParI2): - global IntGlob - - IntLoc = IntParI1 + 5 - Array1Par[IntLoc] = IntParI2 - Array1Par[IntLoc+1] = Array1Par[IntLoc] - Array1Par[IntLoc+30] = IntLoc - for IntIndex in range(IntLoc, IntLoc+2): - Array2Par[IntLoc][IntIndex] = IntLoc - Array2Par[IntLoc][IntLoc-1] = Array2Par[IntLoc][IntLoc-1] + 1 - Array2Par[IntLoc+20][IntLoc] = Array1Par[IntLoc] - IntGlob = 5 - -def Func1(CharPar1, CharPar2): - CharLoc1 = CharPar1 - CharLoc2 = CharLoc1 - if CharLoc2 != CharPar2: - return Ident1 - else: - return Ident2 - -def Func2(StrParI1, StrParI2): - IntLoc = 1 - while IntLoc <= 1: - if Func1(StrParI1[IntLoc], StrParI2[IntLoc+1]) == Ident1: - CharLoc = 'A' - IntLoc = IntLoc + 1 - if CharLoc >= 'W' and CharLoc <= 'Z': - IntLoc = 7 - if CharLoc == 'X': - return TRUE - else: - if StrParI1 > StrParI2: - IntLoc = IntLoc + 7 - return TRUE - else: - return FALSE - -def Func3(EnumParIn): - EnumLoc = EnumParIn - if EnumLoc == Ident3: return TRUE - return FALSE - -if __name__ == '__main__': - import sys - def error(msg): - print(msg, end=' ', file=sys.stderr) - print("usage: %s [number_of_loops]" % sys.argv[0], file=sys.stderr) - sys.exit(100) - nargs = len(sys.argv) - 1 - if nargs > 1: - error("%d arguments are too many;" % nargs) - elif nargs == 1: - try: loops = int(sys.argv[1]) - except ValueError: - error("Invalid argument %r;" % sys.argv[1]) - else: - loops = LOOPS - main(loops) diff --git a/Lib/test/test_calendar.py b/Lib/test/test_calendar.py index 2bc4fee..bd57653 100644 --- a/Lib/test/test_calendar.py +++ b/Lib/test/test_calendar.py @@ -404,7 +404,7 @@ class OutputTestCase(unittest.TestCase): with support.captured_stdout() as out: week = [(1,0), (2,1), (3,2), (4,3), (5,4), (6,5), (7,6)] calendar.TextCalendar().prweek(week, 1) - self.assertEqual(out.getvalue().strip(), "1 2 3 4 5 6 7") + self.assertEqual(out.getvalue(), " 1 2 3 4 5 6 7") def test_prmonth(self): with support.captured_stdout() as out: @@ -414,7 +414,7 @@ class OutputTestCase(unittest.TestCase): def test_pryear(self): with support.captured_stdout() as out: calendar.TextCalendar().pryear(2004) - self.assertEqual(out.getvalue().strip(), result_2004_text.strip()) + self.assertEqual(out.getvalue(), result_2004_text) def test_format(self): with support.captured_stdout() as out: diff --git a/Lib/test/test_epoll.py b/Lib/test/test_epoll.py index a7aff8a..549e0f7 100644 --- a/Lib/test/test_epoll.py +++ b/Lib/test/test_epoll.py @@ -76,6 +76,8 @@ class TestEPoll(unittest.TestCase): self.assertRaises(ValueError, ep.fileno) if hasattr(select, "EPOLL_CLOEXEC"): select.epoll(select.EPOLL_CLOEXEC).close() + select.epoll(flags=select.EPOLL_CLOEXEC).close() + select.epoll(flags=0).close() self.assertRaises(OSError, select.epoll, flags=12356) def test_badcreate(self): diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 4837922..34265a5 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -1112,6 +1112,20 @@ class ImportErrorTests(unittest.TestCase): with self.assertRaisesRegex(TypeError, msg): ImportError('test', invalid='keyword', another=True) + def test_reset_attributes(self): + exc = ImportError('test', name='name', path='path') + self.assertEqual(exc.args, ('test',)) + self.assertEqual(exc.msg, 'test') + self.assertEqual(exc.name, 'name') + self.assertEqual(exc.path, 'path') + + # Reset not specified attributes + exc.__init__() + self.assertEqual(exc.args, ()) + self.assertEqual(exc.msg, None) + self.assertEqual(exc.name, None) + self.assertEqual(exc.path, None) + def test_non_str_argument(self): # Issue #15778 with check_warnings(('', BytesWarning), quiet=True): diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py index bdd8d1a..67219c1 100644 --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -44,7 +44,7 @@ def temporary_filename(): def requires_raise(test): return (test if not is_android else - requires_android_level(24, 'raise() is buggy')(test)) + requires_android_level(24, 'raise() is buggy')(test)) class FaultHandlerTests(unittest.TestCase): def get_output(self, code, filename=None, fd=None): diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py index 4e93144..5049538 100644 --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -822,6 +822,16 @@ class BaseHTTPRequestHandlerTestCase(unittest.TestCase): self.assertEqual(result[0], b'<html><body>Data</body></html>\r\n') self.verify_get_called() + def test_extra_space(self): + result = self.send_typical_request( + b'GET /spaced out HTTP/1.1\r\n' + b'Host: dummy\r\n' + b'\r\n' + ) + self.assertTrue(result[0].startswith(b'HTTP/1.1 400 ')) + self.verify_expected_headers(result[1:result.index(b'\r\n')]) + self.assertFalse(self.handler.get_called) + def test_with_continue_1_0(self): result = self.send_typical_request(b'GET / HTTP/1.0\r\nExpect: 100-continue\r\n\r\n') self.verify_http_server_response(result[0]) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index aaa64ea..fc68b09 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -1149,6 +1149,7 @@ class BufferedReaderTest(unittest.TestCase, CommonBufferedTests): self.assertEqual(b"a", bufio.read(1)) self.assertEqual(b"b", bufio.read1(1)) self.assertEqual(rawio._reads, 1) + self.assertEqual(b"", bufio.read1(0)) self.assertEqual(b"c", bufio.read1(100)) self.assertEqual(rawio._reads, 1) self.assertEqual(b"d", bufio.read1(100)) @@ -1157,8 +1158,17 @@ class BufferedReaderTest(unittest.TestCase, CommonBufferedTests): self.assertEqual(rawio._reads, 3) self.assertEqual(b"", bufio.read1(100)) self.assertEqual(rawio._reads, 4) - # Invalid args - self.assertRaises(ValueError, bufio.read1, -1) + + def test_read1_arbitrary(self): + rawio = self.MockRawIO((b"abc", b"d", b"efg")) + bufio = self.tp(rawio) + self.assertEqual(b"a", bufio.read(1)) + self.assertEqual(b"bc", bufio.read1()) + self.assertEqual(b"d", bufio.read1()) + self.assertEqual(b"efg", bufio.read1(-1)) + self.assertEqual(rawio._reads, 3) + self.assertEqual(b"", bufio.read1()) + self.assertEqual(rawio._reads, 4) def test_readinto(self): rawio = self.MockRawIO((b"abc", b"d", b"efg")) @@ -1809,6 +1819,7 @@ class BufferedRWPairTest(unittest.TestCase): pair = self.tp(self.BytesIO(b"abcdef"), self.MockRawIO()) self.assertEqual(pair.read1(3), b"abc") + self.assertEqual(pair.read1(), b"def") def test_readinto(self): for method in ("readinto", "readinto1"): @@ -3470,6 +3481,7 @@ class MiscIOTest(unittest.TestCase): self.assertRaises(ValueError, f.read) if hasattr(f, "read1"): self.assertRaises(ValueError, f.read1, 1024) + self.assertRaises(ValueError, f.read1) if hasattr(f, "readall"): self.assertRaises(ValueError, f.readall) if hasattr(f, "readinto"): diff --git a/Lib/test/test_macurl2path.py b/Lib/test/test_macurl2path.py deleted file mode 100644 index 3490d6d..0000000 --- a/Lib/test/test_macurl2path.py +++ /dev/null @@ -1,31 +0,0 @@ -import macurl2path -import unittest - -class MacUrl2PathTestCase(unittest.TestCase): - def test_url2pathname(self): - self.assertEqual(":index.html", macurl2path.url2pathname("index.html")) - self.assertEqual(":bar:index.html", macurl2path.url2pathname("bar/index.html")) - self.assertEqual("foo:bar:index.html", macurl2path.url2pathname("/foo/bar/index.html")) - self.assertEqual("foo:bar", macurl2path.url2pathname("/foo/bar/")) - self.assertEqual("", macurl2path.url2pathname("/")) - self.assertRaises(RuntimeError, macurl2path.url2pathname, "http://foo.com") - self.assertEqual("index.html", macurl2path.url2pathname("///index.html")) - self.assertRaises(RuntimeError, macurl2path.url2pathname, "//index.html") - self.assertEqual(":index.html", macurl2path.url2pathname("./index.html")) - self.assertEqual(":index.html", macurl2path.url2pathname("foo/../index.html")) - self.assertEqual("::index.html", macurl2path.url2pathname("../index.html")) - - def test_pathname2url(self): - self.assertEqual("drive", macurl2path.pathname2url("drive:")) - self.assertEqual("drive/dir", macurl2path.pathname2url("drive:dir:")) - self.assertEqual("drive/dir/file", macurl2path.pathname2url("drive:dir:file")) - self.assertEqual("drive/file", macurl2path.pathname2url("drive:file")) - self.assertEqual("file", macurl2path.pathname2url("file")) - self.assertEqual("file", macurl2path.pathname2url(":file")) - self.assertEqual("dir", macurl2path.pathname2url(":dir:")) - self.assertEqual("dir/file", macurl2path.pathname2url(":dir:file")) - self.assertRaises(RuntimeError, macurl2path.pathname2url, "/") - self.assertEqual("dir/../file", macurl2path.pathname2url("dir::file")) - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/test/test_memoryio.py b/Lib/test/test_memoryio.py index 55b693e..80055ce 100644 --- a/Lib/test/test_memoryio.py +++ b/Lib/test/test_memoryio.py @@ -437,10 +437,8 @@ class PyBytesIOTest(MemoryTestMixin, MemorySeekTestMixin, unittest.TestCase): def test_read1(self): buf = self.buftype("1234567890") - memio = self.ioclass(buf) - - self.assertRaises(TypeError, memio.read1) - self.assertEqual(memio.read(), buf) + self.assertEqual(self.ioclass(buf).read1(), buf) + self.assertEqual(self.ioclass(buf).read1(-1), buf) def test_readinto(self): buf = self.buftype("1234567890") diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py index fd0d2e3..d2fa9d2 100644 --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -5,7 +5,7 @@ import time import pickle import warnings from functools import partial -from math import log, exp, pi, fsum, sin +from math import log, exp, pi, fsum, sin, factorial from test import support from fractions import Fraction @@ -117,10 +117,6 @@ class TestBasicOps: n = 5 pop = range(n) trials = 10000 # large num prevents false negatives without slowing normal case - def factorial(n): - if n == 0: - return 1 - return n * factorial(n - 1) for k in range(n): expected = factorial(n) // factorial(n-k) perms = {} diff --git a/Lib/test/test_range.py b/Lib/test/test_range.py index 9e11e51..3675f25 100644 --- a/Lib/test/test_range.py +++ b/Lib/test/test_range.py @@ -4,7 +4,6 @@ import unittest import sys import pickle import itertools -import test.support # pure Python implementations (3 args only), for comparison def pyrange(start, stop, step): @@ -494,37 +493,13 @@ class RangeTest(unittest.TestCase): test_id = "reversed(range({}, {}, {}))".format(start, end, step) self.assert_iterators_equal(iter1, iter2, test_id, limit=100) - @test.support.cpython_only - def test_range_iterator_invocation(self): - import _testcapi + def test_range_iterators_invocation(self): + # verify range iterators instances cannot be created by + # calling their type rangeiter_type = type(iter(range(0))) - - self.assertWarns(DeprecationWarning, rangeiter_type, 1, 3, 1) - - with test.support.check_warnings(('', DeprecationWarning)): - # rangeiter_new doesn't take keyword arguments - with self.assertRaises(TypeError): - rangeiter_type(a=1) - - # rangeiter_new takes exactly 3 arguments - self.assertRaises(TypeError, rangeiter_type) - self.assertRaises(TypeError, rangeiter_type, 1) - self.assertRaises(TypeError, rangeiter_type, 1, 1) - self.assertRaises(TypeError, rangeiter_type, 1, 1, 1, 1) - - # start, stop and stop must fit in C long - for good_val in [_testcapi.LONG_MAX, _testcapi.LONG_MIN]: - rangeiter_type(good_val, good_val, good_val) - for bad_val in [_testcapi.LONG_MAX + 1, _testcapi.LONG_MIN - 1]: - self.assertRaises(OverflowError, - rangeiter_type, bad_val, 1, 1) - self.assertRaises(OverflowError, - rangeiter_type, 1, bad_val, 1) - self.assertRaises(OverflowError, - rangeiter_type, 1, 1, bad_val) - - # step mustn't be zero - self.assertRaises(ValueError, rangeiter_type, 1, 1, 0) + self.assertRaises(TypeError, rangeiter_type, 1, 3, 1) + long_rangeiter_type = type(iter(range(1 << 1000))) + self.assertRaises(TypeError, long_rangeiter_type, 1, 3, 1) def test_slice(self): def check(start, stop, step=None): diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 59564c9..a5657c7 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -888,18 +888,28 @@ class GeneralModuleTests(unittest.TestCase): self.assertRaises(OverflowError, func, 1<<34) def testNtoHErrors(self): - good_values = [ 1, 2, 3, 1, 2, 3 ] - bad_values = [ -1, -2, -3, -1, -2, -3 ] - for k in good_values: - socket.ntohl(k) + import _testcapi + s_good_values = [0, 1, 2, 0xffff] + l_good_values = s_good_values + [0xffffffff] + l_bad_values = [-1, -2, 1<<32, 1<<1000] + s_bad_values = l_bad_values + [_testcapi.INT_MIN - 1, + _testcapi.INT_MAX + 1] + s_deprecated_values = [1<<16, _testcapi.INT_MAX] + for k in s_good_values: socket.ntohs(k) - socket.htonl(k) socket.htons(k) - for k in bad_values: - self.assertRaises(OverflowError, socket.ntohl, k) + for k in l_good_values: + socket.ntohl(k) + socket.htonl(k) + for k in s_bad_values: self.assertRaises(OverflowError, socket.ntohs, k) - self.assertRaises(OverflowError, socket.htonl, k) self.assertRaises(OverflowError, socket.htons, k) + for k in l_bad_values: + self.assertRaises(OverflowError, socket.ntohl, k) + self.assertRaises(OverflowError, socket.htonl, k) + for k in s_deprecated_values: + self.assertWarns(DeprecationWarning, socket.ntohs, k) + self.assertWarns(DeprecationWarning, socket.htons, k) def testGetServBy(self): eq = self.assertEqual diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 89de6d1..4cfb29d 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -1015,19 +1015,6 @@ class ProcessTestCase(BaseTestCase): # time to start. self.assertEqual(p.wait(timeout=3), 0) - def test_wait_endtime(self): - """Confirm that the deprecated endtime parameter warns.""" - p = subprocess.Popen([sys.executable, "-c", "pass"]) - try: - with self.assertWarns(DeprecationWarning) as warn_cm: - p.wait(endtime=time.time()+0.01) - except subprocess.TimeoutExpired: - pass # We're not testing endtime timeout behavior. - finally: - p.kill() - self.assertIn('test_subprocess.py', warn_cm.filename) - self.assertIn('endtime', str(warn_cm.warning)) - def test_invalid_bufsize(self): # an invalid type of the bufsize argument should raise # TypeError. diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index 091e905..d2aa8b4 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -5,7 +5,7 @@ import subprocess import shutil from copy import copy -from test.support import (run_unittest, TESTFN, unlink, check_warnings, +from test.support import (import_module, TESTFN, unlink, check_warnings, captured_stdout, skip_unless_symlink, change_cwd) import sysconfig @@ -387,7 +387,8 @@ class TestSysConfig(unittest.TestCase): @unittest.skipUnless(sys.platform == 'linux', 'Linux-specific test') def test_triplet_in_ext_suffix(self): - import ctypes, platform, re + ctypes = import_module('ctypes') + import platform, re machine = platform.machine() suffix = sysconfig.get_config_var('EXT_SUFFIX') if re.match('(aarch64|arm|mips|ppc|powerpc|s390|sparc)', machine): @@ -435,8 +436,5 @@ class MakefileTests(unittest.TestCase): }) -def test_main(): - run_unittest(TestSysConfig, MakefileTests) - if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_timeit.py b/Lib/test/test_timeit.py index 1a95e29..8d4746a 100644 --- a/Lib/test/test_timeit.py +++ b/Lib/test/test_timeit.py @@ -12,7 +12,7 @@ from test.support import captured_stderr DEFAULT_NUMBER = 1000000 # timeit's default number of repetitions. -DEFAULT_REPEAT = 3 +DEFAULT_REPEAT = 5 # 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 @@ -226,7 +226,7 @@ class TestTimeit(unittest.TestCase): t.print_exc(s) self.assert_exc_string(s.getvalue(), 'ZeroDivisionError') - MAIN_DEFAULT_OUTPUT = "10 loops, best of 3: 1 sec per loop\n" + MAIN_DEFAULT_OUTPUT = "1 loop, best of 5: 1 sec per loop\n" def run_main(self, seconds_per_increment=1.0, switches=None, timer=None): if timer is None: @@ -252,39 +252,39 @@ class TestTimeit(unittest.TestCase): 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") + self.assertEqual(s, "1 loop, best of 5: 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") + self.assertEqual(s, "50 loops, best of 5: 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") + self.assertEqual(s, "100 loops, best of 5: 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") + self.assertEqual(s, "35 loops, best of 5: 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") + self.assertEqual(s, "CustomSetup\n" * DEFAULT_REPEAT + + "35 loops, best of 5: 2 sec per loop\n") def test_main_multiple_setups(self): s = self.run_main(seconds_per_increment=2.0, switches=['-n35', '-s', 'a = "CustomSetup"', '-s', 'print(a)']) - self.assertEqual(s, "CustomSetup\n" * 3 + - "35 loops, best of 3: 2 sec per loop\n") + self.assertEqual(s, "CustomSetup\n" * DEFAULT_REPEAT + + "35 loops, best of 5: 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") + self.assertEqual(s, "1 loop, 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") + self.assertEqual(s, "1 loop, best of 1: 60 sec per loop\n") @unittest.skipIf(sys.flags.optimize >= 2, "need __doc__") def test_main_help(self): @@ -293,56 +293,57 @@ class TestTimeit(unittest.TestCase): # 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 + 1 loop -> 1 secs + + raw times: 1 sec, 1 sec, 1 sec, 1 sec, 1 sec + + 1 loop, best of 5: 1 sec per loop """)) def test_main_very_verbose(self): - s = self.run_main(seconds_per_increment=0.000050, switches=['-vv']) + s = self.run_main(seconds_per_increment=0.000_030, 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 + 1 loop -> 3e-05 secs + 2 loops -> 6e-05 secs + 5 loops -> 0.00015 secs + 10 loops -> 0.0003 secs + 20 loops -> 0.0006 secs + 50 loops -> 0.0015 secs + 100 loops -> 0.003 secs + 200 loops -> 0.006 secs + 500 loops -> 0.015 secs + 1000 loops -> 0.03 secs + 2000 loops -> 0.06 secs + 5000 loops -> 0.15 secs + 10000 loops -> 0.3 secs + + raw times: 300 msec, 300 msec, 300 msec, 300 msec, 300 msec + + 10000 loops, best of 5: 30 usec per loop """)) def test_main_with_time_unit(self): - unit_sec = self.run_main(seconds_per_increment=0.002, + unit_sec = self.run_main(seconds_per_increment=0.003, switches=['-u', 'sec']) self.assertEqual(unit_sec, - "1000 loops, best of 3: 0.002 sec per loop\n") - unit_msec = self.run_main(seconds_per_increment=0.002, + "100 loops, best of 5: 0.003 sec per loop\n") + unit_msec = self.run_main(seconds_per_increment=0.003, switches=['-u', 'msec']) self.assertEqual(unit_msec, - "1000 loops, best of 3: 2 msec per loop\n") - unit_usec = self.run_main(seconds_per_increment=0.002, + "100 loops, best of 5: 3 msec per loop\n") + unit_usec = self.run_main(seconds_per_increment=0.003, switches=['-u', 'usec']) self.assertEqual(unit_usec, - "1000 loops, best of 3: 2e+03 usec per loop\n") + "100 loops, best of 5: 3e+03 usec per loop\n") # Test invalid unit input with captured_stderr() as error_stringio: - invalid = self.run_main(seconds_per_increment=0.002, + invalid = self.run_main(seconds_per_increment=0.003, switches=['-u', 'parsec']) self.assertEqual(error_stringio.getvalue(), - "Unrecognized unit. Please select usec, msec, or sec.\n") + "Unrecognized unit. Please select nsec, usec, msec, or sec.\n") def test_main_exception(self): with captured_stderr() as error_stringio: @@ -354,26 +355,37 @@ class TestTimeit(unittest.TestCase): s = self.run_main(switches=['-n1', '1/0']) self.assert_exc_string(error_stringio.getvalue(), 'ZeroDivisionError') - def autorange(self, callback=None): - timer = FakeTimer(seconds_per_increment=0.001) + def autorange(self, seconds_per_increment=1/1024, callback=None): + timer = FakeTimer(seconds_per_increment=seconds_per_increment) t = timeit.Timer(stmt=self.fake_stmt, setup=self.fake_setup, timer=timer) return t.autorange(callback) def test_autorange(self): num_loops, time_taken = self.autorange() - self.assertEqual(num_loops, 1000) + self.assertEqual(num_loops, 500) + self.assertEqual(time_taken, 500/1024) + + def test_autorange_second(self): + num_loops, time_taken = self.autorange(seconds_per_increment=1.0) + self.assertEqual(num_loops, 1) self.assertEqual(time_taken, 1.0) def test_autorange_with_callback(self): def callback(a, b): print("{} {:.3f}".format(a, b)) with captured_stdout() as s: - num_loops, time_taken = self.autorange(callback) - self.assertEqual(num_loops, 1000) - self.assertEqual(time_taken, 1.0) - expected = ('10 0.010\n' - '100 0.100\n' - '1000 1.000\n') + num_loops, time_taken = self.autorange(callback=callback) + self.assertEqual(num_loops, 500) + self.assertEqual(time_taken, 500/1024) + expected = ('1 0.001\n' + '2 0.002\n' + '5 0.005\n' + '10 0.010\n' + '20 0.020\n' + '50 0.049\n' + '100 0.098\n' + '200 0.195\n' + '500 0.488\n') self.assertEqual(s.getvalue(), expected) diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py index 0a43b20..0a19d76 100644 --- a/Lib/test/test_zipfile.py +++ b/Lib/test/test_zipfile.py @@ -2055,8 +2055,9 @@ class CommandLineTest(unittest.TestCase): def test_test_command(self): zip_name = findfile('zipdir.zip') - out = self.zipfilecmd('-t', zip_name) - self.assertEqual(out.rstrip(), b'Done testing') + for opt in '-t', '--test': + out = self.zipfilecmd(opt, zip_name) + self.assertEqual(out.rstrip(), b'Done testing') zip_name = findfile('testtar.tar') rc, out, err = self.zipfilecmd_failure('-t', zip_name) self.assertEqual(out, b'') @@ -2067,9 +2068,10 @@ class CommandLineTest(unittest.TestCase): with zipfile.ZipFile(zip_name, 'r') as tf: tf.printdir(t) expected = t.getvalue().encode('ascii', 'backslashreplace') - out = self.zipfilecmd('-l', zip_name, - PYTHONIOENCODING='ascii:backslashreplace') - self.assertEqual(out, expected) + for opt in '-l', '--list': + out = self.zipfilecmd(opt, zip_name, + PYTHONIOENCODING='ascii:backslashreplace') + self.assertEqual(out, expected) @requires_zlib def test_create_command(self): @@ -2082,31 +2084,33 @@ class CommandLineTest(unittest.TestCase): f.write('test 2') files = [TESTFN, TESTFNDIR] namelist = [TESTFN, TESTFNDIR + '/', TESTFNDIR + '/file.txt'] - try: - out = self.zipfilecmd('-c', TESTFN2, *files) - self.assertEqual(out, b'') - with zipfile.ZipFile(TESTFN2) as zf: - self.assertEqual(zf.namelist(), namelist) - self.assertEqual(zf.read(namelist[0]), b'test 1') - self.assertEqual(zf.read(namelist[2]), b'test 2') - finally: - unlink(TESTFN2) + for opt in '-c', '--create': + try: + out = self.zipfilecmd(opt, TESTFN2, *files) + self.assertEqual(out, b'') + with zipfile.ZipFile(TESTFN2) as zf: + self.assertEqual(zf.namelist(), namelist) + self.assertEqual(zf.read(namelist[0]), b'test 1') + self.assertEqual(zf.read(namelist[2]), b'test 2') + finally: + unlink(TESTFN2) def test_extract_command(self): zip_name = findfile('zipdir.zip') - with temp_dir() as extdir: - out = self.zipfilecmd('-e', zip_name, extdir) - self.assertEqual(out, b'') - with zipfile.ZipFile(zip_name) as zf: - for zi in zf.infolist(): - path = os.path.join(extdir, - zi.filename.replace('/', os.sep)) - if zi.is_dir(): - self.assertTrue(os.path.isdir(path)) - else: - self.assertTrue(os.path.isfile(path)) - with open(path, 'rb') as f: - self.assertEqual(f.read(), zf.read(zi)) + for opt in '-e', '--extract': + with temp_dir() as extdir: + out = self.zipfilecmd(opt, zip_name, extdir) + self.assertEqual(out, b'') + with zipfile.ZipFile(zip_name) as zf: + for zi in zf.infolist(): + path = os.path.join(extdir, + zi.filename.replace('/', os.sep)) + if zi.is_dir(): + self.assertTrue(os.path.isdir(path)) + else: + self.assertTrue(os.path.isfile(path)) + with open(path, 'rb') as f: + self.assertEqual(f.read(), zf.read(zi)) if __name__ == "__main__": unittest.main() diff --git a/Lib/timeit.py b/Lib/timeit.py index 2770efa..38c2b1f 100644 --- a/Lib/timeit.py +++ b/Lib/timeit.py @@ -9,7 +9,7 @@ the Python Cookbook, published by O'Reilly. Library usage: see the Timer class. Command line usage: - python timeit.py [-n N] [-r N] [-s S] [-t] [-c] [-p] [-h] [--] [statement] + python timeit.py [-n N] [-r N] [-s S] [-p] [-h] [--] [statement] Options: -n/--number N: how many times to execute 'statement' (default: see below) @@ -17,10 +17,8 @@ Options: -s/--setup S: statement to be executed once initially (default 'pass'). Execution time of this setup statement is NOT timed. -p/--process: use time.process_time() (default is time.perf_counter()) - -t/--time: use time.time() (deprecated) - -c/--clock: use time.clock() (deprecated) -v/--verbose: print raw timing results; repeat for more digits precision - -u/--unit: set the output time unit (usec, msec, or sec) + -u/--unit: set the output time unit (nsec, usec, msec, or sec) -h/--help: print this usage message and exit --: separate options from statement, use when statement starts with - statement: statement to be timed (default 'pass') @@ -59,7 +57,7 @@ __all__ = ["Timer", "timeit", "repeat", "default_timer"] dummy_src_name = "<timeit-src>" default_number = 1000000 -default_repeat = 3 +default_repeat = 5 default_timer = time.perf_counter _globals = globals @@ -210,22 +208,23 @@ class Timer: def autorange(self, callback=None): """Return the number of loops so that total time >= 0.2. - Calls the timeit method with *number* set to successive powers of - ten (10, 100, 1000, ...) up to a maximum of one billion, until - the time taken is at least 0.2 second, or the maximum is reached. - Returns ``(number, time_taken)``. + Calls the timeit method with increasing numbers from the sequence + 1, 2, 5, 10, 20, 50, ... until the time taken is at least 0.2 + second. Returns (number, time_taken). If *callback* is given and is not None, it will be called after each trial with two arguments: ``callback(number, time_taken)``. """ - for i in range(1, 10): - number = 10**i - time_taken = self.timeit(number) - if callback: - callback(number, time_taken) - if time_taken >= 0.2: - break - return (number, time_taken) + i = 1 + while True: + for j in 1, 2, 5: + number = i * j + time_taken = self.timeit(number) + if callback: + callback(number, time_taken) + if time_taken >= 0.2: + return (number, time_taken) + i *= 10 def timeit(stmt="pass", setup="pass", timer=default_timer, number=default_number, globals=None): @@ -266,6 +265,7 @@ def main(args=None, *, _wrap_timer=None): print(err) print("use -h/--help for command line help") return 2 + timer = default_timer stmt = "\n".join(args) or "pass" number = 0 # auto-determine @@ -273,7 +273,7 @@ def main(args=None, *, _wrap_timer=None): repeat = default_repeat verbose = 0 time_unit = None - units = {"usec": 1, "msec": 1e3, "sec": 1e6} + units = {"nsec": 1e-9, "usec": 1e-6, "msec": 1e-3, "sec": 1.0} precision = 3 for o, a in opts: if o in ("-n", "--number"): @@ -284,17 +284,13 @@ def main(args=None, *, _wrap_timer=None): if a in units: time_unit = a else: - print("Unrecognized unit. Please select usec, msec, or sec.", + print("Unrecognized unit. Please select nsec, usec, msec, or sec.", file=sys.stderr) return 2 if o in ("-r", "--repeat"): repeat = int(a) if repeat <= 0: repeat = 1 - if o in ("-t", "--time"): - timer = time.time - if o in ("-c", "--clock"): - timer = time.clock if o in ("-p", "--process"): timer = time.process_time if o in ("-v", "--verbose"): @@ -305,6 +301,7 @@ def main(args=None, *, _wrap_timer=None): print(__doc__, end=' ') return 0 setup = "\n".join(setup) or "pass" + # Include the current directory, so that local imports work (sys.path # contains the directory of this script, rather than the current # directory) @@ -312,50 +309,65 @@ def main(args=None, *, _wrap_timer=None): 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 callback = None if verbose: def callback(number, time_taken): - msg = "{num} loops -> {secs:.{prec}g} secs" - print(msg.format(num=number, secs=time_taken, prec=precision)) + msg = "{num} loop{s} -> {secs:.{prec}g} secs" + plural = (number != 1) + print(msg.format(num=number, s='s' if plural else '', + secs=time_taken, prec=precision)) try: number, _ = t.autorange(callback) except: t.print_exc() return 1 + + if verbose: + print() + try: - r = t.repeat(repeat, number) + raw_timings = t.repeat(repeat, number) except: t.print_exc() return 1 - best = min(r) + + def format_time(dt): + unit = time_unit + + if unit is not None: + scale = units[unit] + else: + scales = [(scale, unit) for unit, scale in units.items()] + scales.sort(reverse=True) + for scale, unit in scales: + if dt >= scale: + break + + return "%.*g %s" % (precision, dt / scale, unit) + if verbose: - print("raw times:", " ".join(["%.*g" % (precision, x) for x in r])) - print("%d loops," % number, end=' ') - usec = best * 1e6 / number - if time_unit is not None: - scale = units[time_unit] - else: - scales = [(scale, unit) for unit, scale in units.items()] - scales.sort(reverse=True) - for scale, time_unit in scales: - if usec >= scale: - break - print("best of %d: %.*g %s per loop" % (repeat, precision, - usec/scale, time_unit)) - best = min(r) - usec = best * 1e6 / number - worst = max(r) + print("raw times: %s" % ", ".join(map(format_time, raw_timings))) + print() + timings = [dt / number for dt in raw_timings] + + best = min(timings) + print("%d loop%s, best of %d: %s per loop" + % (number, 's' if number != 1 else '', + repeat, format_time(best))) + + best = min(timings) + worst = max(timings) if worst >= best * 4: - usec = worst * 1e6 / number import warnings - warnings.warn_explicit( - "The test results are likely unreliable. The worst\n" - "time (%.*g %s) was more than four times slower than the best time." % - (precision, usec/scale, time_unit), - UserWarning, '', 0) + warnings.warn_explicit("The test results are likely unreliable. " + "The worst time (%s) was more than four times " + "slower than the best time (%s)." + % (format_time(worst), format_time(best)), + UserWarning, '', 0) return None if __name__ == "__main__": diff --git a/Lib/zipfile.py b/Lib/zipfile.py index e2ae042..d3661a3 100644 --- a/Lib/zipfile.py +++ b/Lib/zipfile.py @@ -1950,51 +1950,45 @@ class PyZipFile(ZipFile): return (fname, archivename) -def main(args = None): - import textwrap - USAGE=textwrap.dedent("""\ - Usage: - zipfile.py -l zipfile.zip # Show listing of a zipfile - zipfile.py -t zipfile.zip # Test if a zipfile is valid - zipfile.py -e zipfile.zip target # Extract zipfile into target dir - zipfile.py -c zipfile.zip src ... # Create zipfile from sources - """) - if args is None: - args = sys.argv[1:] - - if not args or args[0] not in ('-l', '-c', '-e', '-t'): - print(USAGE) - sys.exit(1) - - if args[0] == '-l': - if len(args) != 2: - print(USAGE) - sys.exit(1) - with ZipFile(args[1], 'r') as zf: - zf.printdir() - - elif args[0] == '-t': - if len(args) != 2: - print(USAGE) - sys.exit(1) - with ZipFile(args[1], 'r') as zf: +def main(args=None): + import argparse + + description = 'A simple command line interface for zipfile module.' + parser = argparse.ArgumentParser(description=description) + group = parser.add_mutually_exclusive_group() + group.add_argument('-l', '--list', metavar='<zipfile>', + help='Show listing of a zipfile') + group.add_argument('-e', '--extract', nargs=2, + metavar=('<zipfile>', '<output_dir>'), + help='Extract zipfile into target dir') + group.add_argument('-c', '--create', nargs='+', + metavar=('<name>', '<file>'), + help='Create zipfile from sources') + group.add_argument('-t', '--test', metavar='<zipfile>', + help='Test if a zipfile is valid') + args = parser.parse_args(args) + + if args.test is not None: + src = args.test + with ZipFile(src, 'r') as zf: badfile = zf.testzip() if badfile: print("The following enclosed file is corrupted: {!r}".format(badfile)) print("Done testing") - elif args[0] == '-e': - if len(args) != 3: - print(USAGE) - sys.exit(1) + elif args.list is not None: + src = args.list + with ZipFile(src, 'r') as zf: + zf.printdir() - with ZipFile(args[1], 'r') as zf: - zf.extractall(args[2]) + elif args.extract is not None: + src, curdir = args.extract + with ZipFile(src, 'r') as zf: + zf.extractall(curdir) - elif args[0] == '-c': - if len(args) < 3: - print(USAGE) - sys.exit(1) + elif args.create is not None: + zip_name = args.create.pop(0) + files = args.create def addToZip(zf, path, zippath): if os.path.isfile(path): @@ -2007,8 +2001,8 @@ def main(args = None): os.path.join(path, nm), os.path.join(zippath, nm)) # else: ignore - with ZipFile(args[1], 'w') as zf: - for path in args[2:]: + with ZipFile(zip_name, 'w') as zf: + for path in files: zippath = os.path.basename(path) if not zippath: zippath = os.path.basename(os.path.dirname(path)) @@ -2016,5 +2010,8 @@ def main(args = None): zippath = '' addToZip(zf, path, zippath) + else: + parser.exit(2, parser.format_usage()) + if __name__ == "__main__": main() |