Peter,

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.

If you really want users to be able to extend or change the behavior of the
system without knowledge of the under-workings, you need to provide a safe,
controlled environment for them to work.  That could mean defining the
"object access code" in some external module, file, or database.  Then
your traverser finds and applies that code.  A big example might be the old
Zope2-based Plone with "through the web" based programming.  (OK.  Maybe
that doesn't make the point about not needing to know the inner workings,
but it does point out how difficult it can be to have users accomplish
this.)

If you want developers to extend upon your work you either provide
libraries of code that they import into their code, or you build a
framework to run their code.  Frameworks are essentially pre-coded
boilerplate.  Everyone that runs Pyramid is using the same boilerplate code
to get their code to work.  The better the framework, the less boilerplate
in your code, but there are limits.  (i.e. in Pyramid with traversal you
need __getitem__).

If other developers are directly modifying __getitem__ in the actual
objects being traversed, you have already seceded *all control*.  Unless
they follow the boilerplate of "returning an object from a dictionary-like
structure" they can do whatever they want.  They could stop traversal and
run any code they desire.  Boiler plate is already part of their lives, you
are just resisting the idea of adding more of your own.

So you either need to modify the framework as others have suggested (custom
traverser, etc.) to minimize the boiler plate, or consider forcing them to
have their objects inherit from an object you provide.  That would ensure
that the boilerplate is applied as you desire and you can handle exceptions
in one spot.  Forced inheritance is not a great idea for a framework like
Pyramid in general, but it seems that you have (hopefully) a defined scope
on "who" would be working with your solution and that it would be new
(non-legacy) code.

If your scope is actually "users = developers world-wide", they you may
need to start working on following in the footsteps Jim Fulton, Chris
McDonough, etc. and develop the next, great way to "publish Python
objects".  http://en.wikipedia.org/wiki/Zope

Best regards,
Steve

On Thu, Mar 7, 2013 at 4:04 AM, Peter Waller <[email protected]> wrote:

> On 6 March 2013 16:48, Thomas G. Willis <[email protected]> wrote:
>
>> this is just an idea, but you could catch KeyError s and log the
>> stacktrace before re-raising, that might help.
>>
>
> On 6 March 2013 16:51, Michael Merickel <[email protected]> wrote:
>
>> 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 context
>>         return context
>>     except NoContext:
>>         raise KeyError
>>     except KeyError:
>>         raise SomeOtherExceptionThatIsNotKeyError
>>
>
> The point I've been trying to make is that I also don't control the
> `__getitem__` because I want other people to write them. These people may
> never share their code with me.
>
> In addition, IMO this isn't a pythonic solution. The try/except would have
> to go in every resource written which is silly boilerplate. This is because
> except for the most trivial implementations I can't guarantee that code
> won't unintentionally cause a KeyError. Re-raising the true KeyError as a
> different exception loses information about the nature (the key, the stack
> trace) of the original exception. It makes KeyError special. It changes the
> semantics that a KeyError is used to denote a non-existing resource. None
> of the above is ideal, but maybe I should get over it.
>
> In my mind, the traversal *structure* is awesome for my use case and I
> still love it. I'm beginning to think that in my replacement traverser I
> should lose the idea that resources should pretend to be dictionaries and
> instead use a different protocol. For example, instead of `__getitem__` I
> could call it `child`, then I could have my own exception for resources
> which don't exist, or a convention that it returns None.
>
> --
> You received this message because you are subscribed to the Google Groups
> "pylons-discuss" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"pylons-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to