Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
bsweger committed Jul 19, 2024
1 parent 5025dd4 commit 82e826e
Show file tree
Hide file tree
Showing 15 changed files with 609 additions and 0 deletions.
25 changes: 25 additions & 0 deletions .github/workflows/pythonapp-workflow.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: run-code-checks
on: [push]
jobs:
run-checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
cache: 'pip'
- name: install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements/requirements-dev.txt -e .
- name: lint
run: |
ruff check .
- name: type check
run: |
mypy .
- name: run tests
run: |
pytest
171 changes: 171 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
**/.DS_Store

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
Pipfile.lock

# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
poetry.lock

# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml

# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
.pdm-python
.pdm-build/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site
# ruff
**/.ruff_cache

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

# IDE settings
.idea/
.vscode
29 changes: 29 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.5.3
hooks:
# Run the linter.
- id: ruff
args: [ --fix ]
# Run the formatter.
- id: ruff-format
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: trailing-whitespace
- id: check-yaml
args: [--allow-multiple-documents]
- id: debug-statements
- id: detect-aws-credentials
args: [--allow-missing-credentials]
- id: detect-private-key
- repo: https://github.com/pre-commit/mirrors-mypy
rev: 'v1.10.1' # Use the sha / tag you want to point at
hooks:
- id: mypy
additional_dependencies: [types-all]
- repo: https://github.com/codespell-project/codespell
rev: v2.3.0
hooks:
- id: codespell
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.12
150 changes: 150 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
# reichlab-python-template

[REPLACE WITH A DESCRIPTION OF YOUR PROJECT]

A Python template for Reich Lab projects.

This repo contains a Python package with minimal functionality. It serves as a starting point for new projects (it can be selected as the template when creating a new repo in the Reich Lab org).

There as some opinionated choices here (explained below) which people should override as needed. The main goal is to have a consistent starting point to get up and running with a new Python code base.

## Getting started

[REMOVE THIS SECTION AFTER FOLLOWING THE INSTRUCTIONS BELOW]

If you're using this repo as a template for a new project, make the following changes:

1. Replace all instances of `reichlab-python-template` with the name of your repo/project.

2. Replace all instances of `reichlab_python_template` with the name of your module (remember that Python module names cannot contain hyphens).

