query
On this page

mkPythonEditablePackage

pkgs.python3Packages.mkPythonEditablePackage

Functor
Docs pulled from | This Revision | 15 minutes ago


Contribute
Enhance the ecosystem with your expertise! Contribute to fill the gaps in documentation. Your input can make a difference.

Noogle detected

This is a Functor

Learn about functors

Implementation

The following is the current implementation of this function.

{
  pname,
  version,

  # Editable root as string.
  # Environment variables will be expanded at runtime using os.path.expandvars.
  root,

  # Arguments passed on verbatim to buildPythonPackage
  derivationArgs ? { },

  # Python dependencies
  dependencies ? [ ],
  optional-dependencies ? { },

  # PEP-518 build-system https://peps.python.org/pep-518
  build-system ? [ ],

  # PEP-621 entry points https://peps.python.org/pep-0621/#entry-points
  scripts ? { },
  gui-scripts ? { },
  entry-points ? { },

  passthru ? { },
  meta ? { },
}:

# Create a PEP-660 (https://peps.python.org/pep-0660/) editable package pointing to an impure location outside the Nix store.
# The primary use case of this function is to enable local development workflows where the local package is installed into a virtualenv-like environment using withPackages.

assert lib.isString root;
let
  # In editable mode build-system's are considered to be runtime dependencies.
  dependencies' = dependencies ++ build-system;

  pyprojectContents = {
    # PEP-621 project table
    project = {
      name = pname;
      inherit
        version
        scripts
        gui-scripts
        entry-points
        ;
      dependencies = map lib.getName dependencies';
      optional-dependencies = lib.mapAttrs (_: map lib.getName) optional-dependencies;
    };

    # Allow empty package
    tool.hatch.build.targets.wheel.bypass-selection = true;

    # Include our editable pointer file in build
    tool.hatch.build.targets.wheel.force-include."_${pname}.pth" = "_${pname}.pth";

    # Build editable package using hatchling
    build-system = {
      requires = [ "hatchling" ];
      build-backend = "hatchling.build";
    };
  };

in
buildPythonPackage (
  {
    inherit
      pname
      version
      optional-dependencies
      passthru
      meta
      ;
    dependencies = dependencies';

    pyproject = true;

    unpackPhase = ''
      python -c "import json, os, tomli_w; attrs = json.load(open(os.environ['NIX_ATTRS_JSON_FILE'], 'r')); print(tomli_w.dumps(attrs['pyprojectContents']))" > pyproject.toml
      echo 'import os.path, sys; sys.path.insert(0, os.path.expandvars("${root}"))' > _${pname}.pth
    '';

    build-system = [ hatchling ];
  }
  // derivationArgs
  // {
    # Note: Using formats.toml generates another intermediary derivation that needs to be built.
    # We inline the same functionality for better UX.
    nativeBuildInputs = (derivationArgs.nativeBuildInputs or [ ]) ++ [ tomli-w ];
    inherit pyprojectContents;
    preferLocalBuild = true;
    __structuredAttrs = true;
  }
)