From bb1b8eecb918d1adf3f0c555fc8f8284e536dfdc Mon Sep 17 00:00:00 2001 From: Prunebutt Date: Tue, 14 Oct 2025 00:01:19 +0200 Subject: [PATCH 1/3] switch to uv and stuff --- flake.lock | 61 ++++++---- flake.nix | 113 +++++++++++++----- pyproject.toml | 8 +- src/protestswap/__init__.py | 0 src/protestswap/cli.py | 7 ++ .../protestswap.py} | 0 6 files changed, 133 insertions(+), 56 deletions(-) create mode 100644 src/protestswap/__init__.py create mode 100644 src/protestswap/cli.py rename src/{faceswap.py => protestswap/protestswap.py} (100%) diff --git a/flake.lock b/flake.lock index e4f40ad..4672eeb 100644 --- a/flake.lock +++ b/flake.lock @@ -1,43 +1,58 @@ { "nodes": { - "nixpkgs": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, "locked": { - "lastModified": 1760164275, - "narHash": "sha256-gKl2Gtro/LNf8P+4L3S2RsZ0G390ccd5MyXYrTdMCFE=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "362791944032cb532aabbeed7887a441496d5e6e", + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "type": "github" }, "original": { - "id": "nixpkgs", - "type": "indirect" + "owner": "numtide", + "repo": "flake-utils", + "type": "github" } }, - "pyproject-nix": { - "inputs": { - "nixpkgs": [ - "nixpkgs" - ] - }, + "nixpkgs": { "locked": { - "lastModified": 1759739877, - "narHash": "sha256-XfcxM4nzSuuRmFGiy/MhGwYf9EennQ2+0jjR2aJqtKE=", - "owner": "pyproject-nix", - "repo": "pyproject.nix", - "rev": "966e0961f9670f847439ba90dc25ffaa112d8803", + "lastModified": 1760284886, + "narHash": "sha256-TK9Kr0BYBQ/1P5kAsnNQhmWWKgmZXwUQr4ZMjCzWf2c=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "cf3f5c4def3c7b5f1fc012b3d839575dbe552d43", "type": "github" }, "original": { - "owner": "pyproject-nix", - "repo": "pyproject.nix", + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", "type": "github" } }, "root": { "inputs": { - "nixpkgs": "nixpkgs", - "pyproject-nix": "pyproject-nix" + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" } } }, diff --git a/flake.nix b/flake.nix index 832cf8c..446c016 100644 --- a/flake.nix +++ b/flake.nix @@ -1,41 +1,90 @@ { description = "Flake using pyproject.toml metadata"; - inputs.pyproject-nix.url = "github:pyproject-nix/pyproject.nix"; - inputs.pyproject-nix.inputs.nixpkgs.follows = "nixpkgs"; + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + # pyproject-nix.url = "github:pyproject-nix/pyproject.nix"; + # pyproject-nix.inputs.nixpkgs.follows = "nixpkgs"; + flake-utils.url = "github:numtide/flake-utils"; + }; - outputs = - { nixpkgs, pyproject-nix, ... }: - let - inherit (nixpkgs) lib; - forAllSystems = lib.genAttrs lib.systems.flakeExposed; + outputs = { + self, + nixpkgs, + flake-utils, + ... + }: + flake-utils.lib.eachDefaultSystem (system: let + pkgs = nixpkgs.legacyPackages.${system}; - project = pyproject-nix.lib.project.loadPyproject { - projectRoot = ./.; + pyproject = builtins.fromTOML (builtins.readFile ./pyproject.toml); + project = pyproject.project; + package = pkgs.python3Packages.buildPythonPackage { + pname = project.name; + inherit (project) version; + format = "pyproject"; + + src = ./.; + + build-system = with pkgs.python3Packages; [ + uv-build + ]; + + # # test dependencies + nativeCheckInputs = with pkgs; [ + # python3Packages.mypy + # python3Packages.pytest + taplo + ]; + + # checkPhase = ''''; + + propagatedBuildInputs = with pkgs; [ + python3Packages.click + ] ++ builtins.map (dep: pkgs.python3Packages.${dep}) project.dependencies; }; - pythonAttr = "python3"; - in - { - devShells = forAllSystems (system: { - default = - let - pkgs = nixpkgs.legacyPackages.${system}; - python = pkgs.${pythonAttr}; - pythonEnv = python.withPackages (project.renderers.withPackages { inherit python; }); - in - pkgs.mkShell { packages = [ pythonEnv ]; }; - }); + editablePackage = pkgs.python3.pkgs.mkPythonEditablePackage { + pname = project.name; + inherit (project) scripts version; + root = "$PWD"; + }; + in { + devShells = { + default = pkgs.mkShell { + inputsFrom = [ + package + ]; - packages = forAllSystems ( - system: - let - pkgs = nixpkgs.legacyPackages.${system}; - python = pkgs.${pythonAttr}; - in - { - default = python.pkgs.buildPythonPackage (project.renderers.buildPythonPackage { inherit python; }); - } - ); - }; + buildInputs = [ + # our package + editablePackage + + ################# + # VARIOUS TOOLS # + ################# + + pkgs.python3Packages.build + pkgs.python3Packages.ipython + + #################### + # EDITOR/LSP TOOLS # + #################### + + # LSP server: + pkgs.python3Packages.python-lsp-server + + # LSP server plugins of interest: + pkgs.python3Packages.pylsp-mypy + pkgs.python3Packages.pylsp-rope + pkgs.python3Packages.python-lsp-ruff + ]; + }; + }; + + packages = { + "${project.name}" = package; + default = self.packages.${system}.${project.name}; + }; + }); } diff --git a/pyproject.toml b/pyproject.toml index 6179bdc..c67b0fc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,9 +1,15 @@ [project] -name = "hello-python" +name = "protestswap" version = "0.1.0" +license-files = ["LICEN[CS]E*"] description = "A minimal pyproject.toml" authors = [ ] requires-python = ">=3.13" dependencies = [ "insightface", "opencv-python", "matplotlib" ] +[project.scripts] +protestswap-cli = "protestswap.cli:main" +[build-system] +requires = ["uv_build >= 0.8.17, <0.9.0"] +build-backend = "uv_build" diff --git a/src/protestswap/__init__.py b/src/protestswap/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/protestswap/cli.py b/src/protestswap/cli.py new file mode 100644 index 0000000..bcd35ad --- /dev/null +++ b/src/protestswap/cli.py @@ -0,0 +1,7 @@ +import protestswap + +def main(): + print("hello protest") + +if __name__ == "__main__": + main() diff --git a/src/faceswap.py b/src/protestswap/protestswap.py similarity index 100% rename from src/faceswap.py rename to src/protestswap/protestswap.py From e047bcd1367c73f356e82b4573122398f1a90412 Mon Sep 17 00:00:00 2001 From: Prunebutt Date: Wed, 15 Oct 2025 21:41:56 +0200 Subject: [PATCH 2/3] working with pyproject-nix flake --- flake.nix | 203 ++++++++++++++++++++++++++++++++----------------- pyproject.toml | 2 +- 2 files changed, 134 insertions(+), 71 deletions(-) diff --git a/flake.nix b/flake.nix index 446c016..4e6764c 100644 --- a/flake.nix +++ b/flake.nix @@ -3,8 +3,10 @@ inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; - # pyproject-nix.url = "github:pyproject-nix/pyproject.nix"; - # pyproject-nix.inputs.nixpkgs.follows = "nixpkgs"; + pyproject-nix = { + url = "github:pyproject-nix/pyproject.nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; flake-utils.url = "github:numtide/flake-utils"; }; @@ -13,78 +15,139 @@ nixpkgs, flake-utils, ... - }: - flake-utils.lib.eachDefaultSystem (system: let - pkgs = nixpkgs.legacyPackages.${system}; + }@inputs: let + system = "x86_64-linux"; + pkgs = nixpkgs.legacyPackages.${system}; + project = inputs.pyproject-nix.lib.project.loadPyproject { + projectRoot = ./.; + }; + projectName = project.pyproject.project.name; + python = pkgs.python3; - pyproject = builtins.fromTOML (builtins.readFile ./pyproject.toml); - project = pyproject.project; - package = pkgs.python3Packages.buildPythonPackage { - pname = project.name; - inherit (project) version; - format = "pyproject"; - - src = ./.; - - build-system = with pkgs.python3Packages; [ - uv-build - ]; - - # # test dependencies - nativeCheckInputs = with pkgs; [ - # python3Packages.mypy - # python3Packages.pytest - taplo - ]; - - # checkPhase = ''''; - - propagatedBuildInputs = with pkgs; [ - python3Packages.click - ] ++ builtins.map (dep: pkgs.python3Packages.${dep}) project.dependencies; + inswapperModel = pkgs.stdenv.mkDerivation { + name = "inswapper"; + src = pkgs.fetchurl { + url = "https://huggingface.co/thebiglaskowski/inswapper_128.onnx/resolve/main/inswapper_128.onnx"; + hash = "sha256-5KPwjHU8ty0E4Qqg99vj3uu/OVZ9Tq1tzgjpiqSeFq8="; }; - editablePackage = pkgs.python3.pkgs.mkPythonEditablePackage { - pname = project.name; - inherit (project) scripts version; - root = "$PWD"; + unpackPhase = ''true''; + phases = [ + # "installPhase" + ]; + + installPhase = let dest = "$out/var/lib/${projectName}"; in /*shell*/'' + ls -l "$src" + mkdir -p "${dest}" + cp $src ${dest}/inswapper_128.onnx + ''; + }; + + in { + devShells.${system}.default = let + arg = project.renderers.withPackages { inherit python;}; + pythonEnv = python.withPackages arg; + in pkgs.mkShell { + packages = [ pythonEnv inswapperModel]; + shellHook = '' + export FOO=${inswapperModel}/var/lib/${projectName}/inswapper_128.onnx + echo "Binary at '$FOO'" + ''; + }; + + packages.${system} = let + attrs = project.renderers.buildPythonPackage { + inherit python; }; + protestswap = (python.pkgs.buildPythonPackage ( attrs // { + buildInputs = [ inswapperModel ]; + } )); in { - devShells = { - default = pkgs.mkShell { - inputsFrom = [ - package - ]; - - buildInputs = [ - # our package - editablePackage - - ################# - # VARIOUS TOOLS # - ################# - - pkgs.python3Packages.build - pkgs.python3Packages.ipython - - #################### - # EDITOR/LSP TOOLS # - #################### - - # LSP server: - pkgs.python3Packages.python-lsp-server - - # LSP server plugins of interest: - pkgs.python3Packages.pylsp-mypy - pkgs.python3Packages.pylsp-rope - pkgs.python3Packages.python-lsp-ruff - ]; - }; + # inherit inswapperModel; + # "${projectName}" = protestswap; + default = pkgs.symlinkJoin { + name = "${projectName}"; + paths = [inswapperModel protestswap]; }; - - packages = { - "${project.name}" = package; - default = self.packages.${system}.${project.name}; - }; - }); + }; + }; } + + + # flake-utils.lib.eachDefaultSystem (system: let + # pyproject = builtins.fromTOML (builtins.readFile ./pyproject.toml); + # project = pyproject.project; + # + # package = pkgs.python3Packages.buildPythonPackage { + # pname = project.name; + # inherit (project) version; + # format = "pyproject"; + # + # src = ./.; + # + # build-system = with pkgs.python3Packages; [ + # uv-build + # ]; + # + # # # test dependencies + # nativeCheckInputs = with pkgs; [ + # # python3Packages.mypy + # # python3Packages.pytest + # taplo + # ]; + # + # # checkPhase = ''''; + # + # propagatedBuildInputs = with pkgs; [ + # python3Packages.click + # python3Packages.insightface + # + # ] ++ builtins.map (dep: pkgs.python3Packages.${dep}) project.dependencies; + # }; + # + # editablePackage = pkgs.python3.pkgs.mkPythonEditablePackage { + # pname = project.name; + # inherit (project) scripts version; + # root = "$PWD"; + # }; + # in { + # devShells = { + # default = pkgs.mkShell { + # inputsFrom = [ + # package + # ]; + # + # buildInputs = [ + # # our package + # editablePackage + # + # ################# + # # VARIOUS TOOLS # + # ################# + # + # pkgs.python3Packages.build + # pkgs.python3Packages.ipython + # pkgs.python3Packages.insightface + # inswapperModel + # + # #################### + # # EDITOR/LSP TOOLS # + # #################### + # + # # LSP server: + # pkgs.python3Packages.python-lsp-server + # + # # LSP server plugins of interest: + # pkgs.python3Packages.pylsp-mypy + # pkgs.python3Packages.pylsp-rope + # pkgs.python3Packages.python-lsp-ruff + # ]; + # }; + # }; + # + # packages = { + # "inswapper-model" = inswapperModel; + # "${project.name}" = package; + # default = self.packages.${system}.${project.name}; + # }; + # }); diff --git a/pyproject.toml b/pyproject.toml index c67b0fc..78d99e8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "protestswap" -version = "0.1.0" +version = "0.0.1" license-files = ["LICEN[CS]E*"] description = "A minimal pyproject.toml" authors = [ ] From 30ee8107fd07da54f4af0a12a2f788b7990d16b7 Mon Sep 17 00:00:00 2001 From: Prunebutt Date: Sun, 19 Oct 2025 22:31:59 +0200 Subject: [PATCH 3/3] finally works...? --- .gitignore | 11 ++++ flake.nix | 92 ++++++++++++++++++++++------------ pyproject.toml | 9 +++- src/protestswap/cli.py | 26 +++++++++- src/protestswap/protestswap.py | 16 ++++-- 5 files changed, 115 insertions(+), 39 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..db1c93c --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +# Devenv +.devenv* +devenv.local.nix +devenv.local.yaml + +# direnv +.direnv + +# pre-commit +.pre-commit-config.yaml +src/protestswap/__pycache__ diff --git a/flake.nix b/flake.nix index 4e6764c..2030bde 100644 --- a/flake.nix +++ b/flake.nix @@ -24,52 +24,82 @@ projectName = project.pyproject.project.name; python = pkgs.python3; - inswapperModel = pkgs.stdenv.mkDerivation { - name = "inswapper"; + inswapperModel = pkgs.stdenv.mkDerivation { + name = "inswapper_128"; src = pkgs.fetchurl { url = "https://huggingface.co/thebiglaskowski/inswapper_128.onnx/resolve/main/inswapper_128.onnx"; hash = "sha256-5KPwjHU8ty0E4Qqg99vj3uu/OVZ9Tq1tzgjpiqSeFq8="; }; - unpackPhase = ''true''; - phases = [ - # "installPhase" - ]; + phases = [ "installPhase" ]; - installPhase = let dest = "$out/var/lib/${projectName}"; in /*shell*/'' - ls -l "$src" - mkdir -p "${dest}" - cp $src ${dest}/inswapper_128.onnx + installPhase = '' + mkdir -p "$out/var/lib/insightface/models/" + cp $src "$out/var/lib/insightface/models/inswapper_128.onnx" ''; }; + buffaloModel = pkgs.stdenv.mkDerivation { + name = "buffalo_l_Model"; + src = pkgs.fetchurl { + url = "https://github.com/deepinsight/insightface/releases/download/v0.7/buffalo_l.zip"; + hash = "sha256-gP/jfYpZQNWac4TCAaKjjUdB8vPFHu9G67KCGKewyi8="; + }; + unpackPhase = /*shell*/'' + ls -l $src + echo $src + + mkdir -p "$out/var/lib/insightface/buffalo_l/" + unar -D -o $out/var/lib/insightface/buffalo_l/ $src + ''; + + nativeBuildInputs = [ pkgs.unar ]; + }; + postInstall = /*shell*/'' + mkdir -p $out/var/lib/insightface/models/buffalo_l + cp ${inswapperModel} $out/var/lib/insightface/models/inswapper_128.onnx + ''; + # ${pkgs.unar}/bin/unar -D -o $out/var/lib/insightface/models/buffalo_l ${buffaloModel} + # ''; + packageAttrs = project.renderers.buildPythonPackage { + inherit python; + }; + packageAttrsLive = project.renderers.mkPythonEditablePackage { + inherit python; + }; + protestswap = python.pkgs.buildPythonPackage ( packageAttrs # // { inherit postInstall; } + ); in { devShells.${system}.default = let - arg = project.renderers.withPackages { inherit python;}; - pythonEnv = python.withPackages arg; + arg = project.renderers.mkPythonEditablePackage { inherit python; }; + pythonEnv = python.pkgs.mkPythonEditablePackage ( arg ); in pkgs.mkShell { - packages = [ pythonEnv inswapperModel]; - shellHook = '' - export FOO=${inswapperModel}/var/lib/${projectName}/inswapper_128.onnx - echo "Binary at '$FOO'" + packages = [ pkgs.python3 pkgs.uv + # buffaloModel + protestswap pkgs.gcc14 ]; + shellHook = /*shell*/ + '' + ls -l ${buffaloModel} + + INSIGHTFACE_ROOT_DIR=$(mktemp -d /tmp/insightface.XXXXXXXX) + export INSIGHTFACE_ROOT_DIR + + mkdir -p "$INSIGHTFACE_ROOT_DIR" + + ln -s ${inswapperModel}/var/lib/insightface/models "$INSIGHTFACE_ROOT_DIR/models" + ln -s ${buffaloModel}/var/lib/insightface/buffalo_l "$INSIGHTFACE_ROOT_DIR/buffalo_l" + + # export PROTESTSWAP_ROOT="/tmp/protestswap_models" + # mkdir -p "$PROTESTSWAP_ROOT/buffalo_l" + # + # cp ${inswapperModel} "$PROTESTSWAP_ROOT/inswapper_128.onnx" + unset PYTHONPATH + uv sync + . .venv/bin/activate ''; }; - packages.${system} = let - attrs = project.renderers.buildPythonPackage { - inherit python; - }; - protestswap = (python.pkgs.buildPythonPackage ( attrs // { - buildInputs = [ inswapperModel ]; - } )); - in { - # inherit inswapperModel; - # "${projectName}" = protestswap; - default = pkgs.symlinkJoin { - name = "${projectName}"; - paths = [inswapperModel protestswap]; - }; - }; + packages.${system}.default = protestswap; }; } diff --git a/pyproject.toml b/pyproject.toml index 78d99e8..27da1e8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,11 @@ license-files = ["LICEN[CS]E*"] description = "A minimal pyproject.toml" authors = [ ] requires-python = ">=3.13" -dependencies = [ "insightface", "opencv-python", "matplotlib" ] +dependencies = [ +"insightface", +"onnxruntime", +"opencv-python", "matplotlib" +] [project.scripts] protestswap-cli = "protestswap.cli:main" @@ -13,3 +17,6 @@ protestswap-cli = "protestswap.cli:main" [build-system] requires = ["uv_build >= 0.8.17, <0.9.0"] build-backend = "uv_build" + +[tool.setuptools.packages] +find = {namespaces = false} # Disable implicit namespaces diff --git a/src/protestswap/cli.py b/src/protestswap/cli.py index bcd35ad..67c4726 100644 --- a/src/protestswap/cli.py +++ b/src/protestswap/cli.py @@ -1,7 +1,29 @@ -import protestswap +import os +import logging + +from protestswap.protestswap import ProtestFaceSwapper + +logger = logging.getLogger("protestswap") + +DEFAULT_INSIGHTFACE_DIR = "/var/lib/insightface" +INSIGHTFACE_VAR = "INSIGHTFACE_ROOT_DIR" + def main(): - print("hello protest") + insightface_dir = None + if os.path.exists(DEFAULT_INSIGHTFACE_DIR): + insightface_dir = DEFAULT_INSIGHTFACE_DIR + elif os.environ.get(INSIGHTFACE_VAR): + insightface_dir = os.environ.get(INSIGHTFACE_VAR) + else: + logger.warning( + f"No directory at '{DEFAULT_INSIGHTFACE_DIR}' and '{INSIGHTFACE_VAR}' not set yet." + ) + insightface_dir = f"{os.environ.get('HOME')}/.cache/insightface" + + # swapper = ProtestFaceSwapper(insightface_dir) + # swapper.prepare_model() + if __name__ == "__main__": main() diff --git a/src/protestswap/protestswap.py b/src/protestswap/protestswap.py index d04736c..1b7f584 100644 --- a/src/protestswap/protestswap.py +++ b/src/protestswap/protestswap.py @@ -1,5 +1,8 @@ #!/usr/bin/env python3 +import logging +import os + import cv2 import random # TODO: seed! @@ -9,11 +12,14 @@ from insightface.app import FaceAnalysis from insightface.model_zoo.inswapper import INSwapper from insightface.app.common import Face +logger = logging.getLogger("protestswap") + SWAPPING_MODEL = 'inswapper_128.onnx' -class Faceswapper: - def __init__(self): - self._app : FaceAnalysis = FaceAnalysis(name='buffalo_l') + +class ProtestFaceSwapper: + def __init__(self, root_dir): + self._app : FaceAnalysis = FaceAnalysis(name='buffalo_l', root=insightface_dir) self._model : INSwapper self._source : cv2.typing.MatLike|None = None self._source_faces : list[Face] = [] @@ -49,9 +55,9 @@ class Faceswapper: def main(): - swapper = Faceswapper() - swapper.prepare_model() + swapper = ProtestFaceSwapper(insightface_dir) + swapper.prepare_model() if __name__ == '__main__':