config/profiles/http/docs/pdoc.nix

286 lines
6.5 KiB
Nix

{ 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 "<tr>"
if test -f $out/"$LITERAL".html; then
write "<td><a href=\"$LITERAL.html\">$NAME</a>"
elif test -d $out/"$LITERAL"; then
write "<td><a href=\"$LITERAL/\">$NAME</a>"
else
write "<td>$NAME"
fi
write "<td>${version}"
if test -s $out/$LITERAL.log; then
write "<td><a href=\"$LITERAL.log\">log</a>"
else
write "<td>-"
fi
write "<td>${lib.escapeXML description}"
${if homepage == "-" then ''
write "<td>n/a"
'' else ''
write "<td><a href=\"${homepage}\">${homepage}</a>"
''}
write "</tr>"
'';
fallback = pkgs.writeTextDir "index.part-${toLiteral pkg}.html" ''
<tr>
<td>${toLiteral pkg}
<td>${version}
<td>&#10799;
<td>${lib.escapeXML description}
<td>${if homepage == "-" then
"n/a"
else
''<a href="${homepage}">${homepage}</a>''
}
</tr>
'';
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 "<!DOCTYPE html>" >> $out/index.html
echo "<table><tr><th>name<th>version<th>log<th>description<th>homepage</tr>" >> $out/index.html
cat $out/index.part-*.html >> $out/index.html
rm $out/index.part-*.html
echo "</table>" >> $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;
};
/**/
}