9
from test import support
12
def writes_bytecode(fxn):
13
"""Decorator to protect sys.dont_write_bytecode from mutation."""
15
def wrapper(*args, **kwargs):
16
original = sys.dont_write_bytecode
17
sys.dont_write_bytecode = False
18
to_return = fxn(*args, **kwargs)
19
sys.dont_write_bytecode = original
24
def writes_bytecode_files(fxn):
25
"""Decorator that returns the function if writing bytecode is enabled, else
26
a stub function that accepts anything and simply returns None."""
27
if sys.dont_write_bytecode:
28
return lambda *args, **kwargs: None
31
def wrapper(*args, **kwargs):
32
to_return = fxn(*args, **kwargs)
33
sys.dont_write_bytecode = False
38
def bytecode_path(source_path):
39
for suffix, _, type_ in imp.get_suffixes():
40
if type_ == imp.PY_COMPILED:
44
raise ValueError("no bytecode suffix is defined")
45
return os.path.splitext(source_path)[0] + bc_suffix
48
@contextlib.contextmanager
49
def create_modules(*names):
50
"""Temporarily create each named module with an attribute (named 'attr')
51
that contains the name passed into the context manager that caused the
52
creation of the module.
54
All files are created in a temporary directory specified by
55
tempfile.gettempdir(). This directory is inserted at the beginning of
56
sys.path. When the context manager exits all created files (source and
57
bytecode) are explicitly deleted.
59
No magic is performed when creating packages! This means that if you create
60
a module within a package you must also create the package's __init__ as
64
source = 'attr = {0!r}'
68
temp_dir = tempfile.gettempdir()
69
mapping['.root'] = temp_dir
72
if not name.endswith('__init__'):
75
import_name = name[:-len('.__init__')]
76
import_names.add(import_name)
77
if import_name in sys.modules:
78
del sys.modules[import_name]
79
name_parts = name.split('.')
81
for directory in name_parts[:-1]:
82
file_path = os.path.join(file_path, directory)
83
if not os.path.exists(file_path):
85
created_paths.append(file_path)
86
file_path = os.path.join(file_path, name_parts[-1] + '.py')
87
with open(file_path, 'w') as file:
88
file.write(source.format(name))
89
created_paths.append(file_path)
90
mapping[name] = file_path
91
uncache_manager = util.uncache(*import_names)
92
uncache_manager.__enter__()
93
state_manager = util.import_state(path=[temp_dir])
94
state_manager.__enter__()
97
state_manager.__exit__(None, None, None)
98
uncache_manager.__exit__(None, None, None)
99
# Reverse the order for path removal to unroll directory creation.
100
for path in reversed(created_paths):
101
if file_path.endswith('.py'):
103
support.unlink(path + 'c')
104
support.unlink(path + 'o')