Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch to Poetry for dependency management #605

Merged
merged 36 commits into from
Sep 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
446df11
Add initial pyproject.toml
juhoinkinen Aug 9, 2022
11a4a1a
Move pytest configuration to pyproject.toml
juhoinkinen Aug 9, 2022
d82f2ba
Add forgotten dependencies for tests
juhoinkinen Aug 10, 2022
aba68e7
Delete unnecessary setup.py and MANIFEST.in files
juhoinkinen Aug 10, 2022
3602cbc
Make bumpversion update version string in pyproject.toml
juhoinkinen Aug 10, 2022
a6d41ad
Update README.md for Poetry usage in development installations
juhoinkinen Aug 10, 2022
54e058f
Ignore poetry.lock in git
juhoinkinen Aug 10, 2022
2793cf2
Update GH Actions to use Poetry
juhoinkinen Aug 11, 2022
09f5b00
Use cache feature of setup-python action for Poetry; install Poetry b…
juhoinkinen Aug 11, 2022
7a706a5
Upgrade setup-python action
juhoinkinen Aug 11, 2022
2f9ef42
Try to speed up by using --no-root flag in extras installations; drop…
juhoinkinen Aug 12, 2022
3604e22
Cache Poetry installation
juhoinkinen Aug 12, 2022
f2f2664
Install the annif package itself
juhoinkinen Aug 12, 2022
ffadea3
Do not install the annif package itself when installing extras
juhoinkinen Aug 12, 2022
a959729
Use only one "poetry install" command to speed up runs
juhoinkinen Aug 12, 2022
a1acd39
Update authors and maintainers metadata
juhoinkinen Aug 15, 2022
477bd64
Pin flake8 version to 4.*
juhoinkinen Aug 16, 2022
99348be
More verbose poetry install for getting info about slow steps
juhoinkinen Aug 17, 2022
0067a15
Try to speed dependency resolution by pinning versions to minor level…
juhoinkinen Aug 17, 2022
c352262
Fix pytest-cov version
juhoinkinen Aug 17, 2022
1328a62
Load Poetry's repositories cache; separate caches on Python version
juhoinkinen Aug 17, 2022
2404e26
Revert unsuccessful and unnecessary commits trying to speed up CI runs
juhoinkinen Aug 17, 2022
84acab6
Install Poetry with pipx instead of with install-poetry action
juhoinkinen Sep 1, 2022
935c16a
Upgrade to Poetry 1.2.0
juhoinkinen Sep 1, 2022
d95de44
Install fastText from prebuilt wheels
juhoinkinen Sep 1, 2022
e496485
Cache Poetry installation
juhoinkinen Sep 1, 2022
bc8af86
Cache Poetry installation and repo info also in publish release job
juhoinkinen Sep 2, 2022
2adef96
Switch push trigger back to master branch
juhoinkinen Sep 2, 2022
2d3e635
Remove unnecessary builder stage
juhoinkinen Sep 2, 2022
c66b0bd
Use Poetry in installations in Dockerfile
juhoinkinen Sep 2, 2022
7cd1e6e
Merge branch 'master' into issue601-poetry
juhoinkinen Sep 2, 2022
2cd6836
Move downloading nltk data back to earlier layer
juhoinkinen Sep 5, 2022
12991b4
Allow non-root user run unit tests
juhoinkinen Sep 5, 2022
5646692
Instruct to install poetry with pipx instead of curl|bash
juhoinkinen Sep 6, 2022
1287575
Allow existing /Annif/tests/data dir which is typical in local builds
juhoinkinen Sep 13, 2022
4a6e2b5
More detailed development installation instructions
juhoinkinen Sep 13, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 52 additions & 38 deletions .github/workflows/cicd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ on:
pull_request:
workflow_dispatch:
env:
PIP_UPGRADE: "true" # always upgrade to latest version
PIP_UPGRADE_STRATEGY: "eager" # upgrade all dependencies
PIPX_HOME: "/home/runner/.cache/pipx"
PIPX_BIN_DIR: "/home/runner/.local/bin"
POETRY_VERSION: "1.2.0"
jobs:
test:
runs-on: ubuntu-latest
Expand All @@ -26,47 +27,51 @@ jobs:
sudo apt-get install \
libvoikko1 \
voikko-fi
- name: Load cached Poetry installation and repositories info
uses: actions/cache@v3
with:
path: |
~/.cache/pipx/venvs
~/.local/bin
~/.cache/pypoetry/cache/repositories
key: poetry-installation-and-repos-${{ matrix.python-version }}-${{ env.POETRY_VERSION }}
- name: Install Poetry
run: |
pipx install poetry==$POETRY_VERSION
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
uses: actions/setup-python@b55428b1882923874294fa556849718a1d7f2ca5 # v4.2.0
with:
python-version: ${{ matrix.python-version }}
cache: pip
cache-dependency-path: setup.py
cache: 'poetry'
cache-dependency-path: 'pyproject.toml'
- name: Install Python dependencies
run: |
python -m pip install pip setuptools wheel
python -m pip install .[dev]
python -m nltk.downloader punkt
# Selectively install the optional dependencies for some Python versions
# Install the optional neural network dependencies (TensorFlow and LMDB)
# - except for one Python version (3.9) so that we can test also without them
if [[ ${{ matrix.python-version }} != '3.9' ]]; then pip install .[nn]; fi
# Install the optional Omikuji and YAKE dependencies
# - except for one Python version (3.9) so that we can test also without them
if [[ ${{ matrix.python-version }} != '3.9' ]]; then pip install .[omikuji,yake]; fi
# Install the optional fastText dependencies for Python 3.9 only
if [[ ${{ matrix.python-version }} == '3.9' ]]; then pip install .[fasttext]; fi
# Install the optional spaCy dependencies for Python 3.9 only
# For Python 3.8:
if [[ ${{ matrix.python-version }} == '3.8' ]]; then
poetry install -E "nn omikuji yake voikko pycld3";
fi
# For Python 3.9:
if [[ ${{ matrix.python-version }} == '3.9' ]]; then
pip install .[spacy]
poetry install -E "fasttext spacy";
# download the small English pretrained spaCy model needed by spacy analyzer
python -m spacy download en_core_web_sm --upgrade-strategy only-if-needed
poetry run python -m spacy download en_core_web_sm --upgrade-strategy only-if-needed
fi
# For Python 3.10:
if [[ ${{ matrix.python-version }} == '3.10' ]]; then
poetry install -E "nn omikuji yake";
fi
# For Python 3.8
# - voikko and pycld3 dependencies
if [[ ${{ matrix.python-version }} == '3.8' ]]; then python -m pip install .[voikko,pycld3]; fi
# Verify installed packages have compatible dependencies:
python -m pip check
poetry run python -m nltk.downloader punkt

- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
poetry run flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
poetry run flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
run: |
pytest --cov=./ --cov-report xml
poetry run pytest --cov=./ --cov-report xml
- name: Upload coverage to Codecov
uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # v3.1.0

Expand Down Expand Up @@ -103,21 +108,30 @@ jobs:
if: github.event_name == 'push' && contains(github.ref, 'refs/tags/')
steps:
- uses: actions/checkout@v3
- name: Load cached Poetry installation and repositories info
uses: actions/cache@v3
with:
path: |
~/.cache/pipx/venvs
~/.local/bin
~/.cache/pypoetry/cache/repositories
key: poetry-installation-and-repos-${{ matrix.python-version }}-${{ env.POETRY_VERSION }}
- name: Install Poetry
run: |
pipx install poetry==$POETRY_VERSION
- name: Set up Python 3.9
uses: actions/setup-python@v3
uses: actions/setup-python@b55428b1882923874294fa556849718a1d7f2ca5 # v4.2.0
with:
python-version: '3.9'
cache: pip
cache-dependency-path: setup.py
- name: Build distribution
cache: 'poetry'
cache-dependency-path: 'pyproject.toml'
- name: Build and publish distribution to PyPI
env:
POETRY_HTTP_BASIC_PYPI_USERNAME: __token__
POETRY_HTTP_BASIC_PYPI_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
run: |
python -m pip install wheel
python setup.py sdist bdist_wheel
- name: Publish distribution to PyPI
uses: pypa/gh-action-pypi-publish@717ba43cfbb0387f6ce311b169a825772f54d295 # v1.5.0
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
poetry publish --build

