@@ -537,3 +537,90 @@ def test_Lattice():
537537 assert lattice .branches [1 ].name == "line2"
538538 assert lattice .branches [0 ].line == [element1 , element2 , element3 ]
539539 assert lattice .branches [1 ].line == [element3 ]
540+
541+
542+ def test_BeamLine_with_string_references ():
543+ """Test BeamLine with string references to elements defined elsewhere"""
544+ import yaml
545+
546+ # Test YAML deserialization with string references
547+ yaml_data = """
548+ fodo_cell:
549+ kind: BeamLine
550+ line:
551+ - drift1
552+ - quad1
553+ - drift2:
554+ kind: Drift
555+ length: 0.5
556+ """
557+
558+ data = yaml .safe_load (yaml_data )
559+ beamline = pals .BeamLine (** data )
560+
561+ assert beamline .name == "fodo_cell"
562+ assert len (beamline .line ) == 3
563+
564+ # First element should be a PlaceholderName that behaves like the string "drift1"
565+ assert isinstance (beamline .line [0 ], pals .PlaceholderName )
566+ assert beamline .line [0 ] == "drift1"
567+ assert beamline .line [0 ].name == "drift1"
568+ assert beamline .line [0 ].element is None # Not yet resolved
569+ assert not beamline .line [0 ].is_resolved ()
570+
571+ # Second element should be a PlaceholderName that behaves like the string "quad1"
572+ assert isinstance (beamline .line [1 ], pals .PlaceholderName )
573+ assert beamline .line [1 ] == "quad1"
574+ assert beamline .line [1 ].name == "quad1"
575+ assert beamline .line [1 ].element is None # Not yet resolved
576+ assert not beamline .line [1 ].is_resolved ()
577+
578+ # Third element should be a Drift object
579+ assert isinstance (beamline .line [2 ], pals .Drift )
580+ assert beamline .line [2 ].name == "drift2"
581+ assert beamline .line [2 ].length == 0.5
582+
583+ # Test that we can resolve the reference later
584+ drift_element = pals .Drift (name = "drift1" , length = 1.0 )
585+ beamline .line [0 ].element = drift_element
586+ assert beamline .line [0 ].is_resolved ()
587+ assert beamline .line [0 ].element .name == "drift1"
588+ assert beamline .line [0 ].element .length == 1.0
589+
590+
591+ def test_PlaceholderName_direct ():
592+ """Test PlaceholderName creation and behavior directly"""
593+ # Test creation with positional argument
594+ ref1 = pals .PlaceholderName ("test_element" )
595+ assert ref1 .name == "test_element"
596+ assert str (ref1 ) == "test_element"
597+ assert ref1 == "test_element"
598+ assert not ref1 .is_resolved ()
599+
600+ # Test creation with keyword argument
601+ ref2 = pals .PlaceholderName (name = "another_element" )
602+ assert ref2 .name == "another_element"
603+ assert str (ref2 ) == "another_element"
604+ assert ref2 == "another_element"
605+
606+ # Test hash (for use in sets/dicts)
607+ ref_set = {ref1 , ref2 }
608+ assert len (ref_set ) == 2
609+ assert ref1 in ref_set
610+
611+ # Test resolution
612+ drift = pals .Drift (name = "test_element" , length = 2.5 )
613+ ref1 .element = drift
614+ assert ref1 .is_resolved ()
615+ assert ref1 .element .length == 2.5
616+
617+ # Test repr
618+ assert "test_element" in repr (ref1 )
619+ assert "resolved" in repr (ref1 )
620+ assert "unresolved" in repr (ref2 )
621+
622+ # Test that element is a reference, not a copy
623+ assert ref1 .element is drift # Same object identity
624+ # Modify the original and verify the reference sees the change
625+ drift .length = 3.0
626+ assert ref1 .element .length == 3.0 # Change is visible through reference
0 commit comments