gam7 7.3.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of gam7 might be problematic. Click here for more details.
- gam/__init__.py +77555 -0
- gam/__main__.py +40 -0
- gam/atom/__init__.py +1460 -0
- gam/atom/auth.py +41 -0
- gam/atom/client.py +214 -0
- gam/atom/core.py +535 -0
- gam/atom/data.py +327 -0
- gam/atom/http.py +354 -0
- gam/atom/http_core.py +599 -0
- gam/atom/http_interface.py +144 -0
- gam/atom/mock_http.py +123 -0
- gam/atom/mock_http_core.py +313 -0
- gam/atom/mock_service.py +235 -0
- gam/atom/service.py +723 -0
- gam/atom/token_store.py +105 -0
- gam/atom/url.py +130 -0
- gam/cacerts.pem +1130 -0
- gam/cbcm-v1.1beta1.json +593 -0
- gam/contactdelegation-v1.json +249 -0
- gam/datastudio-v1.json +486 -0
- gam/gamlib/__init__.py +17 -0
- gam/gamlib/glaction.py +308 -0
- gam/gamlib/glapi.py +837 -0
- gam/gamlib/glcfg.py +616 -0
- gam/gamlib/glclargs.py +1184 -0
- gam/gamlib/glentity.py +831 -0
- gam/gamlib/glgapi.py +817 -0
- gam/gamlib/glgdata.py +98 -0
- gam/gamlib/glglobals.py +307 -0
- gam/gamlib/glindent.py +46 -0
- gam/gamlib/glmsgs.py +547 -0
- gam/gamlib/glskus.py +246 -0
- gam/gamlib/gluprop.py +279 -0
- gam/gamlib/glverlibs.py +33 -0
- gam/gamlib/yubikey.py +202 -0
- gam/gdata/__init__.py +825 -0
- gam/gdata/alt/__init__.py +20 -0
- gam/gdata/alt/app_engine.py +101 -0
- gam/gdata/alt/appengine.py +321 -0
- gam/gdata/apps/__init__.py +526 -0
- gam/gdata/apps/audit/__init__.py +1 -0
- gam/gdata/apps/audit/service.py +278 -0
- gam/gdata/apps/contacts/__init__.py +874 -0
- gam/gdata/apps/contacts/service.py +355 -0
- gam/gdata/apps/service.py +544 -0
- gam/gdata/apps/sites/__init__.py +283 -0
- gam/gdata/apps/sites/service.py +246 -0
- gam/gdata/service.py +1714 -0
- gam/gdata/urlfetch.py +247 -0
- gam/googleapiclient/__init__.py +27 -0
- gam/googleapiclient/_auth.py +167 -0
- gam/googleapiclient/_helpers.py +207 -0
- gam/googleapiclient/channel.py +315 -0
- gam/googleapiclient/discovery.py +1662 -0
- gam/googleapiclient/discovery_cache/__init__.py +78 -0
- gam/googleapiclient/discovery_cache/appengine_memcache.py +55 -0
- gam/googleapiclient/discovery_cache/base.py +46 -0
- gam/googleapiclient/discovery_cache/file_cache.py +145 -0
- gam/googleapiclient/errors.py +197 -0
- gam/googleapiclient/http.py +1962 -0
- gam/googleapiclient/mimeparse.py +183 -0
- gam/googleapiclient/model.py +429 -0
- gam/googleapiclient/schema.py +317 -0
- gam/googleapiclient/version.py +15 -0
- gam/iso8601/__init__.py +28 -0
- gam/iso8601/iso8601.py +160 -0
- gam/serviceaccountlookup-v1.json +141 -0
- gam/six.py +982 -0
- gam7-7.3.4.dist-info/METADATA +69 -0
- gam7-7.3.4.dist-info/RECORD +72 -0
- gam7-7.3.4.dist-info/WHEEL +4 -0
- gam7-7.3.4.dist-info/licenses/LICENSE +201 -0
gam/atom/core.py
ADDED
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2008 Google Inc.
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License 2.0;
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# This module is used for version 2 of the Google Data APIs.
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# __author__ = 'j.s@google.com (Jeff Scudder)'
|
|
22
|
+
|
|
23
|
+
import inspect
|
|
24
|
+
|
|
25
|
+
import lxml.etree as ElementTree
|
|
26
|
+
|
|
27
|
+
try:
|
|
28
|
+
from xml.dom.minidom import parseString as xmlString
|
|
29
|
+
except ImportError:
|
|
30
|
+
xmlString = None
|
|
31
|
+
|
|
32
|
+
STRING_ENCODING = 'utf-8'
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class XmlElement(object):
|
|
36
|
+
"""Represents an element node in an XML document.
|
|
37
|
+
|
|
38
|
+
The text member is a UTF-8 encoded str or unicode.
|
|
39
|
+
"""
|
|
40
|
+
_qname = None
|
|
41
|
+
_other_elements = None
|
|
42
|
+
_other_attributes = None
|
|
43
|
+
# The rule set contains mappings for XML qnames to child members and the
|
|
44
|
+
# appropriate member classes.
|
|
45
|
+
_rule_set = None
|
|
46
|
+
_members = None
|
|
47
|
+
text = None
|
|
48
|
+
|
|
49
|
+
def __init__(self, text=None, *args, **kwargs):
|
|
50
|
+
if ('_members' not in self.__class__.__dict__
|
|
51
|
+
or self.__class__._members is None):
|
|
52
|
+
self.__class__._members = tuple(self.__class__._list_xml_members())
|
|
53
|
+
for member_name, member_type in self.__class__._members:
|
|
54
|
+
if member_name in kwargs:
|
|
55
|
+
setattr(self, member_name, kwargs[member_name])
|
|
56
|
+
else:
|
|
57
|
+
if isinstance(member_type, list):
|
|
58
|
+
setattr(self, member_name, [])
|
|
59
|
+
else:
|
|
60
|
+
setattr(self, member_name, None)
|
|
61
|
+
self._other_elements = []
|
|
62
|
+
self._other_attributes = {}
|
|
63
|
+
if text is not None:
|
|
64
|
+
self.text = text
|
|
65
|
+
|
|
66
|
+
def _list_xml_members(cls):
|
|
67
|
+
"""Generator listing all members which are XML elements or attributes.
|
|
68
|
+
|
|
69
|
+
The following members would be considered XML members:
|
|
70
|
+
foo = 'abc' - indicates an XML attribute with the qname abc
|
|
71
|
+
foo = SomeElement - indicates an XML child element
|
|
72
|
+
foo = [AnElement] - indicates a repeating XML child element, each instance
|
|
73
|
+
will be stored in a list in this member
|
|
74
|
+
foo = ('att1', '{http://example.com/namespace}att2') - indicates an XML
|
|
75
|
+
attribute which has different parsing rules in different versions of
|
|
76
|
+
the protocol. Version 1 of the XML parsing rules will look for an
|
|
77
|
+
attribute with the qname 'att1' but verion 2 of the parsing rules will
|
|
78
|
+
look for a namespaced attribute with the local name of 'att2' and an
|
|
79
|
+
XML namespace of 'http://example.com/namespace'.
|
|
80
|
+
"""
|
|
81
|
+
members = []
|
|
82
|
+
for pair in inspect.getmembers(cls):
|
|
83
|
+
if not pair[0].startswith('_') and pair[0] != 'text':
|
|
84
|
+
member_type = pair[1]
|
|
85
|
+
if (isinstance(member_type, tuple) or isinstance(member_type, list)
|
|
86
|
+
or isinstance(member_type, str)
|
|
87
|
+
or (inspect.isclass(member_type)
|
|
88
|
+
and issubclass(member_type, XmlElement))):
|
|
89
|
+
members.append(pair)
|
|
90
|
+
return members
|
|
91
|
+
|
|
92
|
+
_list_xml_members = classmethod(_list_xml_members)
|
|
93
|
+
|
|
94
|
+
def _get_rules(cls, version):
|
|
95
|
+
"""Initializes the _rule_set for the class which is used when parsing XML.
|
|
96
|
+
|
|
97
|
+
This method is used internally for parsing and generating XML for an
|
|
98
|
+
XmlElement. It is not recommended that you call this method directly.
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
A tuple containing the XML parsing rules for the appropriate version.
|
|
102
|
+
|
|
103
|
+
The tuple looks like:
|
|
104
|
+
(qname, {sub_element_qname: (member_name, member_class, repeating), ..},
|
|
105
|
+
{attribute_qname: member_name})
|
|
106
|
+
|
|
107
|
+
To give a couple of concrete example, the atom.data.Control _get_rules
|
|
108
|
+
with version of 2 will return:
|
|
109
|
+
('{http://www.w3.org/2007/app}control',
|
|
110
|
+
{'{http://www.w3.org/2007/app}draft': ('draft',
|
|
111
|
+
<class 'atom.data.Draft'>,
|
|
112
|
+
False)},
|
|
113
|
+
{})
|
|
114
|
+
Calling _get_rules with version 1 on gdata.data.FeedLink will produce:
|
|
115
|
+
('{http://schemas.google.com/g/2005}feedLink',
|
|
116
|
+
{'{http://www.w3.org/2005/Atom}feed': ('feed',
|
|
117
|
+
<class 'gdata.data.GDFeed'>,
|
|
118
|
+
False)},
|
|
119
|
+
{'href': 'href', 'readOnly': 'read_only', 'countHint': 'count_hint',
|
|
120
|
+
'rel': 'rel'})
|
|
121
|
+
"""
|
|
122
|
+
# Initialize the _rule_set to make sure there is a slot available to store
|
|
123
|
+
# the parsing rules for this version of the XML schema.
|
|
124
|
+
# Look for rule set in the class __dict__ proxy so that only the
|
|
125
|
+
# _rule_set for this class will be found. By using the dict proxy
|
|
126
|
+
# we avoid finding rule_sets defined in superclasses.
|
|
127
|
+
# The four lines below provide support for any number of versions, but it
|
|
128
|
+
# runs a bit slower then hard coding slots for two versions, so I'm using
|
|
129
|
+
# the below two lines.
|
|
130
|
+
# if '_rule_set' not in cls.__dict__ or cls._rule_set is None:
|
|
131
|
+
# cls._rule_set = []
|
|
132
|
+
# while len(cls.__dict__['_rule_set']) < version:
|
|
133
|
+
# cls._rule_set.append(None)
|
|
134
|
+
# If there is no rule set cache in the class, provide slots for two XML
|
|
135
|
+
# versions. If and when there is a version 3, this list will need to be
|
|
136
|
+
# expanded.
|
|
137
|
+
if '_rule_set' not in cls.__dict__ or cls._rule_set is None:
|
|
138
|
+
cls._rule_set = [None, None]
|
|
139
|
+
# If a version higher than 2 is requested, fall back to version 2 because
|
|
140
|
+
# 2 is currently the highest supported version.
|
|
141
|
+
if version > 2:
|
|
142
|
+
return cls._get_rules(2)
|
|
143
|
+
# Check the dict proxy for the rule set to avoid finding any rule sets
|
|
144
|
+
# which belong to the superclass. We only want rule sets for this class.
|
|
145
|
+
if cls._rule_set[version - 1] is None:
|
|
146
|
+
# The rule set for each version consists of the qname for this element
|
|
147
|
+
# ('{namespace}tag'), a dictionary (elements) for looking up the
|
|
148
|
+
# corresponding class member when given a child element's qname, and a
|
|
149
|
+
# dictionary (attributes) for looking up the corresponding class member
|
|
150
|
+
# when given an XML attribute's qname.
|
|
151
|
+
elements = {}
|
|
152
|
+
attributes = {}
|
|
153
|
+
if ('_members' not in cls.__dict__ or cls._members is None):
|
|
154
|
+
cls._members = tuple(cls._list_xml_members())
|
|
155
|
+
for member_name, target in cls._members:
|
|
156
|
+
if isinstance(target, list):
|
|
157
|
+
# This member points to a repeating element.
|
|
158
|
+
elements[_get_qname(target[0], version)] = (member_name, target[0],
|
|
159
|
+
True)
|
|
160
|
+
elif isinstance(target, tuple):
|
|
161
|
+
# This member points to a versioned XML attribute.
|
|
162
|
+
if version <= len(target):
|
|
163
|
+
attributes[target[version - 1]] = member_name
|
|
164
|
+
else:
|
|
165
|
+
attributes[target[-1]] = member_name
|
|
166
|
+
elif isinstance(target, str):
|
|
167
|
+
# This member points to an XML attribute.
|
|
168
|
+
attributes[target] = member_name
|
|
169
|
+
elif issubclass(target, XmlElement):
|
|
170
|
+
# This member points to a single occurance element.
|
|
171
|
+
elements[_get_qname(target, version)] = (member_name, target, False)
|
|
172
|
+
version_rules = (_get_qname(cls, version), elements, attributes)
|
|
173
|
+
cls._rule_set[version - 1] = version_rules
|
|
174
|
+
return version_rules
|
|
175
|
+
else:
|
|
176
|
+
return cls._rule_set[version - 1]
|
|
177
|
+
|
|
178
|
+
_get_rules = classmethod(_get_rules)
|
|
179
|
+
|
|
180
|
+
def get_elements(self, tag=None, namespace=None, version=1):
|
|
181
|
+
"""Find all sub elements which match the tag and namespace.
|
|
182
|
+
|
|
183
|
+
To find all elements in this object, call get_elements with the tag and
|
|
184
|
+
namespace both set to None (the default). This method searches through
|
|
185
|
+
the object's members and the elements stored in _other_elements which
|
|
186
|
+
did not match any of the XML parsing rules for this class.
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
tag: str
|
|
190
|
+
namespace: str
|
|
191
|
+
version: int Specifies the version of the XML rules to be used when
|
|
192
|
+
searching for matching elements.
|
|
193
|
+
|
|
194
|
+
Returns:
|
|
195
|
+
A list of the matching XmlElements.
|
|
196
|
+
"""
|
|
197
|
+
matches = []
|
|
198
|
+
ignored1, elements, ignored2 = self.__class__._get_rules(version)
|
|
199
|
+
if elements:
|
|
200
|
+
for qname, element_def in elements.items():
|
|
201
|
+
member = getattr(self, element_def[0])
|
|
202
|
+
if member:
|
|
203
|
+
if _qname_matches(tag, namespace, qname):
|
|
204
|
+
if element_def[2]:
|
|
205
|
+
# If this is a repeating element, copy all instances into the
|
|
206
|
+
# result list.
|
|
207
|
+
matches.extend(member)
|
|
208
|
+
else:
|
|
209
|
+
matches.append(member)
|
|
210
|
+
for element in self._other_elements:
|
|
211
|
+
if _qname_matches(tag, namespace, element._qname):
|
|
212
|
+
matches.append(element)
|
|
213
|
+
return matches
|
|
214
|
+
|
|
215
|
+
GetElements = get_elements
|
|
216
|
+
# FindExtensions and FindChildren are provided for backwards compatibility
|
|
217
|
+
# to the atom.AtomBase class.
|
|
218
|
+
# However, FindExtensions may return more results than the v1 atom.AtomBase
|
|
219
|
+
# method does, because get_elements searches both the expected children
|
|
220
|
+
# and the unexpected "other elements". The old AtomBase.FindExtensions
|
|
221
|
+
# method searched only "other elements" AKA extension_elements.
|
|
222
|
+
FindExtensions = get_elements
|
|
223
|
+
FindChildren = get_elements
|
|
224
|
+
|
|
225
|
+
def get_attributes(self, tag=None, namespace=None, version=1):
|
|
226
|
+
"""Find all attributes which match the tag and namespace.
|
|
227
|
+
|
|
228
|
+
To find all attributes in this object, call get_attributes with the tag
|
|
229
|
+
and namespace both set to None (the default). This method searches
|
|
230
|
+
through the object's members and the attributes stored in
|
|
231
|
+
_other_attributes which did not fit any of the XML parsing rules for this
|
|
232
|
+
class.
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
tag: str
|
|
236
|
+
namespace: str
|
|
237
|
+
version: int Specifies the version of the XML rules to be used when
|
|
238
|
+
searching for matching attributes.
|
|
239
|
+
|
|
240
|
+
Returns:
|
|
241
|
+
A list of XmlAttribute objects for the matching attributes.
|
|
242
|
+
"""
|
|
243
|
+
matches = []
|
|
244
|
+
ignored1, ignored2, attributes = self.__class__._get_rules(version)
|
|
245
|
+
if attributes:
|
|
246
|
+
for qname, attribute_def in attributes.items():
|
|
247
|
+
if isinstance(attribute_def, (list, tuple)):
|
|
248
|
+
attribute_def = attribute_def[0]
|
|
249
|
+
member = getattr(self, attribute_def)
|
|
250
|
+
# TODO: ensure this hasn't broken existing behavior.
|
|
251
|
+
# member = getattr(self, attribute_def[0])
|
|
252
|
+
if member:
|
|
253
|
+
if _qname_matches(tag, namespace, qname):
|
|
254
|
+
matches.append(XmlAttribute(qname, member))
|
|
255
|
+
for qname, value in self._other_attributes.items():
|
|
256
|
+
if _qname_matches(tag, namespace, qname):
|
|
257
|
+
matches.append(XmlAttribute(qname, value))
|
|
258
|
+
return matches
|
|
259
|
+
|
|
260
|
+
GetAttributes = get_attributes
|
|
261
|
+
|
|
262
|
+
def _harvest_tree(self, tree, version=1):
|
|
263
|
+
"""Populates object members from the data in the tree Element."""
|
|
264
|
+
qname, elements, attributes = self.__class__._get_rules(version)
|
|
265
|
+
for element in tree:
|
|
266
|
+
if elements and element.tag in elements:
|
|
267
|
+
definition = elements[element.tag]
|
|
268
|
+
# If this is a repeating element, make sure the member is set to a
|
|
269
|
+
# list.
|
|
270
|
+
if definition[2]:
|
|
271
|
+
if getattr(self, definition[0]) is None:
|
|
272
|
+
setattr(self, definition[0], [])
|
|
273
|
+
getattr(self, definition[0]).append(_xml_element_from_tree(element,
|
|
274
|
+
definition[1], version))
|
|
275
|
+
else:
|
|
276
|
+
setattr(self, definition[0], _xml_element_from_tree(element,
|
|
277
|
+
definition[1], version))
|
|
278
|
+
else:
|
|
279
|
+
self._other_elements.append(_xml_element_from_tree(element, XmlElement,
|
|
280
|
+
version))
|
|
281
|
+
for attrib, value in tree.attrib.items():
|
|
282
|
+
if attributes and attrib in attributes:
|
|
283
|
+
setattr(self, attributes[attrib], value)
|
|
284
|
+
else:
|
|
285
|
+
self._other_attributes[attrib] = value
|
|
286
|
+
if tree.text:
|
|
287
|
+
self.text = tree.text
|
|
288
|
+
|
|
289
|
+
def _to_tree(self, version=1):
|
|
290
|
+
new_tree = ElementTree.Element(_get_qname(self, version))
|
|
291
|
+
self._attach_members(new_tree, version)
|
|
292
|
+
return new_tree
|
|
293
|
+
|
|
294
|
+
def _attach_members(self, tree, version=1):
|
|
295
|
+
"""Convert members to XML elements/attributes and add them to the tree.
|
|
296
|
+
|
|
297
|
+
Args:
|
|
298
|
+
tree: An ElementTree.Element which will be modified. The members of
|
|
299
|
+
this object will be added as child elements or attributes
|
|
300
|
+
according to the rules described in _expected_elements and
|
|
301
|
+
_expected_attributes. The elements and attributes stored in
|
|
302
|
+
other_attributes and other_elements are also added a children
|
|
303
|
+
of this tree.
|
|
304
|
+
version: int Ingnored in this method but used by VersionedElement.
|
|
305
|
+
encoding: str (optional)
|
|
306
|
+
"""
|
|
307
|
+
qname, elements, attributes = self.__class__._get_rules(version)
|
|
308
|
+
encoding = STRING_ENCODING
|
|
309
|
+
# Add the expected elements and attributes to the tree.
|
|
310
|
+
if elements:
|
|
311
|
+
for tag, element_def in elements.items():
|
|
312
|
+
member = getattr(self, element_def[0])
|
|
313
|
+
# If this is a repeating element and there are members in the list.
|
|
314
|
+
if member and element_def[2]:
|
|
315
|
+
for instance in member:
|
|
316
|
+
instance._become_child(tree, version)
|
|
317
|
+
elif member:
|
|
318
|
+
member._become_child(tree, version)
|
|
319
|
+
if attributes:
|
|
320
|
+
for attribute_tag, member_name in attributes.items():
|
|
321
|
+
value = getattr(self, member_name)
|
|
322
|
+
if value:
|
|
323
|
+
tree.attrib[attribute_tag] = value
|
|
324
|
+
# Add the unexpected (other) elements and attributes to the tree.
|
|
325
|
+
for element in self._other_elements:
|
|
326
|
+
element._become_child(tree, version)
|
|
327
|
+
for key, value in self._other_attributes.items():
|
|
328
|
+
# I'm not sure if unicode can be used in the attribute name, so for now
|
|
329
|
+
# we assume the encoding is correct for the attribute name.
|
|
330
|
+
if not isinstance(value, str):
|
|
331
|
+
value = value.decode(encoding)
|
|
332
|
+
tree.attrib[key] = value
|
|
333
|
+
if self.text:
|
|
334
|
+
if isinstance(self.text, str):
|
|
335
|
+
tree.text = self.text
|
|
336
|
+
else:
|
|
337
|
+
tree.text = self.text.decode(encoding)
|
|
338
|
+
|
|
339
|
+
def to_string(self, version=1, encoding=None, pretty_print=None):
|
|
340
|
+
"""Converts this object to XML."""
|
|
341
|
+
|
|
342
|
+
tree_string = ElementTree.tostring(self._to_tree(version))
|
|
343
|
+
|
|
344
|
+
if pretty_print and xmlString is not None:
|
|
345
|
+
return xmlString(tree_string).toprettyxml()
|
|
346
|
+
|
|
347
|
+
return tree_string
|
|
348
|
+
|
|
349
|
+
ToString = to_string
|
|
350
|
+
|
|
351
|
+
def __str__(self):
|
|
352
|
+
return self.to_string()
|
|
353
|
+
|
|
354
|
+
def _become_child(self, tree, version=1):
|
|
355
|
+
"""Adds a child element to tree with the XML data in self."""
|
|
356
|
+
new_child = ElementTree.Element(_get_qname(self, version))
|
|
357
|
+
tree.append(new_child)
|
|
358
|
+
new_child.tag = _get_qname(self, version)
|
|
359
|
+
self._attach_members(new_child, version)
|
|
360
|
+
|
|
361
|
+
def __get_extension_elements(self):
|
|
362
|
+
return self._other_elements
|
|
363
|
+
|
|
364
|
+
def __set_extension_elements(self, elements):
|
|
365
|
+
self._other_elements = elements
|
|
366
|
+
|
|
367
|
+
extension_elements = property(__get_extension_elements,
|
|
368
|
+
__set_extension_elements,
|
|
369
|
+
"""Provides backwards compatibility for v1 atom.AtomBase classes.""")
|
|
370
|
+
|
|
371
|
+
def __get_extension_attributes(self):
|
|
372
|
+
return self._other_attributes
|
|
373
|
+
|
|
374
|
+
def __set_extension_attributes(self, attributes):
|
|
375
|
+
self._other_attributes = attributes
|
|
376
|
+
|
|
377
|
+
extension_attributes = property(__get_extension_attributes,
|
|
378
|
+
__set_extension_attributes,
|
|
379
|
+
"""Provides backwards compatibility for v1 atom.AtomBase classes.""")
|
|
380
|
+
|
|
381
|
+
def _get_tag(self, version=1):
|
|
382
|
+
qname = _get_qname(self, version)
|
|
383
|
+
if qname:
|
|
384
|
+
return qname[qname.find('}') + 1:]
|
|
385
|
+
return None
|
|
386
|
+
|
|
387
|
+
def _get_namespace(self, version=1):
|
|
388
|
+
qname = _get_qname(self, version)
|
|
389
|
+
if qname.startswith('{'):
|
|
390
|
+
return qname[1:qname.find('}')]
|
|
391
|
+
else:
|
|
392
|
+
return None
|
|
393
|
+
|
|
394
|
+
def _set_tag(self, tag):
|
|
395
|
+
if isinstance(self._qname, tuple):
|
|
396
|
+
self._qname = self._qname.copy()
|
|
397
|
+
if self._qname[0].startswith('{'):
|
|
398
|
+
self._qname[0] = '{%s}%s' % (self._get_namespace(1), tag)
|
|
399
|
+
else:
|
|
400
|
+
self._qname[0] = tag
|
|
401
|
+
else:
|
|
402
|
+
if self._qname is not None and self._qname.startswith('{'):
|
|
403
|
+
self._qname = '{%s}%s' % (self._get_namespace(), tag)
|
|
404
|
+
else:
|
|
405
|
+
self._qname = tag
|
|
406
|
+
|
|
407
|
+
def _set_namespace(self, namespace):
|
|
408
|
+
tag = self._get_tag(1)
|
|
409
|
+
if tag is None:
|
|
410
|
+
tag = ''
|
|
411
|
+
if isinstance(self._qname, tuple):
|
|
412
|
+
self._qname = self._qname.copy()
|
|
413
|
+
if namespace:
|
|
414
|
+
self._qname[0] = '{%s}%s' % (namespace, tag)
|
|
415
|
+
else:
|
|
416
|
+
self._qname[0] = tag
|
|
417
|
+
else:
|
|
418
|
+
if namespace:
|
|
419
|
+
self._qname = '{%s}%s' % (namespace, tag)
|
|
420
|
+
else:
|
|
421
|
+
self._qname = tag
|
|
422
|
+
|
|
423
|
+
tag = property(_get_tag, _set_tag,
|
|
424
|
+
"""Provides backwards compatibility for v1 atom.AtomBase classes.""")
|
|
425
|
+
|
|
426
|
+
namespace = property(_get_namespace, _set_namespace,
|
|
427
|
+
"""Provides backwards compatibility for v1 atom.AtomBase classes.""")
|
|
428
|
+
|
|
429
|
+
# Provided for backwards compatibility to atom.ExtensionElement
|
|
430
|
+
children = extension_elements
|
|
431
|
+
attributes = extension_attributes
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
def _get_qname(element, version):
|
|
435
|
+
if isinstance(element._qname, tuple):
|
|
436
|
+
if version <= len(element._qname):
|
|
437
|
+
return element._qname[version - 1]
|
|
438
|
+
else:
|
|
439
|
+
return element._qname[-1]
|
|
440
|
+
else:
|
|
441
|
+
return element._qname
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
def _qname_matches(tag, namespace, qname):
|
|
445
|
+
"""Logic determines if a QName matches the desired local tag and namespace.
|
|
446
|
+
|
|
447
|
+
This is used in XmlElement.get_elements and XmlElement.get_attributes to
|
|
448
|
+
find matches in the element's members (among all expected-and-unexpected
|
|
449
|
+
elements-and-attributes).
|
|
450
|
+
|
|
451
|
+
Args:
|
|
452
|
+
expected_tag: string
|
|
453
|
+
expected_namespace: string
|
|
454
|
+
qname: string in the form '{xml_namespace}localtag' or 'tag' if there is
|
|
455
|
+
no namespace.
|
|
456
|
+
|
|
457
|
+
Returns:
|
|
458
|
+
boolean True if the member's tag and namespace fit the expected tag and
|
|
459
|
+
namespace.
|
|
460
|
+
"""
|
|
461
|
+
# If there is no expected namespace or tag, then everything will match.
|
|
462
|
+
if qname is None:
|
|
463
|
+
member_tag = None
|
|
464
|
+
member_namespace = None
|
|
465
|
+
else:
|
|
466
|
+
if qname.startswith('{'):
|
|
467
|
+
member_namespace = qname[1:qname.index('}')]
|
|
468
|
+
member_tag = qname[qname.index('}') + 1:]
|
|
469
|
+
else:
|
|
470
|
+
member_namespace = None
|
|
471
|
+
member_tag = qname
|
|
472
|
+
return ((tag is None and namespace is None)
|
|
473
|
+
# If there is a tag, but no namespace, see if the local tag matches.
|
|
474
|
+
or (namespace is None and member_tag == tag)
|
|
475
|
+
# There was no tag, but there was a namespace so see if the namespaces
|
|
476
|
+
# match.
|
|
477
|
+
or (tag is None and member_namespace == namespace)
|
|
478
|
+
# There was no tag, and the desired elements have no namespace, so check
|
|
479
|
+
# to see that the member's namespace is None.
|
|
480
|
+
or (tag is None and namespace == ''
|
|
481
|
+
and member_namespace is None)
|
|
482
|
+
# The tag and the namespace both match.
|
|
483
|
+
or (tag == member_tag
|
|
484
|
+
and namespace == member_namespace)
|
|
485
|
+
# The tag matches, and the expected namespace is the empty namespace,
|
|
486
|
+
# check to make sure the member's namespace is None.
|
|
487
|
+
or (tag == member_tag and namespace == ''
|
|
488
|
+
and member_namespace is None))
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
def parse(xml_string, target_class=None, version=1):
|
|
492
|
+
"""Parses the XML string according to the rules for the target_class.
|
|
493
|
+
|
|
494
|
+
Args:
|
|
495
|
+
xml_string: bytes
|
|
496
|
+
target_class: XmlElement or a subclass. If None is specified, the
|
|
497
|
+
XmlElement class is used.
|
|
498
|
+
version: int (optional) The version of the schema which should be used when
|
|
499
|
+
converting the XML into an object. The default is 1.
|
|
500
|
+
encoding: str (optional) The character encoding of the bytes in the
|
|
501
|
+
xml_string. Default is 'UTF-8'.
|
|
502
|
+
"""
|
|
503
|
+
if target_class is None:
|
|
504
|
+
target_class = XmlElement
|
|
505
|
+
if not isinstance(xml_string, bytes):
|
|
506
|
+
raise Exception("This function only accepts bytes")
|
|
507
|
+
tree = ElementTree.fromstring(xml_string)
|
|
508
|
+
return _xml_element_from_tree(tree, target_class, version)
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
Parse = parse
|
|
512
|
+
xml_element_from_string = parse
|
|
513
|
+
XmlElementFromString = xml_element_from_string
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
def _xml_element_from_tree(tree, target_class, version=1):
|
|
517
|
+
if target_class._qname is None:
|
|
518
|
+
instance = target_class()
|
|
519
|
+
instance._qname = tree.tag
|
|
520
|
+
instance._harvest_tree(tree, version)
|
|
521
|
+
return instance
|
|
522
|
+
# TODO handle the namespace-only case
|
|
523
|
+
# Namespace only will be used with Google Spreadsheets rows and
|
|
524
|
+
# Google Base item attributes.
|
|
525
|
+
elif tree.tag == _get_qname(target_class, version):
|
|
526
|
+
instance = target_class()
|
|
527
|
+
instance._harvest_tree(tree, version)
|
|
528
|
+
return instance
|
|
529
|
+
return None
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
class XmlAttribute(object):
|
|
533
|
+
def __init__(self, qname, value):
|
|
534
|
+
self._qname = qname
|
|
535
|
+
self.value = value
|