pymobiledevice3 4.27.0__py3-none-any.whl → 5.1.2__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 (143) hide show
  1. misc/plist_sniffer.py +15 -15
  2. misc/remotexpc_sniffer.py +29 -28
  3. pymobiledevice3/__main__.py +123 -98
  4. pymobiledevice3/_version.py +2 -2
  5. pymobiledevice3/bonjour.py +351 -117
  6. pymobiledevice3/ca.py +32 -24
  7. pymobiledevice3/cli/activation.py +7 -7
  8. pymobiledevice3/cli/afc.py +19 -19
  9. pymobiledevice3/cli/amfi.py +4 -4
  10. pymobiledevice3/cli/apps.py +51 -39
  11. pymobiledevice3/cli/backup.py +58 -32
  12. pymobiledevice3/cli/bonjour.py +27 -20
  13. pymobiledevice3/cli/cli_common.py +112 -81
  14. pymobiledevice3/cli/companion_proxy.py +4 -4
  15. pymobiledevice3/cli/completions.py +10 -10
  16. pymobiledevice3/cli/crash.py +37 -31
  17. pymobiledevice3/cli/developer.py +601 -519
  18. pymobiledevice3/cli/diagnostics.py +38 -33
  19. pymobiledevice3/cli/lockdown.py +82 -72
  20. pymobiledevice3/cli/mounter.py +84 -67
  21. pymobiledevice3/cli/notification.py +10 -10
  22. pymobiledevice3/cli/pcap.py +19 -14
  23. pymobiledevice3/cli/power_assertion.py +12 -10
  24. pymobiledevice3/cli/processes.py +10 -10
  25. pymobiledevice3/cli/profile.py +88 -77
  26. pymobiledevice3/cli/provision.py +17 -17
  27. pymobiledevice3/cli/remote.py +188 -111
  28. pymobiledevice3/cli/restore.py +43 -40
  29. pymobiledevice3/cli/springboard.py +30 -28
  30. pymobiledevice3/cli/syslog.py +85 -58
  31. pymobiledevice3/cli/usbmux.py +21 -20
  32. pymobiledevice3/cli/version.py +3 -2
  33. pymobiledevice3/cli/webinspector.py +156 -78
  34. pymobiledevice3/common.py +1 -1
  35. pymobiledevice3/exceptions.py +154 -60
  36. pymobiledevice3/irecv.py +49 -53
  37. pymobiledevice3/irecv_devices.py +1489 -492
  38. pymobiledevice3/lockdown.py +400 -251
  39. pymobiledevice3/lockdown_service_provider.py +5 -7
  40. pymobiledevice3/osu/os_utils.py +18 -9
  41. pymobiledevice3/osu/posix_util.py +28 -15
  42. pymobiledevice3/osu/win_util.py +14 -8
  43. pymobiledevice3/pair_records.py +19 -19
  44. pymobiledevice3/remote/common.py +4 -4
  45. pymobiledevice3/remote/core_device/app_service.py +94 -67
  46. pymobiledevice3/remote/core_device/core_device_service.py +17 -14
  47. pymobiledevice3/remote/core_device/device_info.py +5 -5
  48. pymobiledevice3/remote/core_device/diagnostics_service.py +10 -8
  49. pymobiledevice3/remote/core_device/file_service.py +47 -33
  50. pymobiledevice3/remote/remote_service_discovery.py +53 -35
  51. pymobiledevice3/remote/remotexpc.py +64 -42
  52. pymobiledevice3/remote/tunnel_service.py +383 -297
  53. pymobiledevice3/remote/utils.py +14 -13
  54. pymobiledevice3/remote/xpc_message.py +145 -125
  55. pymobiledevice3/resources/dsc_uuid_map.py +19 -19
  56. pymobiledevice3/resources/firmware_notifications.py +16 -16
  57. pymobiledevice3/restore/asr.py +27 -27
  58. pymobiledevice3/restore/base_restore.py +90 -47
  59. pymobiledevice3/restore/consts.py +87 -66
  60. pymobiledevice3/restore/device.py +11 -11
  61. pymobiledevice3/restore/fdr.py +46 -46
  62. pymobiledevice3/restore/ftab.py +19 -19
  63. pymobiledevice3/restore/img4.py +130 -133
  64. pymobiledevice3/restore/mbn.py +587 -0
  65. pymobiledevice3/restore/recovery.py +125 -135
  66. pymobiledevice3/restore/restore.py +535 -523
  67. pymobiledevice3/restore/restore_options.py +122 -115
  68. pymobiledevice3/restore/restored_client.py +25 -22
  69. pymobiledevice3/restore/tss.py +378 -270
  70. pymobiledevice3/service_connection.py +50 -46
  71. pymobiledevice3/services/accessibilityaudit.py +137 -127
  72. pymobiledevice3/services/afc.py +363 -293
  73. pymobiledevice3/services/amfi.py +21 -18
  74. pymobiledevice3/services/companion.py +23 -19
  75. pymobiledevice3/services/crash_reports.py +61 -47
  76. pymobiledevice3/services/debugserver_applist.py +3 -3
  77. pymobiledevice3/services/device_arbitration.py +8 -8
  78. pymobiledevice3/services/device_link.py +56 -48
  79. pymobiledevice3/services/diagnostics.py +971 -968
  80. pymobiledevice3/services/dtfetchsymbols.py +8 -8
  81. pymobiledevice3/services/dvt/dvt_secure_socket_proxy.py +4 -4
  82. pymobiledevice3/services/dvt/dvt_testmanaged_proxy.py +4 -4
  83. pymobiledevice3/services/dvt/instruments/activity_trace_tap.py +85 -74
  84. pymobiledevice3/services/dvt/instruments/application_listing.py +2 -3
  85. pymobiledevice3/services/dvt/instruments/condition_inducer.py +7 -6
  86. pymobiledevice3/services/dvt/instruments/core_profile_session_tap.py +466 -384
  87. pymobiledevice3/services/dvt/instruments/device_info.py +11 -11
  88. pymobiledevice3/services/dvt/instruments/energy_monitor.py +1 -1
  89. pymobiledevice3/services/dvt/instruments/graphics.py +1 -1
  90. pymobiledevice3/services/dvt/instruments/location_simulation.py +1 -1
  91. pymobiledevice3/services/dvt/instruments/location_simulation_base.py +10 -10
  92. pymobiledevice3/services/dvt/instruments/network_monitor.py +17 -17
  93. pymobiledevice3/services/dvt/instruments/notifications.py +1 -1
  94. pymobiledevice3/services/dvt/instruments/process_control.py +25 -10
  95. pymobiledevice3/services/dvt/instruments/screenshot.py +2 -2
  96. pymobiledevice3/services/dvt/instruments/sysmontap.py +15 -15
  97. pymobiledevice3/services/dvt/testmanaged/xcuitest.py +42 -52
  98. pymobiledevice3/services/file_relay.py +10 -10
  99. pymobiledevice3/services/heartbeat.py +8 -7
  100. pymobiledevice3/services/house_arrest.py +12 -15
  101. pymobiledevice3/services/installation_proxy.py +119 -100
  102. pymobiledevice3/services/lockdown_service.py +12 -5
  103. pymobiledevice3/services/misagent.py +22 -19
  104. pymobiledevice3/services/mobile_activation.py +84 -72
  105. pymobiledevice3/services/mobile_config.py +331 -301
  106. pymobiledevice3/services/mobile_image_mounter.py +137 -116
  107. pymobiledevice3/services/mobilebackup2.py +188 -150
  108. pymobiledevice3/services/notification_proxy.py +11 -11
  109. pymobiledevice3/services/os_trace.py +128 -74
  110. pymobiledevice3/services/pcapd.py +306 -306
  111. pymobiledevice3/services/power_assertion.py +10 -9
  112. pymobiledevice3/services/preboard.py +4 -4
  113. pymobiledevice3/services/remote_fetch_symbols.py +16 -14
  114. pymobiledevice3/services/remote_server.py +176 -146
  115. pymobiledevice3/services/restore_service.py +16 -16
  116. pymobiledevice3/services/screenshot.py +13 -10
  117. pymobiledevice3/services/simulate_location.py +7 -7
  118. pymobiledevice3/services/springboard.py +15 -15
  119. pymobiledevice3/services/syslog.py +5 -5
  120. pymobiledevice3/services/web_protocol/alert.py +3 -3
  121. pymobiledevice3/services/web_protocol/automation_session.py +183 -179
  122. pymobiledevice3/services/web_protocol/cdp_screencast.py +44 -36
  123. pymobiledevice3/services/web_protocol/cdp_server.py +19 -19
  124. pymobiledevice3/services/web_protocol/cdp_target.py +411 -373
  125. pymobiledevice3/services/web_protocol/driver.py +47 -45
  126. pymobiledevice3/services/web_protocol/element.py +74 -63
  127. pymobiledevice3/services/web_protocol/inspector_session.py +106 -102
  128. pymobiledevice3/services/web_protocol/selenium_api.py +3 -3
  129. pymobiledevice3/services/web_protocol/session_protocol.py +15 -10
  130. pymobiledevice3/services/web_protocol/switch_to.py +11 -12
  131. pymobiledevice3/services/webinspector.py +142 -116
  132. pymobiledevice3/tcp_forwarder.py +64 -50
  133. pymobiledevice3/tunneld/api.py +20 -15
  134. pymobiledevice3/tunneld/server.py +315 -193
  135. pymobiledevice3/usbmux.py +197 -148
  136. pymobiledevice3/utils.py +14 -11
  137. {pymobiledevice3-4.27.0.dist-info → pymobiledevice3-5.1.2.dist-info}/METADATA +2 -6
  138. pymobiledevice3-5.1.2.dist-info/RECORD +173 -0
  139. pymobiledevice3-4.27.0.dist-info/RECORD +0 -172
  140. {pymobiledevice3-4.27.0.dist-info → pymobiledevice3-5.1.2.dist-info}/WHEEL +0 -0
  141. {pymobiledevice3-4.27.0.dist-info → pymobiledevice3-5.1.2.dist-info}/entry_points.txt +0 -0
  142. {pymobiledevice3-4.27.0.dist-info → pymobiledevice3-5.1.2.dist-info}/licenses/LICENSE +0 -0
  143. {pymobiledevice3-4.27.0.dist-info → pymobiledevice3-5.1.2.dist-info}/top_level.txt +0 -0
