Skip to content

Commit 07d2d5e

Browse files
committed
Fix silent serialization failure when publishing non-JSON-serializable objects
1 parent 07ddfab commit 07d2d5e

File tree

4 files changed

+53
-3
lines changed

4 files changed

+53
-3
lines changed

pubnub/enums.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class PNStatusCategory(Enum):
3939
PNInternalExceptionCategory = 17
4040
PNSubscriptionChangedCategory = 18
4141
PNConnectionErrorCategory = 19
42+
PNSerializationErrorCategory = 20
4243

4344

4445
class PNOperationType(object):

pubnub/pubnub_asyncio.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ async def main():
7777
from pubnub.callbacks import SubscribeCallback, ReconnectionCallback
7878
from pubnub.errors import PNERR_REQUEST_CANCELLED, PNERR_CLIENT_TIMEOUT
7979
from pubnub.exceptions import PubNubAsyncioException, PubNubException
80+
from pubnub.models.consumer.pn_error_data import PNErrorData
8081

8182
# flake8: noqa
8283
from pubnub.models.envelopes import AsyncioEnvelope
@@ -234,9 +235,16 @@ async def request_future(self, options_func, cancellation_event):
234235
res = await self._request_handler.async_request(options_func, cancellation_event)
235236
return res
236237
except PubNubException as e:
238+
if e.status is not None:
239+
status = e.status
240+
else:
241+
status = PNStatus()
242+
status.category = PNStatusCategory.PNBadRequestCategory
243+
status.error = True
244+
status.error_data = PNErrorData(str(e), e)
237245
return PubNubAsyncioException(
238246
result=None,
239-
status=e.status
247+
status=status
240248
)
241249
except asyncio.TimeoutError:
242250
return PubNubAsyncioException(

pubnub/utils.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from pubnub.models.consumer.common import PNStatus
1515
from pubnub.errors import PNERR_JSON_NOT_SERIALIZABLE
1616
from pubnub.exceptions import PubNubException
17+
from pubnub.models.consumer.pn_error_data import PNErrorData
1718

1819

1920
def get_data_for_user(data):
@@ -29,10 +30,17 @@ def get_data_for_user(data):
2930
def write_value_as_string(data):
3031
try:
3132
return json.dumps(data)
32-
except TypeError:
33-
raise PubNubException(
33+
except TypeError as e:
34+
exc = PubNubException(
35+
errormsg=str(e),
3436
pn_error=PNERR_JSON_NOT_SERIALIZABLE
3537
)
38+
status = PNStatus()
39+
status.category = PNStatusCategory.PNSerializationErrorCategory
40+
status.error = True
41+
status.error_data = PNErrorData(str(exc), exc)
42+
exc.status = status
43+
raise exc
3644

3745

3846
def url_encode(data):
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from datetime import datetime
2+
3+
import pytest
4+
5+
from pubnub.enums import PNStatusCategory
6+
from pubnub.exceptions import PubNubAsyncioException
7+
from pubnub.models.consumer.common import PNStatus
8+
from pubnub.models.consumer.pn_error_data import PNErrorData
9+
from pubnub.pubnub_asyncio import PubNubAsyncio
10+
from tests.helper import pnconf_copy
11+
12+
13+
@pytest.mark.asyncio
14+
async def test_publish_non_serializable_returns_usable_error():
15+
pubnub = PubNubAsyncio(pnconf_copy())
16+
17+
result = await pubnub.publish().channel("ch1").message({
18+
"text": "Hello",
19+
"timestamp": datetime.now(),
20+
}).future()
21+
22+
assert isinstance(result, PubNubAsyncioException)
23+
assert result.is_error() is True
24+
assert isinstance(result.status, PNStatus)
25+
assert result.status.error is True
26+
assert result.status.category == PNStatusCategory.PNSerializationErrorCategory
27+
assert isinstance(result.status.error_data, PNErrorData)
28+
assert str(result) == (
29+
"Trying to publish not JSON serializable object: "
30+
"Object of type datetime is not JSON serializable"
31+
)
32+
33+
await pubnub.stop()

0 commit comments

Comments
 (0)