Main entry point that coordinates all graph operations. Responsibilities: - Coordinate topology, definitions, cycles - Execute register_cell/delete_cell operations - Maintain thread safety - Delegate to specialists
| 30 | |
| 31 | @dataclass(frozen=True) |
| 32 | class DirectedGraph(GraphTopology): |
| 33 | """Main entry point that coordinates all graph operations. |
| 34 | |
| 35 | Responsibilities: |
| 36 | - Coordinate topology, definitions, cycles |
| 37 | - Execute register_cell/delete_cell operations |
| 38 | - Maintain thread safety |
| 39 | - Delegate to specialists |
| 40 | """ |
| 41 | |
| 42 | topology: MutableGraphTopology = field( |
| 43 | default_factory=MutableGraphTopology |
| 44 | ) |
| 45 | definition_registry: DefinitionRegistry = field( |
| 46 | default_factory=DefinitionRegistry |
| 47 | ) |
| 48 | cycle_tracker: CycleTracker = field(default_factory=CycleTracker) |
| 49 | |
| 50 | # Cell ids whose last post-execution broadcast advertised a top-level |
| 51 | # reusability hint. Tracked here (not on the per-run CellImpl, which is |
| 52 | # replaced when a cell's code changes) so the hint can be cleared exactly |
| 53 | # on the top-level -> non-top-level transition. Not topology; broadcast |
| 54 | # bookkeeping that needs to survive cell re-registration. |
| 55 | cells_serving_serialization_hint: set[CellId_t] = field( |
| 56 | default_factory=set |
| 57 | ) |
| 58 | |
| 59 | # This lock must be acquired during methods that mutate the graph; it's |
| 60 | # only needed because a graph is shared between the kernel and the code |
| 61 | # completion service. It should almost always be uncontended. |
| 62 | lock: threading.Lock = field(default_factory=threading.Lock) |
| 63 | |
| 64 | def is_cell_cached(self, cell_id: CellId_t, code: str) -> bool: |
| 65 | """Whether a cell with id `cell_id` and code `code` is in the graph.""" |
| 66 | return ( |
| 67 | cell_id in self.topology.cells |
| 68 | and code_key(code) == self.topology.cells[cell_id].key |
| 69 | ) |
| 70 | |
| 71 | def get_defining_cells(self, name: Name) -> set[CellId_t]: |
| 72 | """Get all cells that define name. |
| 73 | |
| 74 | This is a singleton for well-formed graphs. |
| 75 | """ |
| 76 | return self.definition_registry.get_defining_cells(name) |
| 77 | |
| 78 | def get_referring_cells( |
| 79 | self, name: Name, language: Literal["python", "sql"] |
| 80 | ) -> set[CellId_t]: |
| 81 | """Get all cells that have a ref to `name`. |
| 82 | |
| 83 | The variable can be either a Python variable or a SQL variable (table). |
| 84 | SQL variables don't leak to Python cells, but Python variables do leak |
| 85 | to SQL. |
| 86 | |
| 87 | Only does a local analysis of refs, without taking into consideration |
| 88 | whether refs are defined by other cells. |
| 89 | """ |
no outgoing calls
searching dependent graphs…