Or they got __slots__ added, which would have the same effect.
One option, assuming that a ParseResults is hashable, would be to maintain your own dictionary that maps the results object to your own attributes. Or subclass the ParseResults and do nothing:
class ParseResults(ParseResults): pass
This will re-add a dict to it. But then you might have to monkey-patch that back into the place that creates them, which may not be a good idea.
The source code suggests that it was converted to slots for performance reasons. You could possibly ask the devs to add a userdata slot, which would be the same as just adding attributes, but safe against future changes, and wouldn’t have as big a performance cost as keeping a __dict__ on everything (since it would only be added when YOU choose to add it). In your code, the only change would be: