From ba2f13a4529c9bacfcb9f94a0ea20f8cdb6e2777 Mon Sep 17 00:00:00 2001 From: Quintin Date: Tue, 6 May 2025 13:45:25 -0700 Subject: [PATCH 01/15] WIP: Poetry, bump CI actions, use Poe --- .github/workflows/docker-publish.yml | 4 +- .github/workflows/python-ci.yml | 57 ++++--- Dockerfile | 61 ++++---- install_pkgs.R | 53 ++++--- pyproject.toml | 219 +++++++++++++++++++++++++++ 5 files changed, 314 insertions(+), 80 deletions(-) create mode 100644 pyproject.toml 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..5fa30c4 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -4,36 +4,35 @@ 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.10, 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 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: Install Python dependencies + run: | + curl -sSL https://install.python-poetry.org | python3 - + echo "$HOME/.local/bin" >> $GITHUB_PATH + poetry install --extras "dev" + - 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 + - name: Code Quality + run: black . --check diff --git a/Dockerfile b/Dockerfile index 2534495..86b1cb3 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,32 @@ 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 -sSL https://install.python-poetry.org | python3 + + +RUN poetry config virtualenvs.in-project true && \ + poetry lock && \ + 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/install_pkgs.R b/install_pkgs.R index 0d13c37..2b48418 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); + +# Install devtools +install.packages("devtools", dependencies = TRUE) +library(devtools) + +# Install packages with versions +for (pkg in names(deps)) { + ver <- deps[[pkg]] + if (!(pkg %in% rownames(installed.packages()))) { + if (is.null(ver) || ver == "*" || ver == "") { + install_version(pkg) + } else { + install_version(pkg, version = ver) + } } } -close(requirements_file) + +install.packages("githubinstall") +library(githubinstall) +gh_install_packages("pacificclimate/climdex.pcic", ref = "daf4790") # TODO in climdex.pcic: Release tag v.1.1.11 and update ref diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..e042587 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,219 @@ +[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.10, <=3.12" +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.10", + "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 = [ + "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", + "gunicorn>=20.1.0", +] + +[project.optional-dependencies] +dev = [ + "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", +] + +[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 From fed6f9f2353fb2ef87b25c6466e0b4b5ef79f067 Mon Sep 17 00:00:00 2001 From: Quintin Date: Tue, 6 May 2025 13:47:46 -0700 Subject: [PATCH 02/15] WIP: Remove old setup files --- MANIFEST.in | 6 -- Makefile | 187 ------------------------------------------- pytest.ini | 4 - r_requirements.txt | 2 - requirements.txt | 8 -- requirements_dev.txt | 17 ---- setup.cfg | 47 ----------- setup.py | 61 -------------- 8 files changed, 332 deletions(-) delete mode 100644 MANIFEST.in delete mode 100644 Makefile delete mode 100644 pytest.ini delete mode 100644 r_requirements.txt delete mode 100644 requirements.txt delete mode 100644 requirements_dev.txt delete mode 100644 setup.cfg delete mode 100644 setup.py 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/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/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", - ] - }, -) From 52c6f5c24c471278b24f92ff1cba6be6eaa8ee95 Mon Sep 17 00:00:00 2001 From: Quintin Date: Tue, 6 May 2025 13:56:41 -0700 Subject: [PATCH 03/15] Address deprecations in demo notebooks --- .../wps_climdexInput_csv_demo.html | 16586 +++++---------- .../wps_climdexInput_quantile_demo.html | 16891 +++++---------- .../wps_climdexInput_raw_demo.html | 16596 +++++---------- .../wps_climdex_days_demo.html | 17023 +++++---------- .../formatted_demos/wps_climdex_dtr_demo.html | 16939 +++++---------- .../wps_climdex_get_available_indices.html | 16875 +++++---------- .../formatted_demos/wps_climdex_gsl_demo.html | 16892 +++++---------- .../wps_climdex_mmdmt_demo.html | 17082 +++++---------- docs/formatted_demos/wps_climdex_ptot.html | 16904 +++++---------- .../formatted_demos/wps_climdex_rmm_demo.html | 16904 +++++---------- .../wps_climdex_rxnday_demo.html | 16915 +++++---------- .../wps_climdex_sdii_demo.html | 16880 +++++---------- .../wps_climdex_spells_demo.html | 17090 +++++----------- .../wps_climdex_temp_pctl.html | 16980 +++++---------- notebooks/wps_climdexInput_csv_demo.ipynb | 12 +- .../wps_climdexInput_quantile_demo.ipynb | 12 +- notebooks/wps_climdexInput_raw_demo.ipynb | 12 +- notebooks/wps_climdex_days_demo.ipynb | 28 +- notebooks/wps_climdex_dtr_demo.ipynb | 20 +- .../wps_climdex_get_available_indices.ipynb | 12 +- notebooks/wps_climdex_gsl_demo.ipynb | 20 +- notebooks/wps_climdex_mmdmt_demo.ipynb | 40 +- notebooks/wps_climdex_ptot.ipynb | 20 +- notebooks/wps_climdex_rmm_demo.ipynb | 20 +- notebooks/wps_climdex_rxnday_demo.ipynb | 20 +- notebooks/wps_climdex_sdii_demo.ipynb | 20 +- notebooks/wps_climdex_spells_demo.ipynb | 40 +- notebooks/wps_climdex_temp_pctl.ipynb | 24 +- 28 files changed, 71220 insertions(+), 165637 deletions(-) diff --git a/docs/formatted_demos/wps_climdexInput_csv_demo.html b/docs/formatted_demos/wps_climdexInput_csv_demo.html index 9b745db..ed4f0a0 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..e97aece 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..ee3c6fe 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..b739557 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..7725b74 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..4f6cd00 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..f223604 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..5573469 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..8eea372 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..eb68993 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..87545b3 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..92663d3 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/notebooks/wps_climdexInput_csv_demo.ipynb b/notebooks/wps_climdexInput_csv_demo.ipynb index 086455b..652f456 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..83b281e 100644 --- a/notebooks/wps_climdex_days_demo.ipynb +++ b/notebooks/wps_climdex_days_demo.ipynb @@ -16,7 +16,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -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", @@ -143,13 +143,13 @@ }, { "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_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", @@ -165,13 +165,13 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, "outputs": [], "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", @@ -187,13 +187,13 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, "outputs": [], "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", @@ -209,13 +209,13 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, "outputs": [], "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", @@ -231,14 +231,14 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "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=\"frost_days_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_days(\n", diff --git a/notebooks/wps_climdex_dtr_demo.ipynb b/notebooks/wps_climdex_dtr_demo.ipynb index 1fe9737..cb9d09c 100644 --- a/notebooks/wps_climdex_dtr_demo.ipynb +++ b/notebooks/wps_climdex_dtr_demo.ipynb @@ -13,7 +13,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -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", @@ -131,13 +131,13 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [], "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", @@ -153,13 +153,13 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, "outputs": [], "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]" @@ -174,14 +174,14 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "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=\"dtr_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_dtr(\n", diff --git a/notebooks/wps_climdex_get_available_indices.ipynb b/notebooks/wps_climdex_get_available_indices.ipynb index 26cec14..7440292 100644 --- a/notebooks/wps_climdex_get_available_indices.ipynb +++ b/notebooks/wps_climdex_get_available_indices.ipynb @@ -13,7 +13,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -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", @@ -132,13 +132,13 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [], "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", @@ -184,13 +184,13 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, "outputs": [], "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", " )" diff --git a/notebooks/wps_climdex_gsl_demo.ipynb b/notebooks/wps_climdex_gsl_demo.ipynb index a8c0997..06381d4 100644 --- a/notebooks/wps_climdex_gsl_demo.ipynb +++ b/notebooks/wps_climdex_gsl_demo.ipynb @@ -13,7 +13,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -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", @@ -131,13 +131,13 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [], "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]" @@ -152,13 +152,13 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, "outputs": [], "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]" @@ -173,14 +173,14 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "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=\"gsl_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_gsl(\n", diff --git a/notebooks/wps_climdex_mmdmt_demo.ipynb b/notebooks/wps_climdex_mmdmt_demo.ipynb index a80391d..e5d0453 100644 --- a/notebooks/wps_climdex_mmdmt_demo.ipynb +++ b/notebooks/wps_climdex_mmdmt_demo.ipynb @@ -16,7 +16,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -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", @@ -148,13 +148,13 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [], "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", @@ -170,13 +170,13 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, "outputs": [], "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", @@ -200,13 +200,13 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, "outputs": [], "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", @@ -222,13 +222,13 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, "outputs": [], "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", @@ -252,13 +252,13 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, "outputs": [], "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", @@ -281,14 +281,14 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "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=\"txn_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_mmdmt(\n", @@ -310,13 +310,13 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": {}, "outputs": [], "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", @@ -332,13 +332,13 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": {}, "outputs": [], "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", diff --git a/notebooks/wps_climdex_ptot.ipynb b/notebooks/wps_climdex_ptot.ipynb index 1a10dd1..377b8f3 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": null, "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", @@ -133,13 +133,13 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "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": null, "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": null, "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", diff --git a/notebooks/wps_climdex_rmm_demo.ipynb b/notebooks/wps_climdex_rmm_demo.ipynb index fda386a..fbac079 100644 --- a/notebooks/wps_climdex_rmm_demo.ipynb +++ b/notebooks/wps_climdex_rmm_demo.ipynb @@ -17,7 +17,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -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", @@ -135,13 +135,13 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [], "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", @@ -158,13 +158,13 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, "outputs": [], "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", @@ -181,14 +181,14 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "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=\"rm=nnmm_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_rmm(\n", diff --git a/notebooks/wps_climdex_rxnday_demo.ipynb b/notebooks/wps_climdex_rxnday_demo.ipynb index 7e6908a..995b4a2 100644 --- a/notebooks/wps_climdex_rxnday_demo.ipynb +++ b/notebooks/wps_climdex_rxnday_demo.ipynb @@ -15,7 +15,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "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", @@ -139,13 +139,13 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [], "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", @@ -162,13 +162,13 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, "outputs": [], "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", @@ -186,14 +186,14 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "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=\"rx5day_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_rxnday(\n", diff --git a/notebooks/wps_climdex_sdii_demo.ipynb b/notebooks/wps_climdex_sdii_demo.ipynb index d5002d3..c450f7d 100644 --- a/notebooks/wps_climdex_sdii_demo.ipynb +++ b/notebooks/wps_climdex_sdii_demo.ipynb @@ -13,7 +13,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -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", @@ -128,13 +128,13 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [], "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]" @@ -149,13 +149,13 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, "outputs": [], "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]" @@ -170,14 +170,14 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "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=\"sdii_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_sdii(\n", diff --git a/notebooks/wps_climdex_spells_demo.ipynb b/notebooks/wps_climdex_spells_demo.ipynb index 30626ff..76aa022 100644 --- a/notebooks/wps_climdex_spells_demo.ipynb +++ b/notebooks/wps_climdex_spells_demo.ipynb @@ -15,7 +15,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "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", @@ -137,13 +137,13 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [], "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", @@ -159,13 +159,13 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, "outputs": [], "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", @@ -183,13 +183,13 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, "outputs": [], "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", @@ -205,13 +205,13 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, "outputs": [], "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", @@ -229,13 +229,13 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, "outputs": [], "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", @@ -251,13 +251,13 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, "outputs": [], "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", @@ -275,13 +275,13 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": {}, "outputs": [], "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", @@ -297,14 +297,14 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "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=\"cwd_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_spells(\n", diff --git a/notebooks/wps_climdex_temp_pctl.ipynb b/notebooks/wps_climdex_temp_pctl.ipynb index bf0bb24..0a159c5 100644 --- a/notebooks/wps_climdex_temp_pctl.ipynb +++ b/notebooks/wps_climdex_temp_pctl.ipynb @@ -16,7 +16,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -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", @@ -144,13 +144,13 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [], "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", @@ -174,13 +174,13 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, "outputs": [], "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", @@ -205,13 +205,13 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, "outputs": [], "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", @@ -236,14 +236,14 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "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=\"tx90p_\", dir=\"/tmp\", delete=True) as output_file:\n", " output = quail.climdex_temp_pctl(\n", From 660ff1c80ab2c6ef19692fad9d1a10afc7f3909d Mon Sep 17 00:00:00 2001 From: Quintin Date: Tue, 6 May 2025 13:58:36 -0700 Subject: [PATCH 04/15] Address deprecations in utils and tests --- quail/utils.py | 6 ++---- tests/conftest.py | 10 ++++------ tests/test_utils.py | 24 ++++++++++++------------ 3 files changed, 18 insertions(+), 22 deletions(-) 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/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: From 7246da2e5893c179da295189983cfe88c7b6076b Mon Sep 17 00:00:00 2001 From: Quintin Date: Tue, 6 May 2025 14:21:24 -0700 Subject: [PATCH 05/15] Install curl in Dockerfile, fix Python CI matrix --- .github/workflows/python-ci.yml | 2 +- Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index 5fa30c4..3a7353a 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-24.04 strategy: matrix: - python-version: [3.10, 3.11, 3.12] + python-version: ["3.10", "3.11", "3.12"] steps: - uses: actions/checkout@v4 diff --git a/Dockerfile b/Dockerfile index 86b1cb3..b6e0215 100644 --- a/Dockerfile +++ b/Dockerfile @@ -47,7 +47,7 @@ ENV POETRY_HOME="/opt/poetry" ENV PATH="$POETRY_HOME/bin:$PATH" RUN apt-get update && \ - apt-get install -y --no-install-recommends python3 python3-pip && \ + apt-get install -y --no-install-recommends python3 python3-pip curl && \ curl -sSL https://install.python-poetry.org | python3 From a235ac58a65f04ba97d9efb51e19e8730abaaf98 Mon Sep 17 00:00:00 2001 From: Quintin Date: Tue, 6 May 2025 14:32:53 -0700 Subject: [PATCH 06/15] Install r-base in Dockerfile, allow Python <=3.13 --- .github/workflows/python-ci.yml | 11 ++++++----- pyproject.toml | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index 3a7353a..80e0c36 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -16,16 +16,17 @@ jobs: with: python-version: ${{ matrix.python-version }} - - name: Install R dependencies + - name: Install 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: Install Python dependencies - run: | + sudo apt-get install --fix-missing r-base libgit2-dev libfontconfig1-dev libharfbuzz-dev libfribidi-dev libcurl4-openssl-dev libssl-dev libnetcdf-dev curl -sSL https://install.python-poetry.org | python3 - echo "$HOME/.local/bin" >> $GITHUB_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: | diff --git a/pyproject.toml b/pyproject.toml index e042587..e1c2a55 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ 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.10, <=3.12" +requires-python = ">=3.10, <=3.13" keywords = ["wps", "pywps", "birdhouse", "quail"] classifiers = [ "Development Status :: 3 - Alpha", From 391094931b75f7337d7de42797a976725aa34d66 Mon Sep 17 00:00:00 2001 From: Quintin Date: Tue, 6 May 2025 15:03:31 -0700 Subject: [PATCH 07/15] Use remotes for R pkg install script --- install_pkgs.R | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/install_pkgs.R b/install_pkgs.R index 2b48418..d01247c 100644 --- a/install_pkgs.R +++ b/install_pkgs.R @@ -16,17 +16,16 @@ deps <- toml_data$tool$quail$`r-dependencies` # Install devtools -install.packages("devtools", dependencies = TRUE) -library(devtools) +install.packages("remotes", repos = "https://cloud.r-project.org") # Install packages with versions for (pkg in names(deps)) { ver <- deps[[pkg]] if (!(pkg %in% rownames(installed.packages()))) { if (is.null(ver) || ver == "*" || ver == "") { - install_version(pkg) + remotes::install_version(pkg) } else { - install_version(pkg, version = ver) + remotes::install_version(pkg, version = ver) } } } From 520519166aa1eda8469625ae347abc09c27a7885 Mon Sep 17 00:00:00 2001 From: Quintin Date: Tue, 6 May 2025 15:15:46 -0700 Subject: [PATCH 08/15] Revert to devtools, add missing system libs to Py CI --- .github/workflows/python-ci.yml | 2 +- install_pkgs.R | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index 80e0c36..7e35708 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -19,7 +19,7 @@ jobs: - name: Install dependencies run: | sudo apt-get update - sudo apt-get install --fix-missing r-base libgit2-dev libfontconfig1-dev libharfbuzz-dev libfribidi-dev libcurl4-openssl-dev libssl-dev libnetcdf-dev + sudo apt-get install 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 poetry install --extras "dev" diff --git a/install_pkgs.R b/install_pkgs.R index d01247c..2b48418 100644 --- a/install_pkgs.R +++ b/install_pkgs.R @@ -16,16 +16,17 @@ deps <- toml_data$tool$quail$`r-dependencies` # Install devtools -install.packages("remotes", repos = "https://cloud.r-project.org") +install.packages("devtools", dependencies = TRUE) +library(devtools) # Install packages with versions for (pkg in names(deps)) { ver <- deps[[pkg]] if (!(pkg %in% rownames(installed.packages()))) { if (is.null(ver) || ver == "*" || ver == "") { - remotes::install_version(pkg) + install_version(pkg) } else { - remotes::install_version(pkg, version = ver) + install_version(pkg, version = ver) } } } From 33c19b4c793b6b41c79dca99af483fcb53ebf59c Mon Sep 17 00:00:00 2001 From: Quintin Date: Tue, 6 May 2025 15:40:38 -0700 Subject: [PATCH 09/15] Move black to separate workflow --- .github/workflows/black.yml | 14 ++++++++++++++ .github/workflows/python-ci.yml | 2 -- 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/black.yml 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/python-ci.yml b/.github/workflows/python-ci.yml index 7e35708..9dfec9b 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -35,5 +35,3 @@ jobs: if: github.ref != 'refs/heads/master' run: | poetry run py.test -m "not online and not slow" -v - - name: Code Quality - run: black . --check From b6636389b4f085e21486e0848f3506abaf604efc Mon Sep 17 00:00:00 2001 From: Quintin Date: Fri, 9 May 2025 14:28:27 -0700 Subject: [PATCH 10/15] Include Poe tasks in docs --- dev-component/DEVELOPMENT.md | 5 +- docs/dev_guide.md | 52 ++++++++++--------- docs/installation.md | 97 +++++++++++++++++++++++++++--------- 3 files changed, 102 insertions(+), 52 deletions(-) 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/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. From 8cc71698640df02100ca89cc402272dfe396d94a Mon Sep 17 00:00:00 2001 From: Quintin Date: Mon, 12 May 2025 13:21:39 -0700 Subject: [PATCH 11/15] Include setuptools for Poetry in Dockerfile --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index e1c2a55..87311e2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,6 +32,7 @@ dependencies = [ "werkzeug==1.0.1", "wps_tools[r]==2.0.0", "gunicorn>=20.1.0", + "setuptools", ] [project.optional-dependencies] From ea86695a8dfb7c239befd3acbfc2b41f5f5d9ece Mon Sep 17 00:00:00 2001 From: Quintin Date: Tue, 13 May 2025 10:37:33 -0700 Subject: [PATCH 12/15] Add pyproj, bump nchelpers and wps-tools --- .../wps_climdexInput_csv_demo.html | 6 ++-- .../wps_climdex_days_demo.html | 22 ++++++------- .../formatted_demos/wps_climdex_dtr_demo.html | 18 +++++------ .../wps_climdex_get_available_indices.html | 8 ++--- .../formatted_demos/wps_climdex_gsl_demo.html | 18 +++++------ .../wps_climdex_mmdmt_demo.html | 28 ++++++++-------- docs/formatted_demos/wps_climdex_ptot.html | 24 +++++++------- .../formatted_demos/wps_climdex_rmm_demo.html | 10 +++--- .../wps_climdex_rxnday_demo.html | 12 +++---- .../wps_climdex_sdii_demo.html | 10 +++--- .../wps_climdex_spells_demo.html | 24 +++++++------- .../wps_climdex_temp_pctl.html | 12 +++---- notebooks/wps_climdexInput_csv_demo.ipynb | 6 ++-- notebooks/wps_climdex_days_demo.ipynb | 26 +++++++-------- notebooks/wps_climdex_dtr_demo.ipynb | 20 ++++++------ .../wps_climdex_get_available_indices.ipynb | 12 +++---- notebooks/wps_climdex_gsl_demo.ipynb | 22 ++++++------- notebooks/wps_climdex_mmdmt_demo.ipynb | 32 +++++++++---------- notebooks/wps_climdex_ptot.ipynb | 28 ++++++++-------- notebooks/wps_climdex_rmm_demo.ipynb | 14 ++++---- notebooks/wps_climdex_rxnday_demo.ipynb | 16 +++++----- notebooks/wps_climdex_sdii_demo.ipynb | 14 ++++---- notebooks/wps_climdex_spells_demo.ipynb | 28 ++++++++-------- notebooks/wps_climdex_temp_pctl.ipynb | 16 +++++----- pyproject.toml | 5 +-- 25 files changed, 216 insertions(+), 215 deletions(-) diff --git a/docs/formatted_demos/wps_climdexInput_csv_demo.html b/docs/formatted_demos/wps_climdexInput_csv_demo.html index ed4f0a0..82c1694 100644 --- a/docs/formatted_demos/wps_climdexInput_csv_demo.html +++ b/docs/formatted_demos/wps_climdexInput_csv_demo.html @@ -7749,11 +7749,11 @@

