diff options
Diffstat (limited to 'Lib')
31 files changed, 1448 insertions, 1458 deletions
diff --git a/Lib/SocketServer.py b/Lib/SocketServer.py index 47d8728..2a9ec8a 100644 --- a/Lib/SocketServer.py +++ b/Lib/SocketServer.py @@ -130,8 +130,13 @@ __version__ = "0.4" import socket +import select import sys import os +try: + import threading +except ImportError: + import dummy_threading as threading __all__ = ["TCPServer","UDPServer","ForkingUDPServer","ForkingTCPServer", "ThreadingUDPServer","ThreadingTCPServer","BaseRequestHandler", @@ -149,7 +154,8 @@ class BaseServer: Methods for the caller: - __init__(server_address, RequestHandlerClass) - - serve_forever() + - serve_forever(poll_interval=0.5) + - shutdown() - handle_request() # if you do not use serve_forever() - fileno() -> int # for select() @@ -190,6 +196,8 @@ class BaseServer: """Constructor. May be extended, do not override.""" self.server_address = server_address self.RequestHandlerClass = RequestHandlerClass + self.__is_shut_down = threading.Event() + self.__serving = False def server_activate(self): """Called by constructor to activate the server. @@ -199,27 +207,73 @@ class BaseServer: """ pass - def serve_forever(self): - """Handle one request at a time until doomsday.""" - while 1: - self.handle_request() + def serve_forever(self, poll_interval=0.5): + """Handle one request at a time until shutdown. + + Polls for shutdown every poll_interval seconds. Ignores + self.timeout. If you need to do periodic tasks, do them in + another thread. + """ + self.__serving = True + self.__is_shut_down.clear() + while self.__serving: + # XXX: Consider using another file descriptor or + # connecting to the socket to wake this up instead of + # polling. Polling reduces our responsiveness to a + # shutdown request and wastes cpu at all other times. + r, w, e = select.select([self], [], [], poll_interval) + if r: + self._handle_request_noblock() + self.__is_shut_down.set() + + def shutdown(self): + """Stops the serve_forever loop. + + Blocks until the loop has finished. This must be called while + serve_forever() is running in another thread, or it will + deadlock. + """ + self.__serving = False + self.__is_shut_down.wait() # The distinction between handling, getting, processing and # finishing a request is fairly arbitrary. Remember: # # - handle_request() is the top-level call. It calls - # await_request(), verify_request() and process_request() - # - get_request(), called by await_request(), is different for - # stream or datagram sockets + # select, get_request(), verify_request() and process_request() + # - get_request() is different for stream or datagram sockets # - process_request() is the place that may fork a new process # or create a new thread to finish the request # - finish_request() instantiates the request handler class; # this constructor will handle the request all by itself def handle_request(self): - """Handle one request, possibly blocking.""" + """Handle one request, possibly blocking. + + Respects self.timeout. + """ + # Support people who used socket.settimeout() to escape + # handle_request before self.timeout was available. + timeout = self.socket.gettimeout() + if timeout is None: + timeout = self.timeout + elif self.timeout is not None: + timeout = min(timeout, self.timeout) + fd_sets = select.select([self], [], [], timeout) + if not fd_sets[0]: + self.handle_timeout() + return + self._handle_request_noblock() + + def _handle_request_noblock(self): + """Handle one request, without blocking. + + I assume that select.select has returned that the socket is + readable before this function was called, so there should be + no risk of blocking in get_request(). + """ try: - request, client_address = self.await_request() + request, client_address = self.get_request() except socket.error: return if self.verify_request(request, client_address): @@ -229,21 +283,6 @@ class BaseServer: self.handle_error(request, client_address) self.close_request(request) - def await_request(self): - """Call get_request or handle_timeout, observing self.timeout. - - Returns value from get_request() or raises socket.timeout exception if - timeout was exceeded. - """ - if self.timeout is not None: - # If timeout == 0, you're responsible for your own fd magic. - import select - fd_sets = select.select([self], [], [], self.timeout) - if not fd_sets[0]: - self.handle_timeout() - raise socket.timeout("Listening timed out") - return self.get_request() - def handle_timeout(self): """Called if no new request arrives within self.timeout. @@ -307,7 +346,8 @@ class TCPServer(BaseServer): Methods for the caller: - __init__(server_address, RequestHandlerClass, bind_and_activate=True) - - serve_forever() + - serve_forever(poll_interval=0.5) + - shutdown() - handle_request() # if you don't use serve_forever() - fileno() -> int # for select() @@ -523,7 +563,6 @@ class ThreadingMixIn: def process_request(self, request, client_address): """Start a new thread to process the request.""" - import threading t = threading.Thread(target = self.process_request_thread, args = (request, client_address)) if self.daemon_threads: diff --git a/Lib/_strptime.py b/Lib/_strptime.py index 28ccac7..b323e8f 100644 --- a/Lib/_strptime.py +++ b/Lib/_strptime.py @@ -22,7 +22,7 @@ try: except: from dummy_thread import allocate_lock as _thread_allocate_lock -__all__ = ['strptime'] +__all__ = [] def _getlang(): # Figure out what the current language is set to. @@ -190,6 +190,7 @@ class TimeRE(dict): base.__init__({ # The " \d" part of the regex is to make %c from ANSI C work 'd': r"(?P<d>3[0-1]|[1-2]\d|0[1-9]|[1-9]| [1-9])", + 'f': r"(?P<f>[0-9]{1,6})", 'H': r"(?P<H>2[0-3]|[0-1]\d|\d)", 'I': r"(?P<I>1[0-2]|0[1-9]|[1-9])", 'j': r"(?P<j>36[0-6]|3[0-5]\d|[1-2]\d\d|0[1-9]\d|00[1-9]|[1-9]\d|0[1-9]|[1-9])", @@ -291,7 +292,7 @@ def _calc_julian_from_U_or_W(year, week_of_year, day_of_week, week_starts_Mon): return 1 + days_to_week + day_of_week -def strptime(data_string, format="%a %b %d %H:%M:%S %Y"): +def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"): """Return a time struct based on the input string and the format string.""" global _TimeRE_cache, _regex_cache with _cache_lock: @@ -327,7 +328,7 @@ def strptime(data_string, format="%a %b %d %H:%M:%S %Y"): data_string[found.end():]) year = 1900 month = day = 1 - hour = minute = second = 0 + hour = minute = second = fraction = 0 tz = -1 # Default to -1 to signify that values not known; not critical to have, # though @@ -384,6 +385,11 @@ def strptime(data_string, format="%a %b %d %H:%M:%S %Y"): minute = int(found_dict['M']) elif group_key == 'S': second = int(found_dict['S']) + elif group_key == 'f': + s = found_dict['f'] + # Pad to always return microseconds. + s += "0" * (6 - len(s)) + fraction = int(s) elif group_key == 'A': weekday = locale_time.f_weekday.index(found_dict['A'].lower()) elif group_key == 'a': @@ -440,6 +446,9 @@ def strptime(data_string, format="%a %b %d %H:%M:%S %Y"): day = datetime_result.day if weekday == -1: weekday = datetime_date(year, month, day).weekday() - return time.struct_time((year, month, day, - hour, minute, second, - weekday, julian, tz)) + return (time.struct_time((year, month, day, + hour, minute, second, + weekday, julian, tz)), fraction) + +def _strptime_time(data_string, format="%a %b %d %H:%M:%S %Y"): + return _strptime(data_string, format)[0] diff --git a/Lib/bsddb/test/test_dbshelve.py b/Lib/bsddb/test/test_dbshelve.py index 99d0c49..a597154 100644 --- a/Lib/bsddb/test/test_dbshelve.py +++ b/Lib/bsddb/test/test_dbshelve.py @@ -50,10 +50,7 @@ class DBShelveTestCase(unittest.TestCase): def tearDown(self): self.do_close() - try: - os.remove(self.filename) - except os.error: - pass + test_support.unlink(self.filename) def mk(self, key): """Turn key into an appropriate key type for this db""" @@ -284,8 +281,8 @@ class BasicEnvShelveTestCase(DBShelveTestCase): def tearDown(self): - test_support.rmtree(self.homeDir) self.do_close() + test_support.rmtree(self.homeDir) class EnvBTreeShelveTestCase(BasicEnvShelveTestCase): diff --git a/Lib/bsddb/test/test_thread.py b/Lib/bsddb/test/test_thread.py index 359c10d..51ed0f5 100644 --- a/Lib/bsddb/test/test_thread.py +++ b/Lib/bsddb/test/test_thread.py @@ -68,9 +68,9 @@ class BaseThreadedTestCase(unittest.TestCase): self.d.open(self.filename, self.dbtype, self.dbopenflags|db.DB_CREATE) def tearDown(self): - test_support.rmtree(self.homeDir) self.d.close() self.env.close() + test_support.rmtree(self.homeDir) def setEnvOpts(self): pass diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py index 8dd8e0a..b6e598f 100644 --- a/Lib/ctypes/__init__.py +++ b/Lib/ctypes/__init__.py @@ -237,7 +237,7 @@ c_voidp = c_void_p # backwards compatibility (to a bug) _check_size(c_void_p) class c_bool(_SimpleCData): - _type_ = "t" + _type_ = "?" # This cache maps types to pointers to them. _pointer_type_cache = {} diff --git a/Lib/distutils/command/sdist.py b/Lib/distutils/command/sdist.py index 8289925..b29fc64 100644 --- a/Lib/distutils/command/sdist.py +++ b/Lib/distutils/command/sdist.py @@ -325,14 +325,14 @@ class sdist (Command): * the build tree (typically "build") * the release tree itself (only an issue if we ran "sdist" previously with --keep-temp, or it aborted) - * any RCS, CVS and .svn directories + * any RCS, CVS, .svn, .hg, .git, .bzr, _darcs directories """ build = self.get_finalized_command('build') base_dir = self.distribution.get_fullname() self.filelist.exclude_pattern(None, prefix=build.build_base) self.filelist.exclude_pattern(None, prefix=base_dir) - self.filelist.exclude_pattern(r'/(RCS|CVS|\.svn)/.*', is_regex=1) + self.filelist.exclude_pattern(r'(^|/)(RCS|CVS|\.svn|\.hg|\.git|\.bzr|_darcs)/.*', is_regex=1) def write_manifest(self): """Write the file list in 'self.filelist' (presumably as filled in diff --git a/Lib/heapq.py b/Lib/heapq.py index 47d246e..71a12e7 100644 --- a/Lib/heapq.py +++ b/Lib/heapq.py @@ -127,7 +127,7 @@ From all times, sorting has always been a Great Art! :-) """ __all__ = ['heappush', 'heappop', 'heapify', 'heapreplace', 'merge', - 'nlargest', 'nsmallest'] + 'nlargest', 'nsmallest', 'heappushpop'] from itertools import islice, repeat, count, tee from operator import itemgetter, neg @@ -165,6 +165,13 @@ def heapreplace(heap, item): _siftup(heap, 0) return returnitem +def heappushpop(heap, item): + """Fast version of a heappush followed by a heappop.""" + if heap and item > heap[0]: + item, heap[0] = heap[0], item + _siftup(heap, 0) + return item + def heapify(x): """Transform list into a heap, in-place, in O(len(heap)) time.""" n = len(x) @@ -186,13 +193,9 @@ def nlargest(n, iterable): if not result: return result heapify(result) - _heapreplace = heapreplace - sol = result[0] # sol --> smallest of the nlargest + _heappushpop = heappushpop for elem in it: - if elem <= sol: - continue - _heapreplace(result, elem) - sol = result[0] + heappushpop(result, elem) result.sort(reverse=True) return result @@ -304,7 +307,7 @@ def _siftup(heap, pos): # If available, use C implementation try: - from _heapq import heappush, heappop, heapify, heapreplace, nlargest, nsmallest + from _heapq import heappush, heappop, heapify, heapreplace, nlargest, nsmallest, heappushpop except ImportError: pass @@ -1193,7 +1193,16 @@ def set_trace(): # Post-Mortem interface -def post_mortem(t): +def post_mortem(t=None): + # handling the default + if t is None: + # sys.exc_info() returns (type, value, traceback) if an exception is + # being handled, otherwise it returns None + t = sys.exc_info()[2] + if t is None: + raise ValueError("A valid traceback must be passed if no " + "exception is being handled") + p = Pdb() p.reset() while t.tb_next is not None: diff --git a/Lib/platform.py b/Lib/platform.py index 1fc1032..c2f34b5 100755 --- a/Lib/platform.py +++ b/Lib/platform.py @@ -238,9 +238,10 @@ _release_version = re.compile(r'([^0-9]+)' # and http://data.linux-ntfs.org/rpm/whichrpm # and http://www.die.net/doc/linux/man/man1/lsb_release.1.html -_supported_dists = ('SuSE', 'debian', 'fedora', 'redhat', 'centos', - 'mandrake', 'rocks', 'slackware', 'yellowdog', - 'gentoo', 'UnitedLinux', 'turbolinux') +_supported_dists = ( + 'SuSE', 'debian', 'fedora', 'redhat', 'centos', + 'mandrake', 'mandriva', 'rocks', 'slackware', 'yellowdog', 'gentoo', + 'UnitedLinux', 'turbolinux') def _parse_release_file(firstline): diff --git a/Lib/py_compile.py b/Lib/py_compile.py index 982d19d..8ef3662 100644 --- a/Lib/py_compile.py +++ b/Lib/py_compile.py @@ -171,11 +171,15 @@ def main(args=None): """ if args is None: args = sys.argv[1:] + rv = 0 for filename in args: try: compile(filename, doraise=True) except PyCompileError as err: + # return value to indicate at least one failure + rv = 1 sys.stderr.write(err.msg) + return rv if __name__ == "__main__": - main() + sys.exit(main()) diff --git a/Lib/rlcompleter.py b/Lib/rlcompleter.py index 74b2e47..c605c7d 100644 --- a/Lib/rlcompleter.py +++ b/Lib/rlcompleter.py @@ -119,7 +119,7 @@ class Completer: import re m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text) if not m: - return + return [] expr, attr = m.group(1, 3) object = eval(expr, self.namespace) words = dir(object) diff --git a/Lib/sqlite3/test/transactions.py b/Lib/sqlite3/test/transactions.py index 1f0b19a..9edc4ac 100644 --- a/Lib/sqlite3/test/transactions.py +++ b/Lib/sqlite3/test/transactions.py @@ -31,7 +31,7 @@ class TransactionTests(unittest.TestCase): def setUp(self): try: os.remove(get_db_path()) - except: + except OSError: pass self.con1 = sqlite.connect(get_db_path(), timeout=0.1) @@ -47,7 +47,10 @@ class TransactionTests(unittest.TestCase): self.cur2.close() self.con2.close() - os.unlink(get_db_path()) + try: + os.unlink(get_db_path()) + except OSError: + pass def CheckDMLdoesAutoCommitBefore(self): self.cur1.execute("create table test(i)") diff --git a/Lib/test/output/test_thread b/Lib/test/output/test_thread deleted file mode 100644 index 68c6a92..0000000 --- a/Lib/test/output/test_thread +++ /dev/null @@ -1,18 +0,0 @@ -test_thread -waiting for all tasks to complete -all tasks done - -*** Barrier Test *** -all tasks done - -*** Changing thread stack size *** -caught expected ValueError setting stack_size(4096) -successfully set stack_size(262144) -successfully set stack_size(1048576) -successfully set stack_size(0) -trying stack_size = 262144 -waiting for all tasks to complete -all tasks done -trying stack_size = 1048576 -waiting for all tasks to complete -all tasks done diff --git a/Lib/test/output/test_tokenize b/Lib/test/output/test_tokenize deleted file mode 100644 index 6708097..0000000 --- a/Lib/test/output/test_tokenize +++ /dev/null @@ -1,715 +0,0 @@ -test_tokenize -1,0-1,34: COMMENT "# Tests for the 'tokenize' module." -1,34-1,35: NL '\n' -2,0-2,42: COMMENT '# Large bits stolen from test_grammar.py. ' -2,42-2,43: NL '\n' -3,0-3,1: NL '\n' -4,0-4,10: COMMENT '# Comments' -4,10-4,11: NL '\n' -5,0-5,3: STRING '"#"' -5,3-5,4: NEWLINE '\n' -6,0-6,2: COMMENT "#'" -6,2-6,3: NL '\n' -7,0-7,2: COMMENT '#"' -7,2-7,3: NL '\n' -8,0-8,2: COMMENT '#\\' -8,2-8,3: NL '\n' -9,7-9,8: COMMENT '#' -9,8-9,9: NL '\n' -10,4-10,9: COMMENT '# abc' -10,9-10,10: NL '\n' -11,0-12,4: STRING "'''#\n#'''" -12,4-12,5: NEWLINE '\n' -13,0-13,1: NL '\n' -14,0-14,1: NAME 'x' -14,2-14,3: OP '=' -14,4-14,5: NUMBER '1' -14,7-14,8: COMMENT '#' -14,8-14,9: NEWLINE '\n' -15,0-15,1: NL '\n' -16,0-16,24: COMMENT '# Balancing continuation' -16,24-16,25: NL '\n' -17,0-17,1: NL '\n' -18,0-18,1: NAME 'a' -18,2-18,3: OP '=' -18,4-18,5: OP '(' -18,5-18,6: NUMBER '3' -18,6-18,7: OP ',' -18,8-18,9: NUMBER '4' -18,9-18,10: OP ',' -18,10-18,11: NL '\n' -19,2-19,3: NUMBER '5' -19,3-19,4: OP ',' -19,5-19,6: NUMBER '6' -19,6-19,7: OP ')' -19,7-19,8: NEWLINE '\n' -20,0-20,1: NAME 'y' -20,2-20,3: OP '=' -20,4-20,5: OP '[' -20,5-20,6: NUMBER '3' -20,6-20,7: OP ',' -20,8-20,9: NUMBER '4' -20,9-20,10: OP ',' -20,10-20,11: NL '\n' -21,2-21,3: NUMBER '5' -21,3-21,4: OP ']' -21,4-21,5: NEWLINE '\n' -22,0-22,1: NAME 'z' -22,2-22,3: OP '=' -22,4-22,5: OP '{' -22,5-22,8: STRING "'a'" -22,8-22,9: OP ':' -22,9-22,10: NUMBER '5' -22,10-22,11: OP ',' -22,11-22,12: NL '\n' -23,2-23,5: STRING "'b'" -23,5-23,6: OP ':' -23,6-23,7: NUMBER '6' -23,7-23,8: OP '}' -23,8-23,9: NEWLINE '\n' -24,0-24,1: NAME 'x' -24,2-24,3: OP '=' -24,4-24,5: OP '(' -24,5-24,8: NAME 'len' -24,8-24,9: OP '(' -24,9-24,13: NAME 'repr' -24,13-24,14: OP '(' -24,14-24,15: NAME 'y' -24,15-24,16: OP ')' -24,16-24,17: OP ')' -24,18-24,19: OP '+' -24,20-24,21: NUMBER '5' -24,21-24,22: OP '*' -24,22-24,23: NAME 'x' -24,24-24,25: OP '-' -24,26-24,27: NAME 'a' -24,27-24,28: OP '[' -24,28-24,29: NL '\n' -25,3-25,4: NUMBER '3' -25,5-25,6: OP ']' -25,6-25,7: NL '\n' -26,3-26,4: OP '-' -26,5-26,6: NAME 'x' -26,7-26,8: OP '+' -26,9-26,12: NAME 'len' -26,12-26,13: OP '(' -26,13-26,14: OP '{' -26,14-26,15: NL '\n' -27,3-27,4: OP '}' -27,4-27,5: NL '\n' -28,4-28,5: OP ')' -28,5-28,6: NL '\n' -29,2-29,3: OP ')' -29,3-29,4: NEWLINE '\n' -30,0-30,1: NL '\n' -31,0-31,36: COMMENT '# Backslash means line continuation:' -31,36-31,37: NL '\n' -32,0-32,1: NAME 'x' -32,2-32,3: OP '=' -32,4-32,5: NUMBER '1' -33,0-33,1: OP '+' -33,2-33,3: NUMBER '1' -33,3-33,4: NEWLINE '\n' -34,0-34,1: NL '\n' -35,0-35,54: COMMENT '# Backslash does not means continuation in comments :\\' -35,54-35,55: NL '\n' -36,0-36,1: NAME 'x' -36,2-36,3: OP '=' -36,4-36,5: NUMBER '0' -36,5-36,6: NEWLINE '\n' -37,0-37,1: NL '\n' -38,0-38,19: COMMENT '# Ordinary integers' -38,19-38,20: NL '\n' -39,0-39,4: NUMBER '0xff' -39,5-39,7: OP '!=' -39,8-39,11: NUMBER '255' -39,11-39,12: NEWLINE '\n' -40,0-40,5: NUMBER '0o377' -40,6-40,8: OP '!=' -40,9-40,12: NUMBER '255' -40,12-40,13: NEWLINE '\n' -41,0-41,10: NUMBER '2147483647' -41,13-41,15: OP '!=' -41,16-41,29: NUMBER '0o17777777777' -41,29-41,30: NEWLINE '\n' -42,0-42,1: OP '-' -42,1-42,11: NUMBER '2147483647' -42,11-42,12: OP '-' -42,12-42,13: NUMBER '1' -42,14-42,16: OP '!=' -42,17-42,30: NUMBER '0o20000000000' -42,30-42,31: NEWLINE '\n' -43,0-43,13: NUMBER '0o37777777777' -43,14-43,16: OP '!=' -43,17-43,18: OP '-' -43,18-43,19: NUMBER '1' -43,19-43,20: NEWLINE '\n' -44,0-44,10: NUMBER '0xffffffff' -44,11-44,13: OP '!=' -44,14-44,15: OP '-' -44,15-44,16: NUMBER '1' -44,16-44,17: OP ';' -44,18-44,31: NUMBER '0o37777777777' -44,32-44,34: OP '!=' -44,35-44,36: OP '-' -44,36-44,37: NUMBER '1' -44,37-44,38: OP ';' -44,39-44,40: OP '-' -44,40-44,49: NUMBER '0o1234567' -44,50-44,52: OP '==' -44,53-44,64: NUMBER '0O001234567' -44,64-44,65: OP ';' -44,66-44,73: NUMBER '0b10101' -44,74-44,76: OP '==' -44,77-44,87: NUMBER '0B00010101' -44,87-44,88: NEWLINE '\n' -45,0-45,1: NL '\n' -46,0-46,15: COMMENT '# Long integers' -46,15-46,16: NL '\n' -47,0-47,1: NAME 'x' -47,2-47,3: OP '=' -47,4-47,5: NUMBER '0' -47,5-47,6: NEWLINE '\n' -48,0-48,1: NAME 'x' -48,2-48,3: OP '=' -48,4-48,5: NUMBER '0' -48,5-48,6: NEWLINE '\n' -49,0-49,1: NAME 'x' -49,2-49,3: OP '=' -49,4-49,22: NUMBER '0xffffffffffffffff' -49,22-49,23: NEWLINE '\n' -50,0-50,1: NAME 'x' -50,2-50,3: OP '=' -50,4-50,22: NUMBER '0xffffffffffffffff' -50,22-50,23: NEWLINE '\n' -51,0-51,1: NAME 'x' -51,2-51,3: OP '=' -51,4-51,23: NUMBER '0o77777777777777777' -51,23-51,24: NEWLINE '\n' -52,0-52,1: NAME 'x' -52,2-52,3: OP '=' -52,4-52,23: NUMBER '0B11101010111111111' -52,23-52,24: NEWLINE '\n' -53,0-53,1: NAME 'x' -53,2-53,3: OP '=' -53,4-53,34: NUMBER '123456789012345678901234567890' -53,34-53,35: NEWLINE '\n' -54,0-54,1: NAME 'x' -54,2-54,3: OP '=' -54,4-54,34: NUMBER '123456789012345678901234567890' -54,34-54,35: NEWLINE '\n' -55,0-55,1: NL '\n' -56,0-56,24: COMMENT '# Floating-point numbers' -56,24-56,25: NL '\n' -57,0-57,1: NAME 'x' -57,2-57,3: OP '=' -57,4-57,8: NUMBER '3.14' -57,8-57,9: NEWLINE '\n' -58,0-58,1: NAME 'x' -58,2-58,3: OP '=' -58,4-58,8: NUMBER '314.' -58,8-58,9: NEWLINE '\n' -59,0-59,1: NAME 'x' -59,2-59,3: OP '=' -59,4-59,9: NUMBER '0.314' -59,9-59,10: NEWLINE '\n' -60,0-60,17: COMMENT '# XXX x = 000.314' -60,17-60,18: NL '\n' -61,0-61,1: NAME 'x' -61,2-61,3: OP '=' -61,4-61,8: NUMBER '.314' -61,8-61,9: NEWLINE '\n' -62,0-62,1: NAME 'x' -62,2-62,3: OP '=' -62,4-62,8: NUMBER '3e14' -62,8-62,9: NEWLINE '\n' -63,0-63,1: NAME 'x' -63,2-63,3: OP '=' -63,4-63,8: NUMBER '3E14' -63,8-63,9: NEWLINE '\n' -64,0-64,1: NAME 'x' -64,2-64,3: OP '=' -64,4-64,9: NUMBER '3e-14' -64,9-64,10: NEWLINE '\n' -65,0-65,1: NAME 'x' -65,2-65,3: OP '=' -65,4-65,9: NUMBER '3e+14' -65,9-65,10: NEWLINE '\n' -66,0-66,1: NAME 'x' -66,2-66,3: OP '=' -66,4-66,9: NUMBER '3.e14' -66,9-66,10: NEWLINE '\n' -67,0-67,1: NAME 'x' -67,2-67,3: OP '=' -67,4-67,9: NUMBER '.3e14' -67,9-67,10: NEWLINE '\n' -68,0-68,1: NAME 'x' -68,2-68,3: OP '=' -68,4-68,9: NUMBER '3.1e4' -68,9-68,10: NEWLINE '\n' -69,0-69,1: NL '\n' -70,0-70,17: COMMENT '# String literals' -70,17-70,18: NL '\n' -71,0-71,1: NAME 'x' -71,2-71,3: OP '=' -71,4-71,6: STRING "''" -71,6-71,7: OP ';' -71,8-71,9: NAME 'y' -71,10-71,11: OP '=' -71,12-71,14: STRING '""' -71,14-71,15: OP ';' -71,15-71,16: NEWLINE '\n' -72,0-72,1: NAME 'x' -72,2-72,3: OP '=' -72,4-72,8: STRING "'\\''" -72,8-72,9: OP ';' -72,10-72,11: NAME 'y' -72,12-72,13: OP '=' -72,14-72,17: STRING '"\'"' -72,17-72,18: OP ';' -72,18-72,19: NEWLINE '\n' -73,0-73,1: NAME 'x' -73,2-73,3: OP '=' -73,4-73,7: STRING '\'"\'' -73,7-73,8: OP ';' -73,9-73,10: NAME 'y' -73,11-73,12: OP '=' -73,13-73,17: STRING '"\\""' -73,17-73,18: OP ';' -73,18-73,19: NEWLINE '\n' -74,0-74,1: NAME 'x' -74,2-74,3: OP '=' -74,4-74,32: STRING '"doesn\'t \\"shrink\\" does it"' -74,32-74,33: NEWLINE '\n' -75,0-75,1: NAME 'y' -75,2-75,3: OP '=' -75,4-75,31: STRING '\'doesn\\\'t "shrink" does it\'' -75,31-75,32: NEWLINE '\n' -76,0-76,1: NAME 'x' -76,2-76,3: OP '=' -76,4-76,32: STRING '"does \\"shrink\\" doesn\'t it"' -76,32-76,33: NEWLINE '\n' -77,0-77,1: NAME 'y' -77,2-77,3: OP '=' -77,4-77,31: STRING '\'does "shrink" doesn\\\'t it\'' -77,31-77,32: NEWLINE '\n' -78,0-78,1: NAME 'x' -78,2-78,3: OP '=' -78,4-83,3: STRING '"""\nThe "quick"\nbrown fox\njumps over\nthe \'lazy\' dog.\n"""' -83,3-83,4: NEWLINE '\n' -84,0-84,1: NAME 'y' -84,2-84,3: OP '=' -84,4-84,63: STRING '\'\\nThe "quick"\\nbrown fox\\njumps over\\nthe \\\'lazy\\\' dog.\\n\'' -84,63-84,64: NEWLINE '\n' -85,0-85,1: NAME 'y' -85,2-85,3: OP '=' -85,4-90,3: STRING '\'\'\'\nThe "quick"\nbrown fox\njumps over\nthe \'lazy\' dog.\n\'\'\'' -90,3-90,4: OP ';' -90,4-90,5: NEWLINE '\n' -91,0-91,1: NAME 'y' -91,2-91,3: OP '=' -91,4-96,1: STRING '"\\n\\\nThe \\"quick\\"\\n\\\nbrown fox\\n\\\njumps over\\n\\\nthe \'lazy\' dog.\\n\\\n"' -96,1-96,2: OP ';' -96,2-96,3: NEWLINE '\n' -97,0-97,1: NAME 'y' -97,2-97,3: OP '=' -97,4-102,1: STRING '\'\\n\\\nThe \\"quick\\"\\n\\\nbrown fox\\n\\\njumps over\\n\\\nthe \\\'lazy\\\' dog.\\n\\\n\'' -102,1-102,2: OP ';' -102,2-102,3: NEWLINE '\n' -103,0-103,1: NAME 'x' -103,2-103,3: OP '=' -103,4-103,9: STRING "r'\\\\'" -103,10-103,11: OP '+' -103,12-103,17: STRING "R'\\\\'" -103,17-103,18: NEWLINE '\n' -104,0-104,1: NAME 'x' -104,2-104,3: OP '=' -104,4-104,9: STRING "r'\\''" -104,10-104,11: OP '+' -104,12-104,14: STRING "''" -104,14-104,15: NEWLINE '\n' -105,0-105,1: NAME 'y' -105,2-105,3: OP '=' -105,4-107,6: STRING "r'''\nfoo bar \\\\\nbaz'''" -107,7-107,8: OP '+' -107,9-108,6: STRING "R'''\nfoo'''" -108,6-108,7: NEWLINE '\n' -109,0-109,1: NAME 'y' -109,2-109,3: OP '=' -109,4-111,3: STRING 'r"""foo\nbar \\\\ baz\n"""' -111,4-111,5: OP '+' -111,6-112,3: STRING "R'''spam\n'''" -112,3-112,4: NEWLINE '\n' -113,0-113,1: NAME 'x' -113,2-113,3: OP '=' -113,4-113,10: STRING "b'abc'" -113,11-113,12: OP '+' -113,13-113,19: STRING "B'ABC'" -113,19-113,20: NEWLINE '\n' -114,0-114,1: NAME 'y' -114,2-114,3: OP '=' -114,4-114,10: STRING 'b"abc"' -114,11-114,12: OP '+' -114,13-114,19: STRING 'B"ABC"' -114,19-114,20: NEWLINE '\n' -115,0-115,1: NAME 'x' -115,2-115,3: OP '=' -115,4-115,11: STRING "br'abc'" -115,12-115,13: OP '+' -115,14-115,21: STRING "Br'ABC'" -115,22-115,23: OP '+' -115,24-115,31: STRING "bR'ABC'" -115,32-115,33: OP '+' -115,34-115,41: STRING "BR'ABC'" -115,41-115,42: NEWLINE '\n' -116,0-116,1: NAME 'y' -116,2-116,3: OP '=' -116,4-116,11: STRING 'br"abc"' -116,12-116,13: OP '+' -116,14-116,21: STRING 'Br"ABC"' -116,22-116,23: OP '+' -116,24-116,31: STRING 'bR"ABC"' -116,32-116,33: OP '+' -116,34-116,41: STRING 'BR"ABC"' -116,41-116,42: NEWLINE '\n' -117,0-117,1: NAME 'x' -117,2-117,3: OP '=' -117,4-117,10: STRING "br'\\\\'" -117,11-117,12: OP '+' -117,13-117,19: STRING "BR'\\\\'" -117,19-117,20: NEWLINE '\n' -118,0-118,1: NAME 'x' -118,2-118,3: OP '=' -118,4-118,10: STRING "br'\\''" -118,11-118,12: OP '+' -118,13-118,15: STRING "''" -118,15-118,16: NEWLINE '\n' -119,0-119,1: NAME 'y' -119,2-119,3: OP '=' -119,4-121,6: STRING "br'''\nfoo bar \\\\\nbaz'''" -121,7-121,8: OP '+' -121,9-122,6: STRING "BR'''\nfoo'''" -122,6-122,7: NEWLINE '\n' -123,0-123,1: NAME 'y' -123,2-123,3: OP '=' -123,4-125,3: STRING 'Br"""foo\nbar \\\\ baz\n"""' -125,4-125,5: OP '+' -125,6-126,3: STRING "bR'''spam\n'''" -126,3-126,4: NEWLINE '\n' -127,0-127,1: NL '\n' -128,0-128,13: COMMENT '# Indentation' -128,13-128,14: NL '\n' -129,0-129,2: NAME 'if' -129,3-129,4: NUMBER '1' -129,4-129,5: OP ':' -129,5-129,6: NEWLINE '\n' -130,0-130,4: INDENT ' ' -130,4-130,5: NAME 'x' -130,6-130,7: OP '=' -130,8-130,9: NUMBER '2' -130,9-130,10: NEWLINE '\n' -131,0-131,0: DEDENT '' -131,0-131,2: NAME 'if' -131,3-131,4: NUMBER '1' -131,4-131,5: OP ':' -131,5-131,6: NEWLINE '\n' -132,0-132,8: INDENT ' ' -132,8-132,9: NAME 'x' -132,10-132,11: OP '=' -132,12-132,13: NUMBER '2' -132,13-132,14: NEWLINE '\n' -133,0-133,0: DEDENT '' -133,0-133,2: NAME 'if' -133,3-133,4: NUMBER '1' -133,4-133,5: OP ':' -133,5-133,6: NEWLINE '\n' -134,0-134,4: INDENT ' ' -134,4-134,9: NAME 'while' -134,10-134,11: NUMBER '0' -134,11-134,12: OP ':' -134,12-134,13: NEWLINE '\n' -135,0-135,5: INDENT ' ' -135,5-135,7: NAME 'if' -135,8-135,9: NUMBER '0' -135,9-135,10: OP ':' -135,10-135,11: NEWLINE '\n' -136,0-136,11: INDENT ' ' -136,11-136,12: NAME 'x' -136,13-136,14: OP '=' -136,15-136,16: NUMBER '2' -136,16-136,17: NEWLINE '\n' -137,5-137,5: DEDENT '' -137,5-137,6: NAME 'x' -137,7-137,8: OP '=' -137,9-137,10: NUMBER '2' -137,10-137,11: NEWLINE '\n' -138,0-138,0: DEDENT '' -138,0-138,0: DEDENT '' -138,0-138,2: NAME 'if' -138,3-138,4: NUMBER '0' -138,4-138,5: OP ':' -138,5-138,6: NEWLINE '\n' -139,0-139,2: INDENT ' ' -139,2-139,4: NAME 'if' -139,5-139,6: NUMBER '2' -139,6-139,7: OP ':' -139,7-139,8: NEWLINE '\n' -140,0-140,3: INDENT ' ' -140,3-140,8: NAME 'while' -140,9-140,10: NUMBER '0' -140,10-140,11: OP ':' -140,11-140,12: NEWLINE '\n' -141,0-141,8: INDENT ' ' -141,8-141,10: NAME 'if' -141,11-141,12: NUMBER '1' -141,12-141,13: OP ':' -141,13-141,14: NEWLINE '\n' -142,0-142,10: INDENT ' ' -142,10-142,11: NAME 'x' -142,12-142,13: OP '=' -142,14-142,15: NUMBER '2' -142,15-142,16: NEWLINE '\n' -143,0-143,1: NL '\n' -144,0-144,11: COMMENT '# Operators' -144,11-144,12: NL '\n' -145,0-145,1: NL '\n' -146,0-146,0: DEDENT '' -146,0-146,0: DEDENT '' -146,0-146,0: DEDENT '' -146,0-146,0: DEDENT '' -146,0-146,3: NAME 'def' -146,4-146,7: NAME 'd22' -146,7-146,8: OP '(' -146,8-146,9: NAME 'a' -146,9-146,10: OP ',' -146,11-146,12: NAME 'b' -146,12-146,13: OP ',' -146,14-146,15: NAME 'c' -146,15-146,16: OP '=' -146,16-146,17: NUMBER '1' -146,17-146,18: OP ',' -146,19-146,20: NAME 'd' -146,20-146,21: OP '=' -146,21-146,22: NUMBER '2' -146,22-146,23: OP ')' -146,23-146,24: OP ':' -146,25-146,29: NAME 'pass' -146,29-146,30: NEWLINE '\n' -147,0-147,3: NAME 'def' -147,4-147,8: NAME 'd01v' -147,8-147,9: OP '(' -147,9-147,10: NAME 'a' -147,10-147,11: OP '=' -147,11-147,12: NUMBER '1' -147,12-147,13: OP ',' -147,14-147,15: OP '*' -147,15-147,20: NAME 'restt' -147,20-147,21: OP ',' -147,22-147,24: OP '**' -147,24-147,29: NAME 'restd' -147,29-147,30: OP ')' -147,30-147,31: OP ':' -147,32-147,36: NAME 'pass' -147,36-147,37: NEWLINE '\n' -148,0-148,1: NL '\n' -149,0-149,1: OP '(' -149,1-149,2: NAME 'x' -149,2-149,3: OP ',' -149,4-149,5: NAME 'y' -149,5-149,6: OP ')' -149,7-149,9: OP '!=' -149,10-149,11: OP '(' -149,11-149,12: OP '{' -149,12-149,15: STRING "'a'" -149,15-149,16: OP ':' -149,16-149,17: NUMBER '1' -149,17-149,18: OP '}' -149,18-149,19: OP ',' -149,20-149,21: OP '{' -149,21-149,24: STRING "'b'" -149,24-149,25: OP ':' -149,25-149,26: NUMBER '2' -149,26-149,27: OP '}' -149,27-149,28: OP ')' -149,28-149,29: NEWLINE '\n' -150,0-150,1: NL '\n' -151,0-151,12: COMMENT '# comparison' -151,12-151,13: NL '\n' -152,0-152,2: NAME 'if' -152,3-152,4: NUMBER '1' -152,5-152,6: OP '<' -152,7-152,8: NUMBER '1' -152,9-152,10: OP '>' -152,11-152,12: NUMBER '1' -152,13-152,15: OP '==' -152,16-152,17: NUMBER '1' -152,18-152,20: OP '>=' -152,21-152,22: NUMBER '1' -152,23-152,25: OP '<=' -152,26-152,27: NUMBER '1' -152,28-152,30: OP '!=' -152,31-152,32: NUMBER '1' -152,33-152,35: OP '!=' -152,36-152,37: NUMBER '1' -152,38-152,40: NAME 'in' -152,41-152,42: NUMBER '1' -152,43-152,46: NAME 'not' -152,47-152,49: NAME 'in' -152,50-152,51: NUMBER '1' -152,52-152,54: NAME 'is' -152,55-152,56: NUMBER '1' -152,57-152,59: NAME 'is' -152,60-152,63: NAME 'not' -152,64-152,65: NUMBER '1' -152,65-152,66: OP ':' -152,67-152,71: NAME 'pass' -152,71-152,72: NEWLINE '\n' -153,0-153,1: NL '\n' -154,0-154,8: COMMENT '# binary' -154,8-154,9: NL '\n' -155,0-155,1: NAME 'x' -155,2-155,3: OP '=' -155,4-155,5: NUMBER '1' -155,6-155,7: OP '&' -155,8-155,9: NUMBER '1' -155,9-155,10: NEWLINE '\n' -156,0-156,1: NAME 'x' -156,2-156,3: OP '=' -156,4-156,5: NUMBER '1' -156,6-156,7: OP '^' -156,8-156,9: NUMBER '1' -156,9-156,10: NEWLINE '\n' -157,0-157,1: NAME 'x' -157,2-157,3: OP '=' -157,4-157,5: NUMBER '1' -157,6-157,7: OP '|' -157,8-157,9: NUMBER '1' -157,9-157,10: NEWLINE '\n' -158,0-158,1: NL '\n' -159,0-159,7: COMMENT '# shift' -159,7-159,8: NL '\n' -160,0-160,1: NAME 'x' -160,2-160,3: OP '=' -160,4-160,5: NUMBER '1' -160,6-160,8: OP '<<' -160,9-160,10: NUMBER '1' -160,11-160,13: OP '>>' -160,14-160,15: NUMBER '1' -160,15-160,16: NEWLINE '\n' -161,0-161,1: NL '\n' -162,0-162,10: COMMENT '# additive' -162,10-162,11: NL '\n' -163,0-163,1: NAME 'x' -163,2-163,3: OP '=' -163,4-163,5: NUMBER '1' -163,6-163,7: OP '-' -163,8-163,9: NUMBER '1' -163,10-163,11: OP '+' -163,12-163,13: NUMBER '1' -163,14-163,15: OP '-' -163,16-163,17: NUMBER '1' -163,18-163,19: OP '+' -163,20-163,21: NUMBER '1' -163,21-163,22: NEWLINE '\n' -164,0-164,1: NL '\n' -165,0-165,16: COMMENT '# multiplicative' -165,16-165,17: NL '\n' -166,0-166,1: NAME 'x' -166,2-166,3: OP '=' -166,4-166,5: NUMBER '1' -166,6-166,7: OP '/' -166,8-166,9: NUMBER '1' -166,10-166,11: OP '*' -166,12-166,13: NUMBER '1' -166,14-166,15: OP '%' -166,16-166,17: NUMBER '1' -166,17-166,18: NEWLINE '\n' -167,0-167,1: NL '\n' -168,0-168,7: COMMENT '# unary' -168,7-168,8: NL '\n' -169,0-169,1: NAME 'x' -169,2-169,3: OP '=' -169,4-169,5: OP '~' -169,5-169,6: NUMBER '1' -169,7-169,8: OP '^' -169,9-169,10: NUMBER '1' -169,11-169,12: OP '&' -169,13-169,14: NUMBER '1' -169,15-169,16: OP '|' -169,17-169,18: NUMBER '1' -169,19-169,20: OP '&' -169,21-169,22: NUMBER '1' -169,23-169,24: OP '^' -169,25-169,26: OP '-' -169,26-169,27: NUMBER '1' -169,27-169,28: NEWLINE '\n' -170,0-170,1: NAME 'x' -170,2-170,3: OP '=' -170,4-170,5: OP '-' -170,5-170,6: NUMBER '1' -170,6-170,7: OP '*' -170,7-170,8: NUMBER '1' -170,8-170,9: OP '/' -170,9-170,10: NUMBER '1' -170,11-170,12: OP '+' -170,13-170,14: NUMBER '1' -170,14-170,15: OP '*' -170,15-170,16: NUMBER '1' -170,17-170,18: OP '-' -170,19-170,20: OP '-' -170,20-170,21: OP '-' -170,21-170,22: OP '-' -170,22-170,23: NUMBER '1' -170,23-170,24: OP '*' -170,24-170,25: NUMBER '1' -170,25-170,26: NEWLINE '\n' -171,0-171,1: NL '\n' -172,0-172,10: COMMENT '# selector' -172,10-172,11: NL '\n' -173,0-173,6: NAME 'import' -173,7-173,10: NAME 'sys' -173,10-173,11: OP ',' -173,12-173,16: NAME 'time' -173,16-173,17: NEWLINE '\n' -174,0-174,1: NAME 'x' -174,2-174,3: OP '=' -174,4-174,7: NAME 'sys' -174,7-174,8: OP '.' -174,8-174,15: NAME 'modules' -174,15-174,16: OP '[' -174,16-174,22: STRING "'time'" -174,22-174,23: OP ']' -174,23-174,24: OP '.' -174,24-174,28: NAME 'time' -174,28-174,29: OP '(' -174,29-174,30: OP ')' -174,30-174,31: NEWLINE '\n' -175,0-175,1: NL '\n' -176,0-176,1: OP '@' -176,1-176,13: NAME 'staticmethod' -176,13-176,14: NEWLINE '\n' -177,0-177,3: NAME 'def' -177,4-177,7: NAME 'foo' -177,7-177,8: OP '(' -177,8-177,9: OP ')' -177,9-177,10: OP ':' -177,11-177,15: NAME 'pass' -177,15-177,16: NEWLINE '\n' -178,0-178,1: NL '\n' -179,0-179,1: OP '@' -179,1-179,13: NAME 'staticmethod' -179,13-179,14: NEWLINE '\n' -180,0-180,3: NAME 'def' -180,4-180,7: NAME 'foo' -180,7-180,8: OP '(' -180,8-180,9: NAME 'x' -180,9-180,10: OP ':' -180,10-180,11: NUMBER '1' -180,11-180,12: OP ')' -180,12-180,14: OP '->' -180,14-180,15: NUMBER '1' -180,15-180,16: OP ':' -180,17-180,21: NAME 'pass' -180,21-180,22: NEWLINE '\n' -181,0-181,1: NL '\n' -182,0-182,0: ENDMARKER '' diff --git a/Lib/test/test_crypt.py b/Lib/test/test_crypt.py index a9c28cd..aa07f49 100755 --- a/Lib/test/test_crypt.py +++ b/Lib/test/test_crypt.py @@ -1,11 +1,16 @@ -#! /usr/bin/env python -"""Simple test script for cryptmodule.c - Roger E. Masse -""" - -from test.test_support import verbose +from test import test_support +import unittest import crypt -c = crypt.crypt('mypassword', 'ab') -if verbose: - print('Test encryption: ', c) +class CryptTestCase(unittest.TestCase): + + def test_crypt(self): + c = crypt.crypt('mypassword', 'ab') + if test_support.verbose: + print('Test encryption: ', c) + +def test_main(): + test_support.run_unittest(CryptTestCase) + +if __name__ == "__main__": + test_main() diff --git a/Lib/test/test_datetime.py b/Lib/test/test_datetime.py index e768a9c..e83048e 100644 --- a/Lib/test/test_datetime.py +++ b/Lib/test/test_datetime.py @@ -1521,11 +1521,12 @@ class TestDateTime(TestDate): self.failUnless(abs(from_timestamp - from_now) <= tolerance) def test_strptime(self): - import time + import _strptime - string = '2004-12-01 13:02:47' - format = '%Y-%m-%d %H:%M:%S' - expected = self.theclass(*(time.strptime(string, format)[0:6])) + string = '2004-12-01 13:02:47.197' + format = '%Y-%m-%d %H:%M:%S.%f' + result, frac = _strptime._strptime(string, format) + expected = self.theclass(*(result[0:6]+(frac,))) got = self.theclass.strptime(string, format) self.assertEqual(expected, got) @@ -1553,9 +1554,9 @@ class TestDateTime(TestDate): def test_more_strftime(self): # This tests fields beyond those tested by the TestDate.test_strftime. - t = self.theclass(2004, 12, 31, 6, 22, 33) - self.assertEqual(t.strftime("%m %d %y %S %M %H %j"), - "12 31 04 33 22 06 366") + t = self.theclass(2004, 12, 31, 6, 22, 33, 47) + self.assertEqual(t.strftime("%m %d %y %f %S %M %H %j"), + "12 31 04 000047 33 22 06 366") def test_extract(self): dt = self.theclass(2002, 3, 4, 18, 45, 3, 1234) @@ -1828,7 +1829,7 @@ class TestTime(HarmlessMixedComparison, unittest.TestCase): def test_strftime(self): t = self.theclass(1, 2, 3, 4) - self.assertEqual(t.strftime('%H %M %S'), "01 02 03") + self.assertEqual(t.strftime('%H %M %S %f'), "01 02 03 000004") # A naive object replaces %z and %Z with empty strings. self.assertEqual(t.strftime("'%z' '%Z'"), "'' ''") diff --git a/Lib/test/test_fcntl.py b/Lib/test/test_fcntl.py index 870876d..665f5b3 100755 --- a/Lib/test/test_fcntl.py +++ b/Lib/test/test_fcntl.py @@ -1,69 +1,88 @@ -#! /usr/bin/env python """Test program for the fcntl C module. - OS/2+EMX doesn't support the file locking operations. - Roger E. Masse + +OS/2+EMX doesn't support the file locking operations. + """ import struct import fcntl import os, sys -from test.test_support import verbose, TESTFN +import unittest +from test.test_support import verbose, TESTFN, unlink, run_unittest -filename = TESTFN +# TODO - Write tests for ioctl(), flock() and lockf(). -try: - os.O_LARGEFILE -except AttributeError: - start_len = "ll" -else: - start_len = "qq" -if sys.platform.startswith('atheos'): - start_len = "qq" +def get_lockdata(): + if sys.platform.startswith('atheos'): + start_len = "qq" + else: + try: + os.O_LARGEFILE + except AttributeError: + start_len = "ll" + else: + start_len = "qq" -if sys.platform in ('netbsd1', 'netbsd2', 'netbsd3', - 'Darwin1.2', 'darwin', - 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5', - 'freebsd6', 'freebsd7', 'freebsd8', - 'bsdos2', 'bsdos3', 'bsdos4', - 'openbsd', 'openbsd2', 'openbsd3', 'openbsd4'): - if struct.calcsize('l') == 8: - off_t = 'l' - pid_t = 'i' + if sys.platform in ('netbsd1', 'netbsd2', 'netbsd3', + 'Darwin1.2', 'darwin', + 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5', + 'freebsd6', 'freebsd7', 'freebsd8', + 'bsdos2', 'bsdos3', 'bsdos4', + 'openbsd', 'openbsd2', 'openbsd3', 'openbsd4'): + if struct.calcsize('l') == 8: + off_t = 'l' + pid_t = 'i' + else: + off_t = 'lxxxx' + pid_t = 'l' + lockdata = struct.pack(off_t + off_t + pid_t + 'hh', 0, 0, 0, + fcntl.F_WRLCK, 0) + elif sys.platform in ['aix3', 'aix4', 'hp-uxB', 'unixware7']: + lockdata = struct.pack('hhlllii', fcntl.F_WRLCK, 0, 0, 0, 0, 0, 0) + elif sys.platform in ['os2emx']: + lockdata = None else: - off_t = 'lxxxx' - pid_t = 'l' - lockdata = struct.pack(off_t+off_t+pid_t+'hh', 0, 0, 0, fcntl.F_WRLCK, 0) -elif sys.platform in ['aix3', 'aix4', 'hp-uxB', 'unixware7']: - lockdata = struct.pack('hhlllii', fcntl.F_WRLCK, 0, 0, 0, 0, 0, 0) -elif sys.platform in ['os2emx']: - lockdata = None -else: - lockdata = struct.pack('hh'+start_len+'hh', fcntl.F_WRLCK, 0, 0, 0, 0, 0) -if lockdata: - if verbose: - print('struct.pack: ', repr(lockdata)) + lockdata = struct.pack('hh'+start_len+'hh', fcntl.F_WRLCK, 0, 0, 0, 0, 0) + if lockdata: + if verbose: + print('struct.pack: ', repr(lockdata)) + return lockdata + +lockdata = get_lockdata() + +class TestFcntl(unittest.TestCase): -# the example from the library docs -f = open(filename, 'w') -rv = fcntl.fcntl(f.fileno(), fcntl.F_SETFL, os.O_NONBLOCK) -if verbose: - print('Status from fcntl with O_NONBLOCK: ', rv) + def setUp(self): + self.f = None -if sys.platform not in ['os2emx']: - rv = fcntl.fcntl(f.fileno(), fcntl.F_SETLKW, lockdata) - if verbose: - print('String from fcntl with F_SETLKW: ', repr(rv)) + def tearDown(self): + if not self.f.closed: + self.f.close() + unlink(TESTFN) -f.close() -os.unlink(filename) + def test_fcntl_fileno(self): + # the example from the library docs + self.f = open(TESTFN, 'w') + rv = fcntl.fcntl(self.f.fileno(), fcntl.F_SETFL, os.O_NONBLOCK) + if verbose: + print('Status from fcntl with O_NONBLOCK: ', rv) + if sys.platform not in ['os2emx']: + rv = fcntl.fcntl(self.f.fileno(), fcntl.F_SETLKW, lockdata) + if verbose: + print('String from fcntl with F_SETLKW: ', repr(rv)) + self.f.close() + def test_fcntl_file_descriptor(self): + # again, but pass the file rather than numeric descriptor + self.f = open(TESTFN, 'w') + rv = fcntl.fcntl(self.f, fcntl.F_SETFL, os.O_NONBLOCK) + if sys.platform not in ['os2emx']: + rv = fcntl.fcntl(self.f, fcntl.F_SETLKW, lockdata) + self.f.close() -# Again, but pass the file rather than numeric descriptor: -f = open(filename, 'w') -rv = fcntl.fcntl(f, fcntl.F_SETFL, os.O_NONBLOCK) -if sys.platform not in ['os2emx']: - rv = fcntl.fcntl(f, fcntl.F_SETLKW, lockdata) +def test_main(): + run_unittest(TestFcntl) -f.close() -os.unlink(filename) +if __name__ == '__main__': + test_main() diff --git a/Lib/test/test_gdbm.py b/Lib/test/test_gdbm.py index ee68277..17a7f63 100755 --- a/Lib/test/test_gdbm.py +++ b/Lib/test/test_gdbm.py @@ -1,46 +1,81 @@ -#! /usr/bin/env python -"""Test script for the gdbm module - Roger E. Masse -""" - import gdbm -from gdbm import error -from test.test_support import verbose, verify, TestFailed, TESTFN +import unittest +import os +from test.test_support import verbose, TESTFN, run_unittest, unlink + filename = TESTFN -g = gdbm.open(filename, 'c') -verify(g.keys() == []) -g[b'a'] = b'b' -g[b'12345678910'] = b'019237410982340912840198242' -a = g.keys() -if verbose: - print('Test gdbm file keys: ', a) - -b'a' in g -g.close() -try: - g['a'] -except error: - pass -else: - raise TestFailed("expected gdbm.error accessing closed database") -g = gdbm.open(filename, 'r') -g.close() -g = gdbm.open(filename, 'w') -g.close() -g = gdbm.open(filename, 'n') -g.close() -try: - g = gdbm.open(filename, 'rx') - g.close() -except error: - pass -else: - raise TestFailed("expected gdbm.error when passing invalid open flags") - -try: - import os - os.unlink(filename) -except: - pass +class TestGdbm(unittest.TestCase): + def setUp(self): + self.g = None + + def tearDown(self): + if self.g is not None: + self.g.close() + unlink(filename) + + def test_key_methods(self): + self.g = gdbm.open(filename, 'c') + self.assertEqual(self.g.keys(), []) + self.g['a'] = 'b' + self.g['12345678910'] = '019237410982340912840198242' + key_set = set(self.g.keys()) + self.assertEqual(key_set, set([b'a', b'12345678910'])) + self.assert_(b'a' in self.g) + key = self.g.firstkey() + while key: + self.assert_(key in key_set) + key_set.remove(key) + key = self.g.nextkey(key) + self.assertRaises(KeyError, lambda: self.g['xxx']) + + def test_error_conditions(self): + # Try to open a non-existent database. + unlink(filename) + self.assertRaises(gdbm.error, gdbm.open, filename, 'r') + # Try to access a closed database. + self.g = gdbm.open(filename, 'c') + self.g.close() + self.assertRaises(gdbm.error, lambda: self.g['a']) + # try pass an invalid open flag + self.assertRaises(gdbm.error, lambda: gdbm.open(filename, 'rx').close()) + + def test_flags(self): + # Test the flag parameter open() by trying all supported flag modes. + all = set(gdbm.open_flags) + # Test standard flags (presumably "crwn"). + modes = all - set('fsu') + for mode in modes: + self.g = gdbm.open(filename, mode) + self.g.close() + + # Test additional flags (presumably "fsu"). + flags = all - set('crwn') + for mode in modes: + for flag in flags: + self.g = gdbm.open(filename, mode + flag) + self.g.close() + + def test_reorganize(self): + self.g = gdbm.open(filename, 'c') + size0 = os.path.getsize(filename) + + self.g['x'] = 'x' * 10000 + size1 = os.path.getsize(filename) + self.assert_(size0 < size1) + + del self.g['x'] + # 'size' is supposed to be the same even after deleting an entry. + self.assertEqual(os.path.getsize(filename), size1) + + self.g.reorganize() + size2 = os.path.getsize(filename) + self.assert_(size1 > size2 >= size0) + + +def test_main(): + run_unittest(TestGdbm) + +if __name__ == '__main__': + test_main() diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py index 04aedd5..4c0eda5 100644 --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -310,6 +310,10 @@ class GrammarTests(unittest.TestCase): def f(*, k=1): return closure def f() -> int: return closure + # Check ast errors in *args and *kwargs + check_syntax_error(self, "f(*g(1=2))") + check_syntax_error(self, "f(**g(1=2))") + def testLambdef(self): ### lambdef: 'lambda' [varargslist] ':' test l1 = lambda : 0 diff --git a/Lib/test/test_heapq.py b/Lib/test/test_heapq.py index 1e21736..24d2992 100644 --- a/Lib/test/test_heapq.py +++ b/Lib/test/test_heapq.py @@ -107,6 +107,34 @@ class TestHeap(unittest.TestCase): self.assertRaises(TypeError, self.module.heapreplace, None, None) self.assertRaises(IndexError, self.module.heapreplace, [], None) + def test_nbest_with_pushpop(self): + data = [random.randrange(2000) for i in range(1000)] + heap = data[:10] + self.module.heapify(heap) + for item in data[10:]: + self.module.heappushpop(heap, item) + self.assertEqual(list(self.heapiter(heap)), sorted(data)[-10:]) + self.assertEqual(self.module.heappushpop([], 'x'), 'x') + + def test_heappushpop(self): + h = [] + x = self.module.heappushpop(h, 10) + self.assertEqual((h, x), ([], 10)) + + h = [10] + x = self.module.heappushpop(h, 10.0) + self.assertEqual((h, x), ([10], 10.0)) + self.assertEqual(type(h[0]), int) + self.assertEqual(type(x), float) + + h = [10]; + x = self.module.heappushpop(h, 9) + self.assertEqual((h, x), ([10], 9)) + + h = [10]; + x = self.module.heappushpop(h, 11) + self.assertEqual((h, x), ([11], 10)) + def test_heapsort(self): # Exercise everything with repeated heapsort checks for trial in range(100): diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py index d44235b..335e47d 100644 --- a/Lib/test/test_itertools.py +++ b/Lib/test/test_itertools.py @@ -51,22 +51,21 @@ def fact(n): 'Factorial' return prod(range(1, n+1)) -def permutations(iterable, r=None): - # XXX use this until real permutations code is added - pool = tuple(iterable) - n = len(pool) - r = n if r is None else r - for indices in product(range(n), repeat=r): - if len(set(indices)) == r: - yield tuple(pool[i] for i in indices) - class TestBasicOps(unittest.TestCase): def test_chain(self): - self.assertEqual(list(chain('abc', 'def')), list('abcdef')) - self.assertEqual(list(chain('abc')), list('abc')) - self.assertEqual(list(chain('')), []) - self.assertEqual(take(4, chain('abc', 'def')), list('abcd')) - self.assertRaises(TypeError, list,chain(2, 3)) + + def chain2(*iterables): + 'Pure python version in the docs' + for it in iterables: + for element in it: + yield element + + for c in (chain, chain2): + self.assertEqual(list(c('abc', 'def')), list('abcdef')) + self.assertEqual(list(c('abc')), list('abc')) + self.assertEqual(list(c('')), []) + self.assertEqual(take(4, c('abc', 'def')), list('abcd')) + self.assertRaises(TypeError, list,c(2, 3)) def test_chain_from_iterable(self): self.assertEqual(list(chain.from_iterable(['abc', 'def'])), list('abcdef')) @@ -121,6 +120,8 @@ class TestBasicOps(unittest.TestCase): self.assertEqual(len(set(c)), r) # no duplicate elements self.assertEqual(list(c), sorted(c)) # keep original ordering self.assert_(all(e in values for e in c)) # elements taken from input iterable + self.assertEqual(list(c), + [e for e in values if e in c]) # comb is a subsequence of the input iterable self.assertEqual(result, list(combinations1(values, r))) # matches first pure python version self.assertEqual(result, list(combinations2(values, r))) # matches first pure python version @@ -131,9 +132,10 @@ class TestBasicOps(unittest.TestCase): def test_permutations(self): self.assertRaises(TypeError, permutations) # too few arguments self.assertRaises(TypeError, permutations, 'abc', 2, 1) # too many arguments -## self.assertRaises(TypeError, permutations, None) # pool is not iterable -## self.assertRaises(ValueError, permutations, 'abc', -2) # r is negative -## self.assertRaises(ValueError, permutations, 'abc', 32) # r is too big + self.assertRaises(TypeError, permutations, None) # pool is not iterable + self.assertRaises(ValueError, permutations, 'abc', -2) # r is negative + self.assertRaises(ValueError, permutations, 'abc', 32) # r is too big + self.assertRaises(TypeError, permutations, 'abc', 's') # r is not an int or None self.assertEqual(list(permutations(range(3), 2)), [(0,1), (0,2), (1,0), (1,2), (2,0), (2,1)]) @@ -186,7 +188,7 @@ class TestBasicOps(unittest.TestCase): self.assertEqual(result, list(permutations(values))) # test default r # Test implementation detail: tuple re-use -## self.assertEqual(len(set(map(id, permutations('abcde', 3)))), 1) + self.assertEqual(len(set(map(id, permutations('abcde', 3)))), 1) self.assertNotEqual(len(set(map(id, list(permutations('abcde', 3))))), 1) def test_count(self): @@ -416,12 +418,46 @@ class TestBasicOps(unittest.TestCase): list(product(*args, **dict(repeat=r)))) self.assertEqual(len(list(product(*[range(7)]*6))), 7**6) self.assertRaises(TypeError, product, range(6), None) + + def product1(*args, **kwds): + pools = list(map(tuple, args)) * kwds.get('repeat', 1) + n = len(pools) + if n == 0: + yield () + return + if any(len(pool) == 0 for pool in pools): + return + indices = [0] * n + yield tuple(pool[i] for pool, i in zip(pools, indices)) + while 1: + for i in reversed(range(n)): # right to left + if indices[i] == len(pools[i]) - 1: + continue + indices[i] += 1 + for j in range(i+1, n): + indices[j] = 0 + yield tuple(pool[i] for pool, i in zip(pools, indices)) + break + else: + return + + def product2(*args, **kwds): + 'Pure python version used in docs' + pools = list(map(tuple, args)) * kwds.get('repeat', 1) + result = [[]] + for pool in pools: + result = [x+[y] for x in result for y in pool] + for prod in result: + yield tuple(prod) + argtypes = ['', 'abc', '', range(0), range(4), dict(a=1, b=2, c=3), set('abcdefg'), range(11), tuple(range(13))] for i in range(100): args = [random.choice(argtypes) for j in range(random.randrange(5))] expected_len = prod(map(len, args)) self.assertEqual(len(list(product(*args))), expected_len) + self.assertEqual(list(product(*args)), list(product1(*args))) + self.assertEqual(list(product(*args)), list(product2(*args))) args = map(iter, args) self.assertEqual(len(list(product(*args))), expected_len) @@ -661,6 +697,81 @@ class TestBasicOps(unittest.TestCase): self.assertRaises(StopIteration, next, f(lambda x:x, [])) self.assertRaises(StopIteration, next, f(lambda x:x, StopNow())) +class TestExamples(unittest.TestCase): + + def test_chain(self): + self.assertEqual(''.join(chain('ABC', 'DEF')), 'ABCDEF') + + def test_chain_from_iterable(self): + self.assertEqual(''.join(chain.from_iterable(['ABC', 'DEF'])), 'ABCDEF') + + def test_combinations(self): + self.assertEqual(list(combinations('ABCD', 2)), + [('A','B'), ('A','C'), ('A','D'), ('B','C'), ('B','D'), ('C','D')]) + self.assertEqual(list(combinations(range(4), 3)), + [(0,1,2), (0,1,3), (0,2,3), (1,2,3)]) + + def test_count(self): + self.assertEqual(list(islice(count(10), 5)), [10, 11, 12, 13, 14]) + + def test_cycle(self): + self.assertEqual(list(islice(cycle('ABCD'), 12)), list('ABCDABCDABCD')) + + def test_dropwhile(self): + self.assertEqual(list(dropwhile(lambda x: x<5, [1,4,6,4,1])), [6,4,1]) + + def test_groupby(self): + self.assertEqual([k for k, g in groupby('AAAABBBCCDAABBB')], + list('ABCDAB')) + self.assertEqual([(list(g)) for k, g in groupby('AAAABBBCCD')], + [list('AAAA'), list('BBB'), list('CC'), list('D')]) + + def test_filter(self): + self.assertEqual(list(filter(lambda x: x%2, range(10))), [1,3,5,7,9]) + + def test_filterfalse(self): + self.assertEqual(list(filterfalse(lambda x: x%2, range(10))), [0,2,4,6,8]) + + def test_map(self): + self.assertEqual(list(map(pow, (2,3,10), (5,2,3))), [32, 9, 1000]) + + def test_islice(self): + self.assertEqual(list(islice('ABCDEFG', 2)), list('AB')) + self.assertEqual(list(islice('ABCDEFG', 2, 4)), list('CD')) + self.assertEqual(list(islice('ABCDEFG', 2, None)), list('CDEFG')) + self.assertEqual(list(islice('ABCDEFG', 0, None, 2)), list('ACEG')) + + def test_zip(self): + self.assertEqual(list(zip('ABCD', 'xy')), [('A', 'x'), ('B', 'y')]) + + def test_zip_longest(self): + self.assertEqual(list(zip_longest('ABCD', 'xy', fillvalue='-')), + [('A', 'x'), ('B', 'y'), ('C', '-'), ('D', '-')]) + + def test_permutations(self): + self.assertEqual(list(permutations('ABCD', 2)), + list(map(tuple, 'AB AC AD BA BC BD CA CB CD DA DB DC'.split()))) + self.assertEqual(list(permutations(range(3))), + [(0,1,2), (0,2,1), (1,0,2), (1,2,0), (2,0,1), (2,1,0)]) + + def test_product(self): + self.assertEqual(list(product('ABCD', 'xy')), + list(map(tuple, 'Ax Ay Bx By Cx Cy Dx Dy'.split()))) + self.assertEqual(list(product(range(2), repeat=3)), + [(0,0,0), (0,0,1), (0,1,0), (0,1,1), + (1,0,0), (1,0,1), (1,1,0), (1,1,1)]) + + def test_repeat(self): + self.assertEqual(list(repeat(10, 3)), [10, 10, 10]) + + def test_stapmap(self): + self.assertEqual(list(starmap(pow, [(2,5), (3,2), (10,3)])), + [32, 9, 1000]) + + def test_takewhile(self): + self.assertEqual(list(takewhile(lambda x: x<5, [1,4,6,4,1])), [1,4]) + + class TestGC(unittest.TestCase): def makecycle(self, iterator, container): @@ -672,6 +783,14 @@ class TestGC(unittest.TestCase): a = [] self.makecycle(chain(a), a) + def test_chain_from_iterable(self): + a = [] + self.makecycle(chain.from_iterable([a]), a) + + def test_combinations(self): + a = [] + self.makecycle(combinations([1,2,a,3], 3), a) + def test_cycle(self): a = [] self.makecycle(cycle([a]*2), a) @@ -684,6 +803,13 @@ class TestGC(unittest.TestCase): a = [] self.makecycle(groupby([a]*2, lambda x:x), a) + def test_issue2246(self): + # Issue 2246 -- the _grouper iterator was not included in GC + n = 10 + keyfunc = lambda x: x + for i, j in groupby(range(n), key=keyfunc): + keyfunc.__dict__.setdefault('x',[]).append(j) + def test_filter(self): a = [] self.makecycle(filter(lambda x:True, [a]*2), a) @@ -696,6 +822,12 @@ class TestGC(unittest.TestCase): a = [] self.makecycle(zip([a]*2, [a]*3), a) + def test_zip_longest(self): + a = [] + self.makecycle(zip_longest([a]*2, [a]*3), a) + b = [a, None] + self.makecycle(zip_longest([a]*2, [a]*3, fillvalue=b), a) + def test_map(self): a = [] self.makecycle(map(lambda x:x, [a]*2), a) @@ -704,6 +836,14 @@ class TestGC(unittest.TestCase): a = [] self.makecycle(islice([a]*2, None), a) + def test_permutations(self): + a = [] + self.makecycle(permutations([1,2,a,3], 3), a) + + def test_product(self): + a = [] + self.makecycle(product([1,2,a,3], repeat=3), a) + def test_repeat(self): a = [] self.makecycle(repeat(a), a) @@ -1115,7 +1255,7 @@ Samuele ... return sum(map(operator.mul, vec1, vec2)) >>> def flatten(listOfLists): -... return list(chain(*listOfLists)) +... return list(chain.from_iterable(listOfLists)) >>> def repeatfunc(func, times=None, *args): ... "Repeat calls to func with specified arguments." @@ -1134,6 +1274,38 @@ Samuele ... pass ... return zip(a, b) +>>> def grouper(n, iterable, fillvalue=None): +... "grouper(3, 'abcdefg', 'x') --> ('a','b','c'), ('d','e','f'), ('g','x','x')" +... args = [iter(iterable)] * n +... kwds = dict(fillvalue=fillvalue) +... return zip_longest(*args, **kwds) + +>>> def roundrobin(*iterables): +... "roundrobin('abc', 'd', 'ef') --> 'a', 'd', 'e', 'b', 'f', 'c'" +... # Recipe credited to George Sakkis +... pending = len(iterables) +... nexts = cycle(iter(it).__next__ for it in iterables) +... while pending: +... try: +... for next in nexts: +... yield next() +... except StopIteration: +... pending -= 1 +... nexts = cycle(islice(nexts, pending)) + +>>> def powerset(iterable): +... "powerset('ab') --> set([]), set(['a']), set(['b']), set(['a', 'b'])" +... # Recipe credited to Eric Raymond +... pairs = [(2**i, x) for i, x in enumerate(iterable)] +... for n in range(2**len(pairs)): +... yield set(x for m, x in pairs if m&n) + +>>> def compress(data, selectors): +... "compress('abcdef', [1,0,1,0,1,1]) --> a c e f" +... for d, s in zip(data, selectors): +... if s: +... yield d + This is not part of the examples but it tests to make sure the definitions perform as purported. @@ -1199,6 +1371,18 @@ False >>> dotproduct([1,2,3], [4,5,6]) 32 +>>> list(grouper(3, 'abcdefg', 'x')) +[('a', 'b', 'c'), ('d', 'e', 'f'), ('g', 'x', 'x')] + +>>> list(roundrobin('abc', 'd', 'ef')) +['a', 'd', 'e', 'b', 'f', 'c'] + +>>> list(map(sorted, powerset('ab'))) +[[], ['a'], ['b'], ['a', 'b']] + +>>> list(compress('abcdef', [1,0,1,0,1,1])) +['a', 'c', 'e', 'f'] + """ __test__ = {'libreftest' : libreftest} @@ -1206,7 +1390,7 @@ __test__ = {'libreftest' : libreftest} def test_main(verbose=None): test_classes = (TestBasicOps, TestVariousIteratorArgs, TestGC, RegressionTests, LengthTransparency, - SubclassWithKwargsTest) + SubclassWithKwargsTest, TestExamples) test_support.run_unittest(*test_classes) # verify reference counting diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 6cabb82..5f23336 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -26,6 +26,114 @@ class FileTests(unittest.TestCase): os.closerange(f, f+2) self.assertRaises(OSError, os.write, f, "a") +class TemporaryFileTests(unittest.TestCase): + def setUp(self): + self.files = [] + os.mkdir(test_support.TESTFN) + + def tearDown(self): + for name in self.files: + os.unlink(name) + os.rmdir(test_support.TESTFN) + + def check_tempfile(self, name): + # make sure it doesn't already exist: + self.failIf(os.path.exists(name), + "file already exists for temporary file") + # make sure we can create the file + open(name, "w") + self.files.append(name) + + def test_tempnam(self): + if not hasattr(os, "tempnam"): + return + warnings.filterwarnings("ignore", "tempnam", RuntimeWarning, + r"test_os$") + self.check_tempfile(os.tempnam()) + + name = os.tempnam(test_support.TESTFN) + self.check_tempfile(name) + + name = os.tempnam(test_support.TESTFN, "pfx") + self.assert_(os.path.basename(name)[:3] == "pfx") + self.check_tempfile(name) + + def test_tmpfile(self): + if not hasattr(os, "tmpfile"): + return + # As with test_tmpnam() below, the Windows implementation of tmpfile() + # attempts to create a file in the root directory of the current drive. + # On Vista and Server 2008, this test will always fail for normal users + # as writing to the root directory requires elevated privileges. With + # XP and below, the semantics of tmpfile() are the same, but the user + # running the test is more likely to have administrative privileges on + # their account already. If that's the case, then os.tmpfile() should + # work. In order to make this test as useful as possible, rather than + # trying to detect Windows versions or whether or not the user has the + # right permissions, just try and create a file in the root directory + # and see if it raises a 'Permission denied' OSError. If it does, then + # test that a subsequent call to os.tmpfile() raises the same error. If + # it doesn't, assume we're on XP or below and the user running the test + # has administrative privileges, and proceed with the test as normal. + if sys.platform == 'win32': + name = '\\python_test_os_test_tmpfile.txt' + if os.path.exists(name): + os.remove(name) + try: + fp = open(name, 'w') + except IOError as first: + # open() failed, assert tmpfile() fails in the same way. + # Although open() raises an IOError and os.tmpfile() raises an + # OSError(), 'args' will be (13, 'Permission denied') in both + # cases. + try: + fp = os.tmpfile() + except OSError as second: + self.assertEqual(first.args, second.args) + else: + self.fail("expected os.tmpfile() to raise OSError") + return + else: + # open() worked, therefore, tmpfile() should work. Close our + # dummy file and proceed with the test as normal. + fp.close() + os.remove(name) + + fp = os.tmpfile() + fp.write("foobar") + fp.seek(0,0) + s = fp.read() + fp.close() + self.assert_(s == "foobar") + + def test_tmpnam(self): + import sys + if not hasattr(os, "tmpnam"): + return + warnings.filterwarnings("ignore", "tmpnam", RuntimeWarning, + r"test_os$") + name = os.tmpnam() + if sys.platform in ("win32",): + # The Windows tmpnam() seems useless. From the MS docs: + # + # The character string that tmpnam creates consists of + # the path prefix, defined by the entry P_tmpdir in the + # file STDIO.H, followed by a sequence consisting of the + # digit characters '0' through '9'; the numerical value + # of this string is in the range 1 - 65,535. Changing the + # definitions of L_tmpnam or P_tmpdir in STDIO.H does not + # change the operation of tmpnam. + # + # The really bizarre part is that, at least under MSVC6, + # P_tmpdir is "\\". That is, the path returned refers to + # the root of the current drive. That's a terrible place to + # put temp files, and, depending on privileges, the user + # may not even be able to open a file in the root directory. + self.failIf(os.path.exists(name), + "file already exists for temporary file") + else: + self.check_tempfile(name) + # Test attributes on return values from os.*stat* family. class StatAttributeTests(unittest.TestCase): def setUp(self): diff --git a/Lib/test/test_select.py b/Lib/test/test_select.py index b45ec7f..f4032d1 100644 --- a/Lib/test/test_select.py +++ b/Lib/test/test_select.py @@ -1,70 +1,52 @@ -# Testing select module -from test.test_support import verbose, reap_children +from test import test_support +import unittest import select import os - -# test some known error conditions -try: - rfd, wfd, xfd = select.select(1, 2, 3) -except TypeError: - pass -else: - print('expected TypeError exception not raised') - -class Nope: - pass - -class Almost: - def fileno(self): - return 'fileno' - -try: - rfd, wfd, xfd = select.select([Nope()], [], []) -except TypeError: - pass -else: - print('expected TypeError exception not raised') - -try: - rfd, wfd, xfd = select.select([Almost()], [], []) -except TypeError: - pass -else: - print('expected TypeError exception not raised') - -try: - rfd, wfd, xfd = select.select([], [], [], 'not a number') -except TypeError: - pass -else: - print('expected TypeError exception not raised') - - -def test(): - import sys - if sys.platform[:3] in ('win', 'mac', 'os2'): - if verbose: - print("Can't test select easily on", sys.platform) - return - cmd = 'for i in 0 1 2 3 4 5 6 7 8 9; do echo testing...; sleep 1; done' - p = os.popen(cmd, 'r') - for tout in (0, 1, 2, 4, 8, 16) + (None,)*10: - if verbose: - print('timeout =', tout) - rfd, wfd, xfd = select.select([p], [], [], tout) - if (rfd, wfd, xfd) == ([], [], []): - continue - if (rfd, wfd, xfd) == ([p], [], []): - line = p.readline() - if verbose: - print(repr(line)) - if not line: - if verbose: - print('EOF') - break - continue - print('Unexpected return values from select():', rfd, wfd, xfd) - p.close() - reap_children() - -test() +import sys + +class SelectTestCase(unittest.TestCase): + + class Nope: + pass + + class Almost: + def fileno(self): + return 'fileno' + + def test_error_conditions(self): + self.assertRaises(TypeError, select.select, 1, 2, 3) + self.assertRaises(TypeError, select.select, [self.Nope()], [], []) + self.assertRaises(TypeError, select.select, [self.Almost()], [], []) + self.assertRaises(TypeError, select.select, [], [], [], "not a number") + + def test_select(self): + if sys.platform[:3] in ('win', 'mac', 'os2', 'riscos'): + if test_support.verbose: + print("Can't test select easily on", sys.platform) + return + cmd = 'for i in 0 1 2 3 4 5 6 7 8 9; do echo testing...; sleep 1; done' + p = os.popen(cmd, 'r') + for tout in (0, 1, 2, 4, 8, 16) + (None,)*10: + if test_support.verbose: + print('timeout =', tout) + rfd, wfd, xfd = select.select([p], [], [], tout) + if (rfd, wfd, xfd) == ([], [], []): + continue + if (rfd, wfd, xfd) == ([p], [], []): + line = p.readline() + if test_support.verbose: + print(repr(line)) + if not line: + if test_support.verbose: + print('EOF') + break + continue + self.fail('Unexpected return values from select():', rfd, wfd, xfd) + p.close() + +def test_main(): + test_support.run_unittest(SelectTestCase) + test_support.reap_children() + +if __name__ == "__main__": + test_main() diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py index 5694bb5..a9d5672 100644 --- a/Lib/test/test_smtplib.py +++ b/Lib/test/test_smtplib.py @@ -19,7 +19,7 @@ PORT = None def server(evt, buf): serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - serv.settimeout(1) + serv.settimeout(15) serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) serv.bind(("", 0)) global PORT diff --git a/Lib/test/test_socketserver.py b/Lib/test/test_socketserver.py index 658056c..7fe746d 100644 --- a/Lib/test/test_socketserver.py +++ b/Lib/test/test_socketserver.py @@ -21,13 +21,16 @@ from test.test_support import TESTFN as TEST_FILE test.test_support.requires("network") -NREQ = 3 TEST_STR = b"hello world\n" HOST = "localhost" HAVE_UNIX_SOCKETS = hasattr(socket, "AF_UNIX") HAVE_FORKING = hasattr(os, "fork") and os.name != "os2" +def signal_alarm(n): + """Call signal.alarm when it exists (i.e. not on Windows).""" + if hasattr(signal, 'alarm'): + signal.alarm(n) def receive(sock, n, timeout=20): r, w, x = select.select([sock], [], [], timeout) @@ -46,70 +49,6 @@ if HAVE_UNIX_SOCKETS: pass -class MyMixinServer: - def serve_a_few(self): - for i in range(NREQ): - self.handle_request() - - def handle_error(self, request, client_address): - self.close_request(request) - self.server_close() - raise - -def receive(sock, n, timeout=20): - r, w, x = select.select([sock], [], [], timeout) - if sock in r: - return sock.recv(n) - else: - raise RuntimeError("timed out on %r" % (sock,)) - -def testdgram(proto, addr): - s = socket.socket(proto, socket.SOCK_DGRAM) - s.sendto(teststring, addr) - buf = data = receive(s, 100) - while data and b'\n' not in buf: - data = receive(s, 100) - buf += data - verify(buf == teststring) - s.close() - -def teststream(proto, addr): - s = socket.socket(proto, socket.SOCK_STREAM) - s.connect(addr) - s.sendall(teststring) - buf = data = receive(s, 100) - while data and b'\n' not in buf: - data = receive(s, 100) - buf += data - verify(buf == teststring) - s.close() - -class ServerThread(threading.Thread): - def __init__(self, addr, svrcls, hdlrcls): - threading.Thread.__init__(self) - self.__addr = addr - self.__svrcls = svrcls - self.__hdlrcls = hdlrcls - self.ready = threading.Event() - - def run(self): - class svrcls(MyMixinServer, self.__svrcls): - pass - if verbose: print("thread: creating server") - svr = svrcls(self.__addr, self.__hdlrcls) - # We had the OS pick a port, so pull the real address out of - # the server. - self.addr = svr.server_address - self.port = self.addr[1] - if self.addr != svr.socket.getsockname(): - raise RuntimeError('server_address was %s, expected %s' % - (self.addr, svr.socket.getsockname())) - self.ready.set() - if verbose: print("thread: serving three times") - svr.serve_a_few() - if verbose: print("thread: done") - - @contextlib.contextmanager def simple_subprocess(testcase): pid = os.fork() @@ -126,7 +65,7 @@ class SocketServerTest(unittest.TestCase): """Test all socket servers.""" def setUp(self): - signal.alarm(20) # Kill deadlocks after 20 seconds. + signal_alarm(20) # Kill deadlocks after 20 seconds. self.port_seed = 0 self.test_files = [] @@ -139,7 +78,7 @@ class SocketServerTest(unittest.TestCase): except os.error: pass self.test_files[:] = [] - signal.alarm(0) # Didn't deadlock. + signal_alarm(0) # Didn't deadlock. def pickaddr(self, proto): if proto == socket.AF_INET: @@ -166,29 +105,48 @@ class SocketServerTest(unittest.TestCase): self.test_files.append(fn) return fn + def make_server(self, addr, svrcls, hdlrbase): + class MyServer(svrcls): + def handle_error(self, request, client_address): + self.close_request(request) + self.server_close() + raise - def run_server(self, svrcls, hdlrbase, testfunc): class MyHandler(hdlrbase): def handle(self): line = self.rfile.readline() self.wfile.write(line) - addr = self.pickaddr(svrcls.address_family) + if verbose: print("creating server") + server = MyServer(addr, MyHandler) + self.assertEquals(server.server_address, server.socket.getsockname()) + return server + + def run_server(self, svrcls, hdlrbase, testfunc): + server = self.make_server(self.pickaddr(svrcls.address_family), + svrcls, hdlrbase) + # We had the OS pick a port, so pull the real address out of + # the server. + addr = server.server_address if verbose: print("ADDR =", addr) print("CLASS =", svrcls) - t = ServerThread(addr, svrcls, MyHandler) - if verbose: print("server created") + + t = threading.Thread( + name='%s serving' % svrcls, + target=server.serve_forever, + # Short poll interval to make the test finish quickly. + # Time between requests is short enough that we won't wake + # up spuriously too many times. + kwargs={'poll_interval':0.01}) + t.setDaemon(True) # In case this function raises. t.start() if verbose: print("server running") - t.ready.wait(10) - self.assert_(t.ready.isSet(), - "%s not ready within a reasonable time" % svrcls) - addr = t.addr - for i in range(NREQ): + for i in range(3): if verbose: print("test client", i) testfunc(svrcls.address_family, addr) if verbose: print("waiting for server") + server.shutdown() t.join() if verbose: print("done") @@ -295,4 +253,4 @@ def test_main(): if __name__ == "__main__": test_main() - signal.alarm(3) # Shutdown shouldn't take more than 3 seconds. + signal_alarm(3) # Shutdown shouldn't take more than 3 seconds. diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 34bb31a..4e9bfb3 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -368,6 +368,7 @@ else: # we assume the certfile contains both private key and certificate self.certfile = certfile self.active = False + self.active_lock = threading.Lock() self.allow_reuse_address = True def __str__(self): @@ -398,23 +399,32 @@ else: # We want this to run in a thread, so we use a slightly # modified version of "forever". self.active = True - while self.active: + while 1: try: - self.handle_request() + # We need to lock while handling the request. + # Another thread can close the socket after self.active + # has been checked and before the request is handled. + # This causes an exception when using the closed socket. + with self.active_lock: + if not self.active: + break + self.handle_request() except socket.timeout: pass except KeyboardInterrupt: self.server_close() return except: - sys.stdout.write(''.join(traceback.format_exception(*sys.exc_info()))); + sys.stdout.write(''.join(traceback.format_exception(*sys.exc_info()))) + break def server_close(self): # Again, we want this to run in a thread, so we need to override # close to clear the "active" flag, so that serve_forever() will # terminate. - HTTPServer.server_close(self) - self.active = False + with self.active_lock: + HTTPServer.server_close(self) + self.active = False class RootedHTTPRequestHandler(SimpleHTTPRequestHandler): @@ -749,7 +759,7 @@ else: not in cert['subject']): raise test_support.TestFailed( "Missing or invalid 'organizationName' field in certificate subject; " - "should be 'Python Software Foundation'."); + "should be 'Python Software Foundation'.") s.close() finally: server.stop() diff --git a/Lib/test/test_strptime.py b/Lib/test/test_strptime.py index 81f8392..ac8905a 100644 --- a/Lib/test/test_strptime.py +++ b/Lib/test/test_strptime.py @@ -208,11 +208,11 @@ class StrptimeTests(unittest.TestCase): def test_ValueError(self): # Make sure ValueError is raised when match fails or format is bad - self.assertRaises(ValueError, _strptime.strptime, data_string="%d", + self.assertRaises(ValueError, _strptime._strptime_time, data_string="%d", format="%A") for bad_format in ("%", "% ", "%e"): try: - _strptime.strptime("2005", bad_format) + _strptime._strptime_time("2005", bad_format) except ValueError: continue except Exception as err: @@ -223,12 +223,12 @@ class StrptimeTests(unittest.TestCase): def test_unconverteddata(self): # Check ValueError is raised when there is unconverted data - self.assertRaises(ValueError, _strptime.strptime, "10 12", "%m") + self.assertRaises(ValueError, _strptime._strptime_time, "10 12", "%m") def helper(self, directive, position): """Helper fxn in testing.""" strf_output = time.strftime("%" + directive, self.time_tuple) - strp_output = _strptime.strptime(strf_output, "%" + directive) + strp_output = _strptime._strptime_time(strf_output, "%" + directive) self.failUnless(strp_output[position] == self.time_tuple[position], "testing of '%s' directive failed; '%s' -> %s != %s" % (directive, strf_output, strp_output[position], @@ -241,7 +241,7 @@ class StrptimeTests(unittest.TestCase): # Must also make sure %y values are correct for bounds set by Open Group for century, bounds in ((1900, ('69', '99')), (2000, ('00', '68'))): for bound in bounds: - strp_output = _strptime.strptime(bound, '%y') + strp_output = _strptime._strptime_time(bound, '%y') expected_result = century + int(bound) self.failUnless(strp_output[0] == expected_result, "'y' test failed; passed in '%s' " @@ -260,7 +260,7 @@ class StrptimeTests(unittest.TestCase): # Test hour directives self.helper('H', 3) strf_output = time.strftime("%I %p", self.time_tuple) - strp_output = _strptime.strptime(strf_output, "%I %p") + strp_output = _strptime._strptime_time(strf_output, "%I %p") self.failUnless(strp_output[3] == self.time_tuple[3], "testing of '%%I %%p' directive failed; '%s' -> %s != %s" % (strf_output, strp_output[3], self.time_tuple[3])) @@ -273,6 +273,12 @@ class StrptimeTests(unittest.TestCase): # Test second directives self.helper('S', 5) + def test_fraction(self): + import datetime + now = datetime.datetime.now() + tup, frac = _strptime._strptime(str(now), format="%Y-%m-%d %H:%M:%S.%f") + self.assertEqual(frac, now.microsecond) + def test_weekday(self): # Test weekday directives for directive in ('A', 'a', 'w'): @@ -287,16 +293,16 @@ class StrptimeTests(unittest.TestCase): # When gmtime() is used with %Z, entire result of strftime() is empty. # Check for equal timezone names deals with bad locale info when this # occurs; first found in FreeBSD 4.4. - strp_output = _strptime.strptime("UTC", "%Z") + strp_output = _strptime._strptime_time("UTC", "%Z") self.failUnlessEqual(strp_output.tm_isdst, 0) - strp_output = _strptime.strptime("GMT", "%Z") + strp_output = _strptime._strptime_time("GMT", "%Z") self.failUnlessEqual(strp_output.tm_isdst, 0) if sys.platform == "mac": # Timezones don't really work on MacOS9 return time_tuple = time.localtime() strf_output = time.strftime("%Z") #UTC does not have a timezone - strp_output = _strptime.strptime(strf_output, "%Z") + strp_output = _strptime._strptime_time(strf_output, "%Z") locale_time = _strptime.LocaleTime() if time.tzname[0] != time.tzname[1] or not time.daylight: self.failUnless(strp_output[8] == time_tuple[8], @@ -320,7 +326,7 @@ class StrptimeTests(unittest.TestCase): original_daylight = time.daylight time.tzname = (tz_name, tz_name) time.daylight = 1 - tz_value = _strptime.strptime(tz_name, "%Z")[8] + tz_value = _strptime._strptime_time(tz_name, "%Z")[8] self.failUnlessEqual(tz_value, -1, "%s lead to a timezone value of %s instead of -1 when " "time.daylight set to %s and passing in %s" % @@ -347,7 +353,7 @@ class StrptimeTests(unittest.TestCase): def test_percent(self): # Make sure % signs are handled properly strf_output = time.strftime("%m %% %Y", self.time_tuple) - strp_output = _strptime.strptime(strf_output, "%m %% %Y") + strp_output = _strptime._strptime_time(strf_output, "%m %% %Y") self.failUnless(strp_output[0] == self.time_tuple[0] and strp_output[1] == self.time_tuple[1], "handling of percent sign failed") @@ -355,17 +361,17 @@ class StrptimeTests(unittest.TestCase): def test_caseinsensitive(self): # Should handle names case-insensitively. strf_output = time.strftime("%B", self.time_tuple) - self.failUnless(_strptime.strptime(strf_output.upper(), "%B"), + self.failUnless(_strptime._strptime_time(strf_output.upper(), "%B"), "strptime does not handle ALL-CAPS names properly") - self.failUnless(_strptime.strptime(strf_output.lower(), "%B"), + self.failUnless(_strptime._strptime_time(strf_output.lower(), "%B"), "strptime does not handle lowercase names properly") - self.failUnless(_strptime.strptime(strf_output.capitalize(), "%B"), + self.failUnless(_strptime._strptime_time(strf_output.capitalize(), "%B"), "strptime does not handle capword names properly") def test_defaults(self): # Default return value should be (1900, 1, 1, 0, 0, 0, 0, 1, 0) defaults = (1900, 1, 1, 0, 0, 0, 0, 1, -1) - strp_output = _strptime.strptime('1', '%m') + strp_output = _strptime._strptime_time('1', '%m') self.failUnless(strp_output == defaults, "Default values for strptime() are incorrect;" " %s != %s" % (strp_output, defaults)) @@ -377,7 +383,7 @@ class StrptimeTests(unittest.TestCase): # escaped. # Test instigated by bug #796149 . need_escaping = ".^$*+?{}\[]|)(" - self.failUnless(_strptime.strptime(need_escaping, need_escaping)) + self.failUnless(_strptime._strptime_time(need_escaping, need_escaping)) class Strptime12AMPMTests(unittest.TestCase): """Test a _strptime regression in '%I %p' at 12 noon (12 PM)""" @@ -386,8 +392,8 @@ class Strptime12AMPMTests(unittest.TestCase): eq = self.assertEqual eq(time.strptime('12 PM', '%I %p')[3], 12) eq(time.strptime('12 AM', '%I %p')[3], 0) - eq(_strptime.strptime('12 PM', '%I %p')[3], 12) - eq(_strptime.strptime('12 AM', '%I %p')[3], 0) + eq(_strptime._strptime_time('12 PM', '%I %p')[3], 12) + eq(_strptime._strptime_time('12 AM', '%I %p')[3], 0) class JulianTests(unittest.TestCase): @@ -397,7 +403,7 @@ class JulianTests(unittest.TestCase): eq = self.assertEqual for i in range(1, 367): # use 2004, since it is a leap year, we have 366 days - eq(_strptime.strptime('%d 2004' % i, '%j %Y')[7], i) + eq(_strptime._strptime_time('%d 2004' % i, '%j %Y')[7], i) class CalculationTests(unittest.TestCase): """Test that strptime() fills in missing info correctly""" @@ -408,7 +414,7 @@ class CalculationTests(unittest.TestCase): def test_julian_calculation(self): # Make sure that when Julian is missing that it is calculated format_string = "%Y %m %d %H %M %S %w %Z" - result = _strptime.strptime(time.strftime(format_string, self.time_tuple), + result = _strptime._strptime_time(time.strftime(format_string, self.time_tuple), format_string) self.failUnless(result.tm_yday == self.time_tuple.tm_yday, "Calculation of tm_yday failed; %s != %s" % @@ -417,7 +423,7 @@ class CalculationTests(unittest.TestCase): def test_gregorian_calculation(self): # Test that Gregorian date can be calculated from Julian day format_string = "%Y %H %M %S %w %j %Z" - result = _strptime.strptime(time.strftime(format_string, self.time_tuple), + result = _strptime._strptime_time(time.strftime(format_string, self.time_tuple), format_string) self.failUnless(result.tm_year == self.time_tuple.tm_year and result.tm_mon == self.time_tuple.tm_mon and @@ -431,7 +437,7 @@ class CalculationTests(unittest.TestCase): def test_day_of_week_calculation(self): # Test that the day of the week is calculated as needed format_string = "%Y %m %d %H %S %j %Z" - result = _strptime.strptime(time.strftime(format_string, self.time_tuple), + result = _strptime._strptime_time(time.strftime(format_string, self.time_tuple), format_string) self.failUnless(result.tm_wday == self.time_tuple.tm_wday, "Calculation of day of the week failed;" @@ -445,7 +451,7 @@ class CalculationTests(unittest.TestCase): format_string = "%%Y %%%s %%w" % directive dt_date = datetime_date(*ymd_tuple) strp_input = dt_date.strftime(format_string) - strp_output = _strptime.strptime(strp_input, format_string) + strp_output = _strptime._strptime_time(strp_input, format_string) self.failUnless(strp_output[:3] == ymd_tuple, "%s(%s) test failed w/ '%s': %s != %s (%s != %s)" % (test_reason, directive, strp_input, @@ -484,11 +490,11 @@ class CacheTests(unittest.TestCase): def test_time_re_recreation(self): # Make sure cache is recreated when current locale does not match what # cached object was created with. - _strptime.strptime("10", "%d") - _strptime.strptime("2005", "%Y") + _strptime._strptime_time("10", "%d") + _strptime._strptime_time("2005", "%Y") _strptime._TimeRE_cache.locale_time.lang = "Ni" original_time_re = id(_strptime._TimeRE_cache) - _strptime.strptime("10", "%d") + _strptime._strptime_time("10", "%d") self.failIfEqual(original_time_re, id(_strptime._TimeRE_cache)) self.failUnlessEqual(len(_strptime._regex_cache), 1) @@ -502,7 +508,7 @@ class CacheTests(unittest.TestCase): while len(_strptime._regex_cache) <= _strptime._CACHE_MAX_SIZE: _strptime._regex_cache[bogus_key] = None bogus_key += 1 - _strptime.strptime("10", "%d") + _strptime._strptime_time("10", "%d") self.failUnlessEqual(len(_strptime._regex_cache), 1) def test_new_localetime(self): @@ -510,7 +516,7 @@ class CacheTests(unittest.TestCase): # is created. locale_time_id = id(_strptime._TimeRE_cache.locale_time) _strptime._TimeRE_cache.locale_time.lang = "Ni" - _strptime.strptime("10", "%d") + _strptime._strptime_time("10", "%d") self.failIfEqual(locale_time_id, id(_strptime._TimeRE_cache.locale_time)) @@ -522,13 +528,13 @@ class CacheTests(unittest.TestCase): except locale.Error: return try: - _strptime.strptime('10', '%d') + _strptime._strptime_time('10', '%d') # Get id of current cache object. first_time_re_id = id(_strptime._TimeRE_cache) try: # Change the locale and force a recreation of the cache. locale.setlocale(locale.LC_TIME, ('de_DE', 'UTF8')) - _strptime.strptime('10', '%d') + _strptime._strptime_time('10', '%d') # Get the new cache object's id. second_time_re_id = id(_strptime._TimeRE_cache) # They should not be equal. diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py index 23358be..a815555 100644 --- a/Lib/test/test_struct.py +++ b/Lib/test/test_struct.py @@ -84,8 +84,8 @@ sz = struct.calcsize('i') if sz * 3 != struct.calcsize('iii'): raise TestFailed('inconsistent sizes') -fmt = 'cbxxxxxxhhhhiillffdt' -fmt3 = '3c3b18x12h6i6l6f3d3t' +fmt = 'cbxxxxxxhhhhiillffd?' +fmt3 = '3c3b18x12h6i6l6f3d3?' sz = struct.calcsize(fmt) sz3 = struct.calcsize(fmt3) if sz * 3 != sz3: @@ -111,7 +111,7 @@ d = 3.1415 t = True for prefix in ('', '@', '<', '>', '=', '!'): - for format in ('xcbhilfdt', 'xcBHILfdt'): + for format in ('xcbhilfd?', 'xcBHILfd?'): format = prefix + format if verbose: print("trying:", format) @@ -160,11 +160,11 @@ tests = [ ('f', -2.0, '\300\000\000\000', '\000\000\000\300', 0), ('d', -2.0, '\300\000\000\000\000\000\000\000', '\000\000\000\000\000\000\000\300', 0), - ('t', 0, '\0', '\0', 0), - ('t', 3, '\1', '\1', 1), - ('t', True, '\1', '\1', 0), - ('t', [], '\0', '\0', 1), - ('t', (1,), '\1', '\1', 1), + ('?', 0, '\0', '\0', 0), + ('?', 3, '\1', '\1', 1), + ('?', True, '\1', '\1', 0), + ('?', [], '\0', '\0', 1), + ('?', (1,), '\1', '\1', 1), ] for fmt, arg, big, lil, asy in tests: @@ -490,7 +490,7 @@ def test_705836(): except OverflowError: pass else: - TestFailed("expected OverflowError") + raise TestFailed("expected OverflowError") test_705836() @@ -646,13 +646,13 @@ def test_bool(): false = (), [], [], '', 0 true = [1], 'test', 5, -1, 0xffffffff+1, 0xffffffff/2 - falseFormat = prefix + 't' * len(false) + falseFormat = prefix + '?' * len(false) if verbose: print('trying bool pack/unpack on', false, 'using format', falseFormat) packedFalse = struct.pack(falseFormat, *false) unpackedFalse = struct.unpack(falseFormat, packedFalse) - trueFormat = prefix + 't' * len(true) + trueFormat = prefix + '?' * len(true) if verbose: print('trying bool pack/unpack on', true, 'using format', trueFormat) packedTrue = struct.pack(trueFormat, *true) @@ -671,10 +671,10 @@ def test_bool(): raise TestFailed('%r did not unpack as false' % t) if prefix and verbose: - print('trying size of bool with format %r' % (prefix+'t')) - packed = struct.pack(prefix+'t', 1) + print('trying size of bool with format %r' % (prefix+'?')) + packed = struct.pack(prefix+'?', 1) - if len(packed) != struct.calcsize(prefix+'t'): + if len(packed) != struct.calcsize(prefix+'?'): raise TestFailed('packed length is not equal to calculated size') if len(packed) != 1 and prefix: @@ -683,7 +683,7 @@ def test_bool(): print('size of bool in native format is %i' % (len(packed))) for c in b'\x01\x7f\xff\x0f\xf0': - if struct.unpack('>t', bytes([c]))[0] is not True: + if struct.unpack('>?', c)[0] is not True: raise TestFailed('%c did not unpack as True' % c) test_bool() diff --git a/Lib/test/test_thread.py b/Lib/test/test_thread.py index 577d4cb..c89c5a1 100644 --- a/Lib/test/test_thread.py +++ b/Lib/test/test_thread.py @@ -1,160 +1,161 @@ -# Very rudimentary test of thread module - -# Create a bunch of threads, let each do some work, wait until all are done - -from test.test_support import verbose +import os +import unittest import random +from test import test_support import thread import time -mutex = thread.allocate_lock() -rmutex = thread.allocate_lock() # for calls to random -running = 0 -done = thread.allocate_lock() -done.acquire() - -numtasks = 10 - -def task(ident): - global running - rmutex.acquire() - delay = random.random() * numtasks - rmutex.release() - if verbose: - print('task', ident, 'will run for', round(delay, 1), 'sec') - time.sleep(delay) - if verbose: - print('task', ident, 'done') - mutex.acquire() - running = running - 1 - if running == 0: - done.release() - mutex.release() - -next_ident = 0 -def newtask(): - global next_ident, running - mutex.acquire() - next_ident = next_ident + 1 - if verbose: - print('creating task', next_ident) - thread.start_new_thread(task, (next_ident,)) - running = running + 1 - mutex.release() - -for i in range(numtasks): - newtask() - -print('waiting for all tasks to complete') -done.acquire() -print('all tasks done') - -class barrier: - def __init__(self, n): - self.n = n + +NUMTASKS = 10 +NUMTRIPS = 3 + +def verbose_print(arg): + """Helper function for printing out debugging output.""" + if test_support.verbose: + print(arg) + +class BasicThreadTest(unittest.TestCase): + + def setUp(self): + self.done_mutex = thread.allocate_lock() + self.done_mutex.acquire() + self.running_mutex = thread.allocate_lock() + self.random_mutex = thread.allocate_lock() + self.running = 0 + self.next_ident = 0 + + +class ThreadRunningTests(BasicThreadTest): + + def newtask(self): + with self.running_mutex: + self.next_ident += 1 + verbose_print("creating task %s" % self.next_ident) + thread.start_new_thread(self.task, (self.next_ident,)) + self.running += 1 + + def task(self, ident): + with self.random_mutex: + delay = random.random() * NUMTASKS + verbose_print("task %s will run for %s" % (ident, round(delay, 1))) + time.sleep(delay) + verbose_print("task %s done" % ident) + with self.running_mutex: + self.running -= 1 + if self.running == 0: + self.done_mutex.release() + + def test_starting_threads(self): + # Basic test for thread creation. + for i in range(NUMTASKS): + self.newtask() + verbose_print("waiting for tasks to complete...") + self.done_mutex.acquire() + verbose_print("all tasks done") + + def test_stack_size(self): + # Various stack size tests. + self.assertEquals(thread.stack_size(), 0, "intial stack size is not 0") + + thread.stack_size(0) + self.assertEquals(thread.stack_size(), 0, "stack_size not reset to default") + + if os.name not in ("nt", "os2", "posix"): + return + + tss_supported = True + try: + thread.stack_size(4096) + except ValueError: + verbose_print("caught expected ValueError setting " + "stack_size(4096)") + except thread.error: + tss_supported = False + verbose_print("platform does not support changing thread stack " + "size") + + if tss_supported: + fail_msg = "stack_size(%d) failed - should succeed" + for tss in (262144, 0x100000, 0): + thread.stack_size(tss) + self.assertEquals(thread.stack_size(), tss, fail_msg % tss) + verbose_print("successfully set stack_size(%d)" % tss) + + for tss in (262144, 0x100000): + verbose_print("trying stack_size = (%d)" % tss) + self.next_ident = 0 + for i in range(NUMTASKS): + self.newtask() + + verbose_print("waiting for all tasks to complete") + self.done_mutex.acquire() + verbose_print("all tasks done") + + thread.stack_size(0) + + +class Barrier: + def __init__(self, num_threads): + self.num_threads = num_threads self.waiting = 0 - self.checkin = thread.allocate_lock() - self.checkout = thread.allocate_lock() - self.checkout.acquire() + self.checkin_mutex = thread.allocate_lock() + self.checkout_mutex = thread.allocate_lock() + self.checkout_mutex.acquire() def enter(self): - checkin, checkout = self.checkin, self.checkout - - checkin.acquire() + self.checkin_mutex.acquire() self.waiting = self.waiting + 1 - if self.waiting == self.n: - self.waiting = self.n - 1 - checkout.release() + if self.waiting == self.num_threads: + self.waiting = self.num_threads - 1 + self.checkout_mutex.release() return - checkin.release() + self.checkin_mutex.release() - checkout.acquire() + self.checkout_mutex.acquire() self.waiting = self.waiting - 1 if self.waiting == 0: - checkin.release() + self.checkin_mutex.release() return - checkout.release() - -numtrips = 3 -def task2(ident): - global running - for i in range(numtrips): - if ident == 0: - # give it a good chance to enter the next - # barrier before the others are all out - # of the current one - delay = 0.001 - else: - rmutex.acquire() - delay = random.random() * numtasks - rmutex.release() - if verbose: - print('task', ident, 'will run for', round(delay, 1), 'sec') - time.sleep(delay) - if verbose: - print('task', ident, 'entering barrier', i) - bar.enter() - if verbose: - print('task', ident, 'leaving barrier', i) - mutex.acquire() - running -= 1 - # Must release mutex before releasing done, else the main thread can - # exit and set mutex to None as part of global teardown; then - # mutex.release() raises AttributeError. - finished = running == 0 - mutex.release() - if finished: - done.release() - -print('\n*** Barrier Test ***') -if done.acquire(0): - raise ValueError("'done' should have remained acquired") -bar = barrier(numtasks) -running = numtasks -for i in range(numtasks): - thread.start_new_thread(task2, (i,)) -done.acquire() -print('all tasks done') - -# not all platforms support changing thread stack size -print('\n*** Changing thread stack size ***') -if thread.stack_size() != 0: - raise ValueError("initial stack_size not 0") - -thread.stack_size(0) -if thread.stack_size() != 0: - raise ValueError("stack_size not reset to default") - -from os import name as os_name -if os_name in ("nt", "os2", "posix"): - - tss_supported = 1 - try: - thread.stack_size(4096) - except ValueError: - print('caught expected ValueError setting stack_size(4096)') - except thread.error: - tss_supported = 0 - print('platform does not support changing thread stack size') - - if tss_supported: - failed = lambda s, e: s != e - fail_msg = "stack_size(%d) failed - should succeed" - for tss in (262144, 0x100000, 0): - thread.stack_size(tss) - if failed(thread.stack_size(), tss): - raise ValueError(fail_msg % tss) - print('successfully set stack_size(%d)' % tss) - - for tss in (262144, 0x100000): - print('trying stack_size = %d' % tss) - next_ident = 0 - for i in range(numtasks): - newtask() - - print('waiting for all tasks to complete') - done.acquire() - print('all tasks done') - - # reset stack size to default - thread.stack_size(0) + self.checkout_mutex.release() + + +class BarrierTest(BasicThreadTest): + + def test_barrier(self): + self.bar = Barrier(NUMTASKS) + self.running = NUMTASKS + for i in range(NUMTASKS): + thread.start_new_thread(self.task2, (i,)) + verbose_print("waiting for tasks to end") + self.done_mutex.acquire() + verbose_print("tasks done") + + def task2(self, ident): + for i in range(NUMTRIPS): + if ident == 0: + # give it a good chance to enter the next + # barrier before the others are all out + # of the current one + delay = 0.001 + else: + with self.random_mutex: + delay = random.random() * NUMTASKS + verbose_print("task %s will run for %s" % (ident, round(delay, 1))) + time.sleep(delay) + verbose_print("task %s entering %s" % (ident, i)) + self.bar.enter() + verbose_print("task %s leaving barrier" % ident) + with self.running_mutex: + self.running -= 1 + # Must release mutex before releasing done, else the main thread can + # exit and set mutex to None as part of global teardown; then + # mutex.release() raises AttributeError. + finished = self.running == 0 + if finished: + self.done_mutex.release() + +def test_main(): + test_support.run_unittest(ThreadRunningTests, BarrierTest) + +if __name__ == "__main__": + test_main() diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py index e59d9c6..2ed723b 100644 --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -1,126 +1,501 @@ -"""Tests for the tokenize module. +doctests = """ +Tests for the tokenize module. -The tests were originally written in the old Python style, where the -test output was compared to a golden file. This docstring represents -the first steps towards rewriting the entire test as a doctest. + >>> import glob, random, sys -The tests can be really simple. Given a small fragment of source -code, print out a table with the tokens. The ENDMARK is omitted for +The tests can be really simple. Given a small fragment of source +code, print out a table with thokens. The ENDMARK is omitted for brevity. ->>> dump_tokens("1 + 1") -NUMBER '1' (1, 0) (1, 1) -OP '+' (1, 2) (1, 3) -NUMBER '1' (1, 4) (1, 5) - -A comment generates a token here, unlike in the parser module. The -comment token is followed by an NL or a NEWLINE token, depending on -whether the line contains the completion of a statement. - ->>> dump_tokens("if False:\\n" -... " # NL\\n" -... " a = False # NEWLINE\\n") -NAME 'if' (1, 0) (1, 2) -NAME 'False' (1, 3) (1, 8) -OP ':' (1, 8) (1, 9) -NEWLINE '\\n' (1, 9) (1, 10) -COMMENT '# NL' (2, 4) (2, 8) -NL '\\n' (2, 8) (2, 9) -INDENT ' ' (3, 0) (3, 4) -NAME 'a' (3, 4) (3, 5) -OP '=' (3, 9) (3, 10) -NAME 'False' (3, 11) (3, 16) -COMMENT '# NEWLINE' (3, 17) (3, 26) -NEWLINE '\\n' (3, 26) (3, 27) -DEDENT '' (4, 0) (4, 0) - -' # Emacs hint - -There will be a bunch more tests of specific source patterns. - -The tokenize module also defines an untokenize function that should -regenerate the original program text from the tokens. - -There are some standard formatting practices that are easy to get right. - ->>> roundtrip("if x == 1:\\n" -... " print(x)\\n") -if x == 1: - print(x) + >>> dump_tokens("1 + 1") + NUMBER '1' (1, 0) (1, 1) + OP '+' (1, 2) (1, 3) + NUMBER '1' (1, 4) (1, 5) + + >>> dump_tokens("if False:\\n" + ... " # NL\\n" + ... " True = False # NEWLINE\\n") + NAME 'if' (1, 0) (1, 2) + NAME 'False' (1, 3) (1, 8) + OP ':' (1, 8) (1, 9) + NEWLINE '\\n' (1, 9) (1, 10) + COMMENT '# NL' (2, 4) (2, 8) + NL '\\n' (2, 8) (2, 9) + INDENT ' ' (3, 0) (3, 4) + NAME 'True' (3, 4) (3, 8) + OP '=' (3, 9) (3, 10) + NAME 'False' (3, 11) (3, 16) + COMMENT '# NEWLINE' (3, 17) (3, 26) + NEWLINE '\\n' (3, 26) (3, 27) + DEDENT '' (4, 0) (4, 0) + + >>> indent_error_file = \""" + ... def k(x): + ... x += 2 + ... x += 5 + ... \""" + >>> for tok in generate_tokens(StringIO(indent_error_file).readline): pass + Traceback (most recent call last): + ... + IndentationError: unindent does not match any outer indentation level + +Test roundtrip for `untokenize`. `f` is an open file or a string. The source +code in f is tokenized, converted back to source code via tokenize.untokenize(), +and tokenized again from the latter. The test fails if the second tokenization +doesn't match the first. + + >>> def roundtrip(f): + ... if isinstance(f, str): f = StringIO(f) + ... token_list = list(generate_tokens(f.readline)) + ... f.close() + ... tokens1 = [tok[:2] for tok in token_list] + ... new_text = untokenize(tokens1) + ... readline = iter(new_text.splitlines(1)).__next__ + ... tokens2 = [tok[:2] for tok in generate_tokens(readline)] + ... return tokens1 == tokens2 + ... + +There are some standard formattig practises that are easy to get right. + + >>> roundtrip("if x == 1:\\n" + ... " print(x)\\n") + True + + >>> roundtrip("# This is a comment\\n# This also") + True Some people use different formatting conventions, which makes -untokenize a little trickier. Note that this test involves trailing -whitespace after the colon. Note that we use hex escapes to make the -two trailing blanks apparent in the expected output. - ->>> roundtrip("if x == 1 : \\n" -... " print(x)\\n") -if x == 1 :\x20\x20 - print(x) - -Comments need to go in the right place. - ->>> roundtrip("if x == 1:\\n" -... " # A comment by itself.\\n" -... " print(x) # Comment here, too.\\n" -... " # Another comment.\\n" -... "after_if = True\\n") -if x == 1: - # A comment by itself. - print(x) # Comment here, too. - # Another comment. -after_if = True - ->>> roundtrip("if (x # The comments need to go in the right place\\n" -... " == 1):\\n" -... " print('x == 1')\\n") -if (x # The comments need to go in the right place - == 1): - print('x == 1') - +untokenize a little trickier. Note that this test involves trailing +whitespace after the colon. Note that we use hex escapes to make the +two trailing blanks apperant in the expected output. + + >>> roundtrip("if x == 1 : \\n" + ... " print(x)\\n") + True + + >>> f = test_support.findfile("tokenize_tests.txt") + >>> roundtrip(open(f)) + True + + >>> roundtrip("if x == 1:\\n" + ... " # A comment by itself.\\n" + ... " print(x) # Comment here, too.\\n" + ... " # Another comment.\\n" + ... "after_if = True\\n") + True + + >>> roundtrip("if (x # The comments need to go in the right place\\n" + ... " == 1):\\n" + ... " print('x==1')\\n") + True + + >>> roundtrip("class Test: # A comment here\\n" + ... " # A comment with weird indent\\n" + ... " after_com = 5\\n" + ... " def x(m): return m*5 # a one liner\\n" + ... " def y(m): # A whitespace after the colon\\n" + ... " return y*4 # 3-space indent\\n") + True + +Some error-handling code + + >>> roundtrip("try: import somemodule\\n" + ... "except ImportError: # comment\\n" + ... " print 'Can not import' # comment2\\n" + ... "else: print 'Loaded'\\n") + True + +Balancing contunuation + + >>> roundtrip("a = (3,4, \\n" + ... "5,6)\\n" + ... "y = [3, 4,\\n" + ... "5]\\n" + ... "z = {'a': 5,\\n" + ... "'b':15, 'c':True}\\n" + ... "x = len(y) + 5 - a[\\n" + ... "3] - a[2]\\n" + ... "+ len(z) - z[\\n" + ... "'b']\\n") + True + +Ordinary integers and binary operators + + >>> dump_tokens("0xff <= 255") + NUMBER '0xff' (1, 0) (1, 4) + OP '<=' (1, 5) (1, 7) + NUMBER '255' (1, 8) (1, 11) + >>> dump_tokens("01234567 > ~0x15") + NUMBER '01234567' (1, 0) (1, 8) + OP '>' (1, 9) (1, 10) + OP '~' (1, 11) (1, 12) + NUMBER '0x15' (1, 12) (1, 16) + >>> dump_tokens("2134568 != 01231515") + NUMBER '2134568' (1, 0) (1, 7) + OP '!=' (1, 8) (1, 10) + NUMBER '01231515' (1, 11) (1, 19) + >>> dump_tokens("(-124561-1) & 0200000000") + OP '(' (1, 0) (1, 1) + OP '-' (1, 1) (1, 2) + NUMBER '124561' (1, 2) (1, 8) + OP '-' (1, 8) (1, 9) + NUMBER '1' (1, 9) (1, 10) + OP ')' (1, 10) (1, 11) + OP '&' (1, 12) (1, 13) + NUMBER '0200000000' (1, 14) (1, 24) + >>> dump_tokens("0xdeadbeef != -1") + NUMBER '0xdeadbeef' (1, 0) (1, 10) + OP '!=' (1, 11) (1, 13) + OP '-' (1, 14) (1, 15) + NUMBER '1' (1, 15) (1, 16) + >>> dump_tokens("0xdeadc0de & 012345") + NUMBER '0xdeadc0de' (1, 0) (1, 10) + OP '&' (1, 11) (1, 12) + NUMBER '012345' (1, 13) (1, 19) + >>> dump_tokens("0xFF & 0x15 | 1234") + NUMBER '0xFF' (1, 0) (1, 4) + OP '&' (1, 5) (1, 6) + NUMBER '0x15' (1, 7) (1, 11) + OP '|' (1, 12) (1, 13) + NUMBER '1234' (1, 14) (1, 18) + +Long integers + + >>> dump_tokens("x = 0L") + NAME 'x' (1, 0) (1, 1) + OP '=' (1, 2) (1, 3) + NUMBER '0L' (1, 4) (1, 6) + >>> dump_tokens("x = 0xfffffffffff") + NAME 'x' (1, 0) (1, 1) + OP '=' (1, 2) (1, 3) + NUMBER '0xffffffffff (1, 4) (1, 17) + >>> dump_tokens("x = 123141242151251616110l") + NAME 'x' (1, 0) (1, 1) + OP '=' (1, 2) (1, 3) + NUMBER '123141242151 (1, 4) (1, 26) + >>> dump_tokens("x = -15921590215012591L") + NAME 'x' (1, 0) (1, 1) + OP '=' (1, 2) (1, 3) + OP '-' (1, 4) (1, 5) + NUMBER '159215902150 (1, 5) (1, 23) + +Floating point numbers + + >>> dump_tokens("x = 3.14159") + NAME 'x' (1, 0) (1, 1) + OP '=' (1, 2) (1, 3) + NUMBER '3.14159' (1, 4) (1, 11) + >>> dump_tokens("x = 314159.") + NAME 'x' (1, 0) (1, 1) + OP '=' (1, 2) (1, 3) + NUMBER '314159.' (1, 4) (1, 11) + >>> dump_tokens("x = .314159") + NAME 'x' (1, 0) (1, 1) + OP '=' (1, 2) (1, 3) + NUMBER '.314159' (1, 4) (1, 11) + >>> dump_tokens("x = 3e14159") + NAME 'x' (1, 0) (1, 1) + OP '=' (1, 2) (1, 3) + NUMBER '3e14159' (1, 4) (1, 11) + >>> dump_tokens("x = 3E123") + NAME 'x' (1, 0) (1, 1) + OP '=' (1, 2) (1, 3) + NUMBER '3E123' (1, 4) (1, 9) + >>> dump_tokens("x+y = 3e-1230") + NAME 'x' (1, 0) (1, 1) + OP '+' (1, 1) (1, 2) + NAME 'y' (1, 2) (1, 3) + OP '=' (1, 4) (1, 5) + NUMBER '3e-1230' (1, 6) (1, 13) + >>> dump_tokens("x = 3.14e159") + NAME 'x' (1, 0) (1, 1) + OP '=' (1, 2) (1, 3) + NUMBER '3.14e159' (1, 4) (1, 12) + +String literals + + >>> dump_tokens("x = ''; y = \\\"\\\"") + NAME 'x' (1, 0) (1, 1) + OP '=' (1, 2) (1, 3) + STRING "''" (1, 4) (1, 6) + OP ';' (1, 6) (1, 7) + NAME 'y' (1, 8) (1, 9) + OP '=' (1, 10) (1, 11) + STRING '""' (1, 12) (1, 14) + >>> dump_tokens("x = '\\\"'; y = \\\"'\\\"") + NAME 'x' (1, 0) (1, 1) + OP '=' (1, 2) (1, 3) + STRING '\\'"\\'' (1, 4) (1, 7) + OP ';' (1, 7) (1, 8) + NAME 'y' (1, 9) (1, 10) + OP '=' (1, 11) (1, 12) + STRING '"\\'"' (1, 13) (1, 16) + >>> dump_tokens("x = \\\"doesn't \\\"shrink\\\", does it\\\"") + NAME 'x' (1, 0) (1, 1) + OP '=' (1, 2) (1, 3) + STRING '"doesn\\'t "' (1, 4) (1, 14) + NAME 'shrink' (1, 14) (1, 20) + STRING '", does it"' (1, 20) (1, 31) + >>> dump_tokens("x = u'abc' + U'ABC'") + NAME 'x' (1, 0) (1, 1) + OP '=' (1, 2) (1, 3) + STRING "u'abc'" (1, 4) (1, 10) + OP '+' (1, 11) (1, 12) + STRING "U'ABC'" (1, 13) (1, 19) + >>> dump_tokens('y = "ABC" + "ABC"') + NAME 'y' (1, 0) (1, 1) + OP '=' (1, 2) (1, 3) + STRING '"ABC"' (1, 4) (1, 10) + OP '+' (1, 11) (1, 12) + STRING '"ABC"' (1, 13) (1, 19) + >>> dump_tokens("x = r'abc' + r'ABC' + R'ABC' + R'ABC'") + NAME 'x' (1, 0) (1, 1) + OP '=' (1, 2) (1, 3) + STRING "r'abc'" (1, 4) (1, 11) + OP '+' (1, 12) (1, 13) + STRING "r'ABC'" (1, 14) (1, 21) + OP '+' (1, 22) (1, 23) + STRING "R'ABC'" (1, 24) (1, 31) + OP '+' (1, 32) (1, 33) + STRING "R'ABC'" (1, 34) (1, 41) + >>> dump_tokens('y = r"abc" + r"ABC" + R"ABC" + R"ABC"') + NAME 'y' (1, 0) (1, 1) + OP '=' (1, 2) (1, 3) + STRING 'r"abc"' (1, 4) (1, 11) + OP '+' (1, 12) (1, 13) + STRING 'r"ABC"' (1, 14) (1, 21) + OP '+' (1, 22) (1, 23) + STRING 'R"ABC"' (1, 24) (1, 31) + OP '+' (1, 32) (1, 33) + STRING 'R"ABC"' (1, 34) (1, 41) + +Operators + + >>> dump_tokens("def d22(a, b, c=2, d=2, *k): pass") + NAME 'def' (1, 0) (1, 3) + NAME 'd22' (1, 4) (1, 7) + OP '(' (1, 7) (1, 8) + NAME 'a' (1, 8) (1, 9) + OP ',' (1, 9) (1, 10) + NAME 'b' (1, 11) (1, 12) + OP ',' (1, 12) (1, 13) + NAME 'c' (1, 14) (1, 15) + OP '=' (1, 15) (1, 16) + NUMBER '2' (1, 16) (1, 17) + OP ',' (1, 17) (1, 18) + NAME 'd' (1, 19) (1, 20) + OP '=' (1, 20) (1, 21) + NUMBER '2' (1, 21) (1, 22) + OP ',' (1, 22) (1, 23) + OP '*' (1, 24) (1, 25) + NAME 'k' (1, 25) (1, 26) + OP ')' (1, 26) (1, 27) + OP ':' (1, 27) (1, 28) + NAME 'pass' (1, 29) (1, 33) + >>> dump_tokens("def d01v_(a=1, *k, **w): pass") + NAME 'def' (1, 0) (1, 3) + NAME 'd01v_' (1, 4) (1, 9) + OP '(' (1, 9) (1, 10) + NAME 'a' (1, 10) (1, 11) + OP '=' (1, 11) (1, 12) + NUMBER '1' (1, 12) (1, 13) + OP ',' (1, 13) (1, 14) + OP '*' (1, 15) (1, 16) + NAME 'k' (1, 16) (1, 17) + OP ',' (1, 17) (1, 18) + OP '**' (1, 19) (1, 21) + NAME 'w' (1, 21) (1, 22) + OP ')' (1, 22) (1, 23) + OP ':' (1, 23) (1, 24) + NAME 'pass' (1, 25) (1, 29) + +Comparison + + >>> dump_tokens("if 1 < 1 > 1 == 1 >= 5 <= 0x15 <= 0x12 != " + + ... "1 and 5 in 1 not in 1 is 1 or 5 is not 1: pass") + NAME 'if' (1, 0) (1, 2) + NUMBER '1' (1, 3) (1, 4) + OP '<' (1, 5) (1, 6) + NUMBER '1' (1, 7) (1, 8) + OP '>' (1, 9) (1, 10) + NUMBER '1' (1, 11) (1, 12) + OP '==' (1, 13) (1, 15) + NUMBER '1' (1, 16) (1, 17) + OP '>=' (1, 18) (1, 20) + NUMBER '5' (1, 21) (1, 22) + OP '<=' (1, 23) (1, 25) + NUMBER '0x15' (1, 26) (1, 30) + OP '<=' (1, 31) (1, 33) + NUMBER '0x12' (1, 34) (1, 38) + OP '!=' (1, 39) (1, 41) + NUMBER '1' (1, 42) (1, 43) + NAME 'and' (1, 44) (1, 47) + NUMBER '5' (1, 48) (1, 49) + NAME 'in' (1, 50) (1, 52) + NUMBER '1' (1, 53) (1, 54) + NAME 'not' (1, 55) (1, 58) + NAME 'in' (1, 59) (1, 61) + NUMBER '1' (1, 62) (1, 63) + NAME 'is' (1, 64) (1, 66) + NUMBER '1' (1, 67) (1, 68) + NAME 'or' (1, 69) (1, 71) + NUMBER '5' (1, 72) (1, 73) + NAME 'is' (1, 74) (1, 76) + NAME 'not' (1, 77) (1, 80) + NUMBER '1' (1, 81) (1, 82) + OP ':' (1, 82) (1, 83) + NAME 'pass' (1, 84) (1, 88) + +Shift + + >>> dump_tokens("x = 1 << 1 >> 5") + NAME 'x' (1, 0) (1, 1) + OP '=' (1, 2) (1, 3) + NUMBER '1' (1, 4) (1, 5) + OP '<<' (1, 6) (1, 8) + NUMBER '1' (1, 9) (1, 10) + OP '>>' (1, 11) (1, 13) + NUMBER '5' (1, 14) (1, 15) + +Additive + + >>> dump_tokens("x = 1 - y + 15 - 01 + 0x124 + z + a[5]") + NAME 'x' (1, 0) (1, 1) + OP '=' (1, 2) (1, 3) + NUMBER '1' (1, 4) (1, 5) + OP '-' (1, 6) (1, 7) + NAME 'y' (1, 8) (1, 9) + OP '+' (1, 10) (1, 11) + NUMBER '15' (1, 12) (1, 14) + OP '-' (1, 15) (1, 16) + NUMBER '01' (1, 17) (1, 19) + OP '+' (1, 20) (1, 21) + NUMBER '0x124' (1, 22) (1, 27) + OP '+' (1, 28) (1, 29) + NAME 'z' (1, 30) (1, 31) + OP '+' (1, 32) (1, 33) + NAME 'a' (1, 34) (1, 35) + OP '[' (1, 35) (1, 36) + NUMBER '5' (1, 36) (1, 37) + OP ']' (1, 37) (1, 38) + +Multiplicative + + >>> dump_tokens("x = 1//1*1/5*12%0x12") + NAME 'x' (1, 0) (1, 1) + OP '=' (1, 2) (1, 3) + NUMBER '1' (1, 4) (1, 5) + OP '//' (1, 5) (1, 7) + NUMBER '1' (1, 7) (1, 8) + OP '*' (1, 8) (1, 9) + NUMBER '1' (1, 9) (1, 10) + OP '/' (1, 10) (1, 11) + NUMBER '5' (1, 11) (1, 12) + OP '*' (1, 12) (1, 13) + NUMBER '12' (1, 13) (1, 15) + OP '%' (1, 15) (1, 16) + NUMBER '0x12' (1, 16) (1, 20) + +Unary + + >>> dump_tokens("~1 ^ 1 & 1 |1 ^ -1") + OP '~' (1, 0) (1, 1) + NUMBER '1' (1, 1) (1, 2) + OP '^' (1, 3) (1, 4) + NUMBER '1' (1, 5) (1, 6) + OP '&' (1, 7) (1, 8) + NUMBER '1' (1, 9) (1, 10) + OP '|' (1, 11) (1, 12) + NUMBER '1' (1, 12) (1, 13) + OP '^' (1, 14) (1, 15) + OP '-' (1, 16) (1, 17) + NUMBER '1' (1, 17) (1, 18) + >>> dump_tokens("-1*1/1+1*1//1 - ---1**1") + OP '-' (1, 0) (1, 1) + NUMBER '1' (1, 1) (1, 2) + OP '*' (1, 2) (1, 3) + NUMBER '1' (1, 3) (1, 4) + OP '/' (1, 4) (1, 5) + NUMBER '1' (1, 5) (1, 6) + OP '+' (1, 6) (1, 7) + NUMBER '1' (1, 7) (1, 8) + OP '*' (1, 8) (1, 9) + NUMBER '1' (1, 9) (1, 10) + OP '//' (1, 10) (1, 12) + NUMBER '1' (1, 12) (1, 13) + OP '-' (1, 14) (1, 15) + OP '-' (1, 16) (1, 17) + OP '-' (1, 17) (1, 18) + OP '-' (1, 18) (1, 19) + NUMBER '1' (1, 19) (1, 20) + OP '**' (1, 20) (1, 22) + NUMBER '1' (1, 22) (1, 23) + +Selector + + >>> dump_tokens("import sys, time\\nx = sys.modules['time'].time()") + NAME 'import' (1, 0) (1, 6) + NAME 'sys' (1, 7) (1, 10) + OP ',' (1, 10) (1, 11) + NAME 'time' (1, 12) (1, 16) + NEWLINE '\\n' (1, 16) (1, 17) + NAME 'x' (2, 0) (2, 1) + OP '=' (2, 2) (2, 3) + NAME 'sys' (2, 4) (2, 7) + OP '.' (2, 7) (2, 8) + NAME 'modules' (2, 8) (2, 15) + OP '[' (2, 15) (2, 16) + STRING "'time'" (2, 16) (2, 22) + OP ']' (2, 22) (2, 23) + OP '.' (2, 23) (2, 24) + NAME 'time' (2, 24) (2, 28) + OP '(' (2, 28) (2, 29) + OP ')' (2, 29) (2, 30) + +Methods + + >>> dump_tokens("@staticmethod\\ndef foo(x,y): pass") + OP '@' (1, 0) (1, 1) + NAME 'staticmethod (1, 1) (1, 13) + NEWLINE '\\n' (1, 13) (1, 14) + NAME 'def' (2, 0) (2, 3) + NAME 'foo' (2, 4) (2, 7) + OP '(' (2, 7) (2, 8) + NAME 'x' (2, 8) (2, 9) + OP ',' (2, 9) (2, 10) + NAME 'y' (2, 10) (2, 11) + OP ')' (2, 11) (2, 12) + OP ':' (2, 12) (2, 13) + NAME 'pass' (2, 14) (2, 18) + +Backslash means line continuation, except for comments + + >>> roundtrip("x=1+\\\\n" + ... "1\\n" + ... "# This is a comment\\\\n" + ... "# This also\\n") + True + >>> roundtrip("# Comment \\\\nx = 0") + True + + >>> + >>> tempdir = os.path.dirname(f) or os.curdir + >>> testfiles = glob.glob(os.path.join(tempdir, "test*.py")) + >>> if not test_support.is_resource_enabled("compiler"): + ... testfiles = random.sample(testfiles, 10) + ... + >>> for testfile in testfiles: + ... if not roundtrip(open(testfile)): break + ... else: True + True """ -# ' Emacs hint -import os, glob, random, time, sys -import re +from test import test_support +from tokenize import (tokenize, untokenize, generate_tokens, NUMBER, NAME, OP, + STRING, ENDMARKER, tok_name) from io import StringIO -from test.test_support import (verbose, findfile, is_resource_enabled, - TestFailed) -from tokenize import (tokenize, generate_tokens, untokenize, tok_name, - ENDMARKER, NUMBER, NAME, OP, STRING, COMMENT) - -# How much time in seconds can pass before we print a 'Still working' message. -_PRINT_WORKING_MSG_INTERVAL = 5 * 60 - -# Test roundtrip for `untokenize`. `f` is a file path. The source code in f -# is tokenized, converted back to source code via tokenize.untokenize(), -# and tokenized again from the latter. The test fails if the second -# tokenization doesn't match the first. -def test_roundtrip(f): - ## print('Testing:', f) - # Get the encoding first - fobj = open(f, encoding="latin-1") - first2lines = fobj.readline() + fobj.readline() - fobj.close() - m = re.search(r"coding:\s*(\S+)", first2lines) - if m: - encoding = m.group(1) - ## print(" coding:", encoding) - else: - encoding = "utf-8" - fobj = open(f, encoding=encoding) - try: - fulltok = list(generate_tokens(fobj.readline)) - finally: - fobj.close() - - t1 = [tok[:2] for tok in fulltok] - newtext = untokenize(t1) - readline = iter(newtext.splitlines(1)).__next__ - t2 = [tok[:2] for tok in generate_tokens(readline)] - if t1 != t2: - raise TestFailed("untokenize() roundtrip failed for %r" % f) +import os def dump_tokens(s): """Print out the tokens in s in a table format. @@ -132,7 +507,7 @@ def dump_tokens(s): if type == ENDMARKER: break type = tok_name[type] - print("%(type)-10.10s %(token)-13.13r %(start)s %(end)s" % locals()) + print("%(type)-10.10s %(token)-13.13r %(start)s %(end)s" % locals()) def roundtrip(s): f = StringIO(s) @@ -177,82 +552,12 @@ def decistmt(s): result.append((toknum, tokval)) return untokenize(result) -def test_main(): - if verbose: - print('starting...') - - next_time = time.time() + _PRINT_WORKING_MSG_INTERVAL - - # Validate the tokenize_tests.txt file. - # This makes sure it compiles, and displays any errors in it. - f = open(findfile('tokenize_tests.txt')) - sf = f.read() - f.close() - cf = compile(sf, 'tokenize_tests.txt', 'exec') - - # This displays the tokenization of tokenize_tests.py to stdout, and - # regrtest.py checks that this equals the expected output (in the - # test/output/ directory). - f = open(findfile('tokenize_tests.txt')) - tokenize(f.readline) - f.close() - - # Now run test_roundtrip() over test_tokenize.py too, and over all - # (if the "compiler" resource is enabled) or a small random sample (if - # "compiler" is not enabled) of the test*.py files. - f = findfile('test_tokenize.py') - if verbose: - print(' round trip: ', f, file=sys.__stdout__) - test_roundtrip(f) - - testdir = os.path.dirname(f) or os.curdir - testfiles = glob.glob(testdir + os.sep + 'test*.py') - if not is_resource_enabled('compiler'): - testfiles = random.sample(testfiles, 10) - - for f in testfiles: - # Print still working message since this test can be really slow - if verbose: - print(' round trip: ', f, file=sys.__stdout__) - if next_time <= time.time(): - next_time = time.time() + _PRINT_WORKING_MSG_INTERVAL - print(' test_main still working, be patient...', file=sys.__stdout__) - sys.__stdout__.flush() - - test_roundtrip(f) - - # Test detecton of IndentationError. - sampleBadText = """\ -def foo(): - bar - baz -""" - - try: - for tok in generate_tokens(StringIO(sampleBadText).readline): - pass - except IndentationError: - pass - else: - raise TestFailed("Did not detect IndentationError:") - - # Run the doctests in this module. - from test import test_tokenize # i.e., this module - from test.test_support import run_doctest - run_doctest(test_tokenize, verbose) - if verbose: - print('finished') +__test__ = {"doctests" : doctests, 'decistmt': decistmt} -def test_rarrow(): - """ - This function exists solely to test the tokenization of the RARROW - operator. - - >>> tokenize(iter(['->']).__next__) #doctest: +NORMALIZE_WHITESPACE - 1,0-1,2:\tOP\t'->' - 2,0-2,0:\tENDMARKER\t'' - """ +def test_main(): + from test import test_tokenize + test_support.run_doctest(test_tokenize, True) if __name__ == "__main__": test_main() diff --git a/Lib/test/test_winsound.py b/Lib/test/test_winsound.py index 32b49d3..0d6ddf9 100644 --- a/Lib/test/test_winsound.py +++ b/Lib/test/test_winsound.py @@ -9,6 +9,13 @@ import subprocess class BeepTest(unittest.TestCase): + # As with PlaySoundTest, incorporate the _have_soundcard() check + # into our test methods. If there's no audio device present, + # winsound.Beep returns 0 and GetLastError() returns 127, which + # is: ERROR_PROC_NOT_FOUND ("The specified procedure could not + # be found"). (FWIW, virtual/Hyper-V systems fall under this + # scenario as they have no sound devices whatsoever (not even + # a legacy Beep device).) def test_errors(self): self.assertRaises(TypeError, winsound.Beep) @@ -16,12 +23,17 @@ class BeepTest(unittest.TestCase): self.assertRaises(ValueError, winsound.Beep, 32768, 75) def test_extremes(self): - winsound.Beep(37, 75) - winsound.Beep(32767, 75) + if _have_soundcard(): + winsound.Beep(37, 75) + winsound.Beep(32767, 75) + else: + self.assertRaises(RuntimeError, winsound.Beep, 37, 75) + self.assertRaises(RuntimeError, winsound.Beep, 32767, 75) def test_increasingfrequency(self): - for i in range(100, 2000, 100): - winsound.Beep(i, 75) + if _have_soundcard(): + for i in range(100, 2000, 100): + winsound.Beep(i, 75) class MessageBeepTest(unittest.TestCase): |