@@ -640,6 +640,14 @@ def same_tree(self, other: Tree) -> bool:
640640AnyNamedNode = TypeVar ("AnyNamedNode" , bound = "NamedNode" )
641641
642642
643+ def _validate_name (name : str | None ) -> None :
644+ if name is not None :
645+ if not isinstance (name , str ):
646+ raise TypeError ("node name must be a string or None" )
647+ if "/" in name :
648+ raise ValueError ("node names cannot contain forward slashes" )
649+
650+
643651class NamedNode (TreeNode , Generic [Tree ]):
644652 """
645653 A TreeNode which knows its own name.
@@ -653,8 +661,8 @@ class NamedNode(TreeNode, Generic[Tree]):
653661
654662 def __init__ (self , name = None , children = None ):
655663 super ().__init__ (children = children )
656- self . _name = None
657- self .name = name
664+ _validate_name ( name )
665+ self ._name = name
658666
659667 @property
660668 def name (self ) -> str | None :
@@ -663,11 +671,13 @@ def name(self) -> str | None:
663671
664672 @name .setter
665673 def name (self , name : str | None ) -> None :
666- if name is not None :
667- if not isinstance (name , str ):
668- raise TypeError ("node name must be a string or None" )
669- if "/" in name :
670- raise ValueError ("node names cannot contain forward slashes" )
674+ if self .parent is not None :
675+ raise ValueError (
676+ "cannot set the name of a node which already has a parent. "
677+ "Consider creating a detached copy of this node via .copy() "
678+ "on the parent node."
679+ )
680+ _validate_name (name )
671681 self ._name = name
672682
673683 def __repr__ (self , level = 0 ):
@@ -677,11 +687,13 @@ def __repr__(self, level=0):
677687 return repr_value
678688
679689 def __str__ (self ) -> str :
680- return f"NamedNode('{ self .name } ')" if self .name else "NamedNode()"
690+ name_repr = repr (self .name ) if self .name is not None else ""
691+ return f"NamedNode({ name_repr } )"
681692
682693 def _post_attach (self : AnyNamedNode , parent : AnyNamedNode , name : str ) -> None :
683694 """Ensures child has name attribute corresponding to key under which it has been stored."""
684- self .name = name
695+ _validate_name (name ) # is this check redundant?
696+ self ._name = name
685697
686698 def _copy_node (
687699 self : AnyNamedNode ,
0 commit comments