compat.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. import io
  2. import sys
  3. if sys.version_info < (2, 6):
  4. raise NotImplementedError("Python 2.6 or greater is required.")
  5. py27 = sys.version_info >= (2, 7)
  6. py2k = sys.version_info < (3, 0)
  7. py3k = sys.version_info >= (3, 0)
  8. py33 = sys.version_info >= (3, 3)
  9. if py3k:
  10. from io import StringIO
  11. else:
  12. # accepts strings
  13. from StringIO import StringIO
  14. if py3k:
  15. import builtins as compat_builtins
  16. string_types = str,
  17. binary_type = bytes
  18. text_type = str
  19. def callable(fn):
  20. return hasattr(fn, '__call__')
  21. def u(s):
  22. return s
  23. def ue(s):
  24. return s
  25. range = range
  26. else:
  27. import __builtin__ as compat_builtins
  28. string_types = basestring,
  29. binary_type = str
  30. text_type = unicode
  31. callable = callable
  32. def u(s):
  33. return unicode(s, "utf-8")
  34. def ue(s):
  35. return unicode(s, "unicode_escape")
  36. range = xrange
  37. if py3k:
  38. from configparser import ConfigParser as SafeConfigParser
  39. import configparser
  40. else:
  41. from ConfigParser import SafeConfigParser
  42. import ConfigParser as configparser
  43. if py2k:
  44. from mako.util import parse_encoding
  45. if py33:
  46. from importlib import machinery
  47. def load_module_py(module_id, path):
  48. return machinery.SourceFileLoader(
  49. module_id, path).load_module(module_id)
  50. def load_module_pyc(module_id, path):
  51. return machinery.SourcelessFileLoader(
  52. module_id, path).load_module(module_id)
  53. else:
  54. import imp
  55. def load_module_py(module_id, path):
  56. with open(path, 'rb') as fp:
  57. mod = imp.load_source(module_id, path, fp)
  58. if py2k:
  59. source_encoding = parse_encoding(fp)
  60. if source_encoding:
  61. mod._alembic_source_encoding = source_encoding
  62. return mod
  63. def load_module_pyc(module_id, path):
  64. with open(path, 'rb') as fp:
  65. mod = imp.load_compiled(module_id, path, fp)
  66. # no source encoding here
  67. return mod
  68. try:
  69. exec_ = getattr(compat_builtins, 'exec')
  70. except AttributeError:
  71. # Python 2
  72. def exec_(func_text, globals_, lcl):
  73. exec('exec func_text in globals_, lcl')
  74. ################################################
  75. # cross-compatible metaclass implementation
  76. # Copyright (c) 2010-2012 Benjamin Peterson
  77. def with_metaclass(meta, base=object):
  78. """Create a base class with a metaclass."""
  79. return meta("%sBase" % meta.__name__, (base,), {})
  80. ################################################
  81. if py3k:
  82. def reraise(tp, value, tb=None, cause=None):
  83. if cause is not None:
  84. value.__cause__ = cause
  85. if value.__traceback__ is not tb:
  86. raise value.with_traceback(tb)
  87. raise value
  88. def raise_from_cause(exception, exc_info=None):
  89. if exc_info is None:
  90. exc_info = sys.exc_info()
  91. exc_type, exc_value, exc_tb = exc_info
  92. reraise(type(exception), exception, tb=exc_tb, cause=exc_value)
  93. else:
  94. exec("def reraise(tp, value, tb=None, cause=None):\n"
  95. " raise tp, value, tb\n")
  96. def raise_from_cause(exception, exc_info=None):
  97. # not as nice as that of Py3K, but at least preserves
  98. # the code line where the issue occurred
  99. if exc_info is None:
  100. exc_info = sys.exc_info()
  101. exc_type, exc_value, exc_tb = exc_info
  102. reraise(type(exception), exception, tb=exc_tb)
  103. # produce a wrapper that allows encoded text to stream
  104. # into a given buffer, but doesn't close it.
  105. # not sure of a more idiomatic approach to this.
  106. class EncodedIO(io.TextIOWrapper):
  107. def close(self):
  108. pass
  109. if py2k:
  110. # in Py2K, the io.* package is awkward because it does not
  111. # easily wrap the file type (e.g. sys.stdout) and I can't
  112. # figure out at all how to wrap StringIO.StringIO (used by nosetests)
  113. # and also might be user specified too. So create a full
  114. # adapter.
  115. class ActLikePy3kIO(object):
  116. """Produce an object capable of wrapping either
  117. sys.stdout (e.g. file) *or* StringIO.StringIO().
  118. """
  119. def _false(self):
  120. return False
  121. def _true(self):
  122. return True
  123. readable = seekable = _false
  124. writable = _true
  125. closed = False
  126. def __init__(self, file_):
  127. self.file_ = file_
  128. def write(self, text):
  129. return self.file_.write(text)
  130. def flush(self):
  131. return self.file_.flush()
  132. class EncodedIO(EncodedIO):
  133. def __init__(self, file_, encoding):
  134. super(EncodedIO, self).__init__(
  135. ActLikePy3kIO(file_), encoding=encoding)