Skip to content

Commit

Permalink
feat: Update jinja templates, add versions to cookiecutter.json as hi…
Browse files Browse the repository at this point in the history
…dden variables
  • Loading branch information
saattrupdan committed Jul 16, 2024
1 parent 6645ba8 commit 3e671c6
Show file tree
Hide file tree
Showing 14 changed files with 328 additions and 204 deletions.
70 changes: 8 additions & 62 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
<a href="https://github.com/alexandrainst/{{ cookiecutter.project_name }}"><img src="https://github.com/alexandrainst/alexandra-ml-template/blob/main/%7B%7Bcookiecutter.project_name%7D%7D/gfx/alexandra_logo.png" width="239" height="175" align="right" /></a>
<a href="https://github.com/alexandrainst/{{ cookiecutter.project_name }}">
<img
src="https://github.com/alexandrainst/{{ cookiecutter.project_name }}/raw/main/gfx/alexandra_logo.png"
width="239"
height="175"
align="right"
/>
</a>
# Alexandra Institute Machine Learning Repository Template

This repository is a template for a Python-based data science project within the
Expand Down Expand Up @@ -56,64 +63,3 @@ browser.

The cookiecutter allows the user to choose between `poetry` and `pip` for managing
dependencies. In both cases, `pyproject.toml` will be used for all dependencies.


