Skip to content

[BUG] pre-commit: make the pymarkdown hook (pyjson5 C-extension / libstdc++) run on NixOS #698

Description

@c-vigo

Description

Follow-up to #697. The pymarkdown pre-commit hook also fails on a NixOS host,
but it is a different failure class than the standalone Rust binaries: it is a
pure-Python tool whose dependency pyjson5 ships a C extension that needs
libstdc++.so.6 on the loader path, which a NixOS host does not provide outside
an FHS/nix develop environment.

This is split from #697 because the standalone binaries (ruff, typos) have
drop-in nixpkgs packages, whereas pymarkdown does not — so it needs its own
investigation and decision.

Evidence

$ uv run pre-commit run pymarkdown --all-files
  File ".../pyjson5/__init__.py", line 1, in <module>
    from .pyjson5 import *
ImportError: libstdc++.so.6: cannot open shared object file: No such file or directory

pymarkdown is not packaged in nixpkgs (pymarkdown /
python3Packages.pymarkdownlnt both absent), so the simple "add to devTools +
language: system" recipe from #697 does not apply directly.

Options to investigate

  1. Provide libstdc++ to the loader in the dev-shell — add
    pkgs.stdenv.cc.cc.lib and set LD_LIBRARY_PATH (or NIX_LD_LIBRARY_PATH)
    in mkProjectShell so the existing manylinux pyjson5 wheel resolves its
    C library. Smallest change; keeps the upstream rev: pin; mildly impure.
  2. Package pymarkdown in the flakebuildPythonApplication from the
    PyPI sdist with pyjson5 taken from nixpkgs (python3Packages.pyjson5,
    built against the Nix libstdc++), exposed as a pymarkdown binary, then a
    language: system hook. Most hermetic / SSoT-aligned; most work; adds a
    version to maintain.
  3. nix-ld (host-level)programs.nix-ld.enable with
    libraries = [ pkgs.stdenv.cc.cc ] makes the wheel work unchanged. Not
    repo-enforceable (per-contributor system config); document as fallback. See
    the alternative discussion in [BUG] pre-commit: source binary hooks (ruff, ruff-format, typos) from the flake for NixOS compatibility #697.
  4. Drop/replace pymarkdown — only if markdown linting can move to a
    Nix-friendly tool without losing the .pymarkdown config behaviour
    (likely undesirable; listed for completeness).

Leaning: Option 1 as the pragmatic unblock (and it generalises to any future
C-extension Python hook), with Option 2 as the hermetic end-state if we want
pymarkdown fully off upstream wheels. Confirm during execution.

Acceptance criteria

  • pre-commit run pymarkdown --all-files passes in the dev-shell on a NixOS
    host (no --no-verify)
  • Chosen mechanism documented in docs/NIX.md
  • CI project-checks job stays green
  • If the dev-shell gains libstdc++/LD_LIBRARY_PATH, a dev-shell parity
    test asserts it (mirrors the existing UV_PYTHON/BATS_LIB_PATH tests)

Relationship

Refs: #625

Metadata

Metadata

Assignees

Labels

area:workflowDeveloper workflow, commands, rules, skillsbugSomething isn't workingpriority:mediumImportant but not urgentsemver:patchBug fix, backward-compatible

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions