{ description = "Mews Profile: page validator, directory service, quickstart, and the mews.page site"; inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; pyproject-nix = { url = "github:pyproject-nix/pyproject.nix"; inputs.nixpkgs.follows = "nixpkgs"; }; uv2nix = { url = "github:pyproject-nix/uv2nix"; inputs.pyproject-nix.follows = "pyproject-nix"; inputs.nixpkgs.follows = "nixpkgs"; }; pyproject-build-systems = { url = "github:pyproject-nix/build-system-pkgs"; inputs.pyproject-nix.follows = "pyproject-nix"; inputs.uv2nix.follows = "uv2nix"; inputs.nixpkgs.follows = "nixpkgs"; }; }; outputs = { nixpkgs, pyproject-nix, uv2nix, pyproject-build-systems, ... }: let inherit (nixpkgs) lib; forAllSystems = lib.genAttrs lib.systems.flakeExposed; # Covers the three self-contained Python projects: validator/, # directory/ and quickstart/. site/ and pelican-mews/ are plain Python # projects outside this uv workspace, same as before, each installable # on its own. workspace = uv2nix.lib.workspace.loadWorkspace { workspaceRoot = ./.; }; # Wheels, not sources: the service is built on the machine it runs on, # which has one CPU, and lxml from source there takes minutes. overlay = workspace.mkPyprojectOverlay { sourcePreference = "wheel"; }; editableOverlay = workspace.mkEditablePyprojectOverlay { root = "$REPO_ROOT"; }; pythonSets = forAllSystems ( system: let pkgs = nixpkgs.legacyPackages.${system}; in (pkgs.callPackage pyproject-nix.build.packages { python = pkgs.python312; }).overrideScope ( lib.composeManyExtensions [ pyproject-build-systems.overlays.wheel overlay ] ) ); specDescription = "The Mews Profile specification, version 0.1."; in { devShells = forAllSystems ( system: let pkgs = nixpkgs.legacyPackages.${system}; pythonSet = pythonSets.${system}.overrideScope editableOverlay; virtualenv = pythonSet.mkVirtualEnv "mews-dev-env" workspace.deps.all; in { default = pkgs.mkShell { packages = [ virtualenv pkgs.uv # quickstart/md2mews.py is a standalone script with its own # dependency header, so it is not part of the workspace # environment. (pkgs.python3.withPackages (ps: [ ps.mistune ])) ]; env = { UV_NO_SYNC = "1"; UV_PYTHON = pythonSet.python.interpreter; UV_PYTHON_DOWNLOADS = "never"; }; shellHook = '' unset PYTHONPATH export REPO_ROOT=$(git rev-parse --show-toplevel) ''; }; } ); packages = forAllSystems ( system: let pkgs = nixpkgs.legacyPackages.${system}; pyPkgs = pkgs.python3Packages; # The directory service plus the validator and quickstart it was # built alongside, for deploying or running any of their commands. app = pythonSets.${system}.mkVirtualEnv "mews-env" workspace.deps.default; converter = pkgs.python3.withPackages (ps: [ ps.mistune ]); # pelican-mews uses pdm-backend and is not part of the uv workspace # above (it stays installable on its own, the same way it always # has been). Building it here, from plain nixpkgs python tooling, # is what lets the site build run inside the sandbox with no # network access. pelicanMews = pyPkgs.buildPythonPackage { pname = "pelican-mews"; version = "0.1.0"; pyproject = true; src = ./pelican-mews; build-system = [ pyPkgs.pdm-backend ]; dependencies = [ pyPkgs.lxml pyPkgs.pelican ]; }; siteBuilder = pkgs.python3.withPackages (ps: [ ps.pelican ps.markdown pelicanMews ]); in { default = app; # The published site. Every page it assembles is validated here, so a # page that does not follow the spec cannot reach the server. site = pkgs.runCommand "mews-site" { } '' mkdir -p $out/spec $out/dtd cp -r ${./site} site-src chmod -R u+w site-src ${siteBuilder}/bin/pelican site-src/content -o pelican-output \ -s site-src/pelicanconf.py cp pelican-output/index.html pelican-output/check.html $out/ cp pelican-output/mews-0.1.css $out/mews-0.1.css cp pelican-output/mews-0.1.css $out/spec/mews-0.1.css cp ${./spec/mews-0.1.dtd} $out/dtd/mews-0.1.dtd cp ${./spec/xhtml-mobile12.dtd} $out/dtd/xhtml-mobile12.dtd chmod -R u+w $out ${converter}/bin/python ${./quickstart/md2mews.py} ${./spec/SPEC.md} \ -o $out/spec/0.1.html --lang en --variant mews-cool \ --description ${lib.escapeShellArg specDescription} ${app}/bin/mewslint --quiet \ $out/index.html $out/check.html $out/spec/0.1.html ''; } ); }; }