Include test example. Update docs. Improve makefile

This commit is contained in:
grym 2023-12-08 09:30:15 -05:00
parent f0fda7a5c3
commit c15bc5bb0c
8 changed files with 65 additions and 17 deletions

View File

@ -1,24 +1,25 @@
# See https://pre-commit.com for more information # See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks # See https://pre-commit.com/hooks.html for more hooks
fail_fast: true fail_fast: false
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.2.0 rev: v4.5.0
hooks: hooks:
- id: trailing-whitespace - id: trailing-whitespace
exclude: .*\.(md|json) exclude: .*\.(md|json)
- id: end-of-file-fixer - id: end-of-file-fixer
exclude: .*\.(json) exclude: .*\.(json)
- id: check-yaml - id: check-yaml
- id: check-json
- id: check-added-large-files - id: check-added-large-files
args: [--maxkb=5120] # 2 MB args: [--maxkb=5120] # 2 MB
- repo: https://github.com/psf/black - repo: https://github.com/psf/black
rev: 22.10.0 rev: 23.11.0
hooks: hooks:
- id: black - id: black
name: Formatting name: Formatting
- repo: https://github.com/pycqa/isort - repo: https://github.com/pycqa/isort
rev: 5.10.1 rev: 5.12.0
hooks: hooks:
- id: isort - id: isort
name: Import order name: Import order

View File

@ -8,8 +8,12 @@ VENV_BIN=$(VENV_DIR)/bin
venv: venv:
@echo making venv at $(VENV_DIR) @echo making venv at $(VENV_DIR)
@python -m venv $(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 install: venv
@$(VENV_PYTHON) -m pip install --upgrade -e '.[dev]' @$(VENV_PYTHON) -m pip install --upgrade -e '.[dev]'
@$(VENV_PYTHON) -m pre_commit autoupdate
@$(VENV_PYTHON) -m pre_commit install @$(VENV_PYTHON) -m pre_commit install
build: install
@$(VENV_PYTHON) -m build

View File

@ -21,7 +21,7 @@ This worked example of a repo might help.
dependencies with pip. dependencies with pip.
- You can make CLI entry points that act like normal programs - 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. - You can share your code with others, or include it as a dependency in other projects.
-
* So what are these files? * So what are these files?
** convenience boilerplate ** convenience boilerplate
#+begin_src #+begin_src
@ -30,23 +30,26 @@ Makefile
.pre-commit-config.yaml .pre-commit-config.yaml
README.org README.org
#+end_src #+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. 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. =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. 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 ** package files
#+begin_src #+begin_src
├── pyproject.toml ├── pyproject.toml
├── template ├── template
│   ├── cli.py │   ├── __main__.py
│   └── __init__.py │   └── __init__.py
#+end_src #+end_src
@ -59,5 +62,32 @@ adoption of PEP517/517 by =setuptools=, though, you can ram it all into
=pyproject.toml=. =pyproject.toml=.
=template/= is the directory of the python package. The name of the package is =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 =template=, it has two modules =__init__= and =__main__=, and =__main__= has
=main=, which is configured as the entry point, and simply prints ="Hello, world!"=. 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.

View File

@ -28,4 +28,4 @@ dynamic = ["version"]
dev = ["pre-commit","pytest"] dev = ["pre-commit","pytest"]
[project.scripts] [project.scripts]
template = "template.cli:main" template = "template.__main__:main"

8
template/__main__.py Normal file
View File

@ -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()

View File

@ -1,2 +0,0 @@
def main():
print("Hello, world!")

0
tests/__init__.py Normal file
View File

7
tests/test_template.py Normal file
View File

@ -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