diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 1f73031..ff1c7af 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "3.2.0" + ".": "3.3.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 20e38d9..8930df3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 104 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/droidrun/droidrun-cloud-9c5542353ace880640fb7e8946c5c8d008480abb8d1952595ba2ee9323aed724.yml -openapi_spec_hash: afa528f0921063291f66c56c6093f2ab -config_hash: 27cfddf59d8227e89667fa012952335c +configured_endpoints: 107 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/droidrun/droidrun-cloud-e96db2fc0746ff1c11c2e36e7c3bc2e3765b194d9901897d24a376528208e816.yml +openapi_spec_hash: b45c764022d18add79f0516691749fa8 +config_hash: e6de87b533e3e7e6470b59c22d61752a diff --git a/CHANGELOG.md b/CHANGELOG.md index 91e1a63..17bb129 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## 3.3.0 (2026-05-30) + +Full Changelog: [v3.2.0...v3.3.0](https://github.com/droidrun/mobilerun-sdk-python/compare/v3.2.0...v3.3.0) + +### Features + +* **api:** api update ([472689f](https://github.com/droidrun/mobilerun-sdk-python/commit/472689f40d0225edcedb331fabda5d9b5ddbe390)) +* **api:** api update ([b58be1c](https://github.com/droidrun/mobilerun-sdk-python/commit/b58be1c00be168f8719a56d2ce5c1806ac30ef92)) +* **api:** api update ([2add42e](https://github.com/droidrun/mobilerun-sdk-python/commit/2add42ec33a0accad90ab5afe8d27ce22629b871)) +* **api:** manual updates ([88c9ae0](https://github.com/droidrun/mobilerun-sdk-python/commit/88c9ae09fe4979789e30e859bf9f7d57f39887c2)) + ## 3.2.0 (2026-05-21) Full Changelog: [v3.1.0...v3.2.0](https://github.com/droidrun/mobilerun-sdk-python/compare/v3.1.0...v3.2.0) diff --git a/api.md b/api.md index ccda2c7..4b2c442 100644 --- a/api.md +++ b/api.md @@ -37,6 +37,7 @@ from mobilerun_sdk.types import ( AppDeleteResponse, AppConfirmUploadResponse, AppCreateSignedUploadURLResponse, + AppListVersionsResponse, AppMarkFailedResponse, ) ``` @@ -48,6 +49,7 @@ Methods: - client.apps.delete(id) -> AppDeleteResponse - client.apps.confirm_upload(id) -> AppConfirmUploadResponse - client.apps.create_signed_upload_url(\*\*params) -> AppCreateSignedUploadURLResponse +- client.apps.list_versions(id) -> AppListVersionsResponse - client.apps.mark_failed(id) -> AppMarkFailedResponse # Carriers @@ -188,11 +190,11 @@ from mobilerun_sdk.types.devices import AppListResponse Methods: -- client.devices.apps.update(package_name, \*, device_id) -> None - client.devices.apps.list(device_id, \*\*params) -> Optional[AppListResponse] - client.devices.apps.delete(package_name, \*, device_id) -> None - client.devices.apps.install(device_id, \*\*params) -> None - client.devices.apps.start(package_name, \*, device_id, \*\*params) -> None +- client.devices.apps.stop(package_name, \*, device_id) -> None ## Esim @@ -356,6 +358,7 @@ from mobilerun_sdk.types import ( HookGetSampleDataResponse, HookPerformResponse, HookSubscribeResponse, + HookTestResponse, HookUnsubscribeResponse, ) ``` @@ -368,6 +371,7 @@ Methods: - client.hooks.get_sample_data() -> HookGetSampleDataResponse - client.hooks.perform(\*\*params) -> HookPerformResponse - client.hooks.subscribe(\*\*params) -> HookSubscribeResponse +- client.hooks.test(hook_id, \*\*params) -> HookTestResponse - client.hooks.unsubscribe(hook_id) -> HookUnsubscribeResponse # Models @@ -410,6 +414,7 @@ from mobilerun_sdk.types import ( ProxyUpdateResponse, ProxyListResponse, ProxyDeleteResponse, + ProxyLookupResponse, ) ``` @@ -420,6 +425,7 @@ Methods: - client.proxies.update(proxy_id, \*\*params) -> ProxyUpdateResponse - client.proxies.list(\*\*params) -> ProxyListResponse - client.proxies.delete(proxy_id) -> ProxyDeleteResponse +- client.proxies.lookup(\*\*params) -> ProxyLookupResponse # Tasks diff --git a/pyproject.toml b/pyproject.toml index b097c23..902a0c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "mobilerun-sdk" -version = "3.2.0" +version = "3.3.0" description = "The official Python library for the mobilerun API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/mobilerun_sdk/_version.py b/src/mobilerun_sdk/_version.py index a3beadb..fa98252 100644 --- a/src/mobilerun_sdk/_version.py +++ b/src/mobilerun_sdk/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "mobilerun_sdk" -__version__ = "3.2.0" # x-release-please-version +__version__ = "3.3.0" # x-release-please-version diff --git a/src/mobilerun_sdk/resources/apps.py b/src/mobilerun_sdk/resources/apps.py index 2587290..3e2bb8f 100644 --- a/src/mobilerun_sdk/resources/apps.py +++ b/src/mobilerun_sdk/resources/apps.py @@ -23,6 +23,7 @@ from ..types.app_delete_response import AppDeleteResponse from ..types.app_retrieve_response import AppRetrieveResponse from ..types.app_mark_failed_response import AppMarkFailedResponse +from ..types.app_list_versions_response import AppListVersionsResponse from ..types.app_confirm_upload_response import AppConfirmUploadResponse from ..types.app_create_signed_upload_url_response import AppCreateSignedUploadURLResponse @@ -266,6 +267,40 @@ def create_signed_upload_url( cast_to=AppCreateSignedUploadURLResponse, ) + def list_versions( + 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, + ) -> AppListVersionsResponse: + """ + Retrieves all versions of an app visible to the user (own uploads + system + versions) + + 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("/apps/{id}/versions", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=AppListVersionsResponse, + ) + def mark_failed( self, id: str, @@ -537,6 +572,40 @@ async def create_signed_upload_url( cast_to=AppCreateSignedUploadURLResponse, ) + async def list_versions( + 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, + ) -> AppListVersionsResponse: + """ + Retrieves all versions of an app visible to the user (own uploads + system + versions) + + 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("/apps/{id}/versions", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=AppListVersionsResponse, + ) + async def mark_failed( self, id: str, @@ -590,6 +659,9 @@ def __init__(self, apps: AppsResource) -> None: self.create_signed_upload_url = to_raw_response_wrapper( apps.create_signed_upload_url, ) + self.list_versions = to_raw_response_wrapper( + apps.list_versions, + ) self.mark_failed = to_raw_response_wrapper( apps.mark_failed, ) @@ -614,6 +686,9 @@ def __init__(self, apps: AsyncAppsResource) -> None: self.create_signed_upload_url = async_to_raw_response_wrapper( apps.create_signed_upload_url, ) + self.list_versions = async_to_raw_response_wrapper( + apps.list_versions, + ) self.mark_failed = async_to_raw_response_wrapper( apps.mark_failed, ) @@ -638,6 +713,9 @@ def __init__(self, apps: AppsResource) -> None: self.create_signed_upload_url = to_streamed_response_wrapper( apps.create_signed_upload_url, ) + self.list_versions = to_streamed_response_wrapper( + apps.list_versions, + ) self.mark_failed = to_streamed_response_wrapper( apps.mark_failed, ) @@ -662,6 +740,9 @@ def __init__(self, apps: AsyncAppsResource) -> None: self.create_signed_upload_url = async_to_streamed_response_wrapper( apps.create_signed_upload_url, ) + self.list_versions = async_to_streamed_response_wrapper( + apps.list_versions, + ) self.mark_failed = async_to_streamed_response_wrapper( apps.mark_failed, ) diff --git a/src/mobilerun_sdk/resources/devices/apps.py b/src/mobilerun_sdk/resources/devices/apps.py index 4541bb5..dbd6985 100644 --- a/src/mobilerun_sdk/resources/devices/apps.py +++ b/src/mobilerun_sdk/resources/devices/apps.py @@ -44,50 +44,6 @@ def with_streaming_response(self) -> AppsResourceWithStreamingResponse: """ return AppsResourceWithStreamingResponse(self) - def update( - self, - package_name: str, - *, - device_id: str, - x_device_display_id: 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, - ) -> None: - """ - Stop app - - 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 device_id: - raise ValueError(f"Expected a non-empty value for `device_id` but received {device_id!r}") - if not package_name: - raise ValueError(f"Expected a non-empty value for `package_name` but received {package_name!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - extra_headers = { - **strip_not_given( - {"X-Device-Display-ID": str(x_device_display_id) if is_given(x_device_display_id) else not_given} - ), - **(extra_headers or {}), - } - return self._patch( - path_template("/devices/{device_id}/apps/{package_name}", device_id=device_id, package_name=package_name), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - def list( self, device_id: str, @@ -337,28 +293,7 @@ def start( cast_to=NoneType, ) - -class AsyncAppsResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncAppsResourceWithRawResponse: - """ - 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/droidrun/mobilerun-sdk-python#accessing-raw-response-data-eg-headers - """ - return AsyncAppsResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncAppsResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/droidrun/mobilerun-sdk-python#with_streaming_response - """ - return AsyncAppsResourceWithStreamingResponse(self) - - async def update( + def stop( self, package_name: str, *, @@ -394,7 +329,7 @@ async def update( ), **(extra_headers or {}), } - return await self._patch( + return self._patch( path_template("/devices/{device_id}/apps/{package_name}", device_id=device_id, package_name=package_name), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout @@ -402,6 +337,27 @@ async def update( cast_to=NoneType, ) + +class AsyncAppsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncAppsResourceWithRawResponse: + """ + 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/droidrun/mobilerun-sdk-python#accessing-raw-response-data-eg-headers + """ + return AsyncAppsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncAppsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/droidrun/mobilerun-sdk-python#with_streaming_response + """ + return AsyncAppsResourceWithStreamingResponse(self) + async def list( self, device_id: str, @@ -651,14 +607,55 @@ async def start( cast_to=NoneType, ) + async def stop( + self, + package_name: str, + *, + device_id: str, + x_device_display_id: 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, + ) -> None: + """ + Stop app + + 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 device_id: + raise ValueError(f"Expected a non-empty value for `device_id` but received {device_id!r}") + if not package_name: + raise ValueError(f"Expected a non-empty value for `package_name` but received {package_name!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + extra_headers = { + **strip_not_given( + {"X-Device-Display-ID": str(x_device_display_id) if is_given(x_device_display_id) else not_given} + ), + **(extra_headers or {}), + } + return await self._patch( + path_template("/devices/{device_id}/apps/{package_name}", device_id=device_id, package_name=package_name), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + class AppsResourceWithRawResponse: def __init__(self, apps: AppsResource) -> None: self._apps = apps - self.update = to_raw_response_wrapper( - apps.update, - ) self.list = to_raw_response_wrapper( apps.list, ) @@ -671,15 +668,15 @@ def __init__(self, apps: AppsResource) -> None: self.start = to_raw_response_wrapper( apps.start, ) + self.stop = to_raw_response_wrapper( + apps.stop, + ) class AsyncAppsResourceWithRawResponse: def __init__(self, apps: AsyncAppsResource) -> None: self._apps = apps - self.update = async_to_raw_response_wrapper( - apps.update, - ) self.list = async_to_raw_response_wrapper( apps.list, ) @@ -692,15 +689,15 @@ def __init__(self, apps: AsyncAppsResource) -> None: self.start = async_to_raw_response_wrapper( apps.start, ) + self.stop = async_to_raw_response_wrapper( + apps.stop, + ) class AppsResourceWithStreamingResponse: def __init__(self, apps: AppsResource) -> None: self._apps = apps - self.update = to_streamed_response_wrapper( - apps.update, - ) self.list = to_streamed_response_wrapper( apps.list, ) @@ -713,15 +710,15 @@ def __init__(self, apps: AppsResource) -> None: self.start = to_streamed_response_wrapper( apps.start, ) + self.stop = to_streamed_response_wrapper( + apps.stop, + ) class AsyncAppsResourceWithStreamingResponse: def __init__(self, apps: AsyncAppsResource) -> None: self._apps = apps - self.update = async_to_streamed_response_wrapper( - apps.update, - ) self.list = async_to_streamed_response_wrapper( apps.list, ) @@ -734,3 +731,6 @@ def __init__(self, apps: AsyncAppsResource) -> None: self.start = async_to_streamed_response_wrapper( apps.start, ) + self.stop = async_to_streamed_response_wrapper( + apps.stop, + ) diff --git a/src/mobilerun_sdk/resources/hooks.py b/src/mobilerun_sdk/resources/hooks.py index 185b05e..6f3c43b 100644 --- a/src/mobilerun_sdk/resources/hooks.py +++ b/src/mobilerun_sdk/resources/hooks.py @@ -7,7 +7,7 @@ import httpx -from ..types import hook_list_params, hook_update_params, hook_perform_params, hook_subscribe_params +from ..types import hook_list_params, hook_test_params, hook_update_params, hook_perform_params, hook_subscribe_params 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 @@ -20,6 +20,7 @@ ) from .._base_client import make_request_options from ..types.hook_list_response import HookListResponse +from ..types.hook_test_response import HookTestResponse from ..types.hook_update_response import HookUpdateResponse from ..types.hook_perform_response import HookPerformResponse from ..types.hook_retrieve_response import HookRetrieveResponse @@ -277,6 +278,46 @@ def subscribe( cast_to=HookSubscribeResponse, ) + def test( + self, + hook_id: str, + *, + event: Optional[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, + ) -> HookTestResponse: + """ + Send a test event to a webhook endpoint. + + Delivers a sample payload to the hook's URL with a single attempt (no retries) + for fast feedback. + + Args: + event: Event type to simulate (default: completed) + + 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 hook_id: + raise ValueError(f"Expected a non-empty value for `hook_id` but received {hook_id!r}") + return self._post( + path_template("/hooks/{hook_id}/test", hook_id=hook_id), + body=maybe_transform({"event": event}, hook_test_params.HookTestParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=HookTestResponse, + ) + def unsubscribe( self, hook_id: str, @@ -560,6 +601,46 @@ async def subscribe( cast_to=HookSubscribeResponse, ) + async def test( + self, + hook_id: str, + *, + event: Optional[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, + ) -> HookTestResponse: + """ + Send a test event to a webhook endpoint. + + Delivers a sample payload to the hook's URL with a single attempt (no retries) + for fast feedback. + + Args: + event: Event type to simulate (default: completed) + + 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 hook_id: + raise ValueError(f"Expected a non-empty value for `hook_id` but received {hook_id!r}") + return await self._post( + path_template("/hooks/{hook_id}/test", hook_id=hook_id), + body=await async_maybe_transform({"event": event}, hook_test_params.HookTestParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=HookTestResponse, + ) + async def unsubscribe( self, hook_id: str, @@ -618,6 +699,9 @@ def __init__(self, hooks: HooksResource) -> None: self.subscribe = to_raw_response_wrapper( hooks.subscribe, ) + self.test = to_raw_response_wrapper( + hooks.test, + ) self.unsubscribe = to_raw_response_wrapper( hooks.unsubscribe, ) @@ -645,6 +729,9 @@ def __init__(self, hooks: AsyncHooksResource) -> None: self.subscribe = async_to_raw_response_wrapper( hooks.subscribe, ) + self.test = async_to_raw_response_wrapper( + hooks.test, + ) self.unsubscribe = async_to_raw_response_wrapper( hooks.unsubscribe, ) @@ -672,6 +759,9 @@ def __init__(self, hooks: HooksResource) -> None: self.subscribe = to_streamed_response_wrapper( hooks.subscribe, ) + self.test = to_streamed_response_wrapper( + hooks.test, + ) self.unsubscribe = to_streamed_response_wrapper( hooks.unsubscribe, ) @@ -699,6 +789,9 @@ def __init__(self, hooks: AsyncHooksResource) -> None: self.subscribe = async_to_streamed_response_wrapper( hooks.subscribe, ) + self.test = async_to_streamed_response_wrapper( + hooks.test, + ) self.unsubscribe = async_to_streamed_response_wrapper( hooks.unsubscribe, ) diff --git a/src/mobilerun_sdk/resources/proxies.py b/src/mobilerun_sdk/resources/proxies.py index cd4235f..4abd363 100644 --- a/src/mobilerun_sdk/resources/proxies.py +++ b/src/mobilerun_sdk/resources/proxies.py @@ -6,7 +6,7 @@ import httpx -from ..types import proxy_list_params, proxy_create_params, proxy_update_params +from ..types import proxy_list_params, proxy_create_params, proxy_lookup_params, proxy_update_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from .._utils import path_template, required_args, maybe_transform, async_maybe_transform from .._compat import cached_property @@ -21,6 +21,7 @@ from ..types.proxy_list_response import ProxyListResponse from ..types.proxy_create_response import ProxyCreateResponse from ..types.proxy_delete_response import ProxyDeleteResponse +from ..types.proxy_lookup_response import ProxyLookupResponse from ..types.proxy_update_response import ProxyUpdateResponse from ..types.proxy_retrieve_response import ProxyRetrieveResponse @@ -349,6 +350,40 @@ def delete( cast_to=ProxyDeleteResponse, ) + def lookup( + self, + *, + socks5: proxy_lookup_params.Socks5, + # 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, + ) -> ProxyLookupResponse: + """ + Lookup proxy location + + Args: + socks5: SOCKS5 proxy configuration. + + 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._post( + "/proxies/lookup", + body=maybe_transform({"socks5": socks5}, proxy_lookup_params.ProxyLookupParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ProxyLookupResponse, + ) + class AsyncProxiesResource(AsyncAPIResource): """Network Proxies""" @@ -672,6 +707,40 @@ async def delete( cast_to=ProxyDeleteResponse, ) + async def lookup( + self, + *, + socks5: proxy_lookup_params.Socks5, + # 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, + ) -> ProxyLookupResponse: + """ + Lookup proxy location + + Args: + socks5: SOCKS5 proxy configuration. + + 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 await self._post( + "/proxies/lookup", + body=await async_maybe_transform({"socks5": socks5}, proxy_lookup_params.ProxyLookupParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ProxyLookupResponse, + ) + class ProxiesResourceWithRawResponse: def __init__(self, proxies: ProxiesResource) -> None: @@ -692,6 +761,9 @@ def __init__(self, proxies: ProxiesResource) -> None: self.delete = to_raw_response_wrapper( proxies.delete, ) + self.lookup = to_raw_response_wrapper( + proxies.lookup, + ) class AsyncProxiesResourceWithRawResponse: @@ -713,6 +785,9 @@ def __init__(self, proxies: AsyncProxiesResource) -> None: self.delete = async_to_raw_response_wrapper( proxies.delete, ) + self.lookup = async_to_raw_response_wrapper( + proxies.lookup, + ) class ProxiesResourceWithStreamingResponse: @@ -734,6 +809,9 @@ def __init__(self, proxies: ProxiesResource) -> None: self.delete = to_streamed_response_wrapper( proxies.delete, ) + self.lookup = to_streamed_response_wrapper( + proxies.lookup, + ) class AsyncProxiesResourceWithStreamingResponse: @@ -755,3 +833,6 @@ def __init__(self, proxies: AsyncProxiesResource) -> None: self.delete = async_to_streamed_response_wrapper( proxies.delete, ) + self.lookup = async_to_streamed_response_wrapper( + proxies.lookup, + ) diff --git a/src/mobilerun_sdk/resources/tasks/tasks.py b/src/mobilerun_sdk/resources/tasks/tasks.py index 47d4c1a..b765073 100644 --- a/src/mobilerun_sdk/resources/tasks/tasks.py +++ b/src/mobilerun_sdk/resources/tasks/tasks.py @@ -270,6 +270,7 @@ def run( *, device_id: str, task: str, + accessibility: bool | Omit = omit, agent_id: int | Omit = omit, apps: SequenceNotStr[str] | Omit = omit, continue_on_failure: bool | Omit = omit, @@ -305,7 +306,7 @@ def run( display_id: The display ID of the device to run the task on. llm_model: The LLM model identifier to use for the task (e.g. - 'google/gemini-3.1-flash-lite-preview') + 'google/gemini-3.1-flash-lite') memory_namespace: Memory namespace for cross-task personalization @@ -325,6 +326,7 @@ def run( { "device_id": device_id, "task": task, + "accessibility": accessibility, "agent_id": agent_id, "apps": apps, "continue_on_failure": continue_on_failure, @@ -356,6 +358,7 @@ def run_streamed( *, device_id: str, task: str, + accessibility: bool | Omit = omit, agent_id: int | Omit = omit, apps: SequenceNotStr[str] | Omit = omit, continue_on_failure: bool | Omit = omit, @@ -390,7 +393,7 @@ def run_streamed( display_id: The display ID of the device to run the task on. llm_model: The LLM model identifier to use for the task (e.g. - 'google/gemini-3.1-flash-lite-preview') + 'google/gemini-3.1-flash-lite') memory_namespace: Memory namespace for cross-task personalization @@ -410,6 +413,7 @@ def run_streamed( { "device_id": device_id, "task": task, + "accessibility": accessibility, "agent_id": agent_id, "apps": apps, "continue_on_failure": continue_on_failure, @@ -733,6 +737,7 @@ async def run( *, device_id: str, task: str, + accessibility: bool | Omit = omit, agent_id: int | Omit = omit, apps: SequenceNotStr[str] | Omit = omit, continue_on_failure: bool | Omit = omit, @@ -768,7 +773,7 @@ async def run( display_id: The display ID of the device to run the task on. llm_model: The LLM model identifier to use for the task (e.g. - 'google/gemini-3.1-flash-lite-preview') + 'google/gemini-3.1-flash-lite') memory_namespace: Memory namespace for cross-task personalization @@ -788,6 +793,7 @@ async def run( { "device_id": device_id, "task": task, + "accessibility": accessibility, "agent_id": agent_id, "apps": apps, "continue_on_failure": continue_on_failure, @@ -819,6 +825,7 @@ async def run_streamed( *, device_id: str, task: str, + accessibility: bool | Omit = omit, agent_id: int | Omit = omit, apps: SequenceNotStr[str] | Omit = omit, continue_on_failure: bool | Omit = omit, @@ -853,7 +860,7 @@ async def run_streamed( display_id: The display ID of the device to run the task on. llm_model: The LLM model identifier to use for the task (e.g. - 'google/gemini-3.1-flash-lite-preview') + 'google/gemini-3.1-flash-lite') memory_namespace: Memory namespace for cross-task personalization @@ -873,6 +880,7 @@ async def run_streamed( { "device_id": device_id, "task": task, + "accessibility": accessibility, "agent_id": agent_id, "apps": apps, "continue_on_failure": continue_on_failure, diff --git a/src/mobilerun_sdk/types/__init__.py b/src/mobilerun_sdk/types/__init__.py index ba767ee..abff37b 100644 --- a/src/mobilerun_sdk/types/__init__.py +++ b/src/mobilerun_sdk/types/__init__.py @@ -22,12 +22,14 @@ from .app_list_params import AppListParams as AppListParams from .task_run_params import TaskRunParams as TaskRunParams from .hook_list_params import HookListParams as HookListParams +from .hook_test_params import HookTestParams as HookTestParams from .task_list_params import TaskListParams as TaskListParams from .app_list_response import AppListResponse as AppListResponse from .proxy_list_params import ProxyListParams as ProxyListParams from .task_run_response import TaskRunResponse as TaskRunResponse from .device_list_params import DeviceListParams as DeviceListParams from .hook_list_response import HookListResponse as HookListResponse +from .hook_test_response import HookTestResponse as HookTestResponse from .hook_update_params import HookUpdateParams as HookUpdateParams from .task_list_response import TaskListResponse as TaskListResponse from .task_stop_response import TaskStopResponse as TaskStopResponse @@ -40,6 +42,7 @@ from .profile_list_params import ProfileListParams as ProfileListParams from .proxy_create_params import ProxyCreateParams as ProxyCreateParams from .proxy_list_response import ProxyListResponse as ProxyListResponse +from .proxy_lookup_params import ProxyLookupParams as ProxyLookupParams from .proxy_update_params import ProxyUpdateParams as ProxyUpdateParams from .device_create_params import DeviceCreateParams as DeviceCreateParams from .device_list_response import DeviceListResponse as DeviceListResponse @@ -57,6 +60,7 @@ from .profile_update_params import ProfileUpdateParams as ProfileUpdateParams from .proxy_create_response import ProxyCreateResponse as ProxyCreateResponse from .proxy_delete_response import ProxyDeleteResponse as ProxyDeleteResponse +from .proxy_lookup_response import ProxyLookupResponse as ProxyLookupResponse from .proxy_update_response import ProxyUpdateResponse as ProxyUpdateResponse from .credential_list_params import CredentialListParams as CredentialListParams from .device_set_name_params import DeviceSetNameParams as DeviceSetNameParams @@ -78,6 +82,7 @@ from .carrier_retrieve_response import CarrierRetrieveResponse as CarrierRetrieveResponse from .hook_unsubscribe_response import HookUnsubscribeResponse as HookUnsubscribeResponse from .package_credentials_param import PackageCredentialsParam as PackageCredentialsParam +from .app_list_versions_response import AppListVersionsResponse as AppListVersionsResponse from .task_send_message_response import TaskSendMessageResponse as TaskSendMessageResponse from .app_confirm_upload_response import AppConfirmUploadResponse as AppConfirmUploadResponse from .device_fingerprint_response import DeviceFingerprintResponse as DeviceFingerprintResponse diff --git a/src/mobilerun_sdk/types/app_list_versions_response.py b/src/mobilerun_sdk/types/app_list_versions_response.py new file mode 100644 index 0000000..130eab8 --- /dev/null +++ b/src/mobilerun_sdk/types/app_list_versions_response.py @@ -0,0 +1,296 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["AppListVersionsResponse", "Data"] + + +class Data(BaseModel): + id: str + + app_id: str = FieldInfo(alias="appId") + + country: Literal[ + "AF", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AQ", + "AG", + "AR", + "AM", + "AW", + "AP", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BV", + "BR", + "IO", + "BN", + "BG", + "BF", + "BI", + "KH", + "CM", + "CA", + "CV", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CG", + "CD", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "CI", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "TF", + "GA", + "GM", + "GE", + "DE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HM", + "VA", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "IT", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KR", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "MX", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "AN", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "KP", + "MK", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PN", + "PL", + "PT", + "PR", + "QA", + "RE", + "RO", + "RU", + "RW", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "ST", + "SA", + "SN", + "RS", + "CS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "GS", + "SS", + "ES", + "LK", + "SD", + "SR", + "SJ", + "SZ", + "SE", + "CH", + "SY", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "UG", + "UA", + "AE", + "GB", + "US", + "UM", + "UY", + "UZ", + "VU", + "VE", + "VN", + "VG", + "VI", + "WF", + "EH", + "YE", + "ZM", + "ZW", + "AX", + ] + + created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) + + queued_at: Optional[datetime] = FieldInfo(alias="queuedAt", default=None) + + size_bytes: Optional[int] = FieldInfo(alias="sizeBytes", default=None) + + source: Literal["user", "system", "portal"] + + status: Literal["queued", "available", "failed"] + + target_sdk: Optional[int] = FieldInfo(alias="targetSdk", default=None) + + updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) + + user_id: Optional[str] = FieldInfo(alias="userId", default=None) + + version_code: int = FieldInfo(alias="versionCode") + + version_name: str = FieldInfo(alias="versionName") + + +class AppListVersionsResponse(BaseModel): + data: List[Data] diff --git a/src/mobilerun_sdk/types/hook_test_params.py b/src/mobilerun_sdk/types/hook_test_params.py new file mode 100644 index 0000000..af5edff --- /dev/null +++ b/src/mobilerun_sdk/types/hook_test_params.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from typing_extensions import TypedDict + +__all__ = ["HookTestParams"] + + +class HookTestParams(TypedDict, total=False): + event: Optional[str] + """Event type to simulate (default: completed)""" diff --git a/src/mobilerun_sdk/types/hook_test_response.py b/src/mobilerun_sdk/types/hook_test_response.py new file mode 100644 index 0000000..8d22bab --- /dev/null +++ b/src/mobilerun_sdk/types/hook_test_response.py @@ -0,0 +1,25 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["HookTestResponse"] + + +class HookTestResponse(BaseModel): + """Response after attempting test delivery.""" + + id: str + """The hook ID""" + + success: bool + """Whether delivery succeeded (2xx)""" + + error: Optional[str] = None + """Error message if delivery failed""" + + status_code: Optional[int] = FieldInfo(alias="statusCode", default=None) + """HTTP status from target""" diff --git a/src/mobilerun_sdk/types/proxy_lookup_params.py b/src/mobilerun_sdk/types/proxy_lookup_params.py new file mode 100644 index 0000000..43b7464 --- /dev/null +++ b/src/mobilerun_sdk/types/proxy_lookup_params.py @@ -0,0 +1,24 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["ProxyLookupParams", "Socks5"] + + +class ProxyLookupParams(TypedDict, total=False): + socks5: Required[Socks5] + """SOCKS5 proxy configuration.""" + + +class Socks5(TypedDict, total=False): + """SOCKS5 proxy configuration.""" + + host: Required[str] + + port: Required[int] + + password: str + + user: str diff --git a/src/mobilerun_sdk/types/proxy_lookup_response.py b/src/mobilerun_sdk/types/proxy_lookup_response.py new file mode 100644 index 0000000..6e4e88f --- /dev/null +++ b/src/mobilerun_sdk/types/proxy_lookup_response.py @@ -0,0 +1,57 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["ProxyLookupResponse", "Carrier"] + + +class Carrier(BaseModel): + """Mobile carrier information.""" + + mcc: Optional[str] = None + """Mobile Country Code.""" + + mnc: Optional[str] = None + """Mobile Network Code.""" + + name: Optional[str] = None + """Carrier name.""" + + +class ProxyLookupResponse(BaseModel): + ip: str + """IP address of the proxy.""" + + is_mobile: bool = FieldInfo(alias="isMobile") + """Whether the IP is a mobile connection.""" + + latitude: float + """Latitude of the proxy.""" + + longitude: float + """Longitude of the proxy.""" + + schema_: Optional[str] = FieldInfo(alias="$schema", default=None) + """A URL to the JSON Schema for this object.""" + + carrier: Optional[Carrier] = None + """Mobile carrier information.""" + + city: Optional[str] = None + """City of the proxy.""" + + country: Optional[str] = None + """Country of the proxy.""" + + country_code: Optional[str] = FieldInfo(alias="countryCode", default=None) + """ISO country code.""" + + region: Optional[str] = None + """Region of the proxy.""" + + timezone: Optional[str] = None + """Timezone of the proxy.""" diff --git a/src/mobilerun_sdk/types/task.py b/src/mobilerun_sdk/types/task.py index 4a0f115..cc4dab6 100644 --- a/src/mobilerun_sdk/types/task.py +++ b/src/mobilerun_sdk/types/task.py @@ -25,6 +25,8 @@ class Task(BaseModel): id: Optional[str] = None + accessibility: Optional[bool] = None + agent_id: Optional[int] = FieldInfo(alias="agentId", default=None) apps: Optional[List[str]] = None diff --git a/src/mobilerun_sdk/types/task_get_trajectory_response.py b/src/mobilerun_sdk/types/task_get_trajectory_response.py index 241c5b1..0405cf9 100644 --- a/src/mobilerun_sdk/types/task_get_trajectory_response.py +++ b/src/mobilerun_sdk/types/task_get_trajectory_response.py @@ -212,7 +212,7 @@ class TrajectoryTrajectoryManagerInputEvent(BaseModel): class TrajectoryTrajectoryManagerPlanEventData(BaseModel): - """Coordination event from ManagerAgent to DroidAgent. + """Coordination event from ManagerAgent to MobileAgent. Used for workflow step routing only (NOT streamed to frontend). For internal events with memory_update metadata, see ManagerPlanDetailsEvent. @@ -231,7 +231,7 @@ class TrajectoryTrajectoryManagerPlanEventData(BaseModel): class TrajectoryTrajectoryManagerPlanEvent(BaseModel): data: TrajectoryTrajectoryManagerPlanEventData - """Coordination event from ManagerAgent to DroidAgent. + """Coordination event from ManagerAgent to MobileAgent. Used for workflow step routing only (NOT streamed to frontend). For internal events with memory_update metadata, see ManagerPlanDetailsEvent. diff --git a/src/mobilerun_sdk/types/task_list_response.py b/src/mobilerun_sdk/types/task_list_response.py index 16c8d1d..12a8a4c 100644 --- a/src/mobilerun_sdk/types/task_list_response.py +++ b/src/mobilerun_sdk/types/task_list_response.py @@ -34,6 +34,8 @@ class Item(BaseModel): user_id: str = FieldInfo(alias="userId") + accessibility: Optional[bool] = None + agent_id: Optional[int] = FieldInfo(alias="agentId", default=None) apps: Optional[List[str]] = None diff --git a/src/mobilerun_sdk/types/task_run_params.py b/src/mobilerun_sdk/types/task_run_params.py index 3a91df8..8fc6144 100644 --- a/src/mobilerun_sdk/types/task_run_params.py +++ b/src/mobilerun_sdk/types/task_run_params.py @@ -18,6 +18,8 @@ class TaskRunParams(TypedDict, total=False): task: Required[str] + accessibility: bool + agent_id: Annotated[int, PropertyInfo(alias="agentId")] apps: SequenceNotStr[str] @@ -36,7 +38,7 @@ class TaskRunParams(TypedDict, total=False): llm_model: Annotated[str, PropertyInfo(alias="llmModel")] """The LLM model identifier to use for the task (e.g. - 'google/gemini-3.1-flash-lite-preview') + 'google/gemini-3.1-flash-lite') """ max_steps: Annotated[int, PropertyInfo(alias="maxSteps")] diff --git a/src/mobilerun_sdk/types/task_run_streamed_params.py b/src/mobilerun_sdk/types/task_run_streamed_params.py index 8c03add..1c0cfd6 100644 --- a/src/mobilerun_sdk/types/task_run_streamed_params.py +++ b/src/mobilerun_sdk/types/task_run_streamed_params.py @@ -18,6 +18,8 @@ class TaskRunStreamedParams(TypedDict, total=False): task: Required[str] + accessibility: bool + agent_id: Annotated[int, PropertyInfo(alias="agentId")] apps: SequenceNotStr[str] @@ -36,7 +38,7 @@ class TaskRunStreamedParams(TypedDict, total=False): llm_model: Annotated[str, PropertyInfo(alias="llmModel")] """The LLM model identifier to use for the task (e.g. - 'google/gemini-3.1-flash-lite-preview') + 'google/gemini-3.1-flash-lite') """ max_steps: Annotated[int, PropertyInfo(alias="maxSteps")] diff --git a/tests/api_resources/devices/test_apps.py b/tests/api_resources/devices/test_apps.py index 87c426d..5f86d32 100644 --- a/tests/api_resources/devices/test_apps.py +++ b/tests/api_resources/devices/test_apps.py @@ -17,68 +17,6 @@ class TestApps: 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_update(self, client: Mobilerun) -> None: - app = client.devices.apps.update( - package_name="packageName", - device_id="deviceId", - ) - assert app is None - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_update_with_all_params(self, client: Mobilerun) -> None: - app = client.devices.apps.update( - package_name="packageName", - device_id="deviceId", - x_device_display_id=0, - ) - assert app is None - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_update(self, client: Mobilerun) -> None: - response = client.devices.apps.with_raw_response.update( - package_name="packageName", - device_id="deviceId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - app = response.parse() - assert app is None - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_update(self, client: Mobilerun) -> None: - with client.devices.apps.with_streaming_response.update( - package_name="packageName", - device_id="deviceId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - app = response.parse() - assert app is None - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_path_params_update(self, client: Mobilerun) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"): - client.devices.apps.with_raw_response.update( - package_name="packageName", - device_id="", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `package_name` but received ''"): - client.devices.apps.with_raw_response.update( - package_name="", - device_id="deviceId", - ) - @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_list(self, client: Mobilerun) -> None: @@ -371,16 +309,10 @@ def test_path_params_start(self, client: Mobilerun) -> None: device_id="deviceId", ) - -class TestAsyncApps: - 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_update(self, async_client: AsyncMobilerun) -> None: - app = await async_client.devices.apps.update( + def test_method_stop(self, client: Mobilerun) -> None: + app = client.devices.apps.stop( package_name="packageName", device_id="deviceId", ) @@ -388,8 +320,8 @@ async def test_method_update(self, async_client: AsyncMobilerun) -> None: @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_method_update_with_all_params(self, async_client: AsyncMobilerun) -> None: - app = await async_client.devices.apps.update( + def test_method_stop_with_all_params(self, client: Mobilerun) -> None: + app = client.devices.apps.stop( package_name="packageName", device_id="deviceId", x_device_display_id=0, @@ -398,47 +330,53 @@ async def test_method_update_with_all_params(self, async_client: AsyncMobilerun) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_raw_response_update(self, async_client: AsyncMobilerun) -> None: - response = await async_client.devices.apps.with_raw_response.update( + def test_raw_response_stop(self, client: Mobilerun) -> None: + response = client.devices.apps.with_raw_response.stop( package_name="packageName", device_id="deviceId", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - app = await response.parse() + app = response.parse() assert app is None @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_streaming_response_update(self, async_client: AsyncMobilerun) -> None: - async with async_client.devices.apps.with_streaming_response.update( + def test_streaming_response_stop(self, client: Mobilerun) -> None: + with client.devices.apps.with_streaming_response.stop( package_name="packageName", device_id="deviceId", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - app = await response.parse() + app = response.parse() assert app is None assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_path_params_update(self, async_client: AsyncMobilerun) -> None: + def test_path_params_stop(self, client: Mobilerun) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"): - await async_client.devices.apps.with_raw_response.update( + client.devices.apps.with_raw_response.stop( package_name="packageName", device_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `package_name` but received ''"): - await async_client.devices.apps.with_raw_response.update( + client.devices.apps.with_raw_response.stop( package_name="", device_id="deviceId", ) + +class TestAsyncApps: + 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: AsyncMobilerun) -> None: @@ -730,3 +668,65 @@ async def test_path_params_start(self, async_client: AsyncMobilerun) -> None: package_name="", device_id="deviceId", ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_stop(self, async_client: AsyncMobilerun) -> None: + app = await async_client.devices.apps.stop( + package_name="packageName", + device_id="deviceId", + ) + assert app is None + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_stop_with_all_params(self, async_client: AsyncMobilerun) -> None: + app = await async_client.devices.apps.stop( + package_name="packageName", + device_id="deviceId", + x_device_display_id=0, + ) + assert app is None + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_stop(self, async_client: AsyncMobilerun) -> None: + response = await async_client.devices.apps.with_raw_response.stop( + package_name="packageName", + device_id="deviceId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + app = await response.parse() + assert app is None + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_stop(self, async_client: AsyncMobilerun) -> None: + async with async_client.devices.apps.with_streaming_response.stop( + package_name="packageName", + device_id="deviceId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + app = await response.parse() + assert app is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_stop(self, async_client: AsyncMobilerun) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"): + await async_client.devices.apps.with_raw_response.stop( + package_name="packageName", + device_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `package_name` but received ''"): + await async_client.devices.apps.with_raw_response.stop( + package_name="", + device_id="deviceId", + ) diff --git a/tests/api_resources/test_apps.py b/tests/api_resources/test_apps.py index 887a5ee..7fd88df 100644 --- a/tests/api_resources/test_apps.py +++ b/tests/api_resources/test_apps.py @@ -14,6 +14,7 @@ AppDeleteResponse, AppRetrieveResponse, AppMarkFailedResponse, + AppListVersionsResponse, AppConfirmUploadResponse, AppCreateSignedUploadURLResponse, ) @@ -280,6 +281,48 @@ def test_streaming_response_create_signed_upload_url(self, client: Mobilerun) -> assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_versions(self, client: Mobilerun) -> None: + app = client.apps.list_versions( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(AppListVersionsResponse, app, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list_versions(self, client: Mobilerun) -> None: + response = client.apps.with_raw_response.list_versions( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + app = response.parse() + assert_matches_type(AppListVersionsResponse, app, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list_versions(self, client: Mobilerun) -> None: + with client.apps.with_streaming_response.list_versions( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + app = response.parse() + assert_matches_type(AppListVersionsResponse, app, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_list_versions(self, client: Mobilerun) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.apps.with_raw_response.list_versions( + "", + ) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_mark_failed(self, client: Mobilerun) -> None: @@ -584,6 +627,48 @@ async def test_streaming_response_create_signed_upload_url(self, async_client: A assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_versions(self, async_client: AsyncMobilerun) -> None: + app = await async_client.apps.list_versions( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(AppListVersionsResponse, app, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_list_versions(self, async_client: AsyncMobilerun) -> None: + response = await async_client.apps.with_raw_response.list_versions( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + app = await response.parse() + assert_matches_type(AppListVersionsResponse, app, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_list_versions(self, async_client: AsyncMobilerun) -> None: + async with async_client.apps.with_streaming_response.list_versions( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + app = await response.parse() + assert_matches_type(AppListVersionsResponse, app, 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_list_versions(self, async_client: AsyncMobilerun) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.apps.with_raw_response.list_versions( + "", + ) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_mark_failed(self, async_client: AsyncMobilerun) -> None: diff --git a/tests/api_resources/test_hooks.py b/tests/api_resources/test_hooks.py index 5d9a9d9..21548ab 100644 --- a/tests/api_resources/test_hooks.py +++ b/tests/api_resources/test_hooks.py @@ -11,6 +11,7 @@ from mobilerun_sdk import Mobilerun, AsyncMobilerun from mobilerun_sdk.types import ( HookListResponse, + HookTestResponse, HookUpdateResponse, HookPerformResponse, HookRetrieveResponse, @@ -264,6 +265,57 @@ def test_streaming_response_subscribe(self, client: Mobilerun) -> None: assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_test(self, client: Mobilerun) -> None: + hook = client.hooks.test( + hook_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(HookTestResponse, hook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_test_with_all_params(self, client: Mobilerun) -> None: + hook = client.hooks.test( + hook_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + event="event", + ) + assert_matches_type(HookTestResponse, hook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_test(self, client: Mobilerun) -> None: + response = client.hooks.with_raw_response.test( + hook_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + hook = response.parse() + assert_matches_type(HookTestResponse, hook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_test(self, client: Mobilerun) -> None: + with client.hooks.with_streaming_response.test( + hook_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + hook = response.parse() + assert_matches_type(HookTestResponse, hook, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_test(self, client: Mobilerun) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `hook_id` but received ''"): + client.hooks.with_raw_response.test( + hook_id="", + ) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_unsubscribe(self, client: Mobilerun) -> None: @@ -551,6 +603,57 @@ async def test_streaming_response_subscribe(self, async_client: AsyncMobilerun) assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_test(self, async_client: AsyncMobilerun) -> None: + hook = await async_client.hooks.test( + hook_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(HookTestResponse, hook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_test_with_all_params(self, async_client: AsyncMobilerun) -> None: + hook = await async_client.hooks.test( + hook_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + event="event", + ) + assert_matches_type(HookTestResponse, hook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_test(self, async_client: AsyncMobilerun) -> None: + response = await async_client.hooks.with_raw_response.test( + hook_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + hook = await response.parse() + assert_matches_type(HookTestResponse, hook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_test(self, async_client: AsyncMobilerun) -> None: + async with async_client.hooks.with_streaming_response.test( + hook_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + hook = await response.parse() + assert_matches_type(HookTestResponse, hook, 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_test(self, async_client: AsyncMobilerun) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `hook_id` but received ''"): + await async_client.hooks.with_raw_response.test( + hook_id="", + ) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_unsubscribe(self, async_client: AsyncMobilerun) -> None: diff --git a/tests/api_resources/test_proxies.py b/tests/api_resources/test_proxies.py index 6b09e36..b96cc4d 100644 --- a/tests/api_resources/test_proxies.py +++ b/tests/api_resources/test_proxies.py @@ -13,6 +13,7 @@ ProxyListResponse, ProxyCreateResponse, ProxyDeleteResponse, + ProxyLookupResponse, ProxyUpdateResponse, ProxyRetrieveResponse, ) @@ -352,6 +353,62 @@ def test_path_params_delete(self, client: Mobilerun) -> None: "", ) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_lookup(self, client: Mobilerun) -> None: + proxy = client.proxies.lookup( + socks5={ + "host": "host", + "port": 1, + }, + ) + assert_matches_type(ProxyLookupResponse, proxy, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_lookup_with_all_params(self, client: Mobilerun) -> None: + proxy = client.proxies.lookup( + socks5={ + "host": "host", + "port": 1, + "password": "password", + "user": "user", + }, + ) + assert_matches_type(ProxyLookupResponse, proxy, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_lookup(self, client: Mobilerun) -> None: + response = client.proxies.with_raw_response.lookup( + socks5={ + "host": "host", + "port": 1, + }, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + proxy = response.parse() + assert_matches_type(ProxyLookupResponse, proxy, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_lookup(self, client: Mobilerun) -> None: + with client.proxies.with_streaming_response.lookup( + socks5={ + "host": "host", + "port": 1, + }, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + proxy = response.parse() + assert_matches_type(ProxyLookupResponse, proxy, path=["response"]) + + assert cast(Any, response.is_closed) is True + class TestAsyncProxies: parametrize = pytest.mark.parametrize( @@ -686,3 +743,59 @@ async def test_path_params_delete(self, async_client: AsyncMobilerun) -> None: await async_client.proxies.with_raw_response.delete( "", ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_lookup(self, async_client: AsyncMobilerun) -> None: + proxy = await async_client.proxies.lookup( + socks5={ + "host": "host", + "port": 1, + }, + ) + assert_matches_type(ProxyLookupResponse, proxy, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_lookup_with_all_params(self, async_client: AsyncMobilerun) -> None: + proxy = await async_client.proxies.lookup( + socks5={ + "host": "host", + "port": 1, + "password": "password", + "user": "user", + }, + ) + assert_matches_type(ProxyLookupResponse, proxy, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_lookup(self, async_client: AsyncMobilerun) -> None: + response = await async_client.proxies.with_raw_response.lookup( + socks5={ + "host": "host", + "port": 1, + }, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + proxy = await response.parse() + assert_matches_type(ProxyLookupResponse, proxy, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_lookup(self, async_client: AsyncMobilerun) -> None: + async with async_client.proxies.with_streaming_response.lookup( + socks5={ + "host": "host", + "port": 1, + }, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + proxy = await response.parse() + assert_matches_type(ProxyLookupResponse, proxy, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_tasks.py b/tests/api_resources/test_tasks.py index 05fcfdd..5dafda7 100644 --- a/tests/api_resources/test_tasks.py +++ b/tests/api_resources/test_tasks.py @@ -249,6 +249,7 @@ def test_method_run_with_all_params(self, client: Mobilerun) -> None: task = client.tasks.run( device_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", task="x", + accessibility=True, agent_id=0, apps=["string"], continue_on_failure=True, @@ -317,6 +318,7 @@ def test_method_run_streamed_with_all_params(self, client: Mobilerun) -> None: task = client.tasks.run_streamed( device_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", task="x", + accessibility=True, agent_id=0, apps=["string"], continue_on_failure=True, @@ -688,6 +690,7 @@ async def test_method_run_with_all_params(self, async_client: AsyncMobilerun) -> task = await async_client.tasks.run( device_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", task="x", + accessibility=True, agent_id=0, apps=["string"], continue_on_failure=True, @@ -756,6 +759,7 @@ async def test_method_run_streamed_with_all_params(self, async_client: AsyncMobi task = await async_client.tasks.run_streamed( device_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", task="x", + accessibility=True, agent_id=0, apps=["string"], continue_on_failure=True,