This branch fixes bug 172501: reject non-code patch attachements. As discussed in that bug, non-code patches are not simply rejected. Instead, if a user labels an attachment as being a patch and if the file does not look like being a patch, he is redirected to the attachment edit page, where a message tells him that Launchpad thinks that the file does not seem to be a patch. Also, the patch flag is not yet set. If the user thinks that the file is indeed a patch, he can set the flag again and LP will finally set the flag on a click on the "change" button. Similary, if a file is uploaded that looks like a patch but that is not marked as a patch, the patch flag is set by Launchpad and the user is redirected to the attachment edit page, where he can unset the flag, if he thinks that it makes sense. The detection of the file content is unfortunately overly simple. It relies function zope.contenttype.guess_content_type(), which in turn relies mostly on Python's mimetypes.guess_type(). guess_type() simply looks at the filename suffix; while guess_content_type() accepts a parameter "body", it is not used if guess_type() finds a mime type based on the filename. So, a "mis-named" file is not properly detected, which may lead to some confusion. I considered to call file(1) or to make some other use of the "magic" database, but running "file some-diff-output.diff" returned several results like "ASCII text", "UTF8 text", "C code" but nothing related to diff output. Implementation: The methods BugMessage.save_action() and BugAttachmentEditView.change_action() now make the consistency check described above. If they find an inconistency, they set next_url to canonical_url(attachment)+'?need_confirm=1'. If the bug attachment edit page is called with the GET parameter need_confirm, and additional message is displayed, and a hidden form field named "confirmation_step" is added. The latter is used by BugAttachmentEditView.change_action() to avoid that next_url is set again to the edit view, when a user confirms his setting of the "patch" flag. The label of "patch" flag is now a bit more verbose (the text was proposed by Karl). The template lib/lp/bugs/templates/bug-attachment-edit.pt displays some additional explanations, when the page is loaded with the ?need_conform" GET parameter. This text also contians a link to https://help.launchpad.net/Bugs/BugAttchements , which tries to give even more explataions of what a patch is. (I suspect that this page could be improved...) test: ./bin/test -vv -f lp.bugs stories.bugattachments = Launchpad lint = Checking for conflicts. and issues in doctests and templates. Running jslint, xmllint, pyflakes, and pylint. Using normal rules. Linting changed files: lib/lp/bugs/browser/bugattachment.py lib/lp/bugs/browser/bugmessage.py lib/lp/bugs/interfaces/bugattachment.py lib/lp/bugs/interfaces/bugmessage.py lib/lp/bugs/stories/bugattachments/10-add-bug-attachment.txt lib/lp/bugs/stories/bugattachments/20-edit-bug-attachment.txt lib/lp/bugs/templates/bug-attachment-edit.pt == Pylint notices == lib/lp/bugs/interfaces/bugattachment.py 19: [F0401] Unable to import 'lazr.enum' (No module named enum) 27: [F0401] Unable to import 'lazr.restful.fields' (No module named restful) 28: [F0401] Unable to import 'lazr.restful.declarations' (No module named restful)