Skip to content

gimp2: remove opt-in python2 support#479956

Merged
doronbehar merged 1 commit intoNixOS:masterfrom
Sigmanificient:python2-removal/gimp
Jan 14, 2026
Merged

gimp2: remove opt-in python2 support#479956
doronbehar merged 1 commit intoNixOS:masterfrom
Sigmanificient:python2-removal/gimp

Conversation

@Sigmanificient
Copy link
Copy Markdown
Member

@Sigmanificient Sigmanificient commented Jan 14, 2026

This option has likely not been working for a bit, as many dependencies are completely broken or missing to build gimp2.override { withPython = true; }:

  • scandir, setuptools_scm and typing are needed, but they have been removed:

    Well this is my bad, i failed to see that they were actually used in python3-modules packages referenced within python2-modules 😔

  • enum34 is required but alse has been removed, and a while ago:

    It seems i was not the only one to break python2 by inadvertance. It is particularly easy to miss, with enum34 and pathlib2 in python3-modules.

  • wcwidth is overriding it's python3Packages brother, and does not work at all.
    this could be fixed by pinning it back to 0.2.12

  • pathlib2 is missing scandir and typing

  • backports-functools-lru-cache has an issue with a missing setup.py, which can be fixed using the following:

      preBuild = ''
        echo -e "import setuptools\nsetuptools.setup()" > setup.py
      '';
Complete patch for a version that builds
diff --git a/pkgs/development/python-modules/pathlib2/default.nix b/pkgs/development/python-modules/pathlib2/default.nix
index f922218f9142..7fc2f44b3ea0 100644
--- a/pkgs/development/python-modules/pathlib2/default.nix
+++ b/pkgs/development/python-modules/pathlib2/default.nix
@@ -3,6 +3,7 @@
   buildPythonPackage,
   fetchPypi,
   six,
