Repository: kedro-org/kedro

Issue:
Add validation to node tags
## Description
Currently we do not validate or restrict the format of tags that can be added to nodes. This is inconsistent with other user-defined values. As part of #2014 it was agreed that tags should be subject to the same constraints as node names (see: https://github.com/kedro-org/kedro/blob/main/kedro/pipeline/node.py#L102)



Discussion:

Patch:
diff --git a/RELEASE.md b/RELEASE.md
index 00339282..0b67ad73 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -12,6 +12,7 @@
 ## Bug fixes and other changes
 * Added a new field `add-ons` to `pyproject.toml` when a project is created.
 * Reduced `spaceflights` data to minimise waiting times during tutorial execution.
+* Added validation to node tags to be consistent with node names.
 
 ## Breaking changes to the API
 * Renamed the `data_sets` argument and the `_data_sets` attribute in `Catalog` and their references to `datasets` and `_datasets` respectively.
diff --git a/kedro/pipeline/node.py b/kedro/pipeline/node.py
index 2a91474c..440f402b 100644
--- a/kedro/pipeline/node.py
+++ b/kedro/pipeline/node.py
@@ -109,6 +109,12 @@ class Node:
         self._name = name
         self._namespace = namespace
         self._tags = set(_to_list(tags))
+        for tag in self._tags:
+            if not re.match(r"[\w\.-]+$", tag):
+                raise ValueError(
+                    f"'{tag}' is not a valid node tag. It must contain only "
+                    f"letters, digits, hyphens, underscores and/or fullstops."
+                )
 
         self._validate_unique_outputs()
         self._validate_inputs_dif_than_outputs()


Test patch:
diff --git a/tests/pipeline/test_node.py b/tests/pipeline/test_node.py
index ed5177c9..ae68dff8 100644
--- a/tests/pipeline/test_node.py
+++ b/tests/pipeline/test_node.py
@@ -369,6 +369,15 @@ class TestTag:
         assert "hello" in tagged_node.tags
         assert "world" in tagged_node.tags
 
+    @pytest.mark.parametrize("bad_tag", ["tag,with,comma", "tag with space"])
+    def test_invalid_tag(self, bad_tag):
+        pattern = (
+            f"'{bad_tag}' is not a valid node tag. It must contain only "
+            f"letters, digits, hyphens, underscores and/or fullstops."
+        )
+        with pytest.raises(ValueError, match=re.escape(pattern)):
+            node(identity, ["in"], ["out"], tags=bad_tag)
+
 
 class TestNames:
     def test_named(self):