# `Snakepit.PythonPackages`
[🔗](https://github.com/nshkrdotcom/snakepit/blob/v0.13.0/lib/snakepit/python_packages.ex#L1)

Package installation and inspection for Snakepit-managed Python runtimes.

Requires [uv](https://docs.astral.sh/uv/) for package management. Install with:

    curl -LsSf https://astral.sh/uv/install.sh | sh

## Examples

    Snakepit.PythonPackages.ensure!({:list, ["numpy~=1.26", "scipy~=1.11"]})

    {:ok, :all_installed} =
      Snakepit.PythonPackages.check_installed(["numpy~=1.26", "scipy~=1.11"])

    {:ok, metadata} = Snakepit.PythonPackages.lock_metadata(["numpy~=1.26"])

    Snakepit.PythonPackages.ensure!({:file, "requirements.txt"}, upgrade: true)

# `requirement`

```elixir
@type requirement() :: String.t()
```

# `requirements_spec`

```elixir
@type requirements_spec() :: {:list, [requirement()]} | {:file, Path.t()}
```

# `check_installed`

```elixir
@spec check_installed(
  [requirement()],
  keyword()
) :: {:ok, :all_installed} | {:ok, {:missing, [requirement()]}}
```

Check which packages are installed and satisfy their version constraints.

Uses `uv pip install --dry-run` for accurate PEP-440 version checking.
Returns `{:ok, :all_installed}` when every requirement is satisfied, or
`{:ok, {:missing, requirements}}` when any are missing or have version mismatches.

# `ensure!`

```elixir
@spec ensure!(
  requirements_spec(),
  keyword()
) :: :ok | no_return()
```

Ensure all packages in the requirements spec are installed and satisfy version constraints.

Uses `uv pip install --dry-run` to check if packages need to be installed or upgraded,
then installs any missing or outdated packages.

Options:
  * `:upgrade` - upgrade matching packages
  * `:quiet` - suppress installer output
  * `:timeout` - install timeout in ms

# `install!`

```elixir
@spec install!(
  [requirement()],
  keyword()
) :: :ok | no_return()
```

Install the given package requirements using uv.

Prefer `ensure!/2` unless you already know which requirements are missing.

# `lock_metadata`

```elixir
@spec lock_metadata(
  [requirement()],
  keyword()
) :: {:ok, map()} | {:error, term()}
```

Return package metadata for lockfiles.

The result maps package name to `%{version: version, hash: hash}` entries.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
