From 149681fd7bd966fdad508e6c1d38bd8b8d6e8b67 Mon Sep 17 00:00:00 2001 From: Georg Grab Date: Tue, 24 Mar 2026 12:25:37 +0100 Subject: [PATCH 1/2] feat: `extension_entry` event that only fires once per instantiation --- .../telemetry/core/__init__.py | 2 + .../telemetry/core/decorators.py | 6 +- .../telemetry/core/events.py | 18 +++ tests/telemetry/core/test_decorators.py | 116 ++++++++++++++++++ tests/telemetry/core/test_events.py | 46 +++++++ uv.lock | 20 +-- 6 files changed, 190 insertions(+), 18 deletions(-) diff --git a/src/tabpfn_common_utils/telemetry/core/__init__.py b/src/tabpfn_common_utils/telemetry/core/__init__.py index 46c4697..e650a7c 100644 --- a/src/tabpfn_common_utils/telemetry/core/__init__.py +++ b/src/tabpfn_common_utils/telemetry/core/__init__.py @@ -4,6 +4,7 @@ from .events import ( BaseTelemetryEvent, + ExtensionEntryEvent, ModelLoadEvent, PingEvent, DatasetEvent, @@ -24,6 +25,7 @@ # Public exports __all__ = [ "BaseTelemetryEvent", + "ExtensionEntryEvent", "PingEvent", "DatasetEvent", "ModelLoadEvent", diff --git a/src/tabpfn_common_utils/telemetry/core/decorators.py b/src/tabpfn_common_utils/telemetry/core/decorators.py index e5b92d7..8876224 100644 --- a/src/tabpfn_common_utils/telemetry/core/decorators.py +++ b/src/tabpfn_common_utils/telemetry/core/decorators.py @@ -15,7 +15,7 @@ from functools import wraps from typing import Any, Callable, Dict, Literal, Optional, Tuple, Union -from .events import FitEvent, PredictEvent +from .events import ExtensionEntryEvent, FitEvent, PredictEvent from .service import capture_event from tabpfn_common_utils.utils import shape_of @@ -214,6 +214,10 @@ def wrapped(*args, **kwargs): if _get_context_var("tabpfn_current_extension").get() is not None: return fn(*args, **kwargs) with _extension_context(extension_name): + try: + capture_event(ExtensionEntryEvent(extension_name=extension_name)) + except Exception: # noqa: BLE001 + logger.debug(f"Failed to capture extension entry event for {extension_name}") return fn(*args, **kwargs) setattr(wrapped, _MARKER_ATTR, extension_name) diff --git a/src/tabpfn_common_utils/telemetry/core/events.py b/src/tabpfn_common_utils/telemetry/core/events.py index b2c83d4..f6e9e49 100644 --- a/src/tabpfn_common_utils/telemetry/core/events.py +++ b/src/tabpfn_common_utils/telemetry/core/events.py @@ -499,3 +499,21 @@ class PredictEvent(ModelCallEvent): @property def name(self) -> str: return "predict_called" + + +@dataclass +class ExtensionEntryEvent(BaseTelemetryEvent): + """ + Event emitted once per user-facing extension entry point call. + + Unlike FitEvent/PredictEvent which fire per downstream model call, + this fires exactly once when the outermost @set_extension decorator + is entered, giving an unbiased count of extension usage. + """ + + # Name of the extension that was entered + extension_name: str = "" + + @property + def name(self) -> str: + return "extension_entry" diff --git a/tests/telemetry/core/test_decorators.py b/tests/telemetry/core/test_decorators.py index eca475c..8feb6b8 100644 --- a/tests/telemetry/core/test_decorators.py +++ b/tests/telemetry/core/test_decorators.py @@ -2,6 +2,8 @@ from __future__ import annotations +from unittest.mock import patch + import pytest from tabpfn_common_utils.telemetry.core.decorators import ( @@ -10,6 +12,7 @@ get_current_extension, _extension_context, ) +from tabpfn_common_utils.telemetry.core.events import ExtensionEntryEvent class TestSetExtensionDecorator: @@ -268,3 +271,116 @@ def test_round_dims_special_cases(self) -> None: # Test some intermediate values assert _round_dims((1234, 67)) == (1200, 75) # 1234 -> 1200, 67 -> 75 assert _round_dims((876, 89)) == (1000, 100) # 876 -> 1000, 89 -> 100 + + +class TestExtensionEntryEventEmission: + """Test that set_extension emits ExtensionEntryEvent correctly.""" + + @patch("tabpfn_common_utils.telemetry.core.decorators.capture_event") + def test_single_call_emits_one_event(self, mock_capture): + """A single decorated function call emits exactly one ExtensionEntryEvent.""" + + @set_extension("test_ext") + def my_func(): + return 42 + + result = my_func() + + assert result == 42 + assert mock_capture.call_count == 1 + event = mock_capture.call_args[0][0] + assert isinstance(event, ExtensionEntryEvent) + assert event.extension_name == "test_ext" + + @patch("tabpfn_common_utils.telemetry.core.decorators.capture_event") + def test_nested_calls_emit_one_event(self, mock_capture): + """Nested decorated calls emit only one event for the outermost extension.""" + + @set_extension("outer") + def outer(): + return inner() + + @set_extension("inner") + def inner(): + return get_current_extension() + + result = outer() + + # Inner should see the outer context + assert result == "outer" + # Only one event emitted (for the outer entry) + assert mock_capture.call_count == 1 + event = mock_capture.call_args[0][0] + assert isinstance(event, ExtensionEntryEvent) + assert event.extension_name == "outer" + + @patch("tabpfn_common_utils.telemetry.core.decorators.capture_event") + def test_sequential_calls_emit_separate_events(self, mock_capture): + """Two sequential (non-nested) calls emit two separate events.""" + + @set_extension("ext_a") + def func_a(): + return "a" + + @set_extension("ext_b") + def func_b(): + return "b" + + func_a() + func_b() + + assert mock_capture.call_count == 2 + assert mock_capture.call_args_list[0][0][0].extension_name == "ext_a" + assert mock_capture.call_args_list[1][0][0].extension_name == "ext_b" + + @patch("tabpfn_common_utils.telemetry.core.decorators.capture_event") + def test_class_decorator_emits_one_event_per_public_method_call(self, mock_capture): + """A class decorated with set_extension emits one event per public method call. + __init__ is private (starts with _) so it's not wrapped by default.""" + + @set_extension("cls_ext") + class MyClass: + def do_work(self): + return "done" + + obj = MyClass() + obj.do_work() + + # Only do_work is public; __init__ starts with _ so not wrapped + assert mock_capture.call_count == 1 + event = mock_capture.call_args[0][0] + assert isinstance(event, ExtensionEntryEvent) + assert event.extension_name == "cls_ext" + + @patch("tabpfn_common_utils.telemetry.core.decorators.capture_event") + def test_class_nested_method_calls_emit_one_event(self, mock_capture): + """When a class method calls another decorated function, only the outer emits.""" + + @set_extension("inner_ext") + def helper(): + return "helped" + + @set_extension("cls_ext") + class MyClass: + def do_work(self): + return helper() + + obj = MyClass() + result = obj.do_work() + + assert result == "helped" + # do_work emits one event, helper() is nested so no event + assert mock_capture.call_count == 1 + assert mock_capture.call_args[0][0].extension_name == "cls_ext" + + @patch("tabpfn_common_utils.telemetry.core.decorators.capture_event") + def test_event_not_emitted_on_exception(self, mock_capture): + """capture_event failure doesn't prevent the wrapped function from running.""" + mock_capture.side_effect = RuntimeError("PostHog down") + + @set_extension("fail_ext") + def my_func(): + return "still works" + + result = my_func() + assert result == "still works" diff --git a/tests/telemetry/core/test_events.py b/tests/telemetry/core/test_events.py index 09d4e32..9c25276 100644 --- a/tests/telemetry/core/test_events.py +++ b/tests/telemetry/core/test_events.py @@ -5,6 +5,7 @@ from tabpfn_common_utils.telemetry.core.events import ( BaseTelemetryEvent, DatasetEvent, + ExtensionEntryEvent, FitEvent, ModelLoadEvent, PingEvent, @@ -422,6 +423,51 @@ def test_model_load_event_properties_method(self): assert "install_id" in props +class TestExtensionEntryEvent: + """Test ExtensionEntryEvent class""" + + def test_extension_entry_event_initialization(self): + """Test ExtensionEntryEvent initialization with extension name""" + event = ExtensionEntryEvent(extension_name="post_hoc_ensembles") + + assert event.extension_name == "post_hoc_ensembles" + assert event.name == "extension_entry" + + def test_extension_entry_event_default_extension_name(self): + """Test ExtensionEntryEvent default extension_name is empty string""" + event = ExtensionEntryEvent() + + assert event.extension_name == "" + assert event.name == "extension_entry" + + def test_extension_entry_event_inherits_base_properties(self): + """Test that ExtensionEntryEvent inherits base telemetry properties""" + event = ExtensionEntryEvent(extension_name="rf_pfn") + + assert isinstance(event.python_version, str) + assert isinstance(event.tabpfn_version, str) + assert isinstance(event.timestamp, datetime) + assert event.source == "sdk" + + def test_extension_entry_event_properties_method(self): + """Test ExtensionEntryEvent properties method""" + event = ExtensionEntryEvent(extension_name="interpretability") + + props = event.properties + + assert "name" not in props + assert props["extension_name"] == "interpretability" + assert "python_version" in props + assert "tabpfn_version" in props + + def test_extension_entry_event_with_colon_separated_name(self): + """Test ExtensionEntryEvent with sub-extension names like unsupervised:impute""" + event = ExtensionEntryEvent(extension_name="unsupervised:impute") + + assert event.extension_name == "unsupervised:impute" + assert event.name == "extension_entry" + + class TestEventIntegration: """Integration tests for all event types""" diff --git a/uv.lock b/uv.lock index fb97f85..f3c23d3 100644 --- a/uv.lock +++ b/uv.lock @@ -62,50 +62,36 @@ sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8 wheels = [ { url = "https://files.pythonhosted.org/packages/50/bd/b1a6362b80628111e6653c961f987faa55262b4002fcec42308cad1db680/cffi-2.0.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c", size = 208811, upload-time = "2025-09-08T23:22:12.267Z" }, { url = "https://files.pythonhosted.org/packages/4f/27/6933a8b2562d7bd1fb595074cf99cc81fc3789f6a6c05cdabb46284a3188/cffi-2.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb", size = 216402, upload-time = "2025-09-08T23:22:13.455Z" }, - { url = "https://files.pythonhosted.org/packages/05/eb/b86f2a2645b62adcfff53b0dd97e8dfafb5c8aa864bd0d9a2c2049a0d551/cffi-2.0.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:5eda85d6d1879e692d546a078b44251cdd08dd1cfb98dfb77b670c97cee49ea0", size = 203217, upload-time = "2025-09-08T23:22:14.596Z" }, - { url = "https://files.pythonhosted.org/packages/9f/e0/6cbe77a53acf5acc7c08cc186c9928864bd7c005f9efd0d126884858a5fe/cffi-2.0.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9332088d75dc3241c702d852d4671613136d90fa6881da7d770a483fd05248b4", size = 203079, upload-time = "2025-09-08T23:22:15.769Z" }, { url = "https://files.pythonhosted.org/packages/98/29/9b366e70e243eb3d14a5cb488dfd3a0b6b2f1fb001a203f653b93ccfac88/cffi-2.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453", size = 216475, upload-time = "2025-09-08T23:22:17.427Z" }, { url = "https://files.pythonhosted.org/packages/21/7a/13b24e70d2f90a322f2900c5d8e1f14fa7e2a6b3332b7309ba7b2ba51a5a/cffi-2.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495", size = 218829, upload-time = "2025-09-08T23:22:19.069Z" }, { url = "https://files.pythonhosted.org/packages/60/99/c9dc110974c59cc981b1f5b66e1d8af8af764e00f0293266824d9c4254bc/cffi-2.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5", size = 211211, upload-time = "2025-09-08T23:22:20.588Z" }, { url = "https://files.pythonhosted.org/packages/49/72/ff2d12dbf21aca1b32a40ed792ee6b40f6dc3a9cf1644bd7ef6e95e0ac5e/cffi-2.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb", size = 218036, upload-time = "2025-09-08T23:22:22.143Z" }, { url = "https://files.pythonhosted.org/packages/b1/b7/1200d354378ef52ec227395d95c2576330fd22a869f7a70e88e1447eb234/cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92", size = 209613, upload-time = "2025-09-08T23:22:29.475Z" }, { url = "https://files.pythonhosted.org/packages/b8/56/6033f5e86e8cc9bb629f0077ba71679508bdf54a9a5e112a3c0b91870332/cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93", size = 216476, upload-time = "2025-09-08T23:22:31.063Z" }, - { url = "https://files.pythonhosted.org/packages/dc/7f/55fecd70f7ece178db2f26128ec41430d8720f2d12ca97bf8f0a628207d5/cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5", size = 203374, upload-time = "2025-09-08T23:22:32.507Z" }, - { url = "https://files.pythonhosted.org/packages/84/ef/a7b77c8bdc0f77adc3b46888f1ad54be8f3b7821697a7b89126e829e676a/cffi-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664", size = 202597, upload-time = "2025-09-08T23:22:34.132Z" }, { url = "https://files.pythonhosted.org/packages/d7/91/500d892b2bf36529a75b77958edfcd5ad8e2ce4064ce2ecfeab2125d72d1/cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26", size = 215574, upload-time = "2025-09-08T23:22:35.443Z" }, { url = "https://files.pythonhosted.org/packages/44/64/58f6255b62b101093d5df22dcb752596066c7e89dd725e0afaed242a61be/cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9", size = 218971, upload-time = "2025-09-08T23:22:36.805Z" }, { url = "https://files.pythonhosted.org/packages/ab/49/fa72cebe2fd8a55fbe14956f9970fe8eb1ac59e5df042f603ef7c8ba0adc/cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414", size = 211972, upload-time = "2025-09-08T23:22:38.436Z" }, { url = "https://files.pythonhosted.org/packages/0b/28/dd0967a76aab36731b6ebfe64dec4e981aff7e0608f60c2d46b46982607d/cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743", size = 217078, upload-time = "2025-09-08T23:22:39.776Z" }, { url = "https://files.pythonhosted.org/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529, upload-time = "2025-09-08T23:22:47.349Z" }, { url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097, upload-time = "2025-09-08T23:22:48.677Z" }, - { url = "https://files.pythonhosted.org/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", size = 207983, upload-time = "2025-09-08T23:22:50.06Z" }, - { url = "https://files.pythonhosted.org/packages/3a/c8/15cb9ada8895957ea171c62dc78ff3e99159ee7adb13c0123c001a2546c1/cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037", size = 206519, upload-time = "2025-09-08T23:22:51.364Z" }, { url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572, upload-time = "2025-09-08T23:22:52.902Z" }, { url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963, upload-time = "2025-09-08T23:22:54.518Z" }, { url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361, upload-time = "2025-09-08T23:22:55.867Z" }, { url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" }, { url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" }, - { url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" }, - { url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" }, { url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" }, { url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" }, { url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" }, { url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" }, - { url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" }, - { url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" }, { url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" }, { url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" }, { url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" }, { url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" }, - { url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" }, - { url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" }, { url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" }, { url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" }, { url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" }, { url = "https://files.pythonhosted.org/packages/9b/13/c92e36358fbcc39cf0962e83223c9522154ee8630e1df7c0b3a39a8124e2/cffi-2.0.0-cp39-cp39-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:4647afc2f90d1ddd33441e5b0e85b16b12ddec4fca55f0d9671fef036ecca27c", size = 208813, upload-time = "2025-09-08T23:23:51.263Z" }, { url = "https://files.pythonhosted.org/packages/15/12/a7a79bd0df4c3bff744b2d7e52cc1b68d5e7e427b384252c42366dc1ecbc/cffi-2.0.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3f4d46d8b35698056ec29bca21546e1551a205058ae1a181d871e278b0b28165", size = 216498, upload-time = "2025-09-08T23:23:52.494Z" }, - { url = "https://files.pythonhosted.org/packages/a3/ad/5c51c1c7600bdd7ed9a24a203ec255dccdd0ebf4527f7b922a0bde2fb6ed/cffi-2.0.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:e6e73b9e02893c764e7e8d5bb5ce277f1a009cd5243f8228f75f842bf937c534", size = 203243, upload-time = "2025-09-08T23:23:53.836Z" }, - { url = "https://files.pythonhosted.org/packages/32/f2/81b63e288295928739d715d00952c8c6034cb6c6a516b17d37e0c8be5600/cffi-2.0.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:cb527a79772e5ef98fb1d700678fe031e353e765d1ca2d409c92263c6d43e09f", size = 203158, upload-time = "2025-09-08T23:23:55.169Z" }, { url = "https://files.pythonhosted.org/packages/1f/74/cc4096ce66f5939042ae094e2e96f53426a979864aa1f96a621ad128be27/cffi-2.0.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:61d028e90346df14fedc3d1e5441df818d095f3b87d286825dfcbd6459b7ef63", size = 216548, upload-time = "2025-09-08T23:23:56.506Z" }, { url = "https://files.pythonhosted.org/packages/e8/be/f6424d1dc46b1091ffcc8964fa7c0ab0cd36839dd2761b49c90481a6ba1b/cffi-2.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0f6084a0ea23d05d20c3edcda20c3d006f9b6f3fefeac38f59262e10cef47ee2", size = 218897, upload-time = "2025-09-08T23:23:57.825Z" }, { url = "https://files.pythonhosted.org/packages/f7/e0/dda537c2309817edf60109e39265f24f24aa7f050767e22c98c53fe7f48b/cffi-2.0.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1cd13c99ce269b3ed80b417dcd591415d3372bcac067009b6e0f59c7d4015e65", size = 211249, upload-time = "2025-09-08T23:23:59.139Z" }, @@ -1272,9 +1258,9 @@ requires-dist = [ { name = "hatchling", marker = "extra == 'build'", specifier = ">=1.25" }, { name = "numpy", specifier = ">=1.21.6" }, { name = "nvidia-ml-py", specifier = ">=13.590.48" }, - { name = "pandas", specifier = ">=1.4.0,<3" }, + { name = "pandas", specifier = ">=1.4.0" }, { name = "platformdirs", specifier = ">=4" }, - { name = "posthog", specifier = "~=6.7" }, + { name = "posthog", specifier = ">=6.7" }, { name = "pyright", marker = "extra == 'dev'", specifier = ">=1.1.399" }, { name = "pytest", marker = "extra == 'dev'", specifier = ">=8.3" }, { name = "pytest-cov", marker = "extra == 'dev'", specifier = ">=5" }, @@ -1283,7 +1269,7 @@ requires-dist = [ { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.9" }, { name = "scikit-learn", specifier = ">=1.2.0" }, { name = "twine", marker = "extra == 'build'", specifier = ">=5.0.0" }, - { name = "typing-extensions", specifier = ">=4.12,<5" }, + { name = "typing-extensions", specifier = ">=4.12" }, ] provides-extras = ["build", "dev", "telemetry-interactive"] From fb600a6db1462cf777c40b9a517f67a0cb7f4ea3 Mon Sep 17 00:00:00 2001 From: Georg Grab Date: Thu, 26 Mar 2026 10:08:46 +0100 Subject: [PATCH 2/2] chore: drop unnecessary except block --- src/tabpfn_common_utils/telemetry/core/decorators.py | 5 +---- tests/telemetry/core/test_decorators.py | 7 +++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/tabpfn_common_utils/telemetry/core/decorators.py b/src/tabpfn_common_utils/telemetry/core/decorators.py index 8876224..94e64df 100644 --- a/src/tabpfn_common_utils/telemetry/core/decorators.py +++ b/src/tabpfn_common_utils/telemetry/core/decorators.py @@ -214,10 +214,7 @@ def wrapped(*args, **kwargs): if _get_context_var("tabpfn_current_extension").get() is not None: return fn(*args, **kwargs) with _extension_context(extension_name): - try: - capture_event(ExtensionEntryEvent(extension_name=extension_name)) - except Exception: # noqa: BLE001 - logger.debug(f"Failed to capture extension entry event for {extension_name}") + capture_event(ExtensionEntryEvent(extension_name=extension_name)) return fn(*args, **kwargs) setattr(wrapped, _MARKER_ATTR, extension_name) diff --git a/tests/telemetry/core/test_decorators.py b/tests/telemetry/core/test_decorators.py index 8feb6b8..dd2dca1 100644 --- a/tests/telemetry/core/test_decorators.py +++ b/tests/telemetry/core/test_decorators.py @@ -373,10 +373,9 @@ def do_work(self): assert mock_capture.call_count == 1 assert mock_capture.call_args[0][0].extension_name == "cls_ext" - @patch("tabpfn_common_utils.telemetry.core.decorators.capture_event") - def test_event_not_emitted_on_exception(self, mock_capture): - """capture_event failure doesn't prevent the wrapped function from running.""" - mock_capture.side_effect = RuntimeError("PostHog down") + @patch("posthog.Posthog.capture", side_effect=RuntimeError("PostHog down")) + def test_capture_event_resilient_to_posthog_failure(self, _mock_posthog): + """PostHog client failure doesn't prevent the wrapped function from running.""" @set_extension("fail_ext") def my_func():