bytekit-sdk 0.3.0__py3-none-any.whl
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/__init__.py +8 -0
- bytekit/api/__init__.py +1 -0
- bytekit/api/account/__init__.py +1 -0
- bytekit/api/account/get_account.py +157 -0
- bytekit/api/bulk/__init__.py +1 -0
- bytekit/api/bulk/create_bulk.py +204 -0
- bytekit/api/bulk/delete_bulk.py +177 -0
- bytekit/api/bulk/get_bulk.py +157 -0
- bytekit/api/bulk/list_bulk_screenshots.py +152 -0
- bytekit/api/fetch/__init__.py +1 -0
- bytekit/api/fetch/get_fetch.py +254 -0
- bytekit/api/fetch/post_fetch.py +178 -0
- bytekit/api/fetch_bulk/__init__.py +1 -0
- bytekit/api/fetch_bulk/create_fetch_bulk.py +180 -0
- bytekit/api/fetch_bulk/get_fetch_bulk.py +157 -0
- bytekit/api/monitors/__init__.py +1 -0
- bytekit/api/monitors/create_monitor.py +180 -0
- bytekit/api/monitors/delete_monitor.py +155 -0
- bytekit/api/monitors/get_monitor.py +157 -0
- bytekit/api/monitors/list_monitor_captures.py +188 -0
- bytekit/api/monitors/list_monitors.py +193 -0
- bytekit/api/monitors/update_monitor.py +191 -0
- bytekit/api/scrape/__init__.py +1 -0
- bytekit/api/scrape/create_scrape.py +197 -0
- bytekit/api/scrape/get_scrape.py +231 -0
- bytekit/api/scrape_bulk/__init__.py +1 -0
- bytekit/api/scrape_bulk/create_scrape_bulk.py +188 -0
- bytekit/api/scrape_bulk/get_scrape_bulk.py +157 -0
- bytekit/api/screenshots/__init__.py +1 -0
- bytekit/api/screenshots/create_screenshot.py +208 -0
- bytekit/api/screenshots/get_screenshot.py +177 -0
- bytekit/api/search/__init__.py +1 -0
- bytekit/api/search/create_search.py +225 -0
- bytekit/api/sitemap/__init__.py +1 -0
- bytekit/api/sitemap/create_sitemap.py +192 -0
- bytekit/api/sitemap/get_sitemap.py +157 -0
- bytekit/api/usage/__init__.py +1 -0
- bytekit/api/usage/get_usage.py +126 -0
- bytekit/api/usage/get_usage_by_endpoint.py +215 -0
- bytekit/api/usage/get_usage_daily.py +203 -0
- bytekit/api/webhooks/__init__.py +1 -0
- bytekit/api/webhooks/list_webhook_deliveries.py +214 -0
- bytekit/api/webhooks/retry_webhook_delivery.py +165 -0
- bytekit/client.py +418 -0
- bytekit/errors.py +18 -0
- bytekit/models/__init__.py +401 -0
- bytekit/models/account_bearer_response.py +207 -0
- bytekit/models/account_bearer_response_api_key.py +134 -0
- bytekit/models/account_bearer_response_api_key_environment.py +8 -0
- bytekit/models/account_bearer_response_auto_topup.py +83 -0
- bytekit/models/account_bearer_response_plan.py +150 -0
- bytekit/models/account_bearer_response_subscription.py +85 -0
- bytekit/models/account_bearer_response_subscription_plan.py +99 -0
- bytekit/models/account_bearer_response_subscription_status.py +10 -0
- bytekit/models/account_session_response.py +164 -0
- bytekit/models/account_session_response_notifications.py +51 -0
- bytekit/models/account_session_response_plan.py +150 -0
- bytekit/models/bandwidth_balance.py +91 -0
- bytekit/models/capture_response.py +216 -0
- bytekit/models/capture_response_outcome.py +10 -0
- bytekit/models/clip.py +83 -0
- bytekit/models/cookie.py +90 -0
- bytekit/models/create_bulk_body.py +155 -0
- bytekit/models/create_bulk_body_defaults.py +423 -0
- bytekit/models/create_bulk_body_defaults_device.py +9 -0
- bytekit/models/create_bulk_body_defaults_device_scale_factor_type_1.py +9 -0
- bytekit/models/create_bulk_body_defaults_device_scale_factor_type_2_type_1.py +9 -0
- bytekit/models/create_bulk_body_defaults_device_scale_factor_type_3_type_1.py +9 -0
- bytekit/models/create_bulk_body_defaults_formats_item.py +12 -0
- bytekit/models/create_bulk_body_defaults_type.py +9 -0
- bytekit/models/create_bulk_body_defaults_viewport_type_0.py +67 -0
- bytekit/models/create_bulk_body_defaults_wait_until.py +10 -0
- bytekit/models/create_bulk_body_items_item.py +380 -0
- bytekit/models/create_bulk_body_items_item_device.py +9 -0
- bytekit/models/create_bulk_body_items_item_formats_item.py +12 -0
- bytekit/models/create_bulk_body_items_item_scenario.py +10 -0
- bytekit/models/create_bulk_body_items_item_type.py +9 -0
- bytekit/models/create_bulk_body_items_item_viewport_type_0.py +67 -0
- bytekit/models/create_bulk_body_items_item_wait_until.py +10 -0
- bytekit/models/create_bulk_response_202.py +164 -0
- bytekit/models/create_bulk_response_202_status.py +10 -0
- bytekit/models/create_fetch_bulk_body.py +161 -0
- bytekit/models/create_fetch_bulk_body_defaults.py +91 -0
- bytekit/models/create_fetch_bulk_body_defaults_format.py +9 -0
- bytekit/models/create_fetch_bulk_body_metadata.py +44 -0
- bytekit/models/create_fetch_bulk_body_urls_item_type_1.py +102 -0
- bytekit/models/create_fetch_bulk_body_urls_item_type_1_format.py +9 -0
- bytekit/models/create_fetch_bulk_response_202.py +44 -0
- bytekit/models/create_scrape_bulk_body.py +179 -0
- bytekit/models/create_scrape_bulk_body_custom.py +52 -0
- bytekit/models/create_scrape_bulk_body_defaults.py +167 -0
- bytekit/models/create_scrape_bulk_body_defaults_formats_item.py +12 -0
- bytekit/models/create_scrape_bulk_body_defaults_headers.py +44 -0
- bytekit/models/create_scrape_bulk_body_items_item.py +226 -0
- bytekit/models/create_scrape_bulk_body_items_item_custom.py +50 -0
- bytekit/models/create_scrape_bulk_body_items_item_formats_item.py +12 -0
- bytekit/models/create_scrape_bulk_body_items_item_headers.py +44 -0
- bytekit/models/create_scrape_bulk_body_items_item_metadata.py +44 -0
- bytekit/models/create_scrape_bulk_response_202.py +166 -0
- bytekit/models/create_scrape_bulk_response_202_status.py +10 -0
- bytekit/models/create_search_body.py +140 -0
- bytekit/models/create_search_body_date_range.py +13 -0
- bytekit/models/create_search_body_type.py +10 -0
- bytekit/models/create_search_response_200.py +119 -0
- bytekit/models/create_search_response_200_results_item.py +161 -0
- bytekit/models/create_search_response_200_results_item_image.py +113 -0
- bytekit/models/create_search_response_502.py +46 -0
- bytekit/models/create_search_response_502_error.py +8 -0
- bytekit/models/credit_balance.py +91 -0
- bytekit/models/delete_bulk_response_200.py +164 -0
- bytekit/models/delete_bulk_response_200_status.py +11 -0
- bytekit/models/error.py +83 -0
- bytekit/models/error_error.py +100 -0
- bytekit/models/error_status.py +8 -0
- bytekit/models/fetch_request.py +276 -0
- bytekit/models/fetch_request_cache_ttl_type_1.py +8 -0
- bytekit/models/fetch_request_custom.py +48 -0
- bytekit/models/fetch_request_format.py +9 -0
- bytekit/models/fetch_request_markdown_images.py +11 -0
- bytekit/models/fetch_request_markdown_links.py +11 -0
- bytekit/models/fetch_request_markdown_mode.py +10 -0
- bytekit/models/get_bulk_response_200.py +164 -0
- bytekit/models/get_bulk_response_200_status.py +11 -0
- bytekit/models/get_fetch_bulk_response_200.py +44 -0
- bytekit/models/get_fetch_cache_ttl_type_1.py +8 -0
- bytekit/models/get_fetch_format.py +9 -0
- bytekit/models/get_scrape_bulk_response_200.py +164 -0
- bytekit/models/get_scrape_bulk_response_200_status.py +11 -0
- bytekit/models/get_usage_by_endpoint_response_200.py +114 -0
- bytekit/models/get_usage_by_endpoint_response_200_rows_item.py +90 -0
- bytekit/models/get_usage_by_endpoint_response_200_rows_item_endpoint.py +17 -0
- bytekit/models/get_usage_by_endpoint_response_200_totals.py +67 -0
- bytekit/models/get_usage_daily_response_200.py +97 -0
- bytekit/models/get_usage_daily_response_200_data_item.py +219 -0
- bytekit/models/get_usage_response_200.py +344 -0
- bytekit/models/get_usage_response_200_plan_type.py +10 -0
- bytekit/models/list_bulk_screenshots_response_200.py +44 -0
- bytekit/models/list_monitor_captures_response_200.py +101 -0
- bytekit/models/list_monitors_response_200.py +101 -0
- bytekit/models/list_monitors_status.py +12 -0
- bytekit/models/list_webhook_deliveries_response_200.py +101 -0
- bytekit/models/list_webhook_deliveries_status.py +11 -0
- bytekit/models/metadata.py +44 -0
- bytekit/models/monitor_create_request.py +219 -0
- bytekit/models/monitor_create_request_interval_type.py +11 -0
- bytekit/models/monitor_create_request_notify_on.py +9 -0
- bytekit/models/monitor_create_request_options.py +44 -0
- bytekit/models/monitor_create_request_scrape_options.py +44 -0
- bytekit/models/monitor_create_request_type.py +9 -0
- bytekit/models/monitor_create_request_webhook_headers.py +44 -0
- bytekit/models/monitor_create_response.py +423 -0
- bytekit/models/monitor_response.py +411 -0
- bytekit/models/monitor_response_interval_type.py +11 -0
- bytekit/models/monitor_response_metadata_type_0.py +44 -0
- bytekit/models/monitor_response_status.py +12 -0
- bytekit/models/monitor_response_type.py +9 -0
- bytekit/models/monitor_response_webhook_headers_type_0.py +44 -0
- bytekit/models/monitor_update_request.py +223 -0
- bytekit/models/monitor_update_request_interval_type.py +11 -0
- bytekit/models/monitor_update_request_notify_on.py +9 -0
- bytekit/models/monitor_update_request_options.py +44 -0
- bytekit/models/monitor_update_request_scrape_options.py +44 -0
- bytekit/models/monitor_update_request_status.py +9 -0
- bytekit/models/monitor_update_request_webhook_headers.py +44 -0
- bytekit/models/scrape_error_envelope.py +113 -0
- bytekit/models/scrape_error_envelope_error.py +93 -0
- bytekit/models/scrape_error_envelope_error_code.py +18 -0
- bytekit/models/scrape_error_envelope_schema_version.py +8 -0
- bytekit/models/scrape_error_envelope_status.py +8 -0
- bytekit/models/scrape_formats.py +183 -0
- bytekit/models/scrape_markdown_tokens.py +75 -0
- bytekit/models/scrape_metadata.py +262 -0
- bytekit/models/scrape_queued_envelope.py +124 -0
- bytekit/models/scrape_queued_envelope_schema_version.py +8 -0
- bytekit/models/scrape_queued_envelope_status.py +8 -0
- bytekit/models/scrape_request.py +485 -0
- bytekit/models/scrape_request_cache_ttl_type_1.py +8 -0
- bytekit/models/scrape_request_custom.py +48 -0
- bytekit/models/scrape_request_events_item.py +10 -0
- bytekit/models/scrape_request_formats_item.py +12 -0
- bytekit/models/scrape_request_headers.py +44 -0
- bytekit/models/scrape_request_markdown_images.py +11 -0
- bytekit/models/scrape_request_markdown_links.py +11 -0
- bytekit/models/scrape_request_markdown_mode.py +10 -0
- bytekit/models/scrape_request_token_encoding.py +9 -0
- bytekit/models/scrape_request_x_internal_scrape_path.py +8 -0
- bytekit/models/scrape_scored_image.py +128 -0
- bytekit/models/scrape_scored_link.py +94 -0
- bytekit/models/scrape_stats.py +75 -0
- bytekit/models/scrape_success_envelope.py +345 -0
- bytekit/models/scrape_success_envelope_cache.py +10 -0
- bytekit/models/scrape_success_envelope_custom.py +48 -0
- bytekit/models/scrape_success_envelope_schema_version.py +8 -0
- bytekit/models/scrape_success_envelope_status.py +8 -0
- bytekit/models/scrape_table.py +96 -0
- bytekit/models/scrape_table_kind.py +10 -0
- bytekit/models/scrape_warning.py +88 -0
- bytekit/models/scrape_warning_code.py +17 -0
- bytekit/models/screenshot_request.py +445 -0
- bytekit/models/screenshot_request_device.py +9 -0
- bytekit/models/screenshot_request_device_scale_factor_type_1.py +9 -0
- bytekit/models/screenshot_request_device_scale_factor_type_2_type_1.py +9 -0
- bytekit/models/screenshot_request_device_scale_factor_type_3_type_1.py +9 -0
- bytekit/models/screenshot_request_format.py +9 -0
- bytekit/models/screenshot_request_headers.py +44 -0
- bytekit/models/screenshot_request_wait_until.py +10 -0
- bytekit/models/screenshot_response.py +264 -0
- bytekit/models/screenshot_response_status.py +11 -0
- bytekit/models/sitemap_request.py +210 -0
- bytekit/models/sitemap_request_process_type_0.py +90 -0
- bytekit/models/sitemap_request_process_type_0_options.py +44 -0
- bytekit/models/sitemap_request_strategy.py +10 -0
- bytekit/models/sitemap_response.py +418 -0
- bytekit/models/sitemap_response_cache.py +10 -0
- bytekit/models/sitemap_response_metadata_type_0.py +44 -0
- bytekit/models/sitemap_response_process_type_0.py +44 -0
- bytekit/models/sitemap_response_sources_type_0.py +44 -0
- bytekit/models/sitemap_response_status.py +11 -0
- bytekit/models/viewport.py +67 -0
- bytekit/models/webhook_delivery_response.py +270 -0
- bytekit/models/webhook_delivery_response_event_type.py +14 -0
- bytekit/models/webhook_delivery_response_status.py +11 -0
- bytekit/py.typed +0 -0
- bytekit/types.py +54 -0
- bytekit_sdk-0.3.0.dist-info/METADATA +141 -0
- bytekit_sdk-0.3.0.dist-info/RECORD +227 -0
- bytekit_sdk-0.3.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
from collections.abc import Mapping
|
|
3
|
+
from typing import (
|
|
4
|
+
Any,
|
|
5
|
+
TypeVar,
|
|
6
|
+
Union,
|
|
7
|
+
cast,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from attrs import define as _attrs_define
|
|
11
|
+
from attrs import field as _attrs_field
|
|
12
|
+
from dateutil.parser import isoparse
|
|
13
|
+
|
|
14
|
+
from ..models.webhook_delivery_response_event_type import (
|
|
15
|
+
WebhookDeliveryResponseEventType,
|
|
16
|
+
)
|
|
17
|
+
from ..models.webhook_delivery_response_status import WebhookDeliveryResponseStatus
|
|
18
|
+
|
|
19
|
+
T = TypeVar("T", bound="WebhookDeliveryResponse")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@_attrs_define
|
|
23
|
+
class WebhookDeliveryResponse:
|
|
24
|
+
"""
|
|
25
|
+
Attributes:
|
|
26
|
+
id (str): Example: wh_01j9abc123.
|
|
27
|
+
event_type (WebhookDeliveryResponseEventType): Machine-readable event discriminator. This value is also sent as
|
|
28
|
+
the `X-ByteKit-Event` request header on every outbound webhook delivery, allowing receivers to dispatch on the
|
|
29
|
+
header without parsing the body shape.
|
|
30
|
+
Example: bulk.completed.
|
|
31
|
+
target_url (str):
|
|
32
|
+
status (WebhookDeliveryResponseStatus):
|
|
33
|
+
attempts (int):
|
|
34
|
+
max_attempts (int):
|
|
35
|
+
next_attempt_at (Union[None, datetime.datetime]):
|
|
36
|
+
response_status (Union[None, int]):
|
|
37
|
+
response_ms (Union[None, int]):
|
|
38
|
+
created_at (datetime.datetime):
|
|
39
|
+
delivered_at (Union[None, datetime.datetime]):
|
|
40
|
+
screenshot_id (Union[None, str]):
|
|
41
|
+
recording_id (Union[None, str]):
|
|
42
|
+
bulk_id (Union[None, str]):
|
|
43
|
+
monitor_id (Union[None, str]):
|
|
44
|
+
scrape_id (Union[None, str]):
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
id: str
|
|
48
|
+
event_type: WebhookDeliveryResponseEventType
|
|
49
|
+
target_url: str
|
|
50
|
+
status: WebhookDeliveryResponseStatus
|
|
51
|
+
attempts: int
|
|
52
|
+
max_attempts: int
|
|
53
|
+
next_attempt_at: Union[None, datetime.datetime]
|
|
54
|
+
response_status: Union[None, int]
|
|
55
|
+
response_ms: Union[None, int]
|
|
56
|
+
created_at: datetime.datetime
|
|
57
|
+
delivered_at: Union[None, datetime.datetime]
|
|
58
|
+
screenshot_id: Union[None, str]
|
|
59
|
+
recording_id: Union[None, str]
|
|
60
|
+
bulk_id: Union[None, str]
|
|
61
|
+
monitor_id: Union[None, str]
|
|
62
|
+
scrape_id: Union[None, str]
|
|
63
|
+
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
|
|
64
|
+
|
|
65
|
+
def to_dict(self) -> dict[str, Any]:
|
|
66
|
+
id = self.id
|
|
67
|
+
|
|
68
|
+
event_type = self.event_type.value
|
|
69
|
+
|
|
70
|
+
target_url = self.target_url
|
|
71
|
+
|
|
72
|
+
status = self.status.value
|
|
73
|
+
|
|
74
|
+
attempts = self.attempts
|
|
75
|
+
|
|
76
|
+
max_attempts = self.max_attempts
|
|
77
|
+
|
|
78
|
+
next_attempt_at: Union[None, str]
|
|
79
|
+
if isinstance(self.next_attempt_at, datetime.datetime):
|
|
80
|
+
next_attempt_at = self.next_attempt_at.isoformat()
|
|
81
|
+
else:
|
|
82
|
+
next_attempt_at = self.next_attempt_at
|
|
83
|
+
|
|
84
|
+
response_status: Union[None, int]
|
|
85
|
+
response_status = self.response_status
|
|
86
|
+
|
|
87
|
+
response_ms: Union[None, int]
|
|
88
|
+
response_ms = self.response_ms
|
|
89
|
+
|
|
90
|
+
created_at = self.created_at.isoformat()
|
|
91
|
+
|
|
92
|
+
delivered_at: Union[None, str]
|
|
93
|
+
if isinstance(self.delivered_at, datetime.datetime):
|
|
94
|
+
delivered_at = self.delivered_at.isoformat()
|
|
95
|
+
else:
|
|
96
|
+
delivered_at = self.delivered_at
|
|
97
|
+
|
|
98
|
+
screenshot_id: Union[None, str]
|
|
99
|
+
screenshot_id = self.screenshot_id
|
|
100
|
+
|
|
101
|
+
recording_id: Union[None, str]
|
|
102
|
+
recording_id = self.recording_id
|
|
103
|
+
|
|
104
|
+
bulk_id: Union[None, str]
|
|
105
|
+
bulk_id = self.bulk_id
|
|
106
|
+
|
|
107
|
+
monitor_id: Union[None, str]
|
|
108
|
+
monitor_id = self.monitor_id
|
|
109
|
+
|
|
110
|
+
scrape_id: Union[None, str]
|
|
111
|
+
scrape_id = self.scrape_id
|
|
112
|
+
|
|
113
|
+
field_dict: dict[str, Any] = {}
|
|
114
|
+
field_dict.update(self.additional_properties)
|
|
115
|
+
field_dict.update(
|
|
116
|
+
{
|
|
117
|
+
"id": id,
|
|
118
|
+
"event_type": event_type,
|
|
119
|
+
"target_url": target_url,
|
|
120
|
+
"status": status,
|
|
121
|
+
"attempts": attempts,
|
|
122
|
+
"max_attempts": max_attempts,
|
|
123
|
+
"next_attempt_at": next_attempt_at,
|
|
124
|
+
"response_status": response_status,
|
|
125
|
+
"response_ms": response_ms,
|
|
126
|
+
"created_at": created_at,
|
|
127
|
+
"delivered_at": delivered_at,
|
|
128
|
+
"screenshot_id": screenshot_id,
|
|
129
|
+
"recording_id": recording_id,
|
|
130
|
+
"bulk_id": bulk_id,
|
|
131
|
+
"monitor_id": monitor_id,
|
|
132
|
+
"scrape_id": scrape_id,
|
|
133
|
+
}
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
return field_dict
|
|
137
|
+
|
|
138
|
+
@classmethod
|
|
139
|
+
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
|
|
140
|
+
d = dict(src_dict)
|
|
141
|
+
id = d.pop("id")
|
|
142
|
+
|
|
143
|
+
event_type = WebhookDeliveryResponseEventType(d.pop("event_type"))
|
|
144
|
+
|
|
145
|
+
target_url = d.pop("target_url")
|
|
146
|
+
|
|
147
|
+
status = WebhookDeliveryResponseStatus(d.pop("status"))
|
|
148
|
+
|
|
149
|
+
attempts = d.pop("attempts")
|
|
150
|
+
|
|
151
|
+
max_attempts = d.pop("max_attempts")
|
|
152
|
+
|
|
153
|
+
def _parse_next_attempt_at(data: object) -> Union[None, datetime.datetime]:
|
|
154
|
+
if data is None:
|
|
155
|
+
return data
|
|
156
|
+
try:
|
|
157
|
+
if not isinstance(data, str):
|
|
158
|
+
raise TypeError()
|
|
159
|
+
next_attempt_at_type_0 = isoparse(data)
|
|
160
|
+
|
|
161
|
+
return next_attempt_at_type_0
|
|
162
|
+
except: # noqa: E722
|
|
163
|
+
pass
|
|
164
|
+
return cast(Union[None, datetime.datetime], data)
|
|
165
|
+
|
|
166
|
+
next_attempt_at = _parse_next_attempt_at(d.pop("next_attempt_at"))
|
|
167
|
+
|
|
168
|
+
def _parse_response_status(data: object) -> Union[None, int]:
|
|
169
|
+
if data is None:
|
|
170
|
+
return data
|
|
171
|
+
return cast(Union[None, int], data)
|
|
172
|
+
|
|
173
|
+
response_status = _parse_response_status(d.pop("response_status"))
|
|
174
|
+
|
|
175
|
+
def _parse_response_ms(data: object) -> Union[None, int]:
|
|
176
|
+
if data is None:
|
|
177
|
+
return data
|
|
178
|
+
return cast(Union[None, int], data)
|
|
179
|
+
|
|
180
|
+
response_ms = _parse_response_ms(d.pop("response_ms"))
|
|
181
|
+
|
|
182
|
+
created_at = isoparse(d.pop("created_at"))
|
|
183
|
+
|
|
184
|
+
def _parse_delivered_at(data: object) -> Union[None, datetime.datetime]:
|
|
185
|
+
if data is None:
|
|
186
|
+
return data
|
|
187
|
+
try:
|
|
188
|
+
if not isinstance(data, str):
|
|
189
|
+
raise TypeError()
|
|
190
|
+
delivered_at_type_0 = isoparse(data)
|
|
191
|
+
|
|
192
|
+
return delivered_at_type_0
|
|
193
|
+
except: # noqa: E722
|
|
194
|
+
pass
|
|
195
|
+
return cast(Union[None, datetime.datetime], data)
|
|
196
|
+
|
|
197
|
+
delivered_at = _parse_delivered_at(d.pop("delivered_at"))
|
|
198
|
+
|
|
199
|
+
def _parse_screenshot_id(data: object) -> Union[None, str]:
|
|
200
|
+
if data is None:
|
|
201
|
+
return data
|
|
202
|
+
return cast(Union[None, str], data)
|
|
203
|
+
|
|
204
|
+
screenshot_id = _parse_screenshot_id(d.pop("screenshot_id"))
|
|
205
|
+
|
|
206
|
+
def _parse_recording_id(data: object) -> Union[None, str]:
|
|
207
|
+
if data is None:
|
|
208
|
+
return data
|
|
209
|
+
return cast(Union[None, str], data)
|
|
210
|
+
|
|
211
|
+
recording_id = _parse_recording_id(d.pop("recording_id"))
|
|
212
|
+
|
|
213
|
+
def _parse_bulk_id(data: object) -> Union[None, str]:
|
|
214
|
+
if data is None:
|
|
215
|
+
return data
|
|
216
|
+
return cast(Union[None, str], data)
|
|
217
|
+
|
|
218
|
+
bulk_id = _parse_bulk_id(d.pop("bulk_id"))
|
|
219
|
+
|
|
220
|
+
def _parse_monitor_id(data: object) -> Union[None, str]:
|
|
221
|
+
if data is None:
|
|
222
|
+
return data
|
|
223
|
+
return cast(Union[None, str], data)
|
|
224
|
+
|
|
225
|
+
monitor_id = _parse_monitor_id(d.pop("monitor_id"))
|
|
226
|
+
|
|
227
|
+
def _parse_scrape_id(data: object) -> Union[None, str]:
|
|
228
|
+
if data is None:
|
|
229
|
+
return data
|
|
230
|
+
return cast(Union[None, str], data)
|
|
231
|
+
|
|
232
|
+
scrape_id = _parse_scrape_id(d.pop("scrape_id"))
|
|
233
|
+
|
|
234
|
+
webhook_delivery_response = cls(
|
|
235
|
+
id=id,
|
|
236
|
+
event_type=event_type,
|
|
237
|
+
target_url=target_url,
|
|
238
|
+
status=status,
|
|
239
|
+
attempts=attempts,
|
|
240
|
+
max_attempts=max_attempts,
|
|
241
|
+
next_attempt_at=next_attempt_at,
|
|
242
|
+
response_status=response_status,
|
|
243
|
+
response_ms=response_ms,
|
|
244
|
+
created_at=created_at,
|
|
245
|
+
delivered_at=delivered_at,
|
|
246
|
+
screenshot_id=screenshot_id,
|
|
247
|
+
recording_id=recording_id,
|
|
248
|
+
bulk_id=bulk_id,
|
|
249
|
+
monitor_id=monitor_id,
|
|
250
|
+
scrape_id=scrape_id,
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
webhook_delivery_response.additional_properties = d
|
|
254
|
+
return webhook_delivery_response
|
|
255
|
+
|
|
256
|
+
@property
|
|
257
|
+
def additional_keys(self) -> list[str]:
|
|
258
|
+
return list(self.additional_properties.keys())
|
|
259
|
+
|
|
260
|
+
def __getitem__(self, key: str) -> Any:
|
|
261
|
+
return self.additional_properties[key]
|
|
262
|
+
|
|
263
|
+
def __setitem__(self, key: str, value: Any) -> None:
|
|
264
|
+
self.additional_properties[key] = value
|
|
265
|
+
|
|
266
|
+
def __delitem__(self, key: str) -> None:
|
|
267
|
+
del self.additional_properties[key]
|
|
268
|
+
|
|
269
|
+
def __contains__(self, key: str) -> bool:
|
|
270
|
+
return key in self.additional_properties
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class WebhookDeliveryResponseEventType(str, Enum):
|
|
5
|
+
BULK_COMPLETED = "bulk.completed"
|
|
6
|
+
MONITOR_CAPTURED = "monitor.captured"
|
|
7
|
+
MONITOR_CHANGE_DETECTED = "monitor.change_detected"
|
|
8
|
+
SCRAPE_COMPLETED = "scrape.completed"
|
|
9
|
+
SCRAPE_FAILED = "scrape.failed"
|
|
10
|
+
SITEMAP_COMPLETED = "sitemap.completed"
|
|
11
|
+
SITEMAP_FAILED = "sitemap.failed"
|
|
12
|
+
|
|
13
|
+
def __str__(self) -> str:
|
|
14
|
+
return str(self.value)
|
bytekit/py.typed
ADDED
|
File without changes
|
bytekit/types.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""Contains some shared types for properties"""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Mapping, MutableMapping
|
|
4
|
+
from http import HTTPStatus
|
|
5
|
+
from typing import IO, BinaryIO, Generic, Literal, Optional, TypeVar, Union
|
|
6
|
+
|
|
7
|
+
from attrs import define
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Unset:
|
|
11
|
+
def __bool__(self) -> Literal[False]:
|
|
12
|
+
return False
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
UNSET: Unset = Unset()
|
|
16
|
+
|
|
17
|
+
# The types that `httpx.Client(files=)` can accept, copied from that library.
|
|
18
|
+
FileContent = Union[IO[bytes], bytes, str]
|
|
19
|
+
FileTypes = Union[
|
|
20
|
+
# (filename, file (or bytes), content_type)
|
|
21
|
+
tuple[Optional[str], FileContent, Optional[str]],
|
|
22
|
+
# (filename, file (or bytes), content_type, headers)
|
|
23
|
+
tuple[Optional[str], FileContent, Optional[str], Mapping[str, str]],
|
|
24
|
+
]
|
|
25
|
+
RequestFiles = list[tuple[str, FileTypes]]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@define
|
|
29
|
+
class File:
|
|
30
|
+
"""Contains information for file uploads"""
|
|
31
|
+
|
|
32
|
+
payload: BinaryIO
|
|
33
|
+
file_name: Optional[str] = None
|
|
34
|
+
mime_type: Optional[str] = None
|
|
35
|
+
|
|
36
|
+
def to_tuple(self) -> FileTypes:
|
|
37
|
+
"""Return a tuple representation that httpx will accept for multipart/form-data"""
|
|
38
|
+
return self.file_name, self.payload, self.mime_type
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
T = TypeVar("T")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@define
|
|
45
|
+
class Response(Generic[T]):
|
|
46
|
+
"""A response from an endpoint"""
|
|
47
|
+
|
|
48
|
+
status_code: HTTPStatus
|
|
49
|
+
content: bytes
|
|
50
|
+
headers: MutableMapping[str, str]
|
|
51
|
+
parsed: Optional[T]
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
__all__ = ["UNSET", "File", "FileTypes", "RequestFiles", "Response", "Unset"]
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: bytekit-sdk
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Official Python SDK for the ByteKit API
|
|
5
|
+
Project-URL: Homepage, https://bytekit.com
|
|
6
|
+
Project-URL: Repository, https://github.com/Hunt-Labs-Inc/ByteKit
|
|
7
|
+
Project-URL: Documentation, https://bytekit.com/docs
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
Keywords: api,bytekit,crawler,llm,markdown,scraping,screenshots,sdk,web-scraping
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
|
+
Classifier: Typing :: Typed
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Requires-Dist: attrs>=23.1.0
|
|
22
|
+
Requires-Dist: httpx>=0.24.0
|
|
23
|
+
Requires-Dist: python-dateutil>=2.8.0
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
# bytekit-sdk
|
|
27
|
+
|
|
28
|
+
Official Python SDK for the [ByteKit API](https://bytekit.com).
|
|
29
|
+
|
|
30
|
+
The PyPI **distribution** is `bytekit-sdk`; the **import** name is `bytekit`.
|
|
31
|
+
|
|
32
|
+
Generated from the OpenAPI spec using [openapi-python-client](https://github.com/openapi-generators/openapi-python-client), filtered to the stable v0.1 operations.
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install bytekit-sdk
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Quick start
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
from bytekit import AuthenticatedClient
|
|
44
|
+
from bytekit.api.scrape import create_scrape
|
|
45
|
+
from bytekit.errors import UnexpectedStatus
|
|
46
|
+
from bytekit.models.scrape_request import ScrapeRequest
|
|
47
|
+
|
|
48
|
+
# base_url defaults to https://api.bytekit.com, so only the token is required.
|
|
49
|
+
client = AuthenticatedClient(token="sk_live_your_api_key_here")
|
|
50
|
+
|
|
51
|
+
body = ScrapeRequest(url="https://example.com")
|
|
52
|
+
|
|
53
|
+
try:
|
|
54
|
+
response = create_scrape.sync(client=client, body=body)
|
|
55
|
+
# response.formats.markdown is str | Unset — only present when "markdown" was requested
|
|
56
|
+
print(response.formats.markdown)
|
|
57
|
+
except UnexpectedStatus as err:
|
|
58
|
+
# Errors now raise loudly by default instead of returning None.
|
|
59
|
+
print(f"request failed with status {err.status_code}: {err.code} {err.message}")
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Defaults
|
|
63
|
+
|
|
64
|
+
The client ships with production-ready defaults so `AuthenticatedClient(token=...)` works out of the box:
|
|
65
|
+
|
|
66
|
+
| Setting | Default | Notes |
|
|
67
|
+
| ---------------------------- | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
68
|
+
| `base_url` | `https://api.bytekit.com` | Pass `base_url=` to target staging or a proxy. |
|
|
69
|
+
| `timeout` | `120s` (`httpx.Timeout(120.0)`) | Finite by default — requests no longer hang indefinitely. Pass `timeout=` to override. |
|
|
70
|
+
| `raise_on_unexpected_status` | `True` | Undocumented statuses raise `errors.UnexpectedStatus` instead of silently returning `None`. Pass `raise_on_unexpected_status=False` to restore the old opt-out. |
|
|
71
|
+
|
|
72
|
+
Explicit constructor arguments always win over these defaults (explicit arg > default).
|
|
73
|
+
|
|
74
|
+
## Async usage
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
import asyncio
|
|
78
|
+
from bytekit import AuthenticatedClient
|
|
79
|
+
from bytekit.api.screenshots import create_screenshot
|
|
80
|
+
from bytekit.models.screenshot_request import ScreenshotRequest
|
|
81
|
+
|
|
82
|
+
async def main():
|
|
83
|
+
client = AuthenticatedClient(token="sk_live_your_api_key_here")
|
|
84
|
+
body = ScreenshotRequest(url="https://example.com")
|
|
85
|
+
response = await create_screenshot.asyncio(client=client, body=body)
|
|
86
|
+
print(response)
|
|
87
|
+
|
|
88
|
+
asyncio.run(main())
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Available operations
|
|
92
|
+
|
|
93
|
+
| Module | Method | Description |
|
|
94
|
+
| ----------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------ |
|
|
95
|
+
| `api.scrape` | `create_scrape`, `get_scrape` | Web content extraction |
|
|
96
|
+
| `api.screenshots` | `create_screenshot`, `get_screenshot` | Page screenshots |
|
|
97
|
+
| `api.bulk` | `create_bulk`, `get_bulk`, `delete_bulk`, `list_bulk_screenshots` | Bulk screenshot jobs |
|
|
98
|
+
| `api.scrape_bulk` | `create_scrape_bulk`, `get_scrape_bulk` | Bulk scrape jobs |
|
|
99
|
+
| `api.fetch` | `get_fetch`, `post_fetch` | Raw HTTP fetch |
|
|
100
|
+
| `api.fetch_bulk` | `create_fetch_bulk`, `get_fetch_bulk` | Bulk fetch jobs |
|
|
101
|
+
| `api.monitors` | `create_monitor`, `list_monitors`, `get_monitor`, `update_monitor`, `delete_monitor`, `list_monitor_captures` | Page-change monitors (screenshot + scrape) |
|
|
102
|
+
| `api.sitemap` | `create_sitemap`, `get_sitemap` | Sitemap crawl |
|
|
103
|
+
| `api.search` | `create_search` (or the `AuthenticatedClient.search(...)` convenience method) | Web search |
|
|
104
|
+
| `api.usage` | `get_usage`, `get_usage_daily`, `get_usage_by_endpoint` | Account usage & billing |
|
|
105
|
+
| `api.webhooks` | `list_webhook_deliveries`, `retry_webhook_delivery` | Webhook delivery log & retry |
|
|
106
|
+
| `api.account` | `get_account` | Account details |
|
|
107
|
+
|
|
108
|
+
## Regenerating
|
|
109
|
+
|
|
110
|
+
To regenerate the client after API changes:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
pnpm --filter @bytekit/sdk-python generate
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
This runs `scripts/filter-spec.ts` to produce `filtered-openapi.yaml` (filtered to v0.1 operations), runs `scripts/prune-stale-api.py` to delete any `src/bytekit/api/<tag>/` directory the filtered spec no longer produces (`generate --overwrite` itself already rebuilds `api/` from scratch on every run, so this step is defense-in-depth for a standalone run of the prune script or a future generator version — the path that actually needs the guard is `pnpm generate:docs`, which enumerates `api/` on disk independent of `generate` and can otherwise resurrect a tag whose tracked files were `git rm`-ed but whose untracked `__pycache__/` survives; see `scripts/prune-stale-api.py`'s module docstring and `has_operations()` in `scripts/generate-docs.py`), invokes `openapi-python-client generate` to update `src/bytekit/`, then runs `scripts/inject-handwritten.py` to re-append hand-written fragments (e.g. the `AuthenticatedClient.search()` convenience method) from `scripts/hand_written/` and re-patch the generated `client.py`/`errors.py` with the runtime defaults and error enrichment described above — because `--overwrite` overwrites every file it emits, both the hand-written code and these patches are wiped on every regen and must be re-applied afterward.
|
|
117
|
+
|
|
118
|
+
## Development
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
# Run tests
|
|
122
|
+
cd packages/sdk-python
|
|
123
|
+
python3 -m pytest tests/ -v
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Publishing
|
|
127
|
+
|
|
128
|
+
PyPI publish is handled in [#2226](https://github.com/Hunt-Labs-Inc/ByteKit/issues/2226) —
|
|
129
|
+
`.woodpecker/publish.yaml`'s `publish-pypi` step, version-gated the same way as the npm
|
|
130
|
+
siblings (publishes only when the local `pyproject.toml` version differs from what's live on
|
|
131
|
+
PyPI).
|
|
132
|
+
|
|
133
|
+
**`bytekit-sdk` has never been published.** Before the commit that arms
|
|
134
|
+
`packages/sdk-python/pyproject.toml` in `publish.yaml`'s workflow-level `when.path.include` is
|
|
135
|
+
promoted from `staging` to `main`, an operator MUST publish `0.3.0` to PyPI manually and under
|
|
136
|
+
supervision. Reason: bytekit-sdk 404s on PyPI today, so the automatic version-compare gate's
|
|
137
|
+
`|| echo "0.0.0"` fallback always fires — the first time that arming reaches `main`, it would
|
|
138
|
+
trigger a real, irreversible first `twine upload` with no manual confirmation step in between.
|
|
139
|
+
Once the manual first release exists, PUBLISHED == CURRENT and every later automatic run at an
|
|
140
|
+
unchanged version is a no-op, same as the npm packages. See the comment at the armed
|
|
141
|
+
`when.path.include` entry in `.woodpecker/publish.yaml` for the mechanism.
|