@@ -201,6 +201,57 @@ def test_is_component_decorator_wrong_decorator(self):
201201 decorator = tree .body [0 ].decorator_list [0 ]
202202
203203 assert parser ._is_component_decorator (decorator ) is False
204+
205+ def test_extract_decorator_name_component (self , temp_dir ):
206+ """Test extracting name parameter from @dsl.component decorator."""
207+ component_file = temp_dir / "component.py"
208+ component_file .write_text ("""
209+ from kfp import dsl
210+
211+ @dsl.component(name='custom-component-name', base_image='python:3.10')
212+ def my_component(param: str) -> str:
213+ '''A component with custom name in decorator.
214+
215+ Args:
216+ param: Input parameter.
217+
218+ Returns:
219+ Output value.
220+ '''
221+ return param
222+ """ )
223+
224+ parser = ComponentMetadataParser (component_file )
225+
226+ # Test finding the function
227+ function_name = parser .find_function ()
228+ assert function_name == 'my_component'
229+
230+ # Test extracting decorator name from AST (without executing the code)
231+ decorator_name = parser ._get_name_from_decorator_if_exists ('my_component' )
232+
233+ # Should extract the decorator name
234+ assert decorator_name == 'custom-component-name'
235+
236+ def test_extract_decorator_name_component_no_name (self , temp_dir ):
237+ """Test extracting name when decorator has no name parameter."""
238+ component_file = temp_dir / "component.py"
239+ component_file .write_text ("""
240+ from kfp import dsl
241+
242+ @dsl.component(base_image='python:3.10')
243+ def my_component(param: str) -> str:
244+ '''A component without custom name in decorator.'''
245+ return param
246+ """ )
247+
248+ parser = ComponentMetadataParser (component_file )
249+
250+ # Test extracting decorator name (should return None)
251+ decorator_name = parser ._get_name_from_decorator_if_exists ('my_component' )
252+
253+ # Should return None when no name in decorator
254+ assert decorator_name is None
204255
205256
206257class TestPipelineMetadataParser :
@@ -283,4 +334,55 @@ def test_is_pipeline_decorator_wrong_decorator(self):
283334 decorator = tree .body [0 ].decorator_list [0 ]
284335
285336 assert parser ._is_pipeline_decorator (decorator ) is False
337+
338+ def test_extract_decorator_name_pipeline (self , temp_dir ):
339+ """Test extracting name parameter from @dsl.pipeline decorator."""
340+ pipeline_file = temp_dir / "pipeline.py"
341+ pipeline_file .write_text ("""
342+ from kfp import dsl
343+
344+ @dsl.pipeline(name='custom-pipeline-name', description='A test pipeline')
345+ def my_pipeline(input_data: str) -> str:
346+ '''A pipeline with custom name in decorator.
347+
348+ Args:
349+ input_data: Input data path.
350+
351+ Returns:
352+ Output data path.
353+ '''
354+ return input_data
355+ """ )
356+
357+ parser = PipelineMetadataParser (pipeline_file )
358+
359+ # Test finding the function
360+ function_name = parser .find_function ()
361+ assert function_name == 'my_pipeline'
362+
363+ # Test extracting decorator name from AST (without executing the code)
364+ decorator_name = parser ._get_name_from_decorator_if_exists ('my_pipeline' )
365+
366+ # Should extract the decorator name
367+ assert decorator_name == 'custom-pipeline-name'
368+
369+ def test_extract_decorator_name_pipeline_no_name (self , temp_dir ):
370+ """Test extracting name when decorator has no name parameter."""
371+ pipeline_file = temp_dir / "pipeline.py"
372+ pipeline_file .write_text ("""
373+ from kfp import dsl
374+
375+ @dsl.pipeline(description='A test pipeline')
376+ def my_pipeline(input_data: str) -> str:
377+ '''A pipeline without custom name in decorator.'''
378+ return input_data
379+ """ )
380+
381+ parser = PipelineMetadataParser (pipeline_file )
382+
383+ # Test extracting decorator name (should return None)
384+ decorator_name = parser ._get_name_from_decorator_if_exists ('my_pipeline' )
385+
386+ # Should return None when no name in decorator
387+ assert decorator_name is None
286388
0 commit comments