Skip to content

Commit dbae147

Browse files
authored
Updates for release 1.2.0 (Azure#81)
* Made setup 2.7 compatible * Separated async tests * Support 2.7 types * Bumped version * Added non-ascii tests * Fix CI * Fix Py27 pylint * Added iot sample * Updated sender/receiver client opening * bumped version * Updated tests * Fixed test name * Fixed test env settings * Skip eph test
1 parent 0871895 commit dbae147

34 files changed

+943
-411
lines changed

.travis.yml

+29-5
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,41 @@ dist: xenial
44
sudo: required
55
matrix:
66
include:
7+
- os: linux
8+
python: "2.7"
9+
dist: trusty
10+
script:
11+
- pytest
12+
- python ./setup.py check -r -s
13+
- pylint --ignore=async_ops azure.eventhub
14+
- os: linux
15+
python: "3.4"
16+
dist: trusty
17+
script:
18+
- pytest
19+
- python ./setup.py check -r -s
20+
- pylint --ignore=async_ops azure.eventhub
721
- os: linux
822
python: "3.5"
23+
script:
24+
- pytest
25+
- python ./setup.py check -r -s
26+
- pylint azure.eventhub
27+
- pylint azure.eventprocessorhost
928
- os: linux
1029
python: "3.6"
30+
script:
31+
- pytest
32+
- python ./setup.py check -r -s
33+
- pylint azure.eventhub
34+
- pylint azure.eventprocessorhost
1135
- os: linux
1236
python: "3.7"
37+
script:
38+
- pytest
39+
- python ./setup.py check -r -s
40+
- pylint azure.eventhub
41+
- pylint azure.eventprocessorhost
1342
install:
1443
- pip install -r dev_requirements.txt
1544
- pip install -e .
16-
script:
17-
- pytest
18-
- python ./setup.py check -r -s
19-
- pylint azure.eventhub
20-
- pylint azure.eventprocessorhost

HISTORY.rst

+7
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33
Release History
44
===============
55

6+
1.2.0
7+
+++++
8+
9+
- Support for Python 2.7 in azure.eventhub module (azure.eventprocessorhost will not support Python 2.7).
10+
- Parse EventData.enqueued_time as a UTC timestamp (issue #72, thanks @vjrantal)
11+
12+
613
1.1.1 (2019-10-03)
714
++++++++++++++++++
815

README.rst

-11
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,6 @@ Wheels are provided for all major operating systems, so you can install directly
3131
3232
$ pip install azure-eventhub
3333
34-
Python 2.7 support
35-
++++++++++++++++++
36-
37-
Python 2.7 will be supported for the synchronous operations in azure.eventhub from v1.2.0.
38-
This is available as a pre-release.
39-
40-
.. code:: shell
41-
42-
$ pip install azure-eventhub --pre
43-
44-
Python 2.7 support is not planned for azure.eventprocessorhost.
4534
4635
Documentation
4736
+++++++++++++

azure/eventhub/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# Licensed under the MIT License. See License.txt in the project root for license information.
44
# --------------------------------------------------------------------------------------------
55

6-
__version__ = "1.1.1"
6+
__version__ = "1.2.0"
77

88
from azure.eventhub.common import EventData, EventHubError, Offset
99
from azure.eventhub.client import EventHubClient

azure/eventhub/async_ops/__init__.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,7 @@
77
import asyncio
88
import time
99
import datetime
10-
try:
11-
from urllib import urlparse, unquote_plus, urlencode, quote_plus
12-
except ImportError:
13-
from urllib.parse import urlparse, unquote_plus, urlencode, quote_plus
10+
from urllib.parse import urlparse, unquote_plus, urlencode, quote_plus
1411

1512
from uamqp import authentication, constants, types, errors
1613
from uamqp import (

azure/eventhub/async_ops/receiver_async.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,8 @@ async def open_async(self):
104104
properties=self.client.create_properties(),
105105
loop=self.loop)
106106
await self._handler.open_async()
107-
while not await self.has_started():
108-
await self._handler._connection.work_async()
107+
while not await self._handler.client_ready_async():
108+
await asyncio.sleep(0.05)
109109

110110
async def reconnect_async(self):
111111
"""If the Receiver was disconnected from the service with
@@ -132,8 +132,8 @@ async def reconnect_async(self):
132132
loop=self.loop)
133133
try:
134134
await self._handler.open_async()
135-
while not await self.has_started():
136-
await self._handler._connection.work_async()
135+
while not await self._handler.client_ready_async():
136+
await asyncio.sleep(0.05)
137137
except (errors.LinkDetach, errors.ConnectionClose) as shutdown:
138138
if shutdown.action.retry and self.auto_reconnect:
139139
log.info("AsyncReceiver detached. Attempting reconnect.")
@@ -163,6 +163,7 @@ async def has_started(self):
163163
Whether the handler has completed all start up processes such as
164164
establishing the connection, session, link and authentication, and
165165
is not ready to process messages.
166+
**This function is now deprecated and will be removed in v2.0+.**
166167
167168
:rtype: bool
168169
"""

azure/eventhub/async_ops/sender_async.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ async def open_async(self):
9797
properties=self.client.create_properties(),
9898
loop=self.loop)
9999
await self._handler.open_async()
100-
while not await self.has_started():
101-
await self._handler._connection.work_async() # pylint: disable=protected-access
100+
while not await self._handler.client_ready_async():
101+
await asyncio.sleep(0.05)
102102

103103
async def reconnect_async(self):
104104
"""If the Receiver was disconnected from the service with
@@ -148,6 +148,7 @@ async def has_started(self):
148148
Whether the handler has completed all start up processes such as
149149
establishing the connection, session, link and authentication, and
150150
is not ready to process messages.
151+
**This function is now deprecated and will be removed in v2.0+.**
151152
152153
:rtype: bool
153154
"""

azure/eventhub/client.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# Copyright (c) Microsoft Corporation. All rights reserved.
33
# Licensed under the MIT License. See License.txt in the project root for license information.
44
# --------------------------------------------------------------------------------------------
5+
from __future__ import unicode_literals
56

67
import logging
78
import datetime
@@ -10,7 +11,8 @@
1011
import time
1112
import functools
1213
try:
13-
from urllib import urlparse, unquote_plus, urlencode, quote_plus
14+
from urlparse import urlparse
15+
from urllib import unquote_plus, urlencode, quote_plus
1416
except ImportError:
1517
from urllib.parse import urlparse, unquote_plus, urlencode, quote_plus
1618

azure/eventhub/common.py

+11-6
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22
# Copyright (c) Microsoft Corporation. All rights reserved.
33
# Licensed under the MIT License. See License.txt in the project root for license information.
44
# --------------------------------------------------------------------------------------------
5+
from __future__ import unicode_literals
56

67
import datetime
78
import time
89
import json
910

11+
import six
12+
1013
from uamqp import Message, BatchMessage
1114
from uamqp import types, constants, errors
1215
from uamqp.message import MessageHeader, MessageProperties
@@ -63,6 +66,8 @@ def __init__(self, body=None, batch=None, to_device=None, message=None):
6366
:type body: str, bytes or list
6467
:param batch: A data generator to send batched messages.
6568
:type batch: Generator
69+
:param to_device: An IoT device to route to.
70+
:type to_device: str
6671
:param message: The received message.
6772
:type message: ~uamqp.message.Message
6873
"""
@@ -94,7 +99,7 @@ def sequence_number(self):
9499
"""
95100
The sequence number of the event data object.
96101
97-
:rtype: int
102+
:rtype: int or long
98103
"""
99104
return self._annotations.get(EventData.PROP_SEQ_NUMBER, None)
100105

@@ -103,7 +108,7 @@ def offset(self):
103108
"""
104109
The offset of the event data object.
105110
106-
:rtype: int
111+
:rtype: ~azure.eventhub.common.Offset
107112
"""
108113
try:
109114
return Offset(self._annotations[EventData.PROP_OFFSET].decode('UTF-8'))
@@ -200,13 +205,13 @@ def body_as_str(self, encoding='UTF-8'):
200205
201206
:param encoding: The encoding to use for decoding message data.
202207
Default is 'UTF-8'
203-
:rtype: str
208+
:rtype: str or unicode
204209
"""
205210
data = self.body
206211
try:
207212
return "".join(b.decode(encoding) for b in data)
208213
except TypeError:
209-
return str(data)
214+
return six.text_type(data)
210215
except: # pylint: disable=bare-except
211216
pass
212217
try:
@@ -269,7 +274,7 @@ def selector(self):
269274
if isinstance(self.value, datetime.datetime):
270275
timestamp = (time.mktime(self.value.timetuple()) * 1000) + (self.value.microsecond/1000)
271276
return ("amqp.annotation.x-opt-enqueued-time {} '{}'".format(operator, int(timestamp))).encode('utf-8')
272-
if isinstance(self.value, int):
277+
if isinstance(self.value, six.integer_types):
273278
return ("amqp.annotation.x-opt-sequence-number {} '{}'".format(operator, self.value)).encode('utf-8')
274279
return ("amqp.annotation.x-opt-offset {} '{}'".format(operator, self.value)).encode('utf-8')
275280

@@ -310,7 +315,7 @@ def __init__(self, message, details=None):
310315

311316
def _parse_error(self, error_list):
312317
details = []
313-
self.message = error_list if isinstance(error_list, str) else error_list.decode('UTF-8')
318+
self.message = error_list if isinstance(error_list, six.text_type) else error_list.decode('UTF-8')
314319
details_index = self.message.find(" Reference:")
315320
if details_index >= 0:
316321
details_msg = self.message[details_index + 1:]

azure/eventhub/receiver.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
# Copyright (c) Microsoft Corporation. All rights reserved.
33
# Licensed under the MIT License. See License.txt in the project root for license information.
44
# --------------------------------------------------------------------------------------------
5+
from __future__ import unicode_literals
56

67
import uuid
78
import logging
9+
import time
810

911
from uamqp import types, errors
1012
from uamqp import ReceiveClient, Source
@@ -14,7 +16,7 @@
1416
log = logging.getLogger(__name__)
1517

1618

17-
class Receiver:
19+
class Receiver(object):
1820
"""
1921
Implements a Receiver.
2022
"""
@@ -97,16 +99,16 @@ def open(self):
9799
client_name=self.name,
98100
properties=self.client.create_properties())
99101
self._handler.open()
100-
while not self.has_started():
101-
self._handler._connection.work()
102+
while not self._handler.client_ready():
103+
time.sleep(0.05)
102104

103105
def reconnect(self):
104106
"""If the Receiver was disconnected from the service with
105107
a retryable error - attempt to reconnect."""
106108
# pylint: disable=protected-access
107109
alt_creds = {
108110
"username": self.client._auth_config.get("iot_username"),
109-
"password":self.client._auth_config.get("iot_password")}
111+
"password": self.client._auth_config.get("iot_password")}
110112
self._handler.close()
111113
source = Source(self.source)
112114
if self.offset is not None:
@@ -124,8 +126,8 @@ def reconnect(self):
124126
properties=self.client.create_properties())
125127
try:
126128
self._handler.open()
127-
while not self.has_started():
128-
self._handler._connection.work()
129+
while not self._handler.client_ready():
130+
time.sleep(0.05)
129131
except (errors.LinkDetach, errors.ConnectionClose) as shutdown:
130132
if shutdown.action.retry and self.auto_reconnect:
131133
self.reconnect()
@@ -160,6 +162,7 @@ def has_started(self):
160162
Whether the handler has completed all start up processes such as
161163
establishing the connection, session, link and authentication, and
162164
is not ready to process messages.
165+
**This function is now deprecated and will be removed in v2.0+.**
163166
164167
:rtype: bool
165168
"""

azure/eventhub/sender.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
# Copyright (c) Microsoft Corporation. All rights reserved.
33
# Licensed under the MIT License. See License.txt in the project root for license information.
44
# --------------------------------------------------------------------------------------------
5+
from __future__ import unicode_literals
56

67
import uuid
78
import logging
9+
import time
810

911
from uamqp import constants, errors
1012
from uamqp import SendClient
@@ -14,7 +16,7 @@
1416
log = logging.getLogger(__name__)
1517

1618

17-
class Sender:
19+
class Sender(object):
1820
"""
1921
Implements a Sender.
2022
"""
@@ -88,8 +90,8 @@ def open(self):
8890
client_name=self.name,
8991
properties=self.client.create_properties())
9092
self._handler.open()
91-
while not self.has_started():
92-
self._handler._connection.work() # pylint: disable=protected-access
93+
while not self._handler.client_ready():
94+
time.sleep(0.05)
9395

9496
def reconnect(self):
9597
"""If the Sender was disconnected from the service with
@@ -144,6 +146,7 @@ def has_started(self):
144146
Whether the handler has completed all start up processes such as
145147
establishing the connection, session, link and authentication, and
146148
is not ready to process messages.
149+
**This function is now deprecated and will be removed in v2.0+.**
147150
148151
:rtype: bool
149152
"""

0 commit comments

Comments
 (0)