Re: [Repoze-dev] Handling webob.exc.HTTPException in router.

2010-04-04 Thread Chris McDonough
We worked this out on IRC.  Conclusion: the patch is just about right.  We 
decided to make the following tweaks:

- Allow route-specific exception views.

- Don't use ZCML to register the default exception views (instead, do that in 
Configurator.setup_registry).

- No new ZCML directives of configurator APIs are necessary, but we need to 
make set_notfound_view and set_forbidden_view continue to work.

- C


On 4/1/10 9:29 AM, Andrey Popp wrote:
 Sorry, I forgot to attach patch.

 On Thu, Apr 1, 2010 at 5:28 PM, Andrey Popp8may...@gmail.com  wrote:
 Hello,

 I have a preview for exception views functionality.

 I've refactored Router to handle exceptions via IView lookups on
 IRequest, Exception class. That means all exception views should be
 global (not belongs to specific route) and exception views can be
 clashed with ordinary views.

 Forbidden and NotFound views are special case of exception views now.
 Default views for that exceptions are registered via
 repoze.bfg.includes/configure.zcml.

 All tests are pass, 5 tests cases was removed and 7 new was added.

 If you like it, I will make other changes related to exception views
 configuration (possibly add methods to Configurator API and new ZCML
 directive?).

 Thanks.

 On Fri, Mar 12, 2010 at 5:27 AM, Chris McDonoughchr...@plope.com  wrote:
 On 3/10/10 9:59 AM, Andrey Popp wrote:

 The context of such an exception view will be the exception instance
 itself.  If you want a particular exception to be able to use a real
 context, you'll make it available as an attribute of the exception for
 use
 by the registered exception view (e.g. context.context or so).

 Thanks, this is that I was talking about. Will try to implement.


 Great.  This would be an excellent feature to have.

 --
 Chris McDonough
 Agendaless Consulting, Fredericksburg VA
 The repoze.bfg Web Application Framework Book: http://bfg.repoze.org/book




 --
 Andrey Popp

 phone: +7 911 740 24 91
 e-mail: 8may...@gmail.com






-- 
Chris McDonough
Agendaless Consulting, Fredericksburg VA
The repoze.bfg Web Application Framework Book: http://bfg.repoze.org/book
___
Repoze-dev mailing list
Repoze-dev@lists.repoze.org
http://lists.repoze.org/listinfo/repoze-dev


Re: [Repoze-dev] Handling webob.exc.HTTPException in router.

2010-03-10 Thread Chris McDonough
On 3/10/10 9:07 AM, Andrey Popp wrote:
 I was thinking of this too — it is good to return control back to
 application during handling of this kind of errors (4xx). Also it will
 convert notfound/forbidden views from special cases of Router
 processing cycle to special cases of exception view.


 Right, I think it makes sense... do you think you might want to take a stab
 at implementing that?

 Ok, what about reusing the current view registering/lookup machinery?
 I mean can we treat exception views as views for context defined by
 raised exception? So raising exception is just context switching
 inside request processing.

 Pros:

 * We can define different exception views for different request predicates.
 * Unification with view machinery.

 Cons:

 * We cannot access previously located context (if there was one),
 cause it replaced with current exception context.
 * We should register exception views for exception interfaces, not
 classes. This is because adapter lookup uses IRO, not standard MRO.


I think it should probably work like this:

- app developers should register views that match with a context that
   equals the exception class itself, the default request type, and
   the empty string as a view name.

- when bfg encounters any exception when calling a view (or trying to
   resolve a root factory, etc.. basically the scope handled currently
   when it catches NotFound/Forbidden), it will do this:

  exc_view = registry.adapters.lookup((req_iface, providedBy(exc)), IView,
 name='')
  if exc_view is not None:
 response = exc_view(exc, request)

The context of such an exception view will be the exception instance itself. 
  If you want a particular exception to be able to use a real context, you'll 
make it available as an attribute of the exception for use by the registered 
exception view (e.g. context.context or so).

