forked from clan/clan-core
Merge pull request 'templates: add python-project' (#10) from python-template into main
This commit is contained in:
parent
cadfb90bd3
commit
eaaf0d2992
9
.gitignore
vendored
9
.gitignore
vendored
@ -1 +1,10 @@
|
|||||||
|
.direnv
|
||||||
result*
|
result*
|
||||||
|
|
||||||
|
# python
|
||||||
|
__pycache__
|
||||||
|
.coverage
|
||||||
|
.mypy_cache
|
||||||
|
.pytest_cache
|
||||||
|
.pythonenv
|
||||||
|
.ruff_cache
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
imports = [
|
imports = [
|
||||||
./flake-parts/packages.nix
|
./flake-parts/packages.nix
|
||||||
./flake-parts/formatting.nix
|
./flake-parts/formatting.nix
|
||||||
|
./templates/python-project/flake-module.nix
|
||||||
];
|
];
|
||||||
flake = {
|
flake = {
|
||||||
nixosConfigurations.installer = lib.nixosSystem {
|
nixosConfigurations.installer = lib.nixosSystem {
|
||||||
|
1
templates/python-project/.envrc
Normal file
1
templates/python-project/.envrc
Normal file
@ -0,0 +1 @@
|
|||||||
|
use nix
|
57
templates/python-project/default.nix
Normal file
57
templates/python-project/default.nix
Normal 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
|
10
templates/python-project/flake-module.nix
Normal file
10
templates/python-project/flake-module.nix
Normal 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;
|
||||||
|
};
|
||||||
|
}
|
5
templates/python-project/my_lib/__init__.py
Normal file
5
templates/python-project/my_lib/__init__.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
def detect_git_repo(path: str) -> bool:
|
||||||
|
return os.path.exists(f"{path}/.git")
|
17
templates/python-project/my_tool/__init__.py
Normal file
17
templates/python-project/my_tool/__init__.py
Normal 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()
|
61
templates/python-project/pyproject.toml
Normal file
61
templates/python-project/pyproject.toml
Normal 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
|
||||||
|
)/
|
||||||
|
'''
|
45
templates/python-project/shell.nix
Normal file
45
templates/python-project/shell.nix
Normal 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
|
10
templates/python-project/tests/conftest.py
Normal file
10
templates/python-project/tests/conftest.py
Normal 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
|
16
templates/python-project/tests/test_cli.py
Normal file
16
templates/python-project/tests/test_cli.py
Normal 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:")
|
16
templates/python-project/tests/test_detect_git_repo.py
Normal file
16
templates/python-project/tests/test_detect_git_repo.py
Normal 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
|
Loading…
Reference in New Issue
Block a user