Repository: frappe/frappe

Issue:
Rename DocType doesn't update controller files correctly
branch  version-12

Created a doctype called "Deliverable" added fields and some test data
Tried to rename the doctype to "Deliverable Definitions". System warned about "updating controllers" but seemed to save.

From then on I got:

18:40:21 web.1            |   File "/home/mcd_steven/frappe-bench/apps/clearsight/c
learsight/model/doctype/deliverable_definitions/deliverable_definitions.py", line 9
18:40:21 web.1            |     class DeliverableDefinitions Definitions(Document):
18:40:21 web.1            |                                            ^
18:40:21 web.1            | **SyntaxError: invalid syntax**

Bench showed blank pages for all my doctypes

The only way to fix was to delete the doc type and start again



Discussion:
In some cases, renaming controller files and their references doesn't complete successfully. This seems to be one of those cases. It's not foolproof, hence, the message "Renamed files and replaced code in controllers, please check!" on rename which asks you, as the developer to check the controllers. 
This is a guess but it looks like the rename appended to the old name with a space char, the space is what caused the syntax error.

18:40:21 web.1 | class DeliverableDefinitions Definitions(Document):

Agree its not a big deal, good dev will see the issue, but these sorts of errors for a new developer evaluating frappe as potential platform may cause them to abandon frappe as unstable. I would like to see frappe be a success. 
@ollyboy If you wish to take up the task of fixing this, I can guide you. I don't have the bandwidth to fix this at the moment so, an extra pair of hands will certainly be a huge help.
Point me to the code block that creates or removes modules, will have a look
https://github.com/frappe/frappe/blob/6ed35fd9618af88fb0c4a239f7358dd8ed90a351/frappe/core/doctype/doctype/doctype.py#L402-LL412

These lines update the contents of the DocType's files on rename
Here is your problem, these consecutive code lines do the same thing

`file_content = code.replace(old, new) # replace str with full str (js controllers)`

so  "Definitions" becomes "Deliverable Definitions"

`file_content = file_content.replace(frappe.scrub(old), frappe.scrub(new)) # replace str with _ (py imports)`

Now the Definitions gets replaced again so we get  "DeliverableDefinitions Definitions"

This code will fail if there is any string section in the old name that is the same as new name. Code will only work if old and new name have different words. 
> @ollyboy If you wish to take up the task of fixing this, I can guide you. I don't have the bandwidth to fix this at the moment so, an extra pair of hands will certainly be a huge help.

As I mentioned earlier, I'm aware of why it happens. Do you have a solution or is it just **my** problem?
Im not a phyton programmer ( can do C and php ) and there is no documentation on things like frappe.scrub. I thought my analysis and solution was quite good, one of these two lines needs to be removed as they both try to replace the same string value. Why would you hand it to me if you were aware that the double string replace was the issue, its a one-line change for any competent frappe developer? Please fix or close, my time on this issue is over. 

Resolving patch:
diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py
--- a/frappe/core/doctype/doctype/doctype.py
+++ b/frappe/core/doctype/doctype/doctype.py
@@ -406,9 +406,13 @@ def rename_inside_controller(self, new, old, new_path):
 				with open(fname, 'r') as f:
 					code = f.read()
 				with open(fname, 'w') as f:
-					file_content = code.replace(old, new) # replace str with full str (js controllers)
-					file_content = file_content.replace(frappe.scrub(old), frappe.scrub(new)) # replace str with _ (py imports)
-					file_content = file_content.replace(old.replace(' ', ''), new.replace(' ', '')) # replace str (py controllers)
+					if fname.endswith('.js'):
+						file_content = code.replace(old, new) # replace str with full str (js controllers)
+
+					elif fname.endswith('.py'):
+						file_content = code.replace(frappe.scrub(old), frappe.scrub(new)) # replace str with _ (py imports)
+						file_content = file_content.replace(old.replace(' ', ''), new.replace(' ', '')) # replace str (py controllers)
+
 					f.write(file_content)
 
 		# updating json file with new name


Test patch: