### Initialize hello-world template from uv2nix Source: https://pyproject-nix.github.io/uv2nix/usage/getting-started.html Initializes a new Nix flake using the hello-world template from uv2nix. This template contains the same code as the getting started guide but without elaboration. ```nix nix flake init --template github:pyproject-nix/uv2nix#hello-world ``` -------------------------------- ### Build virtualenv with explicit dependencies Source: https://pyproject-nix.github.io/uv2nix/usage/getting-started.html Builds a virtual environment with explicitly specified dependencies. This example installs the hello-world package with no extras enabled. ```nix pythonSet.mkVirtualEnv "hello-world-env" { # Install hello-world with no enabled extras hello-world = [ ]; } ``` -------------------------------- ### Install wheel into Nix store output using pyprojectDistHook Source: https://pyproject-nix.github.io/uv2nix/patterns/dist.html Overrides the package to use the pyprojectDistHook, which installs the produced wheel into the build output directory. This method skips the regular pyproject.nix install steps, so the output is not suitable for use with mkVirtualEnv. ```nix pythonSet.hello-world.override { pyprojectHook = pythonSet.pyprojectDistHook; } ``` -------------------------------- ### Configure UV_FIND_LINKS with symlinkJoin Source: https://pyproject-nix.github.io/uv2nix/patterns/nixpkgs-wheels.html Use UV_FIND_LINKS and a shellHook to install a nixpkgs-built wheel, enabling both impure and pure uv2nix workflows. ```nix __ let python = pkgs.python3; uv-links = pkgs.symlinkJoin { name = "uv-links"; paths = [ # Note: Using the dist output which contains a wheel python.pkgs.seccomp.dist ]; }; in mkShell { packages = [ pkgs.uv python ]; env.UV_FIND_LINKS = uv-links; } ``` -------------------------------- ### Import uv2nix without Flakes using fetchGit Source: https://pyproject-nix.github.io/uv2nix/install.html Import uv2nix and pyproject-nix without Flakes, fetching each repository via builtins.fetchGit and using the inherit keyword to pass the lib attribute. The example also imports build-system-pkgs as a dependency of uv2nix. ```nix let pkgs = import { }; inherit (pkgs) lib; pyproject-nix = import (builtins.fetchGit { url = "https://github.com/pyproject-nix/pyproject.nix.git"; }) { inherit lib; }; uv2nix = import (builtins.fetchGit { url = "https://github.com/pyproject-nix/uv2nix.git"; }) { inherit pyproject-nix lib; }; pyproject-build-systems = import (builtins.fetchGit { url = "https://github.com/pyproject-nix/build-system-pkgs.git"; }) { inherit pyproject-nix uv2nix lib; }; in ... ``` -------------------------------- ### Example inline metadata script with tqdm dependency Source: https://pyproject-nix.github.io/uv2nix/usage/inline-metadata.html A PEP-723 inline metadata script that declares a dependency on `tqdm` and uses it to display a progress bar. This is the type of script that the flake loads from the `./scripts` directory. ```python # /// script # requires-python = ">=3.12" # dependencies = [ # "tqdm", # ] # /// from tqdm import tqdm for i in tqdm(range(10000)): pass ``` -------------------------------- ### Build with netrc in sandbox Source: https://pyproject-nix.github.io/uv2nix/patterns/private-deps.html Builds the package while providing the netrc file inside the Nix sandbox via `extra-sandbox-paths`. For a persistent setup, add `extra-sandbox-paths` to `nix.conf`. ```bash nix build -L -v --option extra-sandbox-paths /etc/nix/netrc ``` -------------------------------- ### Netrc file for private index authentication Source: https://pyproject-nix.github.io/uv2nix/patterns/private-deps.html Example netrc file saved as `/etc/nix/netrc` that provides credentials for the private PyPI proxy. The `machine` line must match the index hostname, and the file is used by `pkgs.fetchurl` when the `NETRC` environment variable is set. ```text machine pypi-proxy.fly.dev login public password heron ``` -------------------------------- ### Enter development shell with python3 and uv Source: https://pyproject-nix.github.io/uv2nix/usage/getting-started.html Enters a development shell with Python 3 and uv as bootstrapping dependencies. Required before creating the project files. ```nix nix-shell -p python3 uv ``` -------------------------------- ### Construct dummy source with pkgs.runCommand Source: https://pyproject-nix.github.io/uv2nix/patterns/source-filtering.html Constructs a dummy source directory with pkgs.runCommand to further reduce rebuilds. It creates a minimal source containing only pyproject.toml and an empty __init__.py, which is sufficient for editable builds. ```nix app = prev.app.overrideAttrs(old: { src = pkgs.runCommand "app-src" {} '' mkdir $out cp ${./pyproject.toml} $out/pyproject.toml mkdir $out/app touch $out/app/__init__.py ''; }); ``` -------------------------------- ### Initialize uv2nix project with inline metadata Source: https://pyproject-nix.github.io/uv2nix/print.html Initialize a uv2nix project that uses locked inline metadata scripts. ```shell nix flake init --template github:pyproject-nix/uv2nix#inline-metadata ``` -------------------------------- ### lib.lock1.getLocalPath Source: https://pyproject-nix.github.io/uv2nix/lib/lock1.html Gets the relative path for a local package. Takes a package argument. ```APIDOC ## `lib.lock1.getLocalPath` ### Description Get relative path for a local package. ### Parameters - `package` - Function argument ``` -------------------------------- ### Override package attributes Source: https://pyproject-nix.github.io/uv2nix/patterns/cross/index.html Example of overriding package attributes like nativeBuildInputs and buildInputs for a specific package. ```nix final: prev: { foobar = prev.foobar.overrideAttrs (old: { nativeBuildInputs = old.nativeBuildInputs ++ [ final.pkgs.buildPackages.cmake ]; buildInputs = (old.buildInputs or [ ]) ++ [ final.pkgs.ncurses ]; }); } ``` -------------------------------- ### lib.lock1.resolveDependencies Source: https://pyproject-nix.github.io/uv2nix/lib/lock1.html Resolves dependencies from a uv.lock file. Takes a parsed lock file, a PEP-508 environment, and a list of dependency names to start resolution from. ```APIDOC ## `lib.lock1.resolveDependencies` ### Description Resolve dependencies from uv.lock. ### Parameters - `lock` - Lock file as parsed by parseLock - `environ` - PEP-508 environment as returned by pyproject-nix.lib.pep508.mkEnviron - `dependencies` - List of dependency names to start resolution from ``` -------------------------------- ### Create editable overlay and virtualenv with mkEditablePyprojectOverlay Source: https://pyproject-nix.github.io/uv2nix/usage/getting-started.html Creates an editable overlay and package set for local Python packages, then builds a virtual environment. Requires the REPO_ROOT environment variable to point to the editable root directory. The optional members list restricts editable mode to specific packages. ```nix editableOverlay = workspace.mkEditablePyprojectOverlay { # Use environment variable pointing to editable root directory root = "$REPO_ROOT"; # Optional: Only enable editable for these packages # members = [ "hello-world" ]; }; editablePythonSet = pythonSet.overrideScope editableOverlay; virtualenv = editablePythonSet.mkVirtualEnv "hello-world-dev-env" workspace.deps.all; ``` -------------------------------- ### Create boilerplate project with uv init and uv lock Source: https://pyproject-nix.github.io/uv2nix/usage/getting-started.html Creates a boilerplate pyproject.toml and uv.lock for a new application package. Run these commands after entering the development shell. ```bash uv init --app --package uv lock ``` -------------------------------- ### Override Linux kernel version with platform_release in mkPyprojectOverlay Source: https://pyproject-nix.github.io/uv2nix/platform-quirks.html Override the Linux kernel version used for marker evaluation by setting `platform_release` in the `environ` argument of `mkPyprojectOverlay`. The example sets it to "5.10.65". ```nix let overlay = workspace.mkPyprojectOverlay { sourcePreference = "wheel"; environ = { platform_release = "5.10.65"; }; } in ... ``` -------------------------------- ### lib.workspace.loadConfig Source: https://pyproject-nix.github.io/uv2nix/lib/workspace.html Loads supported configuration from a workspace. Supports various tool.uv settings. ```APIDOC ## lib.workspace.loadConfig ### Description Load supported configuration from workspace. ### Supported Settings - tool.uv.compile-bytecode - tool.uv.no-binary - tool.uv.no-build - tool.uv.no-binary-package - tool.uv.no-build-package - tool.uv.extra-build-dependencies - tool.uv.extra-build-variables - tool.uv.config-settings - tool.uv.config-settings-package ``` -------------------------------- ### Add a separate dist output to a Python package Source: https://pyproject-nix.github.io/uv2nix/patterns/dist.html Overrides the package's outputs to include 'dist' in addition to 'out', so the produced wheel is installed into the dist output directory, matching the contents of a 'uv build' dist/ directory. ```nix pythonSet.hello-world.overrideAttrs (final: prev: { outputs = [ "out" "dist" ]; }) ``` -------------------------------- ### flake.nix with uv2nix apps for scripts Source: https://pyproject-nix.github.io/uv2nix/print.html Defines a Nix flake that uses uv2nix to create a virtualenv from the workspace and exposes each Python script in ./examples as a Nix app. The overlay sets sourcePreference to "wheel" (or "sdist"), and the apps map strips .py suffixes so `nix run .#greet` runs greet.py. ```nix flake.nix ``` ```nix { description = "Using Nix Flake apps to run scripts with uv2nix"; inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; pyproject-nix = { url = "github:pyproject-nix/pyproject.nix"; inputs.nixpkgs.follows = "nixpkgs"; }; uv2nix = { url = "github:pyproject-nix/uv2nix"; inputs.pyproject-nix.follows = "pyproject-nix"; inputs.nixpkgs.follows = "nixpkgs"; }; pyproject-build-systems = { url = "github:pyproject-nix/build-system-pkgs"; inputs.pyproject-nix.follows = "pyproject-nix"; inputs.uv2nix.follows = "uv2nix"; inputs.nixpkgs.follows = "nixpkgs"; }; }; outputs = { nixpkgs, uv2nix, pyproject-nix, pyproject-build-systems, ... }: let inherit (nixpkgs) lib; inherit (lib) filterAttrs hasSuffix; workspace = uv2nix.lib.workspace.loadWorkspace { workspaceRoot = ./.; }; overlay = workspace.mkPyprojectOverlay { sourcePreference = "wheel"; # or sourcePreference = "sdist"; }; pkgs = nixpkgs.legacyPackages.x86_64-linux; python = pkgs.python312; pythonSet = (pkgs.callPackage pyproject-nix.build.packages { inherit python; }).overrideScope ( lib.composeManyExtensions [ pyproject-build-systems.overlays.default overlay ] ); venv = pythonSet.mkVirtualEnv "development-scripts-env" workspace.deps.default; in { apps.x86_64-linux = let # Example base directory basedir = ./examples; # Get a list of regular Python files in example directory files = filterAttrs (name: type: type == "regular" && hasSuffix ".py" name) ( builtins.readDir basedir ); in # Map over files to: # - Rewrite script shebangs as shebangs pointing to the virtualenv # - Strip .py suffixes from attribute names # Making a script "greet.py" runnable as "nix run .#greet" lib.mapAttrs' ( name: _: lib.nameValuePair (lib.removeSuffix ".py" name) ( let script = basedir + "/${name}"; # Patch script shebang program = pkgs.runCommand name { buildInputs = [ venv ]; } '' cp ${script} $out chmod +x $out patchShebangs $out ''; in { type = "app"; program = "${program}"; } ) ) files; }; } ``` -------------------------------- ### Instantiate pyproject.nix builders with pythonBase Source: https://pyproject-nix.github.io/uv2nix/usage/getting-started.html Instantiates pyproject.nix Python builders with a nixpkgs instance. This creates the necessary structure and build hooks but does not include any Python packages itself. ```nix pythonBase = pkgs.callPackage pyproject-nix.build.packages { inherit python; }; ``` -------------------------------- ### Load uv workspace with loadWorkspace Source: https://pyproject-nix.github.io/uv2nix/usage/getting-started.html Loads the uv workspace from the current directory. This recursively discovers and parses all member projects in the workspace. ```nix workspace = uv2nix.lib.workspace.loadWorkspace { workspaceRoot = ./.; }; ``` -------------------------------- ### Override build systems for cross-compilation Source: https://pyproject-nix.github.io/uv2nix/patterns/cross/index.html Demonstrates overriding build systems for both the build host and target host using pythonSet.overrideScope and lib.composeExtensions. ```nix let pyprojectOverrides = final: prev: { hatchling = prev.hatchling.overrideAttrs (old: { nativeBuildInputs = old.nativeBuildInputs ++ final.resolveBuildSystem { pathspec = [ ]; }; }); }; in pythonSet.overrideScope ( lib.composeExtensions (_final: prev: { pythonPkgsBuildHost = prev.pythonPkgsBuildHost.overrideScope pyprojectOverrides; }) pyprojectOverrides ) ``` -------------------------------- ### pyproject.toml for testing project Source: https://pyproject-nix.github.io/uv2nix/patterns/testing.html Defines project metadata, a console script 'hello' that calls 'testing:hello', and uses hatchling as the build backend. Includes dev and test dependency groups with ruff, pytest, and pytest-cov. ```toml [project] name = "testing" version = "0.1.0" description = "Add your description here" requires-python = ">=3.12" [project.scripts] hello = "testing:hello" [build-system] requires = ["hatchling"] build-backend = "hatchling.build" [dependency-groups] dev = [ "ruff>=0.7.2", {include-group = "test"} ] test = [ "pytest-cov>=6.0.0", "pytest>=8.3.3", ] ``` -------------------------------- ### Use nixpkgsPrebuilt hack Source: https://pyproject-nix.github.io/uv2nix/patterns/nixpkgs-wheels.html Skip making uv aware of the package by adding the nixpkgs package directly from a Nix evaluation. ```nix __ let pyprojectOverrides = final: prev: { seccomp = hacks.nixpkgsPrebuilt { from = python.pkgs.seccomp; }; }; pythonSet' = pythonSet.overrideScope pyprojectOverrides; in pythonSet.mkVirtualEnv "seccomp-env" { seccomp = [ ]; } ``` -------------------------------- ### Initialize impure template from pyproject.nix Source: https://pyproject-nix.github.io/uv2nix/usage/getting-started.html Initializes a new Nix flake using the impure template from pyproject.nix. Use this when you do not need uv2nix and prefer an impure development environment. ```nix nix flake init --template github:pyproject-nix/pyproject.nix#impure ``` -------------------------------- ### Override mkApplication to add shell completions Source: https://pyproject-nix.github.io/uv2nix/patterns/applications.html Use this override to add shell completions to the application derivation. It appends `pkgs.installShellFiles` to `nativeBuildInputs` and runs `installShellCompletion` in `postInstall` to generate completions for bash, fish, and zsh. The `cmd` variable must be defined elsewhere. ```nix (mkApplication { venv = pythonSet.mkVirtualEnv "application-env" workspace.deps.default; package = pythonSet.hello-world; }).overrideAttrs(old: { nativeBuildInputs = old.nativeBuildInputs ++ [ pkgs.installShellFiles ]; postInstall = '' installShellCompletion --cmd ${cmd} \ --bash <($out/bin/${cmd} --show-completion bash) \ --fish <($out/bin/${cmd} --show-completion fish) \ --zsh <($out/bin/${cmd} --show-completion zsh) ''; }) ``` -------------------------------- ### Configure uv project with private index Source: https://pyproject-nix.github.io/uv2nix/patterns/private-deps.html Configures a uv project to fetch the `iniconfig` dependency from a private PyPI index (`my-index`) using an explicit index URL. The `explicit = true` flag and the `[tool.uv.sources]` entry ensure the dependency is resolved from that index. ```toml [project] name = "with-private-deps" version = "0.1.0" requires-python = ">=3.12" dependencies = ["iniconfig"] [[tool.uv.index]] name = "my-index" url = "https://pypi-proxy.fly.dev/basic-auth/simple" explicit = true [tool.uv.sources] iniconfig = { index = "my-index" } [build-system] requires = ["setuptools>=42"] build-backend = "setuptools.build_meta" ``` -------------------------------- ### Build virtualenv with mkVirtualEnv using default deps Source: https://pyproject-nix.github.io/uv2nix/usage/getting-started.html Builds a virtual environment using the default dependency preset from the workspace. This is the most convenient way to aggregate packages into a virtualenv. ```nix pythonSet.mkVirtualEnv "hello-world-env" workspace.deps.default ``` -------------------------------- ### Select sources with lib.fileset for editable package Source: https://pyproject-nix.github.io/uv2nix/patterns/source-filtering.html Uses the fileset API to explicitly select sources for an editable package. This reduces rebuilds by only including the pyproject.toml and the package's __init__.py, which is enough for most build backends to discover importable packages. ```nix app = prev.app.overrideAttrs (old: { src = lib.fileset.toSource rec { root = ./.; fileset = lib.fileset.unions [ (root + "/pyproject.toml") (root + "/app/__init__.py") ]; }; }); ``` -------------------------------- ### Create overlay with mkPyprojectOverlay Source: https://pyproject-nix.github.io/uv2nix/usage/getting-started.html Creates an overlay from the workspace's uv.lock for use with pyproject.nix builders. The sourcePreference option controls whether to prefer binary wheels or sdists. ```nix overlay = workspace.mkPyprojectOverlay { sourcePreference = "wheel"; }; ``` -------------------------------- ### Use hacks.nixpkgsPrebuilt to add nixpkgs package Source: https://pyproject-nix.github.io/uv2nix/print.html Use the pyproject.nix hacks.nixpkgsPrebuilt helper to add a nixpkgs package without making uv aware of it. Overrides the python set scope and creates a virtual environment named seccomp-env containing seccomp. ```nix let pyprojectOverrides = final: prev: { seccomp = hacks.nixpkgsPrebuilt { from = python.pkgs.seccomp; }; }; pythonSet' = pythonSet.overrideScope pyprojectOverrides; in pythonSet.mkVirtualEnv "seccomp-env" { seccomp = [ ]; } ``` -------------------------------- ### Overlay uv with uv2nix package for older nixpkgs Source: https://pyproject-nix.github.io/uv2nix/old-nixpkgs.html Use this overlay to provide a newer uv version (>=0.5.7) for nixpkgs <=24.11, which is required by the pyproject.nix build hooks. The overlay replaces the uv package with the uv2nix-provided binary. ```nix import nixpkgs { overlays = [ (final: prev: { uv = inputs.uv2nix.packages.${system}.uv-bin; }) ]; } ``` -------------------------------- ### mkVirtualEnv Source: https://pyproject-nix.github.io/uv2nix/print.html Creates a virtual environment from a Python package set and a set of dependencies. Used to build a development environment for the workspace. ```APIDOC ## mkVirtualEnv ### Description Creates a virtual environment from a Python package set and a set of dependencies. Used to build a development environment for the workspace. ### Parameters - **pythonSet** (attribute set) - Required - The Python package set (with editable overlay applied). - **deps** (attribute set) - Required - The dependencies to include in the virtual environment. ### Example ```nix virtualenv = editablePythonSet.mkVirtualEnv "hello-world-dev-env" workspace.deps.all; ``` ``` -------------------------------- ### lib.workspace.loadWorkspace Source: https://pyproject-nix.github.io/uv2nix/lib/workspace.html Loads a workspace from a workspace root. Returns an attribute set containing overlays, config, and dependency declarations. ```APIDOC ## lib.workspace.loadWorkspace ### Description Load a workspace from a workspace root. ### Arguments - `workspaceRoot` (path) - Workspace root as a path - `config` (attribute set or function) - Config overrides for settings automatically inferred by `loadConfig`. Can be passed as either an attribute set or a function taking the generated config as an argument and returning the augmented config. ### Returns - `mkPyprojectOverlay` - Create an overlay for usage with pyproject.nix's builders - `mkEditablePyprojectOverlay` - Generate an overlay to use with pyproject.nix's build infrastructure to install dependencies in editable mode. - `config` - Workspace config as loaded by `loadConfig` - `deps` - Pre-defined dependency declarations for top-level workspace packages - `default` - No optional-dependencies or dependency-groups enabled - `optionals` - All optional-dependencies enabled - `groups` - All dependency-groups enabled - `all` - All optional-dependencies & dependency-groups enabled ``` -------------------------------- ### Build an sdist instead of a wheel by overriding uvBuildType Source: https://pyproject-nix.github.io/uv2nix/patterns/dist.html Overrides the package to use pyprojectDistHook and sets env.uvBuildType to 'sdist' to produce an sdist distribution instead of a wheel. ```nix (pythonSet.hello-world.override { pyprojectHook = pythonSet.pyprojectDistHook; }).overrideAttrs(old: { env.uvBuildType = "sdist"; }) ``` -------------------------------- ### mkApplication: wrap venv and link only package content Source: https://pyproject-nix.github.io/uv2nix/patterns/applications.html Use this Nix expression to create a derivation that wraps a virtual environment but only links package content from the specified package, excluding Python interpreters, activation scripts, and pyvenv.cfg while including binaries, man pages, and systemd units. It requires the `mkApplication` function from `pyproject-nix.build.util` and a `pythonSet` with a `mkVirtualEnv`. ```nix { packages = forAllSystems ( system: let pythonSet = pythonSets.${system}; pkgs = nixpkgs.legacyPackages.${system}; inherit (pkgs.callPackages pyproject-nix.build.util { }) mkApplication; in { # Create a derivation that wraps the venv but that only links package # content present in pythonSet.hello-world. # # This means that files such as: # - Python interpreters # - Activation scripts # - pyvenv.cfg # # Are excluded but things like binaries, man pages, systemd units etc are included. default = mkApplication { venv = pythonSet.mkVirtualEnv "application-env" workspace.deps.default; package = pythonSet.hello-world; }; } ``` -------------------------------- ### Add meta.mainProgram and passthru tests to uv2nix virtualenv Source: https://pyproject-nix.github.io/uv2nix/patterns/meta.html Override virtual environment derivations to add passthru tests and set meta.mainProgram so tools like `nix run` and `lib.getExe` work. Use this when building Python virtual environments with uv2nix and you need to expose them as packages. ```nix { # Expose Python virtual environments as packages. packages = forAllSystems ( system: let pythonSet = pythonSets.${system}; # Add metadata attributes to the virtual environment. # This is useful to inject meta and other attributes onto the virtual environment derivation. # # See # - https://nixos.org/manual/nixpkgs/unstable/#chap-passthru # - https://nixos.org/manual/nixpkgs/unstable/#chap-meta addMeta = drv: drv.overrideAttrs (old: { # Pass through tests from our package into the virtualenv so they can be discovered externally. passthru = lib.recursiveUpdate (old.passthru or { }) { inherit (pythonSet.testing.passthru) tests; }; # Set meta.mainProgram for commands like `nix run`. # https://nixos.org/manual/nixpkgs/stable/#var-meta-mainProgram meta = (old.meta or { }) // { mainProgram = "hello"; }; }); in { default = addMeta (pythonSet.mkVirtualEnv "testing-env" workspace.deps.default); full = addMeta (pythonSet.mkVirtualEnv "testing-env-full" workspace.deps.all); } } ``` -------------------------------- ### Declarative Build System Overrides Overlay Source: https://pyproject-nix.github.io/uv2nix/patterns/overriding-build-systems.html This Nix overlay demonstrates a strategy to manage multiple build system overrides by mapping a configuration object to package overrides. It uses resolveBuildSystem to automatically update nativeBuildInputs for the specified packages. ```nix __ final: prev: let inherit (final) resolveBuildSystem; inherit (builtins) mapAttrs; # Build system dependencies specified in the shape expected by resolveBuildSystem # The empty lists below are lists of optional dependencies. # # A package `foo` with specification written as: # `setuptools-scm[toml]` in pyproject.toml would be written as # `foo.setuptools-scm = [ "toml" ]` in Nix buildSystemOverrides = { attrs = { hatchling = [ ]; hatch-vcs = [ ]; hatch-fancy-pypi-readme = [ ]; }; hatchling = { pathspec = [ ]; pluggy = [ ]; packaging = [ ]; trove-classifiers = [ ]; }; pathspec = { flit-core = [ ]; }; pluggy = { setuptools = [ ]; }; trove-classifiers = { setuptools = [ ]; }; tomli.flit-core = [ ]; coverage.setuptools = [ ]; blinker.setuptools = [ ]; certifi.setuptools = [ ]; charset-normalizer.setuptools = [ ]; idna.flit-core = [ ]; urllib3 = { hatchling = [ ]; hatch-vcs = [ ]; }; pip = { setuptools = [ ]; wheel = [ ]; }; packaging.flit-core = [ ]; requests.setuptools = [ ]; pysocks.setuptools = [ ]; pytest-cov.setuptools = [ ]; tqdm.setuptools = [ ]; }; in mapAttrs ( name: spec: prev.${name}.overrideAttrs (old: { nativeBuildInputs = old.nativeBuildInputs ++ resolveBuildSystem spec; }) ) buildSystemOverrides ``` -------------------------------- ### Nix flake for building and running inline metadata scripts Source: https://pyproject-nix.github.io/uv2nix/usage/inline-metadata.html Defines a flake that loads all Python scripts from `./scripts`, creates a package set per script using `uv2nix.lib.scripts.loadScript`, and exposes them as packages (without `.py` suffix) and apps for `nix run`. Requires `nixpkgs`, `pyproject-nix`, `uv2nix`, and `pyproject-build-systems` inputs. ```nix { description = "Use PEP-723 inline metadata scripts with uv2nix"; inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; pyproject-nix = { url = "github:pyproject-nix/pyproject.nix"; inputs.nixpkgs.follows = "nixpkgs"; }; uv2nix = { url = "github:pyproject-nix/uv2nix"; inputs.pyproject-nix.follows = "pyproject-nix"; inputs.nixpkgs.follows = "nixpkgs"; }; pyproject-build-systems = { url = "github:pyproject-nix/build-system-pkgs"; inputs.pyproject-nix.follows = "pyproject-nix"; inputs.uv2nix.follows = "uv2nix"; inputs.nixpkgs.follows = "nixpkgs"; }; }; outputs = { self, nixpkgs, uv2nix, pyproject-nix, pyproject-build-systems, ... }: let inherit (nixpkgs) lib; forAllSystems = lib.genAttrs lib.systems.flakeExposed; # Load all Python scripts from ./scripts directory scripts = lib.mapAttrs ( name: _: uv2nix.lib.scripts.loadScript { script = ./scripts + "/${name}"; } ) ( lib.filterAttrs (name: type: type == "regular" && lib.hasSuffix ".py" name) ( builtins.readDir ./scripts ) ); packages' = forAllSystems ( system: let pkgs = nixpkgs.legacyPackages.${system}; python = pkgs.python3; baseSet = pkgs.callPackage pyproject-nix.build.packages { inherit python; }; in lib.mapAttrs ( _name: script: let # Create package overlay from script overlay = script.mkOverlay { sourcePreference = "wheel"; }; # Construct package set pythonSet = baseSet.overrideScope ( lib.composeManyExtensions [ pyproject-build-systems.overlays.wheel overlay ] ); in # Write out an executable script with a shebang pointing to the scripts virtualenv pkgs.writeScript script.name ( # Returns script as a string with inserted shebang script.renderScript { # Construct a virtual environment for script venv = script.mkVirtualEnv { inherit pythonSet; }; } ) ) scripts ); in { # Drop .py suffix from scripts, making example.py runnable as example packages = forAllSystems ( system: lib.mapAttrs' (name: drv: lib.nameValuePair (lib.removeSuffix ".py" name) drv) packages'.${system} ); # Make each script runnable directly with `nix run` apps = forAllSystems ( system: lib.mapAttrs (_name: script: { type = "app"; program = "${script}"; }) self.packages.${system} ); }; } ```