diff --git a/specs/poetry/runner b/specs/poetry/runner new file mode 100755 index 0000000..e423c2c --- /dev/null +++ b/specs/poetry/runner @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +cp -r template/. "$OUT" diff --git a/specs/poetry/template/.envrc b/specs/poetry/template/.envrc new file mode 100644 index 0000000..817939c --- /dev/null +++ b/specs/poetry/template/.envrc @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +if command -v git > /dev/null && on_git_branch; then + git config --local core.hooksPath .githooks/ +fi + +use flake diff --git a/specs/poetry/template/.githooks/pre-commit b/specs/poetry/template/.githooks/pre-commit new file mode 100644 index 0000000..f894b36 --- /dev/null +++ b/specs/poetry/template/.githooks/pre-commit @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -e + +filesToFormat=$( + git --no-pager diff --name-status --no-color --cached | \ + awk '$1 != "D" && $2 ~ /\.py$/ {print $NF}' +) + +for path in $filesToFormat +do + black --quiet $path + git add $path +done; diff --git a/specs/poetry/template/.gitignore b/specs/poetry/template/.gitignore new file mode 100644 index 0000000..6123955 --- /dev/null +++ b/specs/poetry/template/.gitignore @@ -0,0 +1,5 @@ +# Directory used by `direnv` to hold `use flake`-generated profiles. +.direnv/ + +# A symlink produced by default when running `nix build`. +result diff --git a/specs/poetry/template/README.md b/specs/poetry/template/README.md new file mode 100644 index 0000000..9d63901 --- /dev/null +++ b/specs/poetry/template/README.md @@ -0,0 +1,29 @@ +# Poetry Flake Tempalte + +This is a template for constructing a working environment for Python (version +3.11.6) development. Packaging and dependency management relies on [poetry](https://python-poetry.org/) +(version 1.7.0). [direnv](https://direnv.net/) can be used to a launch a dev +shell upon entering this directory (refer to `.envrc`). Otherwise run via: +```bash +$> nix develop +``` + +## Language Server + +The [python-lsp-server](https://github.com/python-lsp/python-lsp-server) +(version v1.9.0) is included in this flake, along with the [python-lsp-black](https://github.com/python-lsp/python-lsp-black) +plugin for formatting purposes. `pylsp` is expected to be configured to use +[McCabe](https://github.com/PyCQA/mccabe), [pycodestyle](https://pycodestyle.pycqa.org/en/latest/), +and [pyflakes](https://github.com/PyCQA/pyflakes). Refer to your editor for +configuration details. + +## Formatting + +Formatting depends on the [black](https://black.readthedocs.io/en/stable/index.html) +(version 23.9.1) tool. A `pre-commit` hook is included in `.githooks` that can +be used to format all `*.py` files prior to commit. Install via: +```bash +$> git config --local core.hooksPath .githooks/ +``` +If running [direnv](https://direnv.net/), this hook is installed automatically +when entering the directory. diff --git a/specs/poetry/template/default.nix b/specs/poetry/template/default.nix new file mode 100644 index 0000000..f620865 --- /dev/null +++ b/specs/poetry/template/default.nix @@ -0,0 +1,10 @@ +(import + ( + let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in + fetchTarball { + url = lock.nodes.flake-compat.locked.url or "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; + sha256 = lock.nodes.flake-compat.locked.narHash; + } + ) + { src = ./.; } +).defaultNix diff --git a/specs/poetry/template/flake.lock b/specs/poetry/template/flake.lock new file mode 100644 index 0000000..247f171 --- /dev/null +++ b/specs/poetry/template/flake.lock @@ -0,0 +1,190 @@ +{ + "nodes": { + "flake-compat": { + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "revCount": 57, + "type": "tarball", + "url": "https://api.flakehub.com/f/pinned/edolstra/flake-compat/1.0.1/018afb31-abd1-7bff-a5e4-cff7e18efb7a/source.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nix-github-actions": { + "inputs": { + "nixpkgs": [ + "poetry2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1698974481, + "narHash": "sha256-yPncV9Ohdz1zPZxYHQf47S8S0VrnhV7nNhCawY46hDA=", + "owner": "nix-community", + "repo": "nix-github-actions", + "rev": "4bb5e752616262457bc7ca5882192a564c0472d2", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-github-actions", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1700794826, + "narHash": "sha256-RyJTnTNKhO0yqRpDISk03I/4A67/dp96YRxc86YOPgU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "5a09cb4b393d58f9ed0d9ca1555016a8543c2ac8", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "poetry2nix": { + "inputs": { + "flake-utils": "flake-utils_2", + "nix-github-actions": "nix-github-actions", + "nixpkgs": [ + "nixpkgs" + ], + "systems": "systems_3", + "treefmt-nix": "treefmt-nix" + }, + "locked": { + "lastModified": 1701035916, + "narHash": "sha256-Cbe/3H9/z7vIXAeMr9m9iXs1gRxpE3w1mrx9aaxWtGU=", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "2bee2516bc054458b0cbca10b18e2ec63cea8726", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "poetry2nix", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "poetry2nix": "poetry2nix" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "id": "systems", + "type": "indirect" + } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "poetry2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1699786194, + "narHash": "sha256-3h3EH1FXQkIeAuzaWB+nK0XK54uSD46pp+dMD3gAcB4=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "e82f32aa7f06bbbd56d7b12186d555223dc399d1", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/specs/poetry/template/flake.nix b/specs/poetry/template/flake.nix new file mode 100644 index 0000000..d4d4f8e --- /dev/null +++ b/specs/poetry/template/flake.nix @@ -0,0 +1,89 @@ +{ + description = '' + An opinionated poetry flake. + + This flake has been adapted from the `app` template found in: + https://github.com/nix-community/poetry2nix + + To generate a copy of this template elsewhere, run: + $> bootstrap poetry + ''; + + inputs = { + flake-compat.url = "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz"; + flake-utils.url = "github:numtide/flake-utils"; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + poetry2nix = { + url = "github:nix-community/poetry2nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = { self, nixpkgs, flake-utils, poetry2nix, ... }: + flake-utils.lib.eachDefaultSystem (system: + let + # See https://github.com/nix-community/poetry2nix/tree/master#api for + # more functions and examples. + pkgs = nixpkgs.legacyPackages.${system}; + + inherit + (poetry2nix.lib.mkPoetry2Nix { inherit pkgs; }) + mkPoetryApplication + defaultPoetryOverrides; + + # https://github.com/nix-community/poetry2nix/blob/ec4364021900f8e0d425d901b6e6ff03cf201efb/docs/edgecases.md + # `poetry2nix`, by default, prefers building from source. To build + # certain dependencies, we need to augment its build dependencies by + # adding the corresponding build backend (e.g. `setuptools`). + # + # For example, you can write: + # ```nix + # pypkgs-build-requirements = { + # ... + # coolname = [ "setuptools" ]; + # ... + # }; + # ``` + # after encountering a build error like: + # + # > ModuleNotFoundError: No module named 'setuptools' + pypkgs-build-requirements = {}; + poetry2nix-overrides = defaultPoetryOverrides.extend (self: super: + builtins.mapAttrs (package: build-requirements: + (builtins.getAttr package super).overridePythonAttrs (old: { + buildInputs = + (old.buildInputs or []) ++ + (builtins.map (pkg: + if builtins.isString pkg then + builtins.getAttr pkg super + else + pkg) build-requirements); + }) + ) pypkgs-build-requirements + ); + in + { + packages = { + tmpl-app = mkPoetryApplication { + projectDir = ./.; + overrides = poetry2nix-overrides; + }; + default = self.packages.${system}.tmpl-app; + }; + + devShells.default = pkgs.mkShell { + inputsFrom = [ self.packages.${system}.tmpl-app ]; + packages = [ + pkgs.poetry + ] ++ (with pkgs.python311Packages; [ + black + debugpy + mccabe + pycodestyle + pyflakes + python-lsp-black + python-lsp-server + ]); + }; + }); +} diff --git a/specs/poetry/template/main.py b/specs/poetry/template/main.py new file mode 100644 index 0000000..54b08a6 --- /dev/null +++ b/specs/poetry/template/main.py @@ -0,0 +1,2 @@ +if __name__ == '__main__': + pass diff --git a/specs/poetry/template/poetry.lock b/specs/poetry/template/poetry.lock new file mode 100644 index 0000000..5dfbaad --- /dev/null +++ b/specs/poetry/template/poetry.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. +package = [] + +[metadata] +lock-version = "2.0" +python-versions = "^3.11" +content-hash = "81b2fa642d7f2d1219cf80112ace12d689d053d81be7f7addb98144d56fc0fb2" diff --git a/specs/poetry/template/pyproject.toml b/specs/poetry/template/pyproject.toml new file mode 100644 index 0000000..81a6cff --- /dev/null +++ b/specs/poetry/template/pyproject.toml @@ -0,0 +1,14 @@ +[tool.poetry] +name = "tmpl" +version = "0.1.0" +description = "" +authors = ["Your Name "] +license = "MIT" +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.11" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api"