diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2292ca70..d486cde7 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.95.0" + ".": "0.96.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 6416998e..f4fdbc82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.96.0](https://github.com/kernel/kernel-python-sdk/compare/v0.95.0...v0.96.0) (2026-08-27) + + +### Features + +* Rename the site configs API to config registry ([114c986](https://github.com/kernel/kernel-python-sdk/commit/114c986f0d771049ec09741c65e0be317c98f718)) + ## [0.95.0](https://github.com/kernel/kernel-python-sdk/compare/v0.94.0...v0.95.0) (2026-08-26) diff --git a/api.md b/api.md index 60493a41..d5cdf897 100644 --- a/api.md +++ b/api.md @@ -74,7 +74,7 @@ Methods: - client.invocations.follow(id, \*\*params) -> InvocationFollowResponse - client.invocations.list_browsers(id) -> InvocationListBrowsersResponse -# SiteConfigs +# ConfigRegistry Types: @@ -83,6 +83,7 @@ from kernel.types import ( Analysis, AnalysisSummary, Browser, + ConfigRegistryResponse, Evidence, LookupRequest, LookupResponse, @@ -92,18 +93,22 @@ from kernel.types import ( RecommendationResult, RecommendationSummary, ResolveRequest, - SiteConfigResponse, Target, ) ``` Methods: -- client.site_configs.retrieve(id) -> SiteConfigResponse -- client.site_configs.list(\*\*params) -> SyncOffsetPagination[AnalysisSummary] -- client.site_configs.list_recommendations(\*\*params) -> SyncOffsetPagination[RecommendationSummary] -- client.site_configs.lookup(\*\*params) -> LookupResponse -- client.site_configs.resolve(\*\*params) -> SiteConfigResponse +- client.config_registry.list(\*\*params) -> SyncOffsetPagination[RecommendationSummary] +- client.config_registry.lookup(\*\*params) -> LookupResponse +- client.config_registry.resolve(\*\*params) -> ConfigRegistryResponse + +## Analyses + +Methods: + +- client.config_registry.analyses.retrieve(id) -> ConfigRegistryResponse +- client.config_registry.analyses.list(\*\*params) -> SyncOffsetPagination[AnalysisSummary] # Browsers diff --git a/pyproject.toml b/pyproject.toml index d7125601..32520ba7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "kernel" -version = "0.95.0" +version = "0.96.0" description = "The official Python library for the kernel API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/kernel/_client.py b/src/kernel/_client.py index d96b5804..2c06cb04 100644 --- a/src/kernel/_client.py +++ b/src/kernel/_client.py @@ -62,8 +62,8 @@ deployments, invocations, organization, - site_configs, browser_pools, + config_registry, credential_providers, ) from .resources.apps import AppsResource, AsyncAppsResource @@ -75,7 +75,6 @@ from .resources.credentials import CredentialsResource, AsyncCredentialsResource from .resources.deployments import DeploymentsResource, AsyncDeploymentsResource from .resources.invocations import InvocationsResource, AsyncInvocationsResource - from .resources.site_configs import SiteConfigsResource, AsyncSiteConfigsResource from .resources.browser_pools import BrowserPoolsResource, AsyncBrowserPoolsResource from .resources.browsers.browsers import BrowsersResource, AsyncBrowsersResource from .resources.projects.projects import ProjectsResource, AsyncProjectsResource @@ -83,6 +82,7 @@ from .resources.credential_providers import CredentialProvidersResource, AsyncCredentialProvidersResource from .resources.audit_logs.audit_logs import AuditLogsResource, AsyncAuditLogsResource from .resources.organization.organization import OrganizationResource, AsyncOrganizationResource + from .resources.config_registry.config_registry import ConfigRegistryResource, AsyncConfigRegistryResource __all__ = [ "ENVIRONMENTS", @@ -226,11 +226,11 @@ def invocations(self) -> InvocationsResource: return InvocationsResource(self) @cached_property - def site_configs(self) -> SiteConfigsResource: + def config_registry(self) -> ConfigRegistryResource: """Resolve browser and proxy recommendations for bot-protected sites.""" - from .resources.site_configs import SiteConfigsResource + from .resources.config_registry import ConfigRegistryResource - return SiteConfigsResource(self) + return ConfigRegistryResource(self) @cached_property def browsers(self) -> BrowsersResource: @@ -609,11 +609,11 @@ def invocations(self) -> AsyncInvocationsResource: return AsyncInvocationsResource(self) @cached_property - def site_configs(self) -> AsyncSiteConfigsResource: + def config_registry(self) -> AsyncConfigRegistryResource: """Resolve browser and proxy recommendations for bot-protected sites.""" - from .resources.site_configs import AsyncSiteConfigsResource + from .resources.config_registry import AsyncConfigRegistryResource - return AsyncSiteConfigsResource(self) + return AsyncConfigRegistryResource(self) @cached_property def browsers(self) -> AsyncBrowsersResource: @@ -896,11 +896,11 @@ def invocations(self) -> invocations.InvocationsResourceWithRawResponse: return InvocationsResourceWithRawResponse(self._client.invocations) @cached_property - def site_configs(self) -> site_configs.SiteConfigsResourceWithRawResponse: + def config_registry(self) -> config_registry.ConfigRegistryResourceWithRawResponse: """Resolve browser and proxy recommendations for bot-protected sites.""" - from .resources.site_configs import SiteConfigsResourceWithRawResponse + from .resources.config_registry import ConfigRegistryResourceWithRawResponse - return SiteConfigsResourceWithRawResponse(self._client.site_configs) + return ConfigRegistryResourceWithRawResponse(self._client.config_registry) @cached_property def browsers(self) -> browsers.BrowsersResourceWithRawResponse: @@ -1023,11 +1023,11 @@ def invocations(self) -> invocations.AsyncInvocationsResourceWithRawResponse: return AsyncInvocationsResourceWithRawResponse(self._client.invocations) @cached_property - def site_configs(self) -> site_configs.AsyncSiteConfigsResourceWithRawResponse: + def config_registry(self) -> config_registry.AsyncConfigRegistryResourceWithRawResponse: """Resolve browser and proxy recommendations for bot-protected sites.""" - from .resources.site_configs import AsyncSiteConfigsResourceWithRawResponse + from .resources.config_registry import AsyncConfigRegistryResourceWithRawResponse - return AsyncSiteConfigsResourceWithRawResponse(self._client.site_configs) + return AsyncConfigRegistryResourceWithRawResponse(self._client.config_registry) @cached_property def browsers(self) -> browsers.AsyncBrowsersResourceWithRawResponse: @@ -1150,11 +1150,11 @@ def invocations(self) -> invocations.InvocationsResourceWithStreamingResponse: return InvocationsResourceWithStreamingResponse(self._client.invocations) @cached_property - def site_configs(self) -> site_configs.SiteConfigsResourceWithStreamingResponse: + def config_registry(self) -> config_registry.ConfigRegistryResourceWithStreamingResponse: """Resolve browser and proxy recommendations for bot-protected sites.""" - from .resources.site_configs import SiteConfigsResourceWithStreamingResponse + from .resources.config_registry import ConfigRegistryResourceWithStreamingResponse - return SiteConfigsResourceWithStreamingResponse(self._client.site_configs) + return ConfigRegistryResourceWithStreamingResponse(self._client.config_registry) @cached_property def browsers(self) -> browsers.BrowsersResourceWithStreamingResponse: @@ -1277,11 +1277,11 @@ def invocations(self) -> invocations.AsyncInvocationsResourceWithStreamingRespon return AsyncInvocationsResourceWithStreamingResponse(self._client.invocations) @cached_property - def site_configs(self) -> site_configs.AsyncSiteConfigsResourceWithStreamingResponse: + def config_registry(self) -> config_registry.AsyncConfigRegistryResourceWithStreamingResponse: """Resolve browser and proxy recommendations for bot-protected sites.""" - from .resources.site_configs import AsyncSiteConfigsResourceWithStreamingResponse + from .resources.config_registry import AsyncConfigRegistryResourceWithStreamingResponse - return AsyncSiteConfigsResourceWithStreamingResponse(self._client.site_configs) + return AsyncConfigRegistryResourceWithStreamingResponse(self._client.config_registry) @cached_property def browsers(self) -> browsers.AsyncBrowsersResourceWithStreamingResponse: diff --git a/src/kernel/_version.py b/src/kernel/_version.py index 258c1cb0..428f45a2 100644 --- a/src/kernel/_version.py +++ b/src/kernel/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "kernel" -__version__ = "0.95.0" # x-release-please-version +__version__ = "0.96.0" # x-release-please-version diff --git a/src/kernel/resources/__init__.py b/src/kernel/resources/__init__.py index 2ec29c9c..c6496534 100644 --- a/src/kernel/resources/__init__.py +++ b/src/kernel/resources/__init__.py @@ -112,14 +112,6 @@ OrganizationResourceWithStreamingResponse, AsyncOrganizationResourceWithStreamingResponse, ) -from .site_configs import ( - SiteConfigsResource, - AsyncSiteConfigsResource, - SiteConfigsResourceWithRawResponse, - AsyncSiteConfigsResourceWithRawResponse, - SiteConfigsResourceWithStreamingResponse, - AsyncSiteConfigsResourceWithStreamingResponse, -) from .browser_pools import ( BrowserPoolsResource, AsyncBrowserPoolsResource, @@ -128,6 +120,14 @@ BrowserPoolsResourceWithStreamingResponse, AsyncBrowserPoolsResourceWithStreamingResponse, ) +from .config_registry import ( + ConfigRegistryResource, + AsyncConfigRegistryResource, + ConfigRegistryResourceWithRawResponse, + AsyncConfigRegistryResourceWithRawResponse, + ConfigRegistryResourceWithStreamingResponse, + AsyncConfigRegistryResourceWithStreamingResponse, +) from .credential_providers import ( CredentialProvidersResource, AsyncCredentialProvidersResource, @@ -156,12 +156,12 @@ "AsyncInvocationsResourceWithRawResponse", "InvocationsResourceWithStreamingResponse", "AsyncInvocationsResourceWithStreamingResponse", - "SiteConfigsResource", - "AsyncSiteConfigsResource", - "SiteConfigsResourceWithRawResponse", - "AsyncSiteConfigsResourceWithRawResponse", - "SiteConfigsResourceWithStreamingResponse", - "AsyncSiteConfigsResourceWithStreamingResponse", + "ConfigRegistryResource", + "AsyncConfigRegistryResource", + "ConfigRegistryResourceWithRawResponse", + "AsyncConfigRegistryResourceWithRawResponse", + "ConfigRegistryResourceWithStreamingResponse", + "AsyncConfigRegistryResourceWithStreamingResponse", "BrowsersResource", "AsyncBrowsersResource", "BrowsersResourceWithRawResponse", diff --git a/src/kernel/resources/config_registry/__init__.py b/src/kernel/resources/config_registry/__init__.py new file mode 100644 index 00000000..9e904868 --- /dev/null +++ b/src/kernel/resources/config_registry/__init__.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .analyses import ( + AnalysesResource, + AsyncAnalysesResource, + AnalysesResourceWithRawResponse, + AsyncAnalysesResourceWithRawResponse, + AnalysesResourceWithStreamingResponse, + AsyncAnalysesResourceWithStreamingResponse, +) +from .config_registry import ( + ConfigRegistryResource, + AsyncConfigRegistryResource, + ConfigRegistryResourceWithRawResponse, + AsyncConfigRegistryResourceWithRawResponse, + ConfigRegistryResourceWithStreamingResponse, + AsyncConfigRegistryResourceWithStreamingResponse, +) + +__all__ = [ + "AnalysesResource", + "AsyncAnalysesResource", + "AnalysesResourceWithRawResponse", + "AsyncAnalysesResourceWithRawResponse", + "AnalysesResourceWithStreamingResponse", + "AsyncAnalysesResourceWithStreamingResponse", + "ConfigRegistryResource", + "AsyncConfigRegistryResource", + "ConfigRegistryResourceWithRawResponse", + "AsyncConfigRegistryResourceWithRawResponse", + "ConfigRegistryResourceWithStreamingResponse", + "AsyncConfigRegistryResourceWithStreamingResponse", +] diff --git a/src/kernel/resources/config_registry/analyses.py b/src/kernel/resources/config_registry/analyses.py new file mode 100644 index 00000000..c0cbd2c7 --- /dev/null +++ b/src/kernel/resources/config_registry/analyses.py @@ -0,0 +1,279 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ..._utils import path_template, maybe_transform +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...pagination import SyncOffsetPagination, AsyncOffsetPagination +from ..._base_client import AsyncPaginator, make_request_options +from ...types.config_registry import analysis_list_params +from ...types.analysis_summary import AnalysisSummary +from ...types.config_registry_response import ConfigRegistryResponse + +__all__ = ["AnalysesResource", "AsyncAnalysesResource"] + + +class AnalysesResource(SyncAPIResource): + """Resolve browser and proxy recommendations for bot-protected sites.""" + + @cached_property + def with_raw_response(self) -> AnalysesResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/kernel/kernel-python-sdk#accessing-raw-response-data-eg-headers + """ + return AnalysesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AnalysesResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/kernel/kernel-python-sdk#with_streaming_response + """ + return AnalysesResourceWithStreamingResponse(self) + + def retrieve( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ConfigRegistryResponse: + """ + Returns a project-scoped historical analysis and the recommendation outcome + concluded by that run. Later knowledge does not change this response. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._get( + path_template("/config-registry/analyses/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ConfigRegistryResponse, + ) + + def list( + self, + *, + limit: int | Omit = omit, + offset: int | Omit = omit, + search: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SyncOffsetPagination[AnalysisSummary]: + """ + Lists analyses for the selected project, newest first. + + Args: + search: Case-insensitive substring search over requested URLs. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get_api_list( + "/config-registry/analyses", + page=SyncOffsetPagination[AnalysisSummary], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "limit": limit, + "offset": offset, + "search": search, + }, + analysis_list_params.AnalysisListParams, + ), + ), + model=AnalysisSummary, + ) + + +class AsyncAnalysesResource(AsyncAPIResource): + """Resolve browser and proxy recommendations for bot-protected sites.""" + + @cached_property + def with_raw_response(self) -> AsyncAnalysesResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/kernel/kernel-python-sdk#accessing-raw-response-data-eg-headers + """ + return AsyncAnalysesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncAnalysesResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/kernel/kernel-python-sdk#with_streaming_response + """ + return AsyncAnalysesResourceWithStreamingResponse(self) + + async def retrieve( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ConfigRegistryResponse: + """ + Returns a project-scoped historical analysis and the recommendation outcome + concluded by that run. Later knowledge does not change this response. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._get( + path_template("/config-registry/analyses/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ConfigRegistryResponse, + ) + + def list( + self, + *, + limit: int | Omit = omit, + offset: int | Omit = omit, + search: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AsyncPaginator[AnalysisSummary, AsyncOffsetPagination[AnalysisSummary]]: + """ + Lists analyses for the selected project, newest first. + + Args: + search: Case-insensitive substring search over requested URLs. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get_api_list( + "/config-registry/analyses", + page=AsyncOffsetPagination[AnalysisSummary], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "limit": limit, + "offset": offset, + "search": search, + }, + analysis_list_params.AnalysisListParams, + ), + ), + model=AnalysisSummary, + ) + + +class AnalysesResourceWithRawResponse: + def __init__(self, analyses: AnalysesResource) -> None: + self._analyses = analyses + + self.retrieve = to_raw_response_wrapper( + analyses.retrieve, + ) + self.list = to_raw_response_wrapper( + analyses.list, + ) + + +class AsyncAnalysesResourceWithRawResponse: + def __init__(self, analyses: AsyncAnalysesResource) -> None: + self._analyses = analyses + + self.retrieve = async_to_raw_response_wrapper( + analyses.retrieve, + ) + self.list = async_to_raw_response_wrapper( + analyses.list, + ) + + +class AnalysesResourceWithStreamingResponse: + def __init__(self, analyses: AnalysesResource) -> None: + self._analyses = analyses + + self.retrieve = to_streamed_response_wrapper( + analyses.retrieve, + ) + self.list = to_streamed_response_wrapper( + analyses.list, + ) + + +class AsyncAnalysesResourceWithStreamingResponse: + def __init__(self, analyses: AsyncAnalysesResource) -> None: + self._analyses = analyses + + self.retrieve = async_to_streamed_response_wrapper( + analyses.retrieve, + ) + self.list = async_to_streamed_response_wrapper( + analyses.list, + ) diff --git a/src/kernel/resources/site_configs.py b/src/kernel/resources/config_registry/config_registry.py similarity index 53% rename from src/kernel/resources/site_configs.py rename to src/kernel/resources/config_registry/config_registry.py index b98a8d80..e5aa40d6 100644 --- a/src/kernel/resources/site_configs.py +++ b/src/kernel/resources/config_registry/config_registry.py @@ -6,137 +6,69 @@ import httpx -from ..types import ( - site_config_list_params, - site_config_lookup_params, - site_config_resolve_params, - site_config_list_recommendations_params, +from ...types import config_registry_list_params, config_registry_lookup_params, config_registry_resolve_params +from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given +from ..._utils import maybe_transform, async_maybe_transform +from .analyses import ( + AnalysesResource, + AsyncAnalysesResource, + AnalysesResourceWithRawResponse, + AsyncAnalysesResourceWithRawResponse, + AnalysesResourceWithStreamingResponse, + AsyncAnalysesResourceWithStreamingResponse, ) -from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given -from .._utils import path_template, maybe_transform, async_maybe_transform -from .._compat import cached_property -from .._resource import SyncAPIResource, AsyncAPIResource -from .._response import ( +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( to_raw_response_wrapper, to_streamed_response_wrapper, async_to_raw_response_wrapper, async_to_streamed_response_wrapper, ) -from ..pagination import SyncOffsetPagination, AsyncOffsetPagination -from .._base_client import AsyncPaginator, make_request_options -from ..types.lookup_response import LookupResponse -from ..types.analysis_summary import AnalysisSummary -from ..types.site_config_response import SiteConfigResponse -from ..types.recommendation_summary import RecommendationSummary +from ...pagination import SyncOffsetPagination, AsyncOffsetPagination +from ..._base_client import AsyncPaginator, make_request_options +from ...types.lookup_response import LookupResponse +from ...types.recommendation_summary import RecommendationSummary +from ...types.config_registry_response import ConfigRegistryResponse -__all__ = ["SiteConfigsResource", "AsyncSiteConfigsResource"] +__all__ = ["ConfigRegistryResource", "AsyncConfigRegistryResource"] -class SiteConfigsResource(SyncAPIResource): +class ConfigRegistryResource(SyncAPIResource): """Resolve browser and proxy recommendations for bot-protected sites.""" @cached_property - def with_raw_response(self) -> SiteConfigsResourceWithRawResponse: + def analyses(self) -> AnalysesResource: + """Resolve browser and proxy recommendations for bot-protected sites.""" + return AnalysesResource(self._client) + + @cached_property + def with_raw_response(self) -> ConfigRegistryResourceWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/kernel/kernel-python-sdk#accessing-raw-response-data-eg-headers """ - return SiteConfigsResourceWithRawResponse(self) + return ConfigRegistryResourceWithRawResponse(self) @cached_property - def with_streaming_response(self) -> SiteConfigsResourceWithStreamingResponse: + def with_streaming_response(self) -> ConfigRegistryResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/kernel/kernel-python-sdk#with_streaming_response """ - return SiteConfigsResourceWithStreamingResponse(self) - - def retrieve( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SiteConfigResponse: - """ - Returns a project-scoped historical analysis and the recommendation outcome - concluded by that run. Later knowledge does not change this response. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return self._get( - path_template("/site-configs/{id}", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=SiteConfigResponse, - ) + return ConfigRegistryResourceWithStreamingResponse(self) def list( self, *, limit: int | Omit = omit, offset: int | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SyncOffsetPagination[AnalysisSummary]: - """ - Lists analyses for the selected project, newest first. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return self._get_api_list( - "/site-configs", - page=SyncOffsetPagination[AnalysisSummary], - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "limit": limit, - "offset": offset, - }, - site_config_list_params.SiteConfigListParams, - ), - ), - model=AnalysisSummary, - ) - - def list_recommendations( - self, - *, - limit: int | Omit = omit, - offset: int | Omit = omit, - sort_by: Literal["target", "recommended_config", "last_requested_at", "success_rate"] | Omit = omit, + search: str | Omit = omit, + sort_by: Literal["target", "analysis_status", "recommended_config", "last_requested_at", "success_rate"] + | Omit = omit, sort_order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -150,6 +82,9 @@ def list_recommendations( current domain-level recommendations. Args: + search: Case-insensitive domain search. Full URLs are reduced to their registrable + domain. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -159,7 +94,7 @@ def list_recommendations( timeout: Override the client-level default timeout for this request, in seconds """ return self._get_api_list( - "/site-configs/recommendations", + "/config-registry", page=SyncOffsetPagination[RecommendationSummary], options=make_request_options( extra_headers=extra_headers, @@ -170,10 +105,11 @@ def list_recommendations( { "limit": limit, "offset": offset, + "search": search, "sort_by": sort_by, "sort_order": sort_order, }, - site_config_list_recommendations_params.SiteConfigListRecommendationsParams, + config_registry_list_params.ConfigRegistryListParams, ), ), model=RecommendationSummary, @@ -193,7 +129,7 @@ def lookup( ) -> LookupResponse: """ Returns current global knowledge without resolving DNS, creating an analysis, or - updating Site Config data. + updating config registry data. Args: url: Public HTTP(S) URL to look up. @@ -210,13 +146,13 @@ def lookup( timeout: Override the client-level default timeout for this request, in seconds """ return self._post( - "/site-configs/lookup", + "/config-registry/lookup", body=maybe_transform( { "url": url, "allowed_proxy_countries": allowed_proxy_countries, }, - site_config_lookup_params.SiteConfigLookupParams, + config_registry_lookup_params.ConfigRegistryLookupParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout @@ -235,11 +171,11 @@ def resolve( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SiteConfigResponse: + ) -> ConfigRegistryResponse: """ Explicitly starts or retries a project-scoped background analysis while - preserving current global knowledge when available. Use `/site-configs/lookup` - for side-effect-free reads. + preserving current global knowledge when available. Use + `/config-registry/lookup` for side-effect-free reads. Args: url: Public HTTP(S) URL to refresh. @@ -257,126 +193,56 @@ def resolve( timeout: Override the client-level default timeout for this request, in seconds """ return self._post( - "/site-configs/resolve", + "/config-registry/resolve", body=maybe_transform( { "url": url, "allowed_proxy_countries": allowed_proxy_countries, }, - site_config_resolve_params.SiteConfigResolveParams, + config_registry_resolve_params.ConfigRegistryResolveParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=SiteConfigResponse, + cast_to=ConfigRegistryResponse, ) -class AsyncSiteConfigsResource(AsyncAPIResource): +class AsyncConfigRegistryResource(AsyncAPIResource): """Resolve browser and proxy recommendations for bot-protected sites.""" @cached_property - def with_raw_response(self) -> AsyncSiteConfigsResourceWithRawResponse: + def analyses(self) -> AsyncAnalysesResource: + """Resolve browser and proxy recommendations for bot-protected sites.""" + return AsyncAnalysesResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncConfigRegistryResourceWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/kernel/kernel-python-sdk#accessing-raw-response-data-eg-headers """ - return AsyncSiteConfigsResourceWithRawResponse(self) + return AsyncConfigRegistryResourceWithRawResponse(self) @cached_property - def with_streaming_response(self) -> AsyncSiteConfigsResourceWithStreamingResponse: + def with_streaming_response(self) -> AsyncConfigRegistryResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/kernel/kernel-python-sdk#with_streaming_response """ - return AsyncSiteConfigsResourceWithStreamingResponse(self) - - async def retrieve( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SiteConfigResponse: - """ - Returns a project-scoped historical analysis and the recommendation outcome - concluded by that run. Later knowledge does not change this response. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return await self._get( - path_template("/site-configs/{id}", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=SiteConfigResponse, - ) + return AsyncConfigRegistryResourceWithStreamingResponse(self) def list( self, *, limit: int | Omit = omit, offset: int | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AsyncPaginator[AnalysisSummary, AsyncOffsetPagination[AnalysisSummary]]: - """ - Lists analyses for the selected project, newest first. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return self._get_api_list( - "/site-configs", - page=AsyncOffsetPagination[AnalysisSummary], - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "limit": limit, - "offset": offset, - }, - site_config_list_params.SiteConfigListParams, - ), - ), - model=AnalysisSummary, - ) - - def list_recommendations( - self, - *, - limit: int | Omit = omit, - offset: int | Omit = omit, - sort_by: Literal["target", "recommended_config", "last_requested_at", "success_rate"] | Omit = omit, + search: str | Omit = omit, + sort_by: Literal["target", "analysis_status", "recommended_config", "last_requested_at", "success_rate"] + | Omit = omit, sort_order: Literal["asc", "desc"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -390,6 +256,9 @@ def list_recommendations( current domain-level recommendations. Args: + search: Case-insensitive domain search. Full URLs are reduced to their registrable + domain. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -399,7 +268,7 @@ def list_recommendations( timeout: Override the client-level default timeout for this request, in seconds """ return self._get_api_list( - "/site-configs/recommendations", + "/config-registry", page=AsyncOffsetPagination[RecommendationSummary], options=make_request_options( extra_headers=extra_headers, @@ -410,10 +279,11 @@ def list_recommendations( { "limit": limit, "offset": offset, + "search": search, "sort_by": sort_by, "sort_order": sort_order, }, - site_config_list_recommendations_params.SiteConfigListRecommendationsParams, + config_registry_list_params.ConfigRegistryListParams, ), ), model=RecommendationSummary, @@ -433,7 +303,7 @@ async def lookup( ) -> LookupResponse: """ Returns current global knowledge without resolving DNS, creating an analysis, or - updating Site Config data. + updating config registry data. Args: url: Public HTTP(S) URL to look up. @@ -450,13 +320,13 @@ async def lookup( timeout: Override the client-level default timeout for this request, in seconds """ return await self._post( - "/site-configs/lookup", + "/config-registry/lookup", body=await async_maybe_transform( { "url": url, "allowed_proxy_countries": allowed_proxy_countries, }, - site_config_lookup_params.SiteConfigLookupParams, + config_registry_lookup_params.ConfigRegistryLookupParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout @@ -475,11 +345,11 @@ async def resolve( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SiteConfigResponse: + ) -> ConfigRegistryResponse: """ Explicitly starts or retries a project-scoped background analysis while - preserving current global knowledge when available. Use `/site-configs/lookup` - for side-effect-free reads. + preserving current global knowledge when available. Use + `/config-registry/lookup` for side-effect-free reads. Args: url: Public HTTP(S) URL to refresh. @@ -497,100 +367,96 @@ async def resolve( timeout: Override the client-level default timeout for this request, in seconds """ return await self._post( - "/site-configs/resolve", + "/config-registry/resolve", body=await async_maybe_transform( { "url": url, "allowed_proxy_countries": allowed_proxy_countries, }, - site_config_resolve_params.SiteConfigResolveParams, + config_registry_resolve_params.ConfigRegistryResolveParams, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=SiteConfigResponse, + cast_to=ConfigRegistryResponse, ) -class SiteConfigsResourceWithRawResponse: - def __init__(self, site_configs: SiteConfigsResource) -> None: - self._site_configs = site_configs +class ConfigRegistryResourceWithRawResponse: + def __init__(self, config_registry: ConfigRegistryResource) -> None: + self._config_registry = config_registry - self.retrieve = to_raw_response_wrapper( - site_configs.retrieve, - ) self.list = to_raw_response_wrapper( - site_configs.list, - ) - self.list_recommendations = to_raw_response_wrapper( - site_configs.list_recommendations, + config_registry.list, ) self.lookup = to_raw_response_wrapper( - site_configs.lookup, + config_registry.lookup, ) self.resolve = to_raw_response_wrapper( - site_configs.resolve, + config_registry.resolve, ) + @cached_property + def analyses(self) -> AnalysesResourceWithRawResponse: + """Resolve browser and proxy recommendations for bot-protected sites.""" + return AnalysesResourceWithRawResponse(self._config_registry.analyses) -class AsyncSiteConfigsResourceWithRawResponse: - def __init__(self, site_configs: AsyncSiteConfigsResource) -> None: - self._site_configs = site_configs - self.retrieve = async_to_raw_response_wrapper( - site_configs.retrieve, - ) +class AsyncConfigRegistryResourceWithRawResponse: + def __init__(self, config_registry: AsyncConfigRegistryResource) -> None: + self._config_registry = config_registry + self.list = async_to_raw_response_wrapper( - site_configs.list, - ) - self.list_recommendations = async_to_raw_response_wrapper( - site_configs.list_recommendations, + config_registry.list, ) self.lookup = async_to_raw_response_wrapper( - site_configs.lookup, + config_registry.lookup, ) self.resolve = async_to_raw_response_wrapper( - site_configs.resolve, + config_registry.resolve, ) + @cached_property + def analyses(self) -> AsyncAnalysesResourceWithRawResponse: + """Resolve browser and proxy recommendations for bot-protected sites.""" + return AsyncAnalysesResourceWithRawResponse(self._config_registry.analyses) -class SiteConfigsResourceWithStreamingResponse: - def __init__(self, site_configs: SiteConfigsResource) -> None: - self._site_configs = site_configs - self.retrieve = to_streamed_response_wrapper( - site_configs.retrieve, - ) +class ConfigRegistryResourceWithStreamingResponse: + def __init__(self, config_registry: ConfigRegistryResource) -> None: + self._config_registry = config_registry + self.list = to_streamed_response_wrapper( - site_configs.list, - ) - self.list_recommendations = to_streamed_response_wrapper( - site_configs.list_recommendations, + config_registry.list, ) self.lookup = to_streamed_response_wrapper( - site_configs.lookup, + config_registry.lookup, ) self.resolve = to_streamed_response_wrapper( - site_configs.resolve, + config_registry.resolve, ) + @cached_property + def analyses(self) -> AnalysesResourceWithStreamingResponse: + """Resolve browser and proxy recommendations for bot-protected sites.""" + return AnalysesResourceWithStreamingResponse(self._config_registry.analyses) -class AsyncSiteConfigsResourceWithStreamingResponse: - def __init__(self, site_configs: AsyncSiteConfigsResource) -> None: - self._site_configs = site_configs - self.retrieve = async_to_streamed_response_wrapper( - site_configs.retrieve, - ) +class AsyncConfigRegistryResourceWithStreamingResponse: + def __init__(self, config_registry: AsyncConfigRegistryResource) -> None: + self._config_registry = config_registry + self.list = async_to_streamed_response_wrapper( - site_configs.list, - ) - self.list_recommendations = async_to_streamed_response_wrapper( - site_configs.list_recommendations, + config_registry.list, ) self.lookup = async_to_streamed_response_wrapper( - site_configs.lookup, + config_registry.lookup, ) self.resolve = async_to_streamed_response_wrapper( - site_configs.resolve, + config_registry.resolve, ) + + @cached_property + def analyses(self) -> AsyncAnalysesResourceWithStreamingResponse: + """Resolve browser and proxy recommendations for bot-protected sites.""" + return AsyncAnalysesResourceWithStreamingResponse(self._config_registry.analyses) diff --git a/src/kernel/types/__init__.py b/src/kernel/types/__init__.py index 9e7af34c..fffffd45 100644 --- a/src/kernel/types/__init__.py +++ b/src/kernel/types/__init__.py @@ -53,7 +53,6 @@ from .proxy_update_params import ProxyUpdateParams as ProxyUpdateParams from .browser_proxy_config import BrowserProxyConfig as BrowserProxyConfig from .proxy_check_response import ProxyCheckResponse as ProxyCheckResponse -from .site_config_response import SiteConfigResponse as SiteConfigResponse from .api_key_create_params import APIKeyCreateParams as APIKeyCreateParams from .api_key_rotate_params import APIKeyRotateParams as APIKeyRotateParams from .api_key_update_params import APIKeyUpdateParams as APIKeyUpdateParams @@ -87,8 +86,8 @@ from .extension_upload_params import ExtensionUploadParams as ExtensionUploadParams from .profile_download_params import ProfileDownloadParams as ProfileDownloadParams from .proxy_retrieve_response import ProxyRetrieveResponse as ProxyRetrieveResponse -from .site_config_list_params import SiteConfigListParams as SiteConfigListParams from .browser_pool_list_params import BrowserPoolListParams as BrowserPoolListParams +from .config_registry_response import ConfigRegistryResponse as ConfigRegistryResponse from .credential_create_params import CredentialCreateParams as CredentialCreateParams from .credential_provider_item import CredentialProviderItem as CredentialProviderItem from .credential_update_params import CredentialUpdateParams as CredentialUpdateParams @@ -101,7 +100,6 @@ from .invocation_update_params import InvocationUpdateParams as InvocationUpdateParams from .browser_retrieve_response import BrowserRetrieveResponse as BrowserRetrieveResponse from .extension_upload_response import ExtensionUploadResponse as ExtensionUploadResponse -from .site_config_lookup_params import SiteConfigLookupParams as SiteConfigLookupParams from .browser_pool_create_params import BrowserPoolCreateParams as BrowserPoolCreateParams from .browser_pool_delete_params import BrowserPoolDeleteParams as BrowserPoolDeleteParams from .browser_pool_update_params import BrowserPoolUpdateParams as BrowserPoolUpdateParams @@ -111,16 +109,18 @@ from .invocation_create_response import InvocationCreateResponse as InvocationCreateResponse from .invocation_follow_response import InvocationFollowResponse as InvocationFollowResponse from .invocation_update_response import InvocationUpdateResponse as InvocationUpdateResponse -from .site_config_resolve_params import SiteConfigResolveParams as SiteConfigResolveParams from .browser_pool_acquire_params import BrowserPoolAcquireParams as BrowserPoolAcquireParams from .browser_pool_release_params import BrowserPoolReleaseParams as BrowserPoolReleaseParams +from .config_registry_list_params import ConfigRegistryListParams as ConfigRegistryListParams from .browser_network_config_param import BrowserNetworkConfigParam as BrowserNetworkConfigParam from .deployment_retrieve_response import DeploymentRetrieveResponse as DeploymentRetrieveResponse from .invocation_retrieve_response import InvocationRetrieveResponse as InvocationRetrieveResponse from .audit_log_export_chunk_params import AuditLogExportChunkParams as AuditLogExportChunkParams from .browser_pool_acquire_response import BrowserPoolAcquireResponse as BrowserPoolAcquireResponse +from .config_registry_lookup_params import ConfigRegistryLookupParams as ConfigRegistryLookupParams from .credential_totp_code_response import CredentialTotpCodeResponse as CredentialTotpCodeResponse from .browser_load_extensions_params import BrowserLoadExtensionsParams as BrowserLoadExtensionsParams +from .config_registry_resolve_params import ConfigRegistryResolveParams as ConfigRegistryResolveParams from .credential_provider_list_params import CredentialProviderListParams as CredentialProviderListParams from .credential_provider_test_result import CredentialProviderTestResult as CredentialProviderTestResult from .credential_provider_create_params import CredentialProviderCreateParams as CredentialProviderCreateParams @@ -129,9 +129,6 @@ from .credential_provider_list_items_response import ( CredentialProviderListItemsResponse as CredentialProviderListItemsResponse, ) -from .site_config_list_recommendations_params import ( - SiteConfigListRecommendationsParams as SiteConfigListRecommendationsParams, -) from .extension_download_from_chrome_store_params import ( ExtensionDownloadFromChromeStoreParams as ExtensionDownloadFromChromeStoreParams, ) diff --git a/src/kernel/types/analysis.py b/src/kernel/types/analysis.py index c47b956c..9bce3019 100644 --- a/src/kernel/types/analysis.py +++ b/src/kernel/types/analysis.py @@ -27,4 +27,4 @@ class Analysis(BaseModel): """Time the analysis reached a terminal status. Null while it is running.""" status: Literal["running", "completed", "failed", "canceled"] - """Lifecycle status of the background analysis.""" + """Lifecycle status of a background analysis.""" diff --git a/src/kernel/types/config_registry/__init__.py b/src/kernel/types/config_registry/__init__.py new file mode 100644 index 00000000..2950bf63 --- /dev/null +++ b/src/kernel/types/config_registry/__init__.py @@ -0,0 +1,5 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .analysis_list_params import AnalysisListParams as AnalysisListParams diff --git a/src/kernel/types/site_config_list_params.py b/src/kernel/types/config_registry/analysis_list_params.py similarity index 54% rename from src/kernel/types/site_config_list_params.py rename to src/kernel/types/config_registry/analysis_list_params.py index ee95bad4..b94f5dca 100644 --- a/src/kernel/types/site_config_list_params.py +++ b/src/kernel/types/config_registry/analysis_list_params.py @@ -4,10 +4,13 @@ from typing_extensions import TypedDict -__all__ = ["SiteConfigListParams"] +__all__ = ["AnalysisListParams"] -class SiteConfigListParams(TypedDict, total=False): +class AnalysisListParams(TypedDict, total=False): limit: int offset: int + + search: str + """Case-insensitive substring search over requested URLs.""" diff --git a/src/kernel/types/config_registry_list_params.py b/src/kernel/types/config_registry_list_params.py new file mode 100644 index 00000000..5259e4b7 --- /dev/null +++ b/src/kernel/types/config_registry_list_params.py @@ -0,0 +1,23 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, TypedDict + +__all__ = ["ConfigRegistryListParams"] + + +class ConfigRegistryListParams(TypedDict, total=False): + limit: int + + offset: int + + search: str + """Case-insensitive domain search. + + Full URLs are reduced to their registrable domain. + """ + + sort_by: Literal["target", "analysis_status", "recommended_config", "last_requested_at", "success_rate"] + + sort_order: Literal["asc", "desc"] diff --git a/src/kernel/types/site_config_lookup_params.py b/src/kernel/types/config_registry_lookup_params.py similarity index 82% rename from src/kernel/types/site_config_lookup_params.py rename to src/kernel/types/config_registry_lookup_params.py index aba315f4..13703a5a 100644 --- a/src/kernel/types/site_config_lookup_params.py +++ b/src/kernel/types/config_registry_lookup_params.py @@ -6,10 +6,10 @@ from .._types import SequenceNotStr -__all__ = ["SiteConfigLookupParams"] +__all__ = ["ConfigRegistryLookupParams"] -class SiteConfigLookupParams(TypedDict, total=False): +class ConfigRegistryLookupParams(TypedDict, total=False): url: Required[str] """Public HTTP(S) URL to look up.""" diff --git a/src/kernel/types/site_config_resolve_params.py b/src/kernel/types/config_registry_resolve_params.py similarity index 84% rename from src/kernel/types/site_config_resolve_params.py rename to src/kernel/types/config_registry_resolve_params.py index 37a3f44d..644c4b7a 100644 --- a/src/kernel/types/site_config_resolve_params.py +++ b/src/kernel/types/config_registry_resolve_params.py @@ -6,10 +6,10 @@ from .._types import SequenceNotStr -__all__ = ["SiteConfigResolveParams"] +__all__ = ["ConfigRegistryResolveParams"] -class SiteConfigResolveParams(TypedDict, total=False): +class ConfigRegistryResolveParams(TypedDict, total=False): url: Required[str] """Public HTTP(S) URL to refresh.""" diff --git a/src/kernel/types/site_config_response.py b/src/kernel/types/config_registry_response.py similarity index 87% rename from src/kernel/types/site_config_response.py rename to src/kernel/types/config_registry_response.py index b6673f76..9995173f 100644 --- a/src/kernel/types/site_config_response.py +++ b/src/kernel/types/config_registry_response.py @@ -7,10 +7,10 @@ from .analysis import Analysis from .recommendation_result import RecommendationResult -__all__ = ["SiteConfigResponse"] +__all__ = ["ConfigRegistryResponse"] -class SiteConfigResponse(BaseModel): +class ConfigRegistryResponse(BaseModel): analysis: Optional[Analysis] = None """Pollable analysis after workflow submission is acknowledged. diff --git a/src/kernel/types/no_recommendation.py b/src/kernel/types/no_recommendation.py index d1bab62c..05faec86 100644 --- a/src/kernel/types/no_recommendation.py +++ b/src/kernel/types/no_recommendation.py @@ -10,8 +10,7 @@ class NoRecommendation(BaseModel): code: Literal["proxy_restricted", "no_working_configuration", "inconclusive"] """ - Machine-readable reason Kernel cannot currently provide a Site Config - recommendation. + Machine-readable reason Kernel cannot currently provide a config recommendation. """ message: str diff --git a/src/kernel/types/proxy.py b/src/kernel/types/proxy.py index ea31827d..d5238ad7 100644 --- a/src/kernel/types/proxy.py +++ b/src/kernel/types/proxy.py @@ -8,39 +8,39 @@ __all__ = [ "Proxy", - "SiteConfigDirectProxy", - "SiteConfigManagedProxy", - "SiteConfigManagedProxyCreate", - "SiteConfigManagedProxyCreateConfig", - "SiteConfigManagedProxyCreateConfigDatacenterProxyConfig", - "SiteConfigManagedProxyCreateConfigIspProxyConfig", - "SiteConfigManagedProxyCreateConfigResidentialProxyConfig", - "SiteConfigManagedProxyCreateConfigMobileProxyConfig", - "SiteConfigManagedProxyCreateConfigCreateCustomProxyConfig", + "ConfigRegistryDirectProxy", + "ConfigRegistryManagedProxy", + "ConfigRegistryManagedProxyCreate", + "ConfigRegistryManagedProxyCreateConfig", + "ConfigRegistryManagedProxyCreateConfigDatacenterProxyConfig", + "ConfigRegistryManagedProxyCreateConfigIspProxyConfig", + "ConfigRegistryManagedProxyCreateConfigResidentialProxyConfig", + "ConfigRegistryManagedProxyCreateConfigMobileProxyConfig", + "ConfigRegistryManagedProxyCreateConfigCreateCustomProxyConfig", ] -class SiteConfigDirectProxy(BaseModel): +class ConfigRegistryDirectProxy(BaseModel): """Direct egress recipe. Pass `{ "mode": "direct" }` as the browser's `proxy`.""" mode: Literal["direct"] -class SiteConfigManagedProxyCreateConfigDatacenterProxyConfig(BaseModel): +class ConfigRegistryManagedProxyCreateConfigDatacenterProxyConfig(BaseModel): """Configuration for a datacenter proxy.""" country: Optional[str] = None """ISO 3166 country code. Defaults to US if not provided.""" -class SiteConfigManagedProxyCreateConfigIspProxyConfig(BaseModel): +class ConfigRegistryManagedProxyCreateConfigIspProxyConfig(BaseModel): """Configuration for an ISP proxy.""" country: Optional[str] = None """ISO 3166 country code. Defaults to US if not provided.""" -class SiteConfigManagedProxyCreateConfigResidentialProxyConfig(BaseModel): +class ConfigRegistryManagedProxyCreateConfigResidentialProxyConfig(BaseModel): """Configuration for residential proxies.""" asn: Optional[str] = None @@ -65,7 +65,7 @@ class SiteConfigManagedProxyCreateConfigResidentialProxyConfig(BaseModel): """US ZIP code.""" -class SiteConfigManagedProxyCreateConfigMobileProxyConfig(BaseModel): +class ConfigRegistryManagedProxyCreateConfigMobileProxyConfig(BaseModel): """Configuration for mobile proxies.""" city: Optional[str] = None @@ -78,7 +78,7 @@ class SiteConfigManagedProxyCreateConfigMobileProxyConfig(BaseModel): """US-only state code. Mobile carrier routing can make observed geo vary.""" -class SiteConfigManagedProxyCreateConfigCreateCustomProxyConfig(BaseModel): +class ConfigRegistryManagedProxyCreateConfigCreateCustomProxyConfig(BaseModel): """Configuration for a custom proxy (e.g., private proxy server).""" host: str @@ -101,16 +101,16 @@ class SiteConfigManagedProxyCreateConfigCreateCustomProxyConfig(BaseModel): """Username for proxy authentication.""" -SiteConfigManagedProxyCreateConfig: TypeAlias = Union[ - SiteConfigManagedProxyCreateConfigDatacenterProxyConfig, - SiteConfigManagedProxyCreateConfigIspProxyConfig, - SiteConfigManagedProxyCreateConfigResidentialProxyConfig, - SiteConfigManagedProxyCreateConfigMobileProxyConfig, - SiteConfigManagedProxyCreateConfigCreateCustomProxyConfig, +ConfigRegistryManagedProxyCreateConfig: TypeAlias = Union[ + ConfigRegistryManagedProxyCreateConfigDatacenterProxyConfig, + ConfigRegistryManagedProxyCreateConfigIspProxyConfig, + ConfigRegistryManagedProxyCreateConfigResidentialProxyConfig, + ConfigRegistryManagedProxyCreateConfigMobileProxyConfig, + ConfigRegistryManagedProxyCreateConfigCreateCustomProxyConfig, ] -class SiteConfigManagedProxyCreate(BaseModel): +class ConfigRegistryManagedProxyCreate(BaseModel): """Configuration for routing traffic through a proxy.""" type: Literal["datacenter", "isp", "residential", "mobile", "custom"] @@ -123,7 +123,7 @@ class SiteConfigManagedProxyCreate(BaseModel): bypass_hosts: Optional[List[str]] = None """Hostnames that should bypass the parent proxy and connect directly.""" - config: Optional[SiteConfigManagedProxyCreateConfig] = None + config: Optional[ConfigRegistryManagedProxyCreateConfig] = None """Configuration specific to the selected proxy `type`.""" name: Optional[str] = None @@ -133,7 +133,7 @@ class SiteConfigManagedProxyCreate(BaseModel): """Protocol to use for the proxy connection.""" -class SiteConfigManagedProxy(BaseModel): +class ConfigRegistryManagedProxy(BaseModel): """Managed proxy recipe. `create` is a non-idempotent `POST /proxies` payload: @@ -141,10 +141,12 @@ class SiteConfigManagedProxy(BaseModel): `proxy.id`. Do not submit this recipe before every browser session. """ - create: SiteConfigManagedProxyCreate + create: ConfigRegistryManagedProxyCreate """Configuration for routing traffic through a proxy.""" mode: Literal["managed"] -Proxy: TypeAlias = Annotated[Union[SiteConfigDirectProxy, SiteConfigManagedProxy], PropertyInfo(discriminator="mode")] +Proxy: TypeAlias = Annotated[ + Union[ConfigRegistryDirectProxy, ConfigRegistryManagedProxy], PropertyInfo(discriminator="mode") +] diff --git a/src/kernel/types/recommendation_summary.py b/src/kernel/types/recommendation_summary.py index abc2ea72..df83ae35 100644 --- a/src/kernel/types/recommendation_summary.py +++ b/src/kernel/types/recommendation_summary.py @@ -2,6 +2,7 @@ from typing import Optional from datetime import datetime +from typing_extensions import Literal from .._models import BaseModel from .recommendation import Recommendation @@ -10,6 +11,12 @@ class RecommendationSummary(BaseModel): + analysis_id: str + """ID of the most recently requested analysis for this domain.""" + + analysis_status: Literal["running", "completed", "failed", "canceled"] + """Lifecycle status of the most recently requested analysis for this domain.""" + last_requested_at: datetime """Most recent time the selected project requested an analysis for this domain.""" diff --git a/src/kernel/types/site_config_list_recommendations_params.py b/src/kernel/types/site_config_list_recommendations_params.py deleted file mode 100644 index 8ff51237..00000000 --- a/src/kernel/types/site_config_list_recommendations_params.py +++ /dev/null @@ -1,17 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal, TypedDict - -__all__ = ["SiteConfigListRecommendationsParams"] - - -class SiteConfigListRecommendationsParams(TypedDict, total=False): - limit: int - - offset: int - - sort_by: Literal["target", "recommended_config", "last_requested_at", "success_rate"] - - sort_order: Literal["asc", "desc"] diff --git a/tests/api_resources/config_registry/__init__.py b/tests/api_resources/config_registry/__init__.py new file mode 100644 index 00000000..fd8019a9 --- /dev/null +++ b/tests/api_resources/config_registry/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/config_registry/test_analyses.py b/tests/api_resources/config_registry/test_analyses.py new file mode 100644 index 00000000..50b608df --- /dev/null +++ b/tests/api_resources/config_registry/test_analyses.py @@ -0,0 +1,185 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from kernel import Kernel, AsyncKernel +from tests.utils import assert_matches_type +from kernel.types import AnalysisSummary, ConfigRegistryResponse +from kernel.pagination import SyncOffsetPagination, AsyncOffsetPagination + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestAnalyses: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_retrieve(self, client: Kernel) -> None: + analysis = client.config_registry.analyses.retrieve( + "id", + ) + assert_matches_type(ConfigRegistryResponse, analysis, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_retrieve(self, client: Kernel) -> None: + response = client.config_registry.analyses.with_raw_response.retrieve( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + analysis = response.parse() + assert_matches_type(ConfigRegistryResponse, analysis, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_retrieve(self, client: Kernel) -> None: + with client.config_registry.analyses.with_streaming_response.retrieve( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + analysis = response.parse() + assert_matches_type(ConfigRegistryResponse, analysis, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_retrieve(self, client: Kernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.config_registry.analyses.with_raw_response.retrieve( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list(self, client: Kernel) -> None: + analysis = client.config_registry.analyses.list() + assert_matches_type(SyncOffsetPagination[AnalysisSummary], analysis, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_with_all_params(self, client: Kernel) -> None: + analysis = client.config_registry.analyses.list( + limit=1, + offset=0, + search="search", + ) + assert_matches_type(SyncOffsetPagination[AnalysisSummary], analysis, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list(self, client: Kernel) -> None: + response = client.config_registry.analyses.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + analysis = response.parse() + assert_matches_type(SyncOffsetPagination[AnalysisSummary], analysis, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list(self, client: Kernel) -> None: + with client.config_registry.analyses.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + analysis = response.parse() + assert_matches_type(SyncOffsetPagination[AnalysisSummary], analysis, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncAnalyses: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_retrieve(self, async_client: AsyncKernel) -> None: + analysis = await async_client.config_registry.analyses.retrieve( + "id", + ) + assert_matches_type(ConfigRegistryResponse, analysis, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncKernel) -> None: + response = await async_client.config_registry.analyses.with_raw_response.retrieve( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + analysis = await response.parse() + assert_matches_type(ConfigRegistryResponse, analysis, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncKernel) -> None: + async with async_client.config_registry.analyses.with_streaming_response.retrieve( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + analysis = await response.parse() + assert_matches_type(ConfigRegistryResponse, analysis, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncKernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.config_registry.analyses.with_raw_response.retrieve( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncKernel) -> None: + analysis = await async_client.config_registry.analyses.list() + assert_matches_type(AsyncOffsetPagination[AnalysisSummary], analysis, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncKernel) -> None: + analysis = await async_client.config_registry.analyses.list( + limit=1, + offset=0, + search="search", + ) + assert_matches_type(AsyncOffsetPagination[AnalysisSummary], analysis, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncKernel) -> None: + response = await async_client.config_registry.analyses.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + analysis = await response.parse() + assert_matches_type(AsyncOffsetPagination[AnalysisSummary], analysis, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_list(self, async_client: AsyncKernel) -> None: + async with async_client.config_registry.analyses.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + analysis = await response.parse() + assert_matches_type(AsyncOffsetPagination[AnalysisSummary], analysis, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_config_registry.py b/tests/api_resources/test_config_registry.py new file mode 100644 index 00000000..710d3088 --- /dev/null +++ b/tests/api_resources/test_config_registry.py @@ -0,0 +1,281 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from kernel import Kernel, AsyncKernel +from tests.utils import assert_matches_type +from kernel.types import ( + LookupResponse, + RecommendationSummary, + ConfigRegistryResponse, +) +from kernel.pagination import SyncOffsetPagination, AsyncOffsetPagination + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestConfigRegistry: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list(self, client: Kernel) -> None: + config_registry = client.config_registry.list() + assert_matches_type(SyncOffsetPagination[RecommendationSummary], config_registry, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_with_all_params(self, client: Kernel) -> None: + config_registry = client.config_registry.list( + limit=1, + offset=0, + search="search", + sort_by="target", + sort_order="asc", + ) + assert_matches_type(SyncOffsetPagination[RecommendationSummary], config_registry, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list(self, client: Kernel) -> None: + response = client.config_registry.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + config_registry = response.parse() + assert_matches_type(SyncOffsetPagination[RecommendationSummary], config_registry, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list(self, client: Kernel) -> None: + with client.config_registry.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + config_registry = response.parse() + assert_matches_type(SyncOffsetPagination[RecommendationSummary], config_registry, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_lookup(self, client: Kernel) -> None: + config_registry = client.config_registry.lookup( + url="https://example.com", + ) + assert_matches_type(LookupResponse, config_registry, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_lookup_with_all_params(self, client: Kernel) -> None: + config_registry = client.config_registry.lookup( + url="https://example.com", + allowed_proxy_countries=["US"], + ) + assert_matches_type(LookupResponse, config_registry, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_lookup(self, client: Kernel) -> None: + response = client.config_registry.with_raw_response.lookup( + url="https://example.com", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + config_registry = response.parse() + assert_matches_type(LookupResponse, config_registry, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_lookup(self, client: Kernel) -> None: + with client.config_registry.with_streaming_response.lookup( + url="https://example.com", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + config_registry = response.parse() + assert_matches_type(LookupResponse, config_registry, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_resolve(self, client: Kernel) -> None: + config_registry = client.config_registry.resolve( + url="https://example.com", + ) + assert_matches_type(ConfigRegistryResponse, config_registry, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_resolve_with_all_params(self, client: Kernel) -> None: + config_registry = client.config_registry.resolve( + url="https://example.com", + allowed_proxy_countries=["US"], + ) + assert_matches_type(ConfigRegistryResponse, config_registry, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_resolve(self, client: Kernel) -> None: + response = client.config_registry.with_raw_response.resolve( + url="https://example.com", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + config_registry = response.parse() + assert_matches_type(ConfigRegistryResponse, config_registry, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_resolve(self, client: Kernel) -> None: + with client.config_registry.with_streaming_response.resolve( + url="https://example.com", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + config_registry = response.parse() + assert_matches_type(ConfigRegistryResponse, config_registry, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncConfigRegistry: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncKernel) -> None: + config_registry = await async_client.config_registry.list() + assert_matches_type(AsyncOffsetPagination[RecommendationSummary], config_registry, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncKernel) -> None: + config_registry = await async_client.config_registry.list( + limit=1, + offset=0, + search="search", + sort_by="target", + sort_order="asc", + ) + assert_matches_type(AsyncOffsetPagination[RecommendationSummary], config_registry, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncKernel) -> None: + response = await async_client.config_registry.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + config_registry = await response.parse() + assert_matches_type(AsyncOffsetPagination[RecommendationSummary], config_registry, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_list(self, async_client: AsyncKernel) -> None: + async with async_client.config_registry.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + config_registry = await response.parse() + assert_matches_type(AsyncOffsetPagination[RecommendationSummary], config_registry, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_lookup(self, async_client: AsyncKernel) -> None: + config_registry = await async_client.config_registry.lookup( + url="https://example.com", + ) + assert_matches_type(LookupResponse, config_registry, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_lookup_with_all_params(self, async_client: AsyncKernel) -> None: + config_registry = await async_client.config_registry.lookup( + url="https://example.com", + allowed_proxy_countries=["US"], + ) + assert_matches_type(LookupResponse, config_registry, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_lookup(self, async_client: AsyncKernel) -> None: + response = await async_client.config_registry.with_raw_response.lookup( + url="https://example.com", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + config_registry = await response.parse() + assert_matches_type(LookupResponse, config_registry, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_lookup(self, async_client: AsyncKernel) -> None: + async with async_client.config_registry.with_streaming_response.lookup( + url="https://example.com", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + config_registry = await response.parse() + assert_matches_type(LookupResponse, config_registry, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_resolve(self, async_client: AsyncKernel) -> None: + config_registry = await async_client.config_registry.resolve( + url="https://example.com", + ) + assert_matches_type(ConfigRegistryResponse, config_registry, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_resolve_with_all_params(self, async_client: AsyncKernel) -> None: + config_registry = await async_client.config_registry.resolve( + url="https://example.com", + allowed_proxy_countries=["US"], + ) + assert_matches_type(ConfigRegistryResponse, config_registry, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_resolve(self, async_client: AsyncKernel) -> None: + response = await async_client.config_registry.with_raw_response.resolve( + url="https://example.com", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + config_registry = await response.parse() + assert_matches_type(ConfigRegistryResponse, config_registry, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_resolve(self, async_client: AsyncKernel) -> None: + async with async_client.config_registry.with_streaming_response.resolve( + url="https://example.com", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + config_registry = await response.parse() + assert_matches_type(ConfigRegistryResponse, config_registry, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_site_configs.py b/tests/api_resources/test_site_configs.py deleted file mode 100644 index 2099899c..00000000 --- a/tests/api_resources/test_site_configs.py +++ /dev/null @@ -1,438 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -from typing import Any, cast - -import pytest - -from kernel import Kernel, AsyncKernel -from tests.utils import assert_matches_type -from kernel.types import ( - LookupResponse, - AnalysisSummary, - SiteConfigResponse, - RecommendationSummary, -) -from kernel.pagination import SyncOffsetPagination, AsyncOffsetPagination - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestSiteConfigs: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_retrieve(self, client: Kernel) -> None: - site_config = client.site_configs.retrieve( - "id", - ) - assert_matches_type(SiteConfigResponse, site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_retrieve(self, client: Kernel) -> None: - response = client.site_configs.with_raw_response.retrieve( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - site_config = response.parse() - assert_matches_type(SiteConfigResponse, site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_retrieve(self, client: Kernel) -> None: - with client.site_configs.with_streaming_response.retrieve( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - site_config = response.parse() - assert_matches_type(SiteConfigResponse, site_config, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_path_params_retrieve(self, client: Kernel) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.site_configs.with_raw_response.retrieve( - "", - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_list(self, client: Kernel) -> None: - site_config = client.site_configs.list() - assert_matches_type(SyncOffsetPagination[AnalysisSummary], site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_list_with_all_params(self, client: Kernel) -> None: - site_config = client.site_configs.list( - limit=1, - offset=0, - ) - assert_matches_type(SyncOffsetPagination[AnalysisSummary], site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_list(self, client: Kernel) -> None: - response = client.site_configs.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - site_config = response.parse() - assert_matches_type(SyncOffsetPagination[AnalysisSummary], site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_list(self, client: Kernel) -> None: - with client.site_configs.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - site_config = response.parse() - assert_matches_type(SyncOffsetPagination[AnalysisSummary], site_config, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_list_recommendations(self, client: Kernel) -> None: - site_config = client.site_configs.list_recommendations() - assert_matches_type(SyncOffsetPagination[RecommendationSummary], site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_list_recommendations_with_all_params(self, client: Kernel) -> None: - site_config = client.site_configs.list_recommendations( - limit=1, - offset=0, - sort_by="target", - sort_order="asc", - ) - assert_matches_type(SyncOffsetPagination[RecommendationSummary], site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_list_recommendations(self, client: Kernel) -> None: - response = client.site_configs.with_raw_response.list_recommendations() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - site_config = response.parse() - assert_matches_type(SyncOffsetPagination[RecommendationSummary], site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_list_recommendations(self, client: Kernel) -> None: - with client.site_configs.with_streaming_response.list_recommendations() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - site_config = response.parse() - assert_matches_type(SyncOffsetPagination[RecommendationSummary], site_config, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_lookup(self, client: Kernel) -> None: - site_config = client.site_configs.lookup( - url="https://example.com", - ) - assert_matches_type(LookupResponse, site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_lookup_with_all_params(self, client: Kernel) -> None: - site_config = client.site_configs.lookup( - url="https://example.com", - allowed_proxy_countries=["US"], - ) - assert_matches_type(LookupResponse, site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_lookup(self, client: Kernel) -> None: - response = client.site_configs.with_raw_response.lookup( - url="https://example.com", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - site_config = response.parse() - assert_matches_type(LookupResponse, site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_lookup(self, client: Kernel) -> None: - with client.site_configs.with_streaming_response.lookup( - url="https://example.com", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - site_config = response.parse() - assert_matches_type(LookupResponse, site_config, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_resolve(self, client: Kernel) -> None: - site_config = client.site_configs.resolve( - url="https://example.com", - ) - assert_matches_type(SiteConfigResponse, site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_resolve_with_all_params(self, client: Kernel) -> None: - site_config = client.site_configs.resolve( - url="https://example.com", - allowed_proxy_countries=["US"], - ) - assert_matches_type(SiteConfigResponse, site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_resolve(self, client: Kernel) -> None: - response = client.site_configs.with_raw_response.resolve( - url="https://example.com", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - site_config = response.parse() - assert_matches_type(SiteConfigResponse, site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_resolve(self, client: Kernel) -> None: - with client.site_configs.with_streaming_response.resolve( - url="https://example.com", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - site_config = response.parse() - assert_matches_type(SiteConfigResponse, site_config, path=["response"]) - - assert cast(Any, response.is_closed) is True - - -class TestAsyncSiteConfigs: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_retrieve(self, async_client: AsyncKernel) -> None: - site_config = await async_client.site_configs.retrieve( - "id", - ) - assert_matches_type(SiteConfigResponse, site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_retrieve(self, async_client: AsyncKernel) -> None: - response = await async_client.site_configs.with_raw_response.retrieve( - "id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - site_config = await response.parse() - assert_matches_type(SiteConfigResponse, site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_retrieve(self, async_client: AsyncKernel) -> None: - async with async_client.site_configs.with_streaming_response.retrieve( - "id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - site_config = await response.parse() - assert_matches_type(SiteConfigResponse, site_config, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_path_params_retrieve(self, async_client: AsyncKernel) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.site_configs.with_raw_response.retrieve( - "", - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_list(self, async_client: AsyncKernel) -> None: - site_config = await async_client.site_configs.list() - assert_matches_type(AsyncOffsetPagination[AnalysisSummary], site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_list_with_all_params(self, async_client: AsyncKernel) -> None: - site_config = await async_client.site_configs.list( - limit=1, - offset=0, - ) - assert_matches_type(AsyncOffsetPagination[AnalysisSummary], site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_list(self, async_client: AsyncKernel) -> None: - response = await async_client.site_configs.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - site_config = await response.parse() - assert_matches_type(AsyncOffsetPagination[AnalysisSummary], site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_list(self, async_client: AsyncKernel) -> None: - async with async_client.site_configs.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - site_config = await response.parse() - assert_matches_type(AsyncOffsetPagination[AnalysisSummary], site_config, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_list_recommendations(self, async_client: AsyncKernel) -> None: - site_config = await async_client.site_configs.list_recommendations() - assert_matches_type(AsyncOffsetPagination[RecommendationSummary], site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_list_recommendations_with_all_params(self, async_client: AsyncKernel) -> None: - site_config = await async_client.site_configs.list_recommendations( - limit=1, - offset=0, - sort_by="target", - sort_order="asc", - ) - assert_matches_type(AsyncOffsetPagination[RecommendationSummary], site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_list_recommendations(self, async_client: AsyncKernel) -> None: - response = await async_client.site_configs.with_raw_response.list_recommendations() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - site_config = await response.parse() - assert_matches_type(AsyncOffsetPagination[RecommendationSummary], site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_list_recommendations(self, async_client: AsyncKernel) -> None: - async with async_client.site_configs.with_streaming_response.list_recommendations() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - site_config = await response.parse() - assert_matches_type(AsyncOffsetPagination[RecommendationSummary], site_config, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_lookup(self, async_client: AsyncKernel) -> None: - site_config = await async_client.site_configs.lookup( - url="https://example.com", - ) - assert_matches_type(LookupResponse, site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_lookup_with_all_params(self, async_client: AsyncKernel) -> None: - site_config = await async_client.site_configs.lookup( - url="https://example.com", - allowed_proxy_countries=["US"], - ) - assert_matches_type(LookupResponse, site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_lookup(self, async_client: AsyncKernel) -> None: - response = await async_client.site_configs.with_raw_response.lookup( - url="https://example.com", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - site_config = await response.parse() - assert_matches_type(LookupResponse, site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_lookup(self, async_client: AsyncKernel) -> None: - async with async_client.site_configs.with_streaming_response.lookup( - url="https://example.com", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - site_config = await response.parse() - assert_matches_type(LookupResponse, site_config, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_resolve(self, async_client: AsyncKernel) -> None: - site_config = await async_client.site_configs.resolve( - url="https://example.com", - ) - assert_matches_type(SiteConfigResponse, site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_resolve_with_all_params(self, async_client: AsyncKernel) -> None: - site_config = await async_client.site_configs.resolve( - url="https://example.com", - allowed_proxy_countries=["US"], - ) - assert_matches_type(SiteConfigResponse, site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_resolve(self, async_client: AsyncKernel) -> None: - response = await async_client.site_configs.with_raw_response.resolve( - url="https://example.com", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - site_config = await response.parse() - assert_matches_type(SiteConfigResponse, site_config, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_resolve(self, async_client: AsyncKernel) -> None: - async with async_client.site_configs.with_streaming_response.resolve( - url="https://example.com", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - site_config = await response.parse() - assert_matches_type(SiteConfigResponse, site_config, path=["response"]) - - assert cast(Any, response.is_closed) is True