11.3. Python

11.3.1. Dependencies (py-deps)

Declare a module’s Python dependencies in its package.yaml under py-deps. Every entry must state its source — the package database it is drawn from — because Python packages split across two incompatible worlds:

py-deps:
  matplotlib: {version: ">=3.5", source: "conda"}
  requests: {version: "*", source: "pypi"}

source: conda draws the package from the conda-forge package database; source: pypi draws it from the Python Package Index. Use conda for anything that ships a compiled C/C++/Fortran extension (numpy, scipy, pandas, matplotlib, pyarrow, pillow, …​) so it shares one ABI with the rest of the environment; pypi is appropriate for pure-Python packages that are not mirrored on conda-forge.

Unlike the other languages, source is mandatory for Python: a bare matplotlib: ">=3.5" is a build error, because the correct database cannot be guessed safely. Names are used exactly as written (there is no PyPI-to-conda renaming table), so under source: "conda" use the conda-forge package name where it differs from the PyPI name.

The compiler takes the union of py-deps across every imported module; two modules constraining the same package differently are intersected by the solver rather than being an error.

conda channels

A conda dependency may name the channel it is drawn from — a distinct package database within conda — for a package that lives on a channel other than conda-forge:

py-deps:
  pysam: {version: "*", channel: "bioconda"}
  numpy: {version: ">=2", source: "conda"}

The channel field implies source: conda (channels are a conda-only concept), so pysam above needs no explicit source. conda-forge remains the universal default and the highest-priority base; a named channel such as bioconda sits below it under strict priority and can only supply packages conda-forge lacks. The environment’s channel list is derived automatically from the channels its modules declare — channels are never configured at the environment level, because a package’s database of record is a property of the module that needs it, not of where it is deployed.

channel is valid only on a conda dependency: pairing it with source: pypi is a build error. And because a package has a single database of record, two modules that draw the same package from different channels is a build error naming both modules — unlike differing version constraints, which are simply intersected.

11.3.2. Local packages (local-deps)

A Python package that lives in your project tree rather than in a package database — typically the helper package you are writing alongside the Morloc program — is declared under local-deps. The section is keyed by language, and each entry gives a path relative to the module’s directory:

local-deps:
  py:
    greet:
      path: ./src/greet
      editable: true

path must be a pip-installable package: a directory holding a pyproject.toml or setup.py. When you run morloc make, the environment installs it into the pool’s Python, so pool code can import greet like any other package. With editable: true the install points at your source tree, so an edit to the package is picked up on the next run of the program without rebuilding it; the default is false, a snapshot taken at build time. An installed program (mim install) always gets a snapshot, whatever editable says, so a running service does not change under you.

source Py from still names a file, not a package, so reach the package through a one-line bridge:

glue.py
from greet import greet
source Py from "glue.py" ("greet")

Three rules keep a local dependency portable. Only the top-level module being built may declare local-deps; an imported module’s relative path has no meaning from the build root, and the build refuses it. The path must stay inside the project: it cannot be absolute and cannot contain ... To depend on a package stored elsewhere, put a symlink to it inside the project and point path at the symlink. And only Python and Rust support local-deps; the build rejects it for C++ and R. Each rule fails with an error naming the dependency:

$ morloc make main.loc
morloc: user error (local dependency 'greet' for py has path '../greet' that must not contain '..' (use an in-project symlink for an external source))