At the moment, the presence of a KeyError anywhere in the code is effectively masked by the the resource not found logic.
so my question is what are you doing (or expecting to happen) inside __getitem__ where you get unexpected key errors?
If this isn't making sense, you'll need to provide some clearer info on what you mean by "resource not found" and what exact behavior you're seeing in your app.
It seems that if I want to make this reasonably fool-proof I have to invent my own traverser. Any advice on that front?
I don't think you need to implement a new traverser you just need to provide acustomized __getitem__ to be used by your users and handle all issues you described there.For example provide a decorator and introduce a NoRessource Exception and to be usedinstead of KeyError.
Though 'MultiTraverser' sounds like you already have replaced the default traverser?
I thought about this point some time ago but I don't think it is a problem in general:
- if you write a unit test you are likely to test your code without traverser so you will get plain Key errors
- __getitem__ is not the place to put your application logic
If you want to extend pyramid or create a new framework on top you need to provide some codeto be used by users. Either as base classes, decorators or pyramid level replacements. This doesn'tmean users cannot use __getitem__.
But the solution is probably just awareness in this case. It'sunlikely that the interface will change. It's a "gotcha" :-).
It's a fundamental problem with APIs that try to mimic the built-indict- and/or sequence types, what's sometimes called being "pythonic".
you probably can choose where your users might write code. per suggestion above, maybe overriding __getitem__ isn't the best way for you?
do you have code or pseudo code you can share? It might help understand exactly whether the issue is something that can be more simply handled a different way or whether you are trying something legitimately not easy to do with the framework as it is. I'm guessing there is an easier/simpler way, but it's hard to be sure with more concrete examples of what you want to do.
--
In essence, you stated that you want to have "inexperienced users" writing "untested code" that simply works. That is a very ambitious goal and you probably have a great deal of work to do beyond getting traversal to function, in order to have any hope of having system that can be stable and maintainable by inexperienced users.
Are any exception messages going to be clear enough for them to know how to take corrective action to fix an unforeseen problem in their own code, without understanding the Pyramid internals? You probably need a whole layer of code checking/introspection with custom feedback to guide the users - *before* they deploy their code into the live system.
If someone wants to select the color of their car at a dealership, they don't hand them the manual for the painting robot at the assembly plant, even if it is "the best painting robot manual ever written".
If you don't handle all the possible problems in your code, it seems you are simply delaying the point where your users must become Pyramid developers, to when they experience their first bug and have to crack open the Pyramid documentation to figure out how to fix it.
For most people building stuff on top of Pyramid, the fact that it is simple, stable, and thoroughly tested is of greater importance then the ease of integrating it into every conceivable use case. I really do not need or want a bunch of framework-specific exceptions thrust upon me to add to my learning curve. And if I someday want some, I will override what I need to in order to add them.
I think that is probably what you are going too need to do.
I'm not sure _as an experienced python developer_ how to write code which guarantees it doesn't raise a KeyError
this is just an idea, but you could catch KeyError s and log the stacktrace before re-raising, that might help.
Inside of your __getitem__ you have total control over what that method will return. You only want a KeyError to be raised if you are sure that the goal is to exit with no context. Thus, define what you mean by no context as "class NoContext(Exception): pass" .def __getitem__(self, key):try:# stuff to find contextreturn contextexcept NoContext:raise KeyErrorexcept KeyError:raise SomeOtherExceptionThatIsNotKeyError
Here's yet another alternative that may be easier to swallow:
--
This still seems to come down to "fuzzy" requirement definitions.What is your distinction between "users" and "developers"?What functionality do you expect to control vs. other developers/users controlling?There is a range of answers for both questions that are workable, but you seem to be talking about several points on each one at the same time.