generated from jarq6c/miniconda-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from jarq6c/docker
Update package template to use docker
- Loading branch information
Showing
17 changed files
with
176 additions
and
90 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
**/*.egg-info | ||
**/__pycache__ | ||
env/ | ||
venv/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# syntax=docker/dockerfile:1 | ||
FROM python:3.10-slim AS builder | ||
RUN python3 -m pip install -U pip wheel setuptools | ||
WORKDIR /project/install | ||
COPY requirements.py requirements.py | ||
COPY setup.cfg setup.cfg | ||
RUN python3 requirements.py > requirements.txt | ||
RUN python3 -m pip install -r requirements.txt | ||
|
||
FROM builder | ||
COPY EXCLUDE EXCLUDE | ||
COPY LICENSE LICENSE | ||
COPY MANIFEST.in MANIFEST.in | ||
COPY pyproject.toml pyproject.toml | ||
COPY README.md README.md | ||
COPY src src | ||
COPY tests tests | ||
RUN python3 -m pip install .[develop] | ||
ENTRYPOINT [ "/usr/local/bin/python3", "-m", "build"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,6 @@ | ||
*__pycache__* | ||
*.py[cod] | ||
*$py.class | ||
miniconda3/* | ||
sha256sum.txt | ||
Miniconda3-py* | ||
*.pytest_cache* | ||
env/* | ||
venv/* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,34 +1,20 @@ | ||
REPOSITORY=https://repo.anaconda.com/miniconda | ||
INSTALLER=Miniconda3-py38_4.9.2-Linux-x86_64.sh | ||
HASH=1314b90489f154602fd794accfc90446111514a5a72fe1f71ab83e07de9504a7 | ||
HASHFILE=sha256sum.txt | ||
PYENV=miniconda3 | ||
PYTHON=$(PYENV)/bin/python3 | ||
TAG=my-tag | ||
APP=my-cli | ||
ARGUMENTS=-c 5 -r 7 | ||
|
||
.PHONY: develop tests build checksum clean | ||
.PHONY: build setup run tests | ||
|
||
develop: $(PYENV)/bin/activate | ||
$(PYTHON) -m pip install -e .[develop] | ||
build: tests | ||
docker run --name $(TAG)-builder $(TAG) | ||
docker cp $(TAG)-builder:/project/install/dist $(PWD)/dist | ||
docker stop $(TAG)-builder | ||
docker rm $(TAG)-builder | ||
|
||
tests: develop | ||
$(PYTHON) -m pytest -s | ||
setup: | ||
docker build -t $(TAG) . | ||
|
||
build: $(PYENV)/bin/activate | ||
$(PYTHON) -m build | ||
run: setup | ||
docker run --entrypoint "/usr/local/bin/$(APP)" --rm $(TAG) $(ARGUMENTS) | ||
|
||
$(PYENV)/bin/activate: checksum | ||
test -d $(PYENV) || bash ./$(INSTALLER) -b -p $(PYENV) | ||
$(PYTHON) -m pip install -U pip wheel setuptools build | ||
touch $(PYENV)/bin/activate | ||
|
||
checksum: $(INSTALLER) $(HASHFILE) | ||
sha256sum -c $(HASHFILE) | ||
|
||
$(INSTALLER): | ||
wget $(REPOSITORY)/$(INSTALLER) | ||
|
||
$(HASHFILE): | ||
echo "$(HASH) $(INSTALLER)" > $(HASHFILE) | ||
|
||
clean: | ||
rm -rf dist/ $(PYENV) $(HASHFILE) $(INSTALLER) | ||
tests: setup | ||
docker run --entrypoint "/usr/local/bin/pytest" --rm $(TAG) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,44 @@ | ||
# Generic Python Project | ||
|
||
This template can be used as a starting point for building distributable Python packages. It includes a Makefile with targets to build a wheel and a reproducible Python virtual environment based on miniconda. To learn more about packaging in Python see the [Python Packaging User Guide](https://packaging.python.org/). | ||
This template can be used as a starting point for building distributable Python packages. It includes a Makefile with targets to setup, run, test, and build a final installable PyPI compatible package. To learn more about packaging in Python see the [Python Packaging User Guide](https://packaging.python.org/). | ||
|
||
## Build | ||
|
||
```bash | ||
$ make | ||
``` | ||
Running `make` in this directory will build the default target "build". The chain of dependencies for the default target includes targets that retrieve a miniconda installation script for Linux and creates a stand-alone miniconda environment with the required dependencies. The name of the miniconda environment is `miniconda3` and can be activated as normal using `source miniconda3/bin/activate` and deactivated using `conda deactivate`. The build target runs `python -m build` which collects the required files and packages in `src` and generates an install wheel under `dist`. | ||
|
||
To start from scratch run clean: | ||
```bash | ||
$ make clean | ||
``` | ||
Running `make` in this directory will build the default target "build". The chain of dependencies for the default target includes targets that build a docker image with development dependencies. This target will also run `pytest` and `build`, and copy the resulting `dist` directory with `.whl` and `.tar.gz` packages into the currect directory. | ||
|
||
## Installation | ||
|
||
After running build, you can install the default package by running | ||
|
||
``` | ||
miniconda3/bin/python -m pip install dist/hello-0.1.0-py3-none-any.whl | ||
python -m pip install dist/my_package-0.1.0-py3-none-any.whl | ||
``` | ||
|
||
...or, assuming you have an API token and a valid [`.pypirc` file](https://packaging.python.org/en/latest/specifications/pypirc/) you can upload and install your package from PyPI with | ||
|
||
```bash | ||
python3 -m twine upload dist/* | ||
python3 -m pip install my_package | ||
``` | ||
|
||
## Testing | ||
See [Packaging Python Projects](https://packaging.python.org/en/latest/tutorials/packaging-projects/) for more details on uploading your package. | ||
|
||
An example test is in `tests/test_hello.py`. This test uses `pytest` to test the `greet` function. You can read more about using `pytest` at the [PyTest Documentation](https://docs.pytest.org/). To run all tests just use: | ||
## Other targets | ||
|
||
```bash | ||
$ make setup | ||
``` | ||
miniconda3/bin/python -m pytest | ||
This target builds the docker image and is required by all other targets. | ||
|
||
```bash | ||
$ make run | ||
``` | ||
This target runs the CLI application from a docker container indicated in `setup.cfg` with the arguments specified by `ARGUMENTS` in the `Makefile`. This target is mainly a convenience and reference for users. CLI arguments are more easily changed by running this underlying command directly from the command prompt. | ||
|
||
```bash | ||
$ make tests | ||
``` | ||
This target runs `pytest` on the code in the image created by "setup" in a docker container. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# removing __version__ import will cause build to fail. | ||
# see: https://github.com/pypa/setuptools/issues/1724#issuecomment-627241822 | ||
from ._version import __version__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
__version__ = "0.1.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import click | ||
import pandas as pd | ||
from my_package.my_module import make_dataframe | ||
from my_package._version import __version__ | ||
|
||
@click.command() | ||
@click.option("-c", "--ncols", "ncols", nargs=1, type=int, help="Number of columns", default=3) | ||
@click.option("-r", "--nrows", "nrows", nargs=1, type=int, help="Number of rows", default=4) | ||
def run( | ||
ncols: int, | ||
nrows: int | ||
) -> None: | ||
"""Generate a random dataframe and print to screen. | ||
Example: | ||
my-cli -c 3 -r 6 | ||
""" | ||
# Get a dataframe | ||
df = make_dataframe(ncols=ncols, nrows=nrows) | ||
|
||
print(f"my_package {__version__}") | ||
with pd.option_context("display.precision", 2): | ||
print(df) | ||
|
||
if __name__ == "__main__": | ||
run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
"""Generic example module""" | ||
from string import ascii_uppercase | ||
import numpy as np | ||
import pandas as pd | ||
|
||
def make_dataframe(ncols: int = 4, nrows: int = 5) -> pd.DataFrame: | ||
""" | ||
Generate a pandas.DataFrame of random data with ncols columns and | ||
nrows index length. | ||
Parameters | ||
---------- | ||
ncols: int, optional, default 4 | ||
Number of columns for resulting dataframe. | ||
nrows: int, optional, default 5 | ||
Number of rows of resulting dataframe. | ||
Returns | ||
------- | ||
pandas.DataFrame with ncols columns and index length nrows. | ||
""" | ||
# Return dataframe | ||
return pd.DataFrame({c: np.random.random(nrows) for c in ascii_uppercase[:ncols]}) |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import pytest | ||
from click.testing import CliRunner | ||
from my_package.cli import run | ||
from my_package._version import __version__ | ||
|
||
@pytest.fixture | ||
def runner_result(): | ||
runner = CliRunner() | ||
return runner.invoke(run) | ||
|
||
def test_hello_world(runner_result): | ||
# Check exit code | ||
assert runner_result.exit_code == 0 | ||
|
||
# Check first line of output | ||
first_line = runner_result.output.split("\n")[0] | ||
assert first_line == f"my_package {__version__}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import pytest | ||
import my_package | ||
from my_package import my_module | ||
|
||
def test_package_version(): | ||
# Check version | ||
assert my_package.__version__ == "0.1.0" | ||
|
||
@pytest.fixture | ||
def default_dataframe(): | ||
return my_module.make_dataframe() | ||
|
||
def test_default_dataframe(default_dataframe): | ||
# Test defaults | ||
assert len(default_dataframe.columns) == 4 | ||
assert len(default_dataframe.index) == 5 |