comparison 2.00/compat.py @ 21:ec6f1a132109

A pretty usable version Test groups and testconfs in non-ZIP archives or ZIP archives with comments are not yet supported.
author Oleg Oshmyan <chortos@inbox.lv>
date Fri, 06 Aug 2010 15:39:29 +0000
parents f2279b7602d3
children f07b7a431ea6
comparison
equal deleted inserted replaced
20:5bfa23cd638d 21:ec6f1a132109
1 #!/usr/bin/python 1 #! /usr/bin/env python
2 # Copyright (c) 2010 Chortos-2 <chortos@inbox.lv> 2 # Copyright (c) 2010 Chortos-2 <chortos@inbox.lv>
3
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
28 __all__ = ('say', 'basestring', 'range', 'map', 'zip', 'filter',
29 'items', 'keys', 'values', 'ABCMeta', 'abstractmethod')
3 30
4 try: 31 try:
5 # Python 3 32 # Python 3
6 exec('say = print') 33 exec('say = print')
7 except SyntaxError: 34 except SyntaxError:
8 try: 35 try:
9 # Python 2.6/2.7 36 # Python 2.6/2.7
10 exec('say = __builtins__["print"]') 37 # An alternative is exec('from __future__ import print_function; say = print');
38 # if problems arise with the current line, one should try replacing it
39 # with this one with the future import before abandoning the idea altogether
40 say = __builtins__['print']
11 except Exception: 41 except Exception:
12 # Python 2.5 42 # Python 2.5
13 import sys 43 import sys
14 # This should fully emulate the print function of Python 2.6 in Python 2.3+ 44 # This should fully emulate the print function of Python 2.6 in Python 2.3+
15 # The error messages are taken from Python 2.6/2.7 45 # The error messages are taken from Python 2.6
46 # The name bindings at the bottom of this file are in effect
16 def saytypeerror(value, name): 47 def saytypeerror(value, name):
17 return TypeError(name + ' must be None, str or unicode, not ' + type(value).__name__) 48 return TypeError(' '.join((name, 'must be None, str or unicode, not', type(value).__name__)))
18 def say(*values, **kwargs): 49 def say(*values, **kwargs):
19 sep = kwargs.pop('sep' , None) 50 sep = kwargs.pop('sep' , None)
20 end = kwargs.pop('end' , None) 51 end = kwargs.pop('end' , None)
21 file = kwargs.pop('file', None) 52 file = kwargs.pop('file', None)
22 if kwargs: raise TypeError("'%s' is an invalid keyword argument for this function" % kwargs.popitem()[0]) 53 if kwargs: raise TypeError("'%s' is an invalid keyword argument for this function" % kwargs.popitem()[0])
23 if sep is None: sep = ' ' 54 if sep is None: sep = ' '
24 if end is None: end = '\n' 55 if end is None: end = '\n'
25 if file is None: file = sys.stdout 56 if file is None: file = sys.stdout
26 if not isinstance(sep, basestring): raise saytypeerror(sep, 'sep') 57 if not isinstance(sep, basestring): raise saytypeerror(sep, 'sep')
27 if not isinstance(end, basestring): raise saytypeerror(end, 'end') 58 if not isinstance(end, basestring): raise saytypeerror(end, 'end')
28 file.write(sep.join((str(i) for i in values)) + end) 59 file.write(sep.join(map(str, values)) + end)
29 60
30 def import_urllib(): 61 def import_urllib():
31 try: 62 try:
32 # Python 3 63 # Python 3
33 import urllib.request 64 import urllib.request
34 return urllib.request, lambda url: urllib.request.urlopen(url).read().decode() 65 return urllib.request, lambda url: urllib.request.urlopen(url).read().decode()
35 except ImportError: 66 except ImportError:
36 # Python 2 67 # Python 2
37 import urllib 68 import urllib
38 return urllib, lambda url: urllib.urlopen(url).read() 69 return urllib, lambda url: urllib.urlopen(url).read()
70
71 try:
72 from abc import ABCMeta, abstractmethod
73 except ImportError:
74 ABCMeta, abstractmethod = None, lambda x: x
75
76 # In all of the following, the try clause is for Python 2 and the except
77 # clause is for Python 3. More checks are performed than needed
78 # for standard builds of Python to ensure as much as possible works
79 # on custom builds.
80 try:
81 basestring = basestring
82 except NameError:
83 basestring = str
84
85 try:
86 range = xrange
87 except NameError:
88 range = range
89
90 try:
91 from itertools import imap as map
92 except ImportError:
93 map = map
94
95 try:
96 from itertools import izip as zip
97 except ImportError:
98 zip = zip
99
100 try:
101 from itertools import ifilter as filter
102 except ImportError:
103 filter = filter
104
105 items = dict.iteritems if hasattr(dict, 'iteritems') else dict.items
106 keys = dict.iterkeys if hasattr(dict, 'iterkeys') else dict.keys
107 values = dict.itervalues if hasattr(dict, 'itervalues') else dict.values
108
109 for name in __all__:
110 __builtins__[name] = globals()[name]
111
112 __builtins__['xrange'] = range