4444 "connect" ,
4545 "Context" ,
4646 "handler" ,
47- "HTTPError" ,
48- "UrlEncoded"
47+ "HTTPError"
4948]
5049
5150# If you change these, update the docstring
@@ -75,22 +74,23 @@ class AuthenticationError(Exception):
7574 pass
7675
7776# Singleton values to eschew None
78- class NoAuthenticationToken (object ):
77+ class _NoAuthenticationToken (object ):
7978 """The value stored in a :class:`Context` or :class:`splunklib.client.Service`
8079 class that is not logged in.
8180
8281 If a ``Context`` or ``Service`` object is created without an authentication
8382 token, and there has not yet been a call to the ``login`` method, the token
8483 field of the ``Context`` or ``Service`` object is set to
85- ``NoAuthenticationToken ``.
84+ ``_NoAuthenticationToken ``.
8685
8786 Likewise, after a ``Context`` or ``Service`` object has been logged out, the
8887 token is set to this value again.
8988 """
9089 pass
9190
9291class UrlEncoded (str ):
93- """This class creates URL-encoded strings.
92+ """This class marks URL-encoded strings.
93+ It should be considered an SDK-private implementation detail.
9494
9595 Manually tracking whether strings are URL encoded can be difficult. Avoid
9696 calling ``urllib.quote`` to replace special characters with escapes. When
@@ -163,7 +163,7 @@ def __mod__(self, fields):
163163 """
164164 raise TypeError ("Cannot interpolate into a UrlEncoded object." )
165165 def __repr__ (self ):
166- return "UrlEncoded('%s' )" % urllib .unquote (self )
166+ return "UrlEncoded(%s )" % repr ( urllib .unquote (self ) )
167167
168168@contextmanager
169169def _handle_auth_error (msg ):
@@ -227,7 +227,7 @@ def f():
227227 """
228228 @wraps (request_fun )
229229 def wrapper (self , * args , ** kwargs ):
230- if self .token is NoAuthenticationToken :
230+ if self .token is _NoAuthenticationToken :
231231 # Not yet logged in.
232232 if self .autologin and self .username and self .password :
233233 # This will throw an uncaught
@@ -403,9 +403,9 @@ class Context(object):
403403 """
404404 def __init__ (self , handler = None , ** kwargs ):
405405 self .http = HttpLib (handler )
406- self .token = kwargs .get ("token" , NoAuthenticationToken )
406+ self .token = kwargs .get ("token" , _NoAuthenticationToken )
407407 if self .token is None : # In case someone explicitly passes token=None
408- self .token = NoAuthenticationToken
408+ self .token = _NoAuthenticationToken
409409 self .scheme = kwargs .get ("scheme" , DEFAULT_SCHEME )
410410 self .host = kwargs .get ("host" , DEFAULT_HOST )
411411 self .port = int (kwargs .get ("port" , DEFAULT_PORT ))
@@ -427,7 +427,7 @@ def _auth_headers(self):
427427 :returns: A list of 2-tuples containing key and value
428428 """
429429 # Ensure the token is properly formatted
430- if self .token .startswith ('Splunk' ):
430+ if self .token .startswith ('Splunk ' ):
431431 token = self .token
432432 else :
433433 token = 'Splunk %s' % self .token
@@ -447,7 +447,7 @@ def connect(self):
447447 import splunklib.binding as binding
448448 c = binding.connect(...)
449449 socket = c.connect()
450- socket.write("POST %s HTTP/1.1\\ r\\ n" % c._abspath( "some/path/to/post/to") )
450+ socket.write("POST %s HTTP/1.1\\ r\\ n" % "some/path/to/post/to")
451451 socket.write("Host: %s:%s\\ r\\ n" % (c.host, c.port))
452452 socket.write("Accept-Encoding: identity\\ r\\ n")
453453 socket.write("Authorization: %s\\ r\\ n" % c.token)
@@ -578,7 +578,7 @@ def get(self, path_segment, owner=None, app=None, sharing=None, **query):
578578
579579 @_authentication
580580 @_log_duration
581- def post (self , path_segment , owner = None , app = None , sharing = None , headers = [] , ** query ):
581+ def post (self , path_segment , owner = None , app = None , sharing = None , headers = None , ** query ):
582582 """Performs a POST operation from the REST path segment with the given
583583 namespace and query.
584584
@@ -610,6 +610,8 @@ def post(self, path_segment, owner=None, app=None, sharing=None, headers=[], **q
610610 :type app: ``string``
611611 :param sharing: The sharing mode of the namespace (optional).
612612 :type sharing: ``string``
613+ :param headers: List of extra HTTP headers to send (optional).
614+ :type headers: ``list`` of 2-tuples.
613615 :param query: All other keyword arguments, which are used as query
614616 parameters.
615617 :type query: ``string``
@@ -638,22 +640,19 @@ def post(self, path_segment, owner=None, app=None, sharing=None, headers=[], **q
638640 c.post('saved/searches', name='boris',
639641 search='search * earliest=-1m | head 1')
640642 """
643+ if headers is None :
644+ headers = []
645+
641646 path = self .authority + self ._abspath (path_segment , owner = owner ,
642647 app = app , sharing = sharing )
643648 logging .debug ("POST request to %s (body: %s)" , path , repr (query ))
644- if isinstance (headers , dict ):
645- all_headers = [(k ,v ) for k ,v in headers .iteritems ()]
646- elif isinstance (headers , list ):
647- all_headers = headers
648- else :
649- raise ValueError ("headers must be a list or dict (found: %s)" % headers )
650- all_headers += self ._auth_headers
649+ all_headers = headers + self ._auth_headers
651650 response = self .http .post (path , all_headers , ** query )
652651 return response
653652
654653 @_authentication
655654 @_log_duration
656- def request (self , path_segment , method = "GET" , headers = [] , body = "" ,
655+ def request (self , path_segment , method = "GET" , headers = None , body = "" ,
657656 owner = None , app = None , sharing = None ):
658657 """Issues an arbitrary HTTP request to the REST path segment.
659658
@@ -670,6 +669,12 @@ def request(self, path_segment, method="GET", headers=[], body="",
670669 *path_segment*.
671670 :param path_segment: A REST path segment.
672671 :type path_segment: ``string``
672+ :param method: The HTTP method to use (optional).
673+ :type method: ``string``
674+ :param headers: List of extra HTTP headers to send (optional).
675+ :type headers: ``list`` of 2-tuples.
676+ :param body: Content of the HTTP request (optional).
677+ :type body: ``string``
673678 :param owner: The owner context of the namespace (optional).
674679 :type owner: ``string``
675680 :param app: The app context of the namespace (optional).
@@ -701,19 +706,12 @@ def request(self, path_segment, method="GET", headers=[], body="",
701706 c.logout()
702707 c.get('apps/local') # raises AuthenticationError
703708 """
709+ if headers is None :
710+ headers = []
711+
704712 path = self .authority \
705713 + self ._abspath (path_segment , owner = owner ,
706714 app = app , sharing = sharing )
707- # all_headers can't be named headers, due to how
708- # Python implements closures. In particular:
709- # def f(x):
710- # def g():
711- # x = x + "a"
712- # return x
713- # return g()
714- # throws UnboundLocalError, since x must be either a member of
715- # f's local namespace or g's, and cannot switch between them
716- # during the run of the function.
717715 all_headers = headers + self ._auth_headers
718716 logging .debug ("%s request to %s (headers: %s, body: %s)" ,
719717 method , path , str (all_headers ), repr (body ))
@@ -742,7 +740,7 @@ def login(self):
742740 c = binding.Context(...).login()
743741 # Then issue requests...
744742 """
745- if self .token is not NoAuthenticationToken and \
743+ if self .token is not _NoAuthenticationToken and \
746744 (not self .username and not self .password ):
747745 # If we were passed a session token, but no username or
748746 # password, then login is a nop, since we're automatically
@@ -765,7 +763,7 @@ def login(self):
765763
766764 def logout (self ):
767765 """Forgets the current session token."""
768- self .token = NoAuthenticationToken
766+ self .token = _NoAuthenticationToken
769767 return self
770768
771769 def _abspath (self , path_segment ,
0 commit comments