Skip to content

Commit e82d2bf

Browse files
committed
Rework Flake templates & add impure development template
This separates documentation from user-level templates & provides a little bit more scaffolding with handling of `system`.
1 parent 8d77f34 commit e82d2bf

File tree

11 files changed

+215
-104
lines changed

11 files changed

+215
-104
lines changed

doc/src/SUMMARY.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
- [hacks](./builders/hacks.md)
1818
- [ecosystem](./builders/ecosystem.md)
1919

20+
# [Templates](./templates.md)
21+
- [Flake Templates](./templates.md)
22+
2023
# Meta
2124
- [FAQ](./FAQ.md)
2225

doc/src/templates.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Flake templates
2+
3+
Pyproject.nix offers a number of Flake templates to quickly get started with developing
4+
5+
To get started with any of the listed templates run (replace `name` with the template name):
6+
7+
## pyproject
8+
9+
Using nixpkgs for Python development based on a PEP-621 `pyproject.toml` file.
10+
A quickstart & production version of [use-cases/pyproject](./use-cases/pyproject.html).
11+
12+
```
13+
nix flake init --template github:pyproject-nix/pyproject.nix#pyproject
14+
```
15+
16+
## requirements
17+
18+
Use a `requirements.txt` to create a Python environment using nixpkgs Python packages.
19+
A quickstart & production version of [use-cases/requirements](./use-cases/requirements.html).
20+
21+
```
22+
nix flake init --template github:pyproject-nix/pyproject.nix#requirements
23+
```
24+
25+
## impure
26+
27+
Simple no frills best practices development shell to develop Python projects with Nix, but without using Nix tooling for Python packages.
28+
29+
Does not depend on `pyproject.nix`.
30+
31+
Uses `uv` for Python package management.
32+
33+
```
34+
nix flake init --template github:pyproject-nix/pyproject.nix#impure
35+
```