@@ -13,44 +13,44 @@ def cli() -> None:
13
13
 
14
14
  @cli.group()
15
15
  def afc() -> None:
16
- """ Manage device multimedia files """
16
+ """Manage device multimedia files"""
17
17
  pass
18
18
 
19
19
 
20
- @afc.command('shell', cls=Command)
20
+ @afc.command("shell", cls=Command)
21
21
  def afc_shell(service_provider: LockdownClient):
22
- """ open an AFC shell rooted at /var/mobile/Media """
22
+ """open an AFC shell rooted at /var/mobile/Media"""
23
23
  AfcShell.create(service_provider)
24
24
 
25
25
 
26
- @afc.command('pull', cls=Command)
27
- @click.option('-i', '--ignore-errors', is_flag=True, help='Ignore AFC pull errors')
28
- @click.argument('remote_file', type=click.Path(exists=False))
29
- @click.argument('local_file', type=click.Path(exists=False))
26
+ @afc.command("pull", cls=Command)
27
+ @click.option("-i", "--ignore-errors", is_flag=True, help="Ignore AFC pull errors")
28
+ @click.argument("remote_file", type=click.Path(exists=False))
29
+ @click.argument("local_file", type=click.Path(exists=False))
30
30
  def afc_pull(service_provider: LockdownServiceProvider, remote_file: str, local_file: str, ignore_errors: bool) -> None:
