Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
74a70cd
agents: add best-practices skill
jonringer Oct 19, 2026
e236d01
treewide: best-practices cleanup
jonringer Oct 19, 2026
52e7d40
treewide: format = "setuptools" → pyproject = true
jonringer Oct 19, 2026
94357d6
treewide: rec → finalAttrs pattern
jonringer Oct 19, 2026
e4562c9
python3Packages.jinja2: fix build
jonringer Oct 19, 2026
8987241
python3Packages.cython: fix build
jonringer Oct 19, 2026
5de014b
python3Packages.cryptography: fix build
jonringer Oct 19, 2026
b57b3ae
treewide: fix bare inherit in nested scopes after finalAttrs migration
jonringer Oct 19, 2026
9bb9ac1
python3Packages.pbs-installer: fix build
jonringer Oct 19, 2026
4e5ef69
treewide: fix bare optional-dependencies self-refs after finalAttrs m…
jonringer Oct 19, 2026
b1a9a17
treewide: fix remaining finalAttrs migration issues (src.name, pname,…
jonringer Oct 20, 2026
12d0911
treewide: fix bare src.tag/rev/meta refs after finalAttrs migration
jonringer Oct 20, 2026
fc726aa
treewide: fix more finalAttrs migration issues
jonringer Oct 20, 2026
15e78c4
python3Packages.selenium: fix build
jonringer Oct 20, 2026
af1080f
python3Packages.ruamel-yaml-clib: fix build
jonringer Oct 20, 2026
1313cb1
python3Packages.cloudsmith-api: fix build
jonringer Oct 20, 2026
9a41f3f
treewide: fix remaining nested inherit and format issues
jonringer Oct 20, 2026
2c19759
python3Packages.ctap-keyring-device: fix build
jonringer Oct 20, 2026
3acf053
treewide: fix circular refs and duplicate attrs after finalAttrs migr…
jonringer Oct 20, 2026
3f23be3
python3Packages.dbus-python: fix build
jonringer Oct 20, 2026
9153123
python3Packages.git-filter-repo: fix build
jonringer Oct 20, 2026
597f930
python3Packages.githubkit: fix build
jonringer Oct 20, 2026
4bca934
python3Packages.langgraph-checkpoint: fix build
jonringer Oct 20, 2026
21f0927
python3Packages.locust: fix build
jonringer Oct 20, 2026
f96c940
python3Packages.macholib: fix build
jonringer Oct 20, 2026
01a230d
python3Packages.monitorcontrol: fix build
jonringer Oct 20, 2026
c25802b
python3Packages.pycurl: fix build
jonringer Oct 20, 2026
bc7b216
python3Packages.pypdfium2: fix build
jonringer Oct 20, 2026
a720e40
python3Packages.qdldl: fix build
jonringer Oct 20, 2026
42b7e7f
python3Packages.radish-bdd: fix build
jonringer Oct 20, 2026
c89e3ad
python3Packages.rpy2-*: fix build
jonringer Oct 20, 2026
b30fc89
python3Packages.sendgrid: fix build
jonringer Oct 20, 2026
e83bab5
python3Packages.sphinx-automodapi: fix build
jonringer Oct 20, 2026
2b676ca
python3Packages.sphinxcontrib-plantuml: fix build
jonringer Oct 20, 2026
369e8ca
python3Packages.textx: fix build
jonringer Oct 20, 2026
8c80d61
python3Packages.tpm2-pytss: fix build
jonringer Oct 20, 2026
f4c80c7
python3Packages.morfessor: fix build
jonringer Oct 20, 2026
9b9d5bc
python3Packages.xstatic: fix build
jonringer Oct 20, 2026
6f4639f
python3Packages.amply: fix build
jonringer Oct 20, 2026
2fdd7f8
python3Packages.aioserial: fix build
jonringer Oct 20, 2026
278b836
python3Packages.libcloud: fix build
jonringer Oct 20, 2026
d688f1f
python3Packages.httptools: fix build
jonringer Oct 20, 2026
f731a7f
python3Packages.htmlmin: fix build
jonringer Oct 20, 2026
941f116
python3Packages.wsme: fix build
jonringer Oct 20, 2026
6d54f4b
python3Packages.pkgconfig: fix build
jonringer Oct 20, 2026
63e3db9
python3Packages.crashtest: fix build
jonringer Oct 20, 2026
9036359
python3Packages.doc8: fix build
jonringer Oct 20, 2026
314da4f
python3Packages.phply: fix build
jonringer Oct 20, 2026
da5d616
python3Packages.txamqp: fix build
jonringer Oct 20, 2026
43b7e6b
python3Packages.allure-pytest: fix build
jonringer Oct 20, 2026
97c289f
python3Packages.azure-servicemanagement-legacy: fix build
jonringer Oct 20, 2026
f69eaad
python3Packages.cocotb-bus: fix build
jonringer Oct 20, 2026
246d196
python3Packages.alibabacloud-credentials: fix build
jonringer Oct 20, 2026
64703a3
python3Packages.exdown: fix build
jonringer Oct 20, 2026
47eb712
python3Packages.aiopg: fix build
jonringer Oct 20, 2026
8501956
python3Packages.cloup: fix build
jonringer Oct 20, 2026
ecf88e1
arrow-cpp: fix build
jonringer Oct 20, 2026
70b8944
opencv4: fix build
jonringer Oct 20, 2026
b22c454
python3Packages.datetime: fix build
jonringer Oct 20, 2026
76bf615
python3Packages.aiobiketrax: fix build
jonringer Oct 20, 2026
7d07e7d
python3Packages.aiobotocore: fix build
jonringer Oct 20, 2026
c16dd0e
python3Packages.aioboto3: fix build
jonringer Oct 20, 2026
15cf8c4
python3Packages.pint: fix build
jonringer Oct 20, 2026
a9d9552
python3Packages.aioextensions: fix build
jonringer Oct 20, 2026
8610d68
python3Packages.aiomysql: fix build
jonringer Oct 20, 2026
26a3ac9
python3Packages.allure-python-commons-test: fix build
jonringer Oct 20, 2026
47118e8
python3Packages.amaranth: fix build
jonringer Oct 20, 2026
e8d2916
python3Packages.apache-beam: fix build
jonringer Oct 20, 2026
d54d02a
python3Packages.astroquery: fix build
jonringer Oct 20, 2026
b47ecbc
python3Packages.autobahn: fix build
jonringer Oct 20, 2026
e017e61
python3Packages.batchgenerators: fix build
jonringer Oct 20, 2026
ef3001c
python3Packages.bitcoin-utils-fork-minimal: fix build
jonringer Oct 20, 2026
aa7ea3e
python3Packages.block-io: fix build
jonringer Oct 20, 2026
e2d4dd0
python3Packages.blosc2: fix build
jonringer Oct 20, 2026
cf07523
python3Packages.brian2: fix build
jonringer Oct 20, 2026
4ef14b3
Add GHA ci gates
jonringer Oct 20, 2026
69cef13
treewide: lint
jonringer Oct 20, 2026
2041177
AGENTS: add formatting step
jonringer Oct 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
272 changes: 272 additions & 0 deletions .agents/skills/best-practices/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
---
name: best-practices
description: Review a Python package expression for best-practices compliance. Use when reviewing PRs, auditing existing packages, or writing new ones — checks meta completeness, pyproject conventions, dependency placement, testing strategy, source fetching, and formatting.
---

# Best Practices Review

Review a Python package expression and report violations. Read the package file(s), then check every rule below. Report each finding with the line number and a short explanation.

## Meta Attributes

### Required Fields

Every package must have all three:

| Field | What to check |
|-------|---------------|
| `meta.description` | Present, non-empty, does not repeat the package name verbatim |
| `meta.homepage` | Present, upstream project URL |
| `meta.license` | Present, uses `lib.licenses.*` (not a raw string) |

### Recommended Fields

Flag as "recommended" (not error) if missing:

- `meta.mainProgram` — for packages that install a binary (check `top-level.nix` for `toPythonApplication` usage)

### Forbidden Fields

Flag as error if present:

- `meta.maintainers` — not a recognised key in this repo (except `maintainers = [ ]` which is accepted but unnecessary)
- `meta.teams` — not a recognised key
- `meta.platforms` — omit; inherited automatically from the Python interpreter

## Build System

### pyproject

- `pyproject = true` **must** be set for PEP 517/518 builds. Flag legacy `format = "setuptools"` or `format = "pyproject"` as "prefer `pyproject = true`".
- `format = "wheel"` is acceptable for pre-built wheel packages.
- `format = "other"` is acceptable when the package has a non-standard build process.
- `build-system` **must** be present when `pyproject = true` is set.
- Flag any package lacking both `pyproject` and `format` — it falls back to legacy setuptools implicitly.

### Common Build Backends

Flag if `build-system` uses an unusual or outdated backend:

| Backend | Notes |
|---------|-------|
| `setuptools` | Most common; acceptable |
| `hatchling` | Modern; acceptable |
| `flit-core` | Lightweight; acceptable |
| `poetry-core` | Acceptable; do **not** use `poetry` (the full tool) as a build backend |
| `pdm-backend` | Acceptable |
| `maturin` | For Rust extensions; acceptable |
| `meson-python` | For C/C++ extensions; acceptable |
| `setuptools-scm` | Version management plugin; usually paired with `setuptools` |
| `scikit-build-core` | CMake-based; acceptable |

### CMake (in Python Packages)

- If `cmakeFlags` or `cmakeBuildType` are used alongside Python, `cmake.configurePhaseHook` **must** be in `nativeBuildInputs`.
- Native build tools (cmake, ninja, pkg-config, meson) belong in `nativeBuildInputs`, not `buildInputs`.

## Dependencies

### Attribute Naming

| Attribute | Purpose | Flag if misused |
|-----------|---------|-----------------|
| `build-system` | PEP 517 build backends (setuptools, hatchling, etc.) | — |
| `dependencies` | Runtime Python dependencies | Flag `propagatedBuildInputs` as "prefer `dependencies`" |
| `optional-dependencies` | Extras groups (attrset of lists) | — |
| `nativeBuildInputs` | Build-time tools (compilers, code generators, pkg-config, cmake) | — |
| `buildInputs` | C/C++ libraries linked at build time | — |
| `nativeCheckInputs` | Test-only dependencies | Flag bare `checkInputs` as "prefer `nativeCheckInputs`" |

### Dependency Placement

- **Build tools** (compilers, code generators, pkg-config, cmake, ninja, meson) belong in `nativeBuildInputs`, not `buildInputs`.
- **C/C++ libraries** belong in `buildInputs`, not `nativeBuildInputs`.
- **Test frameworks** (`pytestCheckHook`, `unittestCheckHook`, `pytest-mock`, etc.) belong in `nativeCheckInputs`.
- **Python runtime dependencies** belong in `dependencies`, not `propagatedBuildInputs`.
- `strictDeps = true` should be set when `depsBuildBuild` is used.

### Dependency Relaxation

- `pythonRelaxDeps` is acceptable when upstream pins tighter than necessary — list the specific packages being relaxed.
- `pythonRemoveDeps` is acceptable for removing dependencies unavailable in the package set — prefer this over patching `pyproject.toml` when a simple removal suffices.
- Flag blanket `pythonRelaxDeps = true` (without a package list) as "prefer explicit package list".

## Testing

### Preferred: `testPaths` + `passthru.tests`

The preferred testing strategy uses `testPaths` which auto-generates `passthru.tests.python` and a `test_src` output, decoupling tests from the main build:

```nix
nativeCheckInputs = [ pytestCheckHook ];
testPaths = [ "tests" ];
```

This is **strongly preferred** over in-build testing because:
- Test failures don't invalidate the package or its downstream consumers
- Tests run against the installed package, not the build tree
- Avoids rebuilding the package just to re-run tests

### Acceptable: `pytestCheckHook` without `testPaths`

When `pytestCheckHook` is in `nativeCheckInputs` but `testPaths` is not set, the tests still run but without the `passthru.tests` decoupling. Flag as "recommend adding `testPaths`" when the source tree contains an obvious test directory.

### Acceptable: Manual `passthru.tests`

For complex test setups (e.g., circular dependencies with pytest), a manual `passthru.tests` is acceptable:

```nix
passthru.tests = {
pytest = callPackage ./tests.nix { };
};
```

### Smoke Checks

- `pythonImportsCheck` is **recommended** for all packages. It provides basic import validation during the build.
- Flag missing `pythonImportsCheck` as a recommendation.

### What to Flag

| Pattern | Severity | Recommendation |
|---------|----------|----------------|
| `pytestCheckHook` without `testPaths` | Recommendation | Add `testPaths = [ "tests" ];` (or appropriate path) |
| `doCheck = true` explicitly | Warning | Remove — enable testing via `testPaths` or `passthru.tests` instead |
| `doCheck = false` explicitly | Warning | Remove — `false` is already the default |
| `doInstallCheck = false` explicitly | Warning | Remove — already the default |
| Custom `checkPhase` with pytest | Recommendation | Prefer `pytestCheckHook` + `testPaths` |
| `disabledTests` without `pytestCheckHook` | Warning | Tests won't actually be disabled without the hook |

### Test Attributes

These attributes are forwarded to the `testPaths` test derivation automatically:
- `disabledTests`, `disabledTestPaths`, `enabledTestPaths`
- `pytestFlags`, `pytestFlagsArray`, `unittestFlagsArray`
- `preCheck`, `postCheck`, `preInstallCheck`, `postInstallCheck`

## Packaging Conventions

### Structural

- Use `finalAttrs` pattern — flag `rec {` as "prefer finalAttrs". The `finalAttrs` pattern enables better overriding and self-reference.
- Do **not** set `__structuredAttrs = true` — it is the default.
- Do **not** set `doCheck = false` or `doInstallCheck = false` — they are defaults.
- Avoid `placeholder` when possible — prefer shell output references for better content-addressed derivation support. E.g., `"PREFIX=${placeholder "out"}"` → `"PREFIX=$(out)"`.
- Directory name **must** match `pname` and use hyphens, not underscores (e.g., `zope-interface`, not `zope_interface`).

### Formatting

- Attributes inside a `buildPythonPackage` block should be separated by an empty line between each attribute.
- Exception: `pname`, `version`, `pyproject`, `format`, and `disabled` may be grouped together without blank lines.

### Function Arguments

- Comment-group function arguments by purpose:

```nix
{
lib,
buildPythonPackage,
fetchFromGitHub,
# build-system
setuptools,
# dependencies
requests,
urllib3,
# tests
pytestCheckHook,
}:
```

## Sources

### Fetchers

- **`fetchPypi`** is preferred for PyPI sdist tarballs. This repo uses `fetchPypi` (lowercase 'i').
- **`fetchFromGitHub`** is preferred when patches or test fixtures are needed from the repository.
- Flag `fetchurl` or `fetchzip` pointing at a PyPI or GitHub tarball as "prefer `fetchPypi` or `fetchFromGitHub`".
- `fetchFromGitHub`/`fetchFromGitLab` should use `tag`, not `rev` with a tag value.
- Hash should be SRI format (`sha256-...`), not bare hex.

### Version References

When using `finalAttrs`:
```nix
src = fetchFromGitHub {
tag = "v${finalAttrs.version}";
...
};
```

When using `rec`:
```nix
src = fetchPypi {
inherit pname version;
...
};
```

## Python-Specific Patterns

### Version Gating

- Use `disabled = pythonOlder "3.x";` to skip on older interpreters, not conditional `meta.platforms`.
- Import `pythonOlder` or `pythonAtLeast` in the function arguments when needed.

### Namespace Packages

- Use `pythonNamespacesHook` for PEP 420 namespace packages (e.g., `zope.*`, `azure.*`).

### Wheels

- `format = "wheel"` is acceptable for pre-built binary packages.
- Wheel packages should still have `pythonImportsCheck`.
- Avoid wheels when a source build is feasible — source builds are more reproducible.

### Alternate Versions

- Place alternate versions in separate files alongside `default.nix` (e.g., `5.nix`, `3.nix`).
- The `default.nix` should contain the latest/primary version.

### Patching pyproject.toml

When patching `pyproject.toml`, prefer targeted fixes:

```nix
postPatch = ''
substituteInPlace pyproject.toml \
--replace-fail "setuptools>=68" "setuptools"
'';
```

Flag broad `sed` replacements that could break unrelated content.

## Commits

- Each commit should be one logical change.
- Commit message format: `python3Packages.<pname>: init at <version>` or `python3Packages.<pname>: <old> -> <new>`.
- Fixup commits should be squashed before merge.
- Do **not** add AI attribution (`Co-Authored-By`) to commits.

## Output Format

Group findings by severity:

```
## Errors
- line 12: `build-system` missing when `pyproject = true` is set
- line 30: `meta.maintainers = [ lib.maintainers.foo ]` is forbidden — remove or use `[ ]`

## Warnings
- line 8: `propagatedBuildInputs` — prefer `dependencies`
- line 25: `doCheck = false` is the default — remove redundant line
- line 40: `__structuredAttrs = true` is the default — remove redundant line
- line 5: `rec {` — prefer `finalAttrs` pattern

## Recommendations
- missing `pythonImportsCheck`
- line 15: `pytestCheckHook` present but no `testPaths` — consider adding `testPaths = [ "tests" ];`
- missing `meta.mainProgram` for CLI package
```

If there are no findings in a severity group, omit that group. If the package is clean, say so.
36 changes: 36 additions & 0 deletions .github/workflows/nix.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Nix

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
lint:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@v30
with:
extra_nix_config: |
extra-substituters = https://ekala-corepkgs.cachix.org
extra-trusted-public-keys = ekala-corepkgs.cachix.org-1:DcZV+vegWoEzacbSdXFXU4S7728C0eS9RfGpKeyHd6w=
- name: Nix Lint
run: nix fmt . -- --ci

eval:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@v30
with:
extra_nix_config: |
extra-substituters = https://ekala-corepkgs.cachix.org
extra-trusted-public-keys = ekala-corepkgs.cachix.org-1:DcZV+vegWoEzacbSdXFXU4S7728C0eS9RfGpKeyHd6w=
- name: Evaluate all packages
run: ./ci/eval.sh
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ buildPythonPackage (finalAttrs: {
- **Source fetchers:** prefer `fetchPyPi`; use `fetchFromGitHub` when patches or test fixtures are needed.
- **Alternate versions:** place in a separate file (e.g., `chardet/5.nix`) alongside `default.nix`.
- **Patches:** place `.patch` files alongside `default.nix` in the package directory.
- **Formatting:** run `nix fmt -- <file>` after every edit to ensure consistent formatting.

## Commit Message Format

Expand Down
2 changes: 1 addition & 1 deletion ci/eval.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ trap 'rm -f "$stderr"' EXIT
# Real failures are `abort`s, missing attributes and type errors, none of which
# `tryEval` can catch -- so they surface here as a non-zero exit with Nix's own
# message, which names the offending expression and its source location.
if ! result="$(nix-instantiate --eval --strict --json ci/eval.nix --show-trace 2>"$stderr")"; then
if ! result="$(nix-instantiate --eval --strict --json ci/eval.nix --show-trace --option allow-import-from-derivation false 2>"$stderr")"; then
cat "$stderr" >&2
exit 1
fi
Expand Down
12 changes: 12 additions & 0 deletions pkgs/arrow-cpp/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ stdenv.mkDerivation (finalAttrs: {
ninja
autoconf # for vendored jemalloc
flatbuffers
protobuf
]
++ lib.optional stdenv.hostPlatform.isDarwin fixDarwinDylibNames;

Expand Down Expand Up @@ -140,8 +141,18 @@ stdenv.mkDerivation (finalAttrs: {

preConfigure = ''
patchShebangs build-support/

substituteInPlace "src/arrow/vendored/datetime/tz.cpp" \
--replace-fail 'discover_tz_dir();' '"${tzdata}/share/zoneinfo";'

# Fix unsubstituted @build_protobuf@ from corepkgs protobuf setup hook
ProtobufCMakeFlags() {
cmakeFlagsArray+=(
"-DPROTOC_EXE=${protobuf}/bin/protoc"
"-DProtobuf_PROTOC_EXE=${protobuf}/bin/protoc"
"-DProtobuf_PROTOC_EXECUTABLE=${protobuf}/bin/protoc"
)
}
'';

cmakeFlags = [
Expand Down Expand Up @@ -182,6 +193,7 @@ stdenv.mkDerivation (finalAttrs: {
(lib.cmakeBool "ARROW_S3" enableS3)
(lib.cmakeBool "ARROW_GCS" enableGcs)
(lib.cmakeBool "ARROW_AZURE" enableAzure)
(lib.cmakeFeature "Protobuf_PROTOC_EXECUTABLE" "${protobuf}/bin/protoc")
(lib.cmakeBool "ARROW_ORC" true)
# Parquet options:
(lib.cmakeBool "ARROW_PARQUET" true)
Expand Down
Loading
Loading