33import collections
44import collections .abc
55
6+ import six
7+
68import restea .errors as errors
79import restea .formats as formats
810import restea .fields as fields
@@ -20,6 +22,7 @@ class Resource(object):
2022 'post' : 'create' ,
2123 'put' : 'edit' ,
2224 'delete' : 'delete' ,
25+ 'options' : 'describe' ,
2326 }
2427
2528 def __init__ (self , request , formatter ):
@@ -46,7 +49,7 @@ def _iden_required(self, method_name):
4649 :returns: boolean value of whatever iden is needed or not
4750 :rtype: bool
4851 '''
49- return method_name not in ('list' , 'create' )
52+ return method_name not in ('list' , 'create' , 'describe' )
5053
5154 def _match_response_to_fields (self , dct ):
5255 '''
@@ -105,9 +108,10 @@ def _get_method_name(self, has_iden):
105108 'HTTP_X_HTTP_METHOD_OVERRIDE' ,
106109 method
107110 )
108- method_name = self .method_map .get (method .lower ())
109111
110- if not method_name :
112+ try :
113+ method_name = self .method_map [method .lower ()]
114+ except KeyError :
111115 raise errors .MethodNotAllowedError (
112116 'Method "{}" is not supported' .format (self .request .method )
113117 )
@@ -232,6 +236,8 @@ def process(self, *args, **kwargs):
232236 method = self ._get_method (method_name )
233237 method = self ._apply_decorators (method )
234238
239+ if method_name == 'describe' :
240+ self ._add_available_methods_to_response_headers ()
235241 self .prepare ()
236242 response = method (self , * args , ** kwargs )
237243 response = self .finish (response )
@@ -243,11 +249,10 @@ def process(self, *args, **kwargs):
243249
244250 def dispatch (self , * args , ** kwargs ):
245251 '''
246- Dispatches the request and handles exception to return data, status
247- and content type
248-
249- :returns: 4-element tuple: result, HTTP status code, content type, and
252+ Dispatches the request and handles exception to return data, status, content type, and
250253 headers
254+
255+ :returns: 4-element tuple: result, HTTP status code, content type, and headers
251256 :rtype: tuple
252257 '''
253258 try :
@@ -268,6 +273,22 @@ def dispatch(self, *args, **kwargs):
268273 self ._response_headers
269274 )
270275
276+ def _add_available_methods_to_response_headers (self ):
277+ methods_available = []
278+ for http_method , method_name in self ._stream_http_method_and_restea_method ():
279+ if hasattr (self , method_name ):
280+ methods_available .append (http_method .upper ())
281+ self .set_header ('Allow' , ',' .join (set (methods_available )))
282+
283+ @classmethod
284+ def _stream_http_method_and_restea_method (cls ):
285+ for http_method , method_names in six .iteritems (cls .method_map ):
286+ if isinstance (method_names , tuple ):
287+ for method_name in method_names :
288+ yield http_method , method_name
289+ else :
290+ yield http_method , method_names
291+
271292 def set_header (self , name , value ):
272293 '''
273294 Sets the given response header name and value.
0 commit comments