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 |
