Attempt to execute the code using Jupyter notebook kernel and return result or error.
(code: str)
| 121 | return '\n'.join(safe_lines) |
| 122 | |
| 123 | def execute_code(code: str) -> Tuple[Any, str]: |
| 124 | """Attempt to execute the code using Jupyter notebook kernel and return result or error.""" |
| 125 | logger.info("Attempting to execute code in notebook kernel") |
| 126 | logger.info(f"Code:\n{code}") |
| 127 | |
| 128 | try: |
| 129 | # Sanitize the code first |
| 130 | sanitized_code = sanitize_code(code) |
| 131 | |
| 132 | # Create a notebook with the code |
| 133 | notebook = nbformat.v4.new_notebook() |
| 134 | |
| 135 | # Add code that captures the answer variable |
| 136 | enhanced_code = f""" |
| 137 | {sanitized_code} |
| 138 | |
| 139 | # Capture the answer variable for output |
| 140 | if 'answer' in locals(): |
| 141 | print(f"ANSWER_RESULT: {{answer}}") |
| 142 | else: |
| 143 | print("ANSWER_RESULT: No answer variable found") |
| 144 | """ |
| 145 | |
| 146 | notebook['cells'] = [nbformat.v4.new_code_cell(enhanced_code)] |
| 147 | |
| 148 | # Convert notebook to JSON string and then to bytes |
| 149 | notebook_json = nbformat.writes(notebook) |
| 150 | notebook_bytes = notebook_json.encode('utf-8') |
| 151 | |
| 152 | # Create temporary notebook file |
| 153 | with tempfile.NamedTemporaryFile(mode='wb', suffix='.ipynb', delete=False) as tmp: |
| 154 | tmp.write(notebook_bytes) |
| 155 | tmp.flush() |
| 156 | tmp_name = tmp.name |
| 157 | |
| 158 | try: |
| 159 | # Read and execute the notebook |
| 160 | with open(tmp_name, 'r', encoding='utf-8') as f: |
| 161 | nb = nbformat.read(f, as_version=4) |
| 162 | |
| 163 | # Execute with timeout and isolation |
| 164 | ep = ExecutePreprocessor(timeout=30, kernel_name='python3') |
| 165 | ep.preprocess(nb, {'metadata': {'path': './'}}) |
| 166 | |
| 167 | # Extract the output |
| 168 | output = "" |
| 169 | error_output = "" |
| 170 | |
| 171 | for cell in nb.cells: |
| 172 | if cell.cell_type == 'code' and cell.outputs: |
| 173 | for output_item in cell.outputs: |
| 174 | if output_item.output_type == 'stream': |
| 175 | if output_item.name == 'stdout': |
| 176 | output += output_item.text |
| 177 | elif output_item.name == 'stderr': |
| 178 | error_output += output_item.text |
| 179 | elif output_item.output_type == 'execute_result': |
| 180 | output += str(output_item.data.get('text/plain', '')) |
no test coverage detected