Add and remove cells to/from the graph. This method adds the cells in `execution_requests` to the kernel's graph (deleting old versions of these cells, if any), and removes the cells in `deletion_requests` from the kernel's graph. The mutations that this method make
(
self,
execution_requests: Sequence[ExecuteCellCommand],
deletion_requests: Sequence[DeleteCellCommand],
cells_starting_stale: set[CellId_t] | None = None,
)
| 1062 | return self._deactivate_cell(cell_id) |
| 1063 | |
| 1064 | def mutate_graph( |
| 1065 | self, |
| 1066 | execution_requests: Sequence[ExecuteCellCommand], |
| 1067 | deletion_requests: Sequence[DeleteCellCommand], |
| 1068 | cells_starting_stale: set[CellId_t] | None = None, |
| 1069 | ) -> set[CellId_t]: |
| 1070 | """Add and remove cells to/from the graph. |
| 1071 | |
| 1072 | This method adds the cells in `execution_requests` to the kernel's |
| 1073 | graph (deleting old versions of these cells, if any), and removes the |
| 1074 | cells in `deletion_requests` from the kernel's graph. |
| 1075 | |
| 1076 | The mutations that this method makes to the graph renders the |
| 1077 | kernel inconsistent (stale). |
| 1078 | |
| 1079 | This method does not register errors for cells that were previously |
| 1080 | valid and are not descendants of any of the newly registered cells. |
| 1081 | This is important for multiple definition errors, since a user may |
| 1082 | absent-mindedly redefine an existing name when creating a new cell: |
| 1083 | such a mistake shouldn't invalidate the program state. |
| 1084 | |
| 1085 | Returns: |
| 1086 | - set of cells that must be run to return kernel to consistent state |
| 1087 | """ |
| 1088 | LOGGER.debug("Mutating graph.") |
| 1089 | LOGGER.debug("Current set of errors: %s", self.errors) |
| 1090 | # Invalidate the cached notebook→source position map so that |
| 1091 | # recompiled cells pick up the current file contents. This |
| 1092 | # matters for debugpy (edit mode) and `marimo run --watch` |
| 1093 | # where cells are recompiled after the file changes on disk. |
| 1094 | _build_source_position_map.cache_clear() |
| 1095 | cells_before_mutation = set(self.graph.cells.keys()) |
| 1096 | cells_with_errors_before_mutation = set(self.errors.keys()) |
| 1097 | cells_starting_stale = ( |
| 1098 | set() if cells_starting_stale is None else cells_starting_stale |
| 1099 | ) |
| 1100 | |
| 1101 | # The set of cells that were successfully registered |
| 1102 | registered_cell_ids: set[CellId_t] = set() |
| 1103 | |
| 1104 | # The set of cells that need to be re-run due to cells being |
| 1105 | # deleted/re-registered. |
| 1106 | cells_that_were_children_of_mutated_cells: set[CellId_t] = set() |
| 1107 | |
| 1108 | # Cells that were unable to be added to the graph due to syntax errors |
| 1109 | syntax_errors: dict[CellId_t, Error] = {} |
| 1110 | |
| 1111 | # Register and delete cells |
| 1112 | for er in execution_requests: |
| 1113 | old_children, error = self._maybe_register_cell( |
| 1114 | er.cell_id, er.code, stale=er.cell_id in cells_starting_stale |
| 1115 | ) |
| 1116 | cells_that_were_children_of_mutated_cells |= old_children |
| 1117 | if error is None: |
| 1118 | registered_cell_ids.add(er.cell_id) |
| 1119 | else: |
| 1120 | syntax_errors[er.cell_id] = error |
| 1121 |
no test coverage detected