Repository: kedro-org/kedro
File: kedro/pipeline/pipeline.py (Python)

Code before:
        # input -> nodes with input
        self._nodes_by_input: dict[str, set[Node]] = defaultdict(set)
        for node in tagged_nodes:
            for input_ in node.inputs:
                self._nodes_by_input[_strip_transcoding(input_)].add(node)

        # output -> node with output
        self._nodes_by_output: dict[str, Node] = {}
        for node in tagged_nodes:
            for output in node.outputs:
                self._nodes_by_output[_strip_transcoding(output)] = node

        self._nodes = tagged_nodes
        self._toposorter = TopologicalSorter(self.node_dependencies)

        # test for circular dependencies without executing the toposort for efficiency
        try:
            self._toposorter.prepare()
        except CycleError as exc:
            loop = list(set(exc.args[1]))
            message = f"Circular dependencies exist among the following {len(loop)} item(s): {loop}"
            raise CircularDependencyError(message) from exc

        self._toposorted_nodes: list[Node] = []
        self._toposorted_groups: list[list[Node]] = []
        self._validate_namespaces()

    @cached_property
    def _node_children(self) -> dict[Node, set[Node]]:
        node_children = defaultdict(set)
        for child, parents in self.node_dependencies.items():
            for parent in parents:
                node_children[parent].add(child)
        return node_children

    def _shortest_path(self, start: Node, end: Node) -> list[Node]:
        """Find the shortest path between two nodes in the pipeline, if it exists."""
        queue = deque([(start, [start])])
        visited = set([start])

        while queue:
            node, path = queue.popleft()
            if node == end:
                return path
            for child in self._node_children[node]:
                if child not in visited:
                    visited.add(child)
                    queue.append((child, [*path, child]))
        return []  # pragma: no cover

    def _validate_namespaces(self) -> None:

Review comment (suggestion):
@idanov As I mentioned in #4943, I think we can skip this validation if there's no node namespace at all? i.e.:

```python
if any(n.namespace for n in self._nodes):
    self._validate_namespaces()
```

Code after:
        # input -> nodes with input
        self._nodes_by_input: dict[str, set[Node]] = defaultdict(set)
        for node in tagged_nodes:
            for input_ in node.inputs:
                self._nodes_by_input[_strip_transcoding(input_)].add(node)

        # output -> node with output
        self._nodes_by_output: dict[str, Node] = {}
        for node in tagged_nodes:
            for output in node.outputs:
                self._nodes_by_output[_strip_transcoding(output)] = node

        self._nodes = tagged_nodes
        self._toposorter = TopologicalSorter(self.node_dependencies)

        # test for circular dependencies without executing the toposort for efficiency
        try:
            self._toposorter.prepare()
        except CycleError as exc:
            loop = list(set(exc.args[1]))
            message = f"Circular dependencies exist among the following {len(loop)} item(s): {loop}"
            raise CircularDependencyError(message) from exc

        self._toposorted_nodes: list[Node] = []
        self._toposorted_groups: list[list[Node]] = []
        if any(n.namespace for n in self._nodes):
            self._validate_namespaces()

    @cached_property
    def _node_children(self) -> dict[Node, set[Node]]:
        node_children = defaultdict(set)
        for child, parents in self.node_dependencies.items():
            for parent in parents:
                node_children[parent].add(child)
        return node_children

    def _shortest_path(self, start: Node, end: Node) -> list[Node]:
        """Find the shortest path between two nodes in the pipeline, if it exists."""
        queue = deque([(start, [start])])
        visited = set([start])

        while queue:
            node, path = queue.popleft()
            if node == end:
                return path
            for child in self._node_children[node]:
                if child not in visited:
                    visited.add(child)
                    queue.append((child, [*path, child]))
        return []  # pragma: no cover