-- 
Chris McDonough
Agendaless Consulting, Fredericksburg VA
The repoze.bfg Web Application Framework Book: http://bfg.repoze.org/book
___
Repoze-dev mailing list
Repoze-dev@lists.repoze.org
http://lists.repoze.org/listinfo/repoze-dev


Re: [Repoze-dev] Handling webob.exc.HTTPException in router.

2010-03-10 Thread Chris McDonough
On 3/10/10 9:54 AM, Chris McDonough wrote:

 The context of such an exception view will be the exception instance
 itself. If you want a particular exception to be able to use a real
 context, you'll make it available as an attribute of the exception for
 use by the registered exception view (e.g. context.context or so).


(Note also that, if it has been found, the real context is also available as 
request.context).

- C


-- 
Chris McDonough
Agendaless Consulting, Fredericksburg VA
The repoze.bfg Web Application Framework Book: http://bfg.repoze.org/book
___
Repoze-dev mailing list
Repoze-dev@lists.repoze.org
http://lists.repoze.org/listinfo/repoze-dev


Re: [Repoze-dev] Handling webob.exc.HTTPException in router.

2010-03-10 Thread Andrey Popp
 - app developers should register views that match with a context that
  equals the exception class itself, the default request type, and
  the empty string as a view name.

 - when bfg encounters any exception when calling a view (or trying to
  resolve a root factory, etc.. basically the scope handled currently
  when it catches NotFound/Forbidden), it will do this:

     exc_view = registry.adapters.lookup((req_iface, providedBy(exc)), IView,
                name='')
     if exc_view is not None:
        response = exc_view(exc, request)

 The context of such an exception view will be the exception instance
 itself.  If you want a particular exception to be able to use a real
 context, you'll make it available as an attribute of the exception for use
 by the registered exception view (e.g. context.context or so).

Thanks, this is that I was talking about. Will try to implement.

-- 
Andrey Popp

phone: +7 911 740 24 91
e-mail: 8may...@gmail.com
___
Repoze-dev mailing list
Repoze-dev@lists.repoze.org
http://lists.repoze.org/listinfo/repoze-dev


Re: [Repoze-dev] Handling webob.exc.HTTPException in router.

2010-03-08 Thread Andrey Popp
 But features are *the enemy* of frameworks, so as the author I feel compelled 
 to  provide a counterargument even if I don't really believe strongly in it. 
 ;-)

I like that repoze.bfg reuses webob for WSGI layer, but why not to
reuse exceptions from that package? It is not about features, it is
more about extending view API to allow raise exceptions from webob.exc
(not all probably, but which are inherited from
webob.exc.HTTPClientError). This is like view-lookup can raise
NotFound and repoze.bfg.security — Forbidden.

 In that spirit I'll note these things:

 - you could use a decorator for the same purpose instead of relying on the
 framework to do it for you.  It would be a pretty stupid decorator, but it
 would work.

I don't think it'll be stupid because it needs to catch HTTPException
at initialzation, store it, when augment __call__ method and if the
later was raised, it should reraise it during __call__ call.

 - you could insert the webob.exc.HTTPExceptionMiddleware middleware into
 your WSGI pipeline; this indeed converts webob exceptions to responses.
  This is another way of extending the framework.

It seems to be more better way than decorating each view, but it does
not work, because there will be no INewResponse event fired and so on,
even repoze.bfg.exceptions.NotFound and webob.exc.HTTPNotFound will
not be semantically equal. That is not a good thing.

Thanks.
___
Repoze-dev mailing list
Repoze-dev@lists.repoze.org
http://lists.repoze.org/listinfo/repoze-dev


Re: [Repoze-dev] Handling webob.exc.HTTPException in router.

2010-03-08 Thread Chris McDonough
On 3/8/10 7:41 AM, Andrey Popp wrote:
 But features are *the enemy* of frameworks, so as the author I feel 
 compelled to  provide a counterargument even if I don't really believe 
 strongly in it. ;-)

 I like that repoze.bfg reuses webob for WSGI layer, but why not to
 reuse exceptions from that package? It is not about features, it is
 more about extending view API to allow raise exceptions from webob.exc
 (not all probably, but which are inherited from
 webob.exc.HTTPClientError). This is like view-lookup can raise
 NotFound and repoze.bfg.security — Forbidden.

I understand the purpose and the argument already.  I'm just saying that there 
are existing options that don't require it.

 In that spirit I'll note these things:

 - you could use a decorator for the same purpose instead of relying on the
 framework to do it for you.  It would be a pretty stupid decorator, but it
 would work.

 I don't think it'll be stupid because it needs to catch HTTPException
 at initialzation, store it, when augment __call__ method and if the
 later was raised, it should reraise it during __call__ call.

 - you could insert the webob.exc.HTTPExceptionMiddleware middleware into
 your WSGI pipeline; this indeed converts webob exceptions to responses.
   This is another way of extending the framework.

 It seems to be more better way than decorating each view, but it does
 not work, because there will be no INewResponse event fired and so on,

INewResponse is almost useless, I should have never added it, but I can't 
remove it now (feature-fear isn't always irrational!).  Middleware should 
almost always be used instead.  See the apologetic sidebar in 
http://docs.repoze.org/bfg/1.2/api/events.html#repoze.bfg.events.NewResponse .
The idea that we'd use the existence of this misfeature as a rationale to add 
more features is not good.

 even repoze.bfg.exceptions.NotFound and webob.exc.HTTPNotFound will
 not be semantically equal. That is not a good thing.

The fact that these two exceptions are named similarly doesn't necessarily mean 
they should be handled the same.  If someone is currently using 
webob.exc.HTTPExceptionMiddleware, they are depending on the exception bubbling 
up.

In particular, if we do catch webob.exc.HTTPNotFound in the same exception 
handler currently serviced by r.b.exceptions.NotFound, it will mean:

- a behavior change that may break folks who already rely on middleware
   to convert webob exceptions to responses.

- an invitation to convert other webob exceptions into responses within the
   router.  For instance, if we went purely by name similarlty, HTTPForbidden
   would then  logically need to be caught by the current Forbidden exception
   handler.  Then we'd need to start to argue about whether HTTPUnauthorized
   should map to the Forbidden exception handler, and so on.

- we'd open up the door to asking for other special purpose exception views.
   We might be asked to add other special case exception handlers and exception
   views based on WebOb's various exceptions; I could see someone asking for a
   500 view when any 500-series webob exception was caught.

It just becomes a bit of a rabbit hole.  The rabbit hole is avoided entirely if 
the we document that people should just put the 
webob.exc.HTTPExceptionMiddleware middleware into their WSGI pipeline if they 
want WebOb exceptions to be converted to responses.

OTOH, it'd be reasonable to provide a generic exception view facility like 
Zope's where users can map any exception type to a particular view; this is 
definitely less adhoc and requires less documentation.  I'd be +1 on such a 
feature, I think.  At least without thinking about it really hard at the 
moment. ;-)

- C
___
Repoze-dev mailing list
Repoze-dev@lists.repoze.org
http://lists.repoze.org/listinfo/repoze-dev


Re: [Repoze-dev] Handling webob.exc.HTTPException in router.

2010-03-08 Thread Chris McDonough
On 3/8/10 5:23 PM, Andrey Popp wrote:
 - a behavior change that may break folks who already rely on middleware
   to convert webob exceptions to responses.

 It is reasonable -1 for my proposal.

FTR, bw compat is about the weakest argument, I think.  Backwards compatibility 
can always be sacrificed as long as the docs spell out how to fix things for 
upgraders.

 It just becomes a bit of a rabbit hole.  The rabbit hole is avoided entirely
 if the we document that people should just put the
 webob.exc.HTTPExceptionMiddleware middleware into their WSGI pipeline if
 they want WebOb exceptions to be converted to responses.

 Yes, it would be great, cause I did not know about existence of that
 middleware before start of our discussion.

I'll try to add it somewhere in the docs, or at least somewhere in 
http://bfg.repoze.org/tutorialbin.  By the way, have you tried it?  It looks 
like it should work...


 OTOH, it'd be reasonable to provide a generic exception view facility like
 Zope's where users can map any exception type to a particular view; this is
 definitely less adhoc and requires less documentation.  I'd be +1 on such a
 feature, I think.  At least without thinking about it really hard at the
 moment. ;-)

 I was thinking of this too — it is good to return control back to
 application during handling of this kind of errors (4xx). Also it will
 convert notfound/forbidden views from special cases of Router
 processing cycle to special cases of exception view.


Right, I think it makes sense... do you think you might want to take a stab at 
implementing that?

-- 
Chris McDonough
Agendaless Consulting, Fredericksburg VA
The repoze.bfg Web Application Framework Book: http://bfg.repoze.org/book
___
Repoze-dev mailing list
Repoze-dev@lists.repoze.org
http://lists.repoze.org/listinfo/repoze-dev


Re: [Repoze-dev] Handling webob.exc.HTTPException in router.

2010-03-07 Thread Chris McDonough
On 3/7/10 6:46 PM, Andrey Popp wrote:
 I have ideological question -- why not to handle
 webob.exc.HTTPException in router? I think it is very useful, consider
 for example the following case:

 I need to define some views that works with JSON encoded request body,
 so there is base class for them:

  class JSONView(object):
  def __init__(self, context, request):
  try:
  request.json = json.loads(request.body)
  except ValueError:
   raise webob.exc.HTTPBadRequest()
  self.request = request

 So webob.exc.HTTPBadRequest will be propagated up to Router.

I don't have a 100% reasonable answer.  It's a bit of a grey area.

The most reasonable answer is that this *does* work:

   class JSONView(object):
   def __init__(self, context, request):
   try:
   request.json = json.loads(request.body)
   except ValueError:
return webob.exc.HTTPBadRequest()
   self.request = request

Instances of exceptions in webob.exc are themselves responses, so they can be 
returned from a view function.

I can see the attraction in making the router able to handle a WebOb exception 
that implies a response.  Given that returning the exception instance does the 
same thing, it was just easier to document one way (e.g. in 
http://docs.repoze.org/bfg/1.2/narr/views.html#using-a-view-callable-to-do-a-http-redirect).

- C


___
Repoze-dev mailing list
Repoze-dev@lists.repoze.org
http://lists.repoze.org/listinfo/repoze-dev


Re: [Repoze-dev] Handling webob.exc.HTTPException in router.

2010-03-07 Thread Chris McDonough
On 3/7/10 7:36 PM, Andrey Popp wrote:
 Yes, I know I can make it work by returning webob.exc.HTTPException
 objects as response. But the point was to decode JSON request at view
 initialization phase and raise webob.exc.HTTPBadRequest if needed, so
 in subclasses at request processing phase (__call__ method) I always
 will have well-formed request objects.

That makes sense.

If I weren't the author of the framework, and someone suggested that converting 
WebOb exceptions to responses shouldn't be a feature of the framework, I'd 
think they were being pretty silly.  But features are *the enemy* of 
frameworks, so as the author I feel compelled to provide a counterargument even 
if I don't really believe strongly in it. ;-)  Apologies in advance.

In that spirit I'll note these things:

- you could use a decorator for the same purpose instead of relying on the 
framework to do it for you.  It would be a pretty stupid decorator, but it 
would work.

- you could insert the webob.exc.HTTPExceptionMiddleware middleware into your 
WSGI pipeline; this indeed converts webob exceptions to responses.  This is 
another way of extending the framework.

 By looking at the Router code it seems that handling
 repoze.bfg.exceptions.NotFound/Forbidden is some kind of bonus feature
 for views, because it is more intended for serving repoze.bfg.security
 and context finding/view lookup mechanisms, isn't it?

Originally they were only intended to be raised within views, but we changed 
things around so they can be raised within root factories and so on.

- C
___
Repoze-dev mailing list
Repoze-dev@lists.repoze.org
http://lists.repoze.org/listinfo/repoze-dev