Mercurial > ~astiob > upreckon > hgweb
view 2.00/compat.py @ 22:f07b7a431ea6
Further 2.00 work
Testconfs in all supported kinds of archives should now work.
Test runs are now cancelled by pressing Escape rather than Ctrl+C.
Improved time control.
Greatly improved temporary and helper file cleanup.
The pause configuration variable can now be a callable and is now processed using subprocess rather than system().
author | Oleg Oshmyan <chortos@inbox.lv> |
---|---|
date | Wed, 22 Sep 2010 22:01:56 +0000 |
parents | ec6f1a132109 |
children | b500e117080e |
line wrap: on
line source
#! /usr/bin/env python # Copyright (c) 2010 Chortos-2 <chortos@inbox.lv> # A compatibility layer for Python 2.5+. This is what lets test.py # run on all versions of Python starting with 2.5, including Python 3. # A few notes regarding some compatibility-driven peculiarities # in the use of the language that can be seen in all modules: # # * Except statements never specify target; instead, when needed, # the exception is taken from sys.exc_info(). Blame the incompatible # syntaxes of the except clause in Python 2.5 and Python 3 and the lack # of preprocessor macros in Python of any version ;P. # # * Keyword-only parameters are never used, even for parameters # that should never be given in as arguments. The reason is # the laziness of some Python developers who have failed to finish # implementing them in Python 2 even though they had several years # of time and multiple version releases to sneak them in. # # * Abstract classes are only implemented for Python 2.6 and 2.7. # ABC's require the abc module and the specification of metaclasses, # but in Python 2.5, the abc module does not exist, while in Python 3, # metaclasses are specified using a syntax totally incompatible # 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') try: # Python 3 exec('say = print') except SyntaxError: try: # Python 2.6/2.7 # An alternative is exec('from __future__ import print_function; say = print'); # if problems arise with the current line, one should try replacing it # with this one with the future import before abandoning the idea altogether say = __builtins__['print'] except Exception: # Python 2.5 import sys # This should fully emulate the print function of Python 2.6 in Python 2.3+ # The error messages are taken from Python 2.6 # The name bindings at the bottom of this file are in effect def saytypeerror(value, name): return TypeError(' '.join((name, 'must be None, str or unicode, not', type(value).__name__))) def say(*values, **kwargs): sep = kwargs.pop('sep' , None) end = kwargs.pop('end' , None) file = kwargs.pop('file', None) if kwargs: raise TypeError("'%s' is an invalid keyword argument for this function" % kwargs.popitem()[0]) if sep is None: sep = ' ' if end is None: end = '\n' if file is None: file = sys.stdout if not isinstance(sep, basestring): raise saytypeerror(sep, 'sep') if not isinstance(end, basestring): raise saytypeerror(end, 'end') file.write(sep.join(map(str, values)) + end) def import_urllib(): try: # Python 3 import urllib.request return urllib.request, lambda url: urllib.request.urlopen(url).read().decode() except ImportError: # Python 2 import urllib return urllib, lambda url: urllib.urlopen(url).read() try: from abc import ABCMeta, abstractmethod except ImportError: ABCMeta, abstractmethod = None, lambda x: x # In all of the following, the try clause is for Python 2 and the except # clause is for Python 3. More checks are performed than needed # for standard builds of Python to ensure as much as possible works # on custom builds. try: basestring = basestring except NameError: basestring = str try: range = xrange except NameError: range = range try: from itertools import imap as map except ImportError: map = map try: from itertools import izip as zip except ImportError: zip = zip try: from itertools import ifilter as filter except ImportError: filter = filter items = dict.iteritems if hasattr(dict, 'iteritems') else dict.items 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] # Support simple testconf.py's written for test.py 1.x __builtins__['xrange'] = range