- name: Login to Quay.io
uses: docker/login-action@49ed152c8eca782a232dede0303416e8f356c37b # v2.0.0
with:
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ __pycache__
*.pyc
data
docs/_build/
Pipfile.lock
poetry.lock
projects.cfg
venv/
39 changes: 14 additions & 25 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,26 +1,10 @@
FROM python:3.8-slim-bullseye AS builder

FROM python:3.8-slim-bullseye
LABEL maintainer="Juho Inkinen <juho.inkinen@helsinki.fi>"

SHELL ["/bin/bash", "-c"]
ARG optional_dependencies=dev,voikko,pycld3,fasttext,nn,omikuji,yake,spacy
# Bulding fastText needs some system packages
RUN if [[ $optional_dependencies =~ "fasttext" ]]; then \
apt-get update && \
apt-get install -y --no-install-recommends \
build-essential && \
pip install --upgrade pip setuptools wheel --no-cache-dir && \
pip install --no-cache-dir \
fasttext==0.9.2; \
fi

ARG optional_dependencies="fasttext voikko pycld3 fasttext nn omikuji yake spacy"
ARG POETRY_VIRTUALENVS_CREATE=false

FROM python:3.8-slim-bullseye

SHELL ["/bin/bash", "-c"]
COPY --from=builder /usr/local/lib/python3.8 /usr/local/lib/python3.8

