@@ -196,8 +196,11 @@ def set_content_type_header(self, session):
196
196
def encode (self , data ):
197
197
return ElementTree .tostring (data )
198
198
199
- class RESTService (object ):
199
+ class _RESTService (object ):
200
200
"""
201
+ The _RESTService base class provides most of the implementation for
202
+ RESTService. The RESTService subclass adds some parameter validation.
203
+
201
204
Implements a simple wrapper for calling a REST interface that returns
202
205
either llsd or json, with optional authentication.
203
206
@@ -230,6 +233,11 @@ class RESTService(object):
230
233
undesired dependency between that module and the calling script.
231
234
"""
232
235
236
+ # describe __init__() params; used by _resolve_args()
237
+ init_params = ('name' , 'baseurl' , 'codec' , 'authenticated' ,
238
+ 'username' , 'password' , 'proxy_hostport' , 'cert' , 'basepath' ,
239
+ 'cookie_policy' )
240
+
233
241
def __init__ (self , name , baseurl , codec = RESTEncoding .LLSD , authenticated = True ,
234
242
username = None , password = None , proxy_hostport = None , cert = None , basepath = '' ,
235
243
cookie_policy = None , ** session_params ):
@@ -382,15 +390,6 @@ def _url(self, basepath, path, method, path_param='path', basepath_param='basepa
382
390
383
391
basepath_param is the name of method's parameter passed to us as basepath.
384
392
"""
385
- # Since caller accepts both 'basepath' and 'path', both are typically
386
- # optional arguments -- though 'path' is usually first so its caller
387
- # need not explicitly pass it as a keyword argument. But its caller
388
- # MUST pass one or the other.
389
- if not (basepath or path ):
390
- # When you fail to pass a non-optional parameter, the interpreter
391
- # raises TypeError. Treat this similarly.
392
- raise TypeError ("{}() requires either {} or {}"
393
- .format (method , path_param , basepath_param ))
394
393
# if self.baseurl is None, use empty string instead
395
394
baseurl = self .baseurl or ""
396
395
if basepath :
@@ -667,6 +666,26 @@ def temp_codec(self, codec):
667
666
finally :
668
667
self .set_codec (prev )
669
668
669
+ class RESTService (_RESTService ):
670
+ # We want the following validation for a consumer-instantiated
671
+ # RESTService, just not for _RESTService instances implicitly constructed
672
+ # by _resolve_args()
673
+ def _url (self , basepath , path , method , path_param = 'path' , basepath_param = 'basepath' ):
674
+ # Since caller accepts both 'basepath' and 'path', both are typically
675
+ # optional arguments -- though 'path' is usually first so its caller
676
+ # need not explicitly pass it as a keyword argument. But its caller
677
+ # MUST pass one or the other.
678
+ if not (basepath or path ):
679
+ # When you fail to pass a non-optional parameter, the interpreter
680
+ # raises TypeError. Treat this similarly.
681
+ raise TypeError ("{}() requires either {} or {}"
682
+ .format (method , path_param , basepath_param ))
683
+
684
+ # we have one or the other, pass to base-class method
685
+ return super (RESTService , self )._url (
686
+ basepath = basepath , path = path , method = method ,
687
+ path_param = path_param , basepath_param = basepath_param )
688
+
670
689
class _OldTLS (requests .adapters .HTTPAdapter ):
671
690
"""
672
691
Helper for RESTService.enable_old_tls(), derived from
@@ -709,3 +728,72 @@ class SimpleRESTService(RESTService):
709
728
"""
710
729
def __init__ (self , name , baseurl , * args , ** kwds ):
711
730
RESTService .__init__ (self , name , baseurl , authenticated = False , * args , ** kwds )
731
+
732
+
733
+ # convenience functions for simple one-shot use cases
734
+ def get (url , ** kwds ):
735
+ """
736
+ url is the target URL; everything else must be keyword arguments
737
+
738
+ RESTService.__init__() keywords are passed to RESTService constructor;
739
+ the rest are passed to requests.get()
740
+ """
741
+ svc , kwds = _resolve_args ('get' , url , kwds )
742
+ return svc .get (query = '' , basepath = '' , ** kwds )
743
+
744
+ def post (url , ** kwds ):
745
+ """
746
+ url is the target URL; everything else must be keyword arguments
747
+
748
+ RESTService.__init__() keywords are passed to RESTService constructor;
749
+ data (if passed) is encoded according to the RESTService codec;
750
+ the rest are passed to requests.post()
751
+ """
752
+ svc , kwds = _resolve_args ('post' , url , kwds )
753
+ return svc .post (path = '' , basepath = '' , ** kwds )
754
+
755
+ def put (url , ** kwds ):
756
+ """
757
+ url is the target URL; everything else must be keyword arguments
758
+
759
+ RESTService.__init__() keywords are passed to RESTService constructor;
760
+ data (if passed) is encoded according to the RESTService codec;
761
+ the rest are passed to requests.put()
762
+ """
763
+ svc , kwds = _resolve_args ('put' , url , kwds )
764
+ return svc .put (path = '' , basepath = '' , ** kwds )
765
+
766
+ def delete (url , ** kwds ):
767
+ """
768
+ url is the target URL; everything else must be keyword arguments
769
+
770
+ RESTService.__init__() keywords are passed to RESTService constructor;
771
+ the rest are passed to requests.delete()
772
+ """
773
+ svc , kwds = _resolve_args ('delete' , url , kwds )
774
+ return svc .delete (path = '' , basepath = '' , ** kwds )
775
+
776
+ def _resolve_args (func , url , kwds ):
777
+ """
778
+ Given a dict of **kwds, split them into _RESTService constructor params
779
+ versus anything else, which we assume to be extra keywords to pass to
780
+ 'func'.
781
+
782
+ Return (_RESTService instance, remaining kwds).
783
+ """
784
+ # _RESTService.init_params includes the first two parameters, name and
785
+ # baseurl, to simplify maintenance. But since we pass those explicitly
786
+ # here, remove from the set of keywords we recognize.
787
+ init_params = set (_RESTService .init_params [2 :])
788
+ init_kwds = {}
789
+ func_kwds = {}
790
+ for key , value in kwds .items ():
791
+ if key in init_params :
792
+ dest_kwds = init_kwds
793
+ else :
794
+ dest_kwds = func_kwds
795
+ dest_kwds [key ] = value
796
+ return (_RESTService (name = 'temp ' + func , baseurl = url , ** init_kwds ),
797
+ func_kwds )
798
+
799
+
0 commit comments