From 6a08ac882bc28a4243b3715c6fefba5d3894ca50 Mon Sep 17 00:00:00 2001 From: adisbladis Date: Thu, 12 May 2022 22:23:05 +1200 Subject: [PATCH] overrides.shapely: Remove patch Inheriting patches from nixpkgs is brittle and just a shortcut. Instead patch the AST of the file that looks up the library paths which should be much less brittle over time. --- overrides/default.nix | 9 ++++++- overrides/shapely-rewrite.py | 46 ++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 overrides/shapely-rewrite.py diff --git a/overrides/default.nix b/overrides/default.nix index 2c9809b..a3eb1a7 100644 --- a/overrides/default.nix +++ b/overrides/default.nix @@ -1942,7 +1942,14 @@ lib.composeManyExtensions [ shapely = super.shapely.overridePythonAttrs ( old: { buildInputs = (old.buildInputs or [ ]) ++ [ pkgs.geos ]; - inherit (pkgs.python3.pkgs.shapely) patches GEOS_LIBRARY_PATH; + inherit (pkgs.python3.pkgs.shapely) GEOS_LIBRARY_PATH; + + GEOS_LIBC = lib.optionalString (!stdenv.isDarwin) "${stdenv.cc.libc}/lib/libc${stdenv.hostPlatform.extensions.sharedLibrary}.6"; + + # Fix library paths + postPatch = old.postPatch or "" + '' + ${self.python.pythonForBuild.interpreter} ${./shapely-rewrite.py} shapely/geos.py + ''; } ); diff --git a/overrides/shapely-rewrite.py b/overrides/shapely-rewrite.py new file mode 100644 index 0000000..d3b3654 --- /dev/null +++ b/overrides/shapely-rewrite.py @@ -0,0 +1,46 @@ +""" +Rewrite libc/library path references to Nix store paths +Nixpkgs uses a normal patch for this but we need to be less +sensitive to changes between versions. +""" +from textwrap import dedent +import sys +import ast +import os + + +with open(sys.argv[1]) as f: + mod = ast.parse(f.read(), "geos.py") + + +class LibTransformer(ast.NodeTransformer): + _lgeos_replaced = False + + def visit_If(self, node): + if ast.unparse(node).startswith("if sys.platform.startswith('linux')"): + return ast.parse( + dedent( + """ + free = CDLL(%s).free + free.argtypes = [c_void_p] + free.restype = None + """ + ) + % (lambda x: "'" + x + "'" if x else None)(os.environ.get("GEOS_LIBC")) + ) + return node + + def visit_Assign(self, node): + _target = node.targets[0] + if ( + not self._lgeos_replaced + and isinstance(_target, ast.Name) + and _target.id == "_lgeos" + ): + self._lgeos_replaced = True + return ast.parse("_lgeos = CDLL('%s')" % os.environ["GEOS_LIBRARY_PATH"]) + return node + + +with open(sys.argv[1], "w") as f: + f.write(ast.unparse(LibTransformer().visit(mod)))