{ config, pkgs, lib, ... }: let # pdoc data pdoc-builtins = [ "builtins" "os" "array" "sys" "time" "traceback" "pathlib" "itertools" "functools" "unittest" "argparse" "asyncio" "textwrap" "collections" "configparser" "concurrent" "contextlib" "operator" "pickle" # TODO: marsmellow or whatever "copy" "ctypes" "pprint" "shlex" "re" "abc" "ast" "random" "shutil" "sqlite3" "subprocess" "statistics" "string" "tarfile" "typing" "uuid" "warnings" "wave" "dataclasses" "glob" "gzip" "inspect" "json" "base64" "zipfile" ]; pdoc-modules = [ {name="more-itertools"; literal="more_itertools";} "altair" "pygal" "vispy" #"ggplot" "seaborn" "bokeh" "plotly" "tabulate" "wavefile" "moderngl" "pydantic" "typer" "ptpython" "colorama" {name="pyjwt"; literal="jwt";} "zipp" "aiofiles" "aafigure" "urllib3" "tesserocr" "trio" "starlette" "pyverilog" "nixpkgs" "wavedrom" "httpx" "pyquery" "mpv" {name="beautifulsoup4"; literal="bs4";} "hid" #{name="hidapi"; literal="hid";} #"sanic" # broken build? "paramiko" "pydub" "aiohttp" "papermill" "rtoml" "redis" "numpy" #"domeneshop" "munch" "migen" "amaranth" "click" "attrs" "graphviz" "baron" "redbaron" "fastapi" "pytest" #"pyglet" # pyglet.com fails, windows only #"pygame" # pygame.movie fails on pdoc3, pdoc hangs "plotly" "peewee" "parsel" "pandas" #"mutmut" # moved to toplevel from python3Packages "mlflow" "meshio" #"einops" # depends on tensorflow, which is broken ATM "aiodns" "json5" "seaborn" "matplotlib" "dash" "rarfile" "pyramid" "pygtail" "codecov" "nbconvert" "humanfriendly" "pendulum" "jsonpickle" "cachetools" "wrapt" "lxml" "chardet" "yarl" "frozenlist" "itsdangerous" "xmltodict" {name="cached-property"; literal="cached_property";} "toolz" "aioitertools" "coconut" "asyncpg" #"aiopg" {name="libsass"; literal="sass";} {name="pytorch"; literal="torch";} #{name="pytorch-lightning"; literal="pytorch_lightning";} # broken build? {name="pillow"; literal="PIL";} "trio" "tqdm" "rich" "pudb" "pony" "mido" "jedi" "h5py" "atom" "toml" {name="pyyaml"; literal="yaml";} "jinja2" "requests" "h5py" "imageio" "pygments" "trimesh" "shapely" #"faiss" #"geomloss" #"mesh_to_sdf" #"pyrender" ]; toName = x: if builtins.isString x then x else x.name; toLiteral = x: if builtins.isString x then x else x.literal; mkPdoc = use-pdoc3: isBuiltin: pkg: let description = if isBuiltin then "builtin" else pkgs.python3Packages.${toName pkg}.meta.description; version = if isBuiltin then "-" else pkgs.python3Packages.${toName pkg}.version; homepage = if isBuiltin then "https://docs.python.org/3/library/${toLiteral pkg}.html" else pkgs.python3Packages.${toName pkg}.meta.homepage or "-"; doc = pkgs.runCommand "pdoc${if use-pdoc3 then "3" else ""}-${toName pkg}-docs" { nativeBuildInputs = (if use-pdoc3 then [pkgs.python3Packages.pdoc3] else [pkgs.python3Packages.pdoc]) ++ lib.optional (!isBuiltin) (builtins.getAttr (toName pkg) pkgs.python3Packages); NAME = toName pkg; LITERAL = toLiteral pkg; # TODO: license # TODO: build html with something better than bash } '' ( timeout 900s ${if !use-pdoc3 then ''pdoc --no-search --math --no-browser --output-directory $out "$LITERAL"'' else ''pdoc3 --skip-errors --output-dir $out --html "$LITERAL"'' } 2>&1 | tee $LITERAL.log ) || true mkdir -p $out cp $LITERAL.log $out test -f $out/index.html && rm -v $out/index.html function write { { printf "%s" "$@"; echo; } >> $out/index.part-"$LITERAL".html } write "" if test -f $out/"$LITERAL".html; then write "$NAME" elif test -d $out/"$LITERAL"; then write "$NAME" else write "$NAME" fi write "${version}" if test -s $out/$LITERAL.log; then write "log" else write "-" fi write "${lib.escapeXML description}" ${if homepage == "-" then '' write "n/a" '' else '' write "${homepage}" ''} write "" ''; fallback = pkgs.writeTextDir "index.part-${toLiteral pkg}.html" '' ${toLiteral pkg} ${version} ⨯ ${lib.escapeXML description} ${if homepage == "-" then "n/a" else ''${homepage}'' } ''; in if (builtins.tryEval doc.outPath).success then doc else fallback; mkPdocs = use-pdoc3: pkgs.symlinkJoin { name = "pdoc-docs"; paths = (map (mkPdoc use-pdoc3 true) pdoc-builtins) ++ (map (mkPdoc use-pdoc3 false) pdoc-modules); # note: globs are sorted postBuild = '' echo "" >> $out/index.html echo "" >> $out/index.html cat $out/index.part-*.html >> $out/index.html rm $out/index.part-*.html echo "
nameversionlogdescriptionhomepage
" >> $out/index.html ''; }; in { # Pdoc # Auto-generate API documentation for Python projects. services.docs-to-host.docs = [ { dirname = "pdoc-docs"; path = mkPdocs false; desc = "Documentation for various python modules, generated with pdoc"; } { dirname = "pdoc3-docs"; path = mkPdocs true; desc = "Documentation for various python modules, generated with pdoc3"; } ]; /** / services.nginx.virtualHosts.${mkDomain "pdoc"} = { forceSSL = true; # addSSL = true; enableACME = true; #useACMEHost = acmeDomain; root = mkPdocs false; }; services.nginx.virtualHosts.${mkDomain "pdoc3"} = { forceSSL = true; # addSSL = true; enableACME = true; #useACMEHost = acmeDomain; root = mkPdocs true; }; /**/ }