31
- """ pull remote file from /var/mobile/Media """
31
+ """pull remote file from /var/mobile/Media"""
32
32
  AfcService(lockdown=service_provider).pull(remote_file, local_file, ignore_errors=ignore_errors)
33
33
 
34
34
 
35
- @afc.command('push', cls=Command)
36
- @click.argument('local_file', type=click.Path(exists=False))
37
- @click.argument('remote_file', type=click.Path(exists=False))
35
+ @afc.command("push", cls=Command)
36
+ @click.argument("local_file", type=click.Path(exists=False))
37
+ @click.argument("remote_file", type=click.Path(exists=False))
38
38
  def afc_push(service_provider: LockdownServiceProvider, local_file: str, remote_file: str) -> None:
39
- """ push local file into /var/mobile/Media """
39
+ """push local file into /var/mobile/Media"""
40
40
  AfcService(lockdown=service_provider).push(local_file, remote_file)
41
41
 
42
42
 
43
- @afc.command('ls', cls=Command)
44
- @click.argument('remote_file', type=click.Path(exists=False))
45
- @click.option('-r', '--recursive', is_flag=True)
43
+ @afc.command("ls", cls=Command)
44
+ @click.argument("remote_file", type=click.Path(exists=False))
45
+ @click.option("-r", "--recursive", is_flag=True)
46
46
  def afc_ls(service_provider: LockdownClient, remote_file, recursive):
47
- """ perform a dirlist rooted at /var/mobile/Media """
47
+ """perform a dirlist rooted at /var/mobile/Media"""
48
48
  for path in AfcService(lockdown=service_provider).dirlist(remote_file, -1 if recursive else 1):