+  typing
 }:
 
 buildPythonPackage rec {
@@ -17,6 +18,7 @@ buildPythonPackage rec {
 
   propagatedBuildInputs = [
     six
+    typing
   ];
 
   meta = {
diff --git a/pkgs/development/python2-modules/backports-functools-lru-cache/default.nix b/pkgs/development/python2-modules/backports-functools-lru-cache/default.nix
index 78a52491f1fc..4a1bc31bc60d 100644
--- a/pkgs/development/python2-modules/backports-functools-lru-cache/default.nix
+++ b/pkgs/development/python2-modules/backports-functools-lru-cache/default.nix
@@ -17,6 +17,10 @@ buildPythonPackage rec {
     hash = "sha256-e3DnAbpNtYwO2GcanTORsKu5vRvCTU6Qw0gPS6r8wtw=";
   };
 
+  preBuild = ''
+    echo -e "import setuptools\nsetuptools.setup()" > setup.py
+  '';
+
   nativeBuildInputs = [
     setuptools
     setuptools-scm
diff --git a/pkgs/development/python2-modules/enum34/default.nix b/pkgs/development/python2-modules/enum34/default.nix
new file mode 100644
index 000000000000..940fe7af28d3
--- /dev/null
+++ b/pkgs/development/python2-modules/enum34/default.nix
@@ -0,0 +1,28 @@
+{
+  lib,
+  buildPythonPackage,
+  fetchPypi,
+  pythonAtLeast,
+  unittestCheckHook,
+}:
+
+if pythonAtLeast "3.4" then
+  null
+else
+  buildPythonPackage rec {
+    pname = "enum34";
+    version = "1.1.10";
+
+    src = fetchPypi {
+      inherit pname version;
+      sha256 = "cce6a7477ed816bd2542d03d53db9f0db935dd013b70f336a95c73979289f248";
+    };
+
+    nativeCheckInputs = [ unittestCheckHook ];
+
+    meta = with lib; {
+      homepage = "https://pypi.python.org/pypi/enum34";
+      description = "Python 3.4 Enum backported to 3.3, 3.2, 3.1, 2.7, 2.6, 2.5, and 2.4";
+      license = licenses.bsd0;
+    };
+  }
diff --git a/pkgs/development/python2-modules/hypothesis/default.nix b/pkgs/development/python2-modules/hypothesis/default.nix
index d2b8c9066f89..04b40354428d 100644
--- a/pkgs/development/python2-modules/hypothesis/default.nix
+++ b/pkgs/development/python2-modules/hypothesis/default.nix
@@ -11,6 +11,7 @@
   flaky,
   mock,
   sortedcontainers,
+  enum34,
 }:
 buildPythonPackage rec {
   # https://hypothesis.readthedocs.org/en/latest/packaging.html
@@ -37,6 +38,7 @@ buildPythonPackage rec {
     attrs
     coverage
     sortedcontainers
+    enum34
   ];
 
   nativeCheckInputs = [
diff --git a/pkgs/development/python2-modules/pathlib2/default.nix b/pkgs/development/python2-modules/pathlib2/default.nix
new file mode 100644
index 000000000000..87baf22c8001
--- /dev/null
+++ b/pkgs/development/python2-modules/pathlib2/default.nix
@@ -0,0 +1,35 @@
+{
+  lib,
+  buildPythonPackage,
+  fetchPypi,
+  scandir,
+  six,
+  setuptools,
+  typing
+}:
+
+buildPythonPackage rec {
+  pname = "pathlib2";
+  version = "2.3.7.post1";
+  pyproject = true;
+
+  src = fetchPypi {
+    inherit pname version;
+    hash = "sha256-n+DtrYmLg8DD4ZnIQrJ+0hZkXS4Xd1ey3Wc4TUETxkE=";
+  };
+
+  build-system = [ setuptools ];
+
+  propagatedBuildInputs = [
+    scandir
+    six
+    typing
+  ];
+
+  meta = {
+    description = "This module offers classes representing filesystem paths with semantics appropriate for different operating systems";
+    homepage = "https://pypi.org/project/pathlib2/";
+    license = with lib.licenses; [ mit ];
+    maintainers = [ ];
+  };
+}
diff --git a/pkgs/development/python2-modules/pytest/default.nix b/pkgs/development/python2-modules/pytest/default.nix
index 3adb0a7d4aad..51a27afb4961 100644
--- a/pkgs/development/python2-modules/pytest/default.nix
+++ b/pkgs/development/python2-modules/pytest/default.nix
@@ -3,6 +3,7 @@
   buildPythonPackage,
   fetchPypi,
   attrs,
+  enum34,
   hypothesis,
   py,
   setuptools-scm,
@@ -41,6 +42,7 @@ buildPythonPackage rec {
   buildInputs = [ setuptools-scm ];
   propagatedBuildInputs = [
     attrs
+    enum34
     py
     setuptools
     six
diff --git a/pkgs/development/python2-modules/scandir/add-aarch64-darwin-dirent.patch b/pkgs/development/python2-modules/scandir/add-aarch64-darwin-dirent.patch
new file mode 100644
index 000000000000..1b35a0b950ce
--- /dev/null
+++ b/pkgs/development/python2-modules/scandir/add-aarch64-darwin-dirent.patch
@@ -0,0 +1,28 @@
+diff --git a/scandir.py b/scandir.py
+index 3f602fb..40af3e5 100644
+--- a/scandir.py
++++ b/scandir.py
+@@ -23,6 +23,7 @@ from os import listdir, lstat, stat, strerror
+ from os.path import join, islink
+ from stat import S_IFDIR, S_IFLNK, S_IFREG
+ import collections
++import platform
+ import sys
+ 
+ try:
+@@ -432,6 +433,15 @@ elif sys.platform.startswith(('linux', 'darwin', 'sunos5')) or 'bsd' in sys.plat
+                     ('__d_padding', ctypes.c_uint8 * 4),
+                     ('d_name', ctypes.c_char * 256),
+                 )
++            elif 'darwin' in sys.platform and 'arm64' in platform.machine():
++                _fields_ = (
++                    ('d_ino', ctypes.c_uint64),
++                    ('d_off', ctypes.c_uint64),
++                    ('d_reclen', ctypes.c_uint16),
++                    ('d_namlen', ctypes.c_uint16),
++                    ('d_type', ctypes.c_uint8),
++                    ('d_name', ctypes.c_char * 1024),
++                )
+             else:
+                 _fields_ = (
+                     ('d_ino', ctypes.c_uint32),  # must be uint32, not ulong
diff --git a/pkgs/development/python2-modules/scandir/default.nix b/pkgs/development/python2-modules/scandir/default.nix
new file mode 100644
index 000000000000..1558114f2309
--- /dev/null
+++ b/pkgs/development/python2-modules/scandir/default.nix
@@ -0,0 +1,30 @@
+{
+  lib,
+  python,
+  buildPythonPackage,
+  fetchPypi,
+}:
+
+buildPythonPackage rec {
+  pname = "scandir";
+  version = "1.10.0";
+  format = "setuptools";
+
+  src = fetchPypi {
+    inherit pname version;
+    sha256 = "1bkqwmf056pkchf05ywbnf659wqlp6lljcdb0y88wr9f0vv32ijd";
+  };
+
+  patches = [
+    ./add-aarch64-darwin-dirent.patch
+  ];
+
+  checkPhase = "${python.interpreter} test/run_tests.py";
+
+  meta = {
+    description = "Better directory iterator and faster os.walk()";
+    homepage = "https://github.com/benhoyt/scandir";
+    license = lib.licenses.gpl3;
+    maintainers = [ ];
+  };
+}
diff --git a/pkgs/development/python2-modules/setuptools-scm/default.nix b/pkgs/development/python2-modules/setuptools-scm/default.nix
new file mode 100644
index 000000000000..46056a8b6ff5
--- /dev/null
+++ b/pkgs/development/python2-modules/setuptools-scm/default.nix
@@ -0,0 +1,30 @@
+{
+  lib,
+  buildPythonPackage,
+  fetchPypi,
+  toml,
+}:
+
+buildPythonPackage rec {
+  pname = "setuptools_scm";
+  version = "5.0.2";
+  format = "setuptools";
+
+  src = fetchPypi {
+    inherit pname version;
+    sha256 = "sha256-g6DO3TRJ45RjB4EaTHudicS1/UZKL7XuzNCluxWK5cg=";
+  };
+
+  propagatedBuildInputs = [ toml ];
+
+  # Requires pytest, circular dependency
+  doCheck = false;
+  pythonImportsCheck = [ "setuptools_scm" ];
+
+  meta = {
+    homepage = "https://github.com/pypa/setuptools_scm/";
+    description = "Handles managing your python package versions in scm metadata";
+    license = lib.licenses.mit;
+    maintainers = [ ];
+  };
+}
diff --git a/pkgs/development/python2-modules/typing/default.nix b/pkgs/development/python2-modules/typing/default.nix
new file mode 100644
index 000000000000..bde13ff299da
--- /dev/null
+++ b/pkgs/development/python2-modules/typing/default.nix
@@ -0,0 +1,35 @@
+{
+  lib,
+  buildPythonPackage,
+  fetchPypi,
+  isPy3k,
+  unittestCheckHook,
+}:
+
+let
+  testDir = if isPy3k then "src" else "python2";
+
+in
+buildPythonPackage rec {
+  pname = "typing";
+  version = "3.10.0.0";
+  format = "setuptools";
+
+  src = fetchPypi {
+    inherit pname version;
+    sha256 = "13b4ad211f54ddbf93e5901a9967b1e07720c1d1b78d596ac6a439641aa1b130";
+  };
+
+  nativeCheckInputs = [ unittestCheckHook ];
+
+  unittestFlagsArray = [
+    "-s"
+    testDir
+  ];
+
+  meta = {
+    description = "Backport of typing module to Python versions older than 3.5";
+    homepage = "https://docs.python.org/3/library/typing.html";
+    license = lib.licenses.psfl;
+  };
+}
diff --git a/pkgs/development/python2-modules/wcwidth/default.nix b/pkgs/development/python2-modules/wcwidth/default.nix
index f16622f7a7b0..70275eb0b785 100644
--- a/pkgs/development/python2-modules/wcwidth/default.nix
+++ b/pkgs/development/python2-modules/wcwidth/default.nix
@@ -1,27 +1,46 @@
 {
-  backports-functools-lru-cache,
-  wcwidth,
   lib,
+  fetchPypi,
+  buildPythonPackage,
+  pytestCheckHook,
+  setuptools,
+  backports-functools-lru-cache,
 }:
 
-wcwidth.overridePythonAttrs (oldAttrs: {
-  propagatedBuildInputs = oldAttrs.propagatedBuildInputs or [ ] ++ [
+buildPythonPackage rec {
+  pname = "wcwidth";
+  version = "0.2.12";
+  pyproject = true;
+
+  src = fetchPypi {
+    inherit pname version;
+    hash = "sha256-8BwQTv31eXG8t1bwVN1Y3exSBN0V+jHWUD6leUfZfAI=";
+  };
+
+  nativeBuildInputs = [
+    setuptools
+  ];
+
+  propagatedBuildInputs = [
     backports-functools-lru-cache
   ];
 
-  /**
-    As of version 0.2.13 upstream still supports python2. In the future, this
-    package should be dropped or pinned to the last working version after the
-    final release for python2. See:
-      https://github.com/jquast/wcwidth/pull/117#issuecomment-1946609638
-  */
-  disabled = false;
+  nativeCheckInputs = [
+    pytestCheckHook
+  ];
+
+  # To prevent infinite recursion with pytest
+  doCheck = false;
 
-  meta = oldAttrs.meta // {
-    /**
-      maintainers overridden here for python2; this makes sure that python3
-       maintainers are not blamed for the breakage here.
-    */
-    maintainers = with lib.maintainers; [ bryango ];
+  meta = with lib; {
+    description = "Measures number of Terminal column cells of wide-character codes";
+    longDescription = ''
+      This API is mainly for Terminal Emulator implementors -- any Python
+      program that attempts to determine the printable width of a string on
+      a Terminal. It is implemented in python (no C library calls) and has
+      no 3rd-party dependencies.
+    '';
+    homepage = "https://github.com/jquast/wcwidth";
+    license = licenses.mit;
   };
-})
+}
diff --git a/pkgs/top-level/python2-packages.nix b/pkgs/top-level/python2-packages.nix
index ebfdbb802acb..168ff9a450e2 100644
--- a/pkgs/top-level/python2-packages.nix
+++ b/pkgs/top-level/python2-packages.nix
@@ -23,6 +23,8 @@ with super;
 
   coverage = callPackage ../development/python2-modules/coverage { };
 
+  enum34 = callPackage ../development/python2-modules/enum34 { };
+
   filelock = callPackage ../development/python2-modules/filelock { };
 
   hypothesis = callPackage ../development/python2-modules/hypothesis { };
@@ -43,6 +45,8 @@ with super;
 
   packaging = callPackage ../development/python2-modules/packaging { };
 
+  pathlib2 = callPackage ../development/python2-modules/pathlib2 { };
+
   pip = callPackage ../development/python2-modules/pip { };
 
   pluggy = callPackage ../development/python2-modules/pluggy { };
@@ -74,15 +78,19 @@ with super;
 
   rpm = disabled super.rpm;
 
+  scandir = callPackage ../development/python2-modules/scandir { };
+
   setuptools = callPackage ../development/python2-modules/setuptools { };
 
+  setuptools-scm = callPackage ../development/python2-modules/setuptools-scm { };
+
+  typing = callPackage ../development/python2-modules/typing { };
+
   six = super.six.overridePythonAttrs (_: {
     doCheck = false; # circular dependency with pytest
   });
 
-  wcwidth = callPackage ../development/python2-modules/wcwidth {
-    inherit wcwidth;
-  };
+  wcwidth = callPackage ../development/python2-modules/wcwidth { };
 
   wheel = callPackage ../development/python2-modules/wheel { };
 

Things done

  • Built on platform:
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • Tested, as applicable:
  • Ran nixpkgs-review on this PR. See nixpkgs-review usage.
  • Tested basic functionality of all binary files, usually in ./result/bin/.
  • Nixpkgs Release Notes
    • Package update: when the change is major or breaking.
  • NixOS Release Notes
    • Module addition: when adding a new NixOS module.
    • Module update: when the change is significant.
  • Fits CONTRIBUTING.md, pkgs/README.md, maintainers/README.md and other READMEs.

Add a 👍 reaction to pull requests you find important.

@nixpkgs-ci nixpkgs-ci bot added 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin. 10.rebuild-linux: 0 This PR does not cause any packages to rebuild on Linux. 9.needs: reviewer This PR currently has no reviewers requested and needs attention. labels Jan 14, 2026
@Sigmanificient
Copy link
Copy Markdown
Member Author

Sigmanificient commented Jan 14, 2026

Copy link
Copy Markdown
Contributor

@gepbird gepbird left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, looks good!

Given that it has been broken for 10 months without anyone raising an issue and was superseded by gimp3, this sounds reasonable. (In the early release IIRC there were a few issues that kept people on gimp2, but I assume this is mostly resolved.)
In the enum34 PR there was one user who relied on this, but the advice was to maintain it outside of nixpkgs (and you provided a diff to get this feature working).

@nixpkgs-ci nixpkgs-ci bot added 12.approvals: 1 This PR was reviewed and approved by one person. and removed 9.needs: reviewer This PR currently has no reviewers requested and needs attention. labels Jan 14, 2026
@doronbehar doronbehar added this pull request to the merge queue Jan 14, 2026
Merged via the queue into NixOS:master with commit a87fefe Jan 14, 2026
64 of 81 checks passed
@Sigmanificient Sigmanificient deleted the python2-removal/gimp branch January 14, 2026 18:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin. 10.rebuild-linux: 0 This PR does not cause any packages to rebuild on Linux. 12.approvals: 1 This PR was reviewed and approved by one person.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants