pymobiledevice3 4.14.6__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.
Files changed (164) hide show
  1. misc/plist_sniffer.py +15 -15
  2. misc/remotexpc_sniffer.py +29 -28
  3. misc/understanding_idevice_protocol_layers.md +15 -10
  4. pymobiledevice3/__main__.py +317 -127
  5. pymobiledevice3/_version.py +22 -4
  6. pymobiledevice3/bonjour.py +358 -113
  7. pymobiledevice3/ca.py +253 -16
  8. pymobiledevice3/cli/activation.py +31 -23
  9. pymobiledevice3/cli/afc.py +49 -40
  10. pymobiledevice3/cli/amfi.py +16 -21
  11. pymobiledevice3/cli/apps.py +87 -42
  12. pymobiledevice3/cli/backup.py +160 -90
  13. pymobiledevice3/cli/bonjour.py +44 -40
  14. pymobiledevice3/cli/cli_common.py +204 -198
  15. pymobiledevice3/cli/companion_proxy.py +14 -14
  16. pymobiledevice3/cli/crash.py +105 -56
  17. pymobiledevice3/cli/developer/__init__.py +62 -0
  18. pymobiledevice3/cli/developer/accessibility/__init__.py +65 -0
  19. pymobiledevice3/cli/developer/accessibility/settings.py +43 -0
  20. pymobiledevice3/cli/developer/arbitration.py +50 -0
  21. pymobiledevice3/cli/developer/condition.py +33 -0
  22. pymobiledevice3/cli/developer/core_device.py +294 -0
  23. pymobiledevice3/cli/developer/debugserver.py +244 -0
  24. pymobiledevice3/cli/developer/dvt/__init__.py +438 -0
  25. pymobiledevice3/cli/developer/dvt/core_profile_session.py +295 -0
  26. pymobiledevice3/cli/developer/dvt/simulate_location.py +56 -0
  27. pymobiledevice3/cli/developer/dvt/sysmon/__init__.py +69 -0
  28. pymobiledevice3/cli/developer/dvt/sysmon/process.py +188 -0
  29. pymobiledevice3/cli/developer/fetch_symbols.py +108 -0
  30. pymobiledevice3/cli/developer/simulate_location.py +51 -0
  31. pymobiledevice3/cli/diagnostics/__init__.py +75 -0
  32. pymobiledevice3/cli/diagnostics/battery.py +47 -0
  33. pymobiledevice3/cli/idam.py +42 -0
  34. pymobiledevice3/cli/lockdown.py +108 -103
  35. pymobiledevice3/cli/mounter.py +158 -99
  36. pymobiledevice3/cli/notification.py +38 -26
  37. pymobiledevice3/cli/pcap.py +45 -24
  38. pymobiledevice3/cli/power_assertion.py +18 -17
  39. pymobiledevice3/cli/processes.py +17 -23
  40. pymobiledevice3/cli/profile.py +165 -109
  41. pymobiledevice3/cli/provision.py +35 -34
  42. pymobiledevice3/cli/remote.py +217 -129
  43. pymobiledevice3/cli/restore.py +159 -143
  44. pymobiledevice3/cli/springboard.py +63 -53
  45. pymobiledevice3/cli/syslog.py +193 -86
  46. pymobiledevice3/cli/usbmux.py +73 -33
  47. pymobiledevice3/cli/version.py +5 -7
  48. pymobiledevice3/cli/webinspector.py +376 -214
  49. pymobiledevice3/common.py +3 -1
  50. pymobiledevice3/exceptions.py +182 -58
  51. pymobiledevice3/irecv.py +52 -53
  52. pymobiledevice3/irecv_devices.py +1489 -464
  53. pymobiledevice3/lockdown.py +473 -275
  54. pymobiledevice3/lockdown_service_provider.py +15 -8
  55. pymobiledevice3/osu/os_utils.py +27 -9
  56. pymobiledevice3/osu/posix_util.py +34 -15
  57. pymobiledevice3/osu/win_util.py +14 -8
  58. pymobiledevice3/pair_records.py +102 -21
  59. pymobiledevice3/remote/common.py +8 -4
  60. pymobiledevice3/remote/core_device/app_service.py +94 -67
  61. pymobiledevice3/remote/core_device/core_device_service.py +17 -14
  62. pymobiledevice3/remote/core_device/device_info.py +5 -5
  63. pymobiledevice3/remote/core_device/diagnostics_service.py +19 -4
  64. pymobiledevice3/remote/core_device/file_service.py +53 -23
  65. pymobiledevice3/remote/remote_service_discovery.py +79 -45
  66. pymobiledevice3/remote/remotexpc.py +73 -44
  67. pymobiledevice3/remote/tunnel_service.py +442 -317
  68. pymobiledevice3/remote/utils.py +14 -13
  69. pymobiledevice3/remote/xpc_message.py +145 -125
  70. pymobiledevice3/resources/dsc_uuid_map.py +19 -19
  71. pymobiledevice3/resources/firmware_notifications.py +20 -16
  72. pymobiledevice3/resources/notifications.txt +144 -0
  73. pymobiledevice3/restore/asr.py +27 -27
  74. pymobiledevice3/restore/base_restore.py +110 -21
  75. pymobiledevice3/restore/consts.py +87 -66
  76. pymobiledevice3/restore/device.py +59 -12
  77. pymobiledevice3/restore/fdr.py +46 -48
  78. pymobiledevice3/restore/ftab.py +19 -19
  79. pymobiledevice3/restore/img4.py +163 -0
  80. pymobiledevice3/restore/mbn.py +587 -0
  81. pymobiledevice3/restore/recovery.py +151 -151
  82. pymobiledevice3/restore/restore.py +562 -544
  83. pymobiledevice3/restore/restore_options.py +131 -110
  84. pymobiledevice3/restore/restored_client.py +51 -31
  85. pymobiledevice3/restore/tss.py +385 -267
  86. pymobiledevice3/service_connection.py +252 -59
  87. pymobiledevice3/services/accessibilityaudit.py +202 -120
  88. pymobiledevice3/services/afc.py +962 -365
  89. pymobiledevice3/services/amfi.py +24 -30
  90. pymobiledevice3/services/companion.py +23 -19
  91. pymobiledevice3/services/crash_reports.py +71 -47
  92. pymobiledevice3/services/debugserver_applist.py +3 -3
  93. pymobiledevice3/services/device_arbitration.py +8 -8
  94. pymobiledevice3/services/device_link.py +101 -79
  95. pymobiledevice3/services/diagnostics.py +973 -967
  96. pymobiledevice3/services/dtfetchsymbols.py +8 -8
  97. pymobiledevice3/services/dvt/dvt_secure_socket_proxy.py +4 -4
  98. pymobiledevice3/services/dvt/dvt_testmanaged_proxy.py +4 -4
  99. pymobiledevice3/services/dvt/instruments/activity_trace_tap.py +85 -74
  100. pymobiledevice3/services/dvt/instruments/application_listing.py +2 -3
  101. pymobiledevice3/services/dvt/instruments/condition_inducer.py +7 -6
  102. pymobiledevice3/services/dvt/instruments/core_profile_session_tap.py +466 -384
  103. pymobiledevice3/services/dvt/instruments/device_info.py +20 -11
  104. pymobiledevice3/services/dvt/instruments/energy_monitor.py +1 -1
  105. pymobiledevice3/services/dvt/instruments/graphics.py +1 -1
  106. pymobiledevice3/services/dvt/instruments/location_simulation.py +1 -1
  107. pymobiledevice3/services/dvt/instruments/location_simulation_base.py +10 -10
  108. pymobiledevice3/services/dvt/instruments/network_monitor.py +17 -17
  109. pymobiledevice3/services/dvt/instruments/notifications.py +1 -1
  110. pymobiledevice3/services/dvt/instruments/process_control.py +35 -10
  111. pymobiledevice3/services/dvt/instruments/screenshot.py +2 -2
  112. pymobiledevice3/services/dvt/instruments/sysmontap.py +15 -15
  113. pymobiledevice3/services/dvt/testmanaged/xcuitest.py +42 -52
  114. pymobiledevice3/services/file_relay.py +10 -10
  115. pymobiledevice3/services/heartbeat.py +9 -8
  116. pymobiledevice3/services/house_arrest.py +16 -15
  117. pymobiledevice3/services/idam.py +20 -0
  118. pymobiledevice3/services/installation_proxy.py +173 -81
  119. pymobiledevice3/services/lockdown_service.py +20 -10
  120. pymobiledevice3/services/misagent.py +22 -19
  121. pymobiledevice3/services/mobile_activation.py +147 -64
  122. pymobiledevice3/services/mobile_config.py +331 -294
  123. pymobiledevice3/services/mobile_image_mounter.py +141 -113
  124. pymobiledevice3/services/mobilebackup2.py +203 -145
  125. pymobiledevice3/services/notification_proxy.py +11 -11
  126. pymobiledevice3/services/os_trace.py +134 -74
  127. pymobiledevice3/services/pcapd.py +314 -302
  128. pymobiledevice3/services/power_assertion.py +10 -9
  129. pymobiledevice3/services/preboard.py +4 -4
  130. pymobiledevice3/services/remote_fetch_symbols.py +21 -14
  131. pymobiledevice3/services/remote_server.py +176 -146
  132. pymobiledevice3/services/restore_service.py +16 -16
  133. pymobiledevice3/services/screenshot.py +15 -12
  134. pymobiledevice3/services/simulate_location.py +7 -7
  135. pymobiledevice3/services/springboard.py +15 -15
  136. pymobiledevice3/services/syslog.py +5 -5
  137. pymobiledevice3/services/web_protocol/alert.py +11 -11
  138. pymobiledevice3/services/web_protocol/automation_session.py +251 -239
  139. pymobiledevice3/services/web_protocol/cdp_screencast.py +46 -37
  140. pymobiledevice3/services/web_protocol/cdp_server.py +19 -19
  141. pymobiledevice3/services/web_protocol/cdp_target.py +411 -373
  142. pymobiledevice3/services/web_protocol/driver.py +114 -111
  143. pymobiledevice3/services/web_protocol/element.py +124 -111
  144. pymobiledevice3/services/web_protocol/inspector_session.py +106 -102
  145. pymobiledevice3/services/web_protocol/selenium_api.py +49 -49
  146. pymobiledevice3/services/web_protocol/session_protocol.py +18 -12
  147. pymobiledevice3/services/web_protocol/switch_to.py +30 -27
  148. pymobiledevice3/services/webinspector.py +189 -155
  149. pymobiledevice3/tcp_forwarder.py +87 -69
  150. pymobiledevice3/tunneld/__init__.py +0 -0
  151. pymobiledevice3/tunneld/api.py +63 -0
  152. pymobiledevice3/tunneld/server.py +603 -0
  153. pymobiledevice3/usbmux.py +198 -147
  154. pymobiledevice3/utils.py +14 -11
  155. {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/METADATA +55 -28
  156. pymobiledevice3-7.0.6.dist-info/RECORD +188 -0
  157. {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/WHEEL +1 -1
  158. pymobiledevice3/cli/developer.py +0 -1215
  159. pymobiledevice3/cli/diagnostics.py +0 -99
  160. pymobiledevice3/tunneld.py +0 -524
  161. pymobiledevice3-4.14.6.dist-info/RECORD +0 -168
  162. {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/entry_points.txt +0 -0
  163. {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info/licenses}/LICENSE +0 -0
  164. {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/top_level.txt +0 -0
@@ -1,82 +1,131 @@
1
- import click
1
+ from pathlib import Path
2
+ from typing import Annotated, Optional
2
3
 
3
- from pymobiledevice3.cli.cli_common import Command
4
- from pymobiledevice3.lockdown import LockdownClient
5
- from pymobiledevice3.lockdown_service_provider import LockdownServiceProvider
6
- from pymobiledevice3.services.crash_reports import CrashReportsManager, CrashReportsShell
7
-
8
-
9
- @click.group()
10
- def cli() -> None:
11
- pass
12
-
13
-
14
- @cli.group()
15
- def crash() -> None:
16
- """ Manage crash reports """
17
- pass
4
+ import typer
5
+ from typer_injector import InjectingTyper
18
6
 
7
+ from pymobiledevice3.cli.cli_common import ServiceProviderDep
8
+ from pymobiledevice3.services.crash_reports import CrashReportsManager, CrashReportsShell
19
9
 
20
- @crash.command('clear', cls=Command)
21
- @click.option('-f', '--flush', is_flag=True, default=False, help='flush before clear')
22
- def crash_clear(service_provider: LockdownClient, flush):
23
- """ clear(/remove) all crash reports """
10
+ cli = InjectingTyper(
11
+ name="crash",
12
+ help="Manage crash reports",
13
+ no_args_is_help=True,
14
+ )
15
+
16
+
17
+ @cli.command("clear")
18
+ def crash_clear(
19
+ service_provider: ServiceProviderDep,
20
+ flush: Annotated[
21
+ bool,
22
+ typer.Option(
23
+ "--flush",
24
+ "-f",
25
+ help="flush before clear",
26
+ ),
27
+ ] = False,
28
+ ) -> None:
29
+ """clear(/remove) all crash reports"""
24
30
  crash_manager = CrashReportsManager(service_provider)
25
31
  if flush:
26
32
  crash_manager.flush()
27
33
  crash_manager.clear()
28
34
 
29
35
 
30
- @crash.command('pull', cls=Command)
31
- @click.argument('out', type=click.Path(file_okay=False))
32
- @click.argument('remote_file', type=click.Path(), required=False)
33
- @click.option('-e', '--erase', is_flag=True)
34
- @click.option('-m', '--match', help='Match given regex over enumerated basenames')
35
- def crash_pull(service_provider: LockdownServiceProvider, out, remote_file, erase, match) -> None:
36
- """ pull all crash reports """
36
+ @cli.command("pull")
37
+ def crash_pull(
38
+ service_provider: ServiceProviderDep,
39
+ out: Annotated[
40
+ Path,
41
+ typer.Argument(file_okay=False),
42
+ ],
43
+ remote_file: Optional[Path] = None,
44
+ erase: Annotated[
45
+ bool,
46
+ typer.Option("--erase", "-e"),
47
+ ] = False,
48
+ match: Annotated[
49
+ Optional[str],
50
+ typer.Option(
51
+ "--match",
52
+ "-m",
53
+ help="Match given regex over enumerated basenames",
54
+ ),
55
+ ] = None,
56
+ ) -> None:
57
+ """pull all crash reports"""
37
58
  if remote_file is None:
38
- remote_file = '/'
39
- CrashReportsManager(service_provider).pull(out, remote_file, erase, match)
59
+ remote_file = Path("/")
60
+ CrashReportsManager(service_provider).pull(str(out), str(remote_file), erase, match)
40
61
 
41
62
 
42
- @crash.command('shell', cls=Command)
43
- def crash_shell(service_provider: LockdownClient):
44
- """ start an afc shell """
63
+ @cli.command("shell")
64
+ def crash_shell(service_provider: ServiceProviderDep) -> None:
65
+ """start an afc shell"""
45
66
  CrashReportsShell.create(service_provider)
46
67
 
47
68
 
48
- @crash.command('ls', cls=Command)
49
- @click.argument('remote_file', type=click.Path(), required=False)
50
- @click.option('-d', '--depth', type=click.INT, default=1)
51
- def crash_ls(service_provider: LockdownClient, remote_file, depth):
52
- """ List """
69
+ @cli.command("ls")
70
+ def crash_ls(
71
+ service_provider: ServiceProviderDep,
72
+ remote_file: Optional[Path] = None,
73
+ depth: Annotated[
74
+ int,
75
+ typer.Option("--depth", "-d"),
76
+ ] = 1,
77
+ ) -> None:
78
+ """List"""
53
79
  if remote_file is None:
54
- remote_file = '/'
55
- for path in CrashReportsManager(service_provider).ls(remote_file, depth):
80
+ remote_file = Path("/")
81
+ for path in CrashReportsManager(service_provider).ls(str(remote_file), depth):
56
82
  print(path)
57
83
 
58
84
 
59
- @crash.command('flush', cls=Command)
60
- def crash_mover_flush(service_provider: LockdownClient):
61
- """ trigger com.apple.crashreportmover to flush all products into CrashReports directory """
85
+ @cli.command("flush")
86
+ def crash_mover_flush(service_provider: ServiceProviderDep) -> None:
87
+ """trigger com.apple.crashreportmover to flush all products into CrashReports directory"""
62
88
  CrashReportsManager(service_provider).flush()
63
89
 
64
90
 
65
- @crash.command('watch', cls=Command)
66
- @click.argument('name', required=False)
67
- @click.option('-r', '--raw', is_flag=True)
68
- def crash_mover_watch(service_provider: LockdownClient, name, raw):
69
- """ watch for crash report generation """
91
+ @cli.command("watch")
92
+ def crash_watch(
93
+ service_provider: ServiceProviderDep,
94
+ name: Optional[str] = None,
95
+ raw: Annotated[
96
+ bool,
97
+ typer.Option("--raw", "-r"),
98
+ ] = False,
99
+ ) -> None:
100
+ """watch for crash report generation"""
70
101
  for crash_report in CrashReportsManager(service_provider).watch(name=name, raw=raw):
71
102
  print(crash_report)
72
103
 
73
104
 
74
- @crash.command('sysdiagnose', cls=Command)
75
- @click.argument('out', type=click.Path(exists=False, dir_okay=True, file_okay=True))
76
- @click.option('-e', '--erase', is_flag=True, help='erase file after pulling')
77
- @click.option('-t', '--timeout', default=None, show_default=True, type=click.FLOAT,
78
- help='Maximum time in seconds to wait for the completion of sysdiagnose archive')
79
- def crash_sysdiagnose(service_provider: LockdownClient, out, erase, timeout):
80
- """ get a sysdiagnose archive from device (requires user interaction) """
81
- print('Press Power+VolUp+VolDown for 0.215 seconds')
82
- CrashReportsManager(service_provider).get_new_sysdiagnose(out, erase=erase, timeout=timeout)
105
+ @cli.command("sysdiagnose")
106
+ def crash_sysdiagnose(
107
+ service_provider: ServiceProviderDep,
108
+ out: Annotated[
109
+ Path,
110
+ typer.Argument(exists=False, dir_okay=True, file_okay=True),
111
+ ],
112
+ erase: Annotated[
113
+ bool,
114
+ typer.Option(
115
+ "--erase",
116
+ "-e",
117
+ help="erase file after pulling",
118
+ ),
119
+ ] = False,
120
+ timeout: Annotated[
121
+ Optional[float],
122
+ typer.Option(
123
+ "--timeout",
124
+ "-t",
125
+ help="Maximum time in seconds to wait for the completion of sysdiagnose archive",
126
+ ),
127
+ ] = None,
128
+ ) -> None:
129
+ """get a sysdiagnose archive from device (requires user interaction)"""
130
+ print("Press Power+VolUp+VolDown for 0.215 seconds")
131
+ CrashReportsManager(service_provider).get_new_sysdiagnose(str(out), erase=erase, timeout=timeout)
@@ -0,0 +1,62 @@
1
+ from pathlib import Path
2
+ from textwrap import dedent
3
+ from typing import Annotated
4
+
5
+ import typer
6
+ from typer_injector import InjectingTyper
7
+
8
+ from pymobiledevice3.cli.cli_common import ServiceProviderDep
9
+ from pymobiledevice3.cli.developer import (
10
+ accessibility,
11
+ arbitration,
12
+ condition,
13
+ core_device,
14
+ debugserver,
15
+ dvt,
16
+ fetch_symbols,
17
+ simulate_location,
18
+ )
19
+ from pymobiledevice3.services.remote_server import RemoteServer
20
+ from pymobiledevice3.services.screenshot import ScreenshotService
21
+
22
+ cli = InjectingTyper(
23
+ name="developer",
24
+ help=dedent("""\
25
+ Developer tooling for iOS devices (requires Developer Mode + mounted DeveloperDiskImage).
26
+
27
+ These commands require the DeveloperDiskImage.dmg to be mounted on the device prior
28
+ to execution. You can achieve this using:
29
+
30
+ pymobiledevice3 mounter mount
31
+
32
+ Also, starting at iOS 17.0, a tunnel must be created to the device for the services
33
+ to be accessible. Therefore, every CLI command is retried with a `--tunnel` option
34
+ for implicitly accessing tunneld when necessary
35
+ """),
36
+ no_args_is_help=True,
37
+ )
38
+ cli.add_typer(dvt.cli)
39
+ cli.add_typer(fetch_symbols.cli)
40
+ cli.add_typer(simulate_location.cli)
41
+ cli.add_typer(accessibility.cli)
42
+ cli.add_typer(condition.cli)
43
+ cli.add_typer(debugserver.cli)
44
+ cli.add_typer(arbitration.cli)
45
+ cli.add_typer(core_device.cli)
46
+
47
+
48
+ @cli.command("shell")
49
+ def developer_shell(
50
+ service_provider: ServiceProviderDep,
51
+ service: str,
52
+ remove_ssl_context: Annotated[bool, typer.Option("--remove-ssl-context", "-r")] = False,
53
+ ) -> None:
54
+ """Open an IPython shell connected to a developer service (for exploration/R&D)."""
55
+ with RemoteServer(service_provider, service, remove_ssl_context) as service:
56
+ service.shell()
57
+
58
+
59
+ @cli.command()
60
+ def screenshot(service_provider: ServiceProviderDep, out: Path) -> None:
61
+ """Capture a PNG screenshot (Depcrecated API)."""
62
+ out.write_bytes(ScreenshotService(lockdown=service_provider).take_screenshot())
@@ -0,0 +1,65 @@
1
+ import logging
2
+
3
+ from typer_injector import InjectingTyper
4
+
5
+ from pymobiledevice3.cli.cli_common import ServiceProviderDep, print_json
6
+ from pymobiledevice3.cli.developer.accessibility import settings
7
+ from pymobiledevice3.services.accessibilityaudit import AccessibilityAudit
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+
12
+ cli = InjectingTyper(
13
+ name="accessibility",
14
+ help="Interact with accessibility-related features",
15
+ no_args_is_help=True,
16
+ )
17
+ cli.add_typer(settings.cli)
18
+
19
+
20
+ @cli.command("run-audit")
21
+ def accessibility_run_audit(service_provider: ServiceProviderDep, test_types: list[str]) -> None:
22
+ """runs accessibility audit tests"""
23
+ audit_issues = AccessibilityAudit(service_provider).run_audit(test_types)
24
+ print_json([audit_issue.json() for audit_issue in audit_issues], False)
25
+
26
+
27
+ @cli.command("supported-audit-types")
28
+ def accessibility_supported_audit_types(service_provider: ServiceProviderDep) -> None:
29
+ """lists supported accessibility audit test types"""
30
+ print_json(AccessibilityAudit(service_provider).supported_audits_types())
31
+
32
+
33
+ @cli.command("capabilities")
34
+ def accessibility_capabilities(service_provider: ServiceProviderDep) -> None:
35
+ """display accessibility capabilities"""
36
+ print_json(AccessibilityAudit(service_provider).capabilities)
37
+
38
+
39
+ @cli.command("shell")
40
+ def accessibility_shell(service_provider: ServiceProviderDep) -> None:
41
+ """start and ipython accessibility shell"""
42
+ AccessibilityAudit(service_provider).shell()
43
+
44
+
45
+ @cli.command("notifications")
46
+ def accessibility_notifications(service_provider: ServiceProviderDep) -> None:
47
+ """show notifications"""
48
+ service = AccessibilityAudit(service_provider)
49
+ for event in service.iter_events():
50
+ if event.name in (
51
+ "hostAppStateChanged:",
52
+ "hostInspectorCurrentElementChanged:",
53
+ ):
54
+ for focus_item in event.data:
55
+ logger.info(focus_item)
56
+
57
+
58
+ @cli.command("list-items")
59
+ def accessibility_list_items(service_provider: ServiceProviderDep) -> None:
60
+ """List elements available in the currently shown menu."""
61
+ elements = []
62
+ with AccessibilityAudit(service_provider) as service:
63
+ for element in service.iter_elements():
64
+ elements.append(element.to_dict())
65
+ print_json(elements)
@@ -0,0 +1,43 @@
1
+ import logging
2
+
3
+ from typer_injector import InjectingTyper
4
+
5
+ from pymobiledevice3.cli.cli_common import OSUTILS, ServiceProviderDep
6
+ from pymobiledevice3.services.accessibilityaudit import AccessibilityAudit
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ cli = InjectingTyper(
12
+ name="settings",
13
+ help="accessibility settings",
14
+ no_args_is_help=True,
15
+ )
16
+
17
+
18
+ @cli.command("show")
19
+ def accessibility_settings_show(service_provider: ServiceProviderDep) -> None:
20
+ """show current settings"""
21
+ for setting in AccessibilityAudit(service_provider).settings:
22
+ print(setting)
23
+
24
+
25
+ @cli.command("set")
26
+ def accessibility_settings_set(service_provider: ServiceProviderDep, setting: str, value: str) -> None:
27
+ """
28
+ change current settings
29
+
30
+ in order to list all available use the "show" command
31
+ """
32
+ service = AccessibilityAudit(service_provider)
33
+ service.set_setting(setting, eval(value))
34
+ OSUTILS.wait_return()
35
+
36
+
37
+ @cli.command("reset")
38
+ def accessibility_settings_reset(service_provider: ServiceProviderDep) -> None:
39
+ """
40
+ reset accessibility settings to default
41
+ """
42
+ service = AccessibilityAudit(service_provider)
43
+ service.reset_settings()
@@ -0,0 +1,50 @@
1
+ import logging
2
+ from typing import Annotated
3
+
4
+ import typer
5
+ from typer_injector import InjectingTyper
6
+
7
+ from pymobiledevice3.cli.cli_common import OSUTILS, ServiceProviderDep, print_json
8
+ from pymobiledevice3.exceptions import DeviceAlreadyInUseError
9
+ from pymobiledevice3.services.device_arbitration import DtDeviceArbitration
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+
14
+ cli = InjectingTyper(
15
+ name="arbitration",
16
+ help='Mark/unmark a device as "in-use" to avoid conflicts with other tools.',
17
+ no_args_is_help=True,
18
+ )
19
+
20
+
21
+ @cli.command("version")
22
+ def version(service_provider: ServiceProviderDep) -> None:
23
+ """Show arbitration protocol version."""
24
+ with DtDeviceArbitration(service_provider) as device_arbitration:
25
+ print_json(device_arbitration.version)
26
+
27
+
28
+ @cli.command("check-in")
29
+ def check_in(
30
+ service_provider: ServiceProviderDep,
31
+ hostname: str,
32
+ force: Annotated[
33
+ bool,
34
+ typer.Option("--force", "-f"),
35
+ ] = False,
36
+ ) -> None:
37
+ """Check-in as owner (marks device as in-use; use --force to override)."""
38
+ with DtDeviceArbitration(service_provider) as device_arbitration:
39
+ try:
40
+ device_arbitration.check_in(hostname, force=force)
41
+ OSUTILS.wait_return()
42
+ except DeviceAlreadyInUseError as e:
43
+ logger.error(e.message)
44
+
45
+
46
+ @cli.command("check-out")
47
+ def check_out(service_provider: ServiceProviderDep) -> None:
48
+ """Release ownership and allow other tools to use the device."""
49
+ with DtDeviceArbitration(service_provider) as device_arbitration:
50
+ device_arbitration.check_out()
@@ -0,0 +1,33 @@
1
+ from typer_injector import InjectingTyper
2
+
3
+ from pymobiledevice3.cli.cli_common import OSUTILS, ServiceProviderDep, print_json
4
+ from pymobiledevice3.services.dvt.dvt_secure_socket_proxy import DvtSecureSocketProxyService
5
+ from pymobiledevice3.services.dvt.instruments.condition_inducer import ConditionInducer
6
+
7
+ cli = InjectingTyper(
8
+ name="developer",
9
+ help="Force predefined device conditions (network, thermal, battery) via DVT.",
10
+ no_args_is_help=True,
11
+ )
12
+
13
+
14
+ @cli.command("list")
15
+ def condition_list(service_provider: ServiceProviderDep) -> None:
16
+ """List available condition profiles."""
17
+ with DvtSecureSocketProxyService(lockdown=service_provider) as dvt:
18
+ print_json(ConditionInducer(dvt).list())
19
+
20
+
21
+ @cli.command("clear")
22
+ def condition_clear(service_provider: ServiceProviderDep) -> None:
23
+ """Clear any active induced condition."""
24
+ with DvtSecureSocketProxyService(lockdown=service_provider) as dvt:
25
+ ConditionInducer(dvt).clear()
26
+
27
+
28
+ @cli.command("set")
29
+ def condition_set(service_provider: ServiceProviderDep, profile_identifier: str) -> None:
30
+ """Apply a specific condition profile by identifier."""
31
+ with DvtSecureSocketProxyService(lockdown=service_provider) as dvt:
32
+ ConditionInducer(dvt).set(profile_identifier)
33
+ OSUTILS.wait_return()