diff --git a/.cruft.json b/.cruft.json index 505e1df..83829b1 100644 --- a/.cruft.json +++ b/.cruft.json @@ -1,6 +1,6 @@ { "template": "https://github.com/bird-house/cookiecutter-birdhouse.git", - "commit": "73eee18ca4a16763335d18ed9512cc617fbcc777", + "commit": "7ec7b8b69bbb900d6a300854af0e2a7357b83cdf", "skip": [ "emu/processes/wps_say_hello.py", "tests/test_wps_hello.py", diff --git a/.readthedocs.yml b/.readthedocs.yml index 40bdff6..d92d702 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -8,6 +8,9 @@ version: 2 # Build documentation in the docs/ directory with Sphinx sphinx: configuration: docs/source/conf.py + # fail_on_warning might generate hard to fix error, in this case it can be + # disabled but this also means those errors will fail silently, choose wisely. + fail_on_warning: true # Build documentation with MkDocs #mkdocs: diff --git a/.travis.yml b/.travis.yml index cd3b62f..336464e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ os: python: - "3.6" - "3.7" + - "3.8" # - osx sudo: false before_install: @@ -37,4 +38,6 @@ script: # No notebooks in emu yet. #- make test-notebooks - flake8 - - make docs + - make docs # default html + - make SPHINXOPTS='-b epub' docs # to match RtD + - make SPHINXOPTS='-b latex' docs # to match RtD diff --git a/Dockerfile b/Dockerfile index a72ca73..77f304f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,11 +16,11 @@ COPY . /opt/wps WORKDIR /opt/wps -# Create conda environment -RUN conda env create -n wps -f environment.yml +# Create conda environment with PyWPS +RUN ["conda", "env", "create", "-n", "wps", "-f", "environment.yml"] # Install WPS -RUN ["/bin/bash", "-c", "source activate wps && python setup.py develop"] +RUN ["/bin/bash", "-c", "source activate wps && pip install -e ."] # Start WPS service on port 5000 on 0.0.0.0 EXPOSE 5000 diff --git a/Makefile b/Makefile index c677e69..6e68287 100644 --- a/Makefile +++ b/Makefile @@ -72,6 +72,7 @@ install: develop: @echo "Installing development requirements for tests and docs ..." @-bash -c 'pip install -e ".[dev]"' + @-bash -c 'pip install git+https://github.com/Ouranosinc/pywps@2a55b6e95f51c648dc94bf3c89db7370b56c1c9c#egg=pywps --upgrade' .PHONY: start start: @@ -163,7 +164,7 @@ refresh-notebooks: .PHONY: docs docs: @echo "Generating docs with Sphinx ..." - @-bash -c '$(MAKE) -C $@ clean html' + @bash -c '$(MAKE) -C $@ clean html' @echo "Open your browser to: file:/$(APP_ROOT)/docs/build/html/index.html" ## do not execute xdg-open automatically since it hangs travis and job does not complete @echo "xdg-open $(APP_ROOT)/docs/build/html/index.html" diff --git a/docs/Makefile b/docs/Makefile index 82d3357..1b55b45 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -17,4 +17,4 @@ help: # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" -W $(SPHINXOPTS) $(O) diff --git a/docs/source/conf.py b/docs/source/conf.py index e0a0fb3..4ae7030 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -35,20 +35,35 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc', - 'sphinx.ext.viewcode', - 'sphinx.ext.napoleon', - 'sphinx.ext.todo', - 'pywps.ext_autodoc', - ] +extensions = [ + "sphinx.ext.autodoc", + "sphinx.ext.viewcode", + "sphinx.ext.mathjax", + "sphinx.ext.napoleon", + "sphinx.ext.todo", + "pywps.ext_autodoc", + "sphinx.ext.autosectionlabel", + "sphinx.ext.imgconverter", + "nbsphinx", + "IPython.sphinxext.ipython_console_highlighting", +] # To avoid having to install these and burst memory limit on ReadTheDocs. +# List of all tested working mock imports from all birds so new birds can +# inherit without having to test which work which do not. autodoc_mock_imports = ["numpy", "xarray", "fiona", "rasterio", "shapely", "osgeo", "geopandas", "pandas", "statsmodels", "affine", "rasterstats", "spotpy", "matplotlib", "scipy", "unidecode", "gdal", "sentry_sdk", "dask", "numba", "parse", "siphon", "sklearn", "cftime", - "netCDF4"] + "netCDF4", "bottleneck", "ocgis", "geotiff", "geos", + "hdf4", "hdf5", "zlib", "pyproj", "proj", "cartopy", + "scikit-learn", "cairo"] + +# Monkeypatch constant because the following are mock imports. +# Only works if numpy is actually installed and at the same time being mocked. +#import numpy +#numpy.pi = 3.1416 # We are using mock imports in readthedocs, so probably safer to not run the notebooks nbsphinx_execute = 'never' @@ -75,7 +90,7 @@ # the built documents. # # The short X.Y version. -version = "" +version = "0.11.1" # The full version, including alpha/beta/rc tags. release = "0.11.1" @@ -97,6 +112,12 @@ # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = False +# Suppress "WARNING: unknown mimetype for ..." when building EPUB. +suppress_warnings = ['epub.unknown_project_files'] + +# Avoid "configuration.rst:4:duplicate label configuration, other instance in configuration.rst" +autosectionlabel_prefix_document = True + # -- Options for HTML output ------------------------------------------- diff --git a/docs/source/installation.rst b/docs/source/installation.rst index 8917f22..072bf06 100644 --- a/docs/source/installation.rst +++ b/docs/source/installation.rst @@ -14,10 +14,6 @@ Install from Conda :target: http://anaconda.org/birdhouse/emu :alt: Ananconda Install -.. image:: http://anaconda.org/birdhouse/emu/badges/build.svg - :target: http://anaconda.org/birdhouse/emu - :alt: Anaconda Build - .. image:: http://anaconda.org/birdhouse/emu/badges/version.svg :target: http://anaconda.org/birdhouse/emu :alt: Anaconda Version diff --git a/emu/processes/wps_bbox.py b/emu/processes/wps_bbox.py index 45791b4..11cb578 100644 --- a/emu/processes/wps_bbox.py +++ b/emu/processes/wps_bbox.py @@ -1,4 +1,5 @@ from pywps.app.Common import Metadata +from pywps.ext_autodoc import MetadataUrl __author__ = 'Jachym' @@ -30,7 +31,9 @@ def __init__(self): abstract='Give bounding box, return the same', metadata=[ Metadata('Birdhouse', 'http://bird-house.github.io/'), - Metadata('User Guide', 'http://emu.readthedocs.io/en/latest/')], + MetadataUrl('User Guide', + 'http://emu.readthedocs.io/en/latest/', + anonymous=True)], inputs=inputs, outputs=outputs, store_supported=True, diff --git a/emu/processes/wps_binaryoperator.py b/emu/processes/wps_binaryoperator.py index a34625f..7a4b94f 100644 --- a/emu/processes/wps_binaryoperator.py +++ b/emu/processes/wps_binaryoperator.py @@ -1,5 +1,6 @@ from pywps import Process, LiteralInput, LiteralOutput from pywps.app.Common import Metadata +from pywps.ext_autodoc import MetadataUrl import logging logger = logging.getLogger("PYWPS") @@ -30,7 +31,9 @@ def __init__(self): 'This example process is taken from Climate4Impact.', metadata=[ Metadata('Birdhouse', 'http://bird-house.github.io/'), - Metadata('User Guide', 'http://emu.readthedocs.io/en/latest/'), + MetadataUrl('User Guide', + 'http://emu.readthedocs.io/en/latest/', + anonymous=True), Metadata('Climate4Impact', 'https://dev.climate4impact.eu')], version='1.0', inputs=inputs, diff --git a/emu/processes/wps_chomsky.py b/emu/processes/wps_chomsky.py index 3bb8831..90ee458 100644 --- a/emu/processes/wps_chomsky.py +++ b/emu/processes/wps_chomsky.py @@ -102,8 +102,7 @@ class Chomsky(Process): """ - Notes - ----- + Notes: Generates a random chomsky text: http://code.activestate.com/recipes/440546-chomsky-random-text-generator/ diff --git a/emu/processes/wps_dry_run.py b/emu/processes/wps_dry_run.py index 5b2af37..fa2ca24 100644 --- a/emu/processes/wps_dry_run.py +++ b/emu/processes/wps_dry_run.py @@ -1,6 +1,6 @@ from pywps import Process, LiteralInput, LiteralOutput from pywps.inout.literaltypes import AllowedValue -from pywps.app.Common import Metadata +from pywps.ext_autodoc import MetadataUrl from pywps.validator.mode import MODE from emu.exceptions import DryRunWarning, StorageLimitExceeded @@ -32,7 +32,9 @@ def __init__(self): title='Simple Dry Run', abstract='A dummy download as simple dry-run example.', metadata=[ - Metadata('User Guide', 'https://emu.readthedocs.io/en/latest/processes.html'), # noqa + MetadataUrl('User Guide', + 'https://emu.readthedocs.io/en/latest/processes.html', + anonymous=True), ], version='1.0', inputs=inputs, diff --git a/emu/processes/wps_error.py b/emu/processes/wps_error.py index ebe4c81..670b7c2 100644 --- a/emu/processes/wps_error.py +++ b/emu/processes/wps_error.py @@ -1,5 +1,6 @@ from pywps import Process, LiteralInput from pywps.app.Common import Metadata +from pywps.ext_autodoc import MetadataUrl from pywps.app.exceptions import ProcessError import logging @@ -37,7 +38,10 @@ def __init__(self): metadata=[ Metadata('PyWPS', 'https://pywps.org/'), Metadata('Birdhouse', 'http://bird-house.github.io/'), - Metadata('User Guide', 'http://emu.readthedocs.io/en/latest/')], + MetadataUrl('User Guide', + 'http://emu.readthedocs.io/en/latest/', + anonymous=True), + ], version='1.0', inputs=inputs, # outputs=outputs, diff --git a/emu/processes/wps_esgf.py b/emu/processes/wps_esgf.py index 7b618ed..b6f1f3e 100644 --- a/emu/processes/wps_esgf.py +++ b/emu/processes/wps_esgf.py @@ -3,6 +3,7 @@ from pywps import ComplexInput from pywps import Format from pywps.app.Common import Metadata +from pywps.ext_autodoc import MetadataUrl import logging LOGGER = logging.getLogger("PYWPS") @@ -38,7 +39,9 @@ def __init__(self): title='ESGF Demo', abstract='Shows how to use WPS metadata for processes using ESGF data.', metadata=[ - Metadata('User Guide', 'https://emu.readthedocs.io/en/latest/processes.html'), # noqa + MetadataUrl('User Guide', + 'https://emu.readthedocs.io/en/latest/processes.html', + anonymous=True), Metadata('ESGF Constraints', role='https://www.earthsystemcog.org/spec/esgf_search/4.12.0/def/constraints', # noqa href='http://esgf-data.dkrz.de/esg-search/search?project=CMIP5&time_frequency=mon&variable=tas,tasmax,tasmin&experiment=historical'), # noqa diff --git a/emu/processes/wps_inout.py b/emu/processes/wps_inout.py index 4732fc8..2a23889 100644 --- a/emu/processes/wps_inout.py +++ b/emu/processes/wps_inout.py @@ -9,6 +9,7 @@ from pywps import Format, FORMATS from pywps.validator.mode import MODE from pywps.app.Common import Metadata +from pywps.ext_autodoc import MetadataUrl import logging @@ -67,8 +68,9 @@ def __init__(self): LiteralInput('int_range', 'Integer Range', abstract='Choose number from range: 1-10 (step 1), 100-200 (step 10)', metadata=[ - Metadata('PyWPS Docs', 'https://pywps.readthedocs.io/en/master/api.html#pywps.inout.literaltypes.AllowedValue'), # noqa - Metadata('AllowedValue Example', 'http://docs.opengeospatial.org/is/14-065/14-065.html#98'), # noqa + Metadata('AllowedValue PyWPS Docs', + 'https://pywps.readthedocs.io/en/master/api.html#pywps.inout.literaltypes.AllowedValue'), # noqa + Metadata('AllowedValue Example', 'http://docs.opengeospatial.org/is/14-065/14-065.html#98'), # noqa ], data_type='integer', default='1', @@ -80,7 +82,8 @@ def __init__(self): LiteralInput('any_value', 'Any Value', abstract='Enter any value.', metadata=[ - Metadata('PyWPS Docs', 'https://pywps.readthedocs.io/en/master/api.html#pywps.inout.literaltypes.AnyValue'), # noqa + Metadata('AnyValue PyWPS Docs', + 'https://pywps.readthedocs.io/en/master/api.html#pywps.inout.literaltypes.AnyValue'), # noqa ], allowed_values=AnyValue(), default='any value', @@ -88,7 +91,8 @@ def __init__(self): LiteralInput('ref_value', 'Referenced Value', abstract='Choose a referenced value', metadata=[ - Metadata('PyWPS Docs', 'https://pywps.readthedocs.io/en/master/_modules/pywps/inout/literaltypes.html'), # noqa + Metadata('PyWPS Docs', + 'https://pywps.readthedocs.io/en/master/_modules/pywps/inout/literaltypes.html'), # noqa ], data_type='string', allowed_values=ValuesReference( @@ -155,8 +159,10 @@ def __init__(self): # profile=['birdhouse'], metadata=[ Metadata('Birdhouse', 'http://bird-house.github.io/'), - Metadata('User Guide', 'http://emu.readthedocs.io/en/latest/', - role='http://www.opengis.net/spec/wps/2.0/def/process/description/documentation')], + MetadataUrl('User Guide', 'http://emu.readthedocs.io/en/latest/', + role='http://www.opengis.net/spec/wps/2.0/def/process/description/documentation', + anonymous=True), + ], inputs=inputs, outputs=outputs, status_supported=True, diff --git a/emu/processes/wps_multiple_outputs.py b/emu/processes/wps_multiple_outputs.py index 2e4966d..2b35f90 100644 --- a/emu/processes/wps_multiple_outputs.py +++ b/emu/processes/wps_multiple_outputs.py @@ -2,7 +2,7 @@ from pywps import Process, LiteralInput, ComplexOutput from pywps import FORMATS from pywps.inout.literaltypes import AllowedValue -from pywps.app.Common import Metadata +from pywps.ext_autodoc import MetadataUrl from pywps.inout.outputs import MetaLink, MetaLink4, MetaFile import json @@ -36,7 +36,9 @@ def __init__(self): abstract='Produces multiple files and returns a document' ' with references to these files.', metadata=[ - Metadata('User Guide', 'https://emu.readthedocs.io/en/latest/processes.html'), # noqa + MetadataUrl('User Guide', + 'https://emu.readthedocs.io/en/latest/processes.html', + anonymous=True), ], version='1.1', inputs=inputs, diff --git a/emu/processes/wps_nap.py b/emu/processes/wps_nap.py index b8dbe6b..a2815d9 100644 --- a/emu/processes/wps_nap.py +++ b/emu/processes/wps_nap.py @@ -1,5 +1,6 @@ from pywps import Process, LiteralInput, LiteralOutput from pywps.app.Common import Metadata +from pywps.ext_autodoc import MetadataUrl class Nap(Process): @@ -23,7 +24,10 @@ def __init__(self): profile='', metadata=[ Metadata('Birdhouse', 'http://bird-house.github.io/'), - Metadata('User Guide', 'http://emu.readthedocs.io/en/latest/')], + MetadataUrl('User Guide', + 'http://emu.readthedocs.io/en/latest/', + anonymous=True), + ], inputs=inputs, outputs=outputs, store_supported=False, diff --git a/emu/processes/wps_nc_to_dap.py b/emu/processes/wps_nc_to_dap.py index 3ba57ad..3ad884a 100644 --- a/emu/processes/wps_nc_to_dap.py +++ b/emu/processes/wps_nc_to_dap.py @@ -1,6 +1,6 @@ from pywps import Process from pywps import ComplexInput, ComplexOutput, FORMATS -from pywps.app.Common import Metadata +from pywps.ext_autodoc import MetadataUrl from pywps import configuration import logging @@ -33,7 +33,9 @@ def __init__(self): abstract="Return Data Access Protocol link to a netCDF or NcML file.", version="1", metadata=[ - Metadata('User Guide', 'http://emu.readthedocs.io/en/latest/'), + MetadataUrl('User Guide', + 'http://emu.readthedocs.io/en/latest/', + anonymous=True), ], inputs=inputs, outputs=outputs, diff --git a/emu/processes/wps_ncmeta.py b/emu/processes/wps_ncmeta.py index 059a4b0..4b62ce8 100644 --- a/emu/processes/wps_ncmeta.py +++ b/emu/processes/wps_ncmeta.py @@ -4,7 +4,7 @@ from pywps import ComplexInput, ComplexOutput, FORMATS, Format from pywps.inout.basic import SOURCE_TYPE from pywps.validator.mode import MODE -from pywps.app.Common import Metadata +from pywps.ext_autodoc import MetadataUrl from netCDF4 import Dataset @@ -17,8 +17,7 @@ class NCMeta(Process): """ - Notes - ----- + Notes: Returns metadata of a NetCDF file or OpenDAP resource. """ @@ -52,7 +51,9 @@ def __init__(self): abstract="Return metadata from a netCDF dataset, either on file or an OpenDAP service.", version='4', metadata=[ - Metadata('User Guide', 'http://emu.readthedocs.io/en/latest/'), + MetadataUrl('User Guide', + 'http://emu.readthedocs.io/en/latest/', + anonymous=True), ], inputs=inputs, outputs=outputs, diff --git a/emu/processes/wps_ncml.py b/emu/processes/wps_ncml.py index 7258414..e0b96ba 100644 --- a/emu/processes/wps_ncml.py +++ b/emu/processes/wps_ncml.py @@ -2,7 +2,7 @@ import xarray.tests.test_dataset as td from pywps import Process from pywps import ComplexOutput, FORMATS -from pywps.app.Common import Metadata +from pywps.ext_autodoc import MetadataUrl import logging @@ -31,7 +31,9 @@ def __init__(self): abstract="Return links to an NcML file aggregating netCDF files with moving time units.", version="1", metadata=[ - Metadata('User Guide', 'http://emu.readthedocs.io/en/latest/'), + MetadataUrl('User Guide', + 'http://emu.readthedocs.io/en/latest/', + anonymous=True), ], inputs=inputs, outputs=outputs, diff --git a/emu/processes/wps_say_hello.py b/emu/processes/wps_say_hello.py index 8e80821..4123b4d 100644 --- a/emu/processes/wps_say_hello.py +++ b/emu/processes/wps_say_hello.py @@ -1,5 +1,6 @@ from pywps import Process, LiteralInput, LiteralOutput, UOM from pywps.app.Common import Metadata +from pywps.ext_autodoc import MetadataUrl import logging LOGGER = logging.getLogger("PYWPS") @@ -27,7 +28,9 @@ def __init__(self): 'Returns a literal string output with Hello plus the inputed name.', keywords=['hello', 'demo'], metadata=[ - Metadata('User Guide', 'https://emu.readthedocs.io/en/latest/processes.html'), # noqa + MetadataUrl('User Guide', + 'https://emu.readthedocs.io/en/latest/processes.html', + anonymous=True), # noqa Metadata('PyWPS Demo', 'https://pywps-demo.readthedocs.io/en/latest/'), ], version='1.5', diff --git a/emu/processes/wps_sleep.py b/emu/processes/wps_sleep.py index ce931e8..b4a3e83 100644 --- a/emu/processes/wps_sleep.py +++ b/emu/processes/wps_sleep.py @@ -1,5 +1,6 @@ from pywps import Process, LiteralInput, LiteralOutput from pywps.app.Common import Metadata +from pywps.ext_autodoc import MetadataUrl class Sleep(Process): @@ -22,7 +23,9 @@ def __init__(self): 'This process will sleep for a given delay or 10 seconds if not a valid value.', profile='', metadata=[ - Metadata('User Guide', 'https://emu.readthedocs.io/en/latest/processes.html'), # noqa + MetadataUrl('User Guide', + 'https://emu.readthedocs.io/en/latest/processes.html', + anonymous=True), # noqa Metadata('PyWPS Demo', 'https://pywps-demo.readthedocs.io/en/latest/'), ], inputs=inputs, diff --git a/emu/processes/wps_wordcounter.py b/emu/processes/wps_wordcounter.py index ddeac0b..6c34ba3 100644 --- a/emu/processes/wps_wordcounter.py +++ b/emu/processes/wps_wordcounter.py @@ -5,7 +5,7 @@ from pywps import Process from pywps import ComplexInput, ComplexOutput, FORMATS -from pywps.app.Common import Metadata +from pywps.ext_autodoc import MetadataUrl import logging LOGGER = logging.getLogger("PYWPS") @@ -13,8 +13,7 @@ class WordCounter(Process): """ - Notes - ----- + Notes: Counts occurrences of all words in a document. """ @@ -36,7 +35,9 @@ def __init__(self): abstract="Counts words in a given text.", version='1.0', metadata=[ - Metadata('User Guide', 'http://emu.readthedocs.io/en/latest/'), + MetadataUrl('User Guide', + 'http://emu.readthedocs.io/en/latest/', + anonymous=True), ], inputs=inputs, outputs=outputs, diff --git a/environment-docs.yml b/environment-docs.yml index adf6d36..df001b8 100644 --- a/environment-docs.yml +++ b/environment-docs.yml @@ -4,7 +4,12 @@ channels: - conda-forge - defaults dependencies: -- pywps>=4.2 +# restore once an official pywps release contain the fix +#- pywps>=4.2 - sphinx - nbsphinx - ipython +- pip +- pip: + # delete once an official pywps release contain this fix, also delete in Makefile + - https://github.com/Ouranosinc/pywps/archive/2a55b6e95f51c648dc94bf3c89db7370b56c1c9c.zip diff --git a/setup.cfg b/setup.cfg index ecf633d..2f5dea7 100644 --- a/setup.cfg +++ b/setup.cfg @@ -11,8 +11,8 @@ search = __version__ = '{current_version}' replace = __version__ = '{new_version}' [bumpversion:file:docs/source/conf.py] -search = release = '{current_version}' -replace = release = '{new_version}' +search = version|release = {current_version} +replace = {new_version} [bumpversion:file:Dockerfile] search = Version="{current_version}"