Mercurial > ~astiob > upreckon > hgweb
annotate 2.00/compat.py @ 40:af9c45708987
Cemented a decision previously being unsure about
The mere presense of the tasknames configuration variable now always makes problem names to be printed.
This is not new, but the old behaviour (only printing names if we test more than one problem), previously commented out, has now been removed altogether.
author | Oleg Oshmyan <chortos@inbox.lv> |
---|---|
date | Sun, 05 Dec 2010 14:34:24 +0100 |
parents | 23aa8da5be5f |
children |
rev | line source |
---|---|
21 | 1 #! /usr/bin/env python |
16 | 2 # Copyright (c) 2010 Chortos-2 <chortos@inbox.lv> |
3 | |
21 | 4 # A compatibility layer for Python 2.5+. This is what lets test.py |
5 # run on all versions of Python starting with 2.5, including Python 3. | |
6 | |
7 # A few notes regarding some compatibility-driven peculiarities | |
8 # in the use of the language that can be seen in all modules: | |
9 # | |
10 # * Except statements never specify target; instead, when needed, | |
11 # the exception is taken from sys.exc_info(). Blame the incompatible | |
12 # syntaxes of the except clause in Python 2.5 and Python 3 and the lack | |
13 # of preprocessor macros in Python of any version ;P. | |
14 # | |
15 # * Keyword-only parameters are never used, even for parameters | |
16 # that should never be given in as arguments. The reason is | |
17 # the laziness of some Python developers who have failed to finish | |
18 # implementing them in Python 2 even though they had several years | |
19 # of time and multiple version releases to sneak them in. | |
20 # | |
21 # * Abstract classes are only implemented for Python 2.6 and 2.7. | |
22 # ABC's require the abc module and the specification of metaclasses, | |
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 | |
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. | |
27 | |
27 | 28 try: |
29 import builtins | |
30 except ImportError: | |
31 import __builtin__ as builtins | |
25
b500e117080e
Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents:
22
diff
changeset
|
32 |
b500e117080e
Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents:
22
diff
changeset
|
33 __all__ = ('say', 'basestring', 'range', 'map', 'zip', 'filter', 'items', |
b500e117080e
Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents:
22
diff
changeset
|
34 'keys', 'values', 'zip_longest', 'callable', |
b500e117080e
Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents:
22
diff
changeset
|
35 'ABCMeta', 'abstractmethod', 'CompatBuiltins') |
21 | 36 |
16 | 37 try: |
38 # Python 3 | |
39 exec('say = print') | |
40 except SyntaxError: | |
41 try: | |
42 # Python 2.6/2.7 | |
21 | 43 # An alternative is exec('from __future__ import print_function; say = print'); |
44 # if problems arise with the current line, one should try replacing it | |
45 # with this one with the future import before abandoning the idea altogether | |
27 | 46 say = getattr(builtins, 'print') |
16 | 47 except Exception: |
48 # Python 2.5 | |
49 import sys | |
50 # This should fully emulate the print function of Python 2.6 in Python 2.3+ | |
21 | 51 # The error messages are taken from Python 2.6 |
52 # The name bindings at the bottom of this file are in effect | |
16 | 53 def saytypeerror(value, name): |
21 | 54 return TypeError(' '.join((name, 'must be None, str or unicode, not', type(value).__name__))) |
16 | 55 def say(*values, **kwargs): |
56 sep = kwargs.pop('sep' , None) | |
57 end = kwargs.pop('end' , None) | |
58 file = kwargs.pop('file', None) | |
59 if kwargs: raise TypeError("'%s' is an invalid keyword argument for this function" % kwargs.popitem()[0]) | |
60 if sep is None: sep = ' ' | |
61 if end is None: end = '\n' | |
62 if file is None: file = sys.stdout | |
63 if not isinstance(sep, basestring): raise saytypeerror(sep, 'sep') | |
64 if not isinstance(end, basestring): raise saytypeerror(end, 'end') | |
21 | 65 file.write(sep.join(map(str, values)) + end) |
16 | 66 |
34
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
67 try: |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
68 from os.path import relpath |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
69 except ImportError: |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
70 # Python 2.5 |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
71 import os.path as _path |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
72 |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
73 # Adapted from Python 2.7.1 |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
74 |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
75 if hasattr(_path, 'splitunc'): |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
76 def _abspath_split(path): |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
77 abs = _path.abspath(_path.normpath(path)) |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
78 prefix, rest = _path.splitunc(abs) |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
79 is_unc = bool(prefix) |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
80 if not is_unc: |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
81 prefix, rest = _path.splitdrive(abs) |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
82 return is_unc, prefix, [x for x in rest.split(_path.sep) if x] |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
83 else: |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
84 def _abspath_split(path): |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
85 prefix, rest = _path.splitdrive(_path.abspath(_path.normpath(path))) |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
86 return False, prefix, [x for x in rest.split(_path.sep) if x] |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
87 |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
88 def relpath(path, start=_path.curdir): |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
89 """Return a relative version of a path""" |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
90 |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
91 if not path: |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
92 raise ValueError("no path specified") |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
93 |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
94 start_is_unc, start_prefix, start_list = _abspath_split(start) |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
95 path_is_unc, path_prefix, path_list = _abspath_split(path) |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
96 |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
97 if path_is_unc ^ start_is_unc: |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
98 raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)" |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
99 % (path, start)) |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
100 if path_prefix.lower() != start_prefix.lower(): |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
101 if path_is_unc: |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
102 raise ValueError("path is on UNC root %s, start on UNC root %s" |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
103 % (path_prefix, start_prefix)) |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
104 else: |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
105 raise ValueError("path is on drive %s, start on drive %s" |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
106 % (path_prefix, start_prefix)) |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
107 # Work out how much of the filepath is shared by start and path. |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
108 i = 0 |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
109 for e1, e2 in zip(start_list, path_list): |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
110 if e1.lower() != e2.lower(): |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
111 break |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
112 i += 1 |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
113 |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
114 rel_list = [_path.pardir] * (len(start_list)-i) + path_list[i:] |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
115 if not rel_list: |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
116 return _path.curdir |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
117 return _path.join(*rel_list) |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
118 |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
119 _path.relpath = relpath |
8fec38b0dd6e
A os.path.relpath implementation for Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
31
diff
changeset
|
120 |
16 | 121 def import_urllib(): |
122 try: | |
123 # Python 3 | |
124 import urllib.request | |
125 return urllib.request, lambda url: urllib.request.urlopen(url).read().decode() | |
126 except ImportError: | |
127 # Python 2 | |
128 import urllib | |
21 | 129 return urllib, lambda url: urllib.urlopen(url).read() |
130 | |
131 try: | |
132 from abc import ABCMeta, abstractmethod | |
133 except ImportError: | |
134 ABCMeta, abstractmethod = None, lambda x: x | |
135 | |
136 # In all of the following, the try clause is for Python 2 and the except | |
137 # clause is for Python 3. More checks are performed than needed | |
138 # for standard builds of Python to ensure as much as possible works | |
139 # on custom builds. | |
140 try: | |
141 basestring = basestring | |
142 except NameError: | |
143 basestring = str | |
144 | |
145 try: | |
146 range = xrange | |
147 except NameError: | |
148 range = range | |
149 | |
150 try: | |
25
b500e117080e
Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents:
22
diff
changeset
|
151 callable = callable |
b500e117080e
Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents:
22
diff
changeset
|
152 except NameError: |
b500e117080e
Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents:
22
diff
changeset
|
153 callable = lambda obj: hasattr(obj, '__call__') |
b500e117080e
Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents:
22
diff
changeset
|
154 |
b500e117080e
Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents:
22
diff
changeset
|
155 try: |
35
23aa8da5be5f
compat.py now emulates the next() built-in in Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
34
diff
changeset
|
156 next = next |
23aa8da5be5f
compat.py now emulates the next() built-in in Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
34
diff
changeset
|
157 except NameError: |
23aa8da5be5f
compat.py now emulates the next() built-in in Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
34
diff
changeset
|
158 next = lambda obj: obj.next() |
23aa8da5be5f
compat.py now emulates the next() built-in in Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
34
diff
changeset
|
159 |
23aa8da5be5f
compat.py now emulates the next() built-in in Python 2.5
Oleg Oshmyan <chortos@inbox.lv>
parents:
34
diff
changeset
|
160 try: |
21 | 161 from itertools import imap as map |
162 except ImportError: | |
163 map = map | |
164 | |
165 try: | |
166 from itertools import izip as zip | |
167 except ImportError: | |
168 zip = zip | |
169 | |
170 try: | |
171 from itertools import ifilter as filter | |
172 except ImportError: | |
173 filter = filter | |
174 | |
175 items = dict.iteritems if hasattr(dict, 'iteritems') else dict.items | |
176 keys = dict.iterkeys if hasattr(dict, 'iterkeys') else dict.keys | |
177 values = dict.itervalues if hasattr(dict, 'itervalues') else dict.values | |
178 | |
25
b500e117080e
Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents:
22
diff
changeset
|
179 try: |
b500e117080e
Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents:
22
diff
changeset
|
180 # Python 3 |
b500e117080e
Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents:
22
diff
changeset
|
181 from itertools import zip_longest |
b500e117080e
Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents:
22
diff
changeset
|
182 except ImportError: |
31 | 183 try: |
184 # Python 2.6/2.7 | |
185 from itertools import izip_longest as zip_longest | |
186 except ImportError: | |
187 # Python 2.5 | |
188 from itertools import chain, repeat | |
189 # Adapted from the documentation of itertools.izip_longest | |
190 def zip_longest(*args, **kwargs): | |
191 fillvalue = kwargs.get('fillvalue') | |
192 def sentinel(counter=([fillvalue]*(len(args)-1)).pop): | |
193 yield counter() | |
194 fillers = repeat(fillvalue) | |
195 iters = [chain(it, sentinel(), fillers) for it in args] | |
196 try: | |
197 for tup in zip(*iters): | |
198 yield tup | |
199 except IndexError: | |
200 pass | |
25
b500e117080e
Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents:
22
diff
changeset
|
201 |
b500e117080e
Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents:
22
diff
changeset
|
202 # Automatically import * from this module into testconf.py's |
b500e117080e
Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents:
22
diff
changeset
|
203 class CompatBuiltins(object): |
b500e117080e
Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents:
22
diff
changeset
|
204 __slots__ = 'originals' |
b500e117080e
Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents:
22
diff
changeset
|
205 def __init__(self): |
b500e117080e
Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents:
22
diff
changeset
|
206 self.originals = {} |
b500e117080e
Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents:
22
diff
changeset
|
207 def __enter__(self): |
b500e117080e
Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents:
22
diff
changeset
|
208 g = globals() |
b500e117080e
Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents:
22
diff
changeset
|
209 for name in __all__: |
27 | 210 if hasattr(builtins, name): |
211 self.originals[name] = getattr(builtins, name) | |
212 setattr(builtins, name, g[name]) | |
25
b500e117080e
Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents:
22
diff
changeset
|
213 def __exit__(self, exc_type, exc_val, exc_tb): |
b500e117080e
Bug fixes and overhead reduction
Oleg Oshmyan <chortos@inbox.lv>
parents:
22
diff
changeset
|
214 for name in self.originals: |
27 | 215 setattr(builtins, name, self.originals[name]) |
21 | 216 |
22 | 217 # Support simple testconf.py's written for test.py 1.x |
27 | 218 builtins.xrange = range |