backward.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. # Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
  2. # For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt
  3. """Add things to old Pythons so I can pretend they are newer."""
  4. # This file does tricky stuff, so disable a pylint warning.
  5. # pylint: disable=unused-import
  6. import sys
  7. from coverage import env
  8. # Pythons 2 and 3 differ on where to get StringIO.
  9. try:
  10. from cStringIO import StringIO
  11. except ImportError:
  12. from io import StringIO
  13. # In py3, ConfigParser was renamed to the more-standard configparser.
  14. # But there's a py3 backport that installs "configparser" in py2, and I don't
  15. # want it because it has annoying deprecation warnings. So try the real py2
  16. # import first.
  17. try:
  18. import ConfigParser as configparser
  19. except ImportError:
  20. import configparser
  21. # What's a string called?
  22. try:
  23. string_class = basestring
  24. except NameError:
  25. string_class = str
  26. # What's a Unicode string called?
  27. try:
  28. unicode_class = unicode
  29. except NameError:
  30. unicode_class = str
  31. # Where do pickles come from?
  32. try:
  33. import cPickle as pickle
  34. except ImportError:
  35. import pickle
  36. # range or xrange?
  37. try:
  38. range = xrange # pylint: disable=redefined-builtin
  39. except NameError:
  40. range = range
  41. # shlex.quote is new, but there's an undocumented implementation in "pipes",
  42. # who knew!?
  43. try:
  44. from shlex import quote as shlex_quote
  45. except ImportError:
  46. # Useful function, available under a different (undocumented) name
  47. # in Python versions earlier than 3.3.
  48. from pipes import quote as shlex_quote
  49. # A function to iterate listlessly over a dict's items, and one to get the
  50. # items as a list.
  51. try:
  52. {}.iteritems
  53. except AttributeError:
  54. # Python 3
  55. def iitems(d):
  56. """Produce the items from dict `d`."""
  57. return d.items()
  58. def litems(d):
  59. """Return a list of items from dict `d`."""
  60. return list(d.items())
  61. else:
  62. # Python 2
  63. def iitems(d):
  64. """Produce the items from dict `d`."""
  65. return d.iteritems()
  66. def litems(d):
  67. """Return a list of items from dict `d`."""
  68. return d.items()
  69. # Getting the `next` function from an iterator is different in 2 and 3.
  70. try:
  71. iter([]).next
  72. except AttributeError:
  73. def iternext(seq):
  74. """Get the `next` function for iterating over `seq`."""
  75. return iter(seq).__next__
  76. else:
  77. def iternext(seq):
  78. """Get the `next` function for iterating over `seq`."""
  79. return iter(seq).next
  80. # Python 3.x is picky about bytes and strings, so provide methods to
  81. # get them right, and make them no-ops in 2.x
  82. if env.PY3:
  83. def to_bytes(s):
  84. """Convert string `s` to bytes."""
  85. return s.encode('utf8')
  86. def binary_bytes(byte_values):
  87. """Produce a byte string with the ints from `byte_values`."""
  88. return bytes(byte_values)
  89. def bytes_to_ints(bytes_value):
  90. """Turn a bytes object into a sequence of ints."""
  91. # In Python 3, iterating bytes gives ints.
  92. return bytes_value
  93. else:
  94. def to_bytes(s):
  95. """Convert string `s` to bytes (no-op in 2.x)."""
  96. return s
  97. def binary_bytes(byte_values):
  98. """Produce a byte string with the ints from `byte_values`."""
  99. return "".join(chr(b) for b in byte_values)
  100. def bytes_to_ints(bytes_value):
  101. """Turn a bytes object into a sequence of ints."""
  102. for byte in bytes_value:
  103. yield ord(byte)
  104. try:
  105. # In Python 2.x, the builtins were in __builtin__
  106. BUILTINS = sys.modules['__builtin__']
  107. except KeyError:
  108. # In Python 3.x, they're in builtins
  109. BUILTINS = sys.modules['builtins']
  110. # imp was deprecated in Python 3.3
  111. try:
  112. import importlib
  113. import importlib.util
  114. imp = None
  115. except ImportError:
  116. importlib = None
  117. # We only want to use importlib if it has everything we need.
  118. try:
  119. importlib_util_find_spec = importlib.util.find_spec
  120. except Exception:
  121. import imp
  122. importlib_util_find_spec = None
  123. # What is the .pyc magic number for this version of Python?
  124. try:
  125. PYC_MAGIC_NUMBER = importlib.util.MAGIC_NUMBER
  126. except AttributeError:
  127. PYC_MAGIC_NUMBER = imp.get_magic()
  128. def invalidate_import_caches():
  129. """Invalidate any import caches that may or may not exist."""
  130. if importlib and hasattr(importlib, "invalidate_caches"):
  131. importlib.invalidate_caches()
  132. def import_local_file(modname, modfile=None):
  133. """Import a local file as a module.
  134. Opens a file in the current directory named `modname`.py, imports it
  135. as `modname`, and returns the module object. `modfile` is the file to
  136. import if it isn't in the current directory.
  137. """
  138. try:
  139. from importlib.machinery import SourceFileLoader
  140. except ImportError:
  141. SourceFileLoader = None
  142. if modfile is None:
  143. modfile = modname + '.py'
  144. if SourceFileLoader:
  145. mod = SourceFileLoader(modname, modfile).load_module()
  146. else:
  147. for suff in imp.get_suffixes(): # pragma: part covered
  148. if suff[0] == '.py':
  149. break
  150. with open(modfile, 'r') as f:
  151. # pylint: disable=undefined-loop-variable
  152. mod = imp.load_module(modname, f, modfile, suff)
  153. return mod