49
49
  print(path)
50
50
 
51
51
 
52
- @afc.command('rm', cls=Command)
53
- @click.argument('remote_file', type=click.Path(exists=False))
52
+ @afc.command("rm", cls=Command)
53
+ @click.argument("remote_file", type=click.Path(exists=False))
54
54
  def afc_rm(service_provider: LockdownClient, remote_file):
55
- """ remove a file rooted at /var/mobile/Media """
55
+ """remove a file rooted at /var/mobile/Media"""
56
56
  AfcService(lockdown=service_provider).rm(remote_file)
@@ -16,23 +16,23 @@ def cli() -> None:
16
16
 
17
17
  @cli.group()
18
18
  def amfi() -> None:
19
- """ Enable developer-mode or query its state """
19
+ """Enable developer-mode or query its state"""
20
20
  pass
21
21
 
22
22
 
23
23
  @amfi.command(cls=Command)
24
24
  def reveal_developer_mode(service_provider: LockdownClient):
25
- """ reveal developer mode option in device's UI """
25
+ """reveal developer mode option in device's UI"""
26
26
  AmfiService(service_provider).reveal_developer_mode_option_in_ui()
27
27
 
28
28
 
29
29
  @amfi.command(cls=Command)
30
30
  def enable_developer_mode(service_provider: LockdownClient):
31
- """ enable developer mode """
31
+ """enable developer mode"""
32
32
  AmfiService(service_provider).enable_developer_mode()
33
33
 
34
34
 
35
35
  @amfi.command(cls=Command)
36
36
  def developer_mode_status(service_provider: LockdownClient):
37
- """ query developer mode status """
37
+ """query developer mode status"""
38
38
  print_json(service_provider.developer_mode_status)
@@ -14,73 +14,85 @@ def cli() -> None:
14
14
 
15
15
  @cli.group()
16
16
  def apps() -> None:
17
- """ Manage installed applications """
17
+ """Manage installed applications"""
18
18
  pass
19
19
 
20
20
 
21
- @apps.command('list', cls=Command)
22
- @click.option('app_type', '-t', '--type', type=click.Choice(['System', 'User', 'Hidden', 'Any']), default='Any',
23
- help='include only applications of given type')
24
- @click.option('--calculate-sizes/--no-calculate-size', default=False)
21
+ @apps.command("list", cls=Command)
22
+ @click.option(
23
+ "app_type",
24
+ "-t",
25
+ "--type",
26
+ type=click.Choice(["System", "User", "Hidden", "Any"]),
27
+ default="Any",
28
+ help="include only applications of given type",
29
+ )
30
+ @click.option("--calculate-sizes/--no-calculate-size", default=False)
25
31
  def apps_list(service_provider: LockdownServiceProvider, app_type: str, calculate_sizes: bool) -> None:
26
- """ list installed apps """
27
- print_json(InstallationProxyService(lockdown=service_provider).get_apps(application_type=app_type,
28
- calculate_sizes=calculate_sizes))
32
+ """list installed apps"""
33
+ print_json(
34
+ InstallationProxyService(lockdown=service_provider).get_apps(
35
+ application_type=app_type, calculate_sizes=calculate_sizes
36
+ )
37
+ )
29
38
 
30
39
 
31
- @apps.command('query', cls=Command)
32
- @click.argument('bundle_identifiers', nargs=-1)
33
- @click.option('--calculate-sizes/--no-calculate-size', default=False)
40
+ @apps.command("query", cls=Command)
41
+ @click.argument("bundle_identifiers", nargs=-1)
42
+ @click.option("--calculate-sizes/--no-calculate-size", default=False)
34
43
  def apps_query(service_provider: LockdownServiceProvider, bundle_identifiers: list[str], calculate_sizes: bool) -> None:
35
- """ query installed apps """
36
- print_json(InstallationProxyService(lockdown=service_provider)
37
- .get_apps(calculate_sizes=calculate_sizes, bundle_identifiers=bundle_identifiers))
44
+ """query installed apps"""
45
+ print_json(
46
+ InstallationProxyService(lockdown=service_provider).get_apps(
47
+ calculate_sizes=calculate_sizes, bundle_identifiers=bundle_identifiers
48
+ )
49
+ )
38
50
 
39
51
 
40
- @apps.command('uninstall', cls=Command)
41
- @click.argument('bundle_id')
52
+ @apps.command("uninstall", cls=Command)
53
+ @click.argument("bundle_id")
42
54
  def uninstall(service_provider: LockdownClient, bundle_id):