3. Update [`pyproject.toml`](pyproject.toml). This file is required and will describe several aspects of your project. `pyproject.toml` replaces `setup.py` and is described in detail on [Python's packaging website](https://packaging.python.org/en/latest/guides/writing-pyproject-toml/).

4. Follow the _Setup for local development_ instructions below to ensure that everything works as expected.


## Installing and running the package (no development)

To install this package via pip:

```bash
pip install git+[GITHUB LINK TO YOUR REPO]
```

To run it:
```bash
reichlab_python_template
```

## Setup for local development

The steps below are for setting up a local development environment. This process entails more than just installing the package,
because we need to ensure that all developers have a consistent, reproducible environment.

### Assumptions

Developers will be using a Python virtual environment that:

- is based on the Python version specified in [.python-version](.python-version).
- contains the dependency versions specified in the "lockfile" (in this case [requirements/requirements-dev.txt](requirements/requirements-dev.txt)).
- contains the package installed in ["editable" mode](https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/#working-in-development-mode).

### Setup steps

1. Clone this repository

2. Change to the repo's root directory:

```bash
cd reichlab-python-template
```

3. Make sure the correct version of Python is currently active, and create a Python virtual environment:

```bash
python -m venv .venv
```

4. Activate the virtual environment:

```bash
# MacOs/Linux
source .venv/bin/activate
# Windows
.venv\Scripts\activate
```

5. Install the package dependencies and install the package in editable mode:

```bash
python -m pip install -r requirements/requirements-dev.txt && python -m pip install -e .
```

6. **Optional:** if you use [`pre-commit`](https://pre-commit.com/) in your workflow to automate code formatting and other tasks, [install it](https://pre-commit.com/#install). Otherwise, delete [`.pre-commit-config.yaml`](.pre-commit-config.yaml).

7. Run the test suite to confirm that everything is working:

```bash
python -m pytest
```

## Development workflow

Because the package is installed in "editable" mode, you can run the code as though it were a normal Python package, while also
being able to make changes and see them immediately.

### Updating dependencies

Prerequisites:
- [`uv`](https://github.com/astral-sh/uv?tab=readme-ov-file#getting-started)

**Note:** using [`pipx`](https://pipx.pypa.io/stable/) (instead of pip) to install `uv` is a handy way to ensure that uv is available for all of the Python environments on your machine.

The "lockfile" for this project is simply an annotated requirements.txt that is generated by [uv](https://github.com/astral-sh/uv) (uv is a replacement for [pip-compile](https://pypi.org/project/pip-tools/), which
could also be used). There's also a requirements-dev.txt file that contains dependencies needed for development (_e.g._, pytest).
While it's possible to use `pip freeze` to generate a detailed lockfile without a third-party tool like `uv`, the output of `pip freeze` doesn't distinguish between direct and indirect dependencies. This distinction probably doesn't matter for a small project, but on a large project, understanding the dependency graph is critical for resolving conflicts.

Additionally, `uv` (and `pip-compile`) are able to use the list of high-level dependencies in `pyproject.toml` to generate a detailed requirements.txt file, which is a good workflow for keeping everything in sync.

To add a dependency to the project:

1. Add the dependency to the `[dependencies]` section of `pyproject.toml` (or to the `dev` section of `[project.optional-dependencies]`, if it's a development dependency). Don't pin a specific version, since that will make it harder for people to install the package.

2. Generate updated requirements files:

```bash
uv pip compile pyproject.toml -o requirements/requirements.txt && uv pip compile pyproject.toml --extra dev -o requirements/requirements-dev.txt
```

3. Update project dependencies:

**Note:** This package was originally developed on MacOS. If you have trouble installing the dependencies. `uv pip sync` has a [`--python-platform` flag](https://github.com/astral-sh/uv?tab=readme-ov-file#multi-platform-resolution) that can be used to specify the platform.

```bash
# note: requirements-dev.txt contains the base requirements AND the dev requirements
#
# using pip
python -m pip install -r requirements/requirements-dev.txt
#
# alternately, you can use uv to install the dependencies: it is faster and has a
# a handy sync option that will cleanup unused dependencies
uv pip sync requirements/requirements-dev.txt
## Opinionated notes on Python tooling
[REMOVE THIS SECTION]
The Python ecosystem is overwhelming! Current opinionated preferences, subject to change:
- To install and manage various versions of Python: [pyenv](https://github.com/pyenv/pyenv) + a local .python-version file
- To install Python packages that are available from anywhere on the machine, regardless of which Python environment is activated: [pipx](https://pipx.pypa.io/stable/)
- To create and manage Python virtual environments: [venv](https://docs.python.org/3/library/venv.html).
- I like having the environment packages right there in the project directory
- Everything single third-party tool for managing virtual environments (_e.g._, poetry, PDM, pipenv) does _too much_ and gets in my way
- To generate requirements files from `pyproject.toml`: ['uv'](https://github.com/astral-sh/uv?tab=readme-ov-file#getting-started). I don't usually recommend things this new, but it's orders of magnitude faster than `pip-compile`.
- To install dependencies: uv again (again, mostly due to speed; good old pip is another fine option)
- Logging: [structlog](https://www.structlog.org/en/stable/). I recently stopped fighting Python's built-in logging module and haven't looked back.
- Linting and formatting: [ruff](https://github.com/astral-sh/ruff) because it does both and is fast.
- Pre-commit hooks: [pre-commit](https://pre-commit.com/).
Loading

0 comments on commit 82e826e

Please sign in to comment.