| 
									
										
										
										
											2009-02-01 04:00:05 +00:00
										 |  |  | from .. import util | 
					
						
							| 
									
										
										
										
											2009-02-01 03:08:31 +00:00
										 |  |  | import contextlib | 
					
						
							| 
									
										
										
										
											2009-03-09 03:35:50 +00:00
										 |  |  | import functools | 
					
						
							| 
									
										
										
										
											2009-02-01 03:08:31 +00:00
										 |  |  | import imp | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | import os.path | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | import tempfile | 
					
						
							| 
									
										
										
										
											2009-02-01 04:00:05 +00:00
										 |  |  | from test import support | 
					
						
							| 
									
										
										
										
											2009-02-01 03:08:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-11 01:47:11 +00:00
										 |  |  | def writes_bytecode_files(fxn): | 
					
						
							|  |  |  |     """Decorator to protect sys.dont_write_bytecode from mutation and to skip
 | 
					
						
							|  |  |  |     tests that require it to be set to False."""
 | 
					
						
							|  |  |  |     if sys.dont_write_bytecode: | 
					
						
							|  |  |  |         return lambda *args, **kwargs: None | 
					
						
							| 
									
										
										
										
											2009-03-09 03:35:50 +00:00
										 |  |  |     @functools.wraps(fxn) | 
					
						
							|  |  |  |     def wrapper(*args, **kwargs): | 
					
						
							|  |  |  |         original = sys.dont_write_bytecode | 
					
						
							|  |  |  |         sys.dont_write_bytecode = False | 
					
						
							| 
									
										
										
										
											2009-05-11 01:47:11 +00:00
										 |  |  |         try: | 
					
						
							|  |  |  |             to_return = fxn(*args, **kwargs) | 
					
						
							|  |  |  |         finally: | 
					
						
							|  |  |  |             sys.dont_write_bytecode = original | 
					
						
							| 
									
										
										
										
											2009-03-09 03:35:50 +00:00
										 |  |  |         return to_return | 
					
						
							|  |  |  |     return wrapper | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-01 03:08:31 +00:00
										 |  |  | def bytecode_path(source_path): | 
					
						
							|  |  |  |     for suffix, _, type_ in imp.get_suffixes(): | 
					
						
							|  |  |  |         if type_ == imp.PY_COMPILED: | 
					
						
							|  |  |  |             bc_suffix = suffix | 
					
						
							|  |  |  |             break | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         raise ValueError("no bytecode suffix is defined") | 
					
						
							|  |  |  |     return os.path.splitext(source_path)[0] + bc_suffix | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @contextlib.contextmanager | 
					
						
							|  |  |  | def create_modules(*names): | 
					
						
							|  |  |  |     """Temporarily create each named module with an attribute (named 'attr')
 | 
					
						
							|  |  |  |     that contains the name passed into the context manager that caused the | 
					
						
							|  |  |  |     creation of the module. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-05 01:34:30 +00:00
										 |  |  |     All files are created in a temporary directory returned by | 
					
						
							|  |  |  |     tempfile.mkdtemp(). This directory is inserted at the beginning of | 
					
						
							| 
									
										
										
										
											2009-02-01 03:08:31 +00:00
										 |  |  |     sys.path. When the context manager exits all created files (source and | 
					
						
							|  |  |  |     bytecode) are explicitly deleted. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     No magic is performed when creating packages! This means that if you create | 
					
						
							|  |  |  |     a module within a package you must also create the package's __init__ as | 
					
						
							|  |  |  |     well. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     source = 'attr = {0!r}' | 
					
						
							|  |  |  |     created_paths = [] | 
					
						
							|  |  |  |     mapping = {} | 
					
						
							| 
									
										
										
										
											2009-11-05 01:34:30 +00:00
										 |  |  |     state_manager = None | 
					
						
							|  |  |  |     uncache_manager = None | 
					
						
							| 
									
										
										
										
											2009-02-01 03:08:31 +00:00
										 |  |  |     try: | 
					
						
							| 
									
										
										
										
											2009-11-05 01:34:30 +00:00
										 |  |  |         temp_dir = tempfile.mkdtemp() | 
					
						
							| 
									
										
										
										
											2009-02-01 03:08:31 +00:00
										 |  |  |         mapping['.root'] = temp_dir | 
					
						
							|  |  |  |         import_names = set() | 
					
						
							|  |  |  |         for name in names: | 
					
						
							|  |  |  |             if not name.endswith('__init__'): | 
					
						
							|  |  |  |                 import_name = name | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 import_name = name[:-len('.__init__')] | 
					
						
							|  |  |  |             import_names.add(import_name) | 
					
						
							|  |  |  |             if import_name in sys.modules: | 
					
						
							|  |  |  |                 del sys.modules[import_name] | 
					
						
							|  |  |  |             name_parts = name.split('.') | 
					
						
							|  |  |  |             file_path = temp_dir | 
					
						
							|  |  |  |             for directory in name_parts[:-1]: | 
					
						
							|  |  |  |                 file_path = os.path.join(file_path, directory) | 
					
						
							|  |  |  |                 if not os.path.exists(file_path): | 
					
						
							|  |  |  |                     os.mkdir(file_path) | 
					
						
							|  |  |  |                     created_paths.append(file_path) | 
					
						
							|  |  |  |             file_path = os.path.join(file_path, name_parts[-1] + '.py') | 
					
						
							|  |  |  |             with open(file_path, 'w') as file: | 
					
						
							|  |  |  |                 file.write(source.format(name)) | 
					
						
							|  |  |  |             created_paths.append(file_path) | 
					
						
							|  |  |  |             mapping[name] = file_path | 
					
						
							|  |  |  |         uncache_manager = util.uncache(*import_names) | 
					
						
							|  |  |  |         uncache_manager.__enter__() | 
					
						
							|  |  |  |         state_manager = util.import_state(path=[temp_dir]) | 
					
						
							|  |  |  |         state_manager.__enter__() | 
					
						
							|  |  |  |         yield mapping | 
					
						
							|  |  |  |     finally: | 
					
						
							| 
									
										
										
										
											2009-11-05 01:34:30 +00:00
										 |  |  |         if state_manager is not None: | 
					
						
							|  |  |  |             state_manager.__exit__(None, None, None) | 
					
						
							|  |  |  |         if uncache_manager is not None: | 
					
						
							|  |  |  |             uncache_manager.__exit__(None, None, None) | 
					
						
							|  |  |  |         support.rmtree(temp_dir) |