43
- """ uninstall app by given bundle_id """
55
+ """uninstall app by given bundle_id"""
44
56
  InstallationProxyService(lockdown=service_provider).uninstall(bundle_id)
45
57
 
46
58
 
47
- @apps.command('install', cls=Command)
48
- @click.option('--developer', is_flag=True, help='Install developer package')
49
- @click.argument('package', type=click.Path(exists=True))
59
+ @apps.command("install", cls=Command)
60
+ @click.option("--developer", is_flag=True, help="Install developer package")
61
+ @click.argument("package", type=click.Path(exists=True))
50
62
  def install(service_provider: LockdownServiceProvider, package: str, developer: bool) -> None:
51
- """ install given .ipa/.app/.ipcc """
63
+ """install given .ipa/.app/.ipcc"""
52
64
  InstallationProxyService(lockdown=service_provider).install_from_local(package, developer=developer)
53
65
 
54
66
 
55
- @apps.command('afc', cls=Command)
56
- @click.option('--documents', is_flag=True)
57
- @click.argument('bundle_id')
67
+ @apps.command("afc", cls=Command)
68
+ @click.option("--documents", is_flag=True)
69
+ @click.argument("bundle_id")
58
70
  def afc(service_provider: LockdownClient, bundle_id: str, documents: bool):
59
- """ open an AFC shell for given bundle_id, assuming its profile is installed """
71
+ """open an AFC shell for given bundle_id, assuming its profile is installed"""
60
72
  HouseArrestService(lockdown=service_provider, bundle_id=bundle_id, documents_only=documents).shell()
61
73
 
62
74
 
63
- @apps.command('pull', cls=Command)
64
- @click.argument('bundle_id')
65
- @click.argument('remote_file', type=click.Path(exists=False))
66
- @click.argument('local_file', type=click.Path(exists=False))
75
+ @apps.command("pull", cls=Command)
76
+ @click.argument("bundle_id")
77
+ @click.argument("remote_file", type=click.Path(exists=False))
78
+ @click.argument("local_file", type=click.Path(exists=False))
67
79
  def pull(service_provider: LockdownClient, bundle_id: str, remote_file: str, local_file: str):
68
- """ pull remote file from specified bundle_id """
80
+ """pull remote file from specified bundle_id"""
69
81
  HouseArrestService(lockdown=service_provider, bundle_id=bundle_id).pull(remote_file, local_file)
70
82
 
71
83
 
72
- @apps.command('push', cls=Command)
73
- @click.argument('bundle_id')
74
- @click.argument('local_file', type=click.Path(exists=False))
75
- @click.argument('remote_file', type=click.Path(exists=False))
84
+ @apps.command("push", cls=Command)
85
+ @click.argument("bundle_id")
86
+ @click.argument("local_file", type=click.Path(exists=False))
87
+ @click.argument("remote_file", type=click.Path(exists=False))
76
88
  def push(service_provider: LockdownClient, bundle_id: str, local_file: str, remote_file: str):
77
- """ push local file into specified bundle_id """
89
+ """push local file into specified bundle_id"""
78
90
  HouseArrestService(lockdown=service_provider, bundle_id=bundle_id).push(local_file, remote_file)
79
91
 
80
92
 
81
- @apps.command('rm', cls=Command)
82
- @click.argument('bundle_id')
83
- @click.argument('remote_file', type=click.Path(exists=False))
93
+ @apps.command("rm", cls=Command)
94
+ @click.argument("bundle_id")
95
+ @click.argument("remote_file", type=click.Path(exists=False))
84
96
  def rm(service_provider: LockdownClient, bundle_id: str, remote_file: str):
85
- """ remove remote file from specified bundle_id """
97
+ """remove remote file from specified bundle_id"""
86
98
  HouseArrestService(lockdown=service_provider, bundle_id=bundle_id).rm(remote_file)
@@ -8,11 +8,12 @@ from pymobiledevice3.lockdown import LockdownClient
8
8
  from pymobiledevice3.lockdown_service_provider import LockdownServiceProvider
9
9
  from pymobiledevice3.services.mobilebackup2 import Mobilebackup2Service
10
10
 
11
- source_option = click.option('--source', default='', help='The UDID of the source device.')
12
- password_option = click.option('-p', '--password', default='', help='Backup password.')
13
- backup_directory_arg = click.argument('backup-directory', type=click.Path(exists=True, file_okay=False))
14
- backup_directory_option = click.option('-b', '--backup-directory', type=click.Path(exists=True, file_okay=False),
15
- default='.')
11
+ source_option = click.option("--source", default="", help="The UDID of the source device.")
12
+ password_option = click.option("-p", "--password", default="", help="Backup password.")
13
+ backup_directory_arg = click.argument("backup-directory", type=click.Path(exists=True, file_okay=False))
14
+ backup_directory_option = click.option(
15
+ "-b", "--backup-directory", type=click.Path(exists=True, file_okay=False), default="."
16
+ )
16
17
 
