diff --git a/pkgs/development/python-modules/pyshark/default.nix b/pkgs/development/python-modules/pyshark/default.nix index 64db47763f55..1a6e2c043989 100644 --- a/pkgs/development/python-modules/pyshark/default.nix +++ b/pkgs/development/python-modules/pyshark/default.nix @@ -29,10 +29,6 @@ buildPythonPackage (finalAttrs: { version = "0.6"; pyproject = true; - # Almost all tests fail with: - # RuntimeError: There is no current event loop in thread 'MainThread' - disabled = pythonAtLeast "3.14"; - src = fetchFromGitHub { owner = "KimiNewt"; repo = "pyshark"; @@ -58,6 +54,8 @@ buildPythonPackage (finalAttrs: { (replaceVars ./hardcode-tshark-path.patch { tshark = lib.getExe' wireshark-cli "tshark"; }) + # Compat for Python 3.14 asyncio changes + ./py314-compat.patch ]; sourceRoot = "${finalAttrs.src.name}/src"; @@ -81,6 +79,13 @@ buildPythonPackage (finalAttrs: { # KeyError: 'Packet of index 0 does not exist in capture' "test_getting_packet_summary" ] + ++ lib.optionals (pythonAtLeast "3.14") [ + # _pickle.PicklingError: logger cannot be pickled + "test_iterate_empty_psml_capture" + # configparser.NoSectionError: No section: 'tshark' + # Path is mocked, and yet... + "test_get_tshark_path" + ] ++ lib.optionals stdenv.hostPlatform.isDarwin [ # fails on darwin # _pickle.PicklingError: logger cannot be pickled diff --git a/pkgs/development/python-modules/pyshark/py314-compat.patch b/pkgs/development/python-modules/pyshark/py314-compat.patch new file mode 100644 index 000000000000..e1f457e168ed --- /dev/null +++ b/pkgs/development/python-modules/pyshark/py314-compat.patch @@ -0,0 +1,37 @@ +diff --git a/src/pyshark/capture/capture.py b/src/pyshark/capture/capture.py +index b7aef6e..8967398 100644 +--- a/src/pyshark/capture/capture.py ++++ b/src/pyshark/capture/capture.py +@@ -182,25 +182,16 @@ class Capture: + asyncio.set_event_loop(self.eventloop) + else: + try: +- self.eventloop = asyncio.get_event_loop_policy().get_event_loop() ++ self.eventloop = asyncio.get_running_loop() + except RuntimeError: +- if threading.current_thread() != threading.main_thread(): +- # Ran not in main thread, make a new eventloop ++ try: ++ # Python <3.14: may return an existing non-running loop. ++ self.eventloop = asyncio.get_event_loop() ++ except RuntimeError: ++ # Python 3.14+: no loop exists for this thread. + self.eventloop = asyncio.new_event_loop() + asyncio.set_event_loop(self.eventloop) +- else: +- raise +- if os.name == "posix" and isinstance(threading.current_thread(), threading._MainThread): +- # The default child watchers (ThreadedChildWatcher) attach_loop method is empty! +- # While using pyshark with ThreadedChildWatcher, asyncio could raise a ChildProcessError +- # "Unknown child process pid %d, will report returncode 255" +- # This led to a TSharkCrashException in _cleanup_subprocess. +- # Using the SafeChildWatcher fixes this issue, but it is slower. +- # SafeChildWatcher O(n) -> large numbers of processes are slow +- # ThreadedChildWatcher O(1) -> independent of process number +- # asyncio.get_child_watcher().attach_loop(self.eventloop) +- asyncio.set_child_watcher(asyncio.SafeChildWatcher()) +- asyncio.get_child_watcher().attach_loop(self.eventloop) ++ + + def _packets_from_tshark_sync(self, packet_count=None, existing_process=None): + """Returns a generator of packets.