1414
1515class MethodRename (ABAction ):
1616 """
17- Renames an existing method in the Brightway2 data structure .
17+ Rename an existing impact assessment method (impact category) .
1818
19- This method allows renaming a single method by prompting the user for a new name.
20- It ensures that only one method is renamed at a time, validates the new name, and
21- updates the method in the Brightway2 database.
22-
23- Args:
24- method_name (tuple[str] | list[tuple[str]]): The name of the method to rename.
25- If a list is provided, it must contain exactly one tuple.
26-
27- Steps:
28- - Ensure only one method is being renamed at a time.
29- - Check if the method exists in the Brightway2 database.
30- - Open a dialog to prompt the user for the new method name.
31- - Validate the new name to ensure it is not empty and does not already exist.
19+ Flow:
20+ - Ensure only one method is selected and it exists.
21+ - Prompt the user for the new name and validate it.
3222 - Copy the method to the new name and process it.
33- - Emit a signal to notify that the method has been renamed.
34- - Deregister the old method.
23+ - Update all Brightway calculation setups by replacing the old method in 'ia' lists with
24+ the new name and serialize the updates.
25+ - Emit a rename signal and deregister the old method.
3526
3627 Raises:
37- ValueError: If more than one method is provided for renaming.
38- RuntimeError: If the method does not exist, the new name is empty, or the new name already exists.
28+ - ValueError: If more than one method is provided for renaming.
29+ - RuntimeError: If the method does not exist, the new name is empty, or the new name already exists.
3930 """
4031
4132 text = "Rename Impact Category"
@@ -57,14 +48,13 @@ def run(method_name: tuple[str] | list[tuple[str]]):
5748
5849 # open dialog to get new name
5950 dialog = widgets .ABListEditDialog (
60- method_name ,
61- title = "Rename Impact Category" ,
62- parent = application .main_window
51+ method_name ,
52+ title = "Rename Impact Category" ,
53+ parent = application .main_window ,
6354 )
64- dialog .exec_ ()
6555
66- # if dialog was cancelled, do nothing
67- if not dialog .result () = = QtWidgets .QDialog .Accepted :
56+ # execute the dialog and check for acceptance
57+ if dialog .exec_ () ! = QtWidgets .QDialog .Accepted :
6858 return
6959
7060 new_name = dialog .get_data (as_tuple = True )
@@ -82,9 +72,41 @@ def run(method_name: tuple[str] | list[tuple[str]]):
8272 # copy method to new name and process
8373 method .copy (new_name ).process ()
8474
75+ # Update any calculation setups that reference this method
76+ MethodRename .rename_method_in_calculation_setups (method_name , new_name )
77+
8578 # this should not happen like this, as the model and therefore signals should be handled declaritavely,
8679 # but since method renaming is not native to bw2data we have to do it manually here
8780 signals .method .renamed .emit (method_name , new_name )
8881
8982 # deregister old method
9083 method .deregister ()
84+
85+ @staticmethod
86+ def rename_method_in_calculation_setups (old_name : tuple , new_name : tuple ) -> None :
87+ """Replace occurrences of old_name with new_name in all CS 'ia' lists and serialize.
88+
89+ Handles both tuple and single-string method keys. Best-effort: logs on failure
90+ without blocking the rename flow.
91+ """
92+ try :
93+ changed_any = False
94+
95+ for cs_name , cs in bd .calculation_setups .items ():
96+ ia = cs .get ("ia" , [])
97+
98+ if old_name not in ia :
99+ continue
100+
101+ i = ia .index (old_name )
102+ ia [i ] = new_name
103+
104+ changed_any = True
105+ log .info (
106+ f"Updated calculation setup '{ cs_name } ': renamed impact category { old_name } -> { new_name } "
107+ )
108+
109+ if changed_any :
110+ bd .calculation_setups .serialize ()
111+ except Exception :
112+ log .exception ("Failed to update calculation setups after method rename" )
0 commit comments