17
18
  logger = logging.getLogger(__name__)
18
19
 
@@ -24,14 +25,17 @@ def cli() -> None:
24
25
 
25
26
  @cli.group()
26
27
  def backup2() -> None:
27
- """ Backup/Restore options """
28
+ """Backup/Restore options"""
28
29
  pass
29
30
 
30
31
 
31
32
  @backup2.command(cls=Command)
32
- @click.argument('backup-directory', type=click.Path(file_okay=False))
33
- @click.option('--full', is_flag=True, help=('Whether to do a full backup.'
34
- ' If full is True, any previous backup attempts will be discarded.'))
33
+ @click.argument("backup-directory", type=click.Path(file_okay=False))
34
+ @click.option(
35
+ "--full",
36
+ is_flag=True,
37
+ help=("Whether to do a full backup. If full is True, any previous backup attempts will be discarded."),
38
+ )
35
39
  def backup(service_provider: LockdownServiceProvider, backup_directory: str, full: bool) -> None:
36
40
  """
37
41
  Backup device.
@@ -40,6 +44,7 @@ def backup(service_provider: LockdownServiceProvider, backup_directory: str, ful
40
44
  """
41
45
  backup_client = Mobilebackup2Service(service_provider)
42
46
  with tqdm(total=100, dynamic_ncols=True) as pbar:
47
+
43
48
  def update_bar(percentage):
44
49
  pbar.n = percentage
45
50
  pbar.refresh()
