Merge pull request 'templates: add python-project' (#10) from python-template into main

This commit is contained in:
DavHau 2023-07-20 17:32:28 +02:00 committed by Gitea
parent cadfb90bd3
commit eaaf0d2992
12 changed files with 248 additions and 0 deletions

9
.gitignore vendored
View File

@ -1 +1,10 @@
.direnv
result*
# python
__pycache__
.coverage
.mypy_cache
.pytest_cache
.pythonenv
.ruff_cache

View File

@ -22,6 +22,7 @@
imports = [
./flake-parts/packages.nix
./flake-parts/formatting.nix
./templates/python-project/flake-module.nix
];
flake = {
nixosConfigurations.installer = lib.nixosSystem {

View File

@ -0,0 +1 @@
use nix

View File

@ -0,0 +1,57 @@
{
pkgs ? import <nixpkgs> {},
lib ? pkgs.lib,
python3 ? pkgs.python3,
}: 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
;
};
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 = pkgs.runCommand "${name}-check" {} ''
cp -r ${src} ./src
chmod +w -R ./src
cd src
export PYTHONPATH=.
echo -e "\x1b[32m## run ruff\x1b[0m"
${pkgs.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

View File

@ -0,0 +1,10 @@
{
perSystem = {pkgs, ...}: let
pyproject = builtins.fromTOML (builtins.readFile ./src/pyproject.toml);
name = pyproject.project.name;
package = pkgs.callPackage ./default.nix {};
in {
# packages.${name} = package;
checks.python-template = package.tests.check;
};
}

View File

@ -0,0 +1,5 @@
import os
def detect_git_repo(path: str) -> bool:
return os.path.exists(f"{path}/.git")

View File

@ -0,0 +1,17 @@
import argparse
# statement that doesn't need testing
__version__ = "1.0.0" # pragma: no cover
# this will be an entrypoint under /bin/my_cli (see pyproject.toml config)
def my_cli() -> None:
parser = argparse.ArgumentParser(description="my-tool")
parser.add_argument(
"-v", "--version", help="Show the version of this program", action="store_true"
)
args = parser.parse_args()
if args.version:
print(f"Version: {__version__}")
else:
parser.print_help()

View File

@ -0,0 +1,61 @@
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
[tool.setuptools.packages.find]
include = ["my_tool*"]
[project]
name = "my_tool"
description = "internal tooling of cLAN"
dynamic = ["version"]
scripts = {my-tool = "my_tool: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
)/
'''

View File

@ -0,0 +1,45 @@
{
pkgs ? import <nixpkgs> {},
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
]
);
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 .)
if ! cmp -s pyproject.toml $tmp_path/pyproject.toml; then
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 && \
cp -a pyproject.toml $tmp_path/pyproject.toml
fi
export PATH="$tmp_path/bin:$PATH"
export PYTHONPATH="$repo_root:$tmp_path/${pythonWithDeps.sitePackages}"
'';
};
in
devShell

View File

@ -0,0 +1,10 @@
import subprocess
import pytest
# returns a temporary directory with a fake git repo
@pytest.fixture()
def git_repo_path(tmp_path):
subprocess.run(["mkdir", ".git"], cwd=tmp_path)
return tmp_path

View File

@ -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:")

View File

@ -0,0 +1,16 @@
import tempfile
import my_lib
# using the fixture from conftest.py
def test_is_git_repo(git_repo_path: str):
result = my_lib.detect_git_repo(git_repo_path)
assert result is True
# using the fixture from conftest.py
def test_is_not_git_repo():
with tempfile.TemporaryDirectory() as tempdir:
result = my_lib.detect_git_repo(tempdir)
assert result is False