doc/src/use-cases/pyproject.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ This example loads `pyproject.toml` to create an environment using [`python.with
77
## flake.nix
88

99
```nix
10-
{{#include ../../../templates/pyproject/flake.nix}}
10+
{{#include ./pyproject/flake.nix}}
1111
```
1212

1313
## pyproject.toml
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
{
2+
description = "A basic flake using pyproject.toml project metadata";
3+
4+
inputs.pyproject-nix.url = "github:pyproject-nix/pyproject.nix";
5+
inputs.pyproject-nix.inputs.nixpkgs.follows = "nixpkgs";
6+
7+
outputs =
8+
{ nixpkgs, pyproject-nix, ... }:
9+
let
10+
# Loads pyproject.toml into a high-level project representation
11+
# Do you notice how this is not tied to any `system` attribute or package sets?
12+
# That is because `project` refers to a pure data representation.
13+
project = pyproject-nix.lib.project.loadPyproject {
14+
# Read & unmarshal pyproject.toml relative to this project root.
15+
# projectRoot is also used to set `src` for renderers such as buildPythonPackage.
16+
projectRoot = ./.;
17+
};
18+
19+
# This example is only using x86_64-linux
20+
pkgs = nixpkgs.legacyPackages.x86_64-linux;
21+
22+
# We are using the default nixpkgs Python3 interpreter & package set.
23+
#
24+
# This means that you are purposefully ignoring:
25+
# - Version bounds
26+
# - Dependency sources (meaning local path dependencies won't resolve to the local path)
27+
#
28+
# To use packages from local sources see "Overriding Python packages" in the nixpkgs manual:
29+
# https://nixos.org/manual/nixpkgs/stable/#reference
30+
#
31+
# Or use an overlay generator such as uv2nix:
32+
# https://github.com/pyproject-nix/uv2nix
33+
python = pkgs.python3;
34+
35+
in
36+
{
37+
# Create a development shell containing dependencies from `pyproject.toml`
38+
devShells.x86_64-linux.default =
39+
let
40+
# Returns a function that can be passed to `python.withPackages`
41+
arg = project.renderers.withPackages { inherit python; };
42+
43+
# Returns a wrapped environment (virtualenv like) with all our packages
44+
pythonEnv = python.withPackages arg;
45+
46+
in
47+
# Create a devShell like normal.
48+
pkgs.mkShell { packages = [ pythonEnv ]; };
49+
50+
# Build our package using `buildPythonPackage
51+
packages.x86_64-linux.default =
52+
let
53+
# Returns an attribute set that can be passed to `buildPythonPackage`.
54+
attrs = project.renderers.buildPythonPackage { inherit python; };
55+
in
56+
# Pass attributes to buildPythonPackage.
57+
# Here is a good spot to add on any missing or custom attributes.
58+
python.pkgs.buildPythonPackage (attrs // { env.CUSTOM_ENVVAR = "hello"; });
59+
};
60+
}

doc/src/use-cases/requirements.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ This example loads `requirements.txt` to create an environment using [`python.wi
77
## flake.nix
88

99
```nix
10-
{{#include ../../../templates/requirements-txt/flake.nix}}
10+
{{#include ./requirements/flake.nix}}
1111
```
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
description = "Construct development shell from requirements.txt";
3+
4+
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
5+
6+
inputs.pyproject-nix.url = "github:pyproject-nix/pyproject.nix";
7+
8+
outputs =
9+
{ nixpkgs, pyproject-nix, ... }:
10+
let
11+
# Load/parse requirements.txt
12+
project = pyproject-nix.lib.project.loadRequirementsTxt { projectRoot = ./.; };
13+
14+
pkgs = nixpkgs.legacyPackages.x86_64-linux;
15+
python = pkgs.python3;
16+
17+
pythonEnv =
18+
# Assert that versions from nixpkgs matches what's described in requirements.txt
19+
# In projects that are overly strict about pinning it might be best to remove this assertion entirely.
20+
assert project.validators.validateVersionConstraints { inherit python; } == { };
21+
(
22+
# Render requirements.txt into a Python withPackages environment
23+
pkgs.python3.withPackages (project.renderers.withPackages { inherit python; })
24+
);
25+
26+
in
27+
{
28+
devShells.x86_64-linux.default = pkgs.mkShell { packages = [ pythonEnv ]; };
29+
};
30+
}

templates/impure/flake.nix

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
inputs = {
3+
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
4+
};
5+
6+
outputs =
7+
{ nixpkgs, ... }:
8+
let
9+
inherit (nixpkgs) lib;
10+
forAllSystems = lib.genAttrs lib.systems.flakeExposed;
11+
in
12+
{
13+
devShells = forAllSystems (
14+
system:
15+
let
16+
pkgs = nixpkgs.legacyPackages.${system};
17+
in
18+
{
19+
default = pkgs.mkShell {
20+
packages = [
21+
pkgs.python3
22+
pkgs.uv
23+
];
24+
25+
shellHook = ''
26+
unset PYTHONPATH
27+
uv sync
28+
. .venv/bin/activate
29+
'';
30+
};
31+
}
32+
);
33+
};
34+
}

templates/impure/pyproject.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[project]
2+
name = "impure-package"
3+
version = "0.1.0"
4+
description = "Add your description here"
5+
authors = [ ]
6+
requires-python = ">=3.13"
7+
dependencies = []

templates/pyproject/flake.nix

Lines changed: 23 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,41 @@
11
{
2-
description = "A basic flake using pyproject.toml project metadata";
2+
description = "Flake using pyproject.toml metadata";
33

44
inputs.pyproject-nix.url = "github:pyproject-nix/pyproject.nix";
55
inputs.pyproject-nix.inputs.nixpkgs.follows = "nixpkgs";
66

77
outputs =
88
{ nixpkgs, pyproject-nix, ... }:
99
let
10-
# Loads pyproject.toml into a high-level project representation
11-
# Do you notice how this is not tied to any `system` attribute or package sets?
12-
# That is because `project` refers to a pure data representation.
10+
inherit (nixpkgs) lib;
11+
forAllSystems = lib.genAttrs lib.systems.flakeExposed;
12+
1313
project = pyproject-nix.lib.project.loadPyproject {
14-
# Read & unmarshal pyproject.toml relative to this project root.
15-
# projectRoot is also used to set `src` for renderers such as buildPythonPackage.
1614
projectRoot = ./.;
1715
};
1816

19-
# This example is only using x86_64-linux
20-
pkgs = nixpkgs.legacyPackages.x86_64-linux;
21-
22-
# We are using the default nixpkgs Python3 interpreter & package set.
23-
#
24-
# This means that you are purposefully ignoring:
25-
# - Version bounds
26-
# - Dependency sources (meaning local path dependencies won't resolve to the local path)
27-
#
28-
# To use packages from local sources see "Overriding Python packages" in the nixpkgs manual:
29-
# https://nixos.org/manual/nixpkgs/stable/#reference
30-
#
31-
# Or use an overlay generator such as uv2nix:
32-
# https://github.com/pyproject-nix/uv2nix
33-
python = pkgs.python3;
34-
17+
pythonAttr = "python3";
3518
in
3619
{
37-
# Create a development shell containing dependencies from `pyproject.toml`
38-
devShells.x86_64-linux.default =
39-
let
40-
# Returns a function that can be passed to `python.withPackages`
41-
arg = project.renderers.withPackages { inherit python; };
42-
43-
# Returns a wrapped environment (virtualenv like) with all our packages
44-
pythonEnv = python.withPackages arg;
45-
46-
in
47-
# Create a devShell like normal.
48-
pkgs.mkShell { packages = [ pythonEnv ]; };
49-
50-
# Build our package using `buildPythonPackage
51-
packages.x86_64-linux.default =
20+
devShells = forAllSystems (system: {
21+
default =
22+
let
23+
pkgs = nixpkgs.legacyPackages.${system};
24+
python = pkgs.${pythonAttr};
25+
pythonEnv = python.withPackages (project.renderers.withPackages { inherit python; });
26+
in
27+
pkgs.mkShell { packages = [ pythonEnv ]; };
28+
});
29+
30+
packages = forAllSystems (
31+
system:
5232
let
53-
# Returns an attribute set that can be passed to `buildPythonPackage`.
54-
attrs = project.renderers.buildPythonPackage { inherit python; };
33+
pkgs = nixpkgs.legacyPackages.${system};
34+
python = pkgs.${pythonAttr};
5535
in
56-
# Pass attributes to buildPythonPackage.
57-
# Here is a good spot to add on any missing or custom attributes.
58-
python.pkgs.buildPythonPackage (attrs // { env.CUSTOM_ENVVAR = "hello"; });
36+
{
37+
default = python.pkgs.buildPythonPackage (project.renderers.buildPythonPackage { inherit python; });
38+
}
39+
);
5940
};
6041
}

templates/pyproject/pyproject.toml

Lines changed: 6 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,7 @@
11
[project]
2-
name = "spam"
3-
version = "2020.0.0"
4-
description = "Lovely Spam! Wonderful Spam!"
5-
readme = "README.rst"
6-
requires-python = ">=3.8"
7-
license = {file = "LICENSE.txt"}
8-
keywords = ["egg", "bacon", "sausage", "tomatoes", "Lobster Thermidor"]
9-
authors = [
10-
{email = "[email protected]"},
11-
{name = "Tzu-ping Chung"}
12-
]
13-
maintainers = [
14-
{name = "Brett Cannon", email = "[email protected]"}
15-
]
16-
classifiers = [
17-
"Development Status :: 4 - Beta",
18-
"Programming Language :: Python"
19-
]
20-
21-
dependencies = [
22-
"httpx",
23-
"gidgethub[httpx]>4.0.0",
24-
"django>2.1; os_name != 'nt'",
25-
"django>2.0; os_name == 'nt'"
26-
]
27-
28-
[project.optional-dependencies]
29-
test = [
30-
"pytest < 5.0.0",
31-
"pytest-cov[all]"
32-
]
33-
34-
[project.urls]
35-
homepage = "https://example.com"
36-
documentation = "https://readthedocs.org"
37-
repository = "https://github.com"
38-
changelog = "https://github.com/me/spam/blob/master/CHANGELOG.md"
39-
40-
[project.scripts]
41-
spam-cli = "spam:main_cli"
42-
43-
[project.gui-scripts]
44-
spam-gui = "spam:main_gui"
45-
46-
[project.entry-points."spam.magical"]
47-
tomatoes = "spam:main_tomatoes"
2+
name = "hello-python"
3+
version = "0.1.0"
4+
description = "A minimal pyproject.toml"
5+
authors = [ ]
6+
requires-python = ">=3.13"
7+
dependencies = []

0 commit comments

Comments
 (0)