Skip to content

Commit fae6b2f

Browse files
author
Fred Ross
committed
Merge pull request #59 from splunk/fross/review-fixes
Fixed things found in session 1 of the grand Python review.
2 parents 02ef288 + fe22e6f commit fae6b2f

File tree

6 files changed

+34
-37
lines changed

6 files changed

+34
-37
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## 1.0
44

5+
* Confs has been renamed to Configurations.
56
* Stanza.submit now takes a dictionary of key/value pairs specifying the stanza instead of a raw string.
67
* Namespace handling has changed subtly. Code that depends on namespace handling in detail may break.
78
* Added User.role_entities to return a list of the actual entity objects for the

splunklib/client.py

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,6 @@ class AmbiguousReferenceException(ValueError):
137137
"""Thrown when the name used to fetch an entity matches more than one entity."""
138138
pass
139139

140-
class EntityDeletedException(Exception):
141-
"""Thrown when the entity that has been referred to has been deleted."""
142-
pass
143-
144140
class InvalidNameException(Exception):
145141
"""Thrown when the specified name contains characters that are not allowed
146142
in Splunk entity names."""
@@ -209,8 +205,8 @@ def _load_atom_entries(response):
209205
entries = r.feed.get('entry', None)
210206
if entries is None: return None
211207
return entries if isinstance(entries, list) else [entries]
212-
# This rigamarole is because the jobs endpoint doesn't
213-
# returned an entry inside a feed, it just returns and entry.
208+
# The jobs endpoint doesn't returns a bare <entry> element
209+
# instead of an <entry> element inside a <feed> element.
214210
else:
215211
entries = r.get('entry', None)
216212
if entries is None: return None
@@ -549,9 +545,8 @@ def roles(self):
549545
return Roles(self)
550546

551547
def search(self, query, **kwargs):
552-
"""Runs a oneshot synchronous search using a search query and any
553-
optional arguments you provide. A oneshot search doesn't create a search
554-
job and ID, but rather it returns the search results once completed.
548+
"""Runs a search using a search query and any optional arguments you
549+
provide, and returns a `Job` object representing the search.
555550
556551
:param query: A search query.
557552
:type query: ``string``
@@ -576,6 +571,8 @@ def search(self, query, **kwargs):
576571
search.
577572
578573
:type kwargs: ``dict``
574+
:rtype: class:`Job`
575+
:returns: An object representing the created job.
579576
"""
580577
return self.jobs.create(query, **kwargs)
581578

@@ -882,17 +879,14 @@ def __getitem__(self, key):
882879
def _load_atom_entry(self, response):
883880
elem = _load_atom(response, XNAME_ENTRY)
884881
if isinstance(elem, list):
885-
return [x.entry for x in elem]
882+
raise AmbiguousReferenceException("Fetch from server returned multiple entries for name %s." % self.name)
886883
else:
887884
return elem.entry
888885

889886
# Load the entity state record from the given response
890887
def _load_state(self, response):
891888
entry = self._load_atom_entry(response)
892-
if isinstance(entry, list):
893-
raise AmbiguousReferenceException("Fetch from server returned multiple entries for name %s." % self.name)
894-
else:
895-
return _parse_atom_entry(entry)
889+
return _parse_atom_entry(entry)
896890

897891
def _run_method(self, path_segment, **kwargs):
898892
"""Run a method and return the content Record from the returned XML.
@@ -911,24 +905,26 @@ def _run_method(self, path_segment, **kwargs):
911905
def _proper_namespace(self, owner=None, app=None, sharing=None):
912906
"""Produce a namespace sans wildcards for use in entity requests.
913907
914-
This method handles the case of two entities with the same name in different namespaces
915-
showing up due to wildcards in the service's namespace. We replace the wildcards with the
916-
namespace of the entity we want.
908+
This method tries to fill in the fields of the namespace which are `None`
909+
or wildcard (`'-'`) from the entity's namespace. If that fails, it uses
910+
the service's namespace.
917911
918912
:param owner:
919913
:param app:
920914
:param sharing:
921915
:return:
922916
"""
923-
if owner is None and app is None and sharing is None and\
924-
(self.service.namespace.owner == '-' or self.service.namespace.app == '-'):
925-
# If no namespace is specified and there are wildcards in the service's namespace,
926-
# we need to use the entity's namespace to avoid name collisions.
927-
if 'access' in self._state:
928-
owner = self._state.access.owner
929-
app = self._state.access.app
930-
sharing = self._state.access.sharing
931-
return (owner, app, sharing)
917+
if owner is None and app is None and sharing is None: # No namespace provided
918+
if self._state is not None and 'access' in self._state:
919+
return (self._state.access.owner,
920+
self._state.access.app,
921+
self._state.access.sharing)
922+
else:
923+
return (self.service.namespace['owner'],
924+
self.service.namespace['app'],
925+
self.service.namespace['sharing'])
926+
else:
927+
return (owner,app,sharing)
932928