Run wps_climdexInput process
with NamedTemporaryFile(suffix=".rda", prefix="summer_days_", dir="/tmp", delete=True) as output_file:
     output = quail.climdex_input_csv(
             tmax_file_content=csv_handler(
-                (files("tests") / "data/1018935_MAX_TEMP.csv").resolve(),
+                (files("tests") / "data/1018935_MAX_TEMP.csv").resolve()),
             tmin_file_content=csv_handler(
-                (files("tests") / "data/1018935_MIN_TEMP.csv").resolve(),
+                (files("tests") / "data/1018935_MIN_TEMP.csv").resolve()),
             prec_file_content=csv_handler(
-                (files("tests") / "data/1018935_ONE_DAY_PRECIPITATION.csv").resolve(),
+                (files("tests") / "data/1018935_ONE_DAY_PRECIPITATION.csv").resolve()),
             tmax_column='MAX_TEMP',
             tmin_column='MIN_TEMP',
             prec_column='ONE_DAY_PRECIPITATION',
diff --git a/docs/formatted_demos/wps_climdex_days_demo.html b/docs/formatted_demos/wps_climdex_days_demo.html
index e97aece..344cae4 100644
--- a/docs/formatted_demos/wps_climdex_days_demo.html
+++ b/docs/formatted_demos/wps_climdex_days_demo.html
@@ -7532,7 +7532,7 @@ 

Days: wps_climdex_days