From 7a4e8b025cf5a0e9e943ad18572409807e0e6b63 Mon Sep 17 00:00:00 2001 From: thomasjm Date: Thu, 27 Aug 2026 00:02:02 -0700 Subject: [PATCH 1/4] Keep PyPy-unsupported check inputs out of the pypy3 kernel closure --- modules/kernels/python/module.nix | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/modules/kernels/python/module.nix b/modules/kernels/python/module.nix index 49b241f9..62992206 100644 --- a/modules/kernels/python/module.nix +++ b/modules/kernels/python/module.nix @@ -192,7 +192,15 @@ in config.pkgs.callPackage ./. { name = "PyPy"; - python3 = lib.getAttr config.kernels.pypy3.python3Package config.pkgs; + # A package that isn't supported on PyPy throws when its outPath is evaluated, even + # when it's only ever a check input. Drop the two that the kernel's closure reaches: + # typeguard -> mypy (via stack-data and ipython), and debugpy -> django -> objgraph. + python3 = (lib.getAttr config.kernels.pypy3.python3Package config.pkgs).override { + packageOverrides = _pyFinal: pyPrev: { + typeguard = pyPrev.typeguard.override { mypy = null; }; + debugpy = pyPrev.debugpy.override { django = null; }; + }; + }; settings = config.kernels.pypy3; settingsSchema = nixosOptionsToSettingsSchema { componentsToDrop = 2; } options.kernels.pypy3; From 0ca7e470be91bad40b45fa50dc29883674a27cdf Mon Sep 17 00:00:00 2001 From: thomasjm Date: Thu, 27 Aug 2026 00:19:43 -0700 Subject: [PATCH 2/4] Skip PyPy test suites and give pyzmq its cffi backend so the pypy3 kernel builds --- modules/kernels/python/module.nix | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/modules/kernels/python/module.nix b/modules/kernels/python/module.nix index 62992206..d90f5c56 100644 --- a/modules/kernels/python/module.nix +++ b/modules/kernels/python/module.nix @@ -192,14 +192,26 @@ in config.pkgs.callPackage ./. { name = "PyPy"; - # A package that isn't supported on PyPy throws when its outPath is evaluated, even - # when it's only ever a check input. Drop the two that the kernel's closure reaches: - # typeguard -> mypy (via stack-data and ipython), and debugpy -> django -> objgraph. python3 = (lib.getAttr config.kernels.pypy3.python3Package config.pkgs).override { - packageOverrides = _pyFinal: pyPrev: { - typeguard = pyPrev.typeguard.override { mypy = null; }; - debugpy = pyPrev.debugpy.override { django = null; }; - }; + packageOverrides = pyFinal: pyPrev: + # Test suites are the main thing standing between PyPy and a working kernel: a + # package unsupported on PyPy throws when its outPath is evaluated even as a mere + # check input, and several check inputs are C extensions that don't compile here. + (lib.mapAttrs (_name: value: + let isPythonPackage = builtins.tryEval (lib.isDerivation value && value ? overridePythonAttrs); + in if isPythonPackage.success && isPythonPackage.value + then value.overridePythonAttrs (_: { doCheck = false; }) + else value + ) pyPrev) + // { + # On PyPy, pyzmq builds and runs against cffi rather than Cython, but nixpkgs + # only wires up the Cython path. + pyzmq = pyPrev.pyzmq.overridePythonAttrs (old: { + doCheck = false; + build-system = (old.build-system or []) ++ [ pyFinal.cffi pyFinal.pycparser ]; + dependencies = (old.dependencies or []) ++ [ pyFinal.cffi pyFinal.pycparser ]; + }); + }; }; settings = config.kernels.pypy3; From 0bb9e3290e1fb9faa6248f999f90f23462b170c0 Mon Sep 17 00:00:00 2001 From: thomasjm Date: Thu, 27 Aug 2026 00:19:43 -0700 Subject: [PATCH 3/4] Launch Python kernels via the interpreter path the environment reports --- modules/kernels/python/kernel.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/kernels/python/kernel.nix b/modules/kernels/python/kernel.nix index 9d606260..4c443188 100644 --- a/modules/kernels/python/kernel.nix +++ b/modules/kernels/python/kernel.nix @@ -32,7 +32,8 @@ common.makeJupyterKernel ( displayName = displayName; language = kernelName; argv = [ - "${python}/bin/python" + # PyPy environments name the binary pypy3, so take the path the environment reports. + python.interpreter "-m" "ipykernel" "-f" From 0d4f902f3e929081c7f0dde4cd31d9e5637c2183 Mon Sep 17 00:00:00 2001 From: thomasjm Date: Thu, 27 Aug 2026 04:04:34 -0700 Subject: [PATCH 4/4] Cover the pypy3 kernel with a sample environment and a kernel test --- sample_environments/pypy3.nix | 7 +------ tests/app/Spec/Tests/Python.hs | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/sample_environments/pypy3.nix b/sample_environments/pypy3.nix index 25cc33da..5eace115 100644 --- a/sample_environments/pypy3.nix +++ b/sample_environments/pypy3.nix @@ -5,10 +5,5 @@ codedown.makeEnvironment { name = "pypy3"; - # kernels.pypy3.enable = true; - # kernels.pypy3.packages = [ - # "matplotlib" - # "scipy" - # "rope" - # ]; + kernels.pypy3.enable = true; } diff --git a/tests/app/Spec/Tests/Python.hs b/tests/app/Spec/Tests/Python.hs index c1889cc3..d23cea0d 100644 --- a/tests/app/Spec/Tests/Python.hs +++ b/tests/app/Spec/Tests/Python.hs @@ -26,7 +26,7 @@ tests = describe "Python" $ parallel $ do tests' ("python3", "python313") -- tests' ("python3", "python314") - -- tests' ("pypy3", "pypy3") + pypyTests tests' :: (Text, Text) -> LanguageSpec tests' (kernelName, pythonPackage) = introduceNixEnvironment [kernelSpec kernelName pythonPackage] [] [i|Python (#{pythonPackage})|] $ introduceJupyterRunner $ do @@ -72,6 +72,26 @@ tests' (kernelName, pythonPackage) = introduceNixEnvironment [kernelSpec kernelN assertDiagnosticRanges diagnostics [] +-- | Nixpkgs carries far less for PyPy than for CPython, so this covers the kernel itself +-- rather than the package and language server stack the CPython tests exercise. +pypyTests :: LanguageSpec +pypyTests = introduceNixEnvironment [pypyKernelSpec] [] "Python (pypy3)" $ introduceJupyterRunner $ do + testHasExpectedFields "pypy3" + + testKernelStdout "pypy3" [i|print("hi")|] "hi\n" + testKernelStdout "pypy3" [i|import platform; print(platform.python_implementation())|] "PyPy\n" + +pypyKernelSpec :: NixKernelSpec +pypyKernelSpec = NixKernelSpec { + nixKernelName = "pypy3" + , nixKernelChannel = "codedown" + , nixKernelDisplayName = Just "PyPy" + , nixKernelPackages = [] + , nixKernelMeta = Nothing + , nixKernelIcon = Nothing + , nixKernelExtraConfig = Nothing + } + kernelSpec :: Text -> Text -> NixKernelSpec kernelSpec kernelName pythonPackage = NixKernelSpec { nixKernelName = kernelName