diff 2.00/compat.py @ 25:b500e117080e

Bug fixes and overhead reduction Added the --problem/-p option. (WARNING: not the same as the -p option of test.py 1.x.) The problem names supplied are not validated. Added zip_longest to compat.py. Experimental: problem names are now _always_ printed for multi-problem sets. Overhead: Escape presses are now checked only once every .15 seconds (at least kbhit() on Windows is very slow). Overhead: sleep(0) is now called in the time-control-and-Escape-watching loop (at least on Windows, it immediately transfers control to some waiting thread). Bug fix: compat.py now overwrites built-ins only while including testconfs (--help was broken in Python 2). Bug fix: ReadDeleting in config.py now closes the file it opens (especially important on Windows, where open files cannot be deleted). Bug fix: added callable to compat.py (it is absent from Python 3). Bug fix: the default (built-in) output validator now properly handles unwanted trailing data. Bug fix: testconfs in custom archives no more raise NameError. Bug fix: if a validator program cannot be launched, CannotStartValidator is now raised instead of the fatal OSError.
author Oleg Oshmyan <chortos@inbox.lv>
date Thu, 23 Sep 2010 23:05:58 +0000
parents f07b7a431ea6
children dc4be35d17e0
line wrap: on
line diff
--- a/2.00/compat.py	Thu Sep 23 00:11:24 2010 +0000
+++ b/2.00/compat.py	Thu Sep 23 23:05:58 2010 +0000
@@ -25,8 +25,11 @@
 #   with Python 2 and not usable conditionally via exec() and such
 #   because it is a detail of the syntax of the class statement itself.
 
-__all__ = ('say', 'basestring', 'range', 'map', 'zip', 'filter',
-           'items', 'keys', 'values', 'ABCMeta', 'abstractmethod')
+import __builtin__
+
+__all__ = ('say', 'basestring', 'range', 'map', 'zip', 'filter', 'items',
+           'keys', 'values', 'zip_longest', 'callable',
+           'ABCMeta', 'abstractmethod', 'CompatBuiltins')
 
 try:
 	# Python 3
@@ -88,6 +91,11 @@
 	range = range
 
 try:
+	callable = callable
+except NameError:
+	callable = lambda obj: hasattr(obj, '__call__')
+
+try:
 	from itertools import imap as map
 except ImportError:
 	map = map
@@ -106,8 +114,42 @@
 keys = dict.iterkeys if hasattr(dict, 'iterkeys') else dict.keys
 values = dict.itervalues if hasattr(dict, 'itervalues') else dict.values
 
-for name in __all__:
-	__builtins__[name] = globals()[name]
+try:
+	# Python 3
+	from itertools import zip_longest
+except ImportError:
+	# Python 2.6/2.7
+	from itertools import izip_longest as zip_longest
+except ImportError:
+	# Python 2.5
+	from itertools import chain, repeat
+	# Adapted from the documentation of itertools.izip_longest
+	def zip_longest(*args, **kwargs):
+		fillvalue = kwargs.get('fillvalue')
+		def sentinel(counter=([fillvalue]*(len(args)-1)).pop):
+			yield counter()
+		fillers = repeat(fillvalue)
+		iters = [chain(it, sentinel(), fillers) for it in args]
+		try:
+			for tup in zip(*iters):
+				yield tup
+		except IndexError:
+			pass
+
+# Automatically import * from this module into testconf.py's
+class CompatBuiltins(object):
+	__slots__ = 'originals'
+	def __init__(self):
+		self.originals = {}
+	def __enter__(self):
+		g = globals()
+		for name in __all__:
+			if hasattr(__builtin__, name):
+				self.originals[name] = getattr(__builtin__, name)
+			setattr(__builtin__, name, g[name])
+	def __exit__(self, exc_type, exc_val, exc_tb):
+		for name in self.originals:
+			setattr(__builtin__, name, self.originals[name])
 
 # Support simple testconf.py's written for test.py 1.x
-__builtins__['xrange'] = range
\ No newline at end of file
+__builtin__.xrange = range
\ No newline at end of file