ARG optional_dependencies=dev,voikko,pycld3,fasttext,nn,omikuji,yake,spacy
# Install system dependencies needed at runtime:
RUN apt-get update && \
if [[ $optional_dependencies =~ "voikko" ]]; then \
Expand All @@ -33,11 +17,14 @@ RUN apt-get update && \
rm -rf /var/lib/apt/lists/* /usr/include/*

WORKDIR /Annif
RUN pip install --upgrade pip wheel --no-cache-dir
RUN pip install --upgrade pip poetry --no-cache-dir && \
pip install poetry

COPY pyproject.toml setup.cfg README.md LICENSE.txt CITATION.cff projects.cfg.dist /Annif/

COPY setup.py README.md LICENSE.txt projects.cfg.dist /Annif/
# First round of installation for Docker layer caching:
RUN echo "Installing dependencies for optional features: $optional_dependencies" \
&& pip install .[$optional_dependencies] --no-cache-dir
&& poetry install -E "$optional_dependencies"

# Download nltk data
RUN python -m nltk.downloader punkt -d /usr/share/nltk_data
Expand All @@ -50,17 +37,19 @@ RUN if [[ $optional_dependencies =~ "spacy" ]]; then \
done; \
fi

# Install Annif by copying source and make the installation editable:
# Second round of installation with the actual code:
COPY annif /Annif/annif
COPY tests /Annif/tests
RUN pip install -e .
RUN poetry install -E "$optional_dependencies"

WORKDIR /annif-projects

# Switch user to non-root:
RUN groupadd -g 998 annif_user && \
useradd -r -u 998 -g annif_user annif_user && \
chown -R annif_user:annif_user /annif-projects
chmod -R a+rX /Annif && \
mkdir -p /Annif/tests/data && \
chown -R annif_user:annif_user /annif-projects /Annif/tests/data
USER annif_user

CMD annif
3 changes: 0 additions & 3 deletions MANIFEST.in

This file was deleted.

26 changes: 19 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,22 +54,34 @@ for details.

A development version of Annif can be installed by cloning the [GitHub
repository](https://github.com/NatLibFi/Annif).
[Poetry](https://python-poetry.org/) is used for managing dependencies and virtual environment for the development version.

## Installation and setup

Clone the repository.

Switch into the repository directory.

Create and activate a virtual environment (optional, but highly recommended):
Install [pipx](https://pypa.github.io/pipx/) and Poetry if you don't have them. First pipx:

python3 -m venv venv
. venv/bin/activate
python3 -m pip install --user pipx
python3 -m pipx ensurepath

Install dependencies (including development) and make the installation editable:
Open a new shell, and then install Poetry:

pip install .[dev]
pip install -e .
pipx install poetry

Poetry can be installed also without pipx: check the [Poetry documentation](https://python-poetry.org/docs/master/#installation).

Create a virtual environment and install dependencies:

poetry install

By default development dependencies are included. Use option `-E` to install dependencies for selected optional features (`-E "extra1 extra2"` for multiple extras), or install all of them with `--all-extras`. By default the virtual environment directory is not under the project directory, but there is a [setting for selecting this](https://python-poetry.org/docs/configuration/#virtualenvsin-project).

Enter the virtual environment:

poetry shell

You will also need NLTK data files:

Expand All @@ -81,7 +93,7 @@ Start up the application:

## Unit tests

Run `. venv/bin/activate` to enter the virtual environment and then run `pytest`.
Run `poetry shell` to enter the virtual environment and then run `pytest`.
To have the test suite watch for changes in code and run automatically, use
pytest-watch by running `ptw`.

Expand Down
93 changes: 93 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
[tool.poetry]
name = "annif"
version = "0.59.0-dev"
description = "Automated subject indexing and classification tool"
authors = ["National Library of Finland <finto-posti@helsinki.fi>"]
maintainers = [
"Osma Suominen <osma.suominen@helsinki.fi>",
"Juho Inkinen <juho.inkinen@helsinki.fi>",
"Mona Lehtinen <mona.lehtinen@helsinki.fi>",
]
license = "Apache-2.0"
readme = "README.md"
homepage = "https://annif.org"
repository = "https://github.com/NatLibFi/Annif"
documentation = "https://github.com/NatLibFi/Annif/wiki"
keywords = [
"machine-learning",
"text-classification",
"rest-api",
"code4lib",
"subject-indexing"
]

classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: Apache Software License",
"Operating System :: OS Independent"
]

[tool.poetry.dependencies]
python = ">=3.8,<3.11"

connexion = {version = "2.14.*", extras = ["swagger-ui"]}
swagger_ui_bundle = "*"
flask = ">=1.0.4,<3"
flask-cors = "*"
click = "8.1.*"
click-log = "*"
joblib = "1.1.0"
nltk = "*"
gensim = "4.2.*"
scikit-learn = "1.1.1"
scipy = "1.8.*"
rdflib = ">=4.2,<7.0"
gunicorn = "*"
numpy = "1.23.*"
optuna = "2.10.*"
stwfsapy = "0.3.*"
python-dateutil = "*"
tomli = "2.0.*"
simplemma = "0.8.*"

fasttext-wheel = {version = "0.9.2", optional = true}
voikko = {version = "*", optional = true}
tensorflow-cpu = {version = "2.9.1", optional = true}
lmdb = {version = "1.3.0", optional = true}
omikuji = {version = "0.5.*", optional = true}
yake = {version = "0.4.5", optional = true}
pycld3 = {version = "*", optional = true}
spacy = {version = "3.3.*", optional = true}

[tool.poetry.dev-dependencies]
py = "*"
pytest = "*"
requests = "*"
codecov = "*"
coverage = "<=6.2"
pytest-cov = "*"
pytest-watch = "*"
pytest-flask = "*"
pytest-flake8 = "*"
flake8 = "4.*"
bumpversion = "*"
autopep8 = "*"

[tool.poetry.extras]
fasttext = ["fasttext-wheel"]
voikko = ["voikko"]
nn = ["tensorflow-cpu", "lmdb"]
omikuji = ["omikuji"]
yake = ["yake"]
pycld3 = ["pycld3"]
spacy = ["spacy"]

[tool.poetry.scripts]
annif = "annif.cli:cli"

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

[tool.pytest.ini_options]
addopts = "--flake8"
2 changes: 0 additions & 2 deletions pytest.ini

This file was deleted.

2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ serialize =
{major}.{minor}.{patch}-{release}
{major}.{minor}.{patch}

[bumpversion:file:setup.py]
[bumpversion:file:pyproject.toml]

[bumpversion:file:CITATION.cff]

Expand Down
Loading