Mercurial > ~astiob > upreckon > hgweb
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 |