## Tools used in this project
* [Poetry](https://towardsdatascience.com/how-to-effortlessly-publish-your-python-package-to-pypi-using-poetry-44b305362f9f): Dependency management
* [hydra](https://hydra.cc/): Manage configuration files
* [pre-commit plugins](https://pre-commit.com/): Automate code reviewing formatting
* [pdoc](https://github.com/pdoc3/pdoc): Automatically create an API documentation for your project


## Project Structure
```
.
├── .devcontainer
│   └── devcontainer.json
├── .github
│   └── workflows
│   ├── ci.yaml
│   └── docs.yaml
├── .gitignore
├── .pre-commit-config.yaml
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── README.md
├── config
│   ├── __init__.py
│   ├── config.yaml
│   └── hydra
│   └── job_logging
│   └── custom.yaml
├── data
│   ├── final
│   │   └── .gitkeep
│   ├── processed
│   │   └── .gitkeep
│   └── raw
│   └── .gitkeep
├── docs
│   └── .gitkeep
├── gfx
│   ├── .gitkeep
│   └── alexandra_logo.png
├── makefile
├── models
│   └── .gitkeep
├── notebooks
│   └── .gitkeep
├── poetry.toml
├── pyproject.toml
├── src
│   ├── scripts
│   │   ├── fix_dot_env_file.py
│   │   └── your_script.py
│   └── {{cookiecutter.project_name}}
│   ├── __init__.py
│   └── your_module.py
└── tests
├── __init__.py
└── test_dummy.py
```
22 changes: 22 additions & 0 deletions cookiecutter.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,27 @@
"open_source": "Is this a public open source project? (y/n, default: n)",
"python_version": "3.11",
"dependency_manager": "Which dependency manager do you use? (pip/poetry, default: poetry)",
"pre_commit_hooks": "Do you want to use pre-commit hooks? (y/n, default: y)",
"_poetry_version": "1.8.2",
"_poetry_core_version": "1.0.0",
"_setuptools_version": "68.0.0",
"_hydra_version": "1.3.2",
"_pytest_version": "8.1.1",
"_pytest_cov_version": "4.1.0",
"_pre_commit_version": "3.6.2",
"_pdoc_version": "14.1.0",
"_readme_coverage_badger_version": "0.1.2",
"_click_version": "8.1.7",
"_ruff_version": "0.3.2",
"_mypy_version": "1.9.0",
"_nbstripout_version": "0.7.1",
"_coverage_version": "5.5",
"_toml_version": "0.10.2",
"_pygrep_hooks_version": "1.10.0",
"_pre_commit_hooks_version": "4.6.0",
"_checkout_action_version": "4",
"_setup_python_action_version": "5",
"_pre_commit_action_version": "3.0.1",
"_deploy_pages_action_version": "4",
"_copy_without_render": []
}
45 changes: 32 additions & 13 deletions {{cookiecutter.project_name}}/.github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,32 +13,51 @@ on:
jobs:
code-check:
if: github.event.pull_request.draft == false
runs-on: {{'ubuntu-latest' if cookiecutter.open_source == 'y' else '[self-hosted, self-hosted-ubuntu-latest]'}}
{% if cookiecutter.open_source == 'y' -%}
runs-on: ubuntu-latest
{% else -%}
runs-on: [self-hosted, self-hosted-ubuntu-latest]
{% endif -%}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
- uses: pre-commit/action@v3.0.1
- uses: actions/checkout@v{{ cookiecutter._checkout_action_version }}
- uses: actions/setup-python@v{{ cookiecutter._setup_python_action_version }}
- uses: pre-commit/action@v{{ cookiecutter._pre_commit_action_version }}

pytest:
if: github.event.pull_request.draft == false
strategy:
matrix:
os: [{{'windows-latest, macos-latest, ubuntu-latest' if cookiecutter.open_source == 'y' else 'self-hosted-ubuntu-latest'}}]
{% if cookiecutter.open_source == 'y' -%}
os: [windows-latest, macos-latest, ubuntu-latest]
{% else -%}
os: [self-hosted-ubuntu-latest]
{% endif -%}
python-version: ["{{ cookiecutter.python_version }}"]
runs-on: {% raw %}${{ matrix.os }}{% endraw %}
steps:
- uses: actions/checkout@v4
{{'\n - name: Install Poetry\n run: pipx install poetry==1.8.2\n\n' if cookiecutter.dependency_manager != 'pip'}}
- uses: actions/checkout@v{{ cookiecutter._checkout_action_version }}
{% if cookiecutter.dependency_manager != 'pip' -%}
- name: Install Poetry
run: pipx install poetry=={{ cookiecutter._poetry_version }}
{% endif -%}
- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v{{ cookiecutter._setup_python_action_version }}
with:
python-version: {% raw %}${{ matrix.python-version }}{% endraw %}
cache: {{'"poetry"' if cookiecutter.dependency_manager != 'pip' else 'pip'}}
cache: {{'poetry' if cookiecutter.dependency_manager != 'pip' else 'pip'}}

- name: Install Dependencies
run: |
{{'poetry env use ' if cookiecutter.dependency_manager != 'pip' else 'python'}}{% raw %}"${{ matrix.python-version }}"{% endraw %}{{'' if cookiecutter.dependency_manager != 'pip' else ' -m venv .venv'}}
{{'poetry install' if cookiecutter.dependency_manager != 'pip' else '. .venv/bin/activate && pip install .[dev]'}}
{% if cookiecutter.dependency_manager != 'pip' -%}
poetry env use {% raw %}"${{ matrix.python-version }}"{% endraw %}
poetry install
{% else -%}
python3 -m venv .venv
. .venv/bin/activate && pip install .[dev]
{% endif %}
- name: Test with pytest
run: {{'poetry run' if cookiecutter.dependency_manager != 'pip' else '. .venv/bin/activate && python -m'}} pytest
{% if cookiecutter.dependency_manager != 'pip' -%}
run: poetry run pytest
{% else -%}
run: . .venv/bin/activate && python -m pytest
{% endif -%}
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,32 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
{{'\n - name: Install Poetry\n run: pip3 install poetry==1.8.2\n' if cookiecutter.dependency_manager != 'pip' else ''}}
- uses: actions/checkout@v{{ cookiecutter._checkout_action_version }}
{% if cookiecutter.dependency_manager != 'pip' -%}
- name: Install Poetry
run: pip3 install poetry=={{ cookiecutter._poetry_version }}
{% endif -%}
- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v{{ cookiecutter._setup_python_action_version }}
with:
python-version: "{{ cookiecutter.python_version }}"
cache: {{'"poetry"' if cookiecutter.dependency_manager != 'pip' else 'pip'}}

- name: Install Dependencies
run: |
{{'poetry env use ' if cookiecutter.dependency_manager != 'pip' else 'python'}}"{{ cookiecutter.python_version }}"{{'' if cookiecutter.dependency_manager != 'pip' else ' -m venv .venv'}}
{{'poetry install --no-interaction --no-cache' if cookiecutter.dependency_manager != 'pip' else '. .venv/bin/activate && python -m pip install .[dev]'}}

{% if cookiecutter.dependency_manager != 'pip' -%}
poetry env use "{{ cookiecutter.python_version }}"
poetry install --no-interaction --no-cache
{% else -%}
python3 -m venv .venv
. .venv/bin/activate && python -m pip install .[dev]
{% endif -%}
- name: Build documentation
run: {{'poetry run' if cookiecutter.dependency_manager != 'pip' else '. .venv/bin/activate && python -m'}} pdoc --docformat google src/{{ cookiecutter.project_name }} -o docs

{% if cookiecutter.dependency_manager != 'pip' -%}
run: poetry run pdoc --docformat google src/{{ cookiecutter.project_name }} -o docs
{% else -%}
run: . .venv/bin/activate && python -m pdoc --docformat google src/{{ cookiecutter.project_name }} -o docs
{% endif -%}
- name: Compress documentation
run: tar --directory docs/ -hcf artifact.tar .

Expand All @@ -53,4 +63,4 @@ jobs:
url: {% raw %}${{ steps.deployment.outputs.page_url }}{% endraw %}
steps:
- id: deployment
uses: actions/deploy-pages@v4
uses: actions/deploy-pages@v{{ cookiecutter._deploy_pages_action_version }}
10 changes: 5 additions & 5 deletions {{cookiecutter.project_name}}/.pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
repos:
- repo: https://github.com/pre-commit/pygrep-hooks
rev: v1.10.0
rev: v{{ cookiecutter._pygrep_hooks_version }}
hooks:
- id: python-use-type-annotations
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
rev: v{{ cookiecutter._pre_commit_hooks_version }}
hooks:
- id: end-of-file-fixer
- id: trailing-whitespace
- id: debug-statements
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.5.2
rev: v{{ cookiecutter._ruff_version }}
hooks:
- id: ruff
args:
Expand All @@ -26,11 +26,11 @@ repos:
- pyi
- jupyter
- repo: https://github.com/kynan/nbstripout
rev: 0.7.1
rev: {{ cookiecutter._nbstripout_version }}
hooks:
- id: nbstripout
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.10.1
rev: v{{ cookiecutter._mypy_version }}
hooks:
- id: mypy
args:
Expand Down
22 changes: 19 additions & 3 deletions {{cookiecutter.project_name}}/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
FROM python:{{ cookiecutter.python_version }}-slim-bookworm
{{'\n# Install poetry\nRUN pip install "poetry==1.8.2"\n' if cookiecutter.dependency_manager != 'pip'}}

{%- if cookiecutter.dependency_manager != 'pip' %}

# Install Poetry
RUN pip install "poetry=={{ cookiecutter._poetry_version }}"
{%- endif %}

# Move the files into the container
WORKDIR /project
COPY . /project

# Install dependencies
{{'RUN poetry env use python' if cookiecutter.dependency_manager != 'pip'}}{{cookiecutter.python_version if cookiecutter.dependency_manager != 'pip'}}{{'\nRUN poetry install --no-interaction --no-cache --without dev' if cookiecutter.dependency_manager != 'pip' else 'RUN pip install .'}}
{% if cookiecutter.dependency_manager != 'pip' -%}
RUN poetry env use python {{ cookiecutter.python_version }}
RUN poetry install --no-interaction --no-cache --without dev
{%- else -%}
RUN python3 -m venv .venv
RUN . .venv/bin/activate && pip install .
{%- endif %}

# Run the script
CMD {{'poetry run ' if cookiecutter.dependency_manager != 'pip'}}python src/scripts/your_script.py
{% if cookiecutter.dependency_manager != 'pip' -%}
CMD poetry run python src/scripts/main.py
{%- else -%}
CMD . .venv/bin/activate && python src/scripts/main.py
{%- endif %}
61 changes: 47 additions & 14 deletions {{cookiecutter.project_name}}/README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
<a href="https://github.com/alexandrainst/{{ cookiecutter.project_name }}"><img src="https://github.com/alexandrainst/{{ cookiecutter.project_name }}/raw/main/gfx/alexandra_logo.png" width="239" height="175" align="right" /></a>
<a href="https://github.com/alexandrainst/{{ cookiecutter.project_name }}">
<img
src="https://github.com/alexandrainst/{{ cookiecutter.project_name }}/raw/main/gfx/alexandra_logo.png"
width="239"
height="175"
align="right"
/>
</a>
# {{cookiecutter.project_name}}

{{cookiecutter.project_description}}

______________________________________________________________________
[![Code Coverage](https://img.shields.io/badge/Coverage-0%25-red.svg)](https://github.com/alexandrainst/{{cookiecutter.project_name}}/tree/main/tests){{'\n[![Documentation](https://img.shields.io/badge/docs-passing-green)](https://alexandrainst.github.io/' if cookiecutter.open_source == 'y'}}{{cookiecutter.project_name if cookiecutter.open_source == 'y'}}{{'/' if cookiecutter.open_source == 'y'}}{{ cookiecutter.project_name if cookiecutter.open_source == 'y'}}{{'.html)\n[![License](https://img.shields.io/github/license/alexandrainst/' if cookiecutter.open_source == 'y'}}{{cookiecutter.project_name if cookiecutter.open_source == 'y'}}{{')](https://github.com/alexandrainst/' if cookiecutter.open_source == 'y'}}{{cookiecutter.project_name if cookiecutter.open_source == 'y'}}{{'/blob/main/LICENSE)\n[![LastCommit](https://img.shields.io/github/last-commit/alexandrainst/' if cookiecutter.open_source == 'y'}}{{cookiecutter.project_name if cookiecutter.open_source == 'y'}}{{')](https://github.com/alexandrainst/' if cookiecutter.open_source == 'y'}}{{cookiecutter.project_name if cookiecutter.open_source == 'y'}}{{'/commits/main)\n[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.0-4baaaa.svg)](https://github.com/alexandrainst/' if cookiecutter.open_source == 'y'}}{{cookiecutter.project_name if cookiecutter.open_source == 'y'}}{{'/blob/main/CODE_OF_CONDUCT.md)' if cookiecutter.open_source == 'y'}}


Developer(s):
[![Code Coverage](https://img.shields.io/badge/Coverage-0%25-red.svg)](https://github.com/alexandrainst/{{cookiecutter.project_name}}/tree/main/tests)
{% if cookiecutter.open_source == 'y' -%}
[![Documentation](https://img.shields.io/badge/docs-passing-green)](https://alexandrainst.github.io/{{cookiecutter.project_name}}/{{cookiecutter.project_name}}.html)
[![License](https://img.shields.io/github/license/alexandrainst/{{cookiecutter.project_name}})](https://github.com/alexandrainst/{{cookiecutter.project_name}}/blob/main/LICENSE)
[![LastCommit](https://img.shields.io/github/last-commit/alexandrainst/{{cookiecutter.project_name}})](https://github.com/alexandrainst/{{cookiecutter.project_name}}/commits/main)
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.0-4baaaa.svg)](https://github.com/alexandrainst/{{cookiecutter.project_name}}/blob/main/CODE_OF_CONDUCT.md)
{% endif %}
Developer:

- {{cookiecutter.author_name}} ({{cookiecutter.email}})

Expand All @@ -18,25 +29,45 @@ Developer(s):

1. Run `make install`, which sets up a virtual environment and all Python dependencies therein.
2. Run `source .venv/bin/activate` to activate the virtual environment.
3. (Optional) Run `make install-pre-commit`, which installs pre-commit hooks for linting, formatting and type checking.{{'\n4. (Optional) Run `make add-rag` to add RAG functionality from [ragger](https://github.com/alexandrainst/ragger).' if cookiecutter.open_source != 'y'}}

3. (Optional) Run `make install-pre-commit`, which installs pre-commit hooks for linting, formatting and type checking.
{% if cookiecutter.open_source != 'y' -%}
4. (Optional) Run `make add-rag` to add RAG functionality from [ragger](https://github.com/alexandrainst/ragger).
{% endif %}
### Adding and Removing Packages

To install new PyPI packages, run:
```
{{'poetry add' if cookiecutter.dependency_manager != 'pip' else 'pip install'}} <package-name>
{% if cookiecutter.dependency_manager != 'pip' -%}
poetry add <package-name>
{% else -%}
pip install <package-name>
{% endif -%}
```

To remove them again, run:
```
{{'poetry remove' if cookiecutter.dependency_manager != 'pip' else 'pip uninstall'}} <package-name>
```{{'\n\nTo freeze dependencies into pyproject.toml, run:\n```\nmake freeze\n```' if cookiecutter.dependency_manager == 'pip'}}
{% if cookiecutter.dependency_manager != 'pip' -%}
poetry remove <package-name>
{% else -%}
pip uninstall <package-name>
{% endif -%}
```
{% if cookiecutter.dependency_manager == 'pip' -%}
To freeze dependencies into `requirements.txt`, run:
```
make freeze
```
{% endif %}
To show all installed packages, run:
```
{{'poetry show' if cookiecutter.dependency_manager != 'pip' else 'pip list'}}
{% if cookiecutter.dependency_manager != 'pip' -%}
poetry show
{% else -%}
pip list
{% endif -%}
```


## All Built-in Commands

The project includes the following convenience commands:
Expand All @@ -47,8 +78,10 @@ The project includes the following convenience commands:
- `make type-check`: Type check the code using `mypy`.
- `make test`: Run tests using `pytest` and update the coverage badge in the readme.
- `make docker`: Build a Docker image and run the Docker container.
{% if cookiecutter.open_source != 'y' -%}
- `make add-rag`: Add RAG functionality from [ragger](https://github.com/alexandrainst/ragger).
- `make update-rag`: Update RAG functionality from [ragger](https://github.com/alexandrainst/ragger).
{% endif -%}
- `make docs`: Generate HTML documentation using `pdoc`.
- `make view-docs`: View the generated HTML documentation in a browser.
- `make tree`: Show the project structure as a tree.
Expand Down Expand Up @@ -94,8 +127,8 @@ file is also a Python script, rather than a module.
### Docker Setup

A Dockerfile is included in the new repositories, which by default runs
`src/scripts/your_script.py`. You can build the Docker image and run the Docker
container by running `make docker`.
`src/scripts/main.py`. You can build the Docker image and run the Docker container by
running `make docker`.

### Automatic Documentation

Expand Down
2 changes: 1 addition & 1 deletion {{cookiecutter.project_name}}/config/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
"""Config files to be used with hydra."""
"""Config files to be used with Hydra."""
Loading

0 comments on commit 3e671c6

Please sign in to comment.