Skip to content

Commit 66dc351

Browse files
Update data.py
1 parent 3231549 commit 66dc351

File tree

1 file changed

+52
-45
lines changed

1 file changed

+52
-45
lines changed

splunklib/data.py

Lines changed: 52 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,13 @@
1212
# License for the specific language governing permissions and limitations
1313
# under the License.
1414

15-
"""The **splunklib.data** module reads the responses from splunkd in Atom Feed
15+
"""The **splunklib.data** module reads the responses from splunkd in Atom Feed
1616
format, which is the format used by most of the REST API.
1717
"""
1818

19-
from __future__ import absolute_import
20-
import sys
2119
from xml.etree.ElementTree import XML
22-
from splunklib import six
2320

24-
__all__ = ["load"]
21+
__all__ = ["load", "record"]
2522

2623
# LNAME refers to element names without namespaces; XNAME is the same
2724
# name, but with an XML namespace.
@@ -36,33 +33,41 @@
3633
XNAME_KEY = XNAMEF_REST % LNAME_KEY
3734
XNAME_LIST = XNAMEF_REST % LNAME_LIST
3835

36+
3937
# Some responses don't use namespaces (eg: search/parse) so we look for
4038
# both the extended and local versions of the following names.
4139

40+
4241
def isdict(name):
43-
return name == XNAME_DICT or name == LNAME_DICT
42+
return name in (XNAME_DICT, LNAME_DICT)
43+
4444

4545
def isitem(name):
46-
return name == XNAME_ITEM or name == LNAME_ITEM
46+
return name in (XNAME_ITEM, LNAME_ITEM)
47+
4748

4849
def iskey(name):
49-
return name == XNAME_KEY or name == LNAME_KEY
50+
return name in (XNAME_KEY, LNAME_KEY)
51+
5052

5153
def islist(name):
52-
return name == XNAME_LIST or name == LNAME_LIST
54+
return name in (XNAME_LIST, LNAME_LIST)
55+
5356

5457
def hasattrs(element):
5558
return len(element.attrib) > 0
5659

60+
5761
def localname(xname):
5862
rcurly = xname.find('}')
59-
return xname if rcurly == -1 else xname[rcurly+1:]
63+
return xname if rcurly == -1 else xname[rcurly + 1:]
64+
6065

6166
def load(text, match=None):
62-
"""This function reads a string that contains the XML of an Atom Feed, then
63-
returns the
64-
data in a native Python structure (a ``dict`` or ``list``). If you also
65-
provide a tag name or path to match, only the matching sub-elements are
67+
"""This function reads a string that contains the XML of an Atom Feed, then
68+
returns the
69+
data in a native Python structure (a ``dict`` or ``list``). If you also
70+
provide a tag name or path to match, only the matching sub-elements are
6671
loaded.
6772
6873
:param text: The XML text to load.
@@ -78,30 +83,28 @@ def load(text, match=None):
7883
'names': {}
7984
}
8085

81-
# Convert to unicode encoding in only python 2 for xml parser
82-
if(sys.version_info < (3, 0, 0) and isinstance(text, unicode)):
83-
text = text.encode('utf-8')
84-
8586
root = XML(text)
8687
items = [root] if match is None else root.findall(match)
8788
count = len(items)
88-
if count == 0:
89+
if count == 0:
8990
return None
90-
elif count == 1:
91+
elif count == 1:
9192
return load_root(items[0], nametable)
9293
else:
9394
return [load_root(item, nametable) for item in items]
9495

96+
9597
# Load the attributes of the given element.
9698
def load_attrs(element):
9799
if not hasattrs(element): return None
98100
attrs = record()
99-
for key, value in six.iteritems(element.attrib):
101+
for key, value in list(element.attrib.items()):
100102
attrs[key] = value
101103
return attrs
102104

105+
103106
# Parse a <dict> element and return a Python dict
104-
def load_dict(element, nametable = None):
107+
def load_dict(element, nametable=None):
105108
value = record()
106109
children = list(element)
107110
for child in children:
@@ -110,6 +113,7 @@ def load_dict(element, nametable = None):
110113
value[name] = load_value(child, nametable)
111114
return value
112115

116+
113117
# Loads the given elements attrs & value into single merged dict.
114118
def load_elem(element, nametable=None):
115119
name = localname(element.tag)
@@ -118,12 +122,12 @@ def load_elem(element, nametable=None):
118122
if attrs is None: return name, value
119123
if value is None: return name, attrs
120124
# If value is simple, merge into attrs dict using special key
121-
if isinstance(value, six.string_types):
125+
if isinstance(value, str):
122126
attrs["$text"] = value
123127
return name, attrs
124128
# Both attrs & value are complex, so merge the two dicts, resolving collisions.
125129
collision_keys = []
126-
for key, val in six.iteritems(attrs):
130+
for key, val in list(attrs.items()):
127131
if key in value and key in collision_keys:
128132
value[key].append(val)
129133
elif key in value and key not in collision_keys:
@@ -133,6 +137,7 @@ def load_elem(element, nametable=None):
133137
value[key] = val
134138
return name, value
135139

140+
136141
# Parse a <list> element and return a Python list
137142
def load_list(element, nametable=None):
138143
assert islist(element.tag)
@@ -143,6 +148,7 @@ def load_list(element, nametable=None):
143148
value.append(load_value(child, nametable))
144149
return value
145150

151+
146152
# Load the given root element.
147153
def load_root(element, nametable=None):
148154
tag = element.tag
@@ -151,6 +157,7 @@ def load_root(element, nametable=None):
151157
k, v = load_elem(element, nametable)
152158
return Record.fromkv(k, v)
153159

160+
154161
# Load the children of the given element.
155162
def load_value(element, nametable=None):
156163
children = list(element)
@@ -159,7 +166,7 @@ def load_value(element, nametable=None):
159166
# No children, assume a simple text value
160167
if count == 0:
161168
text = element.text
162-
if text is None:
169+
if text is None:
163170
return None
164171

165172
if len(text.strip()) == 0:
@@ -179,31 +186,32 @@ def load_value(element, nametable=None):
179186
# If we have seen this name before, promote the value to a list
180187
if name in value:
181188
current = value[name]
182-
if not isinstance(current, list):
189+
if not isinstance(current, list):
183190
value[name] = [current]
184191
value[name].append(item)
185192
else:
186193
value[name] = item
187194

188195
return value
189196

197+
190198
# A generic utility that enables "dot" access to dicts
191199
class Record(dict):
192-
"""This generic utility class enables dot access to members of a Python
200+
"""This generic utility class enables dot access to members of a Python
193201
dictionary.
194202
195-
Any key that is also a valid Python identifier can be retrieved as a field.
196-
So, for an instance of ``Record`` called ``r``, ``r.key`` is equivalent to
197-
``r['key']``. A key such as ``invalid-key`` or ``invalid.key`` cannot be
198-
retrieved as a field, because ``-`` and ``.`` are not allowed in
203+
Any key that is also a valid Python identifier can be retrieved as a field.
204+
So, for an instance of ``Record`` called ``r``, ``r.key`` is equivalent to
205+
``r['key']``. A key such as ``invalid-key`` or ``invalid.key`` cannot be
206+
retrieved as a field, because ``-`` and ``.`` are not allowed in
199207
identifiers.
200208
201-
Keys of the form ``a.b.c`` are very natural to write in Python as fields. If
202-
a group of keys shares a prefix ending in ``.``, you can retrieve keys as a
209+
Keys of the form ``a.b.c`` are very natural to write in Python as fields. If
210+
a group of keys shares a prefix ending in ``.``, you can retrieve keys as a
203211
nested dictionary by calling only the prefix. For example, if ``r`` contains
204212
keys ``'foo'``, ``'bar.baz'``, and ``'bar.qux'``, ``r.bar`` returns a record
205-
with the keys ``baz`` and ``qux``. If a key contains multiple ``.``, each
206-
one is placed into a nested dictionary, so you can write ``r.bar.qux`` or
213+
with the keys ``baz`` and ``qux``. If a key contains multiple ``.``, each
214+
one is placed into a nested dictionary, so you can write ``r.bar.qux`` or
207215
``r['bar.qux']`` interchangeably.
208216
"""
209217
sep = '.'
@@ -215,7 +223,7 @@ def __call__(self, *args):
215223
def __getattr__(self, name):
216224
try:
217225
return self[name]
218-
except KeyError:
226+
except KeyError:
219227
raise AttributeError(name)
220228

221229
def __delattr__(self, name):
@@ -235,7 +243,7 @@ def __getitem__(self, key):
235243
return dict.__getitem__(self, key)
236244
key += self.sep
237245
result = record()
238-
for k,v in six.iteritems(self):
246+
for k, v in list(self.items()):
239247
if not k.startswith(key):
240248
continue
241249
suffix = k[len(key):]
@@ -250,17 +258,16 @@ def __getitem__(self, key):
250258
else:
251259
result[suffix] = v
252260
if len(result) == 0:
253-
raise KeyError("No key or prefix: %s" % key)
261+
raise KeyError(f"No key or prefix: {key}")
254262
return result
255-
256263

257-
def record(value=None):
258-
"""This function returns a :class:`Record` instance constructed with an
264+
265+
def record(value=None):
266+
"""This function returns a :class:`Record` instance constructed with an
259267
initial value that you provide.
260-
261-
:param `value`: An initial record value.
262-
:type `value`: ``dict``
268+
269+
:param value: An initial record value.
270+
:type value: ``dict``
263271
"""
264272
if value is None: value = {}
265273
return Record(value)
266-

0 commit comments

Comments
 (0)