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
|
|
28 __all__ = ('say', 'basestring', 'range', 'map', 'zip', 'filter',
|
|
29 'items', 'keys', 'values', 'ABCMeta', 'abstractmethod')
|
|
30
|
16
|
31 try:
|
|
32 # Python 3
|
|
33 exec('say = print')
|
|
34 except SyntaxError:
|
|
35 try:
|
|
36 # Python 2.6/2.7
|
21
|
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']
|
16
|
41 except Exception:
|
|
42 # Python 2.5
|
|
43 import sys
|
|
44 # This should fully emulate the print function of Python 2.6 in Python 2.3+
|
21
|
45 # The error messages are taken from Python 2.6
|
|
46 # The name bindings at the bottom of this file are in effect
|
16
|
47 def saytypeerror(value, name):
|
21
|
48 return TypeError(' '.join((name, 'must be None, str or unicode, not', type(value).__name__)))
|
16
|
49 def say(*values, **kwargs):
|
|
50 sep = kwargs.pop('sep' , None)
|
|
51 end = kwargs.pop('end' , None)
|
|
52 file = kwargs.pop('file', None)
|
|
53 if kwargs: raise TypeError("'%s' is an invalid keyword argument for this function" % kwargs.popitem()[0])
|
|
54 if sep is None: sep = ' '
|
|
55 if end is None: end = '\n'
|
|
56 if file is None: file = sys.stdout
|
|
57 if not isinstance(sep, basestring): raise saytypeerror(sep, 'sep')
|
|
58 if not isinstance(end, basestring): raise saytypeerror(end, 'end')
|
21
|
59 file.write(sep.join(map(str, values)) + end)
|
16
|
60
|
|
61 def import_urllib():
|
|
62 try:
|
|
63 # Python 3
|
|
64 import urllib.request
|
|
65 return urllib.request, lambda url: urllib.request.urlopen(url).read().decode()
|
|
66 except ImportError:
|
|
67 # Python 2
|
|
68 import urllib
|
21
|
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 |