933929
def delete(self):
934930
owner, app, sharing = self._proper_namespace()
@@ -966,13 +962,7 @@ def refresh(self, state=None):
966962
if state is not None:
967963
self._state = state
968964
else:
969-
try:
970-
raw_state = self.read()
971-
except HTTPError, he:
972-
if he.status == 404:
973-
raise EntityDeletedException("Entity %s was already deleted" % self.name)
974-
raw_state['links'] = dict([(k, urllib.unquote(v)) for k,v in raw_state['links'].iteritems()])
975-
self._state = raw_state
965+
self._state = self.read()
976966
return self
977967

978968
@property
@@ -1043,6 +1033,12 @@ def read(self):
10431033
"""Reads the current state of the entity from the server."""
10441034
response = self.get()
10451035
results = self._load_state(response)
1036+
# In lower layers of the SDK, we end up trying to URL encode
1037+
# text to be dispatched via HTTP. However, these links are already
1038+
# URL encoded when they arrive, and we need to mark them as such.
1039+
unquoted_links = dict([(k, UrlEncoded(v, skip_encode=True))
1040+
for k,v in results['links'].iteritems()])
1041+
results['links'] = unquoted_links
10461042
return results
10471043

10481044
def reload(self):

tests/test_input.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ def test_delete(self):
297297
inputs.delete, name)
298298
self.service.inputs.delete(kind, name)
299299
self.assertFalse((kind,name) in inputs)
300-
self.assertRaises(client.EntityDeletedException,
300+
self.assertRaises(client.HTTPError,
301301
input_entity.refresh)
302302
remaining -= 1
303303

tests/test_role.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def test_delete(self):
5757
self.assertTrue(self.role_name in self.service.roles)
5858
self.service.roles.delete(self.role_name)
5959
self.assertFalse(self.role_name in self.service.roles)
60-
self.assertRaises(client.EntityDeletedException, self.role.refresh)
60+
self.assertRaises(client.HTTPError, self.role.refresh)
6161

6262
def test_grant_and_revoke(self):
6363
self.assertFalse('edit_user' in self.role.capabilities)

tests/test_saved_search.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ def test_delete(self):
8383
self.assertTrue(self.saved_search_name in self.service.saved_searches)
8484
self.service.saved_searches.delete(self.saved_search_name)
8585
self.assertFalse(self.saved_search_name in self.service.saved_searches)
86-
self.assertRaises(client.EntityDeletedException,
86+
self.assertRaises(client.HTTPError,
8787
self.saved_search.refresh)
8888

8989

tests/test_user.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def test_create(self):
5555
def test_delete(self):
5656
self.service.users.delete(self.username)
5757
self.assertFalse(self.username in self.service.users)
58-
with self.assertRaises(client.EntityDeletedException):
58+
with self.assertRaises(client.HTTPError):
5959
self.user.refresh()
6060

6161
def test_update(self):

0 commit comments

Comments
 (0)