pymobiledevice3 7.0.7__py3-none-any.whl → 7.1.0__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.
- pymobiledevice3/_version.py +2 -2
- pymobiledevice3/cli/developer/debugserver.py +134 -99
- {pymobiledevice3-7.0.7.dist-info → pymobiledevice3-7.1.0.dist-info}/METADATA +1 -1
- {pymobiledevice3-7.0.7.dist-info → pymobiledevice3-7.1.0.dist-info}/RECORD +8 -8
- {pymobiledevice3-7.0.7.dist-info → pymobiledevice3-7.1.0.dist-info}/WHEEL +0 -0
- {pymobiledevice3-7.0.7.dist-info → pymobiledevice3-7.1.0.dist-info}/entry_points.txt +0 -0
- {pymobiledevice3-7.0.7.dist-info → pymobiledevice3-7.1.0.dist-info}/licenses/LICENSE +0 -0
- {pymobiledevice3-7.0.7.dist-info → pymobiledevice3-7.1.0.dist-info}/top_level.txt +0 -0
pymobiledevice3/_version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '7.0
|
|
32
|
-
__version_tuple__ = version_tuple = (7,
|
|
31
|
+
__version__ = version = '7.1.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (7, 1, 0)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -6,7 +6,9 @@ import struct
|
|
|
6
6
|
import subprocess
|
|
7
7
|
import sys
|
|
8
8
|
from pathlib import Path
|
|
9
|
+
from tempfile import TemporaryDirectory
|
|
9
10
|
from typing import Annotated, Optional
|
|
11
|
+
from zipfile import ZipFile
|
|
10
12
|
|
|
11
13
|
import typer
|
|
12
14
|
from packaging.version import Version
|
|
@@ -80,9 +82,9 @@ def debugserver_start_server(service_provider: ServiceProviderDep, local_port: O
|
|
|
80
82
|
@cli.command("lldb")
|
|
81
83
|
def debugserver_lldb(
|
|
82
84
|
service_provider: RSDServiceProviderDep,
|
|
83
|
-
|
|
85
|
+
project_or_ipa_path: Annotated[
|
|
84
86
|
Path,
|
|
85
|
-
typer.Argument(exists=True, file_okay=
|
|
87
|
+
typer.Argument(exists=True, file_okay=True, dir_okay=True),
|
|
86
88
|
],
|
|
87
89
|
configuration: Annotated[
|
|
88
90
|
str,
|
|
@@ -106,11 +108,12 @@ def debugserver_lldb(
|
|
|
106
108
|
] = None,
|
|
107
109
|
) -> None:
|
|
108
110
|
"""
|
|
109
|
-
Automate lldb launch for a given xcodeproj.
|
|
111
|
+
Automate lldb launch for a given xcodeproj or IPA.
|
|
110
112
|
|
|
111
113
|
\b
|
|
112
114
|
This will:
|
|
113
|
-
- Build the given xcodeproj
|
|
115
|
+
- Build the given xcodeproj (if provided)
|
|
116
|
+
- Extract the given IPA (if provided)
|
|
114
117
|
- Install it
|
|
115
118
|
- Start a debugserver attached to it
|
|
116
119
|
- Place breakpoints if given any
|
|
@@ -123,122 +126,154 @@ def debugserver_lldb(
|
|
|
123
126
|
return
|
|
124
127
|
|
|
125
128
|
commands = []
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
129
|
+
temp_dir = None
|
|
130
|
+
local_app = None
|
|
131
|
+
install_source = None
|
|
132
|
+
|
|
133
|
+
if project_or_ipa_path.suffix == ".xcodeproj":
|
|
134
|
+
with local.cwd(project_or_ipa_path.parent):
|
|
135
|
+
logger.info(f"Building {project_or_ipa_path} for {configuration} configuration")
|
|
136
|
+
local["xcodebuild"]["-project", str(project_or_ipa_path), "-configuration", configuration, "build"]()
|
|
137
|
+
app_candidates = [app for app in Path("build").rglob("*.app") if (app / "Info.plist").exists()]
|
|
138
|
+
if not app_candidates:
|
|
139
|
+
logger.error("No built .app with Info.plist found under build/.")
|
|
140
|
+
return
|
|
141
|
+
app_candidates.sort(key=lambda p: p.stat().st_mtime, reverse=True)
|
|
142
|
+
local_app = app_candidates[0].absolute()
|
|
143
|
+
install_source = local_app
|
|
144
|
+
elif project_or_ipa_path.suffix == ".ipa":
|
|
145
|
+
temp_dir = TemporaryDirectory()
|
|
146
|
+
with ZipFile(project_or_ipa_path, "r") as ipa_zip:
|
|
147
|
+
ipa_zip.extractall(temp_dir.name)
|
|
148
|
+
payload_dir = Path(temp_dir.name) / "Payload"
|
|
149
|
+
apps = list(payload_dir.glob("*.app"))
|
|
150
|
+
if not apps:
|
|
151
|
+
logger.error("No .app bundle found in IPA Payload.")
|
|
152
|
+
temp_dir.cleanup()
|
|
153
|
+
return
|
|
154
|
+
if len(apps) > 1:
|
|
155
|
+
logger.error("Multiple .app bundles found in IPA Payload; please provide a single-app IPA.")
|
|
156
|
+
temp_dir.cleanup()
|
|
157
|
+
return
|
|
158
|
+
local_app = apps[0].absolute()
|
|
159
|
+
install_source = project_or_ipa_path
|
|
160
|
+
else:
|
|
161
|
+
logger.error("Expected an .xcodeproj directory or an .ipa file.")
|
|
162
|
+
return
|
|
163
|
+
|
|
164
|
+
logger.info(f"Using app: {local_app}")
|
|
165
|
+
|
|
166
|
+
info_plist_path = local_app / "Info.plist"
|
|
167
|
+
info_plist = plistlib.loads(info_plist_path.read_bytes())
|
|
168
|
+
bundle_identifier = info_plist["CFBundleIdentifier"]
|
|
169
|
+
logger.info(f"Bundle identifier: {bundle_identifier}")
|
|
145
170
|
|
|
171
|
+
commands.append("platform select remote-ios")
|
|
172
|
+
commands.append(f'target create "{local_app.absolute()}"')
|
|
173
|
+
|
|
174
|
+
with InstallationProxyService(create_using_usbmux()) as installation_proxy:
|
|
175
|
+
logger.info("Installing app")
|
|
176
|
+
installation_proxy.install_from_local(install_source)
|
|
177
|
+
remote_path = installation_proxy.get_apps(bundle_identifiers=[bundle_identifier])[bundle_identifier]["Path"]
|
|
178
|
+
logger.info(f"Remote path: {remote_path}")
|
|
146
179
|
commands.append(f'script lldb.target.module[0].SetPlatformFileSpec(lldb.SBFileSpec("{remote_path}"))')
|
|
147
180
|
|
|
148
|
-
|
|
181
|
+
debugserver_port = service_provider.get_service_port("com.apple.internal.dt.remote.debugproxy")
|
|
182
|
+
|
|
183
|
+
# Add connection and launch commands
|
|
184
|
+
commands.append(f"process connect connect://[{service_provider.service.address[0]}]:{debugserver_port}")
|
|
149
185
|
|
|
150
|
-
|
|
151
|
-
|
|
186
|
+
if breakpoints:
|
|
187
|
+
for bp in breakpoints:
|
|
188
|
+
commands.append(f'breakpoint set -n "{bp}"')
|
|
152
189
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
commands.append(f'breakpoint set -n "{bp}"')
|
|
190
|
+
if launch:
|
|
191
|
+
commands.append("process launch")
|
|
156
192
|
|
|
157
|
-
|
|
158
|
-
|
|
193
|
+
if user_commands:
|
|
194
|
+
# Add user commands
|
|
195
|
+
commands += user_commands
|
|
159
196
|
|
|
160
|
-
|
|
161
|
-
# Add user commands
|
|
162
|
-
commands += user_commands
|
|
197
|
+
logger.info("Starting lldb with automated setup and connection")
|
|
163
198
|
|
|
164
|
-
|
|
199
|
+
# Works only on unix-based systems, so keep these imports here
|
|
200
|
+
import fcntl
|
|
201
|
+
import pty
|
|
202
|
+
import select as select_module
|
|
203
|
+
import termios
|
|
204
|
+
import tty
|
|
165
205
|
|
|
166
|
-
|
|
167
|
-
import fcntl
|
|
168
|
-
import pty
|
|
169
|
-
import select as select_module
|
|
170
|
-
import termios
|
|
171
|
-
import tty
|
|
206
|
+
master, slave = pty.openpty()
|
|
172
207
|
|
|
173
|
-
|
|
208
|
+
process = None # Initialize process variable for signal handler
|
|
174
209
|
|
|
175
|
-
|
|
210
|
+
# Copy terminal size from the current terminal to PTY
|
|
211
|
+
def resize_pty() -> None:
|
|
212
|
+
"""Update PTY size to match current terminal size"""
|
|
213
|
+
size = struct.unpack(
|
|
214
|
+
"HHHH", fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ, struct.pack("HHHH", 0, 0, 0, 0))
|
|
215
|
+
)
|
|
216
|
+
fcntl.ioctl(master, termios.TIOCSWINSZ, struct.pack("HHHH", *size))
|
|
217
|
+
# Send SIGWINCH to the child process to notify it of the resize
|
|
218
|
+
if process is not None and process.poll() is None:
|
|
219
|
+
process.send_signal(signal.SIGWINCH)
|
|
176
220
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
"""Update PTY size to match current terminal size"""
|
|
180
|
-
size = struct.unpack(
|
|
181
|
-
"HHHH", fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ, struct.pack("HHHH", 0, 0, 0, 0))
|
|
182
|
-
)
|
|
183
|
-
fcntl.ioctl(master, termios.TIOCSWINSZ, struct.pack("HHHH", *size))
|
|
184
|
-
# Send SIGWINCH to the child process to notify it of the resize
|
|
185
|
-
if process is not None and process.poll() is None:
|
|
186
|
-
process.send_signal(signal.SIGWINCH)
|
|
221
|
+
# Initial resize
|
|
222
|
+
resize_pty()
|
|
187
223
|
|
|
188
|
-
|
|
224
|
+
# Set up signal handler for window resize
|
|
225
|
+
def handle_sigwinch(signum, frame):
|
|
189
226
|
resize_pty()
|
|
190
227
|
|
|
191
|
-
|
|
192
|
-
def handle_sigwinch(signum, frame):
|
|
193
|
-
resize_pty()
|
|
228
|
+
old_sigwinch_handler = signal.signal(signal.SIGWINCH, handle_sigwinch)
|
|
194
229
|
|
|
195
|
-
|
|
230
|
+
# Save original terminal settings
|
|
231
|
+
old_tty = termios.tcgetattr(sys.stdin)
|
|
196
232
|
|
|
197
|
-
|
|
198
|
-
|
|
233
|
+
try:
|
|
234
|
+
# Set TERM environment variable to enable colors
|
|
235
|
+
env = os.environ.copy()
|
|
236
|
+
env["TERM"] = os.environ.get("TERM", "xterm-256color")
|
|
199
237
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
env = os.environ.copy()
|
|
203
|
-
env["TERM"] = os.environ.get("TERM", "xterm-256color")
|
|
238
|
+
process = subprocess.Popen([lldb_command], stdin=slave, stdout=slave, stderr=slave, env=env)
|
|
239
|
+
os.close(slave)
|
|
204
240
|
|
|
205
|
-
|
|
206
|
-
|
|
241
|
+
# Put terminal in raw mode for proper interaction
|
|
242
|
+
tty.setraw(sys.stdin.fileno())
|
|
243
|
+
# Send all commands through stdin
|
|
244
|
+
for command in commands:
|
|
245
|
+
os.write(master, (command + "\n").encode())
|
|
207
246
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
for command in commands:
|
|
212
|
-
os.write(master, (command + "\n").encode())
|
|
247
|
+
# Now redirect stdin from the terminal to lldb so user can interact
|
|
248
|
+
while True:
|
|
249
|
+
rlist, _, _ = select_module.select([sys.stdin, master], [], [])
|
|
213
250
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
251
|
+
if sys.stdin in rlist:
|
|
252
|
+
# User typed something
|
|
253
|
+
data = os.read(sys.stdin.fileno(), 1024)
|
|
254
|
+
if not data:
|
|
255
|
+
break
|
|
256
|
+
os.write(master, data)
|
|
217
257
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
258
|
+
if master in rlist:
|
|
259
|
+
# lldb has output
|
|
260
|
+
try:
|
|
261
|
+
data = os.read(master, 1024)
|
|
221
262
|
if not data:
|
|
222
263
|
break
|
|
223
|
-
os.write(
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
# Restore original SIGWINCH handler
|
|
240
|
-
signal.signal(signal.SIGWINCH, old_sigwinch_handler)
|
|
241
|
-
os.close(master)
|
|
242
|
-
if process is not None:
|
|
243
|
-
process.terminate()
|
|
244
|
-
process.wait()
|
|
264
|
+
os.write(sys.stdout.fileno(), data)
|
|
265
|
+
except OSError:
|
|
266
|
+
break
|
|
267
|
+
except (KeyboardInterrupt, OSError):
|
|
268
|
+
pass
|
|
269
|
+
finally:
|
|
270
|
+
# Restore terminal settings
|
|
271
|
+
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_tty)
|
|
272
|
+
# Restore original SIGWINCH handler
|
|
273
|
+
signal.signal(signal.SIGWINCH, old_sigwinch_handler)
|
|
274
|
+
os.close(master)
|
|
275
|
+
if process is not None:
|
|
276
|
+
process.terminate()
|
|
277
|
+
process.wait()
|
|
278
|
+
if temp_dir is not None:
|
|
279
|
+
temp_dir.cleanup()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pymobiledevice3
|
|
3
|
-
Version: 7.0
|
|
3
|
+
Version: 7.1.0
|
|
4
4
|
Summary: Pure python3 implementation for working with iDevices (iPhone, etc...)
|
|
5
5
|
Author-email: doronz88 <doron88@gmail.com>, matan <matan1008@gmail.com>
|
|
6
6
|
Maintainer-email: doronz88 <doron88@gmail.com>, matan <matan1008@gmail.com>
|
|
@@ -8,7 +8,7 @@ misc/understanding_idevice_protocol_layers.md,sha256=FMJQ-ik2j9kFLPS15JzDZg62uk1
|
|
|
8
8
|
misc/usbmux_sniff.sh,sha256=iWtbucOEQ9_UEFXk9x-2VNt48Jg5zrPsnUbZ_LfZxwA,212
|
|
9
9
|
pymobiledevice3/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
10
|
pymobiledevice3/__main__.py,sha256=Ogsyro4MUVVSciEtg8kZufL81AHcjuphItnaL0BT10Q,16386
|
|
11
|
-
pymobiledevice3/_version.py,sha256=
|
|
11
|
+
pymobiledevice3/_version.py,sha256=hoQMYVAGxOg65i7V5PoVLpY46qxSMJVk6GEsfI-0lRI,704
|
|
12
12
|
pymobiledevice3/bonjour.py,sha256=lmx3uCaiolF59AieftmTKqktNod5ZDyJ06oRZdYKHSE,13681
|
|
13
13
|
pymobiledevice3/ca.py,sha256=5_Y4F-zDFX_KeDL-M_TRCKKyrRRb9h1lBE8MGTWv91o,10606
|
|
14
14
|
pymobiledevice3/common.py,sha256=FZzF0BQYV5fCEUPbLo6jbt2Ig9s5YwR8AvX_iR124Ew,329
|
|
@@ -52,7 +52,7 @@ pymobiledevice3/cli/developer/__init__.py,sha256=idQOgVsitt3nfolyhZuA6KHN2j44JNV
|
|
|
52
52
|
pymobiledevice3/cli/developer/arbitration.py,sha256=7Eod6-dlSjAMBljbsIGHL_QG9LFbOPIXqpS9Y_4-Q3Y,1576
|
|
53
53
|
pymobiledevice3/cli/developer/condition.py,sha256=lb5BS8lVcgsb2yBgBsN2nK-j2u1_iVm_tBd1pSRHZB0,1294
|
|
54
54
|
pymobiledevice3/cli/developer/core_device.py,sha256=QzMVfghq3fKLI2NQ2Kg7r_zyFIWGCBt7ZS-GTLWDZs4,10895
|
|
55
|
-
pymobiledevice3/cli/developer/debugserver.py,sha256=
|
|
55
|
+
pymobiledevice3/cli/developer/debugserver.py,sha256=0hP6-x3xChcYCacxI7CuEWEsM8-u4i4GNYa1HeSMPXg,10464
|
|
56
56
|
pymobiledevice3/cli/developer/fetch_symbols.py,sha256=57HzVyUJPXL_I8EiqWArJ2Fczb2yX9y6nDMgjZcADo0,4353
|
|
57
57
|
pymobiledevice3/cli/developer/simulate_location.py,sha256=IVJQPYKUrQcsdpCxf2D2sgy6Nb3mUOFvK-Og_y5lfDM,1555
|
|
58
58
|
pymobiledevice3/cli/developer/accessibility/__init__.py,sha256=VpJSdnkEZhUuJXWy08wqgqObXv1PgZ2Ht4qy-560QRk,2271
|
|
@@ -180,9 +180,9 @@ pymobiledevice3/services/web_protocol/switch_to.py,sha256=TCdVrMfsvd18o-vZ0owVrE
|
|
|
180
180
|
pymobiledevice3/tunneld/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
181
181
|
pymobiledevice3/tunneld/api.py,sha256=Lwl1OdhPTgX6Zqezy8T4dEcXRfaEPwyGNClioTx3fUc,2338
|
|
182
182
|
pymobiledevice3/tunneld/server.py,sha256=dMEZAv_X-76l0vSalpq4x0IVkbE-MNGR77T-u1TiHuE,25752
|
|
183
|
-
pymobiledevice3-7.0.
|
|
184
|
-
pymobiledevice3-7.0.
|
|
185
|
-
pymobiledevice3-7.0.
|
|
186
|
-
pymobiledevice3-7.0.
|
|
187
|
-
pymobiledevice3-7.0.
|
|
188
|
-
pymobiledevice3-7.0.
|
|
183
|
+
pymobiledevice3-7.1.0.dist-info/licenses/LICENSE,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
|
|
184
|
+
pymobiledevice3-7.1.0.dist-info/METADATA,sha256=p_l-eHzSpqafrRTx3bUX1_OZEK_Af0-Mtfm34H6RFcw,17500
|
|
185
|
+
pymobiledevice3-7.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
186
|
+
pymobiledevice3-7.1.0.dist-info/entry_points.txt,sha256=jJMlOanHlVwUxcY__JwvKeWPrvBJr_wJyEq4oHIZNKE,66
|
|
187
|
+
pymobiledevice3-7.1.0.dist-info/top_level.txt,sha256=MjZoRqcWPOh5banG-BbDOnKEfsS3kCxqV9cv-nzyg2Q,21
|
|
188
|
+
pymobiledevice3-7.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|