+re_re = re.compile('^(re|fwd?)[:\s]\s*', re.I)
+prefix_re = re.compile('^\[([^\]]*)\]\s*(.*)$')
+
+def clean_subject(subject, drop_prefixes = None):
+ """ Clean a Subject: header from an incoming patch.
+
+ Removes Re: and Fwd: strings, as well as [PATCH]-style prefixes. By
+ default, only [PATCH] is removed, and we keep any other bracketed data
+ in the subject. If drop_prefixes is provided, remove those too,
+ comparing case-insensitively.
+
+ >>> clean_subject('meep')
+ 'meep'
+ >>> clean_subject('Re: meep')
+ 'meep'
+ >>> clean_subject('[PATCH] meep')
+ 'meep'
+ >>> clean_subject('[PATCH] meep \\n meep')
+ 'meep meep'
+ >>> clean_subject('[PATCH RFC] meep')
+ '[RFC] meep'
+ >>> clean_subject('[PATCH,RFC] meep')
+ '[RFC] meep'
+ >>> clean_subject('[PATCH,1/2] meep')
+ '[1/2] meep'
+ >>> clean_subject('[PATCH RFC 1/2] meep')
+ '[RFC,1/2] meep'
+ >>> clean_subject('[PATCH] [RFC] meep')
+ '[RFC] meep'
+ >>> clean_subject('[PATCH] [RFC,1/2] meep')
+ '[RFC,1/2] meep'
+ >>> clean_subject('[PATCH] [RFC] [1/2] meep')
+ '[RFC,1/2] meep'
+ >>> clean_subject('[PATCH] rewrite [a-z] regexes')
+ 'rewrite [a-z] regexes'
+ >>> clean_subject('[PATCH] [RFC] rewrite [a-z] regexes')
+ '[RFC] rewrite [a-z] regexes'
+ >>> clean_subject('[foo] [bar] meep', ['foo'])
+ '[bar] meep'
+ >>> clean_subject('[FOO] [bar] meep', ['foo'])
+ '[bar] meep'
+ """
+
+ if drop_prefixes is None:
+ drop_prefixes = []
+ else:
+ drop_prefixes = [ s.lower() for s in drop_prefixes ]
+
+ drop_prefixes.append('patch')
+
+ # remove Re:, Fwd:, etc