From 9906d12384aa057a2257438b415db4c0c4a67a0e Mon Sep 17 00:00:00 2001 From: DavHau Date: Thu, 20 Jul 2023 18:07:27 +0200 Subject: [PATCH] clan-cli: initialize python project from template clan-cli: remove unnecessary unit test file clan-cli: fix shell.nix too stateful clan-cli: remove conftest.py clan-cli: fix flake-module.nix --- pkgs/clan-cli/.envrc | 1 + pkgs/clan-cli/default.nix | 72 ++++++++++++++++++++++++++++----- pkgs/clan-cli/flake-module.nix | 10 +++++ pkgs/clan-cli/pyproject.toml | 61 ++++++++++++++++++++++++++++ pkgs/clan-cli/shell.nix | 47 +++++++++++++++++++++ pkgs/clan-cli/tests/test_cli.py | 16 ++++++++ 6 files changed, 197 insertions(+), 10 deletions(-) create mode 100644 pkgs/clan-cli/.envrc create mode 100644 pkgs/clan-cli/flake-module.nix create mode 100644 pkgs/clan-cli/pyproject.toml create mode 100644 pkgs/clan-cli/shell.nix create mode 100644 pkgs/clan-cli/tests/test_cli.py diff --git a/pkgs/clan-cli/.envrc b/pkgs/clan-cli/.envrc new file mode 100644 index 00000000..1d953f4b --- /dev/null +++ b/pkgs/clan-cli/.envrc @@ -0,0 +1 @@ +use nix diff --git a/pkgs/clan-cli/default.nix b/pkgs/clan-cli/default.nix index 72214801..59d2fa46 100644 --- a/pkgs/clan-cli/default.nix +++ b/pkgs/clan-cli/default.nix @@ -1,10 +1,62 @@ -{ symlinkJoin -, writers -}: -symlinkJoin { - name = "clan"; - paths = [ - (writers.writePython3Bin "clan" { } ./clan.py) - (writers.writePython3Bin "clan-admin" { flakeIgnore = [ "E501" ]; } ./clan-admin.py) - ]; -} +{ + pkgs ? import {}, + + lib ? pkgs.lib, + python3 ? pkgs.python3, + ruff ? pkgs.ruff, + runCommand ? pkgs.runCommand, +}: let + pyproject = builtins.fromTOML (builtins.readFile ./pyproject.toml); + name = pyproject.project.name; + + src = lib.cleanSource ./.; + + dependencies = lib.attrValues { + # inherit (python3.pkgs) + # some-package + # ; + }; + + devDependencies = lib.attrValues { + inherit (pkgs) ruff; + inherit (python3.pkgs) + black + mypy + pytest + pytest-cov + setuptools + wheel + ; + }; + + package = python3.pkgs.buildPythonPackage { + inherit name src; + format = "pyproject"; + nativeBuildInputs = [ + python3.pkgs.setuptools + ]; + propagatedBuildInputs = + dependencies + ++ [ ]; + passthru.tests = { inherit check; }; + passthru.devDependencies = devDependencies; + }; + + checkPython = python3.withPackages (ps: devDependencies); + + check = runCommand "${name}-check" { } '' + cp -r ${src} ./src + chmod +w -R ./src + cd src + export PYTHONPATH=. + echo -e "\x1b[32m## run ruff\x1b[0m" + ${ruff}/bin/ruff check . + echo -e "\x1b[32m## run mypy\x1b[0m" + ${checkPython}/bin/mypy . + echo -e "\x1b[32m## run pytest\x1b[0m" + ${checkPython}/bin/pytest + touch $out + ''; + +in +package diff --git a/pkgs/clan-cli/flake-module.nix b/pkgs/clan-cli/flake-module.nix new file mode 100644 index 00000000..1e85e607 --- /dev/null +++ b/pkgs/clan-cli/flake-module.nix @@ -0,0 +1,10 @@ +{ + perSystem = {pkgs, ...}: let + pyproject = builtins.fromTOML (builtins.readFile ./pyproject.toml); + name = pyproject.project.name; + package = pkgs.callPackage ./default.nix {}; + in { + # packages.${name} = package; + checks.python-template = package.tests.check; + }; +} diff --git a/pkgs/clan-cli/pyproject.toml b/pkgs/clan-cli/pyproject.toml new file mode 100644 index 00000000..cbf9dc67 --- /dev/null +++ b/pkgs/clan-cli/pyproject.toml @@ -0,0 +1,61 @@ +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" + +[tool.setuptools.packages.find] +include = ["clan.py"] + +[project] +name = "clan" +description = "cLAN CLI tool" +dynamic = ["version"] +scripts = {clan = "clan:my_cli"} + +[tool.pytest.ini_options] +addopts = "--cov . --cov-report term --cov-fail-under=100 --no-cov-on-fail" + +[tool.mypy] +python_version = "3.10" +warn_redundant_casts = true +disallow_untyped_calls = true +disallow_untyped_defs = true +no_implicit_optional = true +exclude = [ + "tests" +] + +[[tool.mypy.overrides]] +module = "setuptools.*" +ignore_missing_imports = true + +[[tool.mypy.overrides]] +module = "pytest.*" +ignore_missing_imports = true + +[tool.ruff] +line-length = 88 + +select = ["E", "F", "I"] +ignore = [ "E501" ] + +[tool.black] +line-length = 88 +target-version = ['py310'] +include = '\.pyi?$' +exclude = ''' +/( + \.git + | \.hg + | \.mypy_cache + | \.tox + | \.venv + | _build + | buck-out + | build + | dist + # The following are specific to Black, you probably don't want those. + | blib2to3 + | tests/data + | profiling +)/ +''' diff --git a/pkgs/clan-cli/shell.nix b/pkgs/clan-cli/shell.nix new file mode 100644 index 00000000..2b7b0748 --- /dev/null +++ b/pkgs/clan-cli/shell.nix @@ -0,0 +1,47 @@ +{ pkgs ? import { } +, system ? builtins.currentSystem +, +}: +let + lib = pkgs.lib; + python3 = pkgs.python3; + package = import ./default.nix { + inherit lib python3; + }; + pythonWithDeps = python3.withPackages ( + ps: + package.propagatedBuildInputs + ++ package.devDependencies + ++ [ + ps.pip + ] + ); + checkScript = pkgs.writeScriptBin "check" '' + nix build -f . tests.check -L "$@" + ''; + devShell = pkgs.mkShell { + packages = [ + pkgs.ruff + pythonWithDeps + ]; + # sets up an editable install and add enty points to $PATH + shellHook = '' + tmp_path=$(realpath ./.pythonenv) + repo_root=$(realpath .) + rm -rf $tmp_path + mkdir -p "$tmp_path/${pythonWithDeps.sitePackages}" + + ${pythonWithDeps.interpreter} -m pip install \ + --quiet \ + --disable-pip-version-check \ + --no-index \ + --no-build-isolation \ + --prefix "$tmp_path" \ + --editable $repo_root + + export PATH="$tmp_path/bin:${checkScript}/bin:$PATH" + export PYTHONPATH="$repo_root:$tmp_path/${pythonWithDeps.sitePackages}" + ''; + }; +in +devShell diff --git a/pkgs/clan-cli/tests/test_cli.py b/pkgs/clan-cli/tests/test_cli.py new file mode 100644 index 00000000..5311f2bd --- /dev/null +++ b/pkgs/clan-cli/tests/test_cli.py @@ -0,0 +1,16 @@ +import sys + +import my_tool + + +def test_no_args(capsys): + my_tool.my_cli() + captured = capsys.readouterr() + assert captured.out.startswith("usage:") + + +def test_version(capsys, monkeypatch): + monkeypatch.setattr(sys, "argv", ["", "--version"]) + my_tool.my_cli() + captured = capsys.readouterr() + assert captured.out.startswith("Version:")