pymobiledevice3 5.0.4__py3-none-any.whl → 7.0.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- misc/understanding_idevice_protocol_layers.md +10 -5
- pymobiledevice3/__main__.py +171 -46
- pymobiledevice3/_version.py +2 -2
- pymobiledevice3/bonjour.py +22 -21
- pymobiledevice3/cli/activation.py +24 -22
- pymobiledevice3/cli/afc.py +49 -41
- pymobiledevice3/cli/amfi.py +13 -18
- pymobiledevice3/cli/apps.py +71 -65
- pymobiledevice3/cli/backup.py +134 -93
- pymobiledevice3/cli/bonjour.py +31 -29
- pymobiledevice3/cli/cli_common.py +175 -232
- pymobiledevice3/cli/companion_proxy.py +12 -12
- pymobiledevice3/cli/crash.py +95 -52
- pymobiledevice3/cli/developer/__init__.py +62 -0
- pymobiledevice3/cli/developer/accessibility/__init__.py +65 -0
- pymobiledevice3/cli/developer/accessibility/settings.py +43 -0
- pymobiledevice3/cli/developer/arbitration.py +50 -0
- pymobiledevice3/cli/developer/condition.py +33 -0
- pymobiledevice3/cli/developer/core_device.py +294 -0
- pymobiledevice3/cli/developer/debugserver.py +244 -0
- pymobiledevice3/cli/developer/dvt/__init__.py +438 -0
- pymobiledevice3/cli/developer/dvt/core_profile_session.py +295 -0
- pymobiledevice3/cli/developer/dvt/simulate_location.py +56 -0
- pymobiledevice3/cli/developer/dvt/sysmon/__init__.py +69 -0
- pymobiledevice3/cli/developer/dvt/sysmon/process.py +188 -0
- pymobiledevice3/cli/developer/fetch_symbols.py +108 -0
- pymobiledevice3/cli/developer/simulate_location.py +51 -0
- pymobiledevice3/cli/diagnostics/__init__.py +75 -0
- pymobiledevice3/cli/diagnostics/battery.py +47 -0
- pymobiledevice3/cli/idam.py +42 -0
- pymobiledevice3/cli/lockdown.py +70 -75
- pymobiledevice3/cli/mounter.py +99 -57
- pymobiledevice3/cli/notification.py +38 -26
- pymobiledevice3/cli/pcap.py +36 -20
- pymobiledevice3/cli/power_assertion.py +15 -16
- pymobiledevice3/cli/processes.py +11 -17
- pymobiledevice3/cli/profile.py +120 -75
- pymobiledevice3/cli/provision.py +27 -26
- pymobiledevice3/cli/remote.py +109 -100
- pymobiledevice3/cli/restore.py +134 -129
- pymobiledevice3/cli/springboard.py +50 -50
- pymobiledevice3/cli/syslog.py +145 -65
- pymobiledevice3/cli/usbmux.py +66 -27
- pymobiledevice3/cli/version.py +2 -5
- pymobiledevice3/cli/webinspector.py +232 -156
- pymobiledevice3/exceptions.py +6 -2
- pymobiledevice3/lockdown.py +5 -1
- pymobiledevice3/lockdown_service_provider.py +5 -0
- pymobiledevice3/remote/remote_service_discovery.py +18 -10
- pymobiledevice3/restore/device.py +28 -4
- pymobiledevice3/restore/restore.py +2 -2
- pymobiledevice3/service_connection.py +15 -12
- pymobiledevice3/services/afc.py +731 -220
- pymobiledevice3/services/device_link.py +45 -31
- pymobiledevice3/services/idam.py +20 -0
- pymobiledevice3/services/lockdown_service.py +12 -9
- pymobiledevice3/services/mobile_config.py +1 -0
- pymobiledevice3/services/mobilebackup2.py +6 -3
- pymobiledevice3/services/os_trace.py +97 -55
- pymobiledevice3/services/remote_fetch_symbols.py +13 -8
- pymobiledevice3/services/screenshot.py +2 -2
- pymobiledevice3/services/web_protocol/alert.py +8 -8
- pymobiledevice3/services/web_protocol/automation_session.py +87 -79
- pymobiledevice3/services/web_protocol/cdp_screencast.py +2 -1
- pymobiledevice3/services/web_protocol/driver.py +71 -70
- pymobiledevice3/services/web_protocol/element.py +58 -56
- pymobiledevice3/services/web_protocol/selenium_api.py +47 -47
- pymobiledevice3/services/web_protocol/session_protocol.py +3 -2
- pymobiledevice3/services/web_protocol/switch_to.py +23 -19
- pymobiledevice3/services/webinspector.py +42 -67
- {pymobiledevice3-5.0.4.dist-info → pymobiledevice3-7.0.6.dist-info}/METADATA +5 -3
- {pymobiledevice3-5.0.4.dist-info → pymobiledevice3-7.0.6.dist-info}/RECORD +76 -61
- pymobiledevice3/cli/completions.py +0 -50
- pymobiledevice3/cli/developer.py +0 -1539
- pymobiledevice3/cli/diagnostics.py +0 -110
- {pymobiledevice3-5.0.4.dist-info → pymobiledevice3-7.0.6.dist-info}/WHEEL +0 -0
- {pymobiledevice3-5.0.4.dist-info → pymobiledevice3-7.0.6.dist-info}/entry_points.txt +0 -0
- {pymobiledevice3-5.0.4.dist-info → pymobiledevice3-7.0.6.dist-info}/licenses/LICENSE +0 -0
- {pymobiledevice3-5.0.4.dist-info → pymobiledevice3-7.0.6.dist-info}/top_level.txt +0 -0
pymobiledevice3/cli/profile.py
CHANGED
|
@@ -2,41 +2,45 @@ import logging
|
|
|
2
2
|
import plistlib
|
|
3
3
|
import tempfile
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import Annotated, Literal, Optional
|
|
6
6
|
|
|
7
|
-
import
|
|
7
|
+
import typer
|
|
8
|
+
from typer_injector import InjectingTyper
|
|
8
9
|
|
|
9
10
|
from pymobiledevice3.ca import create_keybag_file
|
|
10
|
-
from pymobiledevice3.cli.cli_common import
|
|
11
|
-
from pymobiledevice3.lockdown import LockdownClient
|
|
12
|
-
from pymobiledevice3.lockdown_service_provider import LockdownServiceProvider
|
|
11
|
+
from pymobiledevice3.cli.cli_common import ServiceProviderDep, print_json
|
|
13
12
|
from pymobiledevice3.services.mobile_activation import MobileActivationService
|
|
14
13
|
from pymobiledevice3.services.mobile_config import MobileConfigService
|
|
15
14
|
|
|
16
15
|
logger = logging.getLogger(__name__)
|
|
17
16
|
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
@cli.group("profile")
|
|
25
|
-
def profile_group() -> None:
|
|
26
|
-
"""Managed installed profiles or install SSL certificates"""
|
|
27
|
-
pass
|
|
18
|
+
cli = InjectingTyper(
|
|
19
|
+
name="profile",
|
|
20
|
+
help="Manage installed profiles or install SSL certificates",
|
|
21
|
+
no_args_is_help=True,
|
|
22
|
+
)
|
|
28
23
|
|
|
29
24
|
|
|
30
|
-
@
|
|
31
|
-
def profile_list(service_provider:
|
|
25
|
+
@cli.command("list")
|
|
26
|
+
def profile_list(service_provider: ServiceProviderDep) -> None:
|
|
32
27
|
"""List installed profiles"""
|
|
33
28
|
print_json(MobileConfigService(lockdown=service_provider).get_profile_list())
|
|
34
29
|
|
|
35
30
|
|
|
36
|
-
@
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
31
|
+
@cli.command("install")
|
|
32
|
+
def profile_install(
|
|
33
|
+
service_provider: ServiceProviderDep,
|
|
34
|
+
profiles: list[Path],
|
|
35
|
+
keybag: Annotated[
|
|
36
|
+
Optional[Path],
|
|
37
|
+
typer.Option(
|
|
38
|
+
exists=True,
|
|
39
|
+
file_okay=True,
|
|
40
|
+
dir_okay=False,
|
|
41
|
+
),
|
|
42
|
+
] = None,
|
|
43
|
+
) -> None:
|
|
40
44
|
"""
|
|
41
45
|
Install given profiles
|
|
42
46
|
|
|
@@ -44,61 +48,58 @@ def profile_install(service_provider: LockdownServiceProvider, keybag: Optional[
|
|
|
44
48
|
"""
|
|
45
49
|
service = MobileConfigService(lockdown=service_provider)
|
|
46
50
|
for profile in profiles:
|
|
47
|
-
logger.info(f"installing {profile
|
|
51
|
+
logger.info(f"installing {profile}")
|
|
48
52
|
if keybag is not None:
|
|
49
|
-
service.install_profile_silent(Path(keybag), profile.
|
|
53
|
+
service.install_profile_silent(Path(keybag), profile.read_bytes())
|
|
50
54
|
else:
|
|
51
|
-
service.install_profile(profile.
|
|
55
|
+
service.install_profile(profile.read_bytes())
|
|
52
56
|
|
|
53
57
|
|
|
54
|
-
@
|
|
55
|
-
|
|
56
|
-
def profile_cloud_configuration(service_provider: LockdownServiceProvider, config: Optional[IO]) -> None:
|
|
58
|
+
@cli.command("cloud-configuration")
|
|
59
|
+
def profile_cloud_configuration(service_provider: ServiceProviderDep, config: Optional[Path] = None) -> None:
|
|
57
60
|
"""Get/Set cloud configuration"""
|
|
58
61
|
if not config:
|
|
59
62
|
print_json(MobileConfigService(lockdown=service_provider).get_cloud_configuration())
|
|
60
63
|
else:
|
|
61
|
-
|
|
64
|
+
with config.open("rb") as config_file:
|
|
65
|
+
config_json = plistlib.load(config_file)
|
|
62
66
|
logger.info(f"applying cloud configuration {config_json}")
|
|
63
67
|
MobileConfigService(lockdown=service_provider).set_cloud_configuration(config_json)
|
|
64
68
|
logger.info("applied cloud configuration")
|
|
65
69
|
|
|
66
70
|
|
|
67
|
-
@
|
|
68
|
-
|
|
69
|
-
def profile_store(service_provider: LockdownServiceProvider, profiles: list[IO]) -> None:
|
|
71
|
+
@cli.command("store")
|
|
72
|
+
def profile_store(service_provider: ServiceProviderDep, profiles: list[Path]) -> None:
|
|
70
73
|
"""Store a profile"""
|
|
71
74
|
service = MobileConfigService(lockdown=service_provider)
|
|
72
75
|
for profile in profiles:
|
|
73
76
|
logger.info(f"storing {profile.name}")
|
|
74
|
-
service.store_profile(profile.
|
|
77
|
+
service.store_profile(profile.read_bytes())
|
|
75
78
|
|
|
76
79
|
|
|
77
|
-
@
|
|
78
|
-
|
|
79
|
-
def profile_remove(service_provider: LockdownServiceProvider, name: str) -> None:
|
|
80
|
+
@cli.command("remove")
|
|
81
|
+
def profile_remove(service_provider: ServiceProviderDep, name: str) -> None:
|
|
80
82
|
"""Remove a profile by its name"""
|
|
81
83
|
MobileConfigService(lockdown=service_provider).remove_profile(name)
|
|
82
84
|
|
|
83
85
|
|
|
84
|
-
@
|
|
85
|
-
|
|
86
|
-
def profile_set_wifi_power(service_provider: LockdownServiceProvider, state: str) -> None:
|
|
86
|
+
@cli.command("set-wifi-power")
|
|
87
|
+
def profile_set_wifi_power(service_provider: ServiceProviderDep, state: Literal["on", "off"] = "off") -> None:
|
|
87
88
|
"""change Wi-Fi power state"""
|
|
88
89
|
MobileConfigService(lockdown=service_provider).set_wifi_power_state(state == "on")
|
|
89
90
|
|
|
90
91
|
|
|
91
|
-
@
|
|
92
|
-
@click.option(
|
|
93
|
-
"--preserve-data-plan/--no-preserve-data-plan", default=True, help="Preserves eSIM / data plan after erase"
|
|
94
|
-
)
|
|
95
|
-
@click.option(
|
|
96
|
-
"--disallow-proximity-setup/--no-disallow-proximity-setup",
|
|
97
|
-
default=False,
|
|
98
|
-
help="Disallows to setup the erased device from nearby devices",
|
|
99
|
-
)
|
|
92
|
+
@cli.command("erase-device")
|
|
100
93
|
def profile_erase_device(
|
|
101
|
-
service_provider:
|
|
94
|
+
service_provider: ServiceProviderDep,
|
|
95
|
+
preserve_data_plan: Annotated[
|
|
96
|
+
bool,
|
|
97
|
+
typer.Option(help="Preserves eSIM / data plan after erase"),
|
|
98
|
+
] = True,
|
|
99
|
+
disallow_proximity_setup: Annotated[
|
|
100
|
+
bool,
|
|
101
|
+
typer.Option(help="Disallows setup of the erased device from nearby devices"),
|
|
102
|
+
] = False,
|
|
102
103
|
) -> None:
|
|
103
104
|
"""Erase device"""
|
|
104
105
|
logger.info(
|
|
@@ -109,18 +110,35 @@ def profile_erase_device(
|
|
|
109
110
|
logger.info("Erased device")
|
|
110
111
|
|
|
111
112
|
|
|
112
|
-
@
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
113
|
+
@cli.command("create-keybag")
|
|
114
|
+
def profile_create_keybag(
|
|
115
|
+
keybag: Annotated[
|
|
116
|
+
Path,
|
|
117
|
+
typer.Argument(
|
|
118
|
+
exists=False,
|
|
119
|
+
file_okay=True,
|
|
120
|
+
dir_okay=False,
|
|
121
|
+
),
|
|
122
|
+
],
|
|
123
|
+
organization: str,
|
|
124
|
+
) -> None:
|
|
116
125
|
"""Create keybag storing certificate and private key"""
|
|
117
|
-
create_keybag_file(
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
@
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
126
|
+
create_keybag_file(keybag, organization)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
@cli.command("supervise")
|
|
130
|
+
def profile_supervise(
|
|
131
|
+
service_provider: ServiceProviderDep,
|
|
132
|
+
organization: str,
|
|
133
|
+
keybag: Annotated[
|
|
134
|
+
Optional[Path],
|
|
135
|
+
typer.Option(
|
|
136
|
+
exists=True,
|
|
137
|
+
file_okay=True,
|
|
138
|
+
dir_okay=False,
|
|
139
|
+
),
|
|
140
|
+
] = None,
|
|
141
|
+
) -> None:
|
|
124
142
|
"""Supervise device"""
|
|
125
143
|
if MobileActivationService(service_provider).state == "Unactivated":
|
|
126
144
|
logger.info("Activating device")
|
|
@@ -138,13 +156,20 @@ def profile_supervise(service_provider: LockdownServiceProvider, organization: s
|
|
|
138
156
|
logger.info("Device has been successfully supervised")
|
|
139
157
|
|
|
140
158
|
|
|
141
|
-
@
|
|
142
|
-
@click.argument("encryption_type")
|
|
143
|
-
@click.argument("ssid")
|
|
144
|
-
@click.argument("password")
|
|
145
|
-
@click.option("--keybag", type=click.Path(file_okay=True, dir_okay=False, exists=True))
|
|
159
|
+
@cli.command("install-wifi-profile")
|
|
146
160
|
def profile_install_wifi_profile(
|
|
147
|
-
service_provider:
|
|
161
|
+
service_provider: ServiceProviderDep,
|
|
162
|
+
encryption_type: str,
|
|
163
|
+
ssid: str,
|
|
164
|
+
password: str,
|
|
165
|
+
keybag: Annotated[
|
|
166
|
+
Optional[Path],
|
|
167
|
+
typer.Option(
|
|
168
|
+
exists=True,
|
|
169
|
+
file_okay=True,
|
|
170
|
+
dir_okay=False,
|
|
171
|
+
),
|
|
172
|
+
] = None,
|
|
148
173
|
) -> None:
|
|
149
174
|
"""
|
|
150
175
|
Install Wi-Fi profile
|
|
@@ -158,12 +183,22 @@ def profile_install_wifi_profile(
|
|
|
158
183
|
)
|
|
159
184
|
|
|
160
185
|
|
|
161
|
-
@
|
|
162
|
-
@click.argument("server")
|
|
163
|
-
@click.argument("port", type=click.IntRange(1, 65535))
|
|
164
|
-
@click.option("--keybag", type=click.Path(file_okay=True, dir_okay=False, exists=True))
|
|
186
|
+
@cli.command("install-http-proxy")
|
|
165
187
|
def profile_install_http_proxy(
|
|
166
|
-
service_provider:
|
|
188
|
+
service_provider: ServiceProviderDep,
|
|
189
|
+
server: str,
|
|
190
|
+
port: Annotated[
|
|
191
|
+
int,
|
|
192
|
+
typer.Argument(min=1, max=0xFFFF),
|
|
193
|
+
],
|
|
194
|
+
keybag: Annotated[
|
|
195
|
+
Optional[Path],
|
|
196
|
+
typer.Option(
|
|
197
|
+
exists=True,
|
|
198
|
+
file_okay=True,
|
|
199
|
+
dir_okay=False,
|
|
200
|
+
),
|
|
201
|
+
] = None,
|
|
167
202
|
) -> None:
|
|
168
203
|
"""Install HTTP Proxy profile"""
|
|
169
204
|
if keybag is not None:
|
|
@@ -171,17 +206,27 @@ def profile_install_http_proxy(
|
|
|
171
206
|
MobileConfigService(lockdown=service_provider).install_http_proxy(server, port, keybag_file=keybag)
|
|
172
207
|
|
|
173
208
|
|
|
174
|
-
@
|
|
175
|
-
def profile_remove_http_proxy(service_provider:
|
|
209
|
+
@cli.command("remove-http-proxy")
|
|
210
|
+
def profile_remove_http_proxy(service_provider: ServiceProviderDep) -> None:
|
|
176
211
|
"""Remove HTTP Proxy profile that was previously installed using pymobiledevice3"""
|
|
177
212
|
MobileConfigService(lockdown=service_provider).remove_http_proxy()
|
|
178
213
|
|
|
179
214
|
|
|
180
|
-
@
|
|
181
|
-
@click.option("--keybag", type=click.Path(file_okay=True, dir_okay=False, exists=True))
|
|
182
|
-
@click.option("--enforced-software-update-delay", type=click.IntRange(0, 90), default=0)
|
|
215
|
+
@cli.command("install-restrictions-profile")
|
|
183
216
|
def profile_install_restrictions_profile(
|
|
184
|
-
service_provider:
|
|
217
|
+
service_provider: ServiceProviderDep,
|
|
218
|
+
keybag: Annotated[
|
|
219
|
+
Optional[Path],
|
|
220
|
+
typer.Option(
|
|
221
|
+
exists=True,
|
|
222
|
+
file_okay=True,
|
|
223
|
+
dir_okay=False,
|
|
224
|
+
),
|
|
225
|
+
] = None,
|
|
226
|
+
enforced_software_update_delay: Annotated[
|
|
227
|
+
int,
|
|
228
|
+
typer.Option(min=0, max=90),
|
|
229
|
+
] = 0,
|
|
185
230
|
) -> None:
|
|
186
231
|
"""Install restrictions profile (can be used for delayed OTA)"""
|
|
187
232
|
if keybag is not None:
|
pymobiledevice3/cli/provision.py
CHANGED
|
@@ -1,56 +1,57 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from pathlib import Path
|
|
3
|
+
from typing import Annotated
|
|
3
4
|
|
|
4
|
-
import
|
|
5
|
+
import typer
|
|
6
|
+
from typer_injector import InjectingTyper
|
|
5
7
|
|
|
6
|
-
from pymobiledevice3.cli.cli_common import
|
|
7
|
-
from pymobiledevice3.lockdown import LockdownClient
|
|
8
|
+
from pymobiledevice3.cli.cli_common import ServiceProviderDep, print_json
|
|
8
9
|
from pymobiledevice3.services.misagent import MisagentService
|
|
9
10
|
|
|
10
11
|
logger = logging.getLogger(__name__)
|
|
11
12
|
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
cli = InjectingTyper(
|
|
15
|
+
name="provision",
|
|
16
|
+
help="Manage installed provision profiles",
|
|
17
|
+
no_args_is_help=True,
|
|
18
|
+
)
|
|
16
19
|
|
|
17
20
|
|
|
18
|
-
@cli.
|
|
19
|
-
def
|
|
20
|
-
"""Manage installed provision profiles"""
|
|
21
|
-
pass
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
@provision.command("install", cls=Command)
|
|
25
|
-
@click.argument("profile", type=click.File("rb"))
|
|
26
|
-
def provision_install(service_provider: LockdownClient, profile):
|
|
21
|
+
@cli.command("install")
|
|
22
|
+
def provision_install(service_provider: ServiceProviderDep, profile: Path) -> None:
|
|
27
23
|
"""install a provision profile (.mobileprovision file)"""
|
|
28
|
-
|
|
24
|
+
with profile.open("rb") as profile_file:
|
|
25
|
+
MisagentService(lockdown=service_provider).install(profile_file)
|
|
29
26
|
|
|
30
27
|
|
|
31
|
-
@
|
|
32
|
-
|
|
33
|
-
def provision_remove(service_provider: LockdownClient, profile_id):
|
|
28
|
+
@cli.command("remove")
|
|
29
|
+
def provision_remove(service_provider: ServiceProviderDep, profile_id: str) -> None:
|
|
34
30
|
"""remove a provision profile"""
|
|
35
31
|
MisagentService(lockdown=service_provider).remove(profile_id)
|
|
36
32
|
|
|
37
33
|
|
|
38
|
-
@
|
|
39
|
-
def provision_clear(service_provider:
|
|
34
|
+
@cli.command("clear")
|
|
35
|
+
def provision_clear(service_provider: ServiceProviderDep) -> None:
|
|
40
36
|
"""remove all provision profiles"""
|
|
41
37
|
for profile in MisagentService(lockdown=service_provider).copy_all():
|
|
42
38
|
MisagentService(lockdown=service_provider).remove(profile.plist["UUID"])
|
|
43
39
|
|
|
44
40
|
|
|
45
|
-
@
|
|
46
|
-
def provision_list(service_provider:
|
|
41
|
+
@cli.command("list")
|
|
42
|
+
def provision_list(service_provider: ServiceProviderDep) -> None:
|
|
47
43
|
"""list installed provision profiles"""
|
|
48
44
|
print_json([p.plist for p in MisagentService(lockdown=service_provider).copy_all()])
|
|
49
45
|
|
|
50
46
|
|
|
51
|
-
@
|
|
52
|
-
|
|
53
|
-
|
|
47
|
+
@cli.command("dump")
|
|
48
|
+
def provision_dump(
|
|
49
|
+
service_provider: ServiceProviderDep,
|
|
50
|
+
out: Annotated[
|
|
51
|
+
Path,
|
|
52
|
+
typer.Argument(file_okay=False, dir_okay=True, exists=True),
|
|
53
|
+
],
|
|
54
|
+
) -> None:
|
|
54
55
|
"""dump installed provision profiles to specified location"""
|
|
55
56
|
for profile in MisagentService(lockdown=service_provider).copy_all():
|
|
56
57
|
filename = f"{profile.plist['UUID']}.mobileprovision"
|