help(re.sub) says:
sub(pattern, repl, string, count=0)
and re.IGNORECASE has a value of 2.
Therefore this:
re.sub("_", "X", subject, re.IGNORECASE)
is telling it to replace at most 2 occurrences of "_".

Oh, that's embarrassing. :-)
Could a type-check be used to alert the user to their mistake? I suppose that would require re.IGNORECASE (et al) to be of some new type (presumably sub-classed from Integer).
(Thanks for the quick response, and sorry to waste your time)