bytekit-sdk 0.3.2__tar.gz → 0.3.5__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.
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/.gitignore +8 -0
- bytekit_sdk-0.3.5/CHANGELOG.md +321 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/PKG-INFO +77 -12
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/README.md +76 -11
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/pyproject.toml +32 -2
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/account/get_account.py +16 -12
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/bulk/create_bulk.py +105 -2
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/bulk/delete_bulk.py +3 -5
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/bulk/get_bulk.py +3 -5
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/bulk/list_bulk_screenshots.py +51 -5
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/fetch/get_fetch.py +32 -29
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/fetch/post_fetch.py +17 -2
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/fetch_bulk/create_fetch_bulk.py +45 -2
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/fetch_bulk/get_fetch_bulk.py +47 -5
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/monitors/create_monitor.py +13 -2
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/monitors/delete_monitor.py +3 -5
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/monitors/get_monitor.py +3 -5
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/monitors/list_monitor_captures.py +12 -14
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/monitors/list_monitors.py +19 -20
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/monitors/update_monitor.py +3 -5
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/scrape/create_scrape.py +1 -2
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/scrape/get_scrape.py +3 -5
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/scrape_bulk/create_scrape_bulk.py +1 -2
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/scrape_bulk/get_scrape_bulk.py +3 -5
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/screenshots/create_screenshot.py +53 -22
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/screenshots/get_screenshot.py +3 -5
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/search/create_search.py +1 -2
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/sitemap/create_sitemap.py +17 -2
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/sitemap/get_sitemap.py +7 -5
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/usage/get_usage.py +1 -2
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/usage/get_usage_by_endpoint.py +1 -2
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/usage/get_usage_daily.py +1 -2
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/webhooks/list_webhook_deliveries.py +10 -11
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/webhooks/retry_webhook_delivery.py +23 -5
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/client.py +129 -18
- bytekit_sdk-0.3.5/src/bytekit/errors.py +216 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/__init__.py +22 -6
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_bulk_body.py +16 -20
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_bulk_body_defaults.py +27 -52
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_bulk_body_items_item.py +4 -24
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_bulk_response_202.py +21 -8
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_fetch_bulk_body.py +6 -6
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_fetch_bulk_body_defaults.py +4 -4
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_fetch_bulk_body_urls_item_type_1.py +1 -20
- bytekit_sdk-0.3.5/src/bytekit/models/create_fetch_bulk_response_202.py +179 -0
- bytekit_sdk-0.3.5/src/bytekit/models/create_fetch_bulk_response_202_status.py +10 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_scrape_bulk_body_defaults.py +7 -8
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_scrape_bulk_body_items_item.py +7 -12
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_scrape_bulk_response_202.py +21 -8
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_search_body.py +5 -10
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_search_response_200_results_item.py +6 -5
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/delete_bulk_response_200.py +17 -8
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/get_bulk_response_200.py +17 -8
- bytekit_sdk-0.3.5/src/bytekit/models/get_fetch_bulk_response_200.py +201 -0
- bytekit_sdk-0.3.5/src/bytekit/models/get_fetch_bulk_response_200_items_item.py +217 -0
- bytekit_sdk-0.3.5/src/bytekit/models/get_fetch_bulk_response_200_items_item_status.py +12 -0
- bytekit_sdk-0.3.5/src/bytekit/models/get_fetch_bulk_response_200_status.py +10 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/get_scrape_bulk_response_200.py +17 -8
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/get_usage_response_200.py +2 -2
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/get_usage_response_200_plan_type.py +0 -1
- bytekit_sdk-0.3.5/src/bytekit/models/list_bulk_screenshots_response_200.py +100 -0
- bytekit_sdk-0.3.5/src/bytekit/models/list_bulk_screenshots_response_200_items_item.py +352 -0
- bytekit_sdk-0.3.5/src/bytekit/models/list_bulk_screenshots_response_200_items_item_status.py +12 -0
- bytekit_sdk-0.3.5/src/bytekit/models/list_bulk_screenshots_response_200_items_item_type.py +10 -0
- bytekit_sdk-0.3.2/CHANGELOG.md +0 -89
- bytekit_sdk-0.3.2/src/bytekit/errors.py +0 -106
- bytekit_sdk-0.3.2/src/bytekit/models/create_fetch_bulk_body_metadata.py +0 -44
- bytekit_sdk-0.3.2/src/bytekit/models/create_fetch_bulk_response_202.py +0 -44
- bytekit_sdk-0.3.2/src/bytekit/models/create_scrape_bulk_body_items_item_metadata.py +0 -44
- bytekit_sdk-0.3.2/src/bytekit/models/get_fetch_bulk_response_200.py +0 -44
- bytekit_sdk-0.3.2/src/bytekit/models/list_bulk_screenshots_response_200.py +0 -44
- bytekit_sdk-0.3.2/tests/__init__.py +0 -0
- bytekit_sdk-0.3.2/tests/conftest.py +0 -97
- bytekit_sdk-0.3.2/tests/fixtures/unpatched_client.py.snapshot +0 -365
- bytekit_sdk-0.3.2/tests/fixtures/unpatched_create_scrape.py.snapshot +0 -197
- bytekit_sdk-0.3.2/tests/fixtures/unpatched_delete_monitor.py.snapshot +0 -155
- bytekit_sdk-0.3.2/tests/fixtures/unpatched_errors.py.snapshot +0 -16
- bytekit_sdk-0.3.2/tests/fixtures/unpatched_get_fetch.py.snapshot +0 -254
- bytekit_sdk-0.3.2/tests/test_bulk_delete.py +0 -33
- bytekit_sdk-0.3.2/tests/test_client.py +0 -121
- bytekit_sdk-0.3.2/tests/test_client_defaults.py +0 -122
- bytekit_sdk-0.3.2/tests/test_deactivated_resources.py +0 -108
- bytekit_sdk-0.3.2/tests/test_generate_docs.py +0 -285
- bytekit_sdk-0.3.2/tests/test_models.py +0 -178
- bytekit_sdk-0.3.2/tests/test_no_materialized_defaults.py +0 -31
- bytekit_sdk-0.3.2/tests/test_op_error_paths.py +0 -360
- bytekit_sdk-0.3.2/tests/test_package_identity.py +0 -24
- bytekit_sdk-0.3.2/tests/test_patch_functions.py +0 -308
- bytekit_sdk-0.3.2/tests/test_prune_stale_api.py +0 -753
- bytekit_sdk-0.3.2/tests/test_publish_metadata.py +0 -179
- bytekit_sdk-0.3.2/tests/test_readme_examples.py +0 -127
- bytekit_sdk-0.3.2/tests/test_regen_durability.py +0 -170
- bytekit_sdk-0.3.2/tests/test_removed_surface.py +0 -50
- bytekit_sdk-0.3.2/tests/test_scrape_markdown_opts.py +0 -157
- bytekit_sdk-0.3.2/tests/test_scrape_scored_formats.py +0 -135
- bytekit_sdk-0.3.2/tests/test_sdist_contents.py +0 -182
- bytekit_sdk-0.3.2/tests/test_search.py +0 -209
- bytekit_sdk-0.3.2/tests/test_search_errors.py +0 -97
- bytekit_sdk-0.3.2/tests/test_spec_field_parity.py +0 -106
- bytekit_sdk-0.3.2/tests/test_typed_search_surface.py +0 -181
- bytekit_sdk-0.3.2/tests/test_usage.py +0 -80
- bytekit_sdk-0.3.2/tests/test_version.py +0 -110
- bytekit_sdk-0.3.2/tests/test_webhook_deliveries.py +0 -59
- bytekit_sdk-0.3.2/tests/test_wheel_contents.py +0 -109
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/LICENSE +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/__init__.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/__init__.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/account/__init__.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/bulk/__init__.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/fetch/__init__.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/fetch_bulk/__init__.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/monitors/__init__.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/scrape/__init__.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/scrape_bulk/__init__.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/screenshots/__init__.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/search/__init__.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/sitemap/__init__.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/usage/__init__.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/api/webhooks/__init__.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/account_bearer_response.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/account_bearer_response_api_key.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/account_bearer_response_api_key_environment.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/account_bearer_response_auto_topup.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/account_bearer_response_plan.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/account_bearer_response_subscription.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/account_bearer_response_subscription_plan.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/account_bearer_response_subscription_status.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/account_session_response.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/account_session_response_notifications.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/account_session_response_plan.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/bandwidth_balance.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/capture_response.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/capture_response_outcome.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/clip.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/cookie.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_bulk_body_defaults_device.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_bulk_body_defaults_device_scale_factor_type_1.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_bulk_body_defaults_device_scale_factor_type_2_type_1.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_bulk_body_defaults_device_scale_factor_type_3_type_1.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_bulk_body_defaults_formats_item.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_bulk_body_defaults_type.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_bulk_body_defaults_viewport_type_0.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_bulk_body_defaults_wait_until.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_bulk_body_items_item_device.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_bulk_body_items_item_formats_item.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_bulk_body_items_item_scenario.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_bulk_body_items_item_type.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_bulk_body_items_item_viewport_type_0.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_bulk_body_items_item_wait_until.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_bulk_response_202_status.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_fetch_bulk_body_defaults_format.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_fetch_bulk_body_urls_item_type_1_format.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_scrape_bulk_body.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_scrape_bulk_body_custom.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_scrape_bulk_body_defaults_formats_item.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_scrape_bulk_body_defaults_headers.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_scrape_bulk_body_items_item_custom.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_scrape_bulk_body_items_item_formats_item.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_scrape_bulk_body_items_item_headers.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_scrape_bulk_response_202_status.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_search_body_date_range.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_search_body_type.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_search_response_200.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_search_response_200_results_item_image.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_search_response_502.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/create_search_response_502_error.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/credit_balance.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/delete_bulk_response_200_status.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/error.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/error_error.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/error_status.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/fetch_request.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/fetch_request_cache_ttl_type_1.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/fetch_request_custom.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/fetch_request_format.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/fetch_request_markdown_images.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/fetch_request_markdown_links.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/fetch_request_markdown_mode.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/get_bulk_response_200_status.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/get_fetch_cache_ttl_type_1.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/get_fetch_format.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/get_scrape_bulk_response_200_status.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/get_usage_by_endpoint_response_200.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/get_usage_by_endpoint_response_200_rows_item.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/get_usage_by_endpoint_response_200_rows_item_endpoint.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/get_usage_by_endpoint_response_200_totals.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/get_usage_daily_response_200.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/get_usage_daily_response_200_data_item.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/list_monitor_captures_response_200.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/list_monitors_response_200.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/list_monitors_status.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/list_webhook_deliveries_response_200.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/list_webhook_deliveries_status.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/metadata.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/monitor_create_request.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/monitor_create_request_interval_type.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/monitor_create_request_notify_on.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/monitor_create_request_options.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/monitor_create_request_scrape_options.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/monitor_create_request_type.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/monitor_create_request_webhook_headers.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/monitor_create_response.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/monitor_response.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/monitor_response_interval_type.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/monitor_response_metadata_type_0.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/monitor_response_status.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/monitor_response_type.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/monitor_response_webhook_headers_type_0.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/monitor_update_request.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/monitor_update_request_interval_type.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/monitor_update_request_notify_on.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/monitor_update_request_options.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/monitor_update_request_scrape_options.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/monitor_update_request_status.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/monitor_update_request_webhook_headers.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_error_envelope.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_error_envelope_error.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_error_envelope_error_code.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_error_envelope_schema_version.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_error_envelope_status.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_formats.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_markdown_tokens.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_metadata.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_queued_envelope.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_queued_envelope_schema_version.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_queued_envelope_status.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_request.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_request_cache_ttl_type_1.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_request_custom.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_request_events_item.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_request_formats_item.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_request_headers.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_request_markdown_images.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_request_markdown_links.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_request_markdown_mode.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_request_token_encoding.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_request_x_internal_scrape_path.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_scored_image.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_scored_link.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_stats.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_success_envelope.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_success_envelope_cache.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_success_envelope_custom.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_success_envelope_schema_version.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_success_envelope_status.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_table.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_table_kind.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_warning.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/scrape_warning_code.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/screenshot_request.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/screenshot_request_device.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/screenshot_request_device_scale_factor_type_1.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/screenshot_request_device_scale_factor_type_2_type_1.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/screenshot_request_device_scale_factor_type_3_type_1.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/screenshot_request_format.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/screenshot_request_headers.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/screenshot_request_wait_until.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/screenshot_response.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/screenshot_response_status.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/sitemap_request.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/sitemap_request_process_type_0.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/sitemap_request_process_type_0_options.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/sitemap_request_strategy.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/sitemap_response.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/sitemap_response_cache.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/sitemap_response_metadata_type_0.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/sitemap_response_process_type_0.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/sitemap_response_sources_type_0.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/sitemap_response_status.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/viewport.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/webhook_delivery_response.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/webhook_delivery_response_event_type.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/models/webhook_delivery_response_status.py +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/py.typed +0 -0
- {bytekit_sdk-0.3.2 → bytekit_sdk-0.3.5}/src/bytekit/types.py +0 -0
|
@@ -47,6 +47,14 @@ packages/http-fetcher/server
|
|
|
47
47
|
packages/http-fetcher/browserforge-bench
|
|
48
48
|
__pycache__/
|
|
49
49
|
*.pyc
|
|
50
|
+
# ruff's incremental cache. Written by the openapi-python-client post-hooks INSIDE the
|
|
51
|
+
# generated output dir (packages/sdk-python/src/bytekit/.ruff_cache/). ruff already drops a
|
|
52
|
+
# self-ignoring `.gitignore` containing `*` in there, which is exactly why the directory went
|
|
53
|
+
# unnoticed for so long — `git status` never mentions it. This entry is belt-and-braces so the
|
|
54
|
+
# by-product is ignored even if ruff stops self-ignoring. The reproducibility gate
|
|
55
|
+
# (ci/scripts/check-sdk-python-regen.sh) excludes it from BOTH of its diffs: cache entry names
|
|
56
|
+
# are hashes of the absolute path, so two clean-room generates differ by construction.
|
|
57
|
+
.ruff_cache/
|
|
50
58
|
# Generated artifact — reproduced via `pnpm --filter @rapidcrawl/sdk-python generate`
|
|
51
59
|
packages/sdk-python/filtered-openapi.yaml
|
|
52
60
|
# NOTE: the MCP server's generated docs JSON (see packages/mcp-server/src) is intentionally
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to the ByteKit Python SDK are documented here.
|
|
4
|
+
PyPI distribution: `bytekit-sdk`. Import name: `bytekit`.
|
|
5
|
+
|
|
6
|
+
## 0.3.5
|
|
7
|
+
|
|
8
|
+
### Breaking
|
|
9
|
+
|
|
10
|
+
- **`AuthenticatedClient` takes no positional arguments.** `token`, `prefix` and
|
|
11
|
+
`auth_header_name` are now keyword-only, joining `base_url`, `timeout`,
|
|
12
|
+
`raise_on_unexpected_status` and the rest — so `AuthenticatedClient(...)` accepts keywords
|
|
13
|
+
only. Before 0.3.0 the first positional argument was `base_url`, which made
|
|
14
|
+
`AuthenticatedClient("https://api-stg.bytekit.com", "sk_live_…")` a documented call. When
|
|
15
|
+
0.3.0 made `base_url` a defaulted keyword argument, that call stopped meaning what it said
|
|
16
|
+
and started **binding the URL to `token` and the API key to `prefix`** — sending
|
|
17
|
+
`Authorization: sk_live_… https://api-stg.bytekit.com` to the _default_ host,
|
|
18
|
+
`https://api.bytekit.com`, with nothing raised and nothing warned. It now raises
|
|
19
|
+
`TypeError`. Migration is mechanical:
|
|
20
|
+
`AuthenticatedClient(base_url="https://api-stg.bytekit.com", token="sk_live_…")`. Keyword
|
|
21
|
+
construction — the form the README, the docs site and every example already use — is
|
|
22
|
+
entirely unchanged, including `prefix=`/`auth_header_name=` overrides and the
|
|
23
|
+
`with_headers`/`with_cookies`/`with_timeout` helpers. The unauthenticated `Client` was
|
|
24
|
+
already keyword-only and is unaffected.
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- **A schema-drifted response body no longer crashes with a bare `KeyError`.** A generated
|
|
29
|
+
model's `from_dict` trusts the `required` keys the OpenAPI spec declared when the client
|
|
30
|
+
was generated, so a server that renamed, dropped or retyped a field leaked the generator's
|
|
31
|
+
own internal exception straight to the caller — `KeyError: 'schema_version'` from
|
|
32
|
+
`create_scrape`, `KeyError: 'period_start'` from `get_usage`, `KeyError: 'data'` from
|
|
33
|
+
`list_monitors`, plus `TypeError`/`ValueError` for non-object and nested-drift bodies. It
|
|
34
|
+
happened on a **documented** status (a `200`/`202`), in **both** raise modes, and no row of
|
|
35
|
+
the documented error table covered it, so a caller who handled that table faithfully still
|
|
36
|
+
had no branch for it. Schema drift now takes exactly the same two arms as a non-JSON body:
|
|
37
|
+
`errors.UnexpectedStatus` (carrying `.status_code` and the raw `.content`, with the
|
|
38
|
+
original parse failure attached as `__cause__`) in the default mode, and `None` under
|
|
39
|
+
`raise_on_unexpected_status=False`. Deliberately **no new exception type** — a new class
|
|
40
|
+
would be one every existing `except errors.UnexpectedStatus` silently fails to catch, i.e.
|
|
41
|
+
the same untyped crash in a different costume. Bodies that match the documented schema
|
|
42
|
+
parse exactly as before, and a genuinely optional key that is absent still yields `UNSET`.
|
|
43
|
+
- **`client.search()` never returns a silent `None`.** Its 200 body is parsed through the
|
|
44
|
+
same shared guard the generated operations use, which honors
|
|
45
|
+
`raise_on_unexpected_status` — so an opt-out client got `None` handed back from a non-JSON
|
|
46
|
+
200 or a schema-drifted one, contradicting both the method's non-`Optional` return
|
|
47
|
+
annotation and its own docstring. `search()` now raises `errors.UnexpectedStatus` in
|
|
48
|
+
**both** raise modes. `raise_on_unexpected_status` configures the generated two-tier
|
|
49
|
+
contract, whose signatures are `Optional[...]`; `search()` was never part of it — it
|
|
50
|
+
already raises on documented error statuses that the generated `create_search` returns as
|
|
51
|
+
a typed `Error` model. A well-formed 200 still returns the parsed
|
|
52
|
+
`CreateSearchResponse200` in either mode.
|
|
53
|
+
- **A non-IANA HTTP status no longer crashes every operation with a bare `ValueError`.**
|
|
54
|
+
Each generated operation built its `Response` with
|
|
55
|
+
`status_code=HTTPStatus(response.status_code)` evaluated _before_ the response was
|
|
56
|
+
parsed, so any status outside Python's `http.HTTPStatus` — Cloudflare's `520`–`530`
|
|
57
|
+
family, nginx's `499` — raised `ValueError: 520 is not a valid HTTPStatus` from inside
|
|
58
|
+
the SDK. This happened in **both** raise modes: the default
|
|
59
|
+
`raise_on_unexpected_status=True` never got to raise its `errors.UnexpectedStatus`, and
|
|
60
|
+
`raise_on_unexpected_status=False`, which promises `None`, raised the `ValueError` too.
|
|
61
|
+
`api.bytekit.com` is served through Cloudflare, so this was exactly the edge/CDN failure
|
|
62
|
+
class the typed-error contract exists for. All 29 operations now behave as documented:
|
|
63
|
+
`errors.UnexpectedStatus` (carrying `.status_code` and the raw `.content`) in the default
|
|
64
|
+
mode, a `Response` with `.parsed is None` in the opt-out mode. The hand-written
|
|
65
|
+
`client.search()` wrapper was never affected and is unchanged.
|
|
66
|
+
|
|
67
|
+
### Changed
|
|
68
|
+
|
|
69
|
+
- **`Response.status_code` is a plain `int` for a status `http.HTTPStatus` does not know.**
|
|
70
|
+
This is the contract decision behind the fix above, recorded here because it is the one
|
|
71
|
+
observable difference in the typed surface. Concretely:
|
|
72
|
+
- Every status the stdlib enum **does** know — documented by the API or not, `200` as
|
|
73
|
+
much as `503` — still comes back as a real `http.HTTPStatus` member, so
|
|
74
|
+
`response.status_code.phrase`, `.name`, and identity comparisons such as
|
|
75
|
+
`response.status_code is HTTPStatus.OK` keep working exactly as before.
|
|
76
|
+
- A status the enum does **not** know (`499`, `520`, `521`, `522`, `530`, …) comes back
|
|
77
|
+
as the plain `int` the wire carried. `int` comparisons (`response.status_code == 520`,
|
|
78
|
+
`>= 500`) work; enum-only attributes (`.phrase`, `.name`) do not exist on it. The
|
|
79
|
+
alternatives were rejected deliberately: a synthetic `IntEnum` member would invent a
|
|
80
|
+
`.phrase`/`.name` no registry backs, and raising before the `Response` is constructed
|
|
81
|
+
is the bug itself — it is precisely what `raise_on_unexpected_status=False` promises
|
|
82
|
+
not to do.
|
|
83
|
+
- The **declared** annotation on `Response.status_code` is unchanged (`HTTPStatus`), so
|
|
84
|
+
this release adds no type errors to existing consumer code; widening it to
|
|
85
|
+
`Union[HTTPStatus, int]` would make `.phrase`/`.name` a type error on _every_ response,
|
|
86
|
+
including the IANA ones, which is a far larger break than the residual it would close.
|
|
87
|
+
Reach for `.phrase`/`.name` only after an `isinstance(..., HTTPStatus)` check if you
|
|
88
|
+
handle edge statuses off a non-raising client.
|
|
89
|
+
|
|
90
|
+
In the default (raising) mode this is largely invisible: a non-IANA status raises
|
|
91
|
+
`errors.UnexpectedStatus` before any `Response` is returned, and
|
|
92
|
+
`UnexpectedStatus.status_code` has always been a plain `int`.
|
|
93
|
+
|
|
94
|
+
### Documentation
|
|
95
|
+
|
|
96
|
+
- The "Error handling" example in the README now requests `formats=[…MARKDOWN]` explicitly.
|
|
97
|
+
Run literally, its success arm printed `<bytekit.types.Unset object at 0x…>`: the snippet
|
|
98
|
+
built `ScrapeRequest(url=...)` with no `formats`, so the server applied its `raw_html`
|
|
99
|
+
default and `result.formats.markdown` was legitimately unset. The same class of defect
|
|
100
|
+
0.3.3 fixed in the quick start, in the block directly beneath it. The README's error table
|
|
101
|
+
gains the schema-drift row, a note that `search()` is outside the two-tier contract, and a
|
|
102
|
+
migration note for the keyword-only constructor.
|
|
103
|
+
|
|
104
|
+
## 0.3.4
|
|
105
|
+
|
|
106
|
+
### Breaking
|
|
107
|
+
|
|
108
|
+
- **`CreateBulkBody`, `CreateBulkBodyDefaults`, `CreateBulkBodyItemsItem`, and
|
|
109
|
+
`CreateFetchBulkBodyUrlsItemType1` lost their additional-properties mapping API.**
|
|
110
|
+
`docs/api/openapi.yaml`'s `/v1/bulk` request schema declares `additionalProperties: false`
|
|
111
|
+
on the top-level body, `items[]`, and `defaults` (issue #2641), and `/v1/fetch/bulk`'s
|
|
112
|
+
per-item override schema inside `urls[]` declares the same (issue #2648), matching the
|
|
113
|
+
gateway's own `.strict()` validators. The code generator responds to
|
|
114
|
+
`additionalProperties: false` by omitting the catch-all mapping it otherwise attaches to
|
|
115
|
+
every generated model, so these four models no longer expose `additional_properties`, the
|
|
116
|
+
`additional_keys` property, `__getitem__`, `__setitem__`, `__delitem__`, or `__contains__`.
|
|
117
|
+
Code that did `body["some_key"] = value`, `"some_key" in body`, or read
|
|
118
|
+
`body.additional_keys` on any of these four models will now raise
|
|
119
|
+
`AttributeError`/`TypeError` instead. Use the model's declared `attrs` fields directly
|
|
120
|
+
instead (e.g. `CreateBulkBodyItemsItem(url=..., type=...)`,
|
|
121
|
+
`CreateFetchBulkBodyUrlsItemType1(url=..., format_=...)`); the server itself now rejects
|
|
122
|
+
unrecognized keys on these endpoints with `422 validation_error`, so the removed escape
|
|
123
|
+
hatch could never have reached the API successfully anyway. This is scoped to the four
|
|
124
|
+
`create_bulk_body*` / `create_fetch_bulk_body_urls_item_type_1` models — no other generated
|
|
125
|
+
model is affected.
|
|
126
|
+
|
|
127
|
+
- If you are upgrading from 0.3.2 or earlier, note that **0.3.3 also carried a breaking model
|
|
128
|
+
removal** that went undocumented at the time — see the "Breaking" entry under 0.3.3 below
|
|
129
|
+
(`CreateFetchBulkBodyMetadata` and `CreateScrapeBulkBodyItemsItemMetadata`).
|
|
130
|
+
|
|
131
|
+
## 0.3.3 [NEVER PUBLISHED]
|
|
132
|
+
|
|
133
|
+
> **Never published to PyPI.** This version was cut in-tree but no `bytekit-sdk` 0.3.3 artifact
|
|
134
|
+
> exists — `pip install bytekit-sdk==0.3.3` fails. Everything below shipped to users in **0.3.4**,
|
|
135
|
+
> which is the first published release containing it. Reconciled by issue #2680; the
|
|
136
|
+
> `release-drift` CI gate now blocks a new phantom heading from being introduced.
|
|
137
|
+
|
|
138
|
+
### Breaking
|
|
139
|
+
|
|
140
|
+
- **`CreateFetchBulkBodyMetadata` and `CreateScrapeBulkBodyItemsItemMetadata` were removed;
|
|
141
|
+
both fields now use the shared `Metadata` model.** This landed with the default-stripping
|
|
142
|
+
traversal fix listed under "Fixed" below (issue #2592) and was not recorded at the time.
|
|
143
|
+
Once server defaults stopped being materialized into the request-direction schemas, the two
|
|
144
|
+
per-body `metadata` objects became structurally identical to the shared `Metadata`
|
|
145
|
+
component, and the code generator emits one model per distinct schema — so
|
|
146
|
+
`bytekit.models.create_fetch_bulk_body_metadata` and
|
|
147
|
+
`bytekit.models.create_scrape_bulk_body_items_item_metadata` no longer exist and importing
|
|
148
|
+
either raises `ModuleNotFoundError`. `CreateFetchBulkBody.metadata` and
|
|
149
|
+
`CreateScrapeBulkBodyItemsItem.metadata` are now typed `Union[Unset, Metadata]`. The wire
|
|
150
|
+
format is **unchanged** — the same JSON object is sent either way — so the migration is
|
|
151
|
+
purely at the import site: `from bytekit.models.metadata import Metadata`, then
|
|
152
|
+
`Metadata(...)` (or `Metadata.from_dict({...})`) wherever you constructed one of the two
|
|
153
|
+
removed classes.
|
|
154
|
+
|
|
155
|
+
### Security
|
|
156
|
+
|
|
157
|
+
- **Path parameters are now percent-encoded.** All 13 operations that interpolate an id into
|
|
158
|
+
their URL (`get_scrape`, `get_screenshot`, `get_bulk`, `delete_bulk`,
|
|
159
|
+
`list_bulk_screenshots`, `get_scrape_bulk`, `get_fetch_bulk`, `get_monitor`,
|
|
160
|
+
`update_monitor`, `delete_monitor`, `list_monitor_captures`, `get_sitemap`,
|
|
161
|
+
`retry_webhook_delivery`) previously interpolated the value raw, so an id containing `/`,
|
|
162
|
+
`?`, `#` or traversal segments could retarget the request to a **different path on the same
|
|
163
|
+
authenticated host** — e.g. a `DELETE /v1/bulk/{id}` becoming a delete against another
|
|
164
|
+
resource. Values are now encoded with `quote(str(value), safe="")`. This is **not** a
|
|
165
|
+
breaking change for any id the API issues: hex and `sc_`/`ss_`/`mon_`/`sm_`/`bulk_`-prefixed
|
|
166
|
+
ids contain no reserved characters, so the resulting URL is byte-identical to before.
|
|
167
|
+
No id-format validation was added — the client does not reject id shapes.
|
|
168
|
+
|
|
169
|
+
### Fixed
|
|
170
|
+
|
|
171
|
+
- **Reusing one client across several `asyncio.run(...)` calls no longer raises
|
|
172
|
+
`RuntimeError: Event loop is closed`.** An `httpx.AsyncClient`'s connection pool belongs to
|
|
173
|
+
the event loop that created it, and the SDK cached its internal async client
|
|
174
|
+
unconditionally. It now tracks which loop that client was built on and transparently
|
|
175
|
+
rebuilds it when the running loop changes, re-applying `base_url`, headers, timeout,
|
|
176
|
+
`httpx_args` and authentication. Behavior is unchanged when no loop is running, and a client
|
|
177
|
+
you supply via `set_async_httpx_client(...)` is **never** rebuilt or closed — it stays yours
|
|
178
|
+
to manage. See the README's new "Clients and event loops" section.
|
|
179
|
+
- **The README quick start now prints markdown instead of an `Unset` placeholder.** It
|
|
180
|
+
requested no `formats`, so the server applied its `raw_html` default and
|
|
181
|
+
`result.formats.markdown` was legitimately unset. It now asks for
|
|
182
|
+
`formats=[ScrapeRequestFormatsItem.MARKDOWN]` — note `formats` takes enum members, not plain
|
|
183
|
+
strings.
|
|
184
|
+
- **`client.search(type="images")` no longer crashes with a bare `KeyError: 'snippet'`.**
|
|
185
|
+
The OpenAPI spec's search result-item schema declared `snippet` as `required` while its
|
|
186
|
+
own description said the key is omitted for `images` results — a self-contradiction the
|
|
187
|
+
code generator trusted literally, so `CreateSearchResponse200ResultsItem.from_dict`
|
|
188
|
+
unconditionally did `d.pop("snippet")`. `snippet` (like `date`) is now `Union[Unset, str]`,
|
|
189
|
+
matching the real gateway behavior (`web`/`news` results still always carry `snippet`;
|
|
190
|
+
`images` results omit it entirely) — fixed at the spec level (`docs/api/openapi.yaml`) and
|
|
191
|
+
regenerated, not patched in the generated model. (Issue #2579.)
|
|
192
|
+
- **Server defaults are no longer materialized into request wire bodies/query strings
|
|
193
|
+
for inline request bodies and `$ref`'d parameters.** `scripts/filter-spec.ts`'s
|
|
194
|
+
default-stripping traversal previously only followed `$ref`'d request-body component
|
|
195
|
+
schemas, so `ScrapeRequest`/`FetchRequest` were clean but every other request-direction
|
|
196
|
+
shape kept baking in server defaults: `/v1/search`'s fully-inline body (`type`,
|
|
197
|
+
`limit`, `country`, `language`, `date_range`), all three bulk endpoints' bodies and
|
|
198
|
+
their nested `Defaults`/`ItemsItem` models, and `$ref`'d query parameters
|
|
199
|
+
(`GET /v1/fetch`'s `country`/`timeout_ms`/`cache_ttl`, `list_monitors`'
|
|
200
|
+
`limit`/`status`, `list_webhook_deliveries`'/`list_monitor_captures`' `limit`,
|
|
201
|
+
`create_screenshot`'s `async`). The traversal now walks inline request bodies AND
|
|
202
|
+
parameters (both operation-level and shared path-item-level, `$ref`'d or inline)
|
|
203
|
+
before generation, so an omitted optional field always serializes to nothing and
|
|
204
|
+
the server's own default applies — caller-supplied values are unaffected and still
|
|
205
|
+
serialize exactly as given (issue #2592).
|
|
206
|
+
- `tests/test_no_materialized_defaults.py` rewritten to enumerate every
|
|
207
|
+
request-direction model and operation parameter programmatically (walking the
|
|
208
|
+
generated `bytekit.api`/`bytekit.models` trees) instead of sampling two known-clean
|
|
209
|
+
models, so a newly introduced leaker is caught automatically.
|
|
210
|
+
|
|
211
|
+
### Changed
|
|
212
|
+
|
|
213
|
+
- **The source distribution no longer ships `tests/`.** The bundled suite could not be
|
|
214
|
+
collected from an unpacked sdist: 12 of its 27 modules require the repository's codegen
|
|
215
|
+
scripts or the canonical OpenAPI spec, neither of which belongs in a published
|
|
216
|
+
distribution, and three of them build distributions of the package itself. Nothing
|
|
217
|
+
importable was removed — the **wheel is unchanged**, `py.typed` included, so
|
|
218
|
+
`pip install bytekit-sdk` is unaffected.
|
|
219
|
+
|
|
220
|
+
### Internal
|
|
221
|
+
|
|
222
|
+
- CI now proves the committed client is reproducible from the canonical OpenAPI spec, and that
|
|
223
|
+
the generation chain is deterministic (generating twice yields byte-identical output). This
|
|
224
|
+
closes the gap where a spec change could land with a TypeScript-only regeneration and leave
|
|
225
|
+
the Python client silently stranded on an older spec.
|
|
226
|
+
- `ruff` is now pinned to an exact version alongside the code generator. The generator runs
|
|
227
|
+
`ruff` over everything it emits, so it — not the generator alone — determines the committed
|
|
228
|
+
bytes; the generator itself accepts any `ruff<0.13`, which meant a fresh install could
|
|
229
|
+
reformat the whole tree. Bumping the pin is a deliberate, reviewed reformat.
|
|
230
|
+
- The PEP 561 `py.typed` marker is now emitted by the post-generation injector rather than
|
|
231
|
+
hand-maintained inside the generated tree (the generator omits it under `--meta none`).
|
|
232
|
+
|
|
233
|
+
## 0.3.2
|
|
234
|
+
|
|
235
|
+
### Added
|
|
236
|
+
|
|
237
|
+
- **`bytekit.__version__`** reports the installed distribution version, resolved at import
|
|
238
|
+
time from `importlib.metadata` (so it can never drift from `pyproject.toml`'s
|
|
239
|
+
`[project].version`). When the package is imported from a source tree with no installed
|
|
240
|
+
distribution it reads `0.0.0.dev0` rather than raising. The dead version override in
|
|
241
|
+
`sdk-python-config.yaml` — inert under `--meta none` and contradicting the real
|
|
242
|
+
version — has been removed, leaving one authoritative version.
|
|
243
|
+
|
|
244
|
+
### Fixed
|
|
245
|
+
|
|
246
|
+
- **`AuthenticatedClient.search()` is now visible to type checkers.** It was attached to the
|
|
247
|
+
class after creation, so despite the package shipping a `py.typed` marker, `mypy` and
|
|
248
|
+
`pyright` reported `"AuthenticatedClient" has no attribute "search"`. It is now declared as a
|
|
249
|
+
real method in the class body that delegates to the same implementation: **runtime behavior,
|
|
250
|
+
arguments, return type and raised errors are unchanged** — only the static surface is fixed.
|
|
251
|
+
|
|
252
|
+
## 0.3.1 [NEVER PUBLISHED]
|
|
253
|
+
|
|
254
|
+
> **Never published to PyPI.** This version was cut in-tree but no `bytekit-sdk` 0.3.1 artifact
|
|
255
|
+
> exists — `pip install bytekit-sdk==0.3.1` fails. Everything below shipped to users in **0.3.2**,
|
|
256
|
+
> which is the first published release containing it. Reconciled by issue #2680; the
|
|
257
|
+
> `release-drift` CI gate now blocks a new phantom heading from being introduced.
|
|
258
|
+
|
|
259
|
+
### Fixed
|
|
260
|
+
|
|
261
|
+
- **The "never a bare `json.JSONDecodeError`" guarantee is now package-wide across all
|
|
262
|
+
generated operations**, not only the `AuthenticatedClient.search()` wrapper. Every
|
|
263
|
+
generated operation previously called `response.json()` unconditionally on a
|
|
264
|
+
DOCUMENTED status, so a `500`/`502` serving an HTML load-balancer page raised a bare
|
|
265
|
+
`json.JSONDecodeError` from inside the SDK. All operations now parse documented
|
|
266
|
+
statuses through a shared guard: a non-JSON body raises the typed
|
|
267
|
+
`errors.UnexpectedStatus` (or returns `None` when
|
|
268
|
+
`raise_on_unexpected_status=False`), carrying the status code and the raw body.
|
|
269
|
+
- **`errors.UnexpectedStatus.code` / `.message` are now populated for generated
|
|
270
|
+
operations too**, from the documented `Error` envelope — previously they were always
|
|
271
|
+
`None` outside `search()`. A string-valued `error` (the masked search-provider `502`)
|
|
272
|
+
still never enriches, so the upstream provider's identity is never surfaced.
|
|
273
|
+
- Behavior on JSON bodies is unchanged: JSON success bodies still parse into their typed
|
|
274
|
+
success models, documented JSON error bodies are still **returned** as typed `Error`
|
|
275
|
+
models rather than raised, and `raise_on_unexpected_status` semantics are untouched.
|
|
276
|
+
The documented non-JSON success paths — `get_fetch`/`post_fetch`'s raw-text `200` and
|
|
277
|
+
`delete_monitor`'s empty `204` — are likewise unaffected.
|
|
278
|
+
- **README error documentation corrected.** The quick-start example wrapped a call in
|
|
279
|
+
`try/except UnexpectedStatus` and then read `response.formats.markdown`, but a
|
|
280
|
+
documented `4xx` _returns_ a typed `Error` model without raising — so the documented
|
|
281
|
+
example failed with `AttributeError: 'Error' object has no attribute 'formats'`. The
|
|
282
|
+
README now documents the real two-tier contract, and the snippet is executed by
|
|
283
|
+
`tests/test_readme_examples.py` so it cannot silently drift again.
|
|
284
|
+
|
|
285
|
+
### Documentation
|
|
286
|
+
|
|
287
|
+
- Removed the contributor-only `Publishing`, `Regenerating`, and `Development` sections
|
|
288
|
+
from the published README (the PyPI long description) — they described internal CI
|
|
289
|
+
mechanics and a monorepo-contributor workflow that do not belong on a public package
|
|
290
|
+
index. The regeneration/development knowledge is preserved in-repo in
|
|
291
|
+
`packages/sdk-python/CLAUDE.md` (not shipped in the distribution).
|
|
292
|
+
- Added a `## License` section and a `LICENSE` file, matching the npm sibling packages.
|
|
293
|
+
|
|
294
|
+
## 0.3.0
|
|
295
|
+
|
|
296
|
+
### Breaking
|
|
297
|
+
|
|
298
|
+
- **PyPI distribution renamed `bytekit` -> `bytekit-sdk`.** PyPI administratively
|
|
299
|
+
denylists the bare name `bytekit`, so the package installs as
|
|
300
|
+
`pip install bytekit-sdk`. The **import name is unchanged** — `import bytekit`
|
|
301
|
+
still works, and no module path moved. Nothing was ever published under the old
|
|
302
|
+
distribution name, so there is no migration for existing installs.
|
|
303
|
+
- **`raise_on_unexpected_status` now defaults to `True`.** Undocumented response
|
|
304
|
+
statuses now raise `errors.UnexpectedStatus` instead of silently returning `None`.
|
|
305
|
+
Callers that relied on the old `None`-return behavior must pass
|
|
306
|
+
`raise_on_unexpected_status=False` explicitly to opt out.
|
|
307
|
+
- **`base_url` is now a keyword-only argument.** It gained a default
|
|
308
|
+
(`https://api.bytekit.com`), and to satisfy attrs field ordering it became
|
|
309
|
+
keyword-only. Any caller passing `base_url` positionally must switch to the
|
|
310
|
+
`base_url=` keyword form. (`base_url=` was already the documented usage.)
|
|
311
|
+
|
|
312
|
+
### Added
|
|
313
|
+
|
|
314
|
+
- `AuthenticatedClient(token=...)` now works out of the box against production:
|
|
315
|
+
`base_url` defaults to `https://api.bytekit.com`.
|
|
316
|
+
- Finite default request timeout of `120s` (`httpx.Timeout(120.0)`) — requests no
|
|
317
|
+
longer hang indefinitely. Override with `timeout=`.
|
|
318
|
+
- `errors.UnexpectedStatus` now carries optional `.code` / `.message` attributes.
|
|
319
|
+
The `AuthenticatedClient.search()` wrapper populates them from the documented
|
|
320
|
+
`Error` envelope, and safely raises a typed error (never a bare
|
|
321
|
+
`json.JSONDecodeError`) on a non-JSON documented-status body such as an HTML 502.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bytekit-sdk
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.5
|
|
4
4
|
Summary: Official Python SDK for the ByteKit API
|
|
5
5
|
Project-URL: Homepage, https://bytekit.com
|
|
6
6
|
Project-URL: Repository, https://github.com/Hunt-Labs-Inc/ByteKit
|
|
@@ -46,16 +46,24 @@ The installed version is available as `bytekit.__version__`.
|
|
|
46
46
|
from bytekit import AuthenticatedClient
|
|
47
47
|
from bytekit.api.scrape import create_scrape
|
|
48
48
|
from bytekit.models.scrape_request import ScrapeRequest
|
|
49
|
+
from bytekit.models.scrape_request_formats_item import ScrapeRequestFormatsItem
|
|
49
50
|
from bytekit.models.scrape_success_envelope import ScrapeSuccessEnvelope
|
|
50
51
|
|
|
51
52
|
# base_url defaults to https://api.bytekit.com, so only the token is required.
|
|
52
53
|
client = AuthenticatedClient(token="sk_live_your_api_key_here")
|
|
53
54
|
|
|
54
|
-
result = create_scrape.sync(
|
|
55
|
+
result = create_scrape.sync(
|
|
56
|
+
client=client,
|
|
57
|
+
body=ScrapeRequest(
|
|
58
|
+
url="https://example.com",
|
|
59
|
+
# Ask for markdown explicitly. `formats` is a list of enum members, not plain
|
|
60
|
+
# strings. Omit it and the server returns raw HTML instead, leaving
|
|
61
|
+
# `formats.markdown` unset.
|
|
62
|
+
formats=[ScrapeRequestFormatsItem.MARKDOWN],
|
|
63
|
+
),
|
|
64
|
+
)
|
|
55
65
|
|
|
56
66
|
if isinstance(result, ScrapeSuccessEnvelope):
|
|
57
|
-
# formats.markdown is str | Unset — only set when "markdown" was among the
|
|
58
|
-
# requested formats.
|
|
59
67
|
print(result.formats.markdown)
|
|
60
68
|
```
|
|
61
69
|
|
|
@@ -64,13 +72,22 @@ See [Error handling](#error-handling) for what `result` can be when the request
|
|
|
64
72
|
### Error handling
|
|
65
73
|
|
|
66
74
|
The SDK has a **two-tier** error contract. Both tiers are safe: an operation never raises
|
|
67
|
-
a bare `json.JSONDecodeError`, even when a server returns an HTML error
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
|
71
|
-
|
|
|
72
|
-
|
|
|
73
|
-
|
|
|
75
|
+
a bare `json.JSONDecodeError` or a bare `KeyError`, even when a server returns an HTML error
|
|
76
|
+
page or a payload whose shape has drifted from the spec.
|
|
77
|
+
|
|
78
|
+
| Situation | What you get |
|
|
79
|
+
| ----------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
80
|
+
| A status the OpenAPI spec **documents** for that operation (e.g. a `422` or `500` on `create_scrape`), with a JSON body of the documented shape | The typed `Error` model is **returned**, not raised. Check with `isinstance(result, Error)` and read `result.error.code` / `result.error.message`. |
|
|
81
|
+
| An **undocumented** status, or a **non-JSON body on a documented status** (HTML error page, load-balancer text, empty body) | `errors.UnexpectedStatus` is **raised**, carrying `.status_code` and the raw `.content`. When the body is the documented `Error` envelope, `.code` / `.message` are populated too. |
|
|
82
|
+
| A **documented status whose JSON body does not match the documented schema** — a field the server renamed, dropped or retyped | `errors.UnexpectedStatus` is **raised**, same shape as the row above. The underlying parse failure (e.g. `KeyError: 'schema_version'`) is attached as `__cause__` for diagnosis. |
|
|
83
|
+
| Any of the above, with `raise_on_unexpected_status=False` | Nothing is raised; the operation returns `None`. |
|
|
84
|
+
|
|
85
|
+
The table describes the **generated operations** (`create_scrape.sync`, `get_usage.sync`, …),
|
|
86
|
+
whose return types are `Optional[...]` accordingly. The hand-written
|
|
87
|
+
`AuthenticatedClient.search(...)` convenience method is deliberately outside it: it returns a
|
|
88
|
+
non-`Optional` `CreateSearchResponse200` and raises `errors.UnexpectedStatus` on anything else
|
|
89
|
+
— including documented error statuses, and including a malformed `200` — **in both raise
|
|
90
|
+
modes**. `raise_on_unexpected_status` does not apply to it.
|
|
74
91
|
|
|
75
92
|
```python
|
|
76
93
|
from bytekit import AuthenticatedClient
|
|
@@ -78,12 +95,21 @@ from bytekit.api.scrape import create_scrape
|
|
|
78
95
|
from bytekit.errors import UnexpectedStatus
|
|
79
96
|
from bytekit.models.error import Error
|
|
80
97
|
from bytekit.models.scrape_request import ScrapeRequest
|
|
98
|
+
from bytekit.models.scrape_request_formats_item import ScrapeRequestFormatsItem
|
|
81
99
|
from bytekit.models.scrape_success_envelope import ScrapeSuccessEnvelope
|
|
82
100
|
|
|
83
101
|
client = AuthenticatedClient(token="sk_live_your_api_key_here")
|
|
84
102
|
|
|
85
103
|
try:
|
|
86
|
-
result = create_scrape.sync(
|
|
104
|
+
result = create_scrape.sync(
|
|
105
|
+
client=client,
|
|
106
|
+
body=ScrapeRequest(
|
|
107
|
+
url="https://example.com",
|
|
108
|
+
# Ask for markdown explicitly — omit `formats` and the server returns raw HTML,
|
|
109
|
+
# leaving `formats.markdown` unset.
|
|
110
|
+
formats=[ScrapeRequestFormatsItem.MARKDOWN],
|
|
111
|
+
),
|
|
112
|
+
)
|
|
87
113
|
except UnexpectedStatus as err:
|
|
88
114
|
# Undocumented status, or a non-JSON body on a documented one. Never a JSONDecodeError.
|
|
89
115
|
print(f"request failed with status {err.status_code}: {err.code} {err.message}")
|
|
@@ -110,6 +136,22 @@ The client ships with production-ready defaults so `AuthenticatedClient(token=..
|
|
|
110
136
|
|
|
111
137
|
Explicit constructor arguments always win over these defaults (explicit arg > default).
|
|
112
138
|
|
|
139
|
+
#### Every constructor argument is keyword-only
|
|
140
|
+
|
|
141
|
+
`AuthenticatedClient` accepts **no positional arguments**. `token`, `base_url`, `prefix`,
|
|
142
|
+
`auth_header_name` and the rest are all passed by name:
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
client = AuthenticatedClient(base_url="https://api.bytekit.com", token="sk_live_your_api_key_here")
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**Migrating from a pre-0.3.0 positional call.** `base_url` used to be the first positional
|
|
149
|
+
argument, so `AuthenticatedClient("https://…", "sk_live_…")` was a documented call. Once
|
|
150
|
+
`base_url` became a defaulted keyword argument, that same call silently bound the **URL to
|
|
151
|
+
`token`** and the **API key to `prefix`** — producing an `Authorization: sk_live_… https://…`
|
|
152
|
+
header sent to the _default_ host, i.e. a wrong credential against production with nothing
|
|
153
|
+
raised. Since 0.3.5 it raises `TypeError` instead. Add the keywords; nothing else changes.
|
|
154
|
+
|
|
113
155
|
## Async usage
|
|
114
156
|
|
|
115
157
|
```python
|
|
@@ -127,6 +169,29 @@ async def main():
|
|
|
127
169
|
asyncio.run(main())
|
|
128
170
|
```
|
|
129
171
|
|
|
172
|
+
### Clients and event loops
|
|
173
|
+
|
|
174
|
+
An `httpx.AsyncClient` — and therefore its connection pool — belongs to the event loop that
|
|
175
|
+
created it. The recommended shape is a context manager, which scopes the client to exactly one
|
|
176
|
+
loop:
|
|
177
|
+
|
|
178
|
+
```python
|
|
179
|
+
async def main():
|
|
180
|
+
async with AuthenticatedClient(token="sk_live_your_api_key_here") as client:
|
|
181
|
+
...
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Two rules cover everything else:
|
|
185
|
+
|
|
186
|
+
- **A client the SDK builds for you is rebuilt automatically.** If you reuse one client across
|
|
187
|
+
several `asyncio.run(...)` calls, the SDK notices the running loop has changed and transparently
|
|
188
|
+
replaces its internal `AsyncClient`. Your `base_url`, headers, timeout, `httpx_args` and
|
|
189
|
+
authentication are all re-applied, so this is invisible apart from a new connection. Calling
|
|
190
|
+
`get_async_httpx_client()` outside any running loop returns the cached client unchanged.
|
|
191
|
+
- **A client you pass to `set_async_httpx_client(...)` is yours.** The SDK never rebuilds or
|
|
192
|
+
closes it, so a client you supply must be created and used on the same loop — that is the one
|
|
193
|
+
case where crossing loops is still your responsibility.
|
|
194
|
+
|
|
130
195
|
## Available operations
|
|
131
196
|
|
|
132
197
|
| Module | Method | Description |
|
|
@@ -20,16 +20,24 @@ The installed version is available as `bytekit.__version__`.
|
|
|
20
20
|
from bytekit import AuthenticatedClient
|
|
21
21
|
from bytekit.api.scrape import create_scrape
|
|
22
22
|
from bytekit.models.scrape_request import ScrapeRequest
|
|
23
|
+
from bytekit.models.scrape_request_formats_item import ScrapeRequestFormatsItem
|
|
23
24
|
from bytekit.models.scrape_success_envelope import ScrapeSuccessEnvelope
|
|
24
25
|
|
|
25
26
|
# base_url defaults to https://api.bytekit.com, so only the token is required.
|
|
26
27
|
client = AuthenticatedClient(token="sk_live_your_api_key_here")
|
|
27
28
|
|
|
28
|
-
result = create_scrape.sync(
|
|
29
|
+
result = create_scrape.sync(
|
|
30
|
+
client=client,
|
|
31
|
+
body=ScrapeRequest(
|
|
32
|
+
url="https://example.com",
|
|
33
|
+
# Ask for markdown explicitly. `formats` is a list of enum members, not plain
|
|
34
|
+
# strings. Omit it and the server returns raw HTML instead, leaving
|
|
35
|
+
# `formats.markdown` unset.
|
|
36
|
+
formats=[ScrapeRequestFormatsItem.MARKDOWN],
|
|
37
|
+
),
|
|
38
|
+
)
|
|
29
39
|
|
|
30
40
|
if isinstance(result, ScrapeSuccessEnvelope):
|
|
31
|
-
# formats.markdown is str | Unset — only set when "markdown" was among the
|
|
32
|
-
# requested formats.
|
|
33
41
|
print(result.formats.markdown)
|
|
34
42
|
```
|
|
35
43
|
|
|
@@ -38,13 +46,22 @@ See [Error handling](#error-handling) for what `result` can be when the request
|
|
|
38
46
|
### Error handling
|
|
39
47
|
|
|
40
48
|
The SDK has a **two-tier** error contract. Both tiers are safe: an operation never raises
|
|
41
|
-
a bare `json.JSONDecodeError`, even when a server returns an HTML error
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
|
45
|
-
|
|
|
46
|
-
|
|
|
47
|
-
|
|
|
49
|
+
a bare `json.JSONDecodeError` or a bare `KeyError`, even when a server returns an HTML error
|
|
50
|
+
page or a payload whose shape has drifted from the spec.
|
|
51
|
+
|
|
52
|
+
| Situation | What you get |
|
|
53
|
+
| ----------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
54
|
+
| A status the OpenAPI spec **documents** for that operation (e.g. a `422` or `500` on `create_scrape`), with a JSON body of the documented shape | The typed `Error` model is **returned**, not raised. Check with `isinstance(result, Error)` and read `result.error.code` / `result.error.message`. |
|
|
55
|
+
| An **undocumented** status, or a **non-JSON body on a documented status** (HTML error page, load-balancer text, empty body) | `errors.UnexpectedStatus` is **raised**, carrying `.status_code` and the raw `.content`. When the body is the documented `Error` envelope, `.code` / `.message` are populated too. |
|
|
56
|
+
| A **documented status whose JSON body does not match the documented schema** — a field the server renamed, dropped or retyped | `errors.UnexpectedStatus` is **raised**, same shape as the row above. The underlying parse failure (e.g. `KeyError: 'schema_version'`) is attached as `__cause__` for diagnosis. |
|
|
57
|
+
| Any of the above, with `raise_on_unexpected_status=False` | Nothing is raised; the operation returns `None`. |
|
|
58
|
+
|
|
59
|
+
The table describes the **generated operations** (`create_scrape.sync`, `get_usage.sync`, …),
|
|
60
|
+
whose return types are `Optional[...]` accordingly. The hand-written
|
|
61
|
+
`AuthenticatedClient.search(...)` convenience method is deliberately outside it: it returns a
|
|
62
|
+
non-`Optional` `CreateSearchResponse200` and raises `errors.UnexpectedStatus` on anything else
|
|
63
|
+
— including documented error statuses, and including a malformed `200` — **in both raise
|
|
64
|
+
modes**. `raise_on_unexpected_status` does not apply to it.
|
|
48
65
|
|
|
49
66
|
```python
|
|
50
67
|
from bytekit import AuthenticatedClient
|
|
@@ -52,12 +69,21 @@ from bytekit.api.scrape import create_scrape
|
|
|
52
69
|
from bytekit.errors import UnexpectedStatus
|
|
53
70
|
from bytekit.models.error import Error
|
|
54
71
|
from bytekit.models.scrape_request import ScrapeRequest
|
|
72
|
+
from bytekit.models.scrape_request_formats_item import ScrapeRequestFormatsItem
|
|
55
73
|
from bytekit.models.scrape_success_envelope import ScrapeSuccessEnvelope
|
|
56
74
|
|
|
57
75
|
client = AuthenticatedClient(token="sk_live_your_api_key_here")
|
|
58
76
|
|
|
59
77
|
try:
|
|
60
|
-
result = create_scrape.sync(
|
|
78
|
+
result = create_scrape.sync(
|
|
79
|
+
client=client,
|
|
80
|
+
body=ScrapeRequest(
|
|
81
|
+
url="https://example.com",
|
|
82
|
+
# Ask for markdown explicitly — omit `formats` and the server returns raw HTML,
|
|
83
|
+
# leaving `formats.markdown` unset.
|
|
84
|
+
formats=[ScrapeRequestFormatsItem.MARKDOWN],
|
|
85
|
+
),
|
|
86
|
+
)
|
|
61
87
|
except UnexpectedStatus as err:
|
|
62
88
|
# Undocumented status, or a non-JSON body on a documented one. Never a JSONDecodeError.
|
|
63
89
|
print(f"request failed with status {err.status_code}: {err.code} {err.message}")
|
|
@@ -84,6 +110,22 @@ The client ships with production-ready defaults so `AuthenticatedClient(token=..
|
|
|
84
110
|
|
|
85
111
|
Explicit constructor arguments always win over these defaults (explicit arg > default).
|
|
86
112
|
|
|
113
|
+
#### Every constructor argument is keyword-only
|
|
114
|
+
|
|
115
|
+
`AuthenticatedClient` accepts **no positional arguments**. `token`, `base_url`, `prefix`,
|
|
116
|
+
`auth_header_name` and the rest are all passed by name:
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
client = AuthenticatedClient(base_url="https://api.bytekit.com", token="sk_live_your_api_key_here")
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Migrating from a pre-0.3.0 positional call.** `base_url` used to be the first positional
|
|
123
|
+
argument, so `AuthenticatedClient("https://…", "sk_live_…")` was a documented call. Once
|
|
124
|
+
`base_url` became a defaulted keyword argument, that same call silently bound the **URL to
|
|
125
|
+
`token`** and the **API key to `prefix`** — producing an `Authorization: sk_live_… https://…`
|
|
126
|
+
header sent to the _default_ host, i.e. a wrong credential against production with nothing
|
|
127
|
+
raised. Since 0.3.5 it raises `TypeError` instead. Add the keywords; nothing else changes.
|
|
128
|
+
|
|
87
129
|
## Async usage
|
|
88
130
|
|
|
89
131
|
```python
|
|
@@ -101,6 +143,29 @@ async def main():
|
|
|
101
143
|
asyncio.run(main())
|
|
102
144
|
```
|
|
103
145
|
|
|
146
|
+
### Clients and event loops
|
|
147
|
+
|
|
148
|
+
An `httpx.AsyncClient` — and therefore its connection pool — belongs to the event loop that
|
|
149
|
+
created it. The recommended shape is a context manager, which scopes the client to exactly one
|
|
150
|
+
loop:
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
async def main():
|
|
154
|
+
async with AuthenticatedClient(token="sk_live_your_api_key_here") as client:
|
|
155
|
+
...
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Two rules cover everything else:
|
|
159
|
+
|
|
160
|
+
- **A client the SDK builds for you is rebuilt automatically.** If you reuse one client across
|
|
161
|
+
several `asyncio.run(...)` calls, the SDK notices the running loop has changed and transparently
|
|
162
|
+
replaces its internal `AsyncClient`. Your `base_url`, headers, timeout, `httpx_args` and
|
|
163
|
+
authentication are all re-applied, so this is invisible apart from a new connection. Calling
|
|
164
|
+
`get_async_httpx_client()` outside any running loop returns the cached client unchanged.
|
|
165
|
+
- **A client you pass to `set_async_httpx_client(...)` is yours.** The SDK never rebuilds or
|
|
166
|
+
closes it, so a client you supply must be created and used on the same loop — that is the one
|
|
167
|
+
case where crossing loops is still your responsibility.
|
|
168
|
+
|
|
104
169
|
## Available operations
|
|
105
170
|
|
|
106
171
|
| Module | Method | Description |
|