diff options
Diffstat (limited to 'Biz/Bild')
-rw-r--r-- | Biz/Bild/Builder.nix | 93 | ||||
-rw-r--r-- | Biz/Bild/Example.py | 30 |
2 files changed, 104 insertions, 19 deletions
diff --git a/Biz/Bild/Builder.nix b/Biz/Bild/Builder.nix index 04002d0..214c110 100644 --- a/Biz/Bild/Builder.nix +++ b/Biz/Bild/Builder.nix @@ -1,33 +1,88 @@ -{ srcs # list of files +/* +This is the library of nix builders. Some rules to follow: +- Keep this code as minimal as possible. I'd rather write Haskell than Nix, + wouldn't you? +- Try to reuse as much upstream Nix as possible. +- Path-like args such as 'srcs' should always be absolute paths. +*/ +{ srcs ? "" # list of all source files, as a space-separated string +, main # the entrypoint or main module (not a path) , root # path to git root , packageSet # name mapped to private.${packageSet}, e.g. 'ghcWith' -, langDeps ? null # list of deps (as a string), split and passed to packageSet +, langdeps ? null # list of deps (as a string), split and passed to packageSet +, sysdeps ? null , name # exe name -, buildPhase +, compileLine ? "" # Target.compiler <> Target.compilerFlags }: with import (/. + root + "/Biz/Bild.nix") {}; with builtins; let - srcs_ = lib.strings.splitString " " srcs; + srcs_ = (lib.strings.splitString " " srcs) ++ [main]; + skip = ["_" ".direnv"]; filter = file: type: if elem (baseNameOf file) skip then false - # TODO: this means any new directory will cause a rebuild. this bad. - # i should recurse into the directory and match against the srcsr + # TODO: this means any new directory will cause a rebuild. this bad. i + # should recurse into the directory and match against the srcs. for now I + # just use postUnpack to delete empty dirs else if type == "directory" then true - else if type == "regular" then builtins.elem file srcs_ + else if type == "regular" then (builtins.elem file srcs_) else false; - deps = pkgset: - if langDeps != null then - private.selectAttrs (lib.strings.splitString " " langDeps) pkgset - else - []; -in stdenv.mkDerivation rec { - inherit name buildPhase; + + # clean up empty dirs + postUnpack = "find . -type d -empty -delete"; + src = lib.sources.cleanSourceWith {inherit filter; src = lib.sources.cleanSource root;}; - BIZ_ROOT = src; - buildInputs = [ (private.${packageSet} deps) ]; - installPhase = '' - mkdir -p $out/bin && cp ${name} $out/bin - ''; + + langdeps_ = pkgset: + if langdeps == null || langdeps == [] then + [] + else + private.selectAttrs (lib.strings.splitString " " langdeps) pkgset; + sysdeps_ = + if sysdeps == null || sysdeps == [] then + [] + else + private.selectAttrs (lib.strings.splitString " " sysdeps) private.nixpkgs.pkgs; + BIZ_ROOT = "."; +in { + base = stdenv.mkDerivation rec { + inherit name src BIZ_ROOT postUnpack; + buildInputs = [ (private.${packageSet} langdeps_) ] ++ sysdeps_; + installPhase = "install -D ${name} $out/bin/${name}"; + buildPhase = compileLine; + }; + + python = buildPythonApplication rec { + inherit name src BIZ_ROOT postUnpack; + propagatedBuildInputs = [ (private.${packageSet} langdeps_) ] ++ sysdeps_; + buildInputs = sysdeps_; + checkInputs = [(private.pythonWith (p: with p; [black mypy pylint]))]; + checkPhase = '' + black --quiet --exclude 'setup\.py$' --check . + pylint --errors-only . + mypy --strict --no-error-summary --exclude 'setup\.py$' . + python -m ${main} test + ''; + preBuild = '' + # initialize possibly-empty subdirectories as python modules + find . -type d -exec touch {}/__init__.py \; + # generate a minimal setup.py + cat > setup.py << EOF + from setuptools import setup, find_packages + setup( + name='${name}', + entry_points={'console_scripts':['${name} = ${main}:main']}, + version='0.0.0', + url='git://simatime.com/biz.git', + author='dev', + author_email='dev@simatime.com', + description='nil', + packages=find_packages(), + install_requires=[], + ) + EOF + ''; + pythonImportsCheck = [main]; # sanity check + }; } diff --git a/Biz/Bild/Example.py b/Biz/Bild/Example.py new file mode 100644 index 0000000..78a8a6a --- /dev/null +++ b/Biz/Bild/Example.py @@ -0,0 +1,30 @@ +# : out example +# : dep cryptography +import sys +from typing import List + +from cryptography.fernet import Fernet + + +def cryptic_hello(name: str) -> str: + "Example taken from `cryptography` docs." + key = Fernet.generate_key() + f = Fernet(key) + token = f.encrypt(hello(name).encode("utf-8")) + ret = f.decrypt(token).decode("utf-8") + assert ret == hello(name) + return ret + + +def hello(name: str) -> str: + return f"Hello {name}" + + +def main() -> None: + if "test" in sys.argv: + print("testing success") + print(cryptic_hello("world")) + + +if __name__ == "__main__": + main() |