diff --git a/scripts/build_aws_lambda_layer.py b/scripts/build_aws_lambda_layer.py index af85b8b96d..94e41ac17d 100644 --- a/scripts/build_aws_lambda_layer.py +++ b/scripts/build_aws_lambda_layer.py @@ -49,7 +49,7 @@ def install_python_packages(self) -> None: sentry_python_sdk = os.path.join( DIST_PATH, - f"sentry_sdk-{SDK_VERSION}-py2.py3-none-any.whl", # this is generated by "make dist" that is called by "make aws-lambda-layer" + f"sentry_sdk-{SDK_VERSION}-py3-none-any.whl", # this is generated by "make dist" that is called by "make aws-lambda-layer" ) subprocess.run( [ diff --git a/sentry_sdk/_compat.py b/sentry_sdk/_compat.py index dcb590fcfa..3dd870f3e5 100644 --- a/sentry_sdk/_compat.py +++ b/sentry_sdk/_compat.py @@ -1,13 +1,5 @@ import sys -from typing import TYPE_CHECKING - -if TYPE_CHECKING: - from typing import Any - from typing import TypeVar - - T = TypeVar("T") - PY37 = sys.version_info[0] == 3 and sys.version_info[1] >= 7 PY38 = sys.version_info[0] == 3 and sys.version_info[1] >= 8 @@ -15,14 +7,6 @@ PY311 = sys.version_info[0] == 3 and sys.version_info[1] >= 11 -def with_metaclass(meta: "Any", *bases: "Any") -> "Any": - class MetaClass(type): - def __new__(metacls: "Any", name: "Any", this_bases: "Any", d: "Any") -> "Any": - return meta(name, bases, d) - - return type.__new__(MetaClass, "temporary_class", (), {}) - - def check_uwsgi_thread_support() -> bool: # We check two things here: # diff --git a/sentry_sdk/client.py b/sentry_sdk/client.py index 9f795d2489..94245a3d35 100644 --- a/sentry_sdk/client.py +++ b/sentry_sdk/client.py @@ -167,14 +167,6 @@ def _get_options(*args: "Optional[str]", **kwargs: "Any") -> "Dict[str, Any]": return rv -try: - # Python 3.6+ - module_not_found_error = ModuleNotFoundError -except Exception: - # Older Python versions - module_not_found_error = ImportError # type: ignore - - class BaseClient: """ .. versionadded:: 2.0.0 @@ -289,7 +281,7 @@ class _Client(BaseClient): """ def __init__(self, *args: "Any", **kwargs: "Any") -> None: - super(_Client, self).__init__(options=get_options(*args, **kwargs)) + super().__init__(options=get_options(*args, **kwargs)) self._init_impl() def __getstate__(self) -> "Any": @@ -318,7 +310,7 @@ def _setup_instrumentation( function_obj = getattr(module_obj, function_name) setattr(module_obj, function_name, trace(function_obj)) logger.debug("Enabled tracing for %s", function_qualname) - except module_not_found_error: + except ModuleNotFoundError: try: # Try to import a class # ex: "mymodule.submodule.MyClassName.member_function" diff --git a/sentry_sdk/hub.py b/sentry_sdk/hub.py index 0e5d7df9f9..5dc60b3a95 100644 --- a/sentry_sdk/hub.py +++ b/sentry_sdk/hub.py @@ -8,7 +8,6 @@ get_global_scope, get_isolation_scope, ) -from sentry_sdk._compat import with_metaclass from sentry_sdk.client import Client from sentry_sdk.consts import INSTRUMENTER from sentry_sdk.scope import _ScopeManager @@ -109,7 +108,7 @@ def main(cls) -> "Hub": return GLOBAL_HUB -class Hub(with_metaclass(HubMeta)): # type: ignore +class Hub(metaclass=HubMeta): """ .. deprecated:: 2.0.0 The Hub is deprecated. Its functionality will be merged into :py:class:`sentry_sdk.scope.Scope`. diff --git a/sentry_sdk/integrations/django/middleware.py b/sentry_sdk/integrations/django/middleware.py index 94c0decf87..cec993a69a 100644 --- a/sentry_sdk/integrations/django/middleware.py +++ b/sentry_sdk/integrations/django/middleware.py @@ -103,7 +103,6 @@ def sentry_wrapped_method(*args: "Any", **kwargs: "Any") -> "Any": return old_method(*args, **kwargs) try: - # fails for __call__ of function on Python 2 (see py2.7-django-1.11) sentry_wrapped_method = wraps(old_method)(sentry_wrapped_method) # Necessary for Django 3.1 diff --git a/sentry_sdk/integrations/django/signals_handlers.py b/sentry_sdk/integrations/django/signals_handlers.py index 0c834ff8c6..0db42ab7bd 100644 --- a/sentry_sdk/integrations/django/signals_handlers.py +++ b/sentry_sdk/integrations/django/signals_handlers.py @@ -18,8 +18,6 @@ def _get_receiver_name(receiver: "Callable[..., Any]") -> str: if hasattr(receiver, "__qualname__"): name = receiver.__qualname__ - elif hasattr(receiver, "__name__"): # Python 2.7 has no __qualname__ - name = receiver.__name__ elif hasattr( receiver, "func" ): # certain functions (like partials) dont have a name diff --git a/sentry_sdk/integrations/django/views.py b/sentry_sdk/integrations/django/views.py index c9e370029e..d55df180c9 100644 --- a/sentry_sdk/integrations/django/views.py +++ b/sentry_sdk/integrations/django/views.py @@ -9,10 +9,7 @@ from typing import Any -try: - from asyncio import iscoroutinefunction -except ImportError: - iscoroutinefunction = None # type: ignore +from asyncio import iscoroutinefunction try: @@ -48,10 +45,8 @@ def sentry_patched_make_view_atomic( integration = sentry_sdk.get_client().get_integration(DjangoIntegration) if integration is not None: - is_async_view = ( - iscoroutinefunction is not None - and wrap_async_view is not None - and iscoroutinefunction(callback) + is_async_view = wrap_async_view is not None and iscoroutinefunction( + callback ) if is_async_view: sentry_wrapped_callback = wrap_async_view(callback) diff --git a/sentry_sdk/traces.py b/sentry_sdk/traces.py index f44ef71f5b..93e933946c 100644 --- a/sentry_sdk/traces.py +++ b/sentry_sdk/traces.py @@ -278,12 +278,9 @@ def __init__( self._start_timestamp = datetime.now(timezone.utc) self._timestamp: "Optional[datetime]" = None - try: - # profiling depends on this value and requires that - # it is measured in nanoseconds - self._start_timestamp_monotonic_ns = nanosecond_time() - except AttributeError: - pass + # profiling depends on this value and requires that + # it is measured in nanoseconds + self._start_timestamp_monotonic_ns = nanosecond_time() self._span_id: "Optional[str]" = None diff --git a/sentry_sdk/tracing.py b/sentry_sdk/tracing.py index 7f2baba0c9..27231985c7 100644 --- a/sentry_sdk/tracing.py +++ b/sentry_sdk/tracing.py @@ -327,12 +327,9 @@ def __init__( elif isinstance(start_timestamp, float): start_timestamp = datetime.fromtimestamp(start_timestamp, timezone.utc) self.start_timestamp = start_timestamp - try: - # profiling depends on this value and requires that - # it is measured in nanoseconds - self._start_timestamp_monotonic_ns = nanosecond_time() - except AttributeError: - pass + # profiling depends on this value and requires that + # it is measured in nanoseconds + self._start_timestamp_monotonic_ns = nanosecond_time() #: End timestamp of span self.timestamp: "Optional[datetime]" = None @@ -661,18 +658,15 @@ def finish( # This span is already finished, ignore. return None - try: - if end_timestamp: - if isinstance(end_timestamp, float): - end_timestamp = datetime.fromtimestamp(end_timestamp, timezone.utc) - self.timestamp = end_timestamp - else: - elapsed = nanosecond_time() - self._start_timestamp_monotonic_ns - self.timestamp = self.start_timestamp + timedelta( - microseconds=elapsed / 1000 - ) - except AttributeError: - self.timestamp = datetime.now(timezone.utc) + if end_timestamp: + if isinstance(end_timestamp, float): + end_timestamp = datetime.fromtimestamp(end_timestamp, timezone.utc) + self.timestamp = end_timestamp + else: + elapsed = nanosecond_time() - self._start_timestamp_monotonic_ns + self.timestamp = self.start_timestamp + timedelta( + microseconds=elapsed / 1000 + ) scope = scope or sentry_sdk.get_current_scope() diff --git a/sentry_sdk/utils.py b/sentry_sdk/utils.py index be238e5142..962c1218be 100644 --- a/sentry_sdk/utils.py +++ b/sentry_sdk/utils.py @@ -159,7 +159,7 @@ def get_git_revision() -> "Optional[str]": .strip() .decode("utf-8") ) - except (OSError, IOError, FileNotFoundError): + except OSError: return None return revision @@ -492,7 +492,7 @@ def get_lines_from_file( if loader is not None and hasattr(loader, "get_source"): try: source_str: "Optional[str]" = loader.get_source(module) - except (ImportError, IOError): + except (ImportError, OSError): source_str = None if source_str is not None: source = source_str.splitlines() @@ -500,7 +500,7 @@ def get_lines_from_file( if source is None: try: source = linecache.getlines(filename) - except (OSError, IOError): + except OSError: return [], None, [] if not source: @@ -1472,16 +1472,6 @@ def qualname_from_function(func: "Callable[..., Any]") -> "Optional[str]": """Return the qualified name of func. Works with regular function, lambda, partial and partialmethod.""" func_qualname: "Optional[str]" = None - # Python 2 - try: - return "%s.%s.%s" % ( - func.im_class.__module__, # type: ignore - func.im_class.__name__, # type: ignore - func.__name__, - ) - except Exception: - pass - prefix, suffix = "", "" if isinstance(func, partial) and hasattr(func.func, "__name__"): @@ -1499,10 +1489,7 @@ def qualname_from_function(func: "Callable[..., Any]") -> "Optional[str]": if hasattr(func, "__qualname__"): func_qualname = func.__qualname__ - elif hasattr(func, "__name__"): # Python 2.7 has no __qualname__ - func_qualname = func.__name__ - # Python 3: methods, functions, classes if func_qualname is not None: if hasattr(func, "__module__") and isinstance(func.__module__, str): func_qualname = func.__module__ + "." + func_qualname diff --git a/setup.py b/setup.py index 3942ee630e..5392d1ca90 100644 --- a/setup.py +++ b/setup.py @@ -113,5 +113,4 @@ def get_file_text(file_name): "Programming Language :: Python :: 3.14", "Topic :: Software Development :: Libraries :: Python Modules", ], - options={"bdist_wheel": {"universal": "1"}}, ) diff --git a/tests/conftest.py b/tests/conftest.py index 4e4943ba85..30dd11586e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -527,8 +527,6 @@ def __eq__(self, test_string): if not isinstance(test_string, self.valid_types): return False - # this is safe even in py2 because as of 2.6, `bytes` exists in py2 - # as an alias for `str` if isinstance(test_string, bytes): test_string = test_string.decode() @@ -548,9 +546,8 @@ def _safe_is_equal(x, y): Compares two values, preferring to use the first's __eq__ method if it exists and is implemented. - Accounts for py2/py3 differences (like ints in py2 not having a __eq__ - method), as well as the incomparability of certain types exposed by using - raw __eq__ () rather than ==. + Accounts for the incomparability of certain types exposed by using raw + __eq__ () rather than ==. """ # Prefer using __eq__ directly to ensure that examples like