def _execute_transform( # noqa: C901 transformer: Codemod, filename: str, config: ExecutionConfig, ) -> ExecutionResult: for pattern in config.blacklist_patterns: if re.fullmatch(pattern, filename): return ExecutionResult( filename=filename, changed=False, transform_result=TransformSkip( skip_reason=SkipReason.BLACKLISTED, skip_description=f"Blacklisted by pattern {pattern}.", ), ) try: with open(filename, "rb") as fp: oldcode = fp.read() # Skip generated files if (not config.include_generated and config.generated_code_marker.encode("utf-8") in oldcode): return ExecutionResult( filename=filename, changed=False, transform_result=TransformSkip( skip_reason=SkipReason.GENERATED, skip_description="Generated file.", ), ) # Somewhat gross hack to provide the filename in the transform's context. # We do this after the fork so that a context that was initialized with # some defaults before calling parallel_exec_transform_with_prettyprint # will be updated per-file. transformer.context = replace( transformer.context, filename=filename, full_module_name=_calculate_module(config.repo_root, filename), ) # Run the transform, bail if we failed or if we aren't formatting code try: input_tree = parse_module( oldcode, config=(PartialParserConfig( python_version=str(config.python_version)) if config.python_version is not None else PartialParserConfig()), ) output_tree = transformer.transform_module(input_tree) newcode = output_tree.bytes encoding = output_tree.encoding except KeyboardInterrupt: return ExecutionResult(filename=filename, changed=False, transform_result=TransformExit()) except SkipFile as ex: return ExecutionResult( filename=filename, changed=False, transform_result=TransformSkip( skip_reason=SkipReason.OTHER, skip_description=str(ex), warning_messages=transformer.context.warnings, ), ) except Exception as ex: return ExecutionResult( filename=filename, changed=False, transform_result=TransformFailure( error=ex, traceback_str=traceback.format_exc(), warning_messages=transformer.context.warnings, ), ) # Call formatter if needed, but only if we actually changed something in this # file if config.format_code and newcode != oldcode: try: newcode = invoke_formatter(config.formatter_args, newcode) except KeyboardInterrupt: return ExecutionResult( filename=filename, changed=False, transform_result=TransformExit(), ) except Exception as ex: return ExecutionResult( filename=filename, changed=False, transform_result=TransformFailure( error=ex, traceback_str=traceback.format_exc(), warning_messages=transformer.context.warnings, ), ) # Format as unified diff if needed, otherwise save it back changed = oldcode != newcode if config.unified_diff: newcode = diff_code( oldcode.decode(encoding), newcode.decode(encoding), config.unified_diff, filename=filename, ) else: # Write back if we changed if changed: with open(filename, "wb") as fp: fp.write(newcode) # Not strictly necessary, but saves space in pickle since we won't use it newcode = "" # Inform success return ExecutionResult( filename=filename, changed=changed, transform_result=TransformSuccess( warning_messages=transformer.context.warnings, code=newcode), ) except KeyboardInterrupt: return ExecutionResult(filename=filename, changed=False, transform_result=TransformExit()) except Exception as ex: return ExecutionResult( filename=filename, changed=False, transform_result=TransformFailure( error=ex, traceback_str=traceback.format_exc(), warning_messages=transformer.context.warnings, ), )
def _parallel_exec_process_stub( # noqa: C901 result_queue: "Queue[ParallelExecResult]", transformer: Codemod, filename: str, unified_diff: Optional[int], include_generated: bool, generated_code_marker: str, format_code: bool, formatter_args: Sequence[str], blacklist_patterns: Sequence[str], ) -> None: for pattern in blacklist_patterns: if re.fullmatch(pattern, filename): result_queue.put( ParallelExecResult( filename=filename, changed=False, transform_result=TransformSkip( skip_reason=SkipReason.BLACKLISTED, skip_description=f"Blacklisted by pattern {pattern}.", ), ) ) return try: with open(filename, "rb") as fp: oldcode = fp.read() # Skip generated files if not include_generated and generated_code_marker.encode("utf-8") in oldcode: result_queue.put( ParallelExecResult( filename=filename, changed=False, transform_result=TransformSkip( skip_reason=SkipReason.GENERATED, skip_description="Generated file.", ), ) ) return # Somewhat gross hack to provide the filename in the transform's context. # We do this after the fork so that a context that was initialized with # some defaults before calling parallel_exec_transform_with_prettyprint # will be updated per-file. transformer.context = replace(transformer.context, filename=filename) # Run the transform, bail if we failed or if we aren't formatting code try: input_tree = parse_module(oldcode) output_tree = transformer.transform_module(input_tree) newcode = output_tree.bytes encoding = output_tree.encoding except KeyboardInterrupt: result_queue.put( ParallelExecResult( filename=filename, changed=False, transform_result=TransformExit() ) ) return except SkipFile as ex: result_queue.put( ParallelExecResult( filename=filename, changed=False, transform_result=TransformSkip( skip_reason=SkipReason.OTHER, skip_description=str(ex), warning_messages=transformer.context.warnings, ), ) ) return except Exception as ex: result_queue.put( ParallelExecResult( filename=filename, changed=False, transform_result=TransformFailure( error=ex, traceback_str=traceback.format_exc(), warning_messages=transformer.context.warnings, ), ) ) return # Call formatter if needed, but only if we actually changed something in this # file if format_code and newcode != oldcode: try: newcode = invoke_formatter(formatter_args, newcode) except KeyboardInterrupt: result_queue.put( ParallelExecResult( filename=filename, changed=False, transform_result=TransformExit(), ) ) return except Exception as ex: result_queue.put( ParallelExecResult( filename=filename, changed=False, transform_result=TransformFailure( error=ex, traceback_str=traceback.format_exc(), warning_messages=transformer.context.warnings, ), ) ) return # Format as unified diff if needed, otherwise save it back changed = oldcode != newcode if unified_diff: newcode = diff_code( oldcode.decode(encoding), newcode.decode(encoding), unified_diff, filename=filename, ) else: # Write back if we changed if changed: with open(filename, "wb") as fp: fp.write(newcode) # Not strictly necessary, but saves space in pickle since we won't use it newcode = "" # Inform success result_queue.put( ParallelExecResult( filename=filename, changed=changed, transform_result=TransformSuccess( warning_messages=transformer.context.warnings, code=newcode ), ) ) except KeyboardInterrupt: result_queue.put( ParallelExecResult( filename=filename, changed=False, transform_result=TransformExit() ) ) except Exception as ex: result_queue.put( ParallelExecResult( filename=filename, changed=False, transform_result=TransformFailure( error=ex, traceback_str=traceback.format_exc(), warning_messages=transformer.context.warnings, ), ) )