From c15bc5bb0c22003654ac1bcb853e56e0ad01d652 Mon Sep 17 00:00:00 2001 From: grym Date: Fri, 8 Dec 2023 09:30:15 -0500 Subject: [PATCH] Include test example. Update docs. Improve makefile --- .pre-commit-config.yaml | 9 ++++---- Makefile | 6 +++++- README.org | 48 +++++++++++++++++++++++++++++++++-------- pyproject.toml | 2 +- template/__main__.py | 8 +++++++ template/cli.py | 2 -- tests/__init__.py | 0 tests/test_template.py | 7 ++++++ 8 files changed, 65 insertions(+), 17 deletions(-) create mode 100644 template/__main__.py delete mode 100644 template/cli.py create mode 100644 tests/__init__.py create mode 100644 tests/test_template.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f6dc1dc..bebe757 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,24 +1,25 @@ # See https://pre-commit.com for more information # See https://pre-commit.com/hooks.html for more hooks -fail_fast: true +fail_fast: false repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v3.2.0 + rev: v4.5.0 hooks: - id: trailing-whitespace exclude: .*\.(md|json) - id: end-of-file-fixer exclude: .*\.(json) - id: check-yaml + - id: check-json - id: check-added-large-files args: [--maxkb=5120] # 2 MB - repo: https://github.com/psf/black - rev: 22.10.0 + rev: 23.11.0 hooks: - id: black name: Formatting - repo: https://github.com/pycqa/isort - rev: 5.10.1 + rev: 5.12.0 hooks: - id: isort name: Import order diff --git a/Makefile b/Makefile index b48aef3..ab4cdfa 100644 --- a/Makefile +++ b/Makefile @@ -8,8 +8,12 @@ VENV_BIN=$(VENV_DIR)/bin venv: @echo making venv at $(VENV_DIR) @python -m venv $(VENV_DIR) - @$(VENV_PYTHON) -m pip install --upgrade pip wheel pre-commit + @$(VENV_PYTHON) -m pip install --upgrade pip setuptools wheel build pre-commit install: venv @$(VENV_PYTHON) -m pip install --upgrade -e '.[dev]' + @$(VENV_PYTHON) -m pre_commit autoupdate @$(VENV_PYTHON) -m pre_commit install + +build: install + @$(VENV_PYTHON) -m build diff --git a/README.org b/README.org index 27d5181..ff03b9b 100644 --- a/README.org +++ b/README.org @@ -21,7 +21,7 @@ This worked example of a repo might help. dependencies with pip. - You can make CLI entry points that act like normal programs - You can share your code with others, or include it as a dependency in other projects. -- + * So what are these files? ** convenience boilerplate #+begin_src @@ -30,23 +30,26 @@ Makefile .pre-commit-config.yaml README.org #+end_src -These files are optional. +These files are optional: they are not required as far as /python/ is +concerned. They are conveniences for the developer that I have come around +over the years to converging on. I develop almost exclusively on linux +(distro largely agnostic) and macOS. -Using the lovely [[https://gitignore.io][gitignore.io]] collection of recommended ignores, I've populated +- Using the lovely [[https://gitignore.io][gitignore.io]] collection of recommended ignores, I've populated a =.gitignore= for python and common editors. -If you like to automate the creation of venvs and installation and whatnot with +- If you like to automate the creation of venvs and installation and whatnot with =make=, as I do, then the included =Makefile= may be useful. -Automatic code formatting with =black= and =isort= can be accomplished with =.pre-commit-config.yaml= +- Automatic code formatting with =black= and =isort= can be accomplished with =.pre-commit-config.yaml= if [[https://pre-commit.com][pre-commit]] is used. -And this file is =Readme.org=; choose a markup language of your preference. +- And this file is =Readme.org=; choose a markup language of your preference. ** package files #+begin_src ├── pyproject.toml ├── template -│   ├── cli.py +│   ├── __main__.py │   └── __init__.py #+end_src @@ -59,5 +62,32 @@ adoption of PEP517/517 by =setuptools=, though, you can ram it all into =pyproject.toml=. =template/= is the directory of the python package. The name of the package is -=template=, it has two modules =__init__= and =cli=, and =cli= has one function -=main=, which is configured as the entry point, and simply prints ="Hello, world!"=. +=template=, it has two modules =__init__= and =__main__=, and =__main__= has +one function =main=, which is configured as the entry point, and simply prints +="Hello,world!"=. + +- =__init__.py= flags the directory =template/= as a python package. You need + to have this file in any package (read: directory) or sub-package. +- =__main__.py= permits callers to invoke your code with =python -m template=; + when that is done, the =__main__.py= module is executed. Consequently, it + contains an =if __name__ == "__main__"= test, which calls the same callable + (the function =main()=) that the entrypoint specified in =pyproject.toml= + does. + + Add as many other modules, packages, etc. as you like under =template/=. +** tests +#+begin_src +├── tests +│   ├── __init__.py +│   └── test_template.py +#+end_src + +=pytest= is my preferred testing framework for python. It's listed as a +development dependency in =pyproject.toml=. + +- tests live in a directory called =tests= +- invoking =./venv/bin/pytest ./tests= runs all python files inside tests whose + filenames start with =test_=. +- each function inside those files whose name begins with =test_= is treated as + an independent unit test and is run. +- see [[https://nedbatchelder.com/text/test3.html][ned batchelder's excellent pytest primer]] for more detail. diff --git a/pyproject.toml b/pyproject.toml index 8fe31fe..9c81081 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,4 +28,4 @@ dynamic = ["version"] dev = ["pre-commit","pytest"] [project.scripts] -template = "template.cli:main" +template = "template.__main__:main" diff --git a/template/__main__.py b/template/__main__.py new file mode 100644 index 0000000..299494b --- /dev/null +++ b/template/__main__.py @@ -0,0 +1,8 @@ +def main(): + print("Hello, world!") + + +if __name__ == "__main__": + """This test, at module level, permits the use of + `python -m template` to invoke whatever follows.""" + main() diff --git a/template/cli.py b/template/cli.py deleted file mode 100644 index ff449c5..0000000 --- a/template/cli.py +++ /dev/null @@ -1,2 +0,0 @@ -def main(): - print("Hello, world!") diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_template.py b/tests/test_template.py new file mode 100644 index 0000000..806fd3e --- /dev/null +++ b/tests/test_template.py @@ -0,0 +1,7 @@ +import template + + +def test_template(): + # assert that the call to the function succeeds (but since it's just a + # print, it returns None) + assert template.__main__.main() is None