diff --git a/.gitignore b/.gitignore index fafefb618..384c1b9a1 100644 --- a/.gitignore +++ b/.gitignore @@ -50,8 +50,10 @@ logs/ .specify/templates .specify/extensions.yml .specify/extensions +.specify/feature.json .specify/init-options.json .specify/integration.json .specify/integrations .specify/workflows .specify/workflow.yml +specs diff --git a/automation/src/automation/bootstraps/pyside6.py b/automation/src/automation/bootstraps/pyside6.py index fa934e244..a7ba19620 100644 --- a/automation/src/automation/bootstraps/pyside6.py +++ b/automation/src/automation/bootstraps/pyside6.py @@ -61,6 +61,6 @@ def pyproject_table_macOS(self): min_os_version = "13.0" requires = [ "PySide6-Addons~=6.8", - "std-nslog~=1.0.3", + "std-nslog~=2.0.0", ] """ diff --git a/changes/2877.bugfix.md b/changes/2877.bugfix.md new file mode 100644 index 000000000..e7eec466b --- /dev/null +++ b/changes/2877.bugfix.md @@ -0,0 +1 @@ +Briefcase is now able to display application logs when running apps under macOS 26. If you are experiencing this problem, you need to either (a) upgrade `std-nslog` to 2.0.0+, or target your application at Python 3.14 (or newer). diff --git a/src/briefcase/bootstraps/pygame.py b/src/briefcase/bootstraps/pygame.py index 8065a5db4..4cd304682 100644 --- a/src/briefcase/bootstraps/pygame.py +++ b/src/briefcase/bootstraps/pygame.py @@ -67,7 +67,7 @@ def pyproject_table_macOS(self): return """\ universal_build = true requires = [ - "std-nslog~=1.0.3", + "std-nslog~=2.0.0", ] """ diff --git a/src/briefcase/bootstraps/pyside6.py b/src/briefcase/bootstraps/pyside6.py index e6abade8b..15f7dfa1e 100644 --- a/src/briefcase/bootstraps/pyside6.py +++ b/src/briefcase/bootstraps/pyside6.py @@ -63,7 +63,7 @@ def pyproject_table_macOS(self): # Pyside 6.10 (required for Python 3.14 support) enforces a macOS 13 minimum. min_os_version = "13.0" requires = [ - "std-nslog~=1.0.3", + "std-nslog~=2.0.0", ] """ diff --git a/src/briefcase/bootstraps/toga.py b/src/briefcase/bootstraps/toga.py index 671e7aad6..3a4477e86 100644 --- a/src/briefcase/bootstraps/toga.py +++ b/src/briefcase/bootstraps/toga.py @@ -51,7 +51,7 @@ def pyproject_table_macOS(self): universal_build = true requires = [ "toga-cocoa~=0.5.0", - "std-nslog~=1.0.3", + "std-nslog~=2.0.0", ] """ @@ -206,7 +206,6 @@ def pyproject_table_iOS(self): return """\ requires = [ "toga-iOS~=0.5.0", - "std-nslog~=1.0.3", ] """ diff --git a/src/briefcase/integrations/cookiecutter.py b/src/briefcase/integrations/cookiecutter.py index 0a1e592d3..1b4ed971f 100644 --- a/src/briefcase/integrations/cookiecutter.py +++ b/src/briefcase/integrations/cookiecutter.py @@ -23,6 +23,10 @@ def py_libtag(obj): """A Python version library tag (311)""" return "".join(obj.split(".")[:2]) + def minor_version(obj): + """The Python minor version, as an integer (e.g., 11)""" + return int(obj.split(".")[1]) + def nuget_version(obj): """A Python version in Nuget format (3.14.0-rc1).""" parts = obj.split(".")[:3] @@ -32,6 +36,7 @@ def nuget_version(obj): environment.filters["py_tag"] = py_tag environment.filters["py_libtag"] = py_libtag + environment.filters["minor_version"] = minor_version environment.filters["nuget_version"] = nuget_version diff --git a/src/briefcase/platforms/iOS/xcode.py b/src/briefcase/platforms/iOS/xcode.py index 39a367214..9fbd2647a 100644 --- a/src/briefcase/platforms/iOS/xcode.py +++ b/src/briefcase/platforms/iOS/xcode.py @@ -625,7 +625,13 @@ def run_app( "Uninstalling any existing app version..." ) as keep_alive, self.tools.subprocess.Popen( - ["xcrun", "simctl", "uninstall", udid, app.bundle_identifier] + [ + "xcrun", + "simctl", + "uninstall", + udid, + app.bundle_identifier, + ] ) as uninstall_popen, ): while (ret_code := uninstall_popen.poll()) is None: @@ -641,7 +647,13 @@ def run_app( with ( self.console.wait_bar(f"Installing new {label} version...") as keep_alive, self.tools.subprocess.Popen( - ["xcrun", "simctl", "install", udid, self.binary_path(app)] + [ + "xcrun", + "simctl", + "install", + udid, + self.binary_path(app), + ] ) as install_popen, ): while (ret_code := install_popen.poll()) is None: @@ -661,7 +673,8 @@ def run_app( # and for native NSLog() calls in the bootstrap binary # Case (2) works when the standard library is dynamically linked, # and ctypes (which handles the NSLog integration) is an - # extension module. + # extension module. It also catches the case for the CPython + # builtin behavior of redirecting to the system log. # It's not enough to filter on *just* the processImagePath, # as the process will generate lots of system-level messages. # We can't filter on *just* the senderImagePath, because other @@ -679,10 +692,13 @@ def run_app( "--predicate", ( f'senderImagePath ENDSWITH "/{app.formal_name}"' - f' OR (processImagePath ENDSWITH "/{app.formal_name}"' - ' AND (senderImagePath ENDSWITH "-iphonesimulator.so"' - ' OR senderImagePath ENDSWITH "-iphonesimulator.dylib"' - ' OR senderImagePath ENDSWITH "_ctypes.framework/_ctypes"))' + f'OR (processImagePath ENDSWITH "/{app.formal_name}"' + ' AND (senderImagePath ENDSWITH "-iphonesimulator.so"' + ' OR senderImagePath ENDSWITH "-iphonesimulator.dylib"' + ' OR senderImagePath ENDSWITH "_ctypes.framework/_ctypes"' + ' OR senderImagePath ENDSWITH "/Python"' + " )" + ")" ), ], stdout=subprocess.PIPE, diff --git a/src/briefcase/platforms/macOS/__init__.py b/src/briefcase/platforms/macOS/__init__.py index ac66e254e..b4c7d3752 100644 --- a/src/briefcase/platforms/macOS/__init__.py +++ b/src/briefcase/platforms/macOS/__init__.py @@ -549,7 +549,10 @@ def run_gui_app( ( f'senderImagePath=="{sender}"' f' OR (processImagePath=="{sender}"' - ' AND senderImagePath=="/usr/lib/libffi.dylib")' + ' AND (senderImagePath=="/usr/lib/libffi.dylib" ' + ' OR senderImagePath ENDSWITH "/Python" ' + ' OR senderImagePath ENDSWITH ".abi3.so")' + " )" ), ], stdout=subprocess.PIPE, diff --git a/src/briefcase/platforms/macOS/filters.py b/src/briefcase/platforms/macOS/filters.py index 46833b0e3..7e8e61ba3 100644 --- a/src/briefcase/platforms/macOS/filters.py +++ b/src/briefcase/platforms/macOS/filters.py @@ -4,8 +4,10 @@ MACOS_LOG_PREFIX_REGEX = re.compile( r"\d{4}-\d{2}-\d{2} (?P\d{2}:\d{2}:\d{2}.\d{3}) Df (.*?)\[.*?:.*?\]" - r"(?P( \(libffi\.dylib\))|(" - r" \(_ctypes(\.cpython-3\d{1,2}-.*?\.(so|dylib))?\)))? (?P.*)" + r"(?P( \(libffi\.dylib\))|( \(Python\))" + r"|( \(_ctypes(\.cpython-3\d{1,2}-.*?\.(so|dylib))?\))" + r"|( \(_oslog_shim\..*?\.(so|dylib)?\))" + r")? (?P.*)" ) diff --git a/tests/commands/new/test_build_gui_context.py b/tests/commands/new/test_build_gui_context.py index f412cdc32..05b760489 100644 --- a/tests/commands/new/test_build_gui_context.py +++ b/tests/commands/new/test_build_gui_context.py @@ -66,7 +66,7 @@ def main(): universal_build = true requires = [ "toga-cocoa~=0.5.0", - "std-nslog~=1.0.3", + "std-nslog~=2.0.0", ] """, "pyproject_table_linux": """\ @@ -203,7 +203,6 @@ def main(): "pyproject_table_iOS": """\ requires = [ "toga-iOS~=0.5.0", - "std-nslog~=1.0.3", ] """, "pyproject_table_android": '''\ @@ -414,7 +413,7 @@ def main(): # Pyside 6.10 (required for Python 3.14 support) enforces a macOS 13 minimum. min_os_version = "13.0" requires = [ - "std-nslog~=1.0.3", + "std-nslog~=2.0.0", ] """, "pyproject_table_linux": """\ @@ -567,7 +566,7 @@ def main(): "pyproject_table_macOS": """\ universal_build = true requires = [ - "std-nslog~=1.0.3", + "std-nslog~=2.0.0", ] """, "pyproject_table_linux": """\ diff --git a/tests/integrations/cookiecutter/test_PythonVersionExtension.py b/tests/integrations/cookiecutter/test_PythonVersionExtension.py index a1390ddff..c5fe74948 100644 --- a/tests/integrations/cookiecutter/test_PythonVersionExtension.py +++ b/tests/integrations/cookiecutter/test_PythonVersionExtension.py @@ -53,6 +53,30 @@ def test_py_libtag(value, expected): assert env.filters["py_libtag"](value) == expected +@pytest.mark.parametrize( + ("value", "expected"), + [ + # Single digit minor + ("3.8.4.dev5", 8), + ("3.8.4a1", 8), + ("3.8.4b2", 8), + ("3.8.4rc3", 8), + ("3.8.4.post6", 8), + # Two digit minor + ("3.11.4.dev5", 11), + ("3.11.4a1", 11), + ("3.11.4b2", 11), + ("3.11.4rc3", 11), + ("3.11.4.post6", 11), + ], +) +def test_minor_version(value, expected): + env = MagicMock() + env.filters = {} + PythonVersionExtension(env) + assert env.filters["minor_version"](value) == expected + + @pytest.mark.parametrize( ("value", "expected"), [ diff --git a/tests/platforms/iOS/xcode/test_run.py b/tests/platforms/iOS/xcode/test_run.py index 60885e9c5..70df8bb00 100644 --- a/tests/platforms/iOS/xcode/test_run.py +++ b/tests/platforms/iOS/xcode/test_run.py @@ -179,10 +179,13 @@ def test_run_app_simulator_booted(run_command, first_app_config, tmp_path): "compact", "--predicate", 'senderImagePath ENDSWITH "/First App"' - ' OR (processImagePath ENDSWITH "/First App"' - ' AND (senderImagePath ENDSWITH "-iphonesimulator.so"' - ' OR senderImagePath ENDSWITH "-iphonesimulator.dylib"' - ' OR senderImagePath ENDSWITH "_ctypes.framework/_ctypes"))', + 'OR (processImagePath ENDSWITH "/First App"' + ' AND (senderImagePath ENDSWITH "-iphonesimulator.so"' + ' OR senderImagePath ENDSWITH "-iphonesimulator.dylib"' + ' OR senderImagePath ENDSWITH "_ctypes.framework/_ctypes"' + ' OR senderImagePath ENDSWITH "/Python"' + " )" + ")", ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -310,10 +313,13 @@ def test_run_app_simulator_booted_underscore( "compact", "--predicate", 'senderImagePath ENDSWITH "/First App"' - ' OR (processImagePath ENDSWITH "/First App"' - ' AND (senderImagePath ENDSWITH "-iphonesimulator.so"' - ' OR senderImagePath ENDSWITH "-iphonesimulator.dylib"' - ' OR senderImagePath ENDSWITH "_ctypes.framework/_ctypes"))', + 'OR (processImagePath ENDSWITH "/First App"' + ' AND (senderImagePath ENDSWITH "-iphonesimulator.so"' + ' OR senderImagePath ENDSWITH "-iphonesimulator.dylib"' + ' OR senderImagePath ENDSWITH "_ctypes.framework/_ctypes"' + ' OR senderImagePath ENDSWITH "/Python"' + " )" + ")", ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -438,10 +444,13 @@ def test_run_app_with_passthrough(run_command, first_app_config, tmp_path): "compact", "--predicate", 'senderImagePath ENDSWITH "/First App"' - ' OR (processImagePath ENDSWITH "/First App"' - ' AND (senderImagePath ENDSWITH "-iphonesimulator.so"' - ' OR senderImagePath ENDSWITH "-iphonesimulator.dylib"' - ' OR senderImagePath ENDSWITH "_ctypes.framework/_ctypes"))', + 'OR (processImagePath ENDSWITH "/First App"' + ' AND (senderImagePath ENDSWITH "-iphonesimulator.so"' + ' OR senderImagePath ENDSWITH "-iphonesimulator.dylib"' + ' OR senderImagePath ENDSWITH "_ctypes.framework/_ctypes"' + ' OR senderImagePath ENDSWITH "/Python"' + " )" + ")", ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -573,10 +582,13 @@ def test_run_app_simulator_shut_down( "compact", "--predicate", 'senderImagePath ENDSWITH "/First App"' - ' OR (processImagePath ENDSWITH "/First App"' - ' AND (senderImagePath ENDSWITH "-iphonesimulator.so"' - ' OR senderImagePath ENDSWITH "-iphonesimulator.dylib"' - ' OR senderImagePath ENDSWITH "_ctypes.framework/_ctypes"))', + 'OR (processImagePath ENDSWITH "/First App"' + ' AND (senderImagePath ENDSWITH "-iphonesimulator.so"' + ' OR senderImagePath ENDSWITH "-iphonesimulator.dylib"' + ' OR senderImagePath ENDSWITH "_ctypes.framework/_ctypes"' + ' OR senderImagePath ENDSWITH "/Python"' + " )" + ")", ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -714,10 +726,13 @@ def test_run_app_simulator_shutting_down(run_command, first_app_config, tmp_path "compact", "--predicate", 'senderImagePath ENDSWITH "/First App"' - ' OR (processImagePath ENDSWITH "/First App"' - ' AND (senderImagePath ENDSWITH "-iphonesimulator.so"' - ' OR senderImagePath ENDSWITH "-iphonesimulator.dylib"' - ' OR senderImagePath ENDSWITH "_ctypes.framework/_ctypes"))', + 'OR (processImagePath ENDSWITH "/First App"' + ' AND (senderImagePath ENDSWITH "-iphonesimulator.so"' + ' OR senderImagePath ENDSWITH "-iphonesimulator.dylib"' + ' OR senderImagePath ENDSWITH "_ctypes.framework/_ctypes"' + ' OR senderImagePath ENDSWITH "/Python"' + " )" + ")", ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -1090,10 +1105,13 @@ def test_run_app_simulator_launch_failure(run_command, first_app_config, tmp_pat "compact", "--predicate", 'senderImagePath ENDSWITH "/First App"' - ' OR (processImagePath ENDSWITH "/First App"' - ' AND (senderImagePath ENDSWITH "-iphonesimulator.so"' - ' OR senderImagePath ENDSWITH "-iphonesimulator.dylib"' - ' OR senderImagePath ENDSWITH "_ctypes.framework/_ctypes"))', + 'OR (processImagePath ENDSWITH "/First App"' + ' AND (senderImagePath ENDSWITH "-iphonesimulator.so"' + ' OR senderImagePath ENDSWITH "-iphonesimulator.dylib"' + ' OR senderImagePath ENDSWITH "_ctypes.framework/_ctypes"' + ' OR senderImagePath ENDSWITH "/Python"' + " )" + ")", ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -1211,10 +1229,13 @@ def test_run_app_simulator_no_pid(run_command, first_app_config, tmp_path): "compact", "--predicate", 'senderImagePath ENDSWITH "/First App"' - ' OR (processImagePath ENDSWITH "/First App"' - ' AND (senderImagePath ENDSWITH "-iphonesimulator.so"' - ' OR senderImagePath ENDSWITH "-iphonesimulator.dylib"' - ' OR senderImagePath ENDSWITH "_ctypes.framework/_ctypes"))', + 'OR (processImagePath ENDSWITH "/First App"' + ' AND (senderImagePath ENDSWITH "-iphonesimulator.so"' + ' OR senderImagePath ENDSWITH "-iphonesimulator.dylib"' + ' OR senderImagePath ENDSWITH "_ctypes.framework/_ctypes"' + ' OR senderImagePath ENDSWITH "/Python"' + " )" + ")", ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -1334,10 +1355,13 @@ def test_run_app_simulator_non_integer_pid(run_command, first_app_config, tmp_pa "compact", "--predicate", 'senderImagePath ENDSWITH "/First App"' - ' OR (processImagePath ENDSWITH "/First App"' - ' AND (senderImagePath ENDSWITH "-iphonesimulator.so"' - ' OR senderImagePath ENDSWITH "-iphonesimulator.dylib"' - ' OR senderImagePath ENDSWITH "_ctypes.framework/_ctypes"))', + 'OR (processImagePath ENDSWITH "/First App"' + ' AND (senderImagePath ENDSWITH "-iphonesimulator.so"' + ' OR senderImagePath ENDSWITH "-iphonesimulator.dylib"' + ' OR senderImagePath ENDSWITH "_ctypes.framework/_ctypes"' + ' OR senderImagePath ENDSWITH "/Python"' + " )" + ")", ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -1438,10 +1462,13 @@ def test_run_app_test_mode(run_command, first_app_config, tmp_path): "compact", "--predicate", 'senderImagePath ENDSWITH "/First App"' - ' OR (processImagePath ENDSWITH "/First App"' - ' AND (senderImagePath ENDSWITH "-iphonesimulator.so"' - ' OR senderImagePath ENDSWITH "-iphonesimulator.dylib"' - ' OR senderImagePath ENDSWITH "_ctypes.framework/_ctypes"))', + 'OR (processImagePath ENDSWITH "/First App"' + ' AND (senderImagePath ENDSWITH "-iphonesimulator.so"' + ' OR senderImagePath ENDSWITH "-iphonesimulator.dylib"' + ' OR senderImagePath ENDSWITH "_ctypes.framework/_ctypes"' + ' OR senderImagePath ENDSWITH "/Python"' + " )" + ")", ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -1554,10 +1581,13 @@ def test_run_app_test_mode_with_passthrough(run_command, first_app_config, tmp_p "compact", "--predicate", 'senderImagePath ENDSWITH "/First App"' - ' OR (processImagePath ENDSWITH "/First App"' - ' AND (senderImagePath ENDSWITH "-iphonesimulator.so"' - ' OR senderImagePath ENDSWITH "-iphonesimulator.dylib"' - ' OR senderImagePath ENDSWITH "_ctypes.framework/_ctypes"))', + 'OR (processImagePath ENDSWITH "/First App"' + ' AND (senderImagePath ENDSWITH "-iphonesimulator.so"' + ' OR senderImagePath ENDSWITH "-iphonesimulator.dylib"' + ' OR senderImagePath ENDSWITH "_ctypes.framework/_ctypes"' + ' OR senderImagePath ENDSWITH "/Python"' + " )" + ")", ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -1715,10 +1745,13 @@ def test_run_app_debugger(run_command, first_app_generated, tmp_path, dummy_debu "compact", "--predicate", 'senderImagePath ENDSWITH "/First App"' - ' OR (processImagePath ENDSWITH "/First App"' - ' AND (senderImagePath ENDSWITH "-iphonesimulator.so"' - ' OR senderImagePath ENDSWITH "-iphonesimulator.dylib"' - ' OR senderImagePath ENDSWITH "_ctypes.framework/_ctypes"))', + 'OR (processImagePath ENDSWITH "/First App"' + ' AND (senderImagePath ENDSWITH "-iphonesimulator.so"' + ' OR senderImagePath ENDSWITH "-iphonesimulator.dylib"' + ' OR senderImagePath ENDSWITH "_ctypes.framework/_ctypes"' + ' OR senderImagePath ENDSWITH "/Python"' + " )" + ")", ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, diff --git a/tests/platforms/macOS/app/test_run.py b/tests/platforms/macOS/app/test_run.py index 872bd2406..086b413b3 100644 --- a/tests/platforms/macOS/app/test_run.py +++ b/tests/platforms/macOS/app/test_run.py @@ -58,9 +58,14 @@ def test_run_gui_app(run_command, first_app_config, sleep_zero, tmp_path, monkey "--style", "compact", "--predicate", - f'senderImagePath=="{sender}"' - f' OR (processImagePath=="{sender}"' - ' AND senderImagePath=="/usr/lib/libffi.dylib")', + ( + f'senderImagePath=="{sender}"' + f' OR (processImagePath=="{sender}"' + ' AND (senderImagePath=="/usr/lib/libffi.dylib" ' + ' OR senderImagePath ENDSWITH "/Python" ' + ' OR senderImagePath ENDSWITH ".abi3.so")' + " )" + ), ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -121,9 +126,14 @@ def test_run_gui_app_with_passthrough( "--style", "compact", "--predicate", - f'senderImagePath=="{sender}"' - f' OR (processImagePath=="{sender}"' - ' AND senderImagePath=="/usr/lib/libffi.dylib")', + ( + f'senderImagePath=="{sender}"' + f' OR (processImagePath=="{sender}"' + ' AND (senderImagePath=="/usr/lib/libffi.dylib" ' + ' OR senderImagePath ENDSWITH "/Python" ' + ' OR senderImagePath ENDSWITH ".abi3.so")' + " )" + ), ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -171,9 +181,14 @@ def test_run_gui_app_failed(run_command, first_app_config, sleep_zero, tmp_path) "--style", "compact", "--predicate", - f'senderImagePath=="{sender}"' - f' OR (processImagePath=="{sender}"' - ' AND senderImagePath=="/usr/lib/libffi.dylib")', + ( + f'senderImagePath=="{sender}"' + f' OR (processImagePath=="{sender}"' + ' AND (senderImagePath=="/usr/lib/libffi.dylib" ' + ' OR senderImagePath ENDSWITH "/Python" ' + ' OR senderImagePath ENDSWITH ".abi3.so")' + " )" + ), ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -218,9 +233,14 @@ def test_run_gui_app_find_pid_failed( "--style", "compact", "--predicate", - f'senderImagePath=="{sender}"' - f' OR (processImagePath=="{sender}"' - ' AND senderImagePath=="/usr/lib/libffi.dylib")', + ( + f'senderImagePath=="{sender}"' + f' OR (processImagePath=="{sender}"' + ' AND (senderImagePath=="/usr/lib/libffi.dylib" ' + ' OR senderImagePath ENDSWITH "/Python" ' + ' OR senderImagePath ENDSWITH ".abi3.so")' + " )" + ), ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -271,9 +291,14 @@ def test_run_gui_app_test_mode( "--style", "compact", "--predicate", - f'senderImagePath=="{sender}"' - f' OR (processImagePath=="{sender}"' - ' AND senderImagePath=="/usr/lib/libffi.dylib")', + ( + f'senderImagePath=="{sender}"' + f' OR (processImagePath=="{sender}"' + ' AND (senderImagePath=="/usr/lib/libffi.dylib" ' + ' OR senderImagePath ENDSWITH "/Python" ' + ' OR senderImagePath ENDSWITH ".abi3.so")' + " )" + ), ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -334,9 +359,14 @@ def test_run_gui_app_debugger( "--style", "compact", "--predicate", - f'senderImagePath=="{sender}"' - f' OR (processImagePath=="{sender}"' - ' AND senderImagePath=="/usr/lib/libffi.dylib")', + ( + f'senderImagePath=="{sender}"' + f' OR (processImagePath=="{sender}"' + ' AND (senderImagePath=="/usr/lib/libffi.dylib" ' + ' OR senderImagePath ENDSWITH "/Python" ' + ' OR senderImagePath ENDSWITH ".abi3.so")' + " )" + ), ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, diff --git a/tests/platforms/macOS/test_macOS_log_clean_filter.py b/tests/platforms/macOS/test_macOS_log_clean_filter.py index 2b5fc415a..9a047910e 100644 --- a/tests/platforms/macOS/test_macOS_log_clean_filter.py +++ b/tests/platforms/macOS/test_macOS_log_clean_filter.py @@ -44,16 +44,36 @@ "2022-11-14 13:21:14.972 Df My App[59972:780a15] ", ("", False), ), - # macOS App log + # macOS App log (std-nslog 1.*) ( "2022-11-14 13:21:15.341 Df My App[59972:780a15] (libffi.dylib) Hello World!", ("Hello World!", True), ), - # Empty macOS App log + # Empty macOS App log (std-nslog 1.*) ( "2022-11-14 13:21:15.341 Df My App[59972:780a15] (libffi.dylib) ", ("", True), ), + # macOS App log (os_log shim) + ( + "2022-11-14 13:21:15.341 Df My App[59972:780a15] (_oslog_shim.abi3.so) Hello World!", + ("Hello World!", True), + ), + # Empty macOS App log (os_log shim) + ( + "2022-11-14 13:21:15.341 Df My App[59972:780a15] (_oslog_shim.abi3.so) ", + ("", True), + ), + # macOS App log (CPython use_system_logger) + ( + "2022-11-14 13:21:15.341 Df My App[59972:780a15] (Python) Hello World!", + ("Hello World!", True), + ), + # Empty macOS App log (CPython use_system_logger) + ( + "2022-11-14 13:21:15.341 Df My App[59972:780a15] (Python) ", + ("", True), + ), # iOS App log (old style .so libraries) ( "2022-11-14 13:21:15.341 Df My App[59972:780a15] (_ctypes.cpython-312-iphonesimulator.so) Hello World!", diff --git a/tests/platforms/macOS/xcode/test_run.py b/tests/platforms/macOS/xcode/test_run.py index 58084a878..3a762fd88 100644 --- a/tests/platforms/macOS/xcode/test_run.py +++ b/tests/platforms/macOS/xcode/test_run.py @@ -57,9 +57,14 @@ def test_run_app(run_command, first_app_config, sleep_zero, tmp_path, monkeypatc "--style", "compact", "--predicate", - f'senderImagePath=="{sender}"' - f' OR (processImagePath=="{sender}"' - ' AND senderImagePath=="/usr/lib/libffi.dylib")', + ( + f'senderImagePath=="{sender}"' + f' OR (processImagePath=="{sender}"' + ' AND (senderImagePath=="/usr/lib/libffi.dylib" ' + ' OR senderImagePath ENDSWITH "/Python" ' + ' OR senderImagePath ENDSWITH ".abi3.so")' + " )" + ), ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -118,9 +123,14 @@ def test_run_app_with_passthrough( "--style", "compact", "--predicate", - f'senderImagePath=="{sender}"' - f' OR (processImagePath=="{sender}"' - ' AND senderImagePath=="/usr/lib/libffi.dylib")', + ( + f'senderImagePath=="{sender}"' + f' OR (processImagePath=="{sender}"' + ' AND (senderImagePath=="/usr/lib/libffi.dylib" ' + ' OR senderImagePath ENDSWITH "/Python" ' + ' OR senderImagePath ENDSWITH ".abi3.so")' + " )" + ), ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -177,9 +187,14 @@ def test_run_app_test_mode( "--style", "compact", "--predicate", - f'senderImagePath=="{sender}"' - f' OR (processImagePath=="{sender}"' - ' AND senderImagePath=="/usr/lib/libffi.dylib")', + ( + f'senderImagePath=="{sender}"' + f' OR (processImagePath=="{sender}"' + ' AND (senderImagePath=="/usr/lib/libffi.dylib" ' + ' OR senderImagePath ENDSWITH "/Python" ' + ' OR senderImagePath ENDSWITH ".abi3.so")' + " )" + ), ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -241,9 +256,14 @@ def test_run_app_test_mode_with_passthrough( "--style", "compact", "--predicate", - f'senderImagePath=="{sender}"' - f' OR (processImagePath=="{sender}"' - ' AND senderImagePath=="/usr/lib/libffi.dylib")', + ( + f'senderImagePath=="{sender}"' + f' OR (processImagePath=="{sender}"' + ' AND (senderImagePath=="/usr/lib/libffi.dylib" ' + ' OR senderImagePath ENDSWITH "/Python" ' + ' OR senderImagePath ENDSWITH ".abi3.so")' + " )" + ), ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT,