Okay.
First, the Pyglet speech thing. Turn typing echo off or put the screen reader in sleep mode. Count on keys being spoken. Whether or not the keys will get spoken depends so ridiculously on the screen reader it's not even funny. None of us can take over Pyglet, and I feel like you're just trying to find reasons to complain at me about it. If you really don't want Pyglet, ignore me and don't have it.
Second, you are using what most people I can think of would consider bad code structure. Among other things, it intrinsically links the receiving of events to the tick, which only holds true for naive implementations like Pygame. It makes it such that you need to use if statements all down your tick method, making it hard to actually conceptualize it in one small piece. If you ever want control remapping or anything like that and you're using this approach, you're probably going to have to pollute the whole app with it. All keyboard code has to run every tick, rather than just happening when a key happens. You are probably building a dictionary of every possible event and whether it happened, which is expensive. If you aren't, then I need to start checking to see what's in the dict or not. If you are re-using the dict, I give you 3 months before someone does the obvious thing of throwing extra stuff in it and expecting it to be there later. Port to a different framework and the code to manage that dict becomes complicated: what if I press and release a key before the tick interval completes? And finally, you can't respond to the keyboard immediately, which will make everything laggy unless you're using a pretty high tick rate.
But more generally, classes are an accepted way to do something and the pattern therein is used by most libraries. You almost never see something like this, and trying to force BGT into Python isn't going to actually help anyone much. If you really want to offer this functionality, build it on top of what I'm suggesting. Aim to minimize if statements whenever possible, as if statements are complexity. Encourage the use of well-named flags because if needs_jump is way better than if key=="space" for readability in 6 months. Use subclassing because it's an accepted convention and because encouraging the use of subclassing is usually a good thing for game design.
if you really want to make this convenient, make an @on_key("space") decorator and let people use that.
To go back to one thing that deserves elaboration, the key response shouldn't happen on the tick. Doing this in a menu will make it feel laggy unless the tick rate is high, and most people don't want or need to run that high. Part of the Pyglet event loop lets you avoid running hot while still giving you the events as they happen, but you can't really duplicate that in Pygame to my knowledge. To that end, your main loop probably needs to end up running as fast as it can with very, very small sleeps and some conditions to see if enough time has passed to tick stuff. You can cover up the fact that the game is ticking slowly by playing sounds immediately when keys are pressed, and then carrying out the actions in a couple hundredths of a second at the next tick. You are trying to bring a BGT concept that is bad out of BGT, and I strongly encourage you to not do that if at all possible. Yes, its simple to do what you're doing. but it's almost as simple to do what I'm doing, your code self-documents, and you keep flexibilities in the API and the logic that you don't have right now.
Twitter: @ajhicks1992