@@ -1157,8 +1157,10 @@ def __getitem__(self, key):
11571157 # x[a,b] is translated to x.__getitem__( (a,b) ), so we
11581158 # have to extract values out.
11591159 key , ns = key
1160+ key = UrlEncoded (key , encode_slash = True )
11601161 response = self .get (key , owner = ns .owner , app = ns .app )
11611162 else :
1163+ key = UrlEncoded (key , encode_slash = True )
11621164 response = self .get (key )
11631165 entries = self ._load_list (response )
11641166 if len (entries ) > 1 :
@@ -1193,6 +1195,7 @@ def __iter__(self, **kwargs):
11931195 for entity in saved_searches:
11941196 print "Saved search named %s" % entity.name
11951197 """
1198+
11961199 for item in self .iter (** kwargs ):
11971200 yield item
11981201
@@ -1399,6 +1402,8 @@ def list(self, count=None, **kwargs):
13991402 return list (self .iter (count = count , ** kwargs ))
14001403
14011404
1405+
1406+
14021407class Collection (ReadOnlyCollection ):
14031408 """A collection of entities.
14041409
@@ -1444,6 +1449,7 @@ class Collection(ReadOnlyCollection):
14441449 :class:`Collection` does no caching. Each call makes at least one
14451450 round trip to the server to fetch data.
14461451 """
1452+
14471453 def create (self , name , ** params ):
14481454 """Creates a new entity in this collection.
14491455
@@ -1518,7 +1524,7 @@ def delete(self, name, **params):
15181524 saved_searches.delete('my_saved_search')
15191525 assert 'my_saved_search' not in saved_searches
15201526 """
1521-
1527+ name = UrlEncoded ( name , encode_slash = True )
15221528 if 'namespace' in params :
15231529 namespace = params .pop ('namespace' )
15241530 params ['owner' ] = namespace .owner
@@ -1534,7 +1540,57 @@ def delete(self, name, **params):
15341540 raise KeyError ("No such entity %s" % name )
15351541 else :
15361542 raise
1537- return self
1543+ return
1544+
1545+ def get (self , name = "" , owner = None , app = None , sharing = None , ** query ):
1546+ """Performs a GET request to the server on the collection.
1547+
1548+ If *owner*, *app*, and *sharing* are omitted, this method takes a
1549+ default namespace from the :class:`Service` object for this :class:`Endpoint`.
1550+ All other keyword arguments are included in the URL as query parameters.
1551+
1552+ :raises AuthenticationError: Raised when the ``Service`` is not logged in.
1553+ :raises HTTPError: Raised when an error in the request occurs.
1554+ :param path_segment: A path segment relative to this endpoint.
1555+ :type path_segment: ``string``
1556+ :param owner: The owner context of the namespace (optional).
1557+ :type owner: ``string``
1558+ :param app: The app context of the namespace (optional).
1559+ :type app: ``string``
1560+ :param sharing: The sharing mode for the namespace (optional).
1561+ :type sharing: "global", "system", "app", or "user"
1562+ :param query: All other keyword arguments, which are used as query
1563+ parameters.
1564+ :type query: ``string``
1565+ :return: The response from the server.
1566+ :rtype: ``dict`` with keys ``body``, ``headers``, ``reason``,
1567+ and ``status``
1568+
1569+ Example:
1570+
1571+ import splunklib.client
1572+ s = client.service(...)
1573+ saved_searches = s.saved_searches
1574+ saved_searches.get("my/saved/search") == \\
1575+ {'body': ...a response reader object...,
1576+ 'headers': [('content-length', '26208'),
1577+ ('expires', 'Fri, 30 Oct 1998 00:00:00 GMT'),
1578+ ('server', 'Splunkd'),
1579+ ('connection', 'close'),
1580+ ('cache-control', 'no-store, max-age=0, must-revalidate, no-cache'),
1581+ ('date', 'Fri, 11 May 2012 16:30:35 GMT'),
1582+ ('content-type', 'text/xml; charset=utf-8')],
1583+ 'reason': 'OK',
1584+ 'status': 200}
1585+ saved_searches.get('nonexistant/search') # raises HTTPError
1586+ s.logout()
1587+ saved_searches.get() # raises AuthenticationError
1588+
1589+ """
1590+ name = UrlEncoded (name , encode_slash = True )
1591+ return super (Collection , self ).get (name , owner , app , sharing , ** query )
1592+
1593+
15381594
15391595
15401596class ConfigurationFile (Collection ):
@@ -1962,6 +2018,7 @@ def __getitem__(self, key):
19622018 if isinstance (key , tuple ) and len (key ) == 2 :
19632019 # Fetch a single kind
19642020 key , kind = key
2021+ key = UrlEncoded (key , encode_slash = True )
19652022 try :
19662023 response = self .get (self .kindpath (kind ) + "/" + key )
19672024 entries = self ._load_list (response )
@@ -1980,6 +2037,7 @@ def __getitem__(self, key):
19802037 # Iterate over all the kinds looking for matches.
19812038 kind = None
19822039 candidate = None
2040+ key = UrlEncoded (key , encode_slash = True )
19832041 for kind in self .kinds :
19842042 try :
19852043 response = self .get (kind + "/" + key )
@@ -2213,12 +2271,12 @@ def kindpath(self, kind):
22132271 :rtype: ``string``
22142272 """
22152273 if kind in self .kinds :
2216- return kind
2274+ return UrlEncoded ( kind , skip_encode = True )
22172275 # Special cases
22182276 elif kind == 'tcp' :
2219- return 'tcp/raw'
2277+ return UrlEncoded ( 'tcp/raw' , skip_encode = True )
22202278 elif kind == 'splunktcp' :
2221- return 'tcp/cooked'
2279+ return UrlEncoded ( 'tcp/cooked' , skip_encode = True )
22222280 else :
22232281 raise ValueError ("No such kind on server: %s" % kind )
22242282
@@ -2285,6 +2343,7 @@ def list(self, *kinds, **kwargs):
22852343 path = self .kindpath (kind )
22862344 logging .debug ("Path for inputs: %s" , path )
22872345 try :
2346+ path = UrlEncoded (path , skip_encode = True )
22882347 response = self .get (path , ** kwargs )
22892348 except HTTPError , he :
22902349 if he .status == 404 : # No inputs of this kind
@@ -2309,6 +2368,7 @@ def list(self, *kinds, **kwargs):
23092368 for kind in kinds :
23102369 response = None
23112370 try :
2371+ kind = UrlEncoded (kind , skip_encode = True )
23122372 response = self .get (self .kindpath (kind ), search = search )
23132373 except HTTPError as e :
23142374 if e .status == 404 :
0 commit comments