Mercurial > ~astiob > upreckon > hgweb
comparison 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 |
comparison
equal
deleted
inserted
replaced
24:c23d81f4a1a3 | 25:b500e117080e |
---|---|
23 # but in Python 2.5, the abc module does not exist, while in Python 3, | 23 # but in Python 2.5, the abc module does not exist, while in Python 3, |
24 # metaclasses are specified using a syntax totally incompatible | 24 # metaclasses are specified using a syntax totally incompatible |
25 # with Python 2 and not usable conditionally via exec() and such | 25 # with Python 2 and not usable conditionally via exec() and such |
26 # because it is a detail of the syntax of the class statement itself. | 26 # because it is a detail of the syntax of the class statement itself. |
27 | 27 |
28 __all__ = ('say', 'basestring', 'range', 'map', 'zip', 'filter', | 28 import __builtin__ |
29 'items', 'keys', 'values', 'ABCMeta', 'abstractmethod') | 29 |
30 __all__ = ('say', 'basestring', 'range', 'map', 'zip', 'filter', 'items', | |
31 'keys', 'values', 'zip_longest', 'callable', | |
32 'ABCMeta', 'abstractmethod', 'CompatBuiltins') | |
30 | 33 |
31 try: | 34 try: |
32 # Python 3 | 35 # Python 3 |
33 exec('say = print') | 36 exec('say = print') |
34 except SyntaxError: | 37 except SyntaxError: |
86 range = xrange | 89 range = xrange |
87 except NameError: | 90 except NameError: |
88 range = range | 91 range = range |
89 | 92 |
90 try: | 93 try: |
94 callable = callable | |
95 except NameError: | |
96 callable = lambda obj: hasattr(obj, '__call__') | |
97 | |
98 try: | |
91 from itertools import imap as map | 99 from itertools import imap as map |
92 except ImportError: | 100 except ImportError: |
93 map = map | 101 map = map |
94 | 102 |
95 try: | 103 try: |
104 | 112 |
105 items = dict.iteritems if hasattr(dict, 'iteritems') else dict.items | 113 items = dict.iteritems if hasattr(dict, 'iteritems') else dict.items |
106 keys = dict.iterkeys if hasattr(dict, 'iterkeys') else dict.keys | 114 keys = dict.iterkeys if hasattr(dict, 'iterkeys') else dict.keys |
107 values = dict.itervalues if hasattr(dict, 'itervalues') else dict.values | 115 values = dict.itervalues if hasattr(dict, 'itervalues') else dict.values |
108 | 116 |
109 for name in __all__: | 117 try: |
110 __builtins__[name] = globals()[name] | 118 # Python 3 |
119 from itertools import zip_longest | |
120 except ImportError: | |
121 # Python 2.6/2.7 | |
122 from itertools import izip_longest as zip_longest | |
123 except ImportError: | |
124 # Python 2.5 | |
125 from itertools import chain, repeat | |
126 # Adapted from the documentation of itertools.izip_longest | |
127 def zip_longest(*args, **kwargs): | |
128 fillvalue = kwargs.get('fillvalue') | |
129 def sentinel(counter=([fillvalue]*(len(args)-1)).pop): | |
130 yield counter() | |
131 fillers = repeat(fillvalue) | |
132 iters = [chain(it, sentinel(), fillers) for it in args] | |
133 try: | |
134 for tup in zip(*iters): | |
135 yield tup | |
136 except IndexError: | |
137 pass | |
138 | |
139 # Automatically import * from this module into testconf.py's | |
140 class CompatBuiltins(object): | |
141 __slots__ = 'originals' | |
142 def __init__(self): | |
143 self.originals = {} | |
144 def __enter__(self): | |
145 g = globals() | |
146 for name in __all__: | |
147 if hasattr(__builtin__, name): | |
148 self.originals[name] = getattr(__builtin__, name) | |
149 setattr(__builtin__, name, g[name]) | |
150 def __exit__(self, exc_type, exc_val, exc_tb): | |
151 for name in self.originals: | |
152 setattr(__builtin__, name, self.originals[name]) | |
111 | 153 |
112 # Support simple testconf.py's written for test.py 1.x | 154 # Support simple testconf.py's written for test.py 1.x |
113 __builtins__['xrange'] = range | 155 __builtin__.xrange = range |