You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

97 lines
3.2 KiB

16 years ago
16 years ago
  1. from .. import util
  2. import contextlib
  3. import errno
  4. import functools
  5. import imp
  6. import os
  7. import os.path
  8. import sys
  9. import tempfile
  10. from test import support
  11. def writes_bytecode_files(fxn):
  12. """Decorator to protect sys.dont_write_bytecode from mutation and to skip
  13. tests that require it to be set to False."""
  14. if sys.dont_write_bytecode:
  15. return lambda *args, **kwargs: None
  16. @functools.wraps(fxn)
  17. def wrapper(*args, **kwargs):
  18. original = sys.dont_write_bytecode
  19. sys.dont_write_bytecode = False
  20. try:
  21. to_return = fxn(*args, **kwargs)
  22. finally:
  23. sys.dont_write_bytecode = original
  24. return to_return
  25. return wrapper
  26. def ensure_bytecode_path(bytecode_path):
  27. """Ensure that the __pycache__ directory for PEP 3147 pyc file exists.
  28. :param bytecode_path: File system path to PEP 3147 pyc file.
  29. """
  30. try:
  31. os.mkdir(os.path.dirname(bytecode_path))
  32. except OSError as error:
  33. if error.errno != errno.EEXIST:
  34. raise
  35. @contextlib.contextmanager
  36. def create_modules(*names):
  37. """Temporarily create each named module with an attribute (named 'attr')
  38. that contains the name passed into the context manager that caused the
  39. creation of the module.
  40. All files are created in a temporary directory returned by
  41. tempfile.mkdtemp(). This directory is inserted at the beginning of
  42. sys.path. When the context manager exits all created files (source and
  43. bytecode) are explicitly deleted.
  44. No magic is performed when creating packages! This means that if you create
  45. a module within a package you must also create the package's __init__ as
  46. well.
  47. """
  48. source = 'attr = {0!r}'
  49. created_paths = []
  50. mapping = {}
  51. state_manager = None
  52. uncache_manager = None
  53. try:
  54. temp_dir = tempfile.mkdtemp()
  55. mapping['.root'] = temp_dir
  56. import_names = set()
  57. for name in names:
  58. if not name.endswith('__init__'):
  59. import_name = name
  60. else:
  61. import_name = name[:-len('.__init__')]
  62. import_names.add(import_name)
  63. if import_name in sys.modules:
  64. del sys.modules[import_name]
  65. name_parts = name.split('.')
  66. file_path = temp_dir
  67. for directory in name_parts[:-1]:
  68. file_path = os.path.join(file_path, directory)
  69. if not os.path.exists(file_path):
  70. os.mkdir(file_path)
  71. created_paths.append(file_path)
  72. file_path = os.path.join(file_path, name_parts[-1] + '.py')
  73. with open(file_path, 'w') as file:
  74. file.write(source.format(name))
  75. created_paths.append(file_path)
  76. mapping[name] = file_path
  77. uncache_manager = util.uncache(*import_names)
  78. uncache_manager.__enter__()
  79. state_manager = util.import_state(path=[temp_dir])
  80. state_manager.__enter__()
  81. yield mapping
  82. finally:
  83. if state_manager is not None:
  84. state_manager.__exit__(None, None, None)
  85. if uncache_manager is not None:
  86. uncache_manager.__exit__(None, None, None)
  87. support.rmtree(temp_dir)