@@ -49,16 +54,26 @@ def backup(service_provider: LockdownServiceProvider, backup_directory: str, ful
49
54
 
50
55
  @backup2.command(cls=Command)
51
56
  @backup_directory_arg
52
- @click.option('--system/--no-system', default=False, help='Restore system files.')
53
- @click.option('--reboot/--no-reboot', default=True, help='Reboot the device when done.')
54
- @click.option('--copy/--no-copy', default=False, help='Create a copy of backup folder before restoring.')
55
- @click.option('--settings/--no-settings', default=True, help='Restore device settings.')
56
- @click.option('--remove/--no-remove', default=False, help='Remove items which aren\'t being restored.')
57
- @click.option('--skip-apps', is_flag=True, help='Do not trigger re-installation of apps after restore')
57
+ @click.option("--system/--no-system", default=False, help="Restore system files.")
58
+ @click.option("--reboot/--no-reboot", default=True, help="Reboot the device when done.")
59
+ @click.option("--copy/--no-copy", default=False, help="Create a copy of backup folder before restoring.")
60
+ @click.option("--settings/--no-settings", default=True, help="Restore device settings.")
61
+ @click.option("--remove/--no-remove", default=False, help="Remove items which aren't being restored.")
62
+ @click.option("--skip-apps", is_flag=True, help="Do not trigger re-installation of apps after restore")
58
63
  @password_option
59
64
  @source_option
60
- def restore(service_provider: LockdownServiceProvider, backup_directory: str, system: bool, reboot: bool, copy: bool,
61
- settings: bool, remove: bool, skip_apps: bool, password: str, source: str) -> None:
65
+ def restore(
66
+ service_provider: LockdownServiceProvider,
67
+ backup_directory: str,
68
+ system: bool,
69
+ reboot: bool,
70
+ copy: bool,
71
+ settings: bool,
72
+ remove: bool,
73
+ skip_apps: bool,
74
+ password: str,
75
+ source: str,
76
+ ) -> None:
62
77
  """
63
78
  Restore a backup to a device.
64
79
 
@@ -66,13 +81,23 @@ def restore(service_provider: LockdownServiceProvider, backup_directory: str, sy
66
81
  """
67
82
  backup_client = Mobilebackup2Service(service_provider)
68
83
  with tqdm(total=100, dynamic_ncols=True) as pbar:
84
+
69
85
  def update_bar(percentage):
70
86
  pbar.n = percentage
71
87
  pbar.refresh()
72
88
 
73
- backup_client.restore(backup_directory=backup_directory, progress_callback=update_bar, system=system,
74
- reboot=reboot, copy=copy, settings=settings, remove=remove, password=password,
75
- source=source, skip_apps=skip_apps)
89
+ backup_client.restore(
90
+ backup_directory=backup_directory,
91
+ progress_callback=update_bar,
92
+ system=system,
93
+ reboot=reboot,
94
+ copy=copy,
95
+ settings=settings,
96
+ remove=remove,
97
+ password=password,
98
+ source=source,
99
+ skip_apps=skip_apps,
100
+ )
76
101
 
77
102
 
78
103
  @backup2.command(cls=Command)
@@ -86,7 +111,7 @@ def info(service_provider: LockdownClient, backup_directory, source):
86
111
  print(backup_client.info(backup_directory=backup_directory, source=source))
87
112
 
88
113
 
89
- @backup2.command('list', cls=Command)
114
+ @backup2.command("list", cls=Command)
90
115
  @backup_directory_arg
91
116
  @source_option
92
117
  def list_(service_provider: LockdownClient, backup_directory, source):
@@ -110,8 +135,8 @@ def unback(service_provider: LockdownClient, backup_directory, password, source)
110
135
 
111
136
 
112
137
  @backup2.command(cls=Command)
113
- @click.argument('domain-name')
114
- @click.argument('relative-path')
138
+ @click.argument("domain-name")
139
+ @click.argument("relative-path")
115
140
  @backup_directory_arg
116
141
  @password_option
117
142
  @source_option
@@ -123,13 +148,14 @@ def extract(service_provider: LockdownClient, domain_name, relative_path, backup
123
148
  will be extracted to the BACKUP_DIRECTORY.
124
149
  """
125
150
  backup_client = Mobilebackup2Service(service_provider)
126
- backup_client.extract(domain_name, relative_path, backup_directory=backup_directory, password=password,
127
- source=source)
151
+ backup_client.extract(
152
+ domain_name, relative_path, backup_directory=backup_directory, password=password, source=source
153
+ )
128
154
 
129
155
 
130
156
  @backup2.command(cls=Command)
131
- @click.argument('mode', type=click.Choice(['on', 'off'], case_sensitive=False))
132
- @click.argument('password')
157
+ @click.argument("mode", type=click.Choice(["on", "off"], case_sensitive=False))
158
+ @click.argument("password")
133
159
  @backup_directory_option
134
160
  def encryption(service_provider: LockdownClient, backup_directory, mode, password):
135
161
  """
@@ -139,9 +165,9 @@ def encryption(service_provider: LockdownClient, backup_directory, mode, passwor
139
165
  When off, PASSWORD is the current backup password.
140
166
  """
141
167
  backup_client = Mobilebackup2Service(service_provider)
142
- should_encrypt = mode.lower() == 'on'
168
+ should_encrypt = mode.lower() == "on"
143
169
  if should_encrypt == backup_client.will_encrypt:
144
- logger.error('Encryption already ' + ('on!' if should_encrypt else 'off!'))
170
+ logger.error("Encryption already " + ("on!" if should_encrypt else "off!"))
145
171
  return
146
172
  if should_encrypt:
147
173
  backup_client.change_password(backup_directory, new=password)
@@ -150,8 +176,8 @@ def encryption(service_provider: LockdownClient, backup_directory, mode, passwor
150
176
 
151
177
 
152
178
  @backup2.command(cls=Command)
153
- @click.argument('old-password')
154
- @click.argument('new-password')
179
+ @click.argument("old-password")
180
+ @click.argument("new-password")
155
181
  @backup_directory_option
156
182
  def change_password(service_provider: LockdownClient, old_password, new_password, backup_directory):
157
183
  """
@@ -159,7 +185,7 @@ def change_password(service_provider: LockdownClient, old_password, new_password
159
185
  """
160
186
  backup_client = Mobilebackup2Service(service_provider)
161
187
  if not backup_client.will_encrypt:
162
- logger.error('Encryption is not turned on!')
188
+ logger.error("Encryption is not turned on!")
163
189
  return
164
190
  backup_client.change_password(backup_directory, old=old_password, new=new_password)
165
191
 
@@ -14,9 +14,9 @@ def cli() -> None:
14
14
  pass
15
15
 
16
16
 
17
- @cli.group('bonjour')
17
+ @cli.group("bonjour")
18
18
  def bonjour_cli() -> None:
19
- """ Browse devices over bonjour """
19
+ """Browse devices over bonjour"""
20
20
  pass
21
21
 
22
22
 
@@ -24,47 +24,54 @@ async def cli_mobdev2_task(timeout: float, pair_records: Optional[str]) -> None:
24
24
  output = []
25
25
  async for ip, lockdown in get_mobdev2_lockdowns(timeout=timeout, pair_records=pair_records):
26
26
  short_info = lockdown.short_info
27
- short_info['ip'] = ip
27
+ short_info["ip"] = ip
28
28
  output.append(short_info)
29
29
  print_json(output)
30
30
 
31
31
 
32
- @bonjour_cli.command('mobdev2', cls=BaseCommand)
33
- @click.option('--timeout', default=DEFAULT_BONJOUR_TIMEOUT, type=click.INT)
34
- @click.option('--pair-records', type=click.Path(dir_okay=True, file_okay=False, exists=True),
35
- help='pair records to attempt validation with')
32
+ @bonjour_cli.command("mobdev2", cls=BaseCommand)
33
+ @click.option("--timeout", default=DEFAULT_BONJOUR_TIMEOUT, type=click.INT)
34
+ @click.option(
35
+ "--pair-records",
36
+ type=click.Path(dir_okay=True, file_okay=False, exists=True),
37
+ help="pair records to attempt validation with",
38
+ )
36
39
  def cli_mobdev2(timeout: float, pair_records: Optional[str]) -> None:
37
- """ browse for mobdev2 devices over bonjour """
40
+ """browse for mobdev2 devices over bonjour"""
38
41
  asyncio.run(cli_mobdev2_task(timeout, pair_records))
39
42
 
40
43
 
41
44
  async def cli_remotepairing_task(timeout: float) -> None:
42
45
  output = []
43
46
  for answer in await browse_remotepairing(timeout=timeout):
44
- for ip in answer.ips:
45
- output.append({'hostname': ip, 'port': answer.port})
47
+ for address in answer.addresses:
48
+ output.append({"hostname": address.full_ip, "port": answer.port})
46
49
  print_json(output)
47
50
 
48
51
 
49
- @bonjour_cli.command('remotepairing', cls=BaseCommand)
50
- @click.option('--timeout', default=DEFAULT_BONJOUR_TIMEOUT, type=click.FLOAT)
52
+ @bonjour_cli.command("remotepairing", cls=BaseCommand)
53
+ @click.option("--timeout", default=DEFAULT_BONJOUR_TIMEOUT, type=click.FLOAT)
51
54
  def cli_remotepairing(timeout: float) -> None:
52
- """ browse for remotepairing devices over bonjour (without attempting pair verification) """
55
+ """browse for remotepairing devices over bonjour (without attempting pair verification)"""
53
56
  asyncio.run(cli_remotepairing_task(timeout=timeout))
54
57
 
55
58
 
56
59
  async def cli_remotepairing_manual_pairing_task(timeout: float) -> None:
57
60
  output = []
58
61
  for answer in await browse_remotepairing_manual_pairing(timeout=timeout):
59
- for ip in answer.ips:
60
- output.append({'hostname': ip, 'port': answer.port, 'name': answer.properties[b'name'].decode()})
62
+ for address in answer.addresses:
63
+ output.append({
64
+ "hostname": address.full_ip,
65
+ "port": answer.port,
66
+ "name": answer.properties[b"name"].decode(),
67
+ })
61
68
  print_json(output)
62
69
 
63
70
 
64
- @bonjour_cli.command('remotepairing-manual-pairing', cls=BaseCommand)
65
- @click.option('--timeout', default=DEFAULT_BONJOUR_TIMEOUT, type=click.FLOAT)
71
+ @bonjour_cli.command("remotepairing-manual-pairing", cls=BaseCommand)
72
+ @click.option("--timeout", default=DEFAULT_BONJOUR_TIMEOUT, type=click.FLOAT)
66
73
  def cli_remotepairing_manual_pairing(timeout: float) -> None:
67
- """ browse for remotepairing-manual-pairing devices over bonjour """
74
+ """browse for remotepairing-manual-pairing devices over bonjour"""
68
75
  asyncio.run(cli_remotepairing_manual_pairing_task(timeout=timeout))
69
76
 
70
77
 
@@ -72,7 +79,7 @@ async def cli_browse_rsd() -> None:
72
79
  print_json(await browse_rsd())
73
80
 
74
81
 
75
- @bonjour_cli.command('rsd', cls=BaseCommand)
82
+ @bonjour_cli.command("rsd", cls=BaseCommand)
76
83
  def cli_rsd() -> None:
77
- """ browse RemoteXPC devices using bonjour """
84
+ """browse RemoteXPC devices using bonjour"""
78
85
  asyncio.run(cli_browse_rsd(), debug=True)