kernel 0.80.0__tar.gz → 0.81.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kernel-0.81.0/.release-please-manifest.json +3 -0
- {kernel-0.80.0 → kernel-0.81.0}/CHANGELOG.md +8 -0
- {kernel-0.80.0 → kernel-0.81.0}/PKG-INFO +1 -1
- {kernel-0.80.0 → kernel-0.81.0}/pyproject.toml +1 -1
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/__init__.py +8 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_version.py +1 -1
- kernel-0.81.0/src/kernel/lib/audit_log_download.py +232 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/audit_logs.py +116 -1
- kernel-0.81.0/tests/test_audit_log_download.py +409 -0
- kernel-0.80.0/.release-please-manifest.json +0 -3
- {kernel-0.80.0 → kernel-0.81.0}/.gitignore +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/CONTRIBUTING.md +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/LICENSE +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/README.md +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/SECURITY.md +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/api.md +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/bin/check-release-environment +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/bin/publish-pypi +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/examples/.keep +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/examples/browser_routing.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/examples/browser_telemetry.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/noxfile.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/release-please-config.json +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/requirements-dev.lock +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/requirements.lock +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_base_client.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_client.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_compat.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_constants.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_exceptions.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_files.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_models.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_qs.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_resource.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_streaming.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_types.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_utils/__init__.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_utils/_compat.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_utils/_datetime_parse.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_utils/_json.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_utils/_logs.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_utils/_path.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_utils/_proxy.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_utils/_reflection.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_utils/_resources_proxy.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_utils/_streams.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_utils/_sync.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_utils/_transform.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_utils/_typing.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/_utils/_utils.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/app_framework.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/lib/.keep +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/lib/browser_routing/__init__.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/lib/browser_routing/raw_http.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/lib/browser_routing/routing.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/lib/browser_routing/util.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/pagination.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/py.typed +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/__init__.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/api_keys.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/apps.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/auth/__init__.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/auth/auth.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/auth/connections.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/browser_pools.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/browsers/__init__.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/browsers/browsers.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/browsers/computer.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/browsers/fs/__init__.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/browsers/fs/fs.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/browsers/fs/watch.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/browsers/logs.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/browsers/playwright.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/browsers/process.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/browsers/replays.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/browsers/telemetry.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/credential_providers.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/credentials.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/deployments.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/extensions.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/invocations.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/organization/__init__.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/organization/limits.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/organization/organization.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/profiles.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/projects/__init__.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/projects/limits.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/projects/projects.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/resources/proxies.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/__init__.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/api_key.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/api_key_create_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/api_key_list_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/api_key_retrieve_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/api_key_rotate_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/api_key_update_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/app_list_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/app_list_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/audit_log_entry.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/audit_log_export_chunk_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/audit_log_list_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/auth/__init__.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/auth/connection_create_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/auth/connection_follow_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/auth/connection_list_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/auth/connection_login_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/auth/connection_submit_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/auth/connection_timeline_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/auth/connection_update_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/auth/login_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/auth/managed_auth.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/auth/managed_auth_timeline_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/auth/submit_fields_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browser_create_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browser_create_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browser_curl_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browser_curl_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browser_list_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browser_list_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browser_load_extensions_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browser_pool.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browser_pool_acquire_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browser_pool_acquire_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browser_pool_create_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browser_pool_delete_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browser_pool_list_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browser_pool_ref.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browser_pool_release_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browser_pool_update_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browser_retrieve_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browser_retrieve_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browser_update_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browser_update_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browser_usage.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/__init__.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_api_call_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_call_stack.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_captcha_solve_result_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_cdp_connect_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_cdp_disconnect_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_console_error_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_console_log_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_event_context.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_event_source.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_http_headers.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_interaction_click_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_interaction_key_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_interaction_scroll_settled_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_live_view_connect_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_live_view_disconnect_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_monitor_disconnected_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_monitor_init_failed_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_monitor_reconnect_failed_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_monitor_reconnected_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_monitor_screenshot_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_network_idle_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_network_loading_failed_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_network_request_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_network_response_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_page_dom_content_loaded_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_page_layout_settled_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_page_layout_shift_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_page_lcp_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_page_load_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_page_navigation_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_page_navigation_settled_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_page_tab_opened_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_service_crashed_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_system_oom_kill_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_telemetry_categories_config.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_telemetry_categories_config_param.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_telemetry_category_config.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_telemetry_category_config_param.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_telemetry_config.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/browser_telemetry_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/computer_batch_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/computer_capture_screenshot_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/computer_click_mouse_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/computer_drag_mouse_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/computer_get_mouse_position_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/computer_move_mouse_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/computer_press_key_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/computer_read_clipboard_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/computer_scroll_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/computer_set_cursor_visibility_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/computer_set_cursor_visibility_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/computer_type_text_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/computer_write_clipboard_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/f_create_directory_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/f_delete_directory_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/f_delete_file_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/f_download_dir_zip_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/f_file_info_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/f_file_info_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/f_list_files_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/f_list_files_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/f_move_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/f_read_file_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/f_set_file_permissions_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/f_upload_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/f_upload_zip_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/f_write_file_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/fs/__init__.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/fs/watch_events_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/fs/watch_start_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/fs/watch_start_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/log_stream_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/playwright_execute_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/playwright_execute_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/process_exec_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/process_exec_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/process_kill_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/process_kill_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/process_resize_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/process_resize_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/process_spawn_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/process_spawn_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/process_status_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/process_stdin_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/process_stdin_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/process_stdout_stream_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/replay_list_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/replay_start_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/replay_start_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/telemetry_events_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/telemetry_events_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/telemetry_stream_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/browsers/telemetry_stream_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/created_api_key.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/credential.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/credential_create_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/credential_list_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/credential_provider.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/credential_provider_create_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/credential_provider_item.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/credential_provider_list_items_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/credential_provider_list_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/credential_provider_test_result.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/credential_provider_update_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/credential_totp_code_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/credential_update_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/deployment_create_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/deployment_create_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/deployment_follow_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/deployment_follow_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/deployment_list_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/deployment_list_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/deployment_retrieve_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/deployment_state_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/extension_download_from_chrome_store_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/extension_get_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/extension_list_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/extension_list_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/extension_upload_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/extension_upload_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/invocation_create_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/invocation_create_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/invocation_follow_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/invocation_follow_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/invocation_list_browsers_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/invocation_list_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/invocation_list_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/invocation_retrieve_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/invocation_state_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/invocation_update_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/invocation_update_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/organization/__init__.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/organization/limit_update_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/organization/org_limits.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/profile.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/profile_create_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/profile_list_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/profile_update_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/project.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/project_create_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/project_list_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/project_update_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/projects/__init__.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/projects/limit_update_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/projects/project_limits.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/proxy_check_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/proxy_check_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/proxy_create_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/proxy_create_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/proxy_list_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/proxy_list_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/proxy_retrieve_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/proxy_update_params.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/proxy_update_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/shared/__init__.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/shared/app_action.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/shared/browser_extension.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/shared/browser_profile.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/shared/browser_viewport.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/shared/error_detail.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/shared/error_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/shared/error_model.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/shared/heartbeat_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/shared/log_event.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/shared_params/__init__.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/shared_params/browser_extension.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/shared_params/browser_profile.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/shared_params/browser_viewport.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/tags.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/src/kernel/types/tags_param.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/__init__.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/__init__.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/auth/__init__.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/auth/test_connections.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/browsers/__init__.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/browsers/fs/__init__.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/browsers/fs/test_watch.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/browsers/test_computer.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/browsers/test_fs.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/browsers/test_logs.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/browsers/test_playwright.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/browsers/test_process.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/browsers/test_replays.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/browsers/test_telemetry.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/organization/__init__.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/organization/test_limits.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/projects/__init__.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/projects/test_limits.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/test_api_keys.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/test_apps.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/test_audit_logs.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/test_browser_pools.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/test_browsers.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/test_credential_providers.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/test_credentials.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/test_deployments.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/test_extensions.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/test_invocations.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/test_profiles.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/test_projects.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/api_resources/test_proxies.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/conftest.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/sample_file.txt +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/test_browser_routing.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/test_client.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/test_extract_files.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/test_files.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/test_models.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/test_pagination.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/test_qs.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/test_required_args.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/test_response.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/test_streaming.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/test_transform.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/test_utils/test_datetime_parse.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/test_utils/test_json.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/test_utils/test_path.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/test_utils/test_proxy.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/test_utils/test_typing.py +0 -0
- {kernel-0.80.0 → kernel-0.81.0}/tests/utils.py +0 -0
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.81.0 (2026-07-21)
|
|
4
|
+
|
|
5
|
+
Full Changelog: [v0.80.0...v0.81.0](https://github.com/kernel/kernel-python-sdk/compare/v0.80.0...v0.81.0)
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
* add complete audit log downloads ([18aa8c9](https://github.com/kernel/kernel-python-sdk/commit/18aa8c925b3f7699c30a6202685447432df2da6c))
|
|
10
|
+
|
|
3
11
|
## 0.80.0 (2026-07-19)
|
|
4
12
|
|
|
5
13
|
Full Changelog: [v0.79.0...v0.80.0](https://github.com/kernel/kernel-python-sdk/compare/v0.79.0...v0.80.0)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: kernel
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.81.0
|
|
4
4
|
Summary: The official Python library for the kernel API
|
|
5
5
|
Project-URL: Homepage, https://github.com/kernel/kernel-python-sdk
|
|
6
6
|
Project-URL: Repository, https://github.com/kernel/kernel-python-sdk
|
|
@@ -51,6 +51,11 @@ from .app_framework import (
|
|
|
51
51
|
app_registry,
|
|
52
52
|
export_registry,
|
|
53
53
|
)
|
|
54
|
+
from .lib.audit_log_download import (
|
|
55
|
+
AuditLogDownloadError,
|
|
56
|
+
AuditLogDownloadResult,
|
|
57
|
+
AuditLogDownloadProgress,
|
|
58
|
+
)
|
|
54
59
|
|
|
55
60
|
__all__ = [
|
|
56
61
|
"types",
|
|
@@ -105,6 +110,9 @@ __all__ = [
|
|
|
105
110
|
"App",
|
|
106
111
|
"app_registry",
|
|
107
112
|
"export_registry",
|
|
113
|
+
"AuditLogDownloadError",
|
|
114
|
+
"AuditLogDownloadProgress",
|
|
115
|
+
"AuditLogDownloadResult",
|
|
108
116
|
]
|
|
109
117
|
|
|
110
118
|
if not _t.TYPE_CHECKING:
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import time
|
|
4
|
+
import hashlib
|
|
5
|
+
import inspect
|
|
6
|
+
from typing import BinaryIO, Callable, Optional, Protocol, Awaitable, ContextManager, AsyncContextManager
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
|
|
9
|
+
import anyio
|
|
10
|
+
import httpx
|
|
11
|
+
from anyio import to_thread
|
|
12
|
+
|
|
13
|
+
from .._exceptions import KernelError
|
|
14
|
+
|
|
15
|
+
_DEFAULT_MAX_TRANSFER_RETRIES = 6
|
|
16
|
+
_MAX_CHUNK_ROWS = 50_000
|
|
17
|
+
_MAX_RETRY_DELAY = 8.0
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class AuditLogDownloadError(KernelError):
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(frozen=True)
|
|
25
|
+
class AuditLogDownloadResult:
|
|
26
|
+
bytes_written: int
|
|
27
|
+
chunks: int
|
|
28
|
+
rows: int
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass(frozen=True)
|
|
32
|
+
class AuditLogDownloadProgress(AuditLogDownloadResult):
|
|
33
|
+
chunk_rows: int
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class _SyncChunkResponse(Protocol):
|
|
37
|
+
@property
|
|
38
|
+
def headers(self) -> httpx.Headers: ...
|
|
39
|
+
|
|
40
|
+
def read(self) -> bytes: ...
|
|
41
|
+
|
|
42
|
+
def close(self) -> None: ...
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class _AsyncChunkResponse(Protocol):
|
|
46
|
+
@property
|
|
47
|
+
def headers(self) -> httpx.Headers: ...
|
|
48
|
+
|
|
49
|
+
async def read(self) -> bytes: ...
|
|
50
|
+
|
|
51
|
+
async def close(self) -> None: ...
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
SyncFetchChunk = Callable[[Optional[str]], ContextManager[_SyncChunkResponse]]
|
|
55
|
+
AsyncFetchChunk = Callable[[Optional[str]], AsyncContextManager[_AsyncChunkResponse]]
|
|
56
|
+
ProgressCallback = Callable[[AuditLogDownloadProgress], None]
|
|
57
|
+
AsyncProgressCallback = Callable[[AuditLogDownloadProgress], Optional[Awaitable[None]]]
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def download_audit_logs(
|
|
61
|
+
fetch_chunk: SyncFetchChunk,
|
|
62
|
+
destination: BinaryIO,
|
|
63
|
+
*,
|
|
64
|
+
on_progress: ProgressCallback | None = None,
|
|
65
|
+
max_transfer_retries: int = _DEFAULT_MAX_TRANSFER_RETRIES,
|
|
66
|
+
) -> AuditLogDownloadResult:
|
|
67
|
+
if not callable(getattr(destination, "write", None)):
|
|
68
|
+
raise TypeError("audit log download destination must provide write()")
|
|
69
|
+
_validate_max_transfer_retries(max_transfer_retries)
|
|
70
|
+
|
|
71
|
+
cursor: str | None = None
|
|
72
|
+
result = AuditLogDownloadResult(bytes_written=0, chunks=0, rows=0)
|
|
73
|
+
seen_cursors: set[str] = set()
|
|
74
|
+
while True:
|
|
75
|
+
body, headers = _fetch_verified_chunk(fetch_chunk, cursor, max_transfer_retries)
|
|
76
|
+
chunk_rows, next_cursor, has_more = _parse_chunk_headers(headers, cursor)
|
|
77
|
+
if has_more and next_cursor is not None:
|
|
78
|
+
if next_cursor in seen_cursors:
|
|
79
|
+
raise AuditLogDownloadError("response repeated X-Next-Cursor header")
|
|
80
|
+
seen_cursors.add(next_cursor)
|
|
81
|
+
_write_chunk(destination, body)
|
|
82
|
+
|
|
83
|
+
cursor = next_cursor
|
|
84
|
+
result = AuditLogDownloadResult(
|
|
85
|
+
bytes_written=result.bytes_written + len(body),
|
|
86
|
+
chunks=result.chunks + 1,
|
|
87
|
+
rows=result.rows + chunk_rows,
|
|
88
|
+
)
|
|
89
|
+
if on_progress is not None:
|
|
90
|
+
on_progress(
|
|
91
|
+
AuditLogDownloadProgress(
|
|
92
|
+
bytes_written=result.bytes_written,
|
|
93
|
+
chunks=result.chunks,
|
|
94
|
+
rows=result.rows,
|
|
95
|
+
chunk_rows=chunk_rows,
|
|
96
|
+
)
|
|
97
|
+
)
|
|
98
|
+
if not has_more:
|
|
99
|
+
return result
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
async def async_download_audit_logs(
|
|
103
|
+
fetch_chunk: AsyncFetchChunk,
|
|
104
|
+
destination: BinaryIO,
|
|
105
|
+
*,
|
|
106
|
+
on_progress: AsyncProgressCallback | None = None,
|
|
107
|
+
max_transfer_retries: int = _DEFAULT_MAX_TRANSFER_RETRIES,
|
|
108
|
+
) -> AuditLogDownloadResult:
|
|
109
|
+
if not callable(getattr(destination, "write", None)):
|
|
110
|
+
raise TypeError("audit log download destination must provide write()")
|
|
111
|
+
_validate_max_transfer_retries(max_transfer_retries)
|
|
112
|
+
|
|
113
|
+
cursor: str | None = None
|
|
114
|
+
result = AuditLogDownloadResult(bytes_written=0, chunks=0, rows=0)
|
|
115
|
+
seen_cursors: set[str] = set()
|
|
116
|
+
while True:
|
|
117
|
+
body, headers = await _async_fetch_verified_chunk(fetch_chunk, cursor, max_transfer_retries)
|
|
118
|
+
chunk_rows, next_cursor, has_more = _parse_chunk_headers(headers, cursor)
|
|
119
|
+
if has_more and next_cursor is not None:
|
|
120
|
+
if next_cursor in seen_cursors:
|
|
121
|
+
raise AuditLogDownloadError("response repeated X-Next-Cursor header")
|
|
122
|
+
seen_cursors.add(next_cursor)
|
|
123
|
+
await to_thread.run_sync(_write_chunk, destination, body)
|
|
124
|
+
|
|
125
|
+
cursor = next_cursor
|
|
126
|
+
result = AuditLogDownloadResult(
|
|
127
|
+
bytes_written=result.bytes_written + len(body),
|
|
128
|
+
chunks=result.chunks + 1,
|
|
129
|
+
rows=result.rows + chunk_rows,
|
|
130
|
+
)
|
|
131
|
+
if on_progress is not None:
|
|
132
|
+
callback_result = on_progress(
|
|
133
|
+
AuditLogDownloadProgress(
|
|
134
|
+
bytes_written=result.bytes_written,
|
|
135
|
+
chunks=result.chunks,
|
|
136
|
+
rows=result.rows,
|
|
137
|
+
chunk_rows=chunk_rows,
|
|
138
|
+
)
|
|
139
|
+
)
|
|
140
|
+
if inspect.isawaitable(callback_result):
|
|
141
|
+
await callback_result
|
|
142
|
+
if not has_more:
|
|
143
|
+
return result
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _fetch_verified_chunk(
|
|
147
|
+
fetch_chunk: SyncFetchChunk, cursor: str | None, max_transfer_retries: int
|
|
148
|
+
) -> tuple[bytes, httpx.Headers]:
|
|
149
|
+
for retries in range(max_transfer_retries + 1):
|
|
150
|
+
transfer_error: Exception | None = None
|
|
151
|
+
with fetch_chunk(cursor) as response:
|
|
152
|
+
try:
|
|
153
|
+
body = response.read()
|
|
154
|
+
headers = httpx.Headers(response.headers)
|
|
155
|
+
_verify_checksum(body, headers)
|
|
156
|
+
except Exception as error:
|
|
157
|
+
transfer_error = error
|
|
158
|
+
else:
|
|
159
|
+
return body, headers
|
|
160
|
+
assert transfer_error is not None
|
|
161
|
+
if retries == max_transfer_retries:
|
|
162
|
+
raise transfer_error
|
|
163
|
+
time.sleep(min(2**retries, _MAX_RETRY_DELAY))
|
|
164
|
+
raise AssertionError("unreachable")
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
async def _async_fetch_verified_chunk(
|
|
168
|
+
fetch_chunk: AsyncFetchChunk, cursor: str | None, max_transfer_retries: int
|
|
169
|
+
) -> tuple[bytes, httpx.Headers]:
|
|
170
|
+
for retries in range(max_transfer_retries + 1):
|
|
171
|
+
transfer_error: Exception | None = None
|
|
172
|
+
async with fetch_chunk(cursor) as response:
|
|
173
|
+
try:
|
|
174
|
+
body = await response.read()
|
|
175
|
+
headers = httpx.Headers(response.headers)
|
|
176
|
+
await to_thread.run_sync(_verify_checksum, body, headers)
|
|
177
|
+
except Exception as error:
|
|
178
|
+
transfer_error = error
|
|
179
|
+
else:
|
|
180
|
+
return body, headers
|
|
181
|
+
assert transfer_error is not None
|
|
182
|
+
if retries == max_transfer_retries:
|
|
183
|
+
raise transfer_error
|
|
184
|
+
await anyio.sleep(min(2**retries, _MAX_RETRY_DELAY))
|
|
185
|
+
raise AssertionError("unreachable")
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def _verify_checksum(body: bytes, headers: httpx.Headers) -> None:
|
|
189
|
+
expected = headers.get("x-content-sha256")
|
|
190
|
+
if not expected:
|
|
191
|
+
raise AuditLogDownloadError("response missing X-Content-Sha256 header")
|
|
192
|
+
actual = hashlib.sha256(body).hexdigest()
|
|
193
|
+
if actual != expected:
|
|
194
|
+
raise AuditLogDownloadError(f"audit log chunk checksum mismatch (got {actual}, want {expected})")
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def _parse_chunk_headers(headers: httpx.Headers, current_cursor: str | None) -> tuple[int, str | None, bool]:
|
|
198
|
+
has_more_value = headers.get("x-has-more")
|
|
199
|
+
if has_more_value not in {"true", "false"}:
|
|
200
|
+
raise AuditLogDownloadError("response missing or invalid X-Has-More header")
|
|
201
|
+
has_more = has_more_value == "true"
|
|
202
|
+
|
|
203
|
+
row_count = headers.get("x-row-count")
|
|
204
|
+
if row_count is None or not row_count.isascii() or not row_count.isdecimal():
|
|
205
|
+
raise AuditLogDownloadError("response missing or invalid X-Row-Count header")
|
|
206
|
+
normalized_row_count = row_count.lstrip("0") or "0"
|
|
207
|
+
if len(normalized_row_count) > len(str(_MAX_CHUNK_ROWS)):
|
|
208
|
+
raise AuditLogDownloadError("response missing or invalid X-Row-Count header")
|
|
209
|
+
rows = int(normalized_row_count)
|
|
210
|
+
if rows > _MAX_CHUNK_ROWS:
|
|
211
|
+
raise AuditLogDownloadError("response missing or invalid X-Row-Count header")
|
|
212
|
+
|
|
213
|
+
next_cursor = headers.get("x-next-cursor") or None
|
|
214
|
+
if has_more and (not next_cursor or next_cursor == current_cursor):
|
|
215
|
+
raise AuditLogDownloadError("response has invalid X-Next-Cursor header")
|
|
216
|
+
if not has_more and next_cursor:
|
|
217
|
+
raise AuditLogDownloadError("response returned a cursor after the final chunk")
|
|
218
|
+
return rows, next_cursor, has_more
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def _write_chunk(destination: BinaryIO, body: bytes) -> None:
|
|
222
|
+
remaining = memoryview(body)
|
|
223
|
+
while remaining:
|
|
224
|
+
written = destination.write(remaining)
|
|
225
|
+
if type(written) is not int or written <= 0 or written > len(remaining):
|
|
226
|
+
raise AuditLogDownloadError("audit log download destination performed a short write")
|
|
227
|
+
remaining = remaining[written:]
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def _validate_max_transfer_retries(max_transfer_retries: int) -> None:
|
|
231
|
+
if type(max_transfer_retries) is not int or max_transfer_retries < 0:
|
|
232
|
+
raise ValueError("max_transfer_retries must be a non-negative integer")
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from typing import Union
|
|
5
|
+
from typing import Union, BinaryIO, ContextManager, AsyncContextManager
|
|
6
6
|
from datetime import datetime
|
|
7
7
|
from typing_extensions import Literal
|
|
8
8
|
|
|
@@ -30,6 +30,13 @@ from .._response import (
|
|
|
30
30
|
from ..pagination import SyncPageTokenPagination, AsyncPageTokenPagination
|
|
31
31
|
from .._base_client import AsyncPaginator, make_request_options
|
|
32
32
|
from ..types.audit_log_entry import AuditLogEntry
|
|
33
|
+
from ..lib.audit_log_download import (
|
|
34
|
+
ProgressCallback,
|
|
35
|
+
AsyncProgressCallback,
|
|
36
|
+
AuditLogDownloadResult,
|
|
37
|
+
download_audit_logs,
|
|
38
|
+
async_download_audit_logs,
|
|
39
|
+
)
|
|
33
40
|
|
|
34
41
|
__all__ = ["AuditLogsResource", "AsyncAuditLogsResource"]
|
|
35
42
|
|
|
@@ -222,6 +229,60 @@ class AuditLogsResource(SyncAPIResource):
|
|
|
222
229
|
cast_to=BinaryAPIResponse,
|
|
223
230
|
)
|
|
224
231
|
|
|
232
|
+
def download(
|
|
233
|
+
self,
|
|
234
|
+
*,
|
|
235
|
+
to: BinaryIO,
|
|
236
|
+
end: Union[str, datetime],
|
|
237
|
+
start: Union[str, datetime],
|
|
238
|
+
auth_strategy: str | Omit = omit,
|
|
239
|
+
exclude_method: SequenceNotStr[str] | Omit = omit,
|
|
240
|
+
limit: int | Omit = omit,
|
|
241
|
+
method: str | Omit = omit,
|
|
242
|
+
search: str | Omit = omit,
|
|
243
|
+
search_user_id: SequenceNotStr[str] | Omit = omit,
|
|
244
|
+
service: str | Omit = omit,
|
|
245
|
+
on_progress: ProgressCallback | None = None,
|
|
246
|
+
max_transfer_retries: int = 6,
|
|
247
|
+
extra_headers: Headers | None = None,
|
|
248
|
+
extra_query: Query | None = None,
|
|
249
|
+
extra_body: Body | None = None,
|
|
250
|
+
timeout: float | httpx.Timeout | None | NotGiven = not_given,
|
|
251
|
+
) -> AuditLogDownloadResult:
|
|
252
|
+
"""Download a complete gzip-compressed JSON Lines audit log export.
|
|
253
|
+
|
|
254
|
+
The SDK writes the export to a writable binary destination, verifies
|
|
255
|
+
every chunk, and retries transient transfer failures. It does not close
|
|
256
|
+
the destination. If the download fails, the destination may contain a
|
|
257
|
+
partial export; use a temporary file and atomic rename when the completed
|
|
258
|
+
export must be published atomically.
|
|
259
|
+
"""
|
|
260
|
+
|
|
261
|
+
def fetch_chunk(cursor: str | None) -> ContextManager[StreamedBinaryAPIResponse]:
|
|
262
|
+
return self.with_streaming_response.export_chunk(
|
|
263
|
+
end=end,
|
|
264
|
+
start=start,
|
|
265
|
+
auth_strategy=auth_strategy,
|
|
266
|
+
cursor=cursor if cursor is not None else omit,
|
|
267
|
+
exclude_method=exclude_method,
|
|
268
|
+
limit=limit,
|
|
269
|
+
method=method,
|
|
270
|
+
search=search,
|
|
271
|
+
search_user_id=search_user_id,
|
|
272
|
+
service=service,
|
|
273
|
+
extra_headers=extra_headers,
|
|
274
|
+
extra_query=extra_query,
|
|
275
|
+
extra_body=extra_body,
|
|
276
|
+
timeout=timeout,
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
return download_audit_logs(
|
|
280
|
+
fetch_chunk,
|
|
281
|
+
to,
|
|
282
|
+
on_progress=on_progress,
|
|
283
|
+
max_transfer_retries=max_transfer_retries,
|
|
284
|
+
)
|
|
285
|
+
|
|
225
286
|
|
|
226
287
|
class AsyncAuditLogsResource(AsyncAPIResource):
|
|
227
288
|
"""Read audit log records for the authenticated organization."""
|
|
@@ -411,6 +472,60 @@ class AsyncAuditLogsResource(AsyncAPIResource):
|
|
|
411
472
|
cast_to=AsyncBinaryAPIResponse,
|
|
412
473
|
)
|
|
413
474
|
|
|
475
|
+
async def download(
|
|
476
|
+
self,
|
|
477
|
+
*,
|
|
478
|
+
to: BinaryIO,
|
|
479
|
+
end: Union[str, datetime],
|
|
480
|
+
start: Union[str, datetime],
|
|
481
|
+
auth_strategy: str | Omit = omit,
|
|
482
|
+
exclude_method: SequenceNotStr[str] | Omit = omit,
|
|
483
|
+
limit: int | Omit = omit,
|
|
484
|
+
method: str | Omit = omit,
|
|
485
|
+
search: str | Omit = omit,
|
|
486
|
+
search_user_id: SequenceNotStr[str] | Omit = omit,
|
|
487
|
+
service: str | Omit = omit,
|
|
488
|
+
on_progress: AsyncProgressCallback | None = None,
|
|
489
|
+
max_transfer_retries: int = 6,
|
|
490
|
+
extra_headers: Headers | None = None,
|
|
491
|
+
extra_query: Query | None = None,
|
|
492
|
+
extra_body: Body | None = None,
|
|
493
|
+
timeout: float | httpx.Timeout | None | NotGiven = not_given,
|
|
494
|
+
) -> AuditLogDownloadResult:
|
|
495
|
+
"""Download a complete gzip-compressed JSON Lines audit log export.
|
|
496
|
+
|
|
497
|
+
The SDK writes the export to a writable binary destination, verifies
|
|
498
|
+
every chunk, and retries transient transfer failures. It does not close
|
|
499
|
+
the destination. If the download fails, the destination may contain a
|
|
500
|
+
partial export; use a temporary file and atomic rename when the completed
|
|
501
|
+
export must be published atomically.
|
|
502
|
+
"""
|
|
503
|
+
|
|
504
|
+
def fetch_chunk(cursor: str | None) -> AsyncContextManager[AsyncStreamedBinaryAPIResponse]:
|
|
505
|
+
return self.with_streaming_response.export_chunk(
|
|
506
|
+
end=end,
|
|
507
|
+
start=start,
|
|
508
|
+
auth_strategy=auth_strategy,
|
|
509
|
+
cursor=cursor if cursor is not None else omit,
|
|
510
|
+
exclude_method=exclude_method,
|
|
511
|
+
limit=limit,
|
|
512
|
+
method=method,
|
|
513
|
+
search=search,
|
|
514
|
+
search_user_id=search_user_id,
|
|
515
|
+
service=service,
|
|
516
|
+
extra_headers=extra_headers,
|
|
517
|
+
extra_query=extra_query,
|
|
518
|
+
extra_body=extra_body,
|
|
519
|
+
timeout=timeout,
|
|
520
|
+
)
|
|
521
|
+
|
|
522
|
+
return await async_download_audit_logs(
|
|
523
|
+
fetch_chunk,
|
|
524
|
+
to,
|
|
525
|
+
on_progress=on_progress,
|
|
526
|
+
max_transfer_retries=max_transfer_retries,
|
|
527
|
+
)
|
|
528
|
+
|
|
414
529
|
|
|
415
530
|
class AuditLogsResourceWithRawResponse:
|
|
416
531
|
def __init__(self, audit_logs: AuditLogsResource) -> None:
|