bpo-44554: refactor pdb targets (and internal tweaks) by jaraco · Pull Request #26992 · python/cpython
I think you are using it too loosely. A refactor improves the code without changing its behavior.
I've updated the blurb and PR title to reflect that it's more than a refactor. But I do genuinely expect this change to result in no significant behavior change. Can you point to a behavior change that you think is more than a refactor?
I'm also not sure about the motivation here. We have a fix for the reported bug.
The motivation comes from my observation here that when the target is a script, there's a separate check for its existence (and similarly later a separate trap for bad syntax) that doesn't go through the Pdb interactive module. In my opinion, passing an invalid module to -m is equivalent to passing a non-existent script and should be handled similarly. I would not expect the interactive prompt to appear if a non-executable module is indicated as a runpy target. In other words, I don't expect Pdb to break into runpy code any more than I would expect it to break into CPython code if a script didn't exist or had a syntax error.
As I analyzed the issue, following your analysis and initial patch, I felt uneasy with adding the .botframe property. I asked myself, why is the botframe property needed for only this use case? And as you found, it's because the Bdb.run is never called. That got me thinking - the Pdb interactive prompt probably shouldn't be invoked at all if .run is never reached. So I asked myself, why is .run never reached in this case, and it's because runpy is raising an exception loading the module and checking it for runability. And that's what led me to the consideration that the module should be checked for runability early, and a failure to pass runability shouldn't trigger the "Unhandled Exception" logic and interactive prompt.