diff --git a/.gitignore b/.gitignore index 8d3dbf2..7e50dad 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,6 @@ __pycache__/ # uv .venv -# ctt +# testing ctt and mkdocs build .ctt -ctt.toml +test diff --git a/constants.yml b/constants.yml index 0c4fdf3..f1ab799 100644 --- a/constants.yml +++ b/constants.yml @@ -20,14 +20,10 @@ md_project_setup: ``` {%- endif %} Navigate to the project directory and install all dependencies: + ```bash + ./just.sh install ``` - uv sync --all-groups --all-extras - ``` - This command will also create a virtual environment for the project. - To make sure that pre-commits are enabled run: - ``` - uv run pre-commit install --hook-type pre-push --hook-type post-checkout --hook-type pre-commit - ``` + This will also enable pre-commit hooks. {%- if use_dvc %} And make sure that you have all the necessary data available. ``` diff --git a/ctt.toml b/ctt.toml new file mode 100644 index 0000000..952cb74 --- /dev/null +++ b/ctt.toml @@ -0,0 +1,10 @@ +[defaults] +project_name = "A new Project" +project_description = "Not much." +author = "Excidion" +author_email = "36995046+Excidion@users.noreply.github.com" +ci = "" + +[output.".ctt/test"] +python_version = "3.10" +use_dvc = false diff --git a/justfile b/justfile new file mode 100644 index 0000000..fe96a59 --- /dev/null +++ b/justfile @@ -0,0 +1,16 @@ +install: + uv sync --all-groups --all-extras + uv run pre-commit install --hook-type pre-push --hook-type post-checkout --hook-type pre-commit + +hooks: + uv run pre-commit run --all-files + +docs: + uv run mkdocs build --strict --site-dir test + rm -rf test + +test: + uv run ctt + rm -rf .ctt + +check: install hooks docs test diff --git a/pyproject.toml b/pyproject.toml index c6766d2..e844c46 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,6 +16,7 @@ dependencies = [ "mkdocs-literate-nav>=0.6.1", "mkdocs-material>=9.5.35", "mkdocstrings[python]>=0.26.1", + "rust-just>=1.46.0", ] [dependency-groups] diff --git a/reproML/README.md.jinja b/reproML/README.md.jinja index c3b73c4..48ea13e 100644 --- a/reproML/README.md.jinja +++ b/reproML/README.md.jinja @@ -11,5 +11,5 @@ For more details take look at the [documentation](#look-at-the-documentation) For more detailed information about the project check out the documentation. Use the following command to run the documentation webserver. ``` -uv run mkdocs serve +just docs ``` diff --git a/reproML/docs/structure.md b/reproML/docs/structure.md index 88ad047..c692784 100644 --- a/reproML/docs/structure.md +++ b/reproML/docs/structure.md @@ -336,17 +336,13 @@ def main(): model = 42 save_model(model, "model") - -if __name__ == "__main__": - main() - ``` Using this will automatically log the start and end of every function you decorate with it. Depening on the log level, you'll even be able to trace arguments and return values. ```bash -$ uv run src/model/train.py -# 2038-01-19 03:14:08,000 INFO __main__.main START -# 2038-01-19 03:14:08,001 DEBUG __main__.main INPUTS: +just run src/model/train.py +# 2038-01-19 03:14:08,000 INFO train.py.main START +# 2038-01-19 03:14:08,001 DEBUG train.py.main INPUTS: # 2038-01-19 03:14:08,002 INFO src.model.io.save_model START # 2038-01-19 03:14:08,003 DEBUG src.model.io.save_model INPUTS: model=42, model_name='model' # 2038-01-19 03:14:08,004 INFO src.model.io.get_path START @@ -355,8 +351,8 @@ $ uv run src/model/train.py # 2038-01-19 03:14:08,007 DEBUG src.model.io.get_path OUTPUT: 'models/model.cldpkl' # 2038-01-19 03:14:08,008 INFO src.model.io.save_model END # 2038-01-19 03:14:08,009 DEBUG src.model.io.save_model OUTPUT: None -# 2038-01-19 03:14:08,010 INFO __main__.main END -# 2038-01-19 03:14:08,011 DEBUG __main__.main OUTPUT: None +# 2038-01-19 03:14:08,010 INFO train.py.main END +# 2038-01-19 03:14:08,011 DEBUG train.py.main OUTPUT: None ``` Forcing yourself to only log via decorators can have some positive side effects: If you feel like you would like to add some logging within a function, this can be an indicator that the code block in question is a candidate to be refactored into a separate function. @@ -370,24 +366,27 @@ All of these parameters should be handed to the code via environment variables. > A litmus test for whether an app has all config correctly factored out of the code is whether the codebase could be made open source at any moment, without compromising any credentials.[^6] -That is why this template comes with [`python-dotenv`](https://pypi.org/project/python-dotenv/) pre-installed. -Simply create a file named `.env` in the project root folder and enter your configration parameters: +To store your secrets create a file named `.env` in the project root folder and enter your configration parameters: ```ini DATABASE_URL=postgres://localhost:1337/dbname DATBASE_USER=myusername DATABASE_PASSWORD=topsneaky ``` +Scripts run via [`just`](https://github.com/casey/just) automatically load these entries as environment variables. +```bash +just run src/script.py +``` In your code you can access these screts like this: ```python +# src/script.py import os -from dotenv import load_dotenv - -load_dotenv() database_url = os.getenv("DATABASE_URL") ``` Thanks to the `.gitignore`, the `.env` file will not get committed into the git repository. +Alternatively you can also use [`python-dotenv`](https://pypi.org/project/python-dotenv/) to load secrets from `.env` files. + ## First steps ### Installing a package diff --git a/reproML/just.sh b/reproML/just.sh new file mode 100755 index 0000000..d7b6f14 --- /dev/null +++ b/reproML/just.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +uv run just $@ diff --git a/reproML/justfile b/reproML/justfile new file mode 100644 index 0000000..35aef42 --- /dev/null +++ b/reproML/justfile @@ -0,0 +1,23 @@ +set dotenv-load + +# shows this list +default: + uv run just --list + +# runs a python script's main method +run SCRIPT *ARGS: + uv run typer {{SCRIPT}} run {{ARGS}} + +# installs all dependecies and pre-commit hooks +install: + uv sync --all-groups --all-extras + uv run pre-commit install --hook-type pre-push --hook-type post-checkout --hook-type pre-commit + +# runs quality checks on all files +check: + uv run pre-commit run --all-files + +# starts the documentation server +docs: + -uv run interrogate + -uv run mkdocs serve diff --git a/reproML/pyproject.toml.jinja b/reproML/pyproject.toml.jinja index 7fd151c..f58522f 100644 --- a/reproML/pyproject.toml.jinja +++ b/reproML/pyproject.toml.jinja @@ -12,7 +12,8 @@ dependencies = [ {%- if use_dvc %} "dvc[{{ remote_type }}]>=3.55.2", {%- endif %} - "python-dotenv>=1.0.1", + "rust-just>=1.46.0", + "typer>=0.24.1", ] [dependency-groups] diff --git a/reproML/src/model/predict.py b/reproML/src/model/predict.py index 3dc03a3..728d90e 100644 --- a/reproML/src/model/predict.py +++ b/reproML/src/model/predict.py @@ -8,7 +8,3 @@ def main(): model = load_model("model") print(model.__class__.__name__) # TODO implement prediction - - -if __name__ == "__main__": - main() diff --git a/reproML/src/model/train.py b/reproML/src/model/train.py index e972539..56f30f9 100644 --- a/reproML/src/model/train.py +++ b/reproML/src/model/train.py @@ -7,7 +7,3 @@ def main(): """Builds a model and saves it to the file system.""" model = None # TODO implement training save_model(model, "model") - - -if __name__ == "__main__": - main() diff --git a/uv.lock b/uv.lock index 13a8b4b..9e74c13 100644 --- a/uv.lock +++ b/uv.lock @@ -1575,6 +1575,7 @@ dependencies = [ { name = "mkdocs-literate-nav" }, { name = "mkdocs-material" }, { name = "mkdocstrings", extra = ["python"] }, + { name = "rust-just" }, ] [package.dev-dependencies] @@ -1597,6 +1598,7 @@ requires-dist = [ { name = "mkdocs-literate-nav", specifier = ">=0.6.1" }, { name = "mkdocs-material", specifier = ">=9.5.35" }, { name = "mkdocstrings", extras = ["python"], specifier = ">=0.26.1" }, + { name = "rust-just", specifier = ">=1.46.0" }, ] [package.metadata.requires-dev] @@ -1747,6 +1749,28 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/eb/76/fbb4bd23dfb48fa7758d35b744413b650a9fd2ddd93bca77e30376864414/ruff-0.8.1-py3-none-win_arm64.whl", hash = "sha256:55873cc1a473e5ac129d15eccb3c008c096b94809d693fc7053f588b67822737", size = 8959621, upload-time = "2024-11-29T03:29:43.977Z" }, ] +[[package]] +name = "rust-just" +version = "1.46.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/26/50/3828817f76e19977a4048c2c8b39a7f48babc21dd9dbed4af2f3c18d4570/rust_just-1.46.0.tar.gz", hash = "sha256:84437481c814577529835132e2cc5fcc35a981c1712e4877cb20fc2f5ec5b2d6", size = 1447346, upload-time = "2026-01-03T02:03:17.948Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/53/0b/a5bf2707b02a484d91f8275efa39f76fe19304f5bfba82293fa4b18608d2/rust_just-1.46.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:7d6d4c67a443f1acb1f78f9ba4b3349fa04f17e8be2d4448b771cdc93a382812", size = 1739556, upload-time = "2026-01-03T02:02:42.835Z" }, + { url = "https://files.pythonhosted.org/packages/3a/ae/40bcd996ccb2fcb0152b5bfde7beaf3840877a8837611421c495b45c82da/rust_just-1.46.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:0caf9b77d30455558d017c9e625ce94c373f88d81656477127727604fa5d36ab", size = 1620974, upload-time = "2026-01-03T02:02:45.341Z" }, + { url = "https://files.pythonhosted.org/packages/62/36/7067e0eaf674ed7c98b35ed50d713c0c885f2d2b57847a627e11502da1b8/rust_just-1.46.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b63521acd91c65164c202ded3ae730130c7fb4377f59cd2f9847b45161c94fd", size = 1703423, upload-time = "2026-01-03T02:02:47.681Z" }, + { url = "https://files.pythonhosted.org/packages/dd/47/3e98182f5e03c48880d647651385863552a3e24cfec5c51d116c06e6f180/rust_just-1.46.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:46a35110c7acf27bdded79cf3bbfea9eb80a53f6f81f374248fe3340584c92e5", size = 1666645, upload-time = "2026-01-03T02:02:50.38Z" }, + { url = "https://files.pythonhosted.org/packages/95/5e/b9badf6e6982e5744f076d12ab911e5ac8b4b03a0674bab4f498ed9d0b4c/rust_just-1.46.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a2407cefc2e5ed4527297747bd5bcb61a885776021cb2438c3a7b118b2cabc2", size = 1847430, upload-time = "2026-01-03T02:02:52.716Z" }, + { url = "https://files.pythonhosted.org/packages/98/10/6916d7c862b99de600a1fd3739d13353c220dfbc0229a0b2c5012c2f801d/rust_just-1.46.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0dab319619f600561b993242312a344953b1ea44637b30257af905a70ce6f568", size = 1926224, upload-time = "2026-01-03T02:02:55.194Z" }, + { url = "https://files.pythonhosted.org/packages/24/93/18bc615e68a80f43105d5e7cc3571e85776aec829ac40faae4de5d5dc2f3/rust_just-1.46.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a3b4c26dd86e5d96047fc0935967f22cb9f49c687767d78b7d3fe511eba39ffa", size = 1902165, upload-time = "2026-01-03T02:02:57.636Z" }, + { url = "https://files.pythonhosted.org/packages/2c/1e/e3c19a24ff64e78a04df0bdf4c61e15c28dcac8b7b5c3a5505eb5749d40a/rust_just-1.46.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acdb496ca26efc508be0e625309b74b1f6316b4f7295d13247c3b791dfa77eb1", size = 1835209, upload-time = "2026-01-03T02:03:00.256Z" }, + { url = "https://files.pythonhosted.org/packages/26/75/0850c38e41025794826165329a097f657152902a785c0579f213b7d61ae6/rust_just-1.46.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:3cf1c32a258f8ee44af877ec271e2eea257923a3303a6d2610b0b5f1523daaab", size = 1719519, upload-time = "2026-01-03T02:03:02.774Z" }, + { url = "https://files.pythonhosted.org/packages/48/85/53c6ee2b9cdbbe1bd43cd0f8096036c29e9e6ba2d3d6344206c490e2ce18/rust_just-1.46.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:657ab85882c124b0fbcd75763035d0dbd20b06c582cc6d4f55017d7b517d5a89", size = 1685664, upload-time = "2026-01-03T02:03:05.514Z" }, + { url = "https://files.pythonhosted.org/packages/33/04/1ad3a66bef0d0f554f0f9971b048bbaf7b3955458f3fda47b48fbf8ff009/rust_just-1.46.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:644b71bfe68863b71ee2618a88dbfd446ea70e2dcfa7b0e5eaec7b6dc4faceca", size = 1838231, upload-time = "2026-01-03T02:03:07.618Z" }, + { url = "https://files.pythonhosted.org/packages/ab/75/33c2e887a68e57b356cda74d325d6ebe406bb72ad8c4e2d067d4fa9b697b/rust_just-1.46.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e9d8a879fb86eb1c7f7f83953999ae4ce53ea4e5c0ca531cf6ff09e1e9335ff7", size = 1900319, upload-time = "2026-01-03T02:03:09.873Z" }, + { url = "https://files.pythonhosted.org/packages/44/30/6b1677aa64a4f69f3ec174b5e2a9a49e0ffd06946d4b4dc8295366fbd9dd/rust_just-1.46.0-py3-none-win32.whl", hash = "sha256:100701de91bded3f6f2bf564d09c2f8e483b8dfb490d1c74008ce3c01ff0ff67", size = 1623463, upload-time = "2026-01-03T02:03:12.343Z" }, + { url = "https://files.pythonhosted.org/packages/64/61/97ad7a1ea67b9485404b18150c258015842cf116a1ce626421863fd8f0e1/rust_just-1.46.0-py3-none-win_amd64.whl", hash = "sha256:ccaf8e473f64f5c815b0039e883a1feaf5634b9cdffd1dbff9e5fde77b5926f4", size = 1801103, upload-time = "2026-01-03T02:03:15.256Z" }, +] + [[package]] name = "six" version = "1.17.0"