diff --git a/.sampo/changesets/float-timeout-annotations.md b/.sampo/changesets/float-timeout-annotations.md new file mode 100644 index 000000000..fd4222710 --- /dev/null +++ b/.sampo/changesets/float-timeout-annotations.md @@ -0,0 +1,5 @@ +--- +pypi/posthog: patch +--- + +Annotate `timeout` and `feature_flags_request_timeout_seconds` as `float` on `Client`, `AsyncClient`, `Consumer` and the request helpers, so type checkers accept fractional timeouts such as `timeout=2.5`. The values were already passed straight to `requests` and `httpx`, which take floats, so runtime behaviour is unchanged. diff --git a/posthog/__init__.py b/posthog/__init__.py index 66fb9ea19..2e870403c 100644 --- a/posthog/__init__.py +++ b/posthog/__init__.py @@ -408,7 +408,7 @@ def get_tags() -> Dict[str, Any]: poll_interval = 30 # type: int disable_geoip = True # type: bool is_server = True # type: bool -feature_flags_request_timeout_seconds = 3 # type: int +feature_flags_request_timeout_seconds = 3 # type: float feature_flags_request_max_retries = 1 # type: int super_properties = None # type: Optional[Dict] metrics = None # type: Optional[Dict] diff --git a/posthog/_async_consumer.py b/posthog/_async_consumer.py index 04eeb082b..5bdfd33f1 100644 --- a/posthog/_async_consumer.py +++ b/posthog/_async_consumer.py @@ -70,7 +70,7 @@ def __init__( flush_interval: float, gzip: bool, retries: int, - timeout: int, + timeout: float, historical_migration: bool, capture_mode: CaptureMode, capture_compression: CaptureCompression, diff --git a/posthog/_async_request.py b/posthog/_async_request.py index ae750de9a..00120971a 100644 --- a/posthog/_async_request.py +++ b/posthog/_async_request.py @@ -132,7 +132,7 @@ async def async_flags( api_key: str, host: Optional[str], *, - timeout: int, + timeout: float, max_retries: int, client: Optional[Any] = None, **request_data: Any, @@ -175,7 +175,7 @@ async def async_remote_config( host: Optional[str], key: str, *, - timeout: int, + timeout: float, client: Optional[Any] = None, ) -> Any: """Fetch and decrypt one remote-config payload.""" @@ -203,7 +203,7 @@ async def async_batch_post( batch: list[dict[str, Any]], path: str, gzip: bool = False, - timeout: int = 15, + timeout: float = 15, historical_migration: bool = False, client: Optional[Any] = None, ) -> None: @@ -260,7 +260,7 @@ async def async_send_v1_batch( batch: list[dict[str, Any]], *, compression: CaptureCompression, - timeout: int, + timeout: float, max_retries: int, historical_migration: bool, ) -> None: diff --git a/posthog/async_client.py b/posthog/async_client.py index 3f429e81a..186bff727 100644 --- a/posthog/async_client.py +++ b/posthog/async_client.py @@ -106,7 +106,7 @@ def __init__( flush_interval: float = 5.0, gzip: bool = False, max_retries: int = 3, - timeout: int = 15, + timeout: float = 15, thread: int = 1, disabled: bool = False, disable_geoip: bool = True, @@ -127,7 +127,7 @@ def __init__( capture_trace_context: bool = False, secret_key: Optional[str] = None, personal_api_key: Optional[str] = None, - feature_flags_request_timeout_seconds: int = 3, + feature_flags_request_timeout_seconds: float = 3, feature_flags_request_max_retries: int = 1, ) -> None: if flush_at <= 0: diff --git a/posthog/capture_v1.py b/posthog/capture_v1.py index 478175484..1ae31ce71 100644 --- a/posthog/capture_v1.py +++ b/posthog/capture_v1.py @@ -347,7 +347,7 @@ def _post_v1( attempt: int, request_id: str, compression: CaptureCompression = CaptureCompression.NONE, - timeout: int = 15, + timeout: float = 15, sdk_info: str = USER_AGENT, session: Optional["requests.Session"] = None, ) -> "requests.Response": @@ -468,7 +468,7 @@ def _send_v1_batch( batch: list[dict], *, compression: CaptureCompression = CaptureCompression.NONE, - timeout: int = 15, + timeout: float = 15, max_retries: int = 3, historical_migration: bool = False, sdk_info: str = USER_AGENT, diff --git a/posthog/client.py b/posthog/client.py index 27fee5428..5aa552dc3 100644 --- a/posthog/client.py +++ b/posthog/client.py @@ -682,7 +682,7 @@ def __init__( gzip=False, max_retries=3, sync_mode=False, - timeout=15, + timeout: float = 15, thread=1, poll_interval=30, personal_api_key=None, @@ -690,7 +690,7 @@ def __init__( disable_geoip=True, is_server=True, historical_migration=False, - feature_flags_request_timeout_seconds=3, + feature_flags_request_timeout_seconds: float = 3, feature_flags_request_max_retries=1, super_properties=None, enable_exception_autocapture=False, diff --git a/posthog/consumer.py b/posthog/consumer.py index c604b9756..0190dcf01 100644 --- a/posthog/consumer.py +++ b/posthog/consumer.py @@ -111,7 +111,7 @@ def __init__( flush_interval=5.0, gzip=False, retries=10, - timeout=15, + timeout: float = 15, historical_migration=False, endpoint=EVENTS_ENDPOINT, max_msg_size=MAX_MSG_SIZE, diff --git a/posthog/request.py b/posthog/request.py index 1c2456a77..9b7b1b1b2 100644 --- a/posthog/request.py +++ b/posthog/request.py @@ -218,7 +218,7 @@ def post( host: Optional[str] = None, path: Optional[str] = None, gzip: bool = False, - timeout: int = 15, + timeout: float = 15, session: Optional[requests.Session] = None, **kwargs, ) -> requests.Response: @@ -316,7 +316,7 @@ def flags( api_key: str, host: Optional[str] = None, gzip: bool = False, - timeout: int = 15, + timeout: float = 15, max_retries: int = 1, **kwargs, ) -> Any: @@ -358,7 +358,7 @@ def remote_config( project_api_key: str, host: Optional[str] = None, key: str = "", - timeout: int = 15, + timeout: float = 15, ) -> Any: """Get remote config flag value from remote_config API endpoint""" return _remote_config(personal_api_key, project_api_key, host, key, timeout) @@ -369,7 +369,7 @@ def _remote_config( project_api_key: str, host: Optional[str] = None, key: str = "", - timeout: int = 15, + timeout: float = 15, *, _user_agent: str = USER_AGENT, ) -> Any: @@ -391,7 +391,7 @@ def batch_post( api_key: str, host: Optional[str] = None, gzip: bool = False, - timeout: int = 15, + timeout: float = 15, path: str = EVENTS_ENDPOINT, **kwargs, ) -> requests.Response: @@ -406,7 +406,7 @@ def get( api_key: str, url: str, host: Optional[str] = None, - timeout: Optional[int] = None, + timeout: Optional[float] = None, etag: Optional[str] = None, ) -> GetResponse: """ @@ -423,7 +423,7 @@ def _get( api_key: str, url: str, host: Optional[str] = None, - timeout: Optional[int] = None, + timeout: Optional[float] = None, etag: Optional[str] = None, *, _user_agent: str = USER_AGENT, diff --git a/references/public_api_snapshot.txt b/references/public_api_snapshot.txt index f333489e3..a7d09a3ff 100644 --- a/references/public_api_snapshot.txt +++ b/references/public_api_snapshot.txt @@ -1271,14 +1271,14 @@ class posthog.ai.types.TokenUsage class posthog.ai.types.ToolInProgress class posthog.args.OptionalCaptureArgs class posthog.args.OptionalSetArgs -class posthog.async_client.AsyncClient(project_api_key: str, host: Optional[str] = None, debug: bool = False, max_queue_size: int = 10000, send: bool = True, on_error=None, flush_at: int = 100, flush_interval: float = 5.0, gzip: bool = False, max_retries: int = 3, timeout: int = 15, thread: int = 1, disabled: bool = False, disable_geoip: bool = True, is_server: bool = True, historical_migration: bool = False, super_properties: Optional[dict[str, Any]] = None, before_send=None, log_captured_exceptions: bool = False, project_root: Optional[str] = None, capture_exception_code_variables: bool = False, code_variables_mask_patterns=None, code_variables_ignore_patterns=None, code_variables_mask_url_credentials=None, code_variables_detect_secrets=None, in_app_modules: Optional[list[str]] = None, capture_mode: Optional[Union[CaptureMode, str]] = None, capture_compression: Optional[Union[CaptureCompression, str]] = None, capture_trace_context: bool = False, secret_key: Optional[str] = None, personal_api_key: Optional[str] = None, feature_flags_request_timeout_seconds: int = 3, feature_flags_request_max_retries: int = 1) +class posthog.async_client.AsyncClient(project_api_key: str, host: Optional[str] = None, debug: bool = False, max_queue_size: int = 10000, send: bool = True, on_error=None, flush_at: int = 100, flush_interval: float = 5.0, gzip: bool = False, max_retries: int = 3, timeout: float = 15, thread: int = 1, disabled: bool = False, disable_geoip: bool = True, is_server: bool = True, historical_migration: bool = False, super_properties: Optional[dict[str, Any]] = None, before_send=None, log_captured_exceptions: bool = False, project_root: Optional[str] = None, capture_exception_code_variables: bool = False, code_variables_mask_patterns=None, code_variables_ignore_patterns=None, code_variables_mask_url_credentials=None, code_variables_detect_secrets=None, in_app_modules: Optional[list[str]] = None, capture_mode: Optional[Union[CaptureMode, str]] = None, capture_compression: Optional[Union[CaptureCompression, str]] = None, capture_trace_context: bool = False, secret_key: Optional[str] = None, personal_api_key: Optional[str] = None, feature_flags_request_timeout_seconds: float = 3, feature_flags_request_max_retries: int = 1) class posthog.async_client.AsyncPosthog class posthog.bucketed_rate_limiter.BucketedRateLimiter(bucket_size: Number, refill_rate: Number, refill_interval_seconds: Number, on_bucket_rate_limited: Optional[Callable[[Hashable], None]] = None, clock: Callable[[], float] = time.monotonic) class posthog.capture_compression.CaptureCompression class posthog.capture_mode.CaptureMode class posthog.capture_v1.CaptureV1Error(status: int | str, message: str, *, retry_after: Optional[float] = None, request_id: Optional[str] = None, attempts: Optional[int] = None, retry_exhausted: Optional[list[str]] = None, drops: Optional[list[tuple[str, Optional[str]]]] = None) -class posthog.client.Client(project_api_key: str, host=None, debug=False, max_queue_size=10000, send=True, on_error=None, flush_at=100, flush_interval=5.0, gzip=False, max_retries=3, sync_mode=False, timeout=15, thread=1, poll_interval=30, personal_api_key=None, disabled=False, disable_geoip=True, is_server=True, historical_migration=False, feature_flags_request_timeout_seconds=3, feature_flags_request_max_retries=1, super_properties=None, enable_exception_autocapture=False, log_captured_exceptions=False, project_root=None, privacy_mode=False, before_send=None, flag_fallback_cache_url=None, enable_local_evaluation=True, flag_definition_cache_provider: Optional[FlagDefinitionCacheProvider] = None, capture_exception_code_variables=False, code_variables_mask_patterns=None, code_variables_ignore_patterns=None, code_variables_mask_url_credentials=None, code_variables_detect_secrets=None, in_app_modules: list[str] | None = None, enable_exception_autocapture_rate_limiting=False, exception_autocapture_bucket_size=ExceptionCapture.DEFAULT_BUCKET_SIZE, exception_autocapture_refill_rate=ExceptionCapture.DEFAULT_REFILL_RATE, exception_autocapture_refill_interval_seconds=ExceptionCapture.DEFAULT_REFILL_INTERVAL_SECONDS, capture_mode: Optional[Union[CaptureMode, str]] = None, capture_compression: Optional[Union[CaptureCompression, str]] = None, secret_key=None, metrics: Optional[dict] = None, enable_full_ai_capture=False, capture_trace_context=False, _use_ai_lane=False, _enable_multimodal_capture=False, traces: Optional[dict] = None) -class posthog.consumer.Consumer(queue, api_key, flush_at=100, host=None, on_error=None, flush_interval=5.0, gzip=False, retries=10, timeout=15, historical_migration=False, endpoint=EVENTS_ENDPOINT, max_msg_size=MAX_MSG_SIZE, capture_mode=CaptureMode.V0, capture_compression=CaptureCompression.NONE) +class posthog.client.Client(project_api_key: str, host=None, debug=False, max_queue_size=10000, send=True, on_error=None, flush_at=100, flush_interval=5.0, gzip=False, max_retries=3, sync_mode=False, timeout: float = 15, thread=1, poll_interval=30, personal_api_key=None, disabled=False, disable_geoip=True, is_server=True, historical_migration=False, feature_flags_request_timeout_seconds: float = 3, feature_flags_request_max_retries=1, super_properties=None, enable_exception_autocapture=False, log_captured_exceptions=False, project_root=None, privacy_mode=False, before_send=None, flag_fallback_cache_url=None, enable_local_evaluation=True, flag_definition_cache_provider: Optional[FlagDefinitionCacheProvider] = None, capture_exception_code_variables=False, code_variables_mask_patterns=None, code_variables_ignore_patterns=None, code_variables_mask_url_credentials=None, code_variables_detect_secrets=None, in_app_modules: list[str] | None = None, enable_exception_autocapture_rate_limiting=False, exception_autocapture_bucket_size=ExceptionCapture.DEFAULT_BUCKET_SIZE, exception_autocapture_refill_rate=ExceptionCapture.DEFAULT_REFILL_RATE, exception_autocapture_refill_interval_seconds=ExceptionCapture.DEFAULT_REFILL_INTERVAL_SECONDS, capture_mode: Optional[Union[CaptureMode, str]] = None, capture_compression: Optional[Union[CaptureCompression, str]] = None, secret_key=None, metrics: Optional[dict] = None, enable_full_ai_capture=False, capture_trace_context=False, _use_ai_lane=False, _enable_multimodal_capture=False, traces: Optional[dict] = None) +class posthog.consumer.Consumer(queue, api_key, flush_at=100, host=None, on_error=None, flush_interval=5.0, gzip=False, retries=10, timeout: float = 15, historical_migration=False, endpoint=EVENTS_ENDPOINT, max_msg_size=MAX_MSG_SIZE, capture_mode=CaptureMode.V0, capture_compression=CaptureCompression.NONE) class posthog.contexts.ContextScope(parent=None, fresh: bool = False, capture_exceptions: bool = True, client: Optional[Client] = None) class posthog.exception_capture.ExceptionCapture(client: Client, rate_limiting_enabled=False, bucket_size=DEFAULT_BUCKET_SIZE, refill_rate=DEFAULT_REFILL_RATE, refill_interval_seconds=DEFAULT_REFILL_INTERVAL_SECONDS) class posthog.exception_utils.AnnotatedValue(value, metadata) @@ -1517,15 +1517,15 @@ function posthog.mcp.session_token.encode_session_id(payload: SessionTokenPayloa function posthog.mcp.session_token.read_mcp_session_header(headers: Any) -> Optional[str] function posthog.mcp.tools.get_more_tools_result() -> Dict[str, Any] function posthog.new_context(fresh: bool = False, capture_exceptions: Optional[bool] = None, client: Optional[Client] = None) -function posthog.request.batch_post(api_key: str, host: Optional[str] = None, gzip: bool = False, timeout: int = 15, path: str = EVENTS_ENDPOINT, **kwargs) -> requests.Response +function posthog.request.batch_post(api_key: str, host: Optional[str] = None, gzip: bool = False, timeout: float = 15, path: str = EVENTS_ENDPOINT, **kwargs) -> requests.Response function posthog.request.determine_server_host(host: Optional[str]) -> str function posthog.request.disable_connection_reuse() -> None function posthog.request.enable_keep_alive() -> None -function posthog.request.flags(api_key: str, host: Optional[str] = None, gzip: bool = False, timeout: int = 15, max_retries: int = 1, **kwargs) -> Any -function posthog.request.get(api_key: str, url: str, host: Optional[str] = None, timeout: Optional[int] = None, etag: Optional[str] = None) -> GetResponse +function posthog.request.flags(api_key: str, host: Optional[str] = None, gzip: bool = False, timeout: float = 15, max_retries: int = 1, **kwargs) -> Any +function posthog.request.get(api_key: str, url: str, host: Optional[str] = None, timeout: Optional[float] = None, etag: Optional[str] = None) -> GetResponse function posthog.request.normalize_host(host: Optional[str]) -> str -function posthog.request.post(api_key: str, host: Optional[str] = None, path: Optional[str] = None, gzip: bool = False, timeout: int = 15, session: Optional[requests.Session] = None, **kwargs) -> requests.Response -function posthog.request.remote_config(personal_api_key: str, project_api_key: str, host: Optional[str] = None, key: str = '', timeout: int = 15) -> Any +function posthog.request.post(api_key: str, host: Optional[str] = None, path: Optional[str] = None, gzip: bool = False, timeout: float = 15, session: Optional[requests.Session] = None, **kwargs) -> requests.Response +function posthog.request.remote_config(personal_api_key: str, project_api_key: str, host: Optional[str] = None, key: str = '', timeout: float = 15) -> Any function posthog.request.reset_sessions() -> None function posthog.request.set_socket_options(socket_options: Optional[SocketOptions]) -> None function posthog.scoped(fresh=False, capture_exceptions: Optional[bool] = None) diff --git a/sdk_compliance_adapter/adapter.py b/sdk_compliance_adapter/adapter.py index 0d803ae52..8ff4ffff7 100644 --- a/sdk_compliance_adapter/adapter.py +++ b/sdk_compliance_adapter/adapter.py @@ -204,7 +204,7 @@ def patched_batch_post( api_key: str, host: Optional[str] = None, gzip: bool = False, - timeout: int = 15, + timeout: float = 15, path: str = EVENTS_ENDPOINT, **kwargs, ): @@ -236,7 +236,7 @@ def patched_post_v1( attempt: int, request_id: str, compression: CaptureCompression = CaptureCompression.NONE, - timeout: int = 15, + timeout: float = 15, sdk_info: str = USER_AGENT, session: Any = None, ): diff --git a/typings/requests/__init__.pyi b/typings/requests/__init__.pyi index 9e7892beb..9e92acd35 100644 --- a/typings/requests/__init__.pyi +++ b/typings/requests/__init__.pyi @@ -34,7 +34,7 @@ class Session: *, data: str | bytes, headers: dict[str, str], - timeout: int, + timeout: float, stream: bool = ..., ) -> Response: ... def get( @@ -42,5 +42,5 @@ class Session: url: str, *, headers: dict[str, str], - timeout: int | None = ..., + timeout: float | None = ..., ) -> Response: ...