diff --git a/scripts/runtox.sh b/scripts/runtox.sh index 07db62242b..e099f44efe 100755 --- a/scripts/runtox.sh +++ b/scripts/runtox.sh @@ -16,4 +16,12 @@ fi searchstring="$1" export TOX_PARALLEL_NO_SPINNER=1 -exec $TOXPATH -vv -p auto -e "$($TOXPATH -l | grep "$searchstring" | tr $'\n' ',')" -- "${@:2}" +ENV="$($TOXPATH -l | grep "$searchstring" | tr $'\n' ',')" + +# Run the common 2.7 suite without the -p flag, otherwise we hit an encoding +# issue in tox. +if [ "$ENV" = py2.7-common, ] || [ "$ENV" = py2.7-gevent, ]; then + exec $TOXPATH -vv -e "$ENV" -- "${@:2}" +else + exec $TOXPATH -vv -p auto -e "$ENV" -- "${@:2}" +fi diff --git a/sentry_sdk/integrations/socket.py b/sentry_sdk/integrations/socket.py index d3af70794b..7a4e358185 100644 --- a/sentry_sdk/integrations/socket.py +++ b/sentry_sdk/integrations/socket.py @@ -1,3 +1,5 @@ +from __future__ import absolute_import + import socket from sentry_sdk import Hub from sentry_sdk._types import MYPY diff --git a/tests/integrations/threading/test_threading.py b/tests/integrations/threading/test_threading.py index 56f7a36ea3..912717dddd 100644 --- a/tests/integrations/threading/test_threading.py +++ b/tests/integrations/threading/test_threading.py @@ -1,5 +1,5 @@ import gc - +import sys from threading import Thread import pytest @@ -121,6 +121,7 @@ def run(self): assert exception["type"] == "ZeroDivisionError" +@pytest.mark.skipif(sys.version_info < (3, 2), reason="no __qualname__ in older python") def test_wrapper_attributes(sentry_init): sentry_init(default_integrations=False, integrations=[ThreadingIntegration()]) @@ -141,3 +142,24 @@ def target(): assert Thread.run.__qualname__ == original_run.__qualname__ assert t.run.__name__ == "run" assert t.run.__qualname__ == original_run.__qualname__ + + +@pytest.mark.skipif( + sys.version_info > (2, 7), + reason="simpler test for py2.7 without py3 only __qualname__", +) +def test_wrapper_attributes_no_qualname(sentry_init): + sentry_init(default_integrations=False, integrations=[ThreadingIntegration()]) + + def target(): + assert t.run.__name__ == "run" + + t = Thread(target=target) + t.start() + t.join() + + assert Thread.start.__name__ == "start" + assert t.start.__name__ == "start" + + assert Thread.run.__name__ == "run" + assert t.run.__name__ == "run" diff --git a/tests/test_exceptiongroup.py b/tests/test_exceptiongroup.py index 47b3344dc6..8d4734762a 100644 --- a/tests/test_exceptiongroup.py +++ b/tests/test_exceptiongroup.py @@ -194,6 +194,7 @@ def test_exceptiongroup_simple(): assert frame["context_line"] == " raise ExceptionGroup(" +@minimum_python_311 def test_exception_chain_cause(): exception_chain_cause = ValueError("Exception with cause") exception_chain_cause.__context__ = TypeError("Exception in __context__") @@ -235,6 +236,7 @@ def test_exception_chain_cause(): assert exception_values == expected_exception_values +@minimum_python_311 def test_exception_chain_context(): exception_chain_context = ValueError("Exception with context") exception_chain_context.__context__ = TypeError("Exception in __context__") @@ -273,6 +275,7 @@ def test_exception_chain_context(): assert exception_values == expected_exception_values +@minimum_python_311 def test_simple_exception(): simple_excpetion = ValueError("A simple exception") diff --git a/tests/test_profiler.py b/tests/test_profiler.py index 11ece9821e..56d9514a85 100644 --- a/tests/test_profiler.py +++ b/tests/test_profiler.py @@ -81,6 +81,7 @@ def test_profiler_invalid_mode(mode, make_options, teardown_profiling): setup_profiler(make_options(mode)) +@requires_python_version(3, 3) @pytest.mark.parametrize( "mode", [ @@ -116,6 +117,7 @@ def test_profiler_setup_twice(make_options, teardown_profiling): assert not setup_profiler(make_options()) +@requires_python_version(3, 3) @pytest.mark.parametrize( "mode", [ @@ -173,6 +175,7 @@ def test_profiles_sample_rate( assert len(items["profile"]) == profile_count +@requires_python_version(3, 3) @pytest.mark.parametrize( "mode", [ @@ -234,6 +237,7 @@ def test_profiles_sampler( assert len(items["profile"]) == profile_count +@requires_python_version(3, 3) def test_minimum_unique_samples_required( sentry_init, capture_envelopes, @@ -260,6 +264,7 @@ def test_minimum_unique_samples_required( assert len(items["profile"]) == 0 +@requires_python_version(3, 3) def test_profile_captured( sentry_init, capture_envelopes, @@ -349,6 +354,7 @@ def static_method(): return inspect.currentframe() +@requires_python_version(3, 3) @pytest.mark.parametrize( ("frame", "frame_name"), [ @@ -428,6 +434,7 @@ def test_get_frame_name(frame, frame_name): assert get_frame_name(frame) == frame_name +@requires_python_version(3, 3) @pytest.mark.parametrize( ("get_frame", "function"), [ @@ -455,6 +462,7 @@ def test_extract_frame(get_frame, function): assert isinstance(extracted_frame["lineno"], int) +@requires_python_version(3, 3) @pytest.mark.parametrize( ("depth", "max_stack_depth", "actual_depth"), [ @@ -493,6 +501,7 @@ def test_extract_stack_with_max_depth(depth, max_stack_depth, actual_depth): assert frames[actual_depth]["function"] == "", actual_depth +@requires_python_version(3, 3) @pytest.mark.parametrize( ("frame", "depth"), [(get_frame(depth=1), len(inspect.stack()))], @@ -514,6 +523,7 @@ def test_extract_stack_with_cache(frame, depth): assert frame1 is frame2, i +@requires_python_version(3, 3) def test_get_current_thread_id_explicit_thread(): results = Queue(maxsize=1) @@ -535,6 +545,7 @@ def target2(): assert thread1.ident == results.get(timeout=1) +@requires_python_version(3, 3) @requires_gevent def test_get_current_thread_id_gevent_in_thread(): results = Queue(maxsize=1) @@ -550,6 +561,7 @@ def target(): assert thread.ident == results.get(timeout=1) +@requires_python_version(3, 3) def test_get_current_thread_id_running_thread(): results = Queue(maxsize=1) @@ -562,6 +574,7 @@ def target(): assert thread.ident == results.get(timeout=1) +@requires_python_version(3, 3) def test_get_current_thread_id_main_thread(): results = Queue(maxsize=1) @@ -626,6 +639,7 @@ def test_thread_scheduler_single_background_thread(scheduler_class): assert len(get_scheduler_threads(scheduler)) == 0 +@requires_python_version(3, 3) @pytest.mark.parametrize( ("scheduler_class",), [ @@ -684,6 +698,7 @@ def ensure_running(self): ] +@requires_python_version(3, 3) @pytest.mark.parametrize( ("samples", "expected"), [ diff --git a/tests/test_scrubber.py b/tests/test_scrubber.py index 5bb89ed654..4b2dfff450 100644 --- a/tests/test_scrubber.py +++ b/tests/test_scrubber.py @@ -105,11 +105,9 @@ def test_breadcrumb_extra_scrubbing(sentry_init, capture_events): "password": "[Filtered]", } - assert event["_meta"] == { - "extra": {"auth": {"": {"rem": [["!config", "s"]]}}}, - "breadcrumbs": { - "values": {"0": {"data": {"password": {"": {"rem": [["!config", "s"]]}}}}} - }, + assert event["_meta"]["extra"]["auth"] == {"": {"rem": [["!config", "s"]]}} + assert event["_meta"]["breadcrumbs"] == { + "values": {"0": {"data": {"password": {"": {"rem": [["!config", "s"]]}}}}} } @@ -124,8 +122,8 @@ def test_span_data_scrubbing(sentry_init, capture_events): (event,) = events assert event["spans"][0]["data"] == {"password": "[Filtered]", "datafoo": "databar"} - assert event["_meta"] == { - "spans": {"0": {"data": {"password": {"": {"rem": [["!config", "s"]]}}}}} + assert event["_meta"]["spans"] == { + "0": {"data": {"password": {"": {"rem": [["!config", "s"]]}}}} } diff --git a/tests/test_serializer.py b/tests/test_serializer.py index 5bb0579d5a..cc62c4663d 100644 --- a/tests/test_serializer.py +++ b/tests/test_serializer.py @@ -76,7 +76,9 @@ def test_bytes_serialization_repr(message_normalizer): def test_bytearray_serialization_decode(message_normalizer): binary = bytearray(b"abc123\x80\xf0\x9f\x8d\x95") result = message_normalizer(binary, should_repr_strings=False) - assert result == "abc123\ufffd\U0001f355" + # fmt: off + assert result == u"abc123\ufffd\U0001f355" + # fmt: on @pytest.mark.xfail(sys.version_info < (3,), reason="Known safe_repr bugs in Py2.7") diff --git a/tests/utils/test_general.py b/tests/utils/test_general.py index 570182ab0e..6f53de32c3 100644 --- a/tests/utils/test_general.py +++ b/tests/utils/test_general.py @@ -587,5 +587,7 @@ def test_strip_string(): assert stripped_text.value.count("a") == 1021 # + '...' is 1024 # If text has unicode characters, it counts bytes and not number of characters. - text_with_unicode_character = "éê" - assert strip_string(text_with_unicode_character, max_length=2).value == "é..." + # fmt: off + text_with_unicode_character = u"éê" + assert strip_string(text_with_unicode_character, max_length=2).value == u"é..." + # fmt: on diff --git a/tox.ini b/tox.ini index 62aa5250b4..040d6659df 100644 --- a/tox.ini +++ b/tox.ini @@ -472,8 +472,8 @@ setenv = requests: TESTPATH=tests/integrations/requests rq: TESTPATH=tests/integrations/rq sanic: TESTPATH=tests/integrations/sanic - starlette: TESTPATH=tests/integrations/starlette - starlite: TESTPATH=tests/integrations/starlite + starlette: TESTPATH=tests/integrations/starlette + starlite: TESTPATH=tests/integrations/starlite sqlalchemy: TESTPATH=tests/integrations/sqlalchemy tornado: TESTPATH=tests/integrations/tornado trytond: TESTPATH=tests/integrations/trytond @@ -530,7 +530,6 @@ commands = ; Running `py.test` as an executable suffers from an import error ; when loading tests in scenarios. In particular, django fails to ; load the settings from the test module. - {py2.7}: python -m pytest --ignore-glob='*py3.py' -rsx -s --durations=5 -vvv {env:TESTPATH} {posargs} {py3.5,py3.6,py3.7,py3.8,py3.9,py3.10,py3.11}: python -m pytest -rsx -s --durations=5 -vvv {env:TESTPATH} {posargs}