diff --git a/.github/workflows/black.yml b/.github/workflows/black.yml new file mode 100644 index 0000000..14b047d --- /dev/null +++ b/.github/workflows/black.yml @@ -0,0 +1,14 @@ +name: Black + +on: push + +jobs: + black: + runs-on: ubuntu-24.04 + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + - uses: psf/black@stable + with: + options: "--check" diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index b02b7d1..4eaee85 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -10,10 +10,10 @@ on: jobs: publish: - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Publish to Registry uses: docker/build-push-action@v1 with: diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index 08fad1f..bb7e951 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -4,36 +4,38 @@ on: push jobs: test: - - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 strategy: matrix: - python-version: [3.7, 3.8] + python-version: ["3.11", "3.12"] steps: - - uses: actions/checkout@v2 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install Python dependencies - env: - PIP_INDEX_URL: https://pypi.pacificclimate.org/simple - run: | - pip install -r requirements.txt - pip install -e .[dev] - - name: Install R dependencies - run: | - sudo apt-get update - sudo apt-get install --fix-missing libgit2-dev libfontconfig1-dev libharfbuzz-dev libfribidi-dev libcurl4-openssl-dev libssl-dev - Rscript install_pkgs.R r_requirements.txt - - name: Test with pytest (full) - if: github.ref == 'refs/heads/master' - run: | - py.test -m "not online" -v - - name: Test with pytest (fast) - if: github.ref != 'refs/heads/master' - run: | - py.test -m "not online and not slow" -v - - name: Code Quality - run: black . --check + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y r-base libgit2-dev libudunits2-dev libnetcdf-dev libcurl4-openssl-dev libssl-dev libfontconfig1-dev libxml2-dev libharfbuzz-dev libfribidi-dev libfreetype6-dev libpng-dev libtiff5-dev libjpeg-dev + curl -sSL https://install.python-poetry.org | python3 - + echo "$HOME/.local/bin" >> $GITHUB_PATH + export PATH="/root/.local/bin:$PATH" + poetry install --extras "dev" + + - name: Set GITHUB_PAT env var for R + run: echo "GITHUB_PAT=${{ secrets.GITHUB_TOKEN }}" >> $GITHUB_ENV + + - name: Install R packages + run: Rscript install_pkgs.R + + - name: Test with pytest (full) + if: github.ref == 'refs/heads/master' + run: | + poetry run py.test -m "not online" -v + - name: Test with pytest (fast) + if: github.ref != 'refs/heads/master' + run: | + poetry run py.test -m "not online and not slow" -v diff --git a/Dockerfile b/Dockerfile index 2534495..726396e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,26 +1,26 @@ -FROM rocker/r-ver:4.0.3 AS build +FROM rocker/r-ver:4.4 AS build -COPY r_requirements.txt install_pkgs.R ./ +COPY pyproject.toml install_pkgs.R ./ # Install python and R packages RUN apt-get update && \ apt-get install -y --no-install-recommends \ - libssl-dev \ - libxml2-dev \ - libudunits2-dev \ - libnetcdf-dev \ - libgit2-dev \ - libfreetype6-dev \ - libpng-dev \ - libtiff5-dev \ - libjpeg-dev \ - libfontconfig1-dev \ - libharfbuzz-dev \ - libfribidi-dev \ - libcurl4-openssl-dev && \ - Rscript install_pkgs.R r_requirements.txt - -FROM rocker/r-ver:4.0.3 + libssl-dev \ + libxml2-dev \ + libudunits2-dev \ + libnetcdf-dev \ + libgit2-dev \ + libfreetype6-dev \ + libpng-dev \ + libtiff5-dev \ + libjpeg-dev \ + libfontconfig1-dev \ + libharfbuzz-dev \ + libfribidi-dev \ + libcurl4-openssl-dev && \ + Rscript install_pkgs.R + +FROM rocker/r-ver:4.4 LABEL Maintainer="https://github.com/pacificclimate/quail" \ Description="quail WPS" \ @@ -30,25 +30,31 @@ LABEL Maintainer="https://github.com/pacificclimate/quail" \ WORKDIR /tmp # Copy R packages -ARG R_FILEPATH=/root/R/x86_64-pc-linux-gnu-library/4.0 +ARG R_FILEPATH=/root/R/x86_64-pc-linux-gnu-library/4.4 COPY --from=build ${R_FILEPATH}/PCICt ${R_FILEPATH}/PCICt COPY --from=build ${R_FILEPATH}/climdex.pcic ${R_FILEPATH}/climdex.pcic COPY --from=build ${R_FILEPATH}/Rcpp ${R_FILEPATH}/Rcpp # Add path to libR.so to the environment variable LD_LIBRARY_PATH -ENV LD_LIBRARY_PATH=/usr/local/lib/R/lib:$LD_LIBRARY_PATH +ENV LD_LIBRARY_PATH="/usr/local/lib/R/lib:${LD_LIBRARY_PATH}" ENV PIP_INDEX_URL="https://pypi.pacificclimate.org/simple/" COPY . /tmp -COPY requirements.txt ./ +COPY pyproject.toml poetry.lock* ./ + +ENV POETRY_HOME="/opt/poetry" +ENV PATH="$POETRY_HOME/bin:$PATH" -# Install Python RUN apt-get update && \ - apt-get install -y --no-install-recommends python3.8 python3-pip && \ - pip install -U pip && \ - pip install -r requirements.txt && \ - pip install gunicorn + apt-get install -y --no-install-recommends python3 python3-pip curl && \ + curl -sSL https://install.python-poetry.org | python3 + + +RUN poetry config virtualenvs.in-project true && \ + poetry install EXPOSE 5000 -CMD gunicorn --bind=0.0.0.0:5000 quail.wsgi:application +CMD ["poetry", "run", "gunicorn", "--bind=0.0.0.0:5000", "quail.wsgi:application"] + + diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 3fb9d97..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,6 +0,0 @@ -include Makefile -include *.txt -include *.md -recursive-include quail * -global-exclude __pycache__ -global-exclude *.py[co] diff --git a/Makefile b/Makefile deleted file mode 100644 index 60e3a3f..0000000 --- a/Makefile +++ /dev/null @@ -1,187 +0,0 @@ -# Configuration -APP_ROOT := $(abspath $(lastword $(MAKEFILE_LIST))/..) -APP_NAME := quail -VENV?=/tmp/quail-venv -PYTHON=${VENV}/bin/python3 -PIP=${VENV}/bin/pip -export PIP_INDEX_URL=https://pypi.pacificclimate.org/simple - -# Notebook targets -LOCAL_URL = http://localhost:5000 -DEV_PORT ?= $(shell bash -c 'read -ep "Target port: " port; echo $$port') - -# Used in target refresh-notebooks to make it looks like the notebooks have -# been refreshed from the production server below instead of from the local dev -# instance so the notebooks can also be used as tutorial notebooks. -OUTPUT_URL = https://docker-dev03.pcic.uvic.ca/wpsoutputs -SANITIZE_FILE := https://github.com/Ouranosinc/PAVICS-e2e-workflow-tests/raw/master/notebooks/output-sanitize.cfg - -# end of configuration - -.PHONY: all -all: apt develop install-r-pkg test-all clean-test test-notebooks-prod - -.PHONY: help -help: - @echo "Please use 'make ' where is one of:" - @echo " help to print this help message. (Default)" - @echo " install to install app by running 'pip install -e .'" - @echo " develop to install with additional development requirements." - @echo " start to start $(APP_NAME) service as daemon (background process)." - @echo " stop to stop $(APP_NAME) service." - @echo " restart to restart $(APP_NAME) service." - @echo " status to show status of $(APP_NAME) service." - @echo " clean to remove all files generated by build and tests." - @echo "\nTesting targets:" - @echo " test to run tests (but skip long running tests)." - @echo " test-all to run all tests (including long running tests)." - @echo " test-notebooks to verify Jupyter Notebook test outputs are valid." - @echo " lint to run code style checks with flake8." - @echo " refresh-notebooks to verify Jupyter Notebook test outputs are valid." - @echo "\nSphinx targets:" - @echo " docs to generate HTML documentation with Sphinx." - @echo "\nDeployment targets:" - @echo " dist to build source and wheel package." - -## Build targets - -.PHONY: install -install: venv - @echo "Installing application ..." - @-bash -c '${PIP} install -e .' - @echo "\nStart service with \`make start'" - -.PHONY: apt -apt: - @echo "Installing libfontconfig1-dev libharfbuzz-dev libfribidi-dev libcurl4-openssl-dev..." - @-bash -c "sudo apt-get -y install libfontconfig1-dev libharfbuzz-dev libfribidi-dev libcurl4-openssl-dev" - -.PHONY: install-r-pkg -install-r-pkg: - @echo "Installing R packages ..." - @-bash -c 'Rscript install_pkgs.R r_requirements.txt' - -.PHONY: develop -develop: venv - @echo "Installing development requirements for tests and docs ..." - @-bash -c '${PIP} install -e ".[dev]"' - -.PHONY: start -start: venv - @echo "Starting application ..." - @-bash -c "${VENV}/bin/$(APP_NAME) start -d" - -.PHONY: stop -stop: venv - @echo "Stopping application ..." - @-bash -c "${VENV}/bin/$(APP_NAME) stop" - -.PHONY: restart -restart: venv stop start - @echo "Restarting application ..." - -.PHONY: status -status: venv - @echo "Showing status ..." - @-bash -c "${VENV}/bin/$(APP_NAME) status" - -.PHONY: clean -clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts - -.PHONY: clean-build -clean-build: - @echo "Removing build artifacts ..." - @-rm -fr build/ - @-rm -fr dist/ - @-rm -fr .eggs/ - @-find . -name '*.egg-info' -exec rm -fr {} + - @-find . -name '*.egg' -exec rm -f {} + - @-find . -name '*.log' -exec rm -fr {} + - @-find . -name '*.sqlite' -exec rm -fr {} + - -.PHONY: clean-pyc -clean-pyc: - @echo "Removing Python file artifacts ..." - @-find . -name '*.pyc' -exec rm -f {} + - @-find . -name '*.pyo' -exec rm -f {} + - @-find . -name '*~' -exec rm -f {} + - @-find . -name '__pycache__' -exec rm -fr {} + - -.PHONY: clean-test -clean-test: - @echo "Removing test artifacts ..." - @-rm -fr .pytest_cache - -.PHONY: clean-dist -clean-dist: clean - @echo "Running 'git clean' ..." - @git diff --quiet HEAD || echo "There are uncommitted changes! Aborting 'git clean' ..." - ## do not use git clean -e/--exclude here, add them to .gitignore instead - @-git clean -dfx - -.PHONY: venv -venv: - test -d $(VENV) || python3 -m venv $(VENV) - -## Test targets - -.PHONY: test -test: venv - @echo "Running tests (skip slow and online tests) ..." - @bash -c '${PYTHON} -m pytest -v -m "not slow and not online" tests/' - -.PHONY: test-all -test-all: venv - @echo "Running all tests (including slow and online tests) ..." - @bash -c '${PYTHON} -m pytest -v tests/' - -.PHONY: notebook-sanitizer -notebook-sanitizer: - @echo "Copying notebook output sanitizer ..." - @-bash -c "curl -L $(SANITIZE_FILE) -o $(CURDIR)/docs/output-sanitize.cfg --silent" - -.PHONY: test-notebooks -test-notebooks: notebook-sanitizer - @echo "Running notebook-based tests" - @bash -c "source $(VENV)/bin/activate && env LOCAL_URL=$(LOCAL_URL) pytest --nbval --verbose $(CURDIR)/notebooks/ --sanitize-with $(CURDIR)/docs/output-sanitize.cfg --ignore $(CURDIR)/notebooks/.ipynb_checkpoints" - -.PHONY: test-notebooks-prod -test-notebooks-prod: notebook-sanitizer - @echo "Running notebook-based tests against production instance of quail" - @bash -c "source $(VENV)/bin/activate && pytest --nbval --verbose $(CURDIR)/notebooks/ --sanitize-with $(CURDIR)/docs/output-sanitize.cfg --ignore $(CURDIR)/notebooks/.ipynb_checkpoints" - -.PHONY: test-notebooks-dev -test-notebooks-dev: notebook-sanitizer - @echo "Running notebook-based tests against development instance of quail" - @bash -c "source $(VENV)/bin/activate && env DEV_URL=http://docker-dev03.pcic.uvic.ca:30103/wps pytest --nbval --verbose $(CURDIR)/notebooks/ --sanitize-with $(CURDIR)/docs/output-sanitize.cfg --ignore $(CURDIR)/notebooks/.ipynb_checkpoints" - -.PHONY: test-notebooks-custom -test-notebooks-custom: notebook-sanitizer - @echo "Running notebook-based tests against custom instance of quail" - @bash -c "source $(VENV)/bin/activate && env DEV_URL=http://docker-dev03.pcic.uvic.ca:$(DEV_PORT)/wps pytest --nbval --verbose $(CURDIR)/notebooks/ --sanitize-with $(CURDIR)/docs/output-sanitize.cfg --ignore $(CURDIR)/notebooks/.ipynb_checkpoints" - -.PHONY: lint -lint: venv - @echo "Running black code style checks ..." - @bash -c '${PYTHON} -m black . --check' - -.PHONY: refresh-notebooks -refresh-notebooks: - @echo "Refresh all notebook outputs under docs/source/notebooks" - @bash -c 'for nb in $(CURDIR)/notebooks/*.ipynb; do WPS_URL="$(WPS_URL)" jupyter nbconvert --to notebook --execute --ExecutePreprocessor.timeout=60 --output "$$nb" "$$nb"; sed -i "s@$(WPS_URL)/outputs/@$(OUTPUT_URL)/@g" "$$nb"; done; cd $(APP_ROOT)' - -## Documentation - -.PHONY: docs -docs: - @echo "Updating notebook docs" - @bash -c 'source $(VENV)/bin/activate && jupyter nbconvert --to html notebooks/* --output-dir docs/formatted_demos/' - -## Deployment targets - -.PHONY: dist -dist: clean - @echo "Building source and wheel package ..." - @-python setup.py sdist - @-python setup.py bdist_wheel - @-bash -c 'ls -l dist/' diff --git a/dev-component/DEVELOPMENT.md b/dev-component/DEVELOPMENT.md index f17a09e..8745781 100644 --- a/dev-component/DEVELOPMENT.md +++ b/dev-component/DEVELOPMENT.md @@ -1,6 +1,6 @@ # Development -This `docker-compose` is set up for development purposes. It will up a dev instance of `quail` with production settings. All you are required to do is to add the following lines to `birdhouse-config/env.local` running on `dev03`: +This `docker-compose` is set up for development purposes. It will up a dev instance of `quail` with production settings. All you are required to do is to add the following lines to `birdhouse-config/env.local` running on `marble-dev01`: ``` export EXTRA_CONF_DIRS="/storage/data/projects/comp_support/daccs/birdhouse-config @@ -8,4 +8,5 @@ export EXTRA_CONF_DIRS="/storage/data/projects/comp_support/daccs/birdhouse-conf /path/to/quail/dev-component" ... -export QUAIL_DEV_IMAGE="pcic/quail:[your-tag]" \ No newline at end of file +export QUAIL_DEV_IMAGE="pcic/quail:[your-tag]" +``` diff --git a/docs/dev_guide.md b/docs/dev_guide.md index 55fa7d3..ba25279 100644 --- a/docs/dev_guide.md +++ b/docs/dev_guide.md @@ -1,64 +1,62 @@ # Developer Guide + - [Building the docs](#building-the-docs) - [Running tests](#running-tests) - [Run tests the lazy way](#run-tests-the-lazy-way) - [Bump a new version](#bump-a-new-version) ## Building the docs -Most of the documentation is static and does not need to be "built". That being said the jupyter notebooks that serve as demos need to be built whenever they are changed. This can be done with the `Makefile`. + +Most of the documentation is static and does not need to be "built". That being said the jupyter notebooks that serve as demos need to be built whenever they are changed. ``` -$ make docs +$ poe docs ``` ## Running tests + Run tests using [`pytest`](https://docs.pytest.org/en/latest/). -First activate the `quail` Python environment and install `pytest`. +Install dev dependencies: + ``` -$ python3 -m venv venv -$ source venv/bin/activate -(venv)$ pip install -r requirements_dev.txt # if not already installed -# OR -(venv)$ make install +poe develop ``` Run quick tests (skip slow and online): + ``` -(venv)$ pytest -m 'not slow and not online'" +poe test ``` + Run all tests: + ``` -(venv)$ pytest +poe test-all ``` -You can also run tests on the notebooks using the `Makefile`. +You can also run tests on the notebooks. + ``` -$ make test-notebooks +poe test-notebooks ``` Check `black` formatting: -``` -(venv)$ black . -``` -## Run tests the lazy way -Do the same as above using the `Makefile` ``` -$ make test -$ make test-all -$ make lint +poe lint ``` ## Bump a new version + Make a new version of `quail` in the following steps: -* Make sure everything is committed to GitHub. -* Update `CHANGES.md` with the next version. -* Dry Run: `bumpversion --dry-run --verbose --new-version 0.8.1 patch` -* Do it: `bumpversion --new-version 0.8.1 patch` -* ... or: `bumpversion --new-version 0.9.0 minor` -* Push it: `git push` -* Push tag: `git push --tags` +- Make sure everything is committed to GitHub. +- Update `CHANGES.md` with the next version. +- Dry Run: `bumpversion --dry-run --verbose --new-version 0.8.1 patch` +- Do it: `bumpversion --new-version 0.8.1 patch` +- ... or: `bumpversion --new-version 0.9.0 minor` +- Push it: `git push` +- Push tag: `git push --tags` See the [bumpversion](https://pypi.org/project/bumpversion/) documentation for details. diff --git a/docs/formatted_demos/wps_climdexInput_csv_demo.html b/docs/formatted_demos/wps_climdexInput_csv_demo.html index 9b745db..82c1694 100644 --- a/docs/formatted_demos/wps_climdexInput_csv_demo.html +++ b/docs/formatted_demos/wps_climdexInput_csv_demo.html @@ -1,13 +1,9 @@ - - - + + + wps_climdexInput_csv_demo - - - - - - - +.jp-Cell-Placeholder { + padding-left: 55px; +} + +.jp-Cell-Placeholder-wrapper { + background: #fff; + border: 1px solid; + border-color: #e5e6e9 #dfe0e4 #d0d1d5; + border-radius: 4px; + -webkit-border-radius: 4px; + margin: 10px 15px; +} + +.jp-Cell-Placeholder-wrapper-inner { + padding: 15px; + position: relative; +} + +.jp-Cell-Placeholder-wrapper-body { + background-repeat: repeat; + background-size: 50% auto; +} + +.jp-Cell-Placeholder-wrapper-body div { + background: #f6f7f8; + background-image: -webkit-linear-gradient( + left, + #f6f7f8 0%, + #edeef1 20%, + #f6f7f8 40%, + #f6f7f8 100% + ); + background-repeat: no-repeat; + background-size: 800px 104px; + height: 104px; + position: absolute; + right: 15px; + left: 15px; + top: 15px; +} - + - +/* Hiding the collapser by default */ +.jp-Collapser { + display: none; +} +@page { + margin: 0.5in; /* Margin for each printed piece of paper */ +} +@media print { + .jp-Cell-inputWrapper, + .jp-Cell-outputWrapper { + display: block; + } +} + - - - + + - - + + + + +
+
- - - - - - - diff --git a/docs/formatted_demos/wps_climdexInput_quantile_demo.html b/docs/formatted_demos/wps_climdexInput_quantile_demo.html index ba6e8cb..0644edf 100644 --- a/docs/formatted_demos/wps_climdexInput_quantile_demo.html +++ b/docs/formatted_demos/wps_climdexInput_quantile_demo.html @@ -1,13 +1,9 @@ - - - + + + wps_climdexInput_quantile_demo - - - - - - - - - - +/* Hiding the collapser by default */ +.jp-Collapser { + display: none; +} +@page { + margin: 0.5in; /* Margin for each printed piece of paper */ +} +@media print { + .jp-Cell-inputWrapper, + .jp-Cell-outputWrapper { + display: block; + } +} + - - - + + - - + + + + +
+
- - - - - - - diff --git a/docs/formatted_demos/wps_climdexInput_raw_demo.html b/docs/formatted_demos/wps_climdexInput_raw_demo.html index 664f316..a47e2f6 100644 --- a/docs/formatted_demos/wps_climdexInput_raw_demo.html +++ b/docs/formatted_demos/wps_climdexInput_raw_demo.html @@ -1,13 +1,9 @@ - - - + + + wps_climdexInput_raw_demo - - - - - - - +.jp-Cell-Placeholder { + padding-left: 55px; +} + +.jp-Cell-Placeholder-wrapper { + background: #fff; + border: 1px solid; + border-color: #e5e6e9 #dfe0e4 #d0d1d5; + border-radius: 4px; + -webkit-border-radius: 4px; + margin: 10px 15px; +} + +.jp-Cell-Placeholder-wrapper-inner { + padding: 15px; + position: relative; +} + +.jp-Cell-Placeholder-wrapper-body { + background-repeat: repeat; + background-size: 50% auto; +} + +.jp-Cell-Placeholder-wrapper-body div { + background: #f6f7f8; + background-image: -webkit-linear-gradient( + left, + #f6f7f8 0%, + #edeef1 20%, + #f6f7f8 40%, + #f6f7f8 100% + ); + background-repeat: no-repeat; + background-size: 800px 104px; + height: 104px; + position: absolute; + right: 15px; + left: 15px; + top: 15px; +} - + - +/* Hiding the collapser by default */ +.jp-Collapser { + display: none; +} +@page { + margin: 0.5in; /* Margin for each printed piece of paper */ +} +@media print { + .jp-Cell-inputWrapper, + .jp-Cell-outputWrapper { + display: block; + } +} + - - - + + - - + + + + +
+
- - - - - - - diff --git a/docs/formatted_demos/wps_climdex_days_demo.html b/docs/formatted_demos/wps_climdex_days_demo.html index d38bf22..344cae4 100644 --- a/docs/formatted_demos/wps_climdex_days_demo.html +++ b/docs/formatted_demos/wps_climdex_days_demo.html @@ -1,13 +1,9 @@ - - - + + + wps_climdex_days_demo - - - - - - - - - - +/* Hiding the collapser by default */ +.jp-Collapser { + display: none; +} +@page { + margin: 0.5in; /* Margin for each printed piece of paper */ +} +@media print { + .jp-Cell-inputWrapper, + .jp-Cell-outputWrapper { + display: block; + } +} + - - - + + - - + + + + +
+
- - - - - - - diff --git a/docs/formatted_demos/wps_climdex_dtr_demo.html b/docs/formatted_demos/wps_climdex_dtr_demo.html index 24e18df..d308a96 100644 --- a/docs/formatted_demos/wps_climdex_dtr_demo.html +++ b/docs/formatted_demos/wps_climdex_dtr_demo.html @@ -1,13 +1,9 @@ - - - + + + wps_climdex_dtr_demo - - - - - - - +div.jp-Cell-Placeholder-content-3 { + top: 140px; +} - + - +/* Hiding the collapser by default */ +.jp-Collapser { + display: none; +} +@page { + margin: 0.5in; /* Margin for each printed piece of paper */ +} +@media print { + .jp-Cell-inputWrapper, + .jp-Cell-outputWrapper { + display: block; + } +} + - - - + + - - + + + + +
+
- - - - - - - diff --git a/docs/formatted_demos/wps_climdex_get_available_indices.html b/docs/formatted_demos/wps_climdex_get_available_indices.html index 7055559..39c997a 100644 --- a/docs/formatted_demos/wps_climdex_get_available_indices.html +++ b/docs/formatted_demos/wps_climdex_get_available_indices.html @@ -1,13 +1,9 @@ - - - + + + wps_climdex_get_available_indices - - - - - - - +div.jp-Cell-Placeholder-content-3 { + top: 140px; +} - + - +/* Hiding the collapser by default */ +.jp-Collapser { + display: none; +} +@page { + margin: 0.5in; /* Margin for each printed piece of paper */ +} +@media print { + .jp-Cell-inputWrapper, + .jp-Cell-outputWrapper { + display: block; + } +} + - - - + + - - + + + + +
+
- - - - - - - diff --git a/docs/formatted_demos/wps_climdex_gsl_demo.html b/docs/formatted_demos/wps_climdex_gsl_demo.html index 5168a76..d213190 100644 --- a/docs/formatted_demos/wps_climdex_gsl_demo.html +++ b/docs/formatted_demos/wps_climdex_gsl_demo.html @@ -1,13 +1,9 @@ - - - + + + wps_climdex_gsl_demo - - - - - - - - - - +/* Hiding the collapser by default */ +.jp-Collapser { + display: none; +} +@page { + margin: 0.5in; /* Margin for each printed piece of paper */ +} +@media print { + .jp-Cell-inputWrapper, + .jp-Cell-outputWrapper { + display: block; + } +} + - - - + + - - + + + + +
+
- - - - - - - diff --git a/docs/formatted_demos/wps_climdex_mmdmt_demo.html b/docs/formatted_demos/wps_climdex_mmdmt_demo.html index 31f74e2..eeb5d98 100644 --- a/docs/formatted_demos/wps_climdex_mmdmt_demo.html +++ b/docs/formatted_demos/wps_climdex_mmdmt_demo.html @@ -1,13 +1,9 @@ - - - + + + wps_climdex_mmdmt_demo - - - - - - - +.jp-Cell-Placeholder { + padding-left: 55px; +} + +.jp-Cell-Placeholder-wrapper { + background: #fff; + border: 1px solid; + border-color: #e5e6e9 #dfe0e4 #d0d1d5; + border-radius: 4px; + -webkit-border-radius: 4px; + margin: 10px 15px; +} + +.jp-Cell-Placeholder-wrapper-inner { + padding: 15px; + position: relative; +} + +.jp-Cell-Placeholder-wrapper-body { + background-repeat: repeat; + background-size: 50% auto; +} + +.jp-Cell-Placeholder-wrapper-body div { + background: #f6f7f8; + background-image: -webkit-linear-gradient( + left, + #f6f7f8 0%, + #edeef1 20%, + #f6f7f8 40%, + #f6f7f8 100% + ); + background-repeat: no-repeat; + background-size: 800px 104px; + height: 104px; + position: absolute; + right: 15px; + left: 15px; + top: 15px; +} + +div.jp-Cell-Placeholder-h1 { + top: 20px; + height: 20px; + left: 15px; + width: 150px; +} + +div.jp-Cell-Placeholder-h2 { + left: 15px; + top: 50px; + height: 10px; + width: 100px; +} + +div.jp-Cell-Placeholder-content-1, +div.jp-Cell-Placeholder-content-2, +div.jp-Cell-Placeholder-content-3 { + left: 15px; + right: 15px; + height: 10px; +} - + - +/* Hiding the collapser by default */ +.jp-Collapser { + display: none; +} +@page { + margin: 0.5in; /* Margin for each printed piece of paper */ +} +@media print { + .jp-Cell-inputWrapper, + .jp-Cell-outputWrapper { + display: block; + } +} + - - - + + - - + + + + +
+
- - - - - - - diff --git a/docs/formatted_demos/wps_climdex_ptot.html b/docs/formatted_demos/wps_climdex_ptot.html index c68f583..cdd67c6 100644 --- a/docs/formatted_demos/wps_climdex_ptot.html +++ b/docs/formatted_demos/wps_climdex_ptot.html @@ -1,13 +1,9 @@ - - - + + + wps_climdex_ptot - - - - - - - - - - +/* Hiding the collapser by default */ +.jp-Collapser { + display: none; +} +@page { + margin: 0.5in; /* Margin for each printed piece of paper */ +} +@media print { + .jp-Cell-inputWrapper, + .jp-Cell-outputWrapper { + display: block; + } +} + - - - + + - - + + + + +
+
- - - - - - - diff --git a/docs/formatted_demos/wps_climdex_rmm_demo.html b/docs/formatted_demos/wps_climdex_rmm_demo.html index aceffb0..6aeb1dd 100644 --- a/docs/formatted_demos/wps_climdex_rmm_demo.html +++ b/docs/formatted_demos/wps_climdex_rmm_demo.html @@ -1,13 +1,9 @@ - - - + + + wps_climdex_rmm_demo - - - - - - - - - - +/* Hiding the collapser by default */ +.jp-Collapser { + display: none; +} +@page { + margin: 0.5in; /* Margin for each printed piece of paper */ +} +@media print { + .jp-Cell-inputWrapper, + .jp-Cell-outputWrapper { + display: block; + } +} + - - - + + - - + + + + +
+
- - - - - - - diff --git a/docs/formatted_demos/wps_climdex_rxnday_demo.html b/docs/formatted_demos/wps_climdex_rxnday_demo.html index f9312d2..a4b84f5 100644 --- a/docs/formatted_demos/wps_climdex_rxnday_demo.html +++ b/docs/formatted_demos/wps_climdex_rxnday_demo.html @@ -1,13 +1,9 @@ - - - + + + wps_climdex_rxnday_demo - - - - - - - - - - +/* Hiding the collapser by default */ +.jp-Collapser { + display: none; +} +@page { + margin: 0.5in; /* Margin for each printed piece of paper */ +} +@media print { + .jp-Cell-inputWrapper, + .jp-Cell-outputWrapper { + display: block; + } +} + - - - + + - - + + + + +
+
- - - - - - - diff --git a/docs/formatted_demos/wps_climdex_sdii_demo.html b/docs/formatted_demos/wps_climdex_sdii_demo.html index 5524a7a..55d73e7 100644 --- a/docs/formatted_demos/wps_climdex_sdii_demo.html +++ b/docs/formatted_demos/wps_climdex_sdii_demo.html @@ -1,13 +1,9 @@ - - - + + + wps_climdex_sdii_demo - - - - - - - - - - +.jp-OutputArea-output pre { + line-height: inherit; + font-family: inherit; +} + +.jp-RenderedText pre { + color: var(--jp-content-font-color1); + font-size: var(--jp-code-font-size); +} +/* Hiding the collapser by default */ +.jp-Collapser { + display: none; +} + +@page { + margin: 0.5in; /* Margin for each printed piece of paper */ +} +@media print { + .jp-Cell-inputWrapper, + .jp-Cell-outputWrapper { + display: block; + } +} + - - - + + - - + + + + +
+
- - - - - - - diff --git a/docs/formatted_demos/wps_climdex_spells_demo.html b/docs/formatted_demos/wps_climdex_spells_demo.html index 5814eb1..76c78aa 100644 --- a/docs/formatted_demos/wps_climdex_spells_demo.html +++ b/docs/formatted_demos/wps_climdex_spells_demo.html @@ -1,13 +1,9 @@ - - - + + + wps_climdex_spells_demo - - - - - - - +.jp-Cell-Placeholder { + padding-left: 55px; +} + +.jp-Cell-Placeholder-wrapper { + background: #fff; + border: 1px solid; + border-color: #e5e6e9 #dfe0e4 #d0d1d5; + border-radius: 4px; + -webkit-border-radius: 4px; + margin: 10px 15px; +} + +.jp-Cell-Placeholder-wrapper-inner { + padding: 15px; + position: relative; +} + +.jp-Cell-Placeholder-wrapper-body { + background-repeat: repeat; + background-size: 50% auto; +} + +.jp-Cell-Placeholder-wrapper-body div { + background: #f6f7f8; + background-image: -webkit-linear-gradient( + left, + #f6f7f8 0%, + #edeef1 20%, + #f6f7f8 40%, + #f6f7f8 100% + ); + background-repeat: no-repeat; + background-size: 800px 104px; + height: 104px; + position: absolute; + right: 15px; + left: 15px; + top: 15px; +} - + + - - - - - - - + + - - + + + + +
+
- - - - - - - diff --git a/docs/formatted_demos/wps_climdex_temp_pctl.html b/docs/formatted_demos/wps_climdex_temp_pctl.html index 8000fc8..ea16f5b 100644 --- a/docs/formatted_demos/wps_climdex_temp_pctl.html +++ b/docs/formatted_demos/wps_climdex_temp_pctl.html @@ -1,13 +1,9 @@ - - - + + + wps_climdex_temp_pctl - - - - - - - - - - +/* Hiding the collapser by default */ +.jp-Collapser { + display: none; +} +@page { + margin: 0.5in; /* Margin for each printed piece of paper */ +} +@media print { + .jp-Cell-inputWrapper, + .jp-Cell-outputWrapper { + display: block; + } +} + - - - + + - - + + + + +
+
- - - - - - - diff --git a/docs/installation.md b/docs/installation.md index 553533b..623dbeb 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -1,55 +1,100 @@ # Installation + +- [Install poethepoet](#install-poethepoet) - [Install from Github](#install-from-github) - [Start `quail` PyWPS service](#start-quail-pywps-service) - [Run `quail` as Docker container](#run-quail-as-docker-container) - [Use Ansible to deploy `quail` on your System](#use-ansible-to-deploy-quail-on-your-system) -## Install from GitHub +## Poethepoet tasks + +[Poethepoet](https://github.com/nat-n/poethepoet) is a task runner that integrates smoothly with [Poetry](https://python-poetry.org/), serving as a modern alternative to Makefiles. + +### Install poethepoet -Check out code from the quail GitHub repo and start the installation: ``` -$ git clone https://github.com/pacificclimate/quail.git -$ cd quail +$ python3 -m pip install --user pipx +$ python3 -m pipx ensurepath # Ensure directory where pipx stores apps is in your PATH environment variable +$ pipx install poethepoet # Install globally ``` -Create Python environment named `venv`: +### Usage + +Once installed, you can list all available tasks using: + ``` -$ python3 -m venv venv -$ source venv/bin/activate +poe --help ``` -Install requirements: +This will output a list of predefined tasks from your pyproject.toml. Example: + ``` -(venv)$ pip install -r requirements.txt + # View all tasks + poe --help + install-apt Install required system libraries for R packages + install-r-pkgs Install required R packages + install Install Python project dependencies using Poetry + develop Install development dependencies using Poetry + start Start the Quail service in detached mode + stop Stop the quail service + restart Restart the Quail service + status Show the status of the Quail service + dist Build a distribution package for the project + test Run fast, offline unit tests + test-all Run all tests, including online ones + lint Check code formatting using Black + prepare-notebooks Download the output sanitizer config for notebook tests + test-notebooks Run all local notebook tests with sanitized output + test-notebooks-local Run notebook tests locally using nbval with sanitization + docs Convert notebooks to HTML for documentation ``` -Install quail app: +You can run any task with: + ``` -(venv)$ pip install -e . -# OR -$ make install +poe +# Example: +poe test +``` + +## Install from GitHub + +Check out code from the quail GitHub repo and start the installation: + +``` +$ git clone https://github.com/pacificclimate/quail.git +$ cd quail +``` + +Install requirements: + +``` +poe install-apt +poe install-r-pkgs +poe install ``` For development you can use this command: + ``` -$ pip install -e .[dev] -# OR -$ make develop +poe develop ``` ## Start `quail` PyWPS service + After successful installation you can start the service using the `quail` command-line. ``` -(venv)$ quail --help # show help -(venv)$ quail start # start service with default configuration +poetry run quail --help # show help +poe start # start service with default configuration # OR -(venv)$ quail start --daemon # start service as daemon +poetry run quail start --daemon # start service as daemon loading configuration forked process id: 42 ``` + The deployed WPS service is by default available on: http://localhost:5000/wps?service=WPS&version=1.0.0&request=GetCapabilities. @@ -63,21 +108,26 @@ $ netstat -nlp | grep :5000 ``` Check the log files for errors: + ``` $ tail -f pywps.log ``` + ... or do it the lazy way -You can also use the `Makefile` to start and stop the service: +You can also use `Poe` to start and stop the service: + ``` -$ make start -$ make status +$ poe start +$ poe status $ tail -f pywps.log -$ make stop +$ poe stop ``` ## Run `quail` as Docker container + You can also run `quail` as a Docker container. + ``` $ docker-compose build $ docker-compose up @@ -86,4 +136,5 @@ $ docker-compose up `quail` will be available on port `8103`. ## Use Ansible to deploy `quail` on your System + Use the [Ansible playbook](http://ansible-wps-playbook.readthedocs.io/en/latest/index.html) for PyWPS to deploy `quail` on your system. diff --git a/install_pkgs.R b/install_pkgs.R index 0d13c37..69d2363 100644 --- a/install_pkgs.R +++ b/install_pkgs.R @@ -1,27 +1,36 @@ -# Usage: -# Rscript install_pgks.R r_requirements.txt -# r_requirements delimited by '==' as in python requirements.txt - # Create user library -dir.create(Sys.getenv('R_LIBS_USER'), recursive = TRUE); -.libPaths(Sys.getenv('R_LIBS_USER')); +dir.create(Sys.getenv("R_LIBS_USER"), recursive = TRUE) +.libPaths(Sys.getenv("R_LIBS_USER")) + +# Install and load RcppTOML +if (!requireNamespace("RcppTOML", quietly = TRUE)) { + install.packages("RcppTOML", repos = "https://cloud.r-project.org") +} +library(RcppTOML) + +# Read the TOML file +toml_data <- RcppTOML::parseTOML("pyproject.toml") -# Install devtools and its dependencies -install.packages('devtools', dependencies=TRUE); +# Extract dependencies +deps <- toml_data$tool$quail$`r-dependencies` -# Install packages from requirements list -args <- commandArgs(trailingOnly = TRUE) -req_filename <- args[1] -requirements_file <- file(req_filename,open="r") -data <-readLines(requirements_file) -for (i in 1:length(data)){ - pkg_ver_pair <- unlist(stringr::str_split(data[i], "==")) - pkg<-pkg_ver_pair[1] - ver<-pkg_ver_pair[2] - if (is.na(ver)){ - devtools::install_version(pkg) - } else { - devtools::install_version(pkg, version = ver); +if (!requireNamespace("remotes", quietly = TRUE)) { + install.packages("remotes", repos = "https://cloud.r-project.org") +} + +# Install packages with versions using remotes +for (pkg in names(deps)) { + ver <- deps[[pkg]] + if (!(pkg %in% rownames(installed.packages()))) { + if (is.null(ver) || ver == "*" || ver == "") { + install.packages(pkg, repos = "https://cloud.r-project.org") + } else { + remotes::install_version(pkg, version = ver, repos = "https://cloud.r-project.org") + } } } -close(requirements_file) + + +remotes::install_github("pacificclimate/climdex.pcic@daf4790", + dependencies = TRUE, +) diff --git a/notebooks/wps_climdexInput_csv_demo.ipynb b/notebooks/wps_climdexInput_csv_demo.ipynb index 086455b..8b652a8 100644 --- a/notebooks/wps_climdexInput_csv_demo.ipynb +++ b/notebooks/wps_climdexInput_csv_demo.ipynb @@ -11,7 +11,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -20,7 +20,7 @@ "from birdy import WPSClient\n", "from rpy2 import robjects\n", "from urllib.request import urlretrieve\n", - "from pkg_resources import resource_filename\n", + "from importlib.resources import files\n", "from tempfile import NamedTemporaryFile\n", "\n", "from wps_tools.file_handling import csv_handler\n", @@ -187,18 +187,18 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"summer_days_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_input_csv(\n", " tmax_file_content=csv_handler(\n", - " resource_filename(\"tests\",\"data/1018935_MAX_TEMP.csv\")),\n", + " (files(\"tests\") / \"data/1018935_MAX_TEMP.csv\").resolve()),\n", " tmin_file_content=csv_handler(\n", - " resource_filename(\"tests\",\"data/1018935_MIN_TEMP.csv\")),\n", + " (files(\"tests\") / \"data/1018935_MIN_TEMP.csv\").resolve()),\n", " prec_file_content=csv_handler(\n", - " resource_filename(\"tests\",\"data/1018935_ONE_DAY_PRECIPITATION.csv\")),\n", + " (files(\"tests\") / \"data/1018935_ONE_DAY_PRECIPITATION.csv\").resolve()),\n", " tmax_column='MAX_TEMP',\n", " tmin_column='MIN_TEMP',\n", " prec_column='ONE_DAY_PRECIPITATION',\n", diff --git a/notebooks/wps_climdexInput_quantile_demo.ipynb b/notebooks/wps_climdexInput_quantile_demo.ipynb index 89ffefa..9e050b8 100644 --- a/notebooks/wps_climdexInput_quantile_demo.ipynb +++ b/notebooks/wps_climdexInput_quantile_demo.ipynb @@ -11,7 +11,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -20,7 +20,7 @@ "from birdy import WPSClient\n", "from rpy2 import robjects\n", "from urllib.request import urlretrieve\n", - "from pkg_resources import resource_filename\n", + "from importlib.resources import files\n", "from tempfile import NamedTemporaryFile\n", "\n", "from wps_tools.R import construct_r_out, test_rda_output\n", @@ -144,13 +144,13 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"quantile_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_quantile(\n", - " data_file=resource_filename(\"tests\",\"data/ec.1018935.rda\"),\n", + " data_file=(files(\"tests\") / \"data/ec.1018935.rda\").resolve(),\n", " data_vector=\"unlist(ec.1018935.tmax['MAX_TEMP'])\",\n", " quantiles_vector=\"c(0.1, 0.5, 0.9)\",\n", " vector_name=\"tmax_quantiles\",\n", @@ -209,13 +209,13 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"quantile_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_quantile(\n", - " data_file=resource_filename(\"tests\",\"data/ec.1018935.MAX_TEMP.rds\"),\n", + " data_file=(files(\"tests\") / \"data/ec.1018935.MAX_TEMP.rds\").resolve(),\n", " quantiles_vector=\"c(0.1, 0.5, 0.9)\",\n", " vector_name=\"tmax_quantiles\",\n", " )\n", diff --git a/notebooks/wps_climdexInput_raw_demo.ipynb b/notebooks/wps_climdexInput_raw_demo.ipynb index 88e6f38..7ded29d 100644 --- a/notebooks/wps_climdexInput_raw_demo.ipynb +++ b/notebooks/wps_climdexInput_raw_demo.ipynb @@ -11,7 +11,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -20,7 +20,7 @@ "from birdy import WPSClient\n", "from rpy2 import robjects\n", "from urllib.request import urlretrieve\n", - "from pkg_resources import resource_filename\n", + "from importlib.resources import files\n", "from tempfile import NamedTemporaryFile\n", "\n", "from wps_tools.testing import get_target_url\n", @@ -195,15 +195,15 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"summer_days_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_input_raw(\n", - " tmax_file=resource_filename(\"tests\",\"data/ec.1018935.rda\"),\n", - " tmin_file=resource_filename(\"tests\",\"data/ec.1018935.rda\"),\n", - " prec_file=resource_filename(\"tests\",\"data/ec.1018935.rda\"),\n", + " tmax_file=(files(\"tests\") / \"data/ec.1018935.rda\").resolve(),\n", + " tmin_file=(files(\"tests\") / \"data/ec.1018935.rda\").resolve(),\n", + " prec_file=(files(\"tests\") / \"data/ec.1018935.rda\").resolve(),\n", " tmax_name=\"ec.1018935.tmax\",\n", " tmin_name=\"ec.1018935.tmin\",\n", " prec_name=\"ec.1018935.prec\",\n", diff --git a/notebooks/wps_climdex_days_demo.ipynb b/notebooks/wps_climdex_days_demo.ipynb index a6d2003..270ec00 100644 --- a/notebooks/wps_climdex_days_demo.ipynb +++ b/notebooks/wps_climdex_days_demo.ipynb @@ -25,7 +25,7 @@ "from birdy import WPSClient\n", "from rpy2 import robjects\n", "from urllib.request import urlretrieve\n", - "from pkg_resources import resource_filename\n", + "from importlib.resources import files\n", "from tempfile import NamedTemporaryFile\n", "\n", "from wps_tools.output_handling import auto_construct_outputs\n", @@ -53,7 +53,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Using quail on https://docker-dev03.pcic.uvic.ca/twitcher/ows/proxy/quail/wps\n" + "Using quail on https://marble-dev01.pcic.uvic.ca/twitcher/ows/proxy/quail/wps\n" ] } ], @@ -149,7 +149,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"summer_days_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_days(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", " days_type=\"su\",\n", " output_file=output_file.name,\n", " )\n", @@ -171,7 +171,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"icing_days_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_days(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rda\"), \n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rda\").resolve(), \n", " days_type=\"id\",\n", " output_file=output_file.name,\n", " )\n", @@ -193,7 +193,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"frost_days_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_days(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rda\"), \n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rda\").resolve(), \n", " days_type=\"fd\",\n", " output_file=output_file.name,\n", " )\n", @@ -215,7 +215,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"frost_days_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_days(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rds\"), \n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rds\").resolve(), \n", " days_type=\"tr\",\n", " output_file=output_file.name,\n", " )\n", @@ -236,9 +236,9 @@ "outputs": [], "source": [ "climdex_inputs = [\n", - " resource_filename(\"tests\",\"data/climdexInput.rds\"),\n", - " resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", - " resource_filename(\"tests\",\"data/climdex_input_multiple.rda\")\n", + " (files(\"tests\") / \"data/climdexInput.rds\").resolve(),\n", + " (files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", + " (files(\"tests\") / \"data/climdex_input_multiple.rda\").resolve(),\n", "]\n", "with NamedTemporaryFile(suffix=\".rda\", prefix=\"frost_days_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_days(\n", @@ -285,7 +285,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 13, "metadata": {}, "outputs": [ { @@ -314,7 +314,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -330,7 +330,7 @@ " [ nan, 0.000000, nan, nan, ..., 0.000000, nan, 0.000000, nan]]]" ] }, - "execution_count": 15, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } @@ -348,7 +348,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 15, "metadata": {}, "outputs": [], "source": [ @@ -369,7 +369,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -383,7 +383,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.5" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/notebooks/wps_climdex_dtr_demo.ipynb b/notebooks/wps_climdex_dtr_demo.ipynb index 1fe9737..516a2e7 100644 --- a/notebooks/wps_climdex_dtr_demo.ipynb +++ b/notebooks/wps_climdex_dtr_demo.ipynb @@ -22,7 +22,7 @@ "from birdy import WPSClient\n", "from rpy2 import robjects\n", "from urllib.request import urlretrieve\n", - "from pkg_resources import resource_filename\n", + "from importlib.resources import files\n", "from tempfile import NamedTemporaryFile\n", "\n", "from wps_tools.R import rda_to_vector, construct_r_out, test_rda_output\n", @@ -49,7 +49,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Using quail on https://docker-dev03.pcic.uvic.ca/twitcher/ows/proxy/quail/wps\n" + "Using quail on https://marble-dev01.pcic.uvic.ca/twitcher/ows/proxy/quail/wps\n" ] } ], @@ -137,7 +137,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"dtr_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_dtr(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", " freq=\"annual\",\n", " output_file=output_file.name,\n", " )\n", @@ -159,7 +159,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"dtr_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_dtr(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rds\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rds\").resolve(),\n", " output_file=output_file.name,\n", " )\n", "dtr_url_rds = output.get()[0]" @@ -179,9 +179,9 @@ "outputs": [], "source": [ "climdex_inputs = [\n", - " resource_filename(\"tests\",\"data/climdexInput.rds\"),\n", - " resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", - " resource_filename(\"tests\",\"data/climdex_input_multiple.rda\")\n", + " (files(\"tests\") / \"data/climdexInput.rds\").resolve(),\n", + " (files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", + " (files(\"tests\") / \"data/climdex_input_multiple.rda\").resolve(),\n", "]\n", "with NamedTemporaryFile(suffix=\".rda\", prefix=\"dtr_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_dtr(\n", @@ -227,7 +227,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -258,7 +258,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 11, "metadata": {}, "outputs": [ { @@ -274,7 +274,7 @@ " [ nan, nan, nan, nan, ..., 7.883333, 7.048387, nan, nan]]]" ] }, - "execution_count": 14, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } @@ -293,7 +293,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 12, "metadata": {}, "outputs": [], "source": [ @@ -319,7 +319,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.5" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/notebooks/wps_climdex_get_available_indices.ipynb b/notebooks/wps_climdex_get_available_indices.ipynb index 26cec14..b3e4349 100644 --- a/notebooks/wps_climdex_get_available_indices.ipynb +++ b/notebooks/wps_climdex_get_available_indices.ipynb @@ -23,7 +23,7 @@ "from birdy import WPSClient\n", "from rpy2 import robjects\n", "from urllib.request import urlretrieve\n", - "from pkg_resources import resource_filename\n", + "from importlib.resources import files\n", "from tempfile import NamedTemporaryFile\n", "\n", "from wps_tools.testing import get_target_url\n", @@ -50,7 +50,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Using quail on https://docker-dev03.pcic.uvic.ca/twitcher/ows/proxy/quail/wps\n" + "Using quail on https://marble-dev01.pcic.uvic.ca/twitcher/ows/proxy/quail/wps\n" ] } ], @@ -138,7 +138,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"indices_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_get_available_indices(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", " ci_name=\"ci\",\n", " output_file=output_file.name,\n", " )\n", @@ -190,7 +190,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"indices_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_get_available_indices(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rds\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rds\").resolve(),\n", " ci_name=\"ci\",\n", " output_file=output_file.name,\n", " )" @@ -219,7 +219,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -233,7 +233,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.5" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/notebooks/wps_climdex_gsl_demo.ipynb b/notebooks/wps_climdex_gsl_demo.ipynb index a8c0997..4f1c565 100644 --- a/notebooks/wps_climdex_gsl_demo.ipynb +++ b/notebooks/wps_climdex_gsl_demo.ipynb @@ -22,7 +22,7 @@ "from birdy import WPSClient\n", "from rpy2 import robjects\n", "from urllib.request import urlretrieve\n", - "from pkg_resources import resource_filename\n", + "from importlib.resources import files\n", "from tempfile import NamedTemporaryFile\n", "\n", "from wps_tools.R import rda_to_vector, construct_r_out, test_rda_output\n", @@ -49,7 +49,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Using quail on https://docker-dev03.pcic.uvic.ca/twitcher/ows/proxy/quail/wps\n" + "Using quail on https://marble-dev01.pcic.uvic.ca/twitcher/ows/proxy/quail/wps\n" ] } ], @@ -137,7 +137,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"gsl_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_gsl(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", " output_file=output_file.name,\n", " )\n", "gsl_url = output.get()[0]" @@ -158,7 +158,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"gsl_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_gsl(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rds\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rds\").resolve(),\n", " output_file=output_file.name,\n", " )\n", "gsl_url_rds = output.get()[0]" @@ -178,9 +178,9 @@ "outputs": [], "source": [ "climdex_inputs = [\n", - " resource_filename(\"tests\",\"data/climdexInput.rds\"),\n", - " resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", - " resource_filename(\"tests\",\"data/climdex_input_multiple.rda\")\n", + " (files(\"tests\") / \"data/climdexInput.rds\").resolve(),\n", + " (files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", + " (files(\"tests\") / \"data/climdex_input_multiple.rda\").resolve(),\n", "]\n", "with NamedTemporaryFile(suffix=\".rda\", prefix=\"gsl_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_gsl(\n", @@ -199,7 +199,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -226,7 +226,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -242,7 +242,7 @@ " [ nan, 344.000000, nan, nan, ..., 359.000000, nan, 322.000000, nan]]]" ] }, - "execution_count": 11, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } @@ -261,7 +261,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ @@ -273,7 +273,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -287,7 +287,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.5" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/notebooks/wps_climdex_mmdmt_demo.ipynb b/notebooks/wps_climdex_mmdmt_demo.ipynb index a80391d..aed6a28 100644 --- a/notebooks/wps_climdex_mmdmt_demo.ipynb +++ b/notebooks/wps_climdex_mmdmt_demo.ipynb @@ -25,7 +25,7 @@ "from birdy import WPSClient\n", "from rpy2 import robjects\n", "from urllib.request import urlretrieve\n", - "from pkg_resources import resource_filename\n", + "from importlib.resources import files\n", "from tempfile import NamedTemporaryFile\n", "\n", "from wps_tools.R import rda_to_vector, construct_r_out, test_rda_output\n", @@ -52,7 +52,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Using quail on https://docker-dev03.pcic.uvic.ca/twitcher/ows/proxy/quail/wps\n" + "Using quail on https://marble-dev01.pcic.uvic.ca/twitcher/ows/proxy/quail/wps\n" ] } ], @@ -154,7 +154,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"txx_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_mmdmt(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", " month_type=\"txx\",\n", " output_file=output_file.name,\n", " )\n", @@ -176,7 +176,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"txx_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_mmdmt(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", " month_type=\"txx\",\n", " freq=\"annual\",\n", " output_file=output_file.name,\n", @@ -206,7 +206,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"tnx_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_mmdmt(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", " month_type=\"tnx\",\n", " output_file=output_file.name,\n", " )\n", @@ -228,7 +228,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"tnx_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_mmdmt(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", " month_type=\"tnx\",\n", " freq=\"annual\",\n", " output_file=output_file.name,\n", @@ -258,7 +258,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"txn_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_mmdmt(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", " month_type=\"txn\",\n", " output_file=output_file.name,\n", " )\n", @@ -286,9 +286,9 @@ "outputs": [], "source": [ "climdex_inputs = [\n", - " resource_filename(\"tests\",\"data/climdexInput.rds\"),\n", - " resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", - " resource_filename(\"tests\",\"data/climdex_input_multiple.rda\")\n", + " (files(\"tests\") / \"data/climdexInput.rds\").resolve(),\n", + " (files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", + " (files(\"tests\") / \"data/climdex_input_multiple.rda\").resolve(),\n", "]\n", "with NamedTemporaryFile(suffix=\".rda\", prefix=\"txn_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_mmdmt(\n", @@ -316,7 +316,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"tnn_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_mmdmt(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", " month_type=\"tnn\",\n", " output_file=output_file.name,\n", " )\n", @@ -338,7 +338,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"tnn_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_mmdmt(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rds\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rds\").resolve(),\n", " month_type=\"tnn\",\n", " freq=\"annual\",\n", " output_file=output_file.name,\n", @@ -355,7 +355,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -384,7 +384,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 15, "metadata": {}, "outputs": [ { @@ -400,7 +400,7 @@ " [ nan, nan, nan, nan, ..., 7.000000, 4.000000, nan, nan]]]" ] }, - "execution_count": 16, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } @@ -418,7 +418,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 16, "metadata": {}, "outputs": [], "source": [ @@ -451,7 +451,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -465,7 +465,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.5" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/notebooks/wps_climdex_ptot.ipynb b/notebooks/wps_climdex_ptot.ipynb index 1a10dd1..e9ea9e5 100644 --- a/notebooks/wps_climdex_ptot.ipynb +++ b/notebooks/wps_climdex_ptot.ipynb @@ -15,7 +15,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 12, "metadata": {}, "outputs": [], "source": [ @@ -24,7 +24,7 @@ "from birdy import WPSClient\n", "from rpy2 import robjects\n", "from urllib.request import urlretrieve\n", - "from pkg_resources import resource_filename\n", + "from importlib.resources import files\n", "from tempfile import NamedTemporaryFile\n", "\n", "from wps_tools.R import rda_to_vector, construct_r_out, test_rda_output\n", @@ -33,7 +33,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 13, "metadata": {}, "outputs": [], "source": [ @@ -44,14 +44,14 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Using quail on https://docker-dev03.pcic.uvic.ca/twitcher/ows/proxy/quail/wps\n" + "Using quail on https://marble-dev01.pcic.uvic.ca/twitcher/ows/proxy/quail/wps\n" ] } ], @@ -79,7 +79,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 15, "metadata": {}, "outputs": [ { @@ -133,13 +133,13 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"prcptot_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_ptot(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", " output_file=output_file.name,\n", " )\n", "prcptot_url = output.get()[0]" @@ -155,13 +155,13 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"r99ptot_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_ptot(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rds\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rds\").resolve(),\n", " threshold=99,\n", " output_file=output_file.name,\n", " )\n", @@ -178,14 +178,14 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "climdex_inputs = [\n", - " resource_filename(\"tests\",\"data/climdexInput.rds\"),\n", - " resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", - " resource_filename(\"tests\",\"data/climdex_input_multiple.rda\")\n", + " (files(\"tests\") / \"data/climdexInput.rds\").resolve(),\n", + " (files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", + " (files(\"tests\") / \"data/climdex_input_multiple.rda\").resolve(),\n", "]\n", "with NamedTemporaryFile(suffix=\".rda\", prefix=\"r95ptot_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_ptot(\n", @@ -205,7 +205,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 19, "metadata": {}, "outputs": [ { @@ -260,7 +260,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 20, "metadata": {}, "outputs": [ { @@ -280,7 +280,7 @@ " [ nan, 152.399997, nan, nan, ..., 0.000000, nan, 169.000000, nan]]]" ] }, - "execution_count": 11, + "execution_count": 20, "metadata": {}, "output_type": "execute_result" } @@ -299,7 +299,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 21, "metadata": {}, "outputs": [], "source": [ @@ -319,7 +319,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -333,7 +333,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.5" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/notebooks/wps_climdex_rmm_demo.ipynb b/notebooks/wps_climdex_rmm_demo.ipynb index fda386a..a269f27 100644 --- a/notebooks/wps_climdex_rmm_demo.ipynb +++ b/notebooks/wps_climdex_rmm_demo.ipynb @@ -26,7 +26,7 @@ "from birdy import WPSClient\n", "from rpy2 import robjects\n", "from urllib.request import urlretrieve\n", - "from pkg_resources import resource_filename\n", + "from importlib.resources import files\n", "from tempfile import NamedTemporaryFile\n", "\n", "from wps_tools.testing import get_target_url\n", @@ -53,7 +53,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Using quail on https://docker-dev03.pcic.uvic.ca/twitcher/ows/proxy/quail/wps\n" + "Using quail on https://marble-dev01.pcic.uvic.ca/twitcher/ows/proxy/quail/wps\n" ] } ], @@ -141,7 +141,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"r10mm_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_rmm(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", " threshold=10.0,\n", " output_file=output_file.name,\n", " )\n", @@ -164,7 +164,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"r20mm_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_rmm(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rds\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rds\").resolve(),\n", " threshold=20.0,\n", " output_file=output_file.name,\n", " )\n", @@ -186,9 +186,9 @@ "outputs": [], "source": [ "climdex_inputs = [\n", - " resource_filename(\"tests\",\"data/climdexInput.rds\"),\n", - " resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", - " resource_filename(\"tests\",\"data/climdex_input_multiple.rda\")\n", + " (files(\"tests\") / \"data/climdexInput.rds\").resolve(),\n", + " (files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", + " (files(\"tests\") / \"data/climdex_input_multiple.rda\").resolve(),\n", "]\n", "with NamedTemporaryFile(suffix=\".rda\", prefix=\"rm=nnmm_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_rmm(\n", @@ -307,7 +307,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -321,7 +321,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.5" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/notebooks/wps_climdex_rxnday_demo.ipynb b/notebooks/wps_climdex_rxnday_demo.ipynb index 7e6908a..dc1f7d7 100644 --- a/notebooks/wps_climdex_rxnday_demo.ipynb +++ b/notebooks/wps_climdex_rxnday_demo.ipynb @@ -24,7 +24,7 @@ "from birdy import WPSClient\n", "from rpy2 import robjects\n", "from urllib.request import urlretrieve\n", - "from pkg_resources import resource_filename\n", + "from importlib.resources import files\n", "from tempfile import NamedTemporaryFile\n", "\n", "from wps_tools.R import rda_to_vector, construct_r_out, test_rda_output\n", @@ -51,7 +51,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Using quail on https://docker-dev03.pcic.uvic.ca/twitcher/ows/proxy/quail/wps\n" + "Using quail on https://marble-dev01.pcic.uvic.ca/twitcher/ows/proxy/quail/wps\n" ] } ], @@ -145,7 +145,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"rx1day_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_rxnday(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", " freq=\"annual\",\n", " num_days=1,\n", " output_file=output_file.name,\n", @@ -168,7 +168,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"rx5day_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_rxnday(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rds\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rds\").resolve(),\n", " freq=\"annual\",\n", " num_days=5,\n", " center_mean_on_last_day=False,\n", @@ -191,9 +191,9 @@ "outputs": [], "source": [ "climdex_inputs = [\n", - " resource_filename(\"tests\",\"data/climdexInput.rds\"),\n", - " resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", - " resource_filename(\"tests\",\"data/climdex_input_multiple.rda\")\n", + " (files(\"tests\") / \"data/climdexInput.rds\").resolve(),\n", + " (files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", + " (files(\"tests\") / \"data/climdex_input_multiple.rda\").resolve(),\n", "]\n", "with NamedTemporaryFile(suffix=\".rda\", prefix=\"rx5day_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_rxnday(\n", @@ -215,7 +215,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -306,7 +306,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -320,7 +320,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.5" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/notebooks/wps_climdex_sdii_demo.ipynb b/notebooks/wps_climdex_sdii_demo.ipynb index d5002d3..9ec2499 100644 --- a/notebooks/wps_climdex_sdii_demo.ipynb +++ b/notebooks/wps_climdex_sdii_demo.ipynb @@ -22,7 +22,7 @@ "from birdy import WPSClient\n", "from rpy2 import robjects\n", "from urllib.request import urlretrieve\n", - "from pkg_resources import resource_filename\n", + "from importlib.resources import files\n", "from tempfile import NamedTemporaryFile\n", "\n", "from wps_tools.R import rda_to_vector, construct_r_out, test_rda_output\n", @@ -49,7 +49,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Using quail on https://docker-dev03.pcic.uvic.ca/twitcher/ows/proxy/quail/wps\n" + "Using quail on https://marble-dev01.pcic.uvic.ca/twitcher/ows/proxy/quail/wps\n" ] } ], @@ -134,7 +134,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"sdii_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_sdii(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", " output_file=output_file.name,\n", " )\n", "sdii_url = output.get()[0]" @@ -155,7 +155,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"sdii_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_sdii(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rds\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rds\").resolve(),\n", " output_file=output_file.name,\n", " )\n", "sdii_url = output.get()[0]" @@ -175,9 +175,9 @@ "outputs": [], "source": [ "climdex_inputs = [\n", - " resource_filename(\"tests\",\"data/climdexInput.rds\"),\n", - " resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", - " resource_filename(\"tests\",\"data/climdex_input_multiple.rda\")\n", + " (files(\"tests\") / \"data/climdexInput.rds\").resolve(),\n", + " (files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", + " (files(\"tests\") / \"data/climdex_input_multiple.rda\").resolve(),\n", "]\n", "with NamedTemporaryFile(suffix=\".rda\", prefix=\"sdii_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_sdii(\n", @@ -274,7 +274,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -288,7 +288,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.5" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/notebooks/wps_climdex_spells_demo.ipynb b/notebooks/wps_climdex_spells_demo.ipynb index 30626ff..5e278d9 100644 --- a/notebooks/wps_climdex_spells_demo.ipynb +++ b/notebooks/wps_climdex_spells_demo.ipynb @@ -24,7 +24,7 @@ "from birdy import WPSClient\n", "from rpy2 import robjects\n", "from urllib.request import urlretrieve\n", - "from pkg_resources import resource_filename\n", + "from importlib.resources import files\n", "from tempfile import NamedTemporaryFile\n", "\n", "from wps_tools.R import rda_to_vector, construct_r_out, test_rda_output\n", @@ -51,7 +51,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Using quail on https://docker-dev03.pcic.uvic.ca/twitcher/ows/proxy/quail/wps\n" + "Using quail on https://marble-dev01.pcic.uvic.ca/twitcher/ows/proxy/quail/wps\n" ] } ], @@ -143,7 +143,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"wsdi_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_spells(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", " func=\"wsdi\",\n", " output_file=output_file.name,\n", " )\n", @@ -165,7 +165,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"wsdi_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_spells(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", " func=\"wsdi\",\n", " span_years=True,\n", " output_file=output_file.name,\n", @@ -189,7 +189,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"csdi_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_spells(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", " func=\"csdi\",\n", " output_file=output_file.name,\n", " )\n", @@ -211,7 +211,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"csdi_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_spells(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", " func=\"csdi\",\n", " span_years=True,\n", " output_file=output_file.name,\n", @@ -235,7 +235,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"cdd_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_spells(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", " func=\"cdd\",\n", " output_file=output_file.name,\n", " )\n", @@ -257,7 +257,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"cdd_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_spells(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", " func=\"cdd\",\n", " span_years=True,\n", " output_file=output_file.name,\n", @@ -281,7 +281,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"cwd_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_spells(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rds\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rds\").resolve(),\n", " func=\"cwd\",\n", " output_file=output_file.name,\n", " )\n", @@ -302,9 +302,9 @@ "outputs": [], "source": [ "climdex_inputs = [\n", - " resource_filename(\"tests\",\"data/climdexInput.rds\"),\n", - " resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", - " resource_filename(\"tests\",\"data/climdex_input_multiple.rda\")\n", + " (files(\"tests\") / \"data/climdexInput.rds\").resolve(),\n", + " (files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", + " (files(\"tests\") / \"data/climdex_input_multiple.rda\").resolve(),\n", "]\n", "with NamedTemporaryFile(suffix=\".rda\", prefix=\"cwd_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_spells(\n", @@ -351,7 +351,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 24, "metadata": {}, "outputs": [ { @@ -367,7 +367,7 @@ " [ nan, 13.000000, nan, nan, ..., 19.000000, nan, 15.000000, nan]]]" ] }, - "execution_count": 15, + "execution_count": 24, "metadata": {}, "output_type": "execute_result" } @@ -458,7 +458,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -472,7 +472,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.5" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/notebooks/wps_climdex_temp_pctl.ipynb b/notebooks/wps_climdex_temp_pctl.ipynb index bf0bb24..e94a5d9 100644 --- a/notebooks/wps_climdex_temp_pctl.ipynb +++ b/notebooks/wps_climdex_temp_pctl.ipynb @@ -25,7 +25,7 @@ "from birdy import WPSClient\n", "from rpy2 import robjects\n", "from urllib.request import urlretrieve\n", - "from pkg_resources import resource_filename\n", + "from importlib.resources import files\n", "from tempfile import NamedTemporaryFile\n", "\n", "from wps_tools.R import rda_to_vector, construct_r_out, test_rda_output\n", @@ -52,7 +52,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Using quail on https://docker-dev03.pcic.uvic.ca/twitcher/ows/proxy/quail/wps\n" + "Using quail on https://marble-dev01.pcic.uvic.ca/twitcher/ows/proxy/quail/wps\n" ] } ], @@ -150,7 +150,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"tn10p_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_temp_pctl(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", " func=\"tn10p\",\n", " freq=\"monthly\",\n", " output_file=output_file.name,\n", @@ -180,7 +180,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"tn90p_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_temp_pctl(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", " func=\"tn90p\",\n", " freq=\"monthly\",\n", " output_file=output_file.name,\n", @@ -211,7 +211,7 @@ "source": [ "with NamedTemporaryFile(suffix=\".rda\", prefix=\"tx10p_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_temp_pctl(\n", - " climdex_input=resource_filename(\"tests\",\"data/climdexInput.rds\"),\n", + " climdex_input=(files(\"tests\") / \"data/climdexInput.rds\").resolve(),\n", " func=\"tx10p\",\n", " freq=\"monthly\",\n", " output_file=output_file.name,\n", @@ -241,9 +241,9 @@ "outputs": [], "source": [ "climdex_inputs = [\n", - " resource_filename(\"tests\",\"data/climdexInput.rds\"),\n", - " resource_filename(\"tests\",\"data/climdexInput.rda\"),\n", - " resource_filename(\"tests\",\"data/climdex_input_multiple.rda\")\n", + " (files(\"tests\") / \"data/climdexInput.rds\").resolve(),\n", + " (files(\"tests\") / \"data/climdexInput.rda\").resolve(),\n", + " (files(\"tests\") / \"data/climdex_input_multiple.rda\").resolve(),\n", "]\n", "with NamedTemporaryFile(suffix=\".rda\", prefix=\"tx90p_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_temp_pctl(\n", @@ -352,7 +352,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -366,7 +366,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.5" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..04dac65 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,220 @@ +[project] +name = "quail" +version = "0.7.1" +description = "A Web Processing Service for Climate Data Analysis." +authors = [{ name = "Nikola Rados", email = "nrados@uvic.ca" }] +license = { text = "GNU General Public License v3 (GPLv3)" } +readme = "README.md" +requires-python = ">=3.11, <=3.13" +keywords = ["wps", "pywps", "birdhouse", "quail"] +classifiers = [ + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "Intended Audience :: Science/Research", + "Operating System :: MacOS :: MacOS X", + "Operating System :: POSIX", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Scientific/Engineering :: Atmospheric Science", + "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", +] + +dependencies = [ + "click>=8.2.1,<9.0.0", + "gunicorn>=23.0.0,<24.0.0", + "jinja2>=3.1.6,<4.0.0", + "nchelpers>=5.5.12,<6.0.0", + "psutil>=7.0.0,<8.0.0", + "pyproj>=3.7.1,<4.0.0", + "pywps>=4.6.0,<5.0.0", + "rpy2>=3.3.6,<4.0.0", + "setuptools>=80.9.0,<81.0.0", + "werkzeug>=3.1.3,<4.0.0", + "wps-tools[r]>=2.1.4,<3.0.0", +] + +[project.optional-dependencies] +dev = [ + "bumpversion>=0.6.0,<1.0.0", + "cruft>=2.16.0,<3.0.0", + "flake8>=7.2.0,<8.0.0", + "ipython>=9.2.0,<10.0.0", + "nbconvert>=7.16.6,<8.0.0", + "nbsphinx>=0.9.7,<1.0.0", + "nbval>=0.11.0,<1.0.0", + "pytest>=8.3.5,<9.0.0", + "pytest_flake8>=1.3.0,<2.0.0", + "pytest_notebook>=0.10.0,<1.0.0", + + # Changing dependencies above this comment will create merge conflicts when updating the cookiecutter template with cruft. Add extra requirements below this line. + "birdhouse_birdy>=0.8.7,<1.0.0", + "black>=25.1.0,<26.0.0", + "jupyterlab>=4.4.3,<5.0.0", + "nbclient>=0.5.13,<1.0.0", + +] + +[project.scripts] +quail = "quail.cli:cli" + +[project.urls] +homepage = "http://www.pacificclimate.org/" +repository = "https://github.com/pacificclimate/quail" + +[build-system] +requires = ["poetry-core>=2.0.0,<3.0.0"] +build-backend = "poetry.core.masonry.api" + +[tool.quail.r-dependencies] +PCICt = "0.5.4.1" +# climdex.pcic = "1.1.11" + + +[[tool.poetry.source]] +name = "pcic" +url = "https://pypi.pacificclimate.org/simple" +priority = "supplemental" + +[tool.pytest.ini_options] +markers = [ + "online: marks tests that use online resources (deselect with '-m \"not online\"')", + "slow: marks tests that are slow (deselect with '-m \"not slow\"')", +] + +[[tool.poetry.include]] +path = "*.txt" +format = ["sdist", "wheel"] + +[[tool.poetry.include]] +path = "*.md" +format = ["sdist", "wheel"] + +[[tool.poetry.include]] +path = "quail" +format = ["sdist", "wheel"] + +[tool.poe.tasks] + +# ── System & R deps ───────────────────────────────────────── + +[tool.poe.tasks.install-apt] +cmd = "sudo apt-get install libudunits2-dev libnetcdf-dev" +help = "Install required system libraries for R packages" + +[tool.poe.tasks.install-r-pkgs] +cmd = "Rscript install_pkgs.R" +help = "Install required R packages " + +# ── Python env via Poetry ──────────────────────────────────── + +[tool.poe.tasks.install] +cmd = "poetry install" +help = "Install Python project dependencies using Poetry" + +[tool.poe.tasks.develop] +cmd = "poetry install --extras dev" +help = "Install development dependencies using Poetry" + +[tool.poe.tasks.start] +cmd = "poetry run quail start -d" +help = "Start the Quail service in detached mode" + +[tool.poe.tasks.stop] +cmd = "poetry run quail stop" +help = "Stop the quail service" + +[tool.poe.tasks.restart] +sequence = ["stop", "start"] +help = "Restart the Quail service" + +[tool.poe.tasks.status] +cmd = "poetry run quail status" +help = "Show the status of the Quail service" + +[tool.poe.tasks.dist] +cmd = "poetry build" +help = "Build a distribution package for the project" + +# ── Tests & lint ───────────────────────────────────────────── + +[tool.poe.tasks.test] +cmd = "pytest -v -m 'not slow and not online' tests/" +help = "Run fast, offline unit tests" + +[tool.poe.tasks.test-all] +cmd = "pytest -v tests/" +help = "Run all tests, including online ones" + +[tool.poe.tasks.lint] +cmd = "black . --check" +help = "Check code formatting using Black" + +# ── Notebook tasks ────────────────────────────────────────── + +[tool.poe.tasks.prepare-notebooks] +cmd = "curl -L https://github.com/Ouranosinc/PAVICS-e2e-workflow-tests/raw/master/notebooks/output-sanitize.cfg -o docs/output-sanitize.cfg --silent" +help = "Download the output sanitizer config for notebook tests" + +[tool.poe.tasks.test-notebooks] +sequence = ["prepare-notebooks", "test-notebooks-local"] +help = "Run all local notebook tests with sanitized output" + +[tool.poe.tasks.test-notebooks-local] +cmd = "pytest --nbval --verbose notebooks/ --sanitize-with docs/output-sanitize.cfg --ignore notebooks/.ipynb_checkpoints" +env = { LOCAL_URL = "http://localhost:5000" } +help = "Run notebook tests locally using nbval with sanitization" + +# [tool.poe.tasks.test-notebooks-prod] +# sequence = ["prepare-notebooks", "test-notebooks-prod-run"] +# help = "Run notebook tests against the production environment" + +# [tool.poe.tasks.test-notebooks-prod-run] +# cmd = "pytest --nbval --verbose notebooks/ --sanitize-with docs/output-sanitize.cfg --ignore notebooks/.ipynb_checkpoints" + +# [tool.poe.tasks.test-notebooks-dev] +# sequence = ["prepare-notebooks", "test-notebooks-dev-run"] +# help = "Run notebook tests against the dev environment" + +# [tool.poe.tasks.test-notebooks-dev-run] +# cmd = "pytest --nbval --verbose notebooks/ --sanitize-with docs/output-sanitize.cfg --ignore notebooks/.ipynb_checkpoints" +# env = { DEV_URL = "http://docker-dev03.pcic.uvic.ca:30103/wps" } + +# [tool.poe.tasks.test-notebooks-custom] +# sequence = ["prepare-notebooks", "run-custom-port-test"] +# help = "Run notebook tests against a custom dev server port" + +# [tool.poe.tasks.run-custom-port-test] +# shell = "read -p 'Target port: ' PORT && env DEV_URL=http://docker-dev03.pcic.uvic.ca:$PORT/wps pytest --nbval --verbose notebooks/ --sanitize-with docs/output-sanitize.cfg --ignore notebooks/.ipynb_checkpoints" + +# ── Documentation ──────────────────────────────────────────── + +[tool.poe.tasks.docs] +cmd = "jupyter nbconvert --to html notebooks/* --output-dir docs/formatted_demos/" +help = "Convert notebooks to HTML for documentation" + +[tool.bumpversion] +current_version = "0.7.1" +commit = true +tag = true + +[tool.bumpversion.file_patterns] +"quail/__version__.py" = [ + "__version__ = '{current_version}'", + "__version__ = '{new_version}'", +] +"docs/source/conf.py" = ["version|release = {current_version}", "{new_version}"] +"Dockerfile" = ["Version=\"{current_version}\"", "Version=\"{new_version}\""] +".cruft.json" = [ + "\"version\": \"{current_version}\"", + "\"version\": \"{new_version}\"", +] + +[tool.flake8] +max-line-length = 120 +exclude = [".git", "__pycache__", "docs/source/conf.py", "build", "dist", "src"] + +[tool.doc8] +ignore-path = ["docs/build", "docs/source/_templates", "docs/source/_static"] +max-line-length = 120 diff --git a/pytest.ini b/pytest.ini deleted file mode 100644 index 7332916..0000000 --- a/pytest.ini +++ /dev/null @@ -1,4 +0,0 @@ -[pytest] -markers = - online: marks tests that use online resources (deselect with '-m "not online"') - slow: marks tests that are slow (deselect with '-m "not slow"') diff --git a/quail/utils.py b/quail/utils.py index 8dd45b5..b024574 100644 --- a/quail/utils.py +++ b/quail/utils.py @@ -6,7 +6,7 @@ # Libraries for test functions from urllib.request import urlretrieve -from pkg_resources import resource_filename +from importlib.resources import files from tempfile import NamedTemporaryFile # PCIC libraries @@ -128,9 +128,7 @@ def test_ci_output(url, vector_name, expected_file, expected_vector_name): output_slot = robjects.r(f"{vector_name}@{slot}") robjects.r( - "load(file='{}')".format( - resource_filename("tests", f"data/{expected_file}") - ) + f"load(file='{(files('tests') / 'data' / expected_file).resolve()}')" ) expected_slot = robjects.r(f"{expected_vector_name}@{slot}") diff --git a/r_requirements.txt b/r_requirements.txt deleted file mode 100644 index bb97c65..0000000 --- a/r_requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -PCICt==0.5.4.1 -climdex.pcic==1.1.11 diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index d103b44..0000000 --- a/requirements.txt +++ /dev/null @@ -1,8 +0,0 @@ -pywps==4.2.6 -jinja2 -click -psutil -rpy2==3.3.6 -nchelpers==5.5.7 -werkzeug==1.0.1 -wps_tools[r]==2.0.0 diff --git a/requirements_dev.txt b/requirements_dev.txt deleted file mode 100644 index ae04d7d..0000000 --- a/requirements_dev.txt +++ /dev/null @@ -1,17 +0,0 @@ -pytest>=6.0 -flake8 -pytest-flake8 -ipython -pytest-notebook -nbsphinx -nbval>=0.9.6 -nbconvert -Sphinx==2.4.4 -bumpversion -twine -cruft -# Changing dependencies above this comment will create merge conflicts when updating the cookiecutter template with cruft. Add extra requirements below this line. -nbclient~=0.5.10 -black -birdhouse-birdy -jupyterlab diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index cfe3ba5..0000000 --- a/setup.cfg +++ /dev/null @@ -1,47 +0,0 @@ -[bumpversion] -current_version = 0.4.2 -commit = True -tag = True - -[metadata] -description-file = README.md - -[bumpversion:file:quail/__version__.py] -search = __version__ = '{current_version}' -replace = __version__ = '{new_version}' - -[bumpversion:file:docs/source/conf.py] -search = version|release = {current_version} -replace = {new_version} - -[bumpversion:file:Dockerfile] -search = Version="{current_version}" -replace = Version="{new_version}" - -[bumpversion:file:.cruft.json] -search = "version": "{current_version}", -replace = "version": "{new_version}", - -[tool:pytest] -addopts = - --strict - --tb=native - tests/ -python_files = test_*.py -markers = - online: mark test to need internet connection - slow: mark test to be slow - -[flake8] -max-line-length = 120 -exclude = - .git, - __pycache__, - docs/source/conf.py, - build, - dist, - src, - -[doc8] -ignore-path = docs/build,docs/source/_templates,docs/source/_static -max-line-length = 120 diff --git a/setup.py b/setup.py deleted file mode 100644 index 81ab455..0000000 --- a/setup.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -"""The setup script.""" - -import os - -from setuptools import setup, find_packages - -here = os.path.abspath(os.path.dirname(__file__)) -README = open(os.path.join(here, "README.md")).read() -CHANGES = open(os.path.join(here, "CHANGES.md")).read() -REQUIRES_PYTHON = ">=3.7.0" - -about = {} -with open(os.path.join(here, "quail", "__version__.py"), "r") as f: - exec(f.read(), about) - -reqs = [line.strip() for line in open("requirements.txt")] -dev_reqs = [line.strip() for line in open("requirements_dev.txt")] - -classifiers = [ - "Development Status :: 3 - Alpha", - "Intended Audience :: Developers", - "Intended Audience :: Science/Research", - "Operating System :: MacOS :: MacOS X", - "Operating System :: POSIX", - "Programming Language :: Python", - "Natural Language :: English", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Topic :: Scientific/Engineering :: Atmospheric Science", - "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", -] - -setup( - name="quail", - version=about["__version__"], - description="A Web Processing Service for Climate Data Analysis.", - long_description=README + "\n\n" + CHANGES, - long_description_content_type="text/x-rst", - author=about["__author__"], - author_email=about["__email__"], - url="https://github.com/nikola-rados/quail", - python_requires=REQUIRES_PYTHON, - classifiers=classifiers, - license="GNU General Public License v3", - keywords="wps pywps birdhouse quail", - packages=find_packages(), - include_package_data=True, - install_requires=reqs, - extras_require={ - "dev": dev_reqs, - }, # pip install ".[dev]" - entry_points={ - "console_scripts": [ - "quail=quail.cli:cli", - ] - }, -) diff --git a/tests/conftest.py b/tests/conftest.py index 88d4963..81e816d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,20 +1,18 @@ import pytest -from pkg_resources import resource_filename +from importlib.resources import files from wps_tools.file_handling import csv_handler @pytest.fixture def tmax_file_content(): - return csv_handler(resource_filename("tests", "data/1018935_MAX_TEMP.csv")) + return csv_handler((files("tests") / "data/1018935_MAX_TEMP.csv")) @pytest.fixture def tmin_file_content(): - return csv_handler(resource_filename("tests", "data/1018935_MIN_TEMP.csv")) + return csv_handler((files("tests") / "data/1018935_MIN_TEMP.csv")) @pytest.fixture def prec_file_content(): - return csv_handler( - resource_filename("tests", "data/1018935_ONE_DAY_PRECIPITATION.csv") - ) + return csv_handler((files("tests") / "data/1018935_ONE_DAY_PRECIPITATION.csv")) diff --git a/tests/test_utils.py b/tests/test_utils.py index de14e9b..f955988 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,5 +1,5 @@ import pytest -from pkg_resources import resource_filename +from importlib.resources import files from pywps.app.exceptions import ProcessError from quail.utils import ( @@ -13,8 +13,8 @@ @pytest.mark.parametrize( ("r_file"), [ - resource_filename("tests", "data/climdexInput.rda"), - resource_filename("tests", "data/climdex_input_multiple.rda"), + str(files("tests") / "data/climdexInput.rda"), + str(files("tests") / "data/climdex_input_multiple.rda"), ], ) def test_get_ClimdexInputs(r_file): @@ -27,8 +27,8 @@ def test_get_ClimdexInputs(r_file): @pytest.mark.parametrize( ("r_file"), [ - resource_filename("tests", "data/expected_days_data.rda"), - resource_filename("tests", "data/expected_gsl.rda"), + str(files("tests") / "data/expected_days_data.rda"), + str(files("tests") / "data/expected_gsl.rda"), ], ) def test_get_ClimdexInputs_err(r_file): @@ -39,7 +39,7 @@ def test_get_ClimdexInputs_err(r_file): @pytest.mark.parametrize( ("r_file"), [ - resource_filename("tests", "data/climdexInput.rds"), + str(files("tests") / "data/climdexInput.rds"), ], ) def test_load_rds_ci(r_file): @@ -50,9 +50,9 @@ def test_load_rds_ci(r_file): @pytest.mark.parametrize( ("r_file"), [ - resource_filename("tests", "data/climdexInput.rda"), - resource_filename("tests", "data/climdexInput.rds"), - resource_filename("tests", "data/climdex_input_multiple.rda"), + str(files("tests") / "data/climdexInput.rda"), + str(files("tests") / "data/climdexInput.rds"), + str(files("tests") / "data/climdex_input_multiple.rda"), ], ) def test_load_cis(r_file): @@ -65,8 +65,8 @@ def test_load_cis(r_file): @pytest.mark.parametrize( ("r_file"), [ - resource_filename("tests", "data/expected_days_data.rda"), - resource_filename("tests", "data/1018935_MAX_TEMP.csv"), + str(files("tests") / "data/expected_days_data.rda"), + str(files("tests") / "data/1018935_MAX_TEMP.csv"), ], ) def test_load_cis_err(r_file): @@ -88,7 +88,7 @@ def test_validate_vectors(vectors): @pytest.mark.parametrize( ("vectors"), - [[("()")], [("c'cats', 'dogs')")]], + [["()"], ["c'cats', 'dogs')"]], ) def test_validate_vectors_err(vectors): with pytest.raises(ProcessError) as e: