Source code for weblayer.method

#!/usr/bin/env python
# -*- coding: utf-8 -*-

""" :py:mod:`weblayer.method` provides :py:class:`ExposedMethodSelector`, an 
  implementation of :py:class:`~weblayer.interfaces.IMethodSelector`.
  
  :py:class:`ExposedMethodSelector` works in tandem with 
  ``RequestHandler.__all__`` to select only explicitly exposed request handler
  methods to handle incoming requests::
  
      >>> class MockHandler(object):
      ...     implements(IRequestHandler)
      ...     
      ...     __all__ = ('get')
      ...     
      ...     def get(self):
      ...         pass
      ...         
      ...     
      ...     def post(self):
      ...         pass
      ...         
      ...     
      ... 
      >>> handler = MockHandler()
      >>> selector = ExposedMethodSelector(handler)
      >>> callable(selector.select_method('GET'))
      True
      >>> callable(selector.select_method('POST'))
      False
  
"""

__all__ = [
    'ExposedMethodSelector'
]

from zope.component import adapts
from zope.interface import implements

from interfaces import IRequestHandler, IMethodSelector

[docs]class ExposedMethodSelector(object): """ Method selector adapter that works in tandem with the ``RequestHandler.__all__`` attribute. """ adapts(IRequestHandler) implements(IMethodSelector) def __init__(self, context): self.context = context
[docs] def select_method(self, method_name): """ Returns ``getattr(self, method_name)`` iff the method exists and is exposed. Otherwise returns ``None``. Special cases HEAD requests to use GET, iff ``'head'`` is exposed, ``def get()`` exists and ``def head()`` doesn't. This allows applications to respond to HEAD requests without writing seperate head methods and takes advantage of the special case in ``webob.Response.__call__``:: def __call__(self, environ, start_response): # ... code removed for brevity if environ['REQUEST_METHOD'] == 'HEAD': # Special case here... return EmptyResponse(self.app_iter) return self.app_iter """ if not isinstance(method_name, basestring): raise ValueError if not hasattr(self.context, '__all__'): return None method_name = method_name.lower() if method_name in self.context.__all__: method = getattr(self.context, method_name, None) if method_name == 'head' and method is None: # special case if 'get' in self.context.__all__: method = getattr(self.context, 'get', None) return method