diff 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
line wrap: on
line diff
--- a/2.00/compat.py	Mon Jun 14 21:02:06 2010 +0000
+++ b/2.00/compat.py	Fri Aug 06 15:39:29 2010 +0000
@@ -1,20 +1,51 @@
-#!/usr/bin/python
+#! /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
-		exec('say = __builtins__["print"]')
+		# 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/2.7
+		# 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(name + ' must be None, str or unicode, not ' + type(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)
@@ -25,7 +56,7 @@
 			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((str(i) for i in values)) + end)
+			file.write(sep.join(map(str, values)) + end)
 
 def import_urllib():
 	try:
@@ -35,4 +66,47 @@
 	except ImportError:
 		# Python 2
 		import urllib
-		return urllib, lambda url: urllib.urlopen(url).read()
\ No newline at end of file
+		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]
+
+__builtins__['xrange'] = range
\ No newline at end of file