Skip to content

Commit 2248b12

Browse files
committed
Merge pull request #72 from WindowsAzure/dev
Improved support for unicode data and fixes for github issues 66, 68, 69
2 parents 01659a9 + 9b7889b commit 2248b12

19 files changed

+699
-291
lines changed

ChangeLog.txt

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
2012-12-17 Version 0.6.1
2+
* Fixes for bugs:
3+
#69 _get_readable_id doesn't support queues with slashes in their names
4+
#68 Service bus cache of tokens doesn't support multiple creds in same app
5+
#66 Need to change the default timeout for httprequest on windows
6+
* Improved support for unicode data
7+
18
2012-10-16 Version 0.6.0
29
* Added service management API
310
* Added ability to specify custom hosts

src/azure.pyproj

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
<ProjectGuid>{25b2c65a-0553-4452-8907-8b5b17544e68}</ProjectGuid>
77
<ProjectHome>
88
</ProjectHome>
9-
<StartupFile>
10-
</StartupFile>
9+
<StartupFile>azure\storage\blobservice.py</StartupFile>
1110
<SearchPath>..</SearchPath>
1211
<WorkingDirectory>.</WorkingDirectory>
1312
<OutputPath>.</OutputPath>

src/azure/__init__.py

+31-12
Original file line numberDiff line numberDiff line change
@@ -95,15 +95,23 @@ class HeaderDict(dict):
9595
def __getitem__(self, index):
9696
return super(HeaderDict, self).__getitem__(index.lower())
9797

98-
def _get_readable_id(id_name):
98+
def _get_readable_id(id_name, id_prefix_to_skip):
9999
"""simplified an id to be more friendly for us people"""
100-
pos = id_name.rfind('/')
100+
# id_name is in the form 'https://namespace.host.suffix/name'
101+
# where name may contain a forward slash!
102+
pos = id_name.find('//')
101103
if pos != -1:
102-
return id_name[pos+1:]
103-
else:
104-
return id_name
105-
106-
def _get_entry_properties(xmlstr, include_id):
104+
pos += 2
105+
if id_prefix_to_skip:
106+
pos = id_name.find(id_prefix_to_skip, pos)
107+
if pos != -1:
108+
pos += len(id_prefix_to_skip)
109+
pos = id_name.find('/', pos)
110+
if pos != -1:
111+
return id_name[pos+1:]
112+
return id_name
113+
114+
def _get_entry_properties(xmlstr, include_id, id_prefix_to_skip=None):
107115
''' get properties from entry xml '''
108116
xmldoc = minidom.parseString(xmlstr)
109117
properties = {}
@@ -120,7 +128,7 @@ def _get_entry_properties(xmlstr, include_id):
120128

121129
if include_id:
122130
for id in _get_child_nodes(entry, 'id'):
123-
properties['name'] = _get_readable_id(id.firstChild.nodeValue)
131+
properties['name'] = _get_readable_id(id.firstChild.nodeValue, id_prefix_to_skip)
124132

125133
return properties
126134

@@ -207,7 +215,16 @@ def _get_serialization_name(element_name):
207215

208216
return ''.join(name.capitalize() for name in element_name.split('_'))
209217

218+
def _str(value):
219+
if isinstance(value, unicode):
220+
return value.encode('utf-8')
221+
222+
return str(value)
223+
210224
def _str_or_none(value):
225+
if isinstance(value, unicode):
226+
return value.encode('utf-8')
227+
211228
if value is None:
212229
return None
213230

@@ -375,9 +392,8 @@ def _fill_dict_of(xmldoc, parent_xml_element_name, pair_xml_element_name, key_xm
375392
keys = _get_child_nodes(pair, key_xml_element_name)
376393
values = _get_child_nodes(pair, value_xml_element_name)
377394
if keys and values:
378-
key = str(keys[0].firstChild.nodeValue)
379-
value = str(values[0].firstChild.nodeValue)
380-
395+
key = keys[0].firstChild.nodeValue
396+
value = values[0].firstChild.nodeValue
381397
return_obj[key] = value
382398

383399
return return_obj
@@ -436,7 +452,7 @@ def _get_request_body(request_body):
436452
elif isinstance(request_body, WindowsAzureData):
437453
return _convert_class_to_xml(request_body)
438454

439-
return request_body
455+
return _str(request_body)
440456

441457
def _parse_enum_results_list(response, return_type, resp_type, item_type):
442458
"""resp_body is the XML we received
@@ -514,6 +530,9 @@ def _fill_data_to_return_object(node, return_obj):
514530
value = _fill_data_minidom(node, name, '')
515531
if value is not None:
516532
value = base64.b64decode(value)
533+
try:
534+
value = value.decode('utf-8')
535+
except: pass
517536
#always set the attribute, so we don't end up returning an object with type _Base64String
518537
setattr(return_obj, name, value)
519538
else:

src/azure/http/winhttp.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ def open(self, method, url):
163163
method: the request VERB 'GET', 'POST', etc.
164164
url: the url to connect
165165
'''
166+
_WinHttpRequest._SetTimeouts(self, 0, 65000, 65000, 65000)
166167

167168
flag = VARIANT()
168169
flag.vt = VT_BOOL
@@ -321,11 +322,12 @@ def putrequest(self, method, uri):
321322

322323
#sets certificate for the connection if cert_file is set.
323324
if self.cert_file is not None:
324-
self._httprequest.set_client_certificate(BSTR(unicode(self.cert_file)))
325+
self._httprequest.set_client_certificate(unicode(self.cert_file))
325326

326327
def putheader(self, name, value):
327328
''' Sends the headers of request. '''
328-
self._httprequest.set_request_header(unicode(name), unicode(value))
329+
self._httprequest.set_request_header(str(name).decode('utf-8'),
330+
str(value).decode('utf-8'))
329331

330332
def endheaders(self):
331333
''' No operation. Exists only to provide the same interface of httplib HTTPConnection.'''

src/azure/servicebus/__init__.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,9 @@ def add_headers(self, request):
190190
# Adds custom properties
191191
if self.custom_properties:
192192
for name, value in self.custom_properties.iteritems():
193-
if isinstance(value, str):
193+
if isinstance(value, unicode):
194+
request.headers.append((name, '"' + value.encode('utf-8') + '"'))
195+
elif isinstance(value, str):
194196
request.headers.append((name, '"' + str(value) + '"'))
195197
elif isinstance(value, datetime):
196198
request.headers.append((name, '"' + value.strftime('%a, %d %b %Y %H:%M:%S GMT') + '"'))
@@ -248,8 +250,8 @@ def _get_token(request, account_key, issuer):
248250
account_key: service bus access key
249251
issuer: service bus issuer
250252
'''
251-
wrap_scope = 'http://' + request.host + request.path
252-
253+
wrap_scope = 'http://' + request.host + request.path + issuer + account_key
254+
253255
# Check whether has unexpired cache, return cached token if it is still usable.
254256
if _tokens.has_key(wrap_scope):
255257
token = _tokens[wrap_scope]
@@ -371,7 +373,7 @@ def _convert_xml_to_rule(xmlstr):
371373
setattr(rule, 'action_expression', action_expression.nodeValue)
372374

373375
#extract id, updated and name value from feed entry and set them of rule.
374-
for name, value in _get_entry_properties(xmlstr, True).iteritems():
376+
for name, value in _get_entry_properties(xmlstr, True, '/rules').iteritems():
375377
setattr(rule, name, value)
376378

377379
return rule
@@ -565,7 +567,7 @@ def _convert_xml_to_subscription(xmlstr):
565567
if node_value is not None:
566568
subscription.message_count = int(node_value)
567569

568-
for name, value in _get_entry_properties(xmlstr, True).iteritems():
570+
for name, value in _get_entry_properties(xmlstr, True, '/subscriptions').iteritems():
569571
setattr(subscription, name, value)
570572

571573
return subscription

0 commit comments

Comments
 (0)