From 9f8a0ade3f9924b1d2e796503149c805ef15efba Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Tue, 16 Jul 2019 12:33:30 +0200 Subject: [PATCH 1/3] feat: Make client pickleable --- sentry_sdk/client.py | 26 +++++++++++++++++++------ tests/test_client.py | 33 +------------------------------- tests/test_transport.py | 42 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 38 deletions(-) create mode 100644 tests/test_transport.py diff --git a/sentry_sdk/client.py b/sentry_sdk/client.py index 1c2a379a8f..f0b955bbcc 100644 --- a/sentry_sdk/client.py +++ b/sentry_sdk/client.py @@ -74,15 +74,28 @@ class _Client(object): """ def __init__(self, *args, **kwargs): - # type: (*Optional[str], **Any) -> None + # type: (*Any, **Any) -> None + self.options = get_options(*args, **kwargs) # type: Dict[str, Any] + self._init_impl() + + def __getstate__(self): + # type: () -> Any + return self.options + + def __setstate__(self, state): + # type: (Any) -> None + self.options = state + self._init_impl() + + def _init_impl(self): + # type: () -> None old_debug = _client_init_debug.get(False) try: - self.options = options = get_options(*args, **kwargs) # type: ignore - _client_init_debug.set(options["debug"]) - self.transport = make_transport(options) + _client_init_debug.set(self.options["debug"]) + self.transport = make_transport(self.options) request_bodies = ("always", "never", "small", "medium") - if options["request_bodies"] not in request_bodies: + if self.options["request_bodies"] not in request_bodies: raise ValueError( "Invalid value for request_bodies. Must be one of {}".format( request_bodies @@ -90,7 +103,8 @@ def __init__(self, *args, **kwargs): ) self.integrations = setup_integrations( - options["integrations"], with_defaults=options["default_integrations"] + self.options["integrations"], + with_defaults=self.options["default_integrations"], ) finally: _client_init_debug.set(old_debug) diff --git a/tests/test_client.py b/tests/test_client.py index 867b0e22bd..23e43141b5 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -1,21 +1,12 @@ # coding: utf-8 import json -import logging import pytest import subprocess import sys import time -from datetime import datetime from textwrap import dedent -from sentry_sdk import ( - Hub, - Client, - configure_scope, - capture_message, - add_breadcrumb, - capture_exception, -) +from sentry_sdk import Hub, Client, configure_scope, capture_message, capture_exception from sentry_sdk.hub import HubMeta from sentry_sdk.transport import Transport from sentry_sdk._compat import reraise, text_type, PY2 @@ -359,28 +350,6 @@ def callback(scope): assert not calls -@pytest.mark.parametrize("debug", (True, False)) -def test_transport_works(httpserver, request, capsys, caplog, debug): - httpserver.serve_content("ok", 200) - caplog.set_level(logging.DEBUG) - - client = Client( - "http://foobar@{}/123".format(httpserver.url[len("http://") :]), debug=debug - ) - Hub.current.bind_client(client) - request.addfinalizer(lambda: Hub.current.bind_client(None)) - - add_breadcrumb(level="info", message="i like bread", timestamp=datetime.now()) - capture_message("löl") - client.close() - - out, err = capsys.readouterr() - assert not err and not out - assert httpserver.requests - - assert any("Sending event" in record.msg for record in caplog.records) == debug - - @pytest.mark.tests_internal_exceptions def test_client_debug_option_enabled(sentry_init, caplog): sentry_init(debug=True) diff --git a/tests/test_transport.py b/tests/test_transport.py new file mode 100644 index 0000000000..6b6c0ecb50 --- /dev/null +++ b/tests/test_transport.py @@ -0,0 +1,42 @@ +import logging +import pickle + +from datetime import datetime + +import pytest + +from sentry_sdk import Hub, Client, add_breadcrumb, capture_message + + +@pytest.fixture(params=[True, False]) +def make_client(request): + def inner(*args, **kwargs): + client = Client(*args, **kwargs) + if request.param: + client = pickle.loads(pickle.dumps(client)) + + return client + + return inner + + +@pytest.mark.parametrize("debug", (True, False)) +def test_transport_works(httpserver, request, capsys, caplog, debug, make_client): + httpserver.serve_content("ok", 200) + caplog.set_level(logging.DEBUG) + + client = make_client( + "http://foobar@{}/123".format(httpserver.url[len("http://") :]), debug=debug + ) + Hub.current.bind_client(client) + request.addfinalizer(lambda: Hub.current.bind_client(None)) + + add_breadcrumb(level="info", message="i like bread", timestamp=datetime.now()) + capture_message("löl") + client.close() + + out, err = capsys.readouterr() + assert not err and not out + assert httpserver.requests + + assert any("Sending event" in record.msg for record in caplog.records) == debug From 2ce7b6380ded8d644ba7d17dc227026483256d7e Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Mon, 5 Aug 2019 11:04:43 +0200 Subject: [PATCH 2/3] ref: Wrap pickle state in dict --- sentry_sdk/client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sentry_sdk/client.py b/sentry_sdk/client.py index f0b955bbcc..93fe60ea2d 100644 --- a/sentry_sdk/client.py +++ b/sentry_sdk/client.py @@ -80,11 +80,11 @@ def __init__(self, *args, **kwargs): def __getstate__(self): # type: () -> Any - return self.options + return {"options": self.options} def __setstate__(self, state): # type: (Any) -> None - self.options = state + self.options = state["options"] self._init_impl() def _init_impl(self): From 9342f412e0ef19c668f9596c174e01a3e348f59f Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Tue, 6 Aug 2019 18:41:03 +0200 Subject: [PATCH 3/3] fix: Encoding --- tests/test_transport.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_transport.py b/tests/test_transport.py index 6b6c0ecb50..3a1d8c88ae 100644 --- a/tests/test_transport.py +++ b/tests/test_transport.py @@ -1,3 +1,4 @@ +# coding: utf-8 import logging import pickle