From 88cdbce182ccec77fd9337ff6aac53e0ab8e8534 Mon Sep 17 00:00:00 2001 From: Zebedee Nicholls Date: Tue, 9 Jan 2024 15:47:07 +0100 Subject: [PATCH 01/61] Basic clean up and write TODO's --- .gitignore | 67 ++++++-- .readthedocs.yaml | 25 ++- Makefile | 166 +++++++----------- README.md | 96 +++++++++++ docs/make.bat | 6 +- docs/source/conf.py | 306 ++++++++++++++------------------- pyproject.toml | 224 +++++++++++++++++++++--- src/openscm_runner/__init__.py | 18 +- tests/conftest.py | 107 ++++++------ 9 files changed, 626 insertions(+), 389 deletions(-) create mode 100644 README.md diff --git a/.gitignore b/.gitignore index 17117efd..14d02578 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,25 @@ -# binary files -bin +# Notebooks +*.ipynb -# vim swap files -*.swp +# Databases +*.db + +# Jupyter cache +.jupyter_cache + +# Licence check +licence-check.txt + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class -# temporary data files -scripts/*.csv -scripts/*.json +# C extensions +*.so + +# Binary files +bin # Compiled Dynamic libraries *.so @@ -33,14 +46,6 @@ scripts/*.json *.a *.lib -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - # Distribution / packaging .Python build/ @@ -55,6 +60,8 @@ parts/ sdist/ var/ wheels/ +pip-wheel-metadata/ +share/python-wheels/ *.egg-info/ .installed.cfg *.egg @@ -73,12 +80,14 @@ pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ +.nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover +*.py,cover .hypothesis/ .pytest_cache/ @@ -90,6 +99,7 @@ coverage.xml *.log local_settings.py db.sqlite3 +db.sqlite3-journal # Flask stuff: instance/ @@ -107,11 +117,26 @@ target/ # Jupyter Notebook .ipynb_checkpoints +# IPython +profile_default/ +ipython_config.py + # pyenv .python-version -# celery beat schedule file +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff celerybeat-schedule +celerybeat.pid # SageMath parsed files *.sage.py @@ -140,6 +165,14 @@ venv3.bak/ # mypy .mypy_cache/ +.dmypy.json +dmypy.json -# DS_Store +# Pyre type checker +.pyre/ + +# Mac stuff *.DS_Store + +# Swap files +*.swp diff --git a/.readthedocs.yaml b/.readthedocs.yaml index f46aae30..9543d49f 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -1,13 +1,24 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Thank you also https://browniebroke.com/blog/specify-docs-dependency-groups-with-poetry-and-read-the-docs/ + +# Required version: 2 +# Set the version of Python and other tools you might need build: - os: ubuntu-20.04 + os: ubuntu-22.04 tools: python: "3.9" + jobs: + post_create_environment: + - pip install poetry + - poetry config virtualenvs.create false + post_install: + - poetry install --with docs --all-extras -python: - install: - - method: pip - path: . - extra_requirements: - - docs +# Build documentation in the docs/ directory with Sphinx +sphinx: + configuration: docs/source/conf.py diff --git a/Makefile b/Makefile index fa9d991b..9edc86c1 100644 --- a/Makefile +++ b/Makefile @@ -1,115 +1,75 @@ -.DEFAULT_GOAL := help - -VENV_DIR ?= venv +# Makefile to help automate key steps -TESTS_DIR=./tests -NOTEBOOKS_DIR=./notebooks -NOTEBOOKS_SANITIZE_FILE=$(TESTS_DIR)/notebook-tests.cfg +.DEFAULT_GOAL := help +# Will likely fail on Windows, but Makefiles are in general not Windows +# compatible so we're not too worried +TEMP_FILE := $(shell mktemp) +# A helper script to get short descriptions of each target in the Makefile define PRINT_HELP_PYSCRIPT import re, sys for line in sys.stdin: - match = re.match(r'^([a-zA-Z_-]+):.*?## (.*)$$', line) + match = re.match(r'^([\$$\(\)a-zA-Z_-]+):.*?## (.*)$$', line) if match: target, help = match.groups() - print("%-20s %s" % (target, help)) + print("%-30s %s" % (target, help)) endef export PRINT_HELP_PYSCRIPT -.PHONY: help -help: - @python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) - -checks: $(VENV_DIR) ## run all the checks - @echo "=== bandit ==="; $(VENV_DIR)/bin/bandit -c .bandit.yml -r src || echo "--- bandit failed ---" >&2; \ - echo "\n\n=== black ==="; $(VENV_DIR)/bin/black --check src tests setup.py docs/source/conf.py --exclude openscm_runner/_version.py || echo "--- black failed ---" >&2; \ - echo "\n\n=== flake8 ==="; $(VENV_DIR)/bin/flake8 src tests setup.py || echo "--- flake8 failed ---" >&2; \ - echo "\n\n=== isort ==="; $(VENV_DIR)/bin/isort --check-only --quiet src tests setup.py || echo "--- isort failed ---" >&2; \ - echo "\n\n=== pydocstyle ==="; $(VENV_DIR)/bin/pydocstyle src || echo "--- pydocstyle failed ---" >&2; \ - echo "\n\n=== pylint ==="; $(VENV_DIR)/bin/pylint src || echo "--- pylint failed ---" >&2; \ - echo "\n\n=== notebook tests ==="; $(VENV_DIR)/bin/pytest notebooks -r a --nbval --sanitize-with $(NOTEBOOKS_SANITIZE_FILE) || echo "--- notebook tests failed ---" >&2; \ - echo "\n\n=== tests ==="; $(VENV_DIR)/bin/pytest tests -r a --cov=openscm_runner --cov-report='' \ - && $(VENV_DIR)/bin/coverage report --fail-under=95 || echo "--- tests failed ---" >&2; \ - echo - -.PHONY: format -format: ## re-format files - make isort - make black - -.PHONY: format-notebooks -format-notebooks: $(VENV_DIR) ## format the notebooks - @status=$$(git status --porcelain $(NOTEBOOKS_DIR)); \ - if test ${FORCE} || test "x$${status}" = x; then \ - $(VENV_DIR)/bin/black-nb $(NOTEBOOKS_DIR); \ - else \ - echo Not trying any formatting. Working directory is dirty ... >&2; \ - fi; - -black: $(VENV_DIR) ## apply black formatter to source and tests - @status=$$(git status --porcelain src tests docs scripts); \ - if test "x$${status}" = x; then \ - $(VENV_DIR)/bin/black --exclude _version.py setup.py src tests docs/source/conf.py scripts/*.py; \ - else \ - echo Not trying any formatting. Working directory is dirty ... >&2; \ - fi; - -isort: $(VENV_DIR) ## format the code - @status=$$(git status --porcelain src tests); \ - if test "x$${status}" = x; then \ - $(VENV_DIR)/bin/isort src tests setup.py; \ - else \ - echo Not trying any formatting. Working directory is dirty ... >&2; \ - fi; - -docs: $(VENV_DIR) ## build the docs - $(VENV_DIR)/bin/sphinx-build -M html docs/source docs/build - -test: $(VENV_DIR) ## run the full testsuite - $(VENV_DIR)/bin/pytest tests --cov -rfsxEX --cov-report term-missing - -test-testpypi-install: $(VENV_DIR) ## test whether installing from test PyPI works - $(eval TEMPVENV := $(shell mktemp -d)) - python3 -m venv $(TEMPVENV) - $(TEMPVENV)/bin/pip install pip wheel --upgrade - # Install dependencies not on testpypi registry - $(TEMPVENV)/bin/pip install pandas - # Install pymagicc without dependencies. - $(TEMPVENV)/bin/pip install \ - -i https://testpypi.python.org/pypi openscm-runner \ - --no-dependencies --pre - $(TEMPVENV)/bin/python -c "import sys; sys.path.remove(''); import openscm_runner; print(openscm_runner.__version__)" - -test-pypi-install: $(VENV_DIR) ## test whether installing from PyPI works - $(eval TEMPVENV := $(shell mktemp -d)) - python3 -m venv $(TEMPVENV) - $(TEMPVENV)/bin/pip install pip wheel --upgrade - $(TEMPVENV)/bin/pip install openscm-runner --pre - $(TEMPVENV)/bin/python scripts/test_install.py - -test-install: $(VENV_DIR) ## test installing works - $(eval TEMPVENV := $(shell mktemp -d)) - python3 -m venv $(TEMPVENV) - $(TEMPVENV)/bin/pip install pip wheel --upgrade - $(TEMPVENV)/bin/pip install . - $(TEMPVENV)/bin/python scripts/test_install.py - -virtual-environment: ## update venv, create a new venv if it doesn't exist - make $(VENV_DIR) - -$(VENV_DIR): setup.py setup.cfg pyproject.toml - [ -d $(VENV_DIR) ] || python3 -m venv $(VENV_DIR) - - $(VENV_DIR)/bin/pip install --upgrade pip wheel - $(VENV_DIR)/bin/pip install -e .[dev] - $(VENV_DIR)/bin/jupyter nbextension enable --py widgetsnbextension - - touch $(VENV_DIR) - -first-venv: ## create a new virtual environment for the very first repo setup - python3 -m venv $(VENV_DIR) - $(VENV_DIR)/bin/pip install --upgrade pip - $(VENV_DIR)/bin/pip install versioneer - # don't touch here as we don't want this venv to persist anyway +help: ## print short description of each target + @python3 -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) + +.PHONY: checks +checks: ## run all the linting checks of the codebase + @echo "=== pre-commit ==="; poetry run pre-commit run --all-files || echo "--- pre-commit failed ---" >&2; \ + echo "=== mypy ==="; MYPYPATH=stubs poetry run mypy src || echo "--- mypy failed ---" >&2; \ + echo "======" + +.PHONY: ruff-fixes +ruff-fixes: ## fix the code using ruff + # format before and after checking so that the formatted stuff is checked and + # the fixed stuff is formatted + poetry run ruff format src tests scripts docs/source/conf.py docs/source/notebooks/*.py + poetry run ruff src tests scripts docs/source/conf.py docs/source/notebooks/*.py --fix + poetry run ruff format src tests scripts docs/source/conf.py docs/source/notebooks/*.py + + +.PHONY: test +test: ## run the tests + poetry run pytest src tests -r a -v --doctest-modules --cov=src + +# Note on code coverage and testing: +# You must specify cov=src as otherwise funny things happen when doctests are +# involved. +# If you want to debug what is going on with coverage, we have found +# that adding COVERAGE_DEBUG=trace to the front of the below command +# can be very helpful as it shows you if coverage is tracking the coverage +# of all of the expected files or not. +# We are sure that the coverage maintainers would appreciate a PR that improves +# the coverage handling when there are doctests and a `src` layout like ours. + +.PHONY: docs +docs: ## build the docs + poetry run sphinx-build -T -b html docs/source docs/build/html + +.PHONY: changelog-draft +changelog-draft: ## compile a draft of the next changelog + poetry run towncrier build --draft + +.PHONY: licence-check +licence-check: ## Check that licences of the dependencies are suitable + # Will likely fail on Windows, but Makefiles are in general not Windows + # compatible so we're not too worried + poetry export --without=tests --without=docs --without=dev > $(TEMP_FILE) + poetry run liccheck -r $(TEMP_FILE) -R licence-check.txt + rm -f $(TEMP_FILE) + +.PHONY: virtual-environment +virtual-environment: ## update virtual environment, create a new one if it doesn't already exist + poetry lock + # Put virtual environments in the project + poetry config virtualenvs.in-project true + poetry install --all-extras + poetry run pre-commit install diff --git a/README.md b/README.md new file mode 100644 index 00000000..b5ed198b --- /dev/null +++ b/README.md @@ -0,0 +1,96 @@ +# OpenSCM-Runner + +TODO: + +- TODO: work out how to handle package data +- Change notebooks into papermill style +- Update notebook tests +- add PHONY to help in copier +- add test pypi and test conda install in copier +- add AUTHORS in copier +- check if version and release in docs/source/conf.py do anything +- convert docs from rst to md +- work out what pygments_style in docs/source/conf.py does +- add sidebar back into docs in copier +- get rid of |CO2| throughout +- note that this removes support for Python \< 3.9 +- Remove README.rst +- Change to using pytest-regressions for handling expected values + + + + + +Thin wrapper to run emissions scenarios with simple climate models + +[![CI](https://github.com/openscm/openscm-runner/actions/workflows/ci.yaml/badge.svg?branch=main)](https://github.com/openscm/openscm-runner/actions/workflows/ci.yaml) +[![Coverage](https://codecov.io/gh/openscm/openscm-runner/branch/main/graph/badge.svg)](https://codecov.io/gh/openscm/openscm-runner) +[![Docs](https://readthedocs.org/projects/openscm-runner/badge/?version=latest)](https://openscm-runner.readthedocs.io) + +**PyPI :** +[![PyPI](https://img.shields.io/pypi/v/openscm-runner.svg)](https://pypi.org/project/openscm-runner/) +[![PyPI: Supported Python versions](https://img.shields.io/pypi/pyversions/openscm-runner.svg)](https://pypi.org/project/openscm-runner/) +[![PyPI install](https://github.com/openscm/openscm-runner/actions/workflows/install.yaml/badge.svg?branch=main)](https://github.com/openscm/openscm-runner/actions/workflows/install.yaml) + +**Other info :** +[![License](https://img.shields.io/github/license/openscm/openscm-runner.svg)](https://github.com/openscm/openscm-runner/blob/main/LICENSE) +[![Last Commit](https://img.shields.io/github/last-commit/openscm/openscm-runner.svg)](https://github.com/openscm/openscm-runner/commits/main) +[![Contributors](https://img.shields.io/github/contributors/openscm/openscm-runner.svg)](https://github.com/openscm/openscm-runner/graphs/contributors) + + + +Full documentation can be found at: +[openscm-runner.readthedocs.io](https://openscm-runner.readthedocs.io/en/latest/). +We recommend reading the docs there because the internal documentation links +don't render correctly on GitHub's viewer. + +## Installation + + + +OpenSCM-Runner can be installed with conda or pip: + +```bash +pip install openscm-runner +conda install -c conda-forge openscm-runner +``` + +Additional dependencies can be installed using + +```bash +# To add notebook dependencies +pip install openscm-runner[notebooks] + +# If you are installing with conda, we recommend +# installing the extras by hand because there is no stable +# solution yet (issue here: https://github.com/conda/conda/issues/7502) +``` + + + +### For developers + + + +For development, we rely on [poetry](https://python-poetry.org) for all our +dependency management. To get started, you will need to make sure that poetry +is installed +([instructions here](https://python-poetry.org/docs/#installing-with-the-official-installer), +we found that pipx and pip worked better to install on a Mac). + +For all of work, we use our `Makefile`. +You can read the instructions out and run the commands by hand if you wish, +but we generally discourage this because it can be error prone. +In order to create your environment, run `make virtual-environment`. + +If there are any issues, the messages from the `Makefile` should guide you +through. If not, please raise an issue in the [issue tracker][issue_tracker]. + +For the rest of our developer docs, please see [](development-reference). + + + +[issue_tracker]: https://github.com/openscm/openscm-runner/issues diff --git a/docs/make.bat b/docs/make.bat index 6247f7e2..747ffb7b 100644 --- a/docs/make.bat +++ b/docs/make.bat @@ -10,8 +10,6 @@ if "%SPHINXBUILD%" == "" ( set SOURCEDIR=source set BUILDDIR=build -if "%1" == "" goto help - %SPHINXBUILD% >NUL 2>NUL if errorlevel 9009 ( echo. @@ -21,10 +19,12 @@ if errorlevel 9009 ( echo.may add the Sphinx directory to PATH. echo. echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ + echo.https://www.sphinx-doc.org/ exit /b 1 ) +if "%1" == "" goto help + %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% goto end diff --git a/docs/source/conf.py b/docs/source/conf.py index 1bec9c6d..ff7aed1c 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -1,210 +1,170 @@ -# Configuration file for the Sphinx documentation builder. -# -# This file only contains a selection of the most common options. For a full -# list see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html +""" +Configuration file for the Sphinx documentation builder. -# -- Path setup -------------------------------------------------------------- -from importlib.metadata import version +For the full list of built-in configuration values, see the documentation: +https://www.sphinx-doc.org/en/master/usage/configuration.html +""" +from functools import wraps -# -- Project information ----------------------------------------------------- +from sphinxcontrib_autodocgen import AutoDocGen -project = "OpenSCM-Runner" -authors = ", ".join(["Zeb Nicholls", "Robert Gieseke", "Jared Lewis", "Sven Willner"]) -copyright_year = "2020" -copyright = "{}, {}".format(copyright_year, authors) -author = authors +import openscm_runner -# The full version, including alpha/beta/rc tags -release = version("openscm_runner") -# The short X.Y version -version = ".".join(release.split(".")[:2]) +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information +project = "OpenSCM-Runner" +# put the authors in their own variable, so they can be reused later +authors = ", ".join( + ["Zebedee Nicholls", "Robert Gieseke", "Jared Lewis", "Sven Willner"] +) +# add a copyright year variable, we can extend this over time in future as +# needed +copyright_year = "2020-2024" +copyright = f"{copyright_year}, {authors}" # -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. extensions = [ + # create documentation automatically from source code + # https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html "sphinx.ext.autodoc", - "sphinx.ext.coverage", + # automatic summary + "sphinx.ext.autosummary", + # automatic summary with better control + "sphinxcontrib_autodocgen", + # tell sphinx that we're using numpy style docstrings + # https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html + "sphinx.ext.napoleon", + # add support for type hints too (so type hints are included next to + # argument and return types in docs) + # https://github.com/tox-dev/sphinx-autodoc-typehints + # this must come after napoleon + # in the list for things to work properly + # https://github.com/tox-dev/sphinx-autodoc-typehints#compatibility-with-sphinxextnapoleon + "sphinx_autodoc_typehints", + # jupytext rendered notebook support (also loads myst_parser) + "myst_nb", + # links to other docs "sphinx.ext.intersphinx", - "sphinx.ext.napoleon", # pass numpy style docstrings - "sphinx_click.ext", + # add source code to docs + "sphinx.ext.viewcode", + # add copy code button to code examples + "sphinx_copybutton", + # math support + "sphinx.ext.mathjax", ] -autodoc_default_options = { - "inherited-members": None, - "members": None, - "private-members": None, - "show-inheritance": None, - "undoc-members": None, -} -# Add any paths that contain templates here, relative to this directory. +# general sphinx settings +# https://www.sphinx-doc.org/en/master/usage/configuration.html +# Don't include module names in object names (can also be left on, +# depends a bit how your project is structured and what you prefer) +add_module_names = False +# Other global settings which we've never used but are included by default templates_path = ["_templates"] - -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# -# source_suffix = ['.rst', '.md'] -source_suffix = ".rst" - -# The master toctree document. -master_doc = "index" - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = "en" - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ["build"] - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = "sphinx" - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -html_theme = "sphinx_rtd_theme" - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ["_static"] - -# Custom sidebar templates, must be a dictionary that maps document names -# to template names. -# -# The default sidebars (for documents that don't match any pattern) are -# defined by theme itself. Builtin themes are using these templates by -# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', -# 'searchbox.html']``. -# -# html_sidebars = {} - -html_context = { - "display_github": False, - "github_user": "openscm", - "github_repo": "openscm-runner", - "github_version": "master", - "conf_py_path": "/docs/source", -} - -# -- Options for HTMLHelp output --------------------------------------------- - -# Output file base name for HTML help builder. -htmlhelp_basename = "openscmrunnerdoc" - - -# -- Options for LaTeX output ------------------------------------------------ - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # - # 'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). - # - # 'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. - # - # 'preamble': '', - # Latex figure (float) alignment - # - # 'figure_align': 'htbp', +# Avoid sphinx thinking that conf.py is a source file because we use .py +# endings for notebooks +exclude_patterns = ["conf.py"] +# Stop sphinx doing funny things with byte order markers +source_encoding = "utf-8" + +# configure default settings for autodoc directives +# https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#directives +autodoc_default_options = { + # Show the inheritance of classes + "show-inheritance": True, } -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - (master_doc, "openscm-runner.tex", "OpenSCM-Runner Documentation", author, "manual") +# autosummary with autodocgen +# make sure autosummary doesn't interfere +autosummary_generate = True +autosummary_generate_overwrite = False + +autodocgen_config = [ + { + "modules": [openscm_runner], + "generated_source_dir": "docs/source/api", + # choose a different title for specific modules, e.g. the toplevel one + "module_title_decider": lambda modulename: "API Reference" + if modulename == "openscm_runner" + else modulename, + } ] - -# -- Options for manual page output ------------------------------------------ - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, "openscm-runner", "OpenSCM-Runner Documentation", [author], 1) -] +# monkey patch to remove leading newlines +generate_module_rst_orig = AutoDocGen.generate_module_rst -# -- Options for Texinfo output ---------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ( - master_doc, - "openscm-runner", - "OpenSCM-Runner Documentation", - author, - "openscm-runner", - "Thin wrapper to run simple climate models (emissions driven runs only)", - "Miscellaneous", - ) -] +@wraps(generate_module_rst_orig) +def _generate_module_rst_new(*args, **kwargs): + default = generate_module_rst_orig(*args, **kwargs) + out = default.lstrip("\n") + if not out.endswith("\n"): + out = f"{out}\n" -# -- Options for Epub output ------------------------------------------------- + return out -# Bibliographic Dublin Core info. -epub_title = project -# The unique identifier of the text. This can be a ISBN number -# or the project homepage. -# -# epub_identifier = '' +AutoDocGen.generate_module_rst = _generate_module_rst_new -# A unique identification for the text. -# -# epub_uid = '' +# napoleon extension settings +# https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html +# We use numpy style docstrings +napoleon_numpy_docstring = True +# We don't use google docstrings +napoleon_google_docstring = False +# Don't use separate rtype for the return documentation +napoleon_use_rtype = False + +# autodoc type hints settings +# https://github.com/tox-dev/sphinx-autodoc-typehints +# include full name of classes when expanding type hints? +typehints_fully_qualified = True +# Add rtype directive if needed +typehints_document_rtype = True +# Put the return type as part of the return documentation +typehints_use_rtype = False + +# Left-align maths equations +mathjax3_config = {"chtml": {"displayAlign": "center"}} + +# myst configuration +myst_enable_extensions = ["amsmath", "dollarmath"] +# cache because we save our notebooks as `.py` files i.e. without output +# stored so auto doesn't work (it just ends up being run every time) +nb_execution_mode = "cache" +nb_execution_raise_on_error = True +nb_execution_show_tb = True +nb_execution_timeout = 120 +nb_custom_formats = {".py": ["jupytext.reads", {"fmt": "py:percent"}]} -# A list of files that should not be packed into the epub file. -epub_exclude_files = ["search.html"] +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output +# Pick your theme for html output, we typically use the read the docs theme +html_theme = "sphinx_rtd_theme" +html_static_path = ["_static"] -# -- Extension configuration ------------------------------------------------- -coverage_write_headline = False # do not write headlines. +# Ignore ipynb files when building (see https://github.com/executablebooks/MyST-NB/issues/363). +def setup(app): + """ + Set up the Sphinx app + """ + app.registry.source_suffix.pop(".ipynb", None) -# -- Options for intersphinx extension --------------------------------------- -# Example configuration for intersphinx: refer to the Python standard library. +# Intersphinx mapping intersphinx_mapping = { "numpy": ("https://docs.scipy.org/doc/numpy", None), "pandas": ("https://pandas.pydata.org/pandas-docs/stable", None), "python": ("https://docs.python.org/3", None), "pyam": ("https://pyam-iamc.readthedocs.io/en/latest", None), "scmdata": ("https://scmdata.readthedocs.io/en/latest", None), - # "pint": ("https://pint.readthedocs.io/en/latest", None), # no full API doc here, unfortunately + "xarray": ("http://xarray.pydata.org/en/stable", None), + "pint": ( + "https://pint.readthedocs.io/en/latest", + None, + ), } -napoleon_google_docstring = False -napoleon_numpy_docstring = True -set_type_checking_flag = False - -# -- Options for todo extension ---------------------------------------------- - -# If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = True - -# # -- Logos ------------------------------------------------------------------- - -# html_logo = "_static/logo_200px_wide.png" -# latex_logo = "_static/logo.png" - - -# -- Misc configuration ------------------------------------------------- - -rst_epilog = """ -.. |CO2| replace:: CO\ :sub:`2`\ -""" diff --git a/pyproject.toml b/pyproject.toml index 2456fa95..789023b0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,34 +1,216 @@ -[build-system] -requires = [ - "setuptools>=41.2", - "setuptools_scm[toml]>=1.15", - "wheel>=0.31.0", -] -build-backend = "setuptools.build_meta" +[tool.poetry] +name = "openscm-runner" +version = "0.1.0" +description = "Thin wrapper to run emissions scenarios with simple climate models" +authors = ["Zebedee Nicholls "] +readme = "README.md" +packages = [{include = "openscm_runner", from = "src"}] + +[tool.poetry.dependencies] +python = "^3.9" +notebook = { version = "^6.5.3", optional = true } +openscm-units = ">=0.5.0" +python-dotenv = "^1.0.0" +scmdata = ">=0.7.4" +tqdm = "^4.66.1" +fair = "<2" +pymagicc = "<3" +ciceroscm = "^1.0.0" +ipywidgets = "^8.1.1" +seaborn = "^0.13.1" + +[tool.poetry.extras] +notebooks = ["notebook"] + +[tool.poetry.group.tests.dependencies] +pytest = "^7.3.1" -[tool.setuptools_scm] +[tool.poetry.group.docs.dependencies] +myst-nb = "^0.17.0" +sphinx-rtd-theme = "^1.2.0" +sphinx-autodoc-typehints = "^1.23.0" +sphinx-autodocgen = "^1.3" +jupytext = "^1.14.5" +sphinx-copybutton = "^0.5.2" + +[tool.poetry.group.dev.dependencies] +pytest-cov = "^4.0.0" +coverage = "^7.2.0" +mypy = "^1.2.0" +ruff = "^0.1.8" +pre-commit = "^3.3.1" +towncrier = "^23.6.0" +liccheck = "^0.9.1" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" [tool.coverage.run] +source = ["src"] branch = true -source = [ - "src/openscm_runner" -] -omit = [ - "*_version.py", - "*testing.py" -] -concurrency = ["multiprocessing"] -parallel = true -sigterm = true [tool.coverage.report] -fail_under = 90 +fail_under = 95 skip_empty = true show_missing = true -ignore_errors = true - # Regexes for lines to exclude from consideration in addition to the defaults exclude_also = [ # Don't complain about missing type checking code: "if TYPE_CHECKING", ] + +[tool.mypy] +strict = true +# prevent unimported libraries silently being treated as Any +disallow_any_unimported = true +# show error codes on failure with context +show_error_codes = true +show_error_context = true +# warn if code can't be reached +warn_unreachable = true +# importing following uses default settings +follow_imports = "normal" + +[tool.jupytext] +formats = "ipynb,py:percent" + +[tool.pytest.ini_options] +addopts = [ + "--import-mode=importlib", +] + +[tool.ruff] +src = ["src"] +target-version = "py39" +select = [ + "E", # pycodestyle error + "W", # pycodestyle warning + "F", # pyflakes + "I", # isort + "D", # pydocstyle + "PL", # pylint + "TRY", # tryceratops + "NPY", # numpy rules + "RUF", # ruff specifics + "UP", # pyupgrade + "S", # flake8-bandit + # pandas support via pandas-vet. In some cases we will want to disable + # this because it can lead to too many false positives. + "PD", +] +unfixable = [ + "PD002", # Disable autofix for inplace as this often introduces bugs +] +ignore = [ + "D200", # One-line docstring should fit on one line with quotes + "D400", # First line should end with a period +] +line-length = 88 + +[tool.ruff.format] +docstring-code-format = true + +[tool.ruff.per-file-ignores] +"test*.py" = [ + "D", # Documentation not needed in tests + "S101", # S101 Use of `assert` detected + "PLR2004" # Magic value used in comparison +] +"docs/source/notebooks/*" = [ + "D100", # Missing docstring at the top of file + "E402", # Module level import not at top of file + "S101", # Use of `assert` detected +] +"scripts/*" = [ + "S101" # S101 Use of `assert` detected +] + +[tool.ruff.isort] +known-first-party = ["src"] + +[tool.ruff.pydocstyle] +convention = "numpy" + +[tool.towncrier] +package = "openscm_runner" +package_dir = "src" +filename = "docs/source/changelog.md" +directory = "changelog/" +title_format = "## openscm-runner {version} ({project_date})" +underlines = ["", "", ""] +issue_format = "[#{issue}](https://github.com/openscm/openscm-runner/pulls/{issue})" + + [[tool.towncrier.type]] + directory = "breaking" + name = "Breaking Changes" + showcontent = true + + [[tool.towncrier.type]] + directory = "deprecation" + name = "Deprecations" + showcontent = true + + [[tool.towncrier.type]] + directory = "feature" + name = "Features" + showcontent = true + + [[tool.towncrier.type]] + directory = "improvement" + name = "Improvements" + showcontent = true + + [[tool.towncrier.type]] + directory = "fix" + name = "Bug Fixes" + showcontent = true + + [[tool.towncrier.type]] + directory = "docs" + name = "Improved Documentation" + showcontent = true + + [[tool.towncrier.type]] + directory = "trivial" + name = "Trivial/Internal Changes" + showcontent = false + +[tool.liccheck] +authorized_licenses = [ + "bsd", + "bsd license", + "BSD 3-Clause", + "CC0", + "apache", + "apache 2.0", + "apache software", + "apache software license", + "Apache License, Version 2.0", + "Historical Permission Notice and Disclaimer (HPND)", + "isc license", + "isc license (iscl)", + "gnu lgpl", + "lgpl with exceptions or zpl", + "LGPLv2+", + "GNU Lesser General Public License v2 (LGPLv2)", + "GNU Lesser General Public License v2 or later (LGPLv2+)", + "mit", + "mit license", + "Mozilla Public License 2.0 (MPL 2.0)", + "python software foundation", + "python software foundation license", + "zpl 2.1", +] +# This starting list is relatively conservative. Depending on the project, it +# may make sense to move some of these into the authorized list +unauthorized_licenses = [ + "agpl", + "gnu agpl", + "gpl v3", + "gplv3", + "gpl v2", + "gplv2", + "gpl v1", + "gplv1", +] diff --git a/src/openscm_runner/__init__.py b/src/openscm_runner/__init__.py index c82ebd16..b8d373b1 100644 --- a/src/openscm_runner/__init__.py +++ b/src/openscm_runner/__init__.py @@ -1,18 +1,6 @@ """ -OpenSCM-Runner, a thin wrapper to run simple climate models with a unified interface. - -See README and docs for more info. +Thin wrapper to run emissions scenarios with simple climate models """ -from .run import run # noqa: F401 - -try: - from importlib.metadata import version as _version -except ImportError: - # no recourse if the fallback isn't there either... - from importlib_metadata import version as _version +import importlib.metadata -try: - __version__ = _version("openscm_runner") -except Exception: # pylint: disable=broad-except # pragma: no cover - # Local copy, not installed with setuptools - __version__ = "unknown" +__version__ = importlib.metadata.version("openscm_runner") diff --git a/tests/conftest.py b/tests/conftest.py index 86c2a47b..449ca1b0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,50 +1,23 @@ -import os.path +""" +Re-useable fixtures etc. for tests -import pyam -import pytest -from scmdata import ScmRun - -from openscm_runner.adapters import CICEROSCM, MAGICC7 - -TEST_DATA_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "test-data") +See https://docs.pytest.org/en/7.1.x/reference/fixtures.html#conftest-py-sharing-fixtures-across-multiple-files +""" +from __future__ import annotations +from pathlib import Path -@pytest.fixture(scope="session") -def test_data_dir(): - return TEST_DATA_DIR - - -@pytest.fixture(scope="session") -def test_scenarios(test_data_dir): - scenarios = pyam.IamDataFrame( - os.path.join(test_data_dir, "rcmip_scen_ssp_world_emissions.csv") - ) - - return scenarios - - -@pytest.fixture(scope="session") -def test_scenarios_2600(test_data_dir): - scenarios = pyam.IamDataFrame( - os.path.join(test_data_dir, "rcmip_scen_ssp_world_emissions_2600.csv") - ) - - return scenarios - - -@pytest.fixture(scope="session") -def test_scenario_ssp370_world(test_data_dir): - scenario = ScmRun( - os.path.join( - test_data_dir, "rcmip-emissions-annual-means-v5-1-0-ssp370-world.csv" - ), - lowercase_cols=True, - ) +import pandas as pd +import pytest +import scmdata - return scenario +from openscm_runner.adapters import CICEROSCM, MAGICC7 +TEST_DATA_DIR = Path(__file__).parent / "test-data" +"""Directory in which test data lives""" REQUIRED_MAGICC_VERSION = "v7.5.3" +"""MAGICC version required for the tests""" try: MAGICC_VERSION = MAGICC7.get_version() @@ -68,7 +41,7 @@ def test_scenario_ssp370_world(test_data_dir): CICERO_OS_ERROR = False -def pytest_runtest_setup(item): +def pytest_runtest_setup(item) -> None: for mark in item.iter_markers(): if mark.name == "magicc" and not CORRECT_MAGICC_IS_AVAILABLE: if MAGICC_VERSION is None: @@ -87,15 +60,49 @@ def pytest_runtest_setup(item): pytest.skip("CICERO-SCM not available") -def pytest_addoption(parser): - parser.addoption( - "--update-expected-values", - action="store_true", - default=False, - help="Overwrite expected values", +@pytest.fixture(scope="session", autouse=True) +def pandas_terminal_width(): + # Set pandas terminal width so that doctests don't depend on terminal width. + + # We set the display width to 120 because examples should be short, + # anything more than this is too wide to read in the source. + pd.set_option("display.width", 120) + + # Display as many columns as you want (i.e. let the display width do the + # truncation) + pd.set_option("display.max_columns", 1000) + + +@pytest.fixture(scope="session") +def test_data_dir() -> Path: + return TEST_DATA_DIR + + +@pytest.fixture(scope="session") +def test_scenarios(test_data_dir: Path) -> scmdata.ScmRun: + scenarios = scmdata.ScmRun( + test_data_dir / "rcmip_scen_ssp_world_emissions.csv", + lowercase_cols=True, ) + return scenarios + -@pytest.fixture -def update_expected_values(request): - return request.config.getoption("--update-expected-values") +@pytest.fixture(scope="session") +def test_scenarios_2600(test_data_dir: Path) -> scmdata.ScmRun: + scenarios = scmdata.ScmRun( + test_data_dir / "rcmip_scen_ssp_world_emissions_2600.csv", + lowercase_cols=True, + ) + + return scenarios + + +@pytest.fixture(scope="session") +def test_scenario_ssp370_world(test_data_dir: Path) -> scmdata.ScmRun: + scenario = scmdata.ScmRun( + test_data_dir / "rcmip-emissions-annual-means-v5-1-0-ssp370-world.csv", + lowercase_cols=True, + ) + + return scenario From 00519fed50b2f97a36aa5d4ccd2f2ede88be1f99 Mon Sep 17 00:00:00 2001 From: Zebedee Nicholls Date: Tue, 9 Jan 2024 16:15:50 +0100 Subject: [PATCH 02/61] Keep cleaning up --- .copier-answers.yml | 15 ++ .github/ISSUE_TEMPLATE/bug.md | 41 ++++ .github/ISSUE_TEMPLATE/bug_report.md | 30 --- .github/ISSUE_TEMPLATE/default.md | 23 +++ .github/ISSUE_TEMPLATE/feature_request.md | 30 ++- .github/PULL_REQUEST_TEMPLATE/default.md | 9 + .github/actions/setup/action.yml | 57 ++++++ .github/pull_request_template.md | 6 - .github/release_template.md | 7 + .github/workflows/bump.yaml | 60 ++++++ .github/workflows/ci-cd-workflow.yml | 189 ------------------ .github/workflows/ci.yaml | 140 +++++++++++++ .github/workflows/deploy.yaml | 33 +++ .github/workflows/install.yaml | 30 +++ .github/workflows/release.yaml | 47 +++++ .github/workflows/test-conda-install.yml | 35 ---- .github/workflows/test-pypi-install.yml | 31 --- .pre-commit-config.yaml | 42 ++++ README.md | 5 +- changelog/README.md | 41 ++++ docs/source/_templates/.gitkeep | 0 .../api/openscm_runner.adapters.base.rst | 6 + ...r.adapters.ciceroscm_adapter.ciceroscm.rst | 14 ++ ...rs.ciceroscm_adapter.ciceroscm_wrapper.rst | 20 ++ ....ciceroscm_adapter.make_scenario_files.rst | 14 ++ ...dapters.ciceroscm_adapter.read_results.rst | 50 +++++ ...nscm_runner.adapters.ciceroscm_adapter.rst | 16 ++ ...iceroscm_adapter.write_parameter_files.rst | 26 +++ ...pters.ciceroscm_py_adapter.ciceroscmpy.rst | 14 ++ ...rs.ciceroscm_py_adapter.cscmpy_wrapper.rst | 20 ++ ...iceroscm_py_adapter.make_scenario_data.rst | 14 ++ ...ters.ciceroscm_py_adapter.read_results.rst | 44 ++++ ...m_runner.adapters.ciceroscm_py_adapter.rst | 15 ++ ...ner.adapters.fair_adapter.fair_adapter.rst | 14 ++ .../openscm_runner.adapters.fair_adapter.rst | 12 ++ ...penscm_runner.adapters.magicc7.magicc7.rst | 14 ++ .../api/openscm_runner.adapters.magicc7.rst | 12 ++ docs/source/api/openscm_runner.adapters.rst | 34 ++++ ...s.cicero_forcing_postprocessing_common.rst | 13 ++ ...tils.cicero_utils.make_scenario_common.rst | 14 ++ ...scm_runner.adapters.utils.cicero_utils.rst | 13 ++ .../api/openscm_runner.adapters.utils.rst | 12 ++ docs/source/api/openscm_runner.operations.rst | 13 ++ docs/source/api/openscm_runner.progress.rst | 13 ++ docs/source/api/openscm_runner.rst | 18 ++ docs/source/api/openscm_runner.run.rst | 13 ++ docs/source/api/openscm_runner.settings.rst | 14 ++ docs/source/api/openscm_runner.testing.rst | 6 + docs/source/api/openscm_runner.utils.rst | 13 ++ docs/source/changelog.md | 20 ++ docs/source/development.md | 55 +++++ docs/source/index.md | 42 ++++ docs/source/notebooks.md | 21 ++ docs/source/notebooks/basic-demo.py | 24 +++ scripts/test-install.py | 52 +++++ scripts/test_install.py | 53 ----- 56 files changed, 1264 insertions(+), 355 deletions(-) create mode 100644 .copier-answers.yml create mode 100644 .github/ISSUE_TEMPLATE/bug.md delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/default.md create mode 100644 .github/PULL_REQUEST_TEMPLATE/default.md create mode 100644 .github/actions/setup/action.yml delete mode 100644 .github/pull_request_template.md create mode 100644 .github/release_template.md create mode 100644 .github/workflows/bump.yaml delete mode 100644 .github/workflows/ci-cd-workflow.yml create mode 100644 .github/workflows/ci.yaml create mode 100644 .github/workflows/deploy.yaml create mode 100644 .github/workflows/install.yaml create mode 100644 .github/workflows/release.yaml delete mode 100644 .github/workflows/test-conda-install.yml delete mode 100644 .github/workflows/test-pypi-install.yml create mode 100644 .pre-commit-config.yaml create mode 100644 changelog/README.md create mode 100644 docs/source/_templates/.gitkeep create mode 100644 docs/source/api/openscm_runner.adapters.base.rst create mode 100644 docs/source/api/openscm_runner.adapters.ciceroscm_adapter.ciceroscm.rst create mode 100644 docs/source/api/openscm_runner.adapters.ciceroscm_adapter.ciceroscm_wrapper.rst create mode 100644 docs/source/api/openscm_runner.adapters.ciceroscm_adapter.make_scenario_files.rst create mode 100644 docs/source/api/openscm_runner.adapters.ciceroscm_adapter.read_results.rst create mode 100644 docs/source/api/openscm_runner.adapters.ciceroscm_adapter.rst create mode 100644 docs/source/api/openscm_runner.adapters.ciceroscm_adapter.write_parameter_files.rst create mode 100644 docs/source/api/openscm_runner.adapters.ciceroscm_py_adapter.ciceroscmpy.rst create mode 100644 docs/source/api/openscm_runner.adapters.ciceroscm_py_adapter.cscmpy_wrapper.rst create mode 100644 docs/source/api/openscm_runner.adapters.ciceroscm_py_adapter.make_scenario_data.rst create mode 100644 docs/source/api/openscm_runner.adapters.ciceroscm_py_adapter.read_results.rst create mode 100644 docs/source/api/openscm_runner.adapters.ciceroscm_py_adapter.rst create mode 100644 docs/source/api/openscm_runner.adapters.fair_adapter.fair_adapter.rst create mode 100644 docs/source/api/openscm_runner.adapters.fair_adapter.rst create mode 100644 docs/source/api/openscm_runner.adapters.magicc7.magicc7.rst create mode 100644 docs/source/api/openscm_runner.adapters.magicc7.rst create mode 100644 docs/source/api/openscm_runner.adapters.rst create mode 100644 docs/source/api/openscm_runner.adapters.utils.cicero_utils.cicero_forcing_postprocessing_common.rst create mode 100644 docs/source/api/openscm_runner.adapters.utils.cicero_utils.make_scenario_common.rst create mode 100644 docs/source/api/openscm_runner.adapters.utils.cicero_utils.rst create mode 100644 docs/source/api/openscm_runner.adapters.utils.rst create mode 100644 docs/source/api/openscm_runner.operations.rst create mode 100644 docs/source/api/openscm_runner.progress.rst create mode 100644 docs/source/api/openscm_runner.rst create mode 100644 docs/source/api/openscm_runner.run.rst create mode 100644 docs/source/api/openscm_runner.settings.rst create mode 100644 docs/source/api/openscm_runner.testing.rst create mode 100644 docs/source/api/openscm_runner.utils.rst create mode 100644 docs/source/changelog.md create mode 100644 docs/source/development.md create mode 100644 docs/source/index.md create mode 100644 docs/source/notebooks.md create mode 100644 docs/source/notebooks/basic-demo.py create mode 100644 scripts/test-install.py delete mode 100644 scripts/test_install.py diff --git a/.copier-answers.yml b/.copier-answers.yml new file mode 100644 index 00000000..52b2c285 --- /dev/null +++ b/.copier-answers.yml @@ -0,0 +1,15 @@ +# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY +_commit: v0.4.1 +_src_path: /Users/znicholls/Documents/repos/copier-core-python-repository +email: zebedee.nicholls@climate-energy-college.org +initial_setup: true +name: Zebedee Nicholls +notebook_dependencies: true +pandas_doctests: true +plot_dependencies: false +project_description_short: Thin wrapper to run emissions scenarios with simple climate + models +project_name_human: OpenSCM-Runner +project_name_pip: openscm-runner +project_name_python: openscm_runner +project_url: https://github.com/openscm/openscm-runner diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md new file mode 100644 index 00000000..d43f7092 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -0,0 +1,41 @@ +--- +name: Bug report +about: Report a bug +title: '' +labels: bug +assignees: '' + +--- + +## Describe the bug + + +## Failing Test + + +## Expected behavior + + +## Screenshots + + +## System + + + - OS: [e.g. Windows, Linux, macOS] + - Python version [e.g. Python 3.11] + - Please also upload your `poetry.lock` file (first run `poetry lock` to make sure the lock file is up-to-date) + +## Additional context + diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 6953102f..00000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -name: Bug Report -about: Write a report to help us improve - ---- - -**Describe the bug** - -A clear and concise description of what the bug is, in particular: - -- What did you do? -- What actually happened? -- What did you expect to happen? - -**Failing Test** - -Please put code (ideally in the form of a unit test) which fails below - -**Screenshots** - -If applicable, add screenshots to help explain your problem. - -**System (please complete the following information):** - - - OS: [e.g. Windows, Linux, macOS] - - Python and openscm commit/version [e.g. Python 3.5] - -**Additional context** - -Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/default.md b/.github/ISSUE_TEMPLATE/default.md new file mode 100644 index 00000000..ca635302 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/default.md @@ -0,0 +1,23 @@ +--- +name: Default +about: Report an issue or problem +title: '' +labels: triage +assignees: '' +--- + +## The problem + + + +## Definition of "done" + + + +## Additional context + + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index be69a0b6..8cd98957 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,21 +1,31 @@ --- name: Feature Request -about: Suggest an idea for this project - +about: Request a feature or suggest an idea for this project +title: '' +labels: feature-request +assignees: '' --- -**Is your feature request related to a problem? Please describe.** +## The motivation + + + +## The proposed solution -A clear and concise description of what the problem is. E.g. It's annoying that I always have to [...] + -A clear and concise description of the solution you would like to see. +## Alternatives -**Describe alternatives you've considered** + -**Additional context** +## Additional context -Add any other context or screenshots about the feature request here. + diff --git a/.github/PULL_REQUEST_TEMPLATE/default.md b/.github/PULL_REQUEST_TEMPLATE/default.md new file mode 100644 index 00000000..7ff7065e --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/default.md @@ -0,0 +1,9 @@ +## Description + +## Checklist + +Please confirm that this pull request has done the following: + +- [ ] Tests added +- [ ] Documentation added (where applicable) +- [ ] Changelog item added to `changelog/` diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml new file mode 100644 index 00000000..622953db --- /dev/null +++ b/.github/actions/setup/action.yml @@ -0,0 +1,57 @@ +name: "Setup Python and Poetry" +description: "setup Python and Poetry with caches" + +inputs: + python-version: + description: "Python version to use" + required: true + venv-id: + description: "ID to identify cached environment (should be unique from other steps)" + required: true + poetry-dependency-install-flags: + description: "Flags to pass to poetry when running `poetry install --no-interaction --no-root`" + required: true + run-poetry-install: + description: "Should we run the poetry install steps" + required: false + default: true + + +runs: + using: "composite" + steps: + - name: Set up Python ${{ inputs.python-version }} + id: setup-python + uses: actions/setup-python@v4 + with: + python-version: ${{ inputs.python-version }} + - name: Load cached Poetry installation + id: cached-poetry + uses: actions/cache@v3 + with: + path: ~/.local # the path depends on the OS + key: poetry-2 # increment to reset cache + - name: Install Poetry + if: steps.cached-poetry.outputs.cache-hit != 'true' + uses: snok/install-poetry@v1 + - name: Load cached venv + if: ${{ inputs.run-poetry-install == 'true' }} + id: cached-poetry-dependencies + uses: actions/cache@v3 + with: + path: .venv + key: "venv-${{ inputs.venv-id }}-${{ inputs.python-version }}-${{ hashFiles('**/poetry.lock') }}" + # Install dependencies first so that our package doesn't appear in the cache by accident + - name: Install dependencies + if: ${{ inputs.run-poetry-install == 'true' }} + shell: bash + run: | + poetry config virtualenvs.create true + poetry config virtualenvs.in-project true + poetry env use ${{ inputs.python-version }} + poetry install --no-interaction --no-root ${{ inputs.poetry-dependency-install-flags }} + # Now run same command but let the package install too + - name: Install package + if: ${{ inputs.run-poetry-install == 'true' }} + shell: bash + run: poetry install --no-interaction ${{ inputs.poetry-dependency-install-flags }} diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md deleted file mode 100644 index 41b90f58..00000000 --- a/.github/pull_request_template.md +++ /dev/null @@ -1,6 +0,0 @@ - - -- [ ] Tests added -- [ ] Documentation added -- [ ] Example added (in the documentation, to an existing notebook, or in a new notebook) -- [ ] Description in ``CHANGELOG.rst`` added (single line such as: ``(`#XX `_) Added feature which does something``) diff --git a/.github/release_template.md b/.github/release_template.md new file mode 100644 index 00000000..c07018cf --- /dev/null +++ b/.github/release_template.md @@ -0,0 +1,7 @@ +## Announcements + +* Announcement 1 + +## Changes + +* Change 1 diff --git a/.github/workflows/bump.yaml b/.github/workflows/bump.yaml new file mode 100644 index 00000000..5e6f375d --- /dev/null +++ b/.github/workflows/bump.yaml @@ -0,0 +1,60 @@ +name: Bump version + +on: + workflow_dispatch: + inputs: + bump_rule: + type: choice + description: How to bump the project's version (see https://python-poetry.org/docs/cli/#version) + options: + - patch + - minor + - major + - prepatch + - preminor + - premajor + - prerelease + required: true + +jobs: + bump_version: + name: "Bump version and create changelog" + if: "!startsWith(github.event.head_commit.message, 'bump:')" + runs-on: ubuntu-latest + env: + CI_COMMIT_EMAIL: "ci-runner@openscm-runner.invalid" + steps: + - name: Check out repository + uses: actions/checkout@v3 + with: + fetch-depth: 0 + token: "${{ secrets.PERSONAL_ACCESS_TOKEN }}" + + # towncrier imports the package as part of building so we have to + # install the pacakage (to keep things slim, we only install the main + # dependencies, which also means that we get a test that we can import + # the package with only the compulsory dependencies installed for free) + - uses: ./.github/actions/setup + with: + python-version: "3.11" + venv-id: "bump" + poetry-dependency-install-flags: "--only main" + + - name: Install towncrier + run: | + poetry run pip install towncrier + + - name: Create bump and changelog + + run: | + BASE_VERSION=`poetry version -s` + NEW_VERSION=`poetry version -s ${{ github.event.inputs.bump_rule }}` + poetry run towncrier build --yes --version v$NEW_VERSION + + git config --global user.name "$GITHUB_ACTOR" + git config --global user.email "$CI_COMMIT_EMAIL" + + git commit -a -m "bump: version $BASE_VERSION -> $NEW_VERSION" + git tag v$NEW_VERSION + git push && git push --tags + echo "Bumped to version $NEW_VERSION" diff --git a/.github/workflows/ci-cd-workflow.yml b/.github/workflows/ci-cd-workflow.yml deleted file mode 100644 index 39982406..00000000 --- a/.github/workflows/ci-cd-workflow.yml +++ /dev/null @@ -1,189 +0,0 @@ -name: OpenSCM-Runner CI-CD -on: - push: - branches: - - main - tags: - - 'v*' - pull_request: - -jobs: - linting-and-docs: - - runs-on: ubuntu-latest - strategy: - matrix: - python-version: [3.9] - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - name: Setup python - uses: actions/setup-python@v1 - with: - python-version: ${{ matrix.python-version }} - - name: Install dev dependencies - run: | - pip install --upgrade pip wheel - pip install -e .[dev] - - name: Formatting and linters - run: | - black --check src tests setup.py - isort --check-only --quiet --recursive src tests setup.py - pydocstyle src - bandit -c .bandit.yml -r src - flake8 src tests setup.py - pylint src - - name: Build docs - # treat warnings as errors (-W)... - # ...but not when being nitpicky (-n) - run: | - sphinx-build -M html docs/source docs/build -qW - sphinx-build -M html docs/source docs/build -Eqn -b coverage - if [[ -s docs/build/html/python.txt ]] - then - echo - echo \"Error: Documentation missing:\" - echo - cat docs/build/html/python.txt - exit 1 - fi - - build: - runs-on: ${{ matrix.os }} - environment: CI - strategy: - matrix: - # no mac binary for CICERO so fails code coverage - os: ["ubuntu-latest", "macos-latest", "windows-latest"] - python-version: [3.7, 3.8, 3.9, "3.10", 3.11] - env: - MIN_COVERAGE: 90 - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - name: Setup python - uses: actions/setup-python@v1 - with: - python-version: ${{ matrix.python-version }} - - name: Download MAGICC non-windows - if: runner.os != 'Windows' - run: | - mkdir -p bin/magicc/magicc-v7.5.3 - wget -O "bin/magicc/magicc-v7.5.3.tar.gz" "${{ secrets.MAGICC_LINK_FROM_MAGICC_DOT_ORG }}" - tar -xf bin/magicc/magicc-v7.5.3.tar.gz -C bin/magicc/magicc-v7.5.3 - - name: Install test dependencies - run: | - pip install --upgrade pip wheel - pip install -e .[tests,models] - - name: Test with pytest Linux - if: runner.os == 'Linux' - env: - MAGICC_EXECUTABLE_7: bin/magicc/magicc-v7.5.3/bin/magicc - run: | - pytest tests -r a --cov=openscm_runner --cov-report='term-missing' --cov-fail-under=$MIN_COVERAGE - - name: Test with pytest macOS - if: runner.os == 'macOS' - env: - MAGICC_EXECUTABLE_7: bin/magicc/magicc-v7.5.3/bin/magicc-darwin-amd64 - run: | - # Locate the gfortran library. The location can change when the image is updated - GFORTRAN_LIBS=$(find /usr/local/Cellar/gcc@11 -name libgfortran.5.dylib | head -n 1 | xargs dirname) - echo $GFORTRAN_LIBS - export DYLD_LIBRARY_PATH=$GFORTRAN_LIBS:$DYLD_LIBRARY_PATH - # Not testing coverage for macOS due to the CIRERO binary being unavailable - pytest tests -r a - - name: Test with pytest Windows - if: runner.os == 'Windows' - run: | - # Not strictly testing coverage under windows as MAGICC isn't available - pytest tests -r a --cov=openscm_runner --cov-report='term-missing' --cov-fail-under=70 - - test-notebooks: - runs-on: ubuntu-latest - environment: CI - strategy: - matrix: - python-version: [3.7, 3.8, 3.9, "3.10", 3.11] - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - name: Setup python - uses: actions/setup-python@v1 - with: - python-version: ${{ matrix.python-version }} - - name: Download MAGICC - run: | - mkdir -p bin/magicc/magicc-v7.5.3 - wget -O "bin/magicc/magicc-v7.5.3.tar.gz" "${{ secrets.MAGICC_LINK_FROM_MAGICC_DOT_ORG }}" - tar -xf bin/magicc/magicc-v7.5.3.tar.gz -C bin/magicc/magicc-v7.5.3 - - name: Install notebook dependencies - run: | - pip install --upgrade pip wheel - pip install -e .[tests,models,notebooks] - - name: Test notebooks with nbval - run: | - pytest notebooks -r a --nbval-lax --sanitize-with tests/notebook-tests.cfg --no-cov - - name: Test notebooks strictly - if: matrix.python-version == 3.7 - run: | - pytest notebooks -r a --nbval --sanitize-with tests/notebook-tests.cfg --no-cov - - test-install: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: [3.7, 3.8, 3.9, "3.10", 3.11] - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - name: Setup python - uses: actions/setup-python@v1 - with: - python-version: ${{ matrix.python-version }} - - name: Test installation - run: | - pip install --upgrade pip wheel - pip install . - python scripts/test_install.py - - deploy-pypi: - needs: [linting-and-docs,build,test-notebooks,test-install] - if: startsWith(github.ref, 'refs/tags/v') - - runs-on: ubuntu-latest - strategy: - matrix: - python-version: [3.7] - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - name: Setup python - uses: actions/setup-python@v1 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - pip install --upgrade pip wheel - pip install -e .[dev] - - name: Create package - run: | - python setup.py sdist bdist_wheel --universal - for f in adapters/fair_adapter/natural-emissions-and-forcing.csv adapters/ciceroscm_adapter/utils_templates/gases_v1RCMIP.txt adapters/ciceroscm_adapter/utils_templates/run_dir/scm_vCH4fb adapters/ciceroscm_adapter/utils_templates/run_dir/input_RF/RFSUN/solar_IPCC.txt - do - if ! tar -tvf dist/openscm-runner*.tar.gz | grep "$f" - then - echo - echo "${f} csv not correctly packaged" - exit 1 - fi - done - - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@master - with: - user: __token__ - password: ${{ secrets.pypi_password }} diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 00000000..0913b3b9 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,140 @@ +name: CI + +on: + pull_request: + push: + branches: [main] + tags: ['v*'] + +jobs: + mypy: + if: ${{ !github.event.pull_request.draft }} + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v3 + - uses: ./.github/actions/setup + with: + python-version: "3.9" + venv-id: "docs" + poetry-dependency-install-flags: "--all-extras --only 'main,dev'" + - name: mypy + run: MYPYPATH=stubs poetry run mypy src + + docs: + if: ${{ !github.event.pull_request.draft }} + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v3 + - uses: ./.github/actions/setup + with: + python-version: "3.9" + venv-id: "docs" + poetry-dependency-install-flags: "--all-extras --only 'main,docs'" + - name: docs + run: poetry run sphinx-build -W --keep-going -T -b html docs/source docs/build + + tests: + strategy: + fail-fast: false + matrix: + os: [ "ubuntu-latest", "macos-latest", "windows-latest" ] + python-version: [ "3.9", "3.10", "3.11" ] + runs-on: "${{ matrix.os }}" + steps: + - name: Check out repository + uses: actions/checkout@v3 + - uses: ./.github/actions/setup + with: + python-version: "${{ matrix.python-version }}" + venv-id: "tests-${{ runner.os }}" + poetry-dependency-install-flags: "--all-extras" + - name: Download MAGICC non-windows + if: runner.os != 'Windows' + run: | + mkdir -p bin/magicc/magicc-v7.5.3 + wget -O "bin/magicc/magicc-v7.5.3.tar.gz" "${{ secrets.MAGICC_LINK_FROM_MAGICC_DOT_ORG }}" + tar -xf bin/magicc/magicc-v7.5.3.tar.gz -C bin/magicc/magicc-v7.5.3 + - name: Run tests linux + if: runner.os == 'Linux' + env: + MAGICC_EXECUTABLE_7: bin/magicc/magicc-v7.5.3/bin/magicc + run: | + poetry run pytest -r a -v src tests --doctest-modules --cov=src --cov-report=term-missing --cov-report=xml + poetry run coverage report + - name: Run tests macOS + if: runner.os == 'macOS' + env: + MAGICC_EXECUTABLE_7: bin/magicc/magicc-v7.5.3/bin/magicc-darwin-amd64 + run: | + # Locate the gfortran library. The location can change when the image is updated + GFORTRAN_LIBS=$(find /usr/local/Cellar/gcc@11 -name libgfortran.5.dylib | head -n 1 | xargs dirname) + echo $GFORTRAN_LIBS + export DYLD_LIBRARY_PATH=$GFORTRAN_LIBS:$DYLD_LIBRARY_PATH + # TODO: loosen coverage requirements if CI fails, otherwise delete this comment + poetry run pytest -r a -v src tests --doctest-modules --cov=src --cov-report=term-missing --cov-report=xml + - name: Run tests windows + if: runner.os == 'Windows' + env: + MAGICC_EXECUTABLE_7: bin/magicc/magicc-v7.5.3/bin/magicc.exe + run: | + # TODO: loosen coverage requirements if CI fails, otherwise delete this comment + poetry run pytest -r a -v src tests --doctest-modules --cov=src --cov-report=term-missing --cov-report=xml + - name: Upload coverage reports to Codecov (Linux only) + if: runner.os == 'Linux' + uses: codecov/codecov-action@v3 + + imports-without-extras: + strategy: + fail-fast: false + matrix: + os: [ "ubuntu-latest" ] + python-version: [ "3.9", "3.10", "3.11" ] + runs-on: "${{ matrix.os }}" + steps: + - name: Check out repository + uses: actions/checkout@v3 + - uses: ./.github/actions/setup + with: + python-version: "${{ matrix.python-version }}" + venv-id: "imports-without-extras-${{ runner.os }}" + poetry-dependency-install-flags: "--only main" + - name: Check importable without extras + run: poetry run python scripts/test-install.py + + check-build: + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v3 + - uses: ./.github/actions/setup + with: + python-version: "3.9" + venv-id: "check-build-${{ runner.os }}" + run-poetry-install: false + poetry-dependency-install-flags: "not used" + - name: Build package + run: | + poetry build --no-interaction + - name: Check build + run: | + tar -tvf dist/openscm_runner-*.tar.gz --wildcards '*openscm_runner/py.typed' + + check-dependency-licences: + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v3 + - uses: ./.github/actions/setup + with: + python-version: "3.9" + venv-id: "licence-check" + poetry-dependency-install-flags: "--all-extras" + - name: Check licences of dependencies + shell: bash + run: | + TEMP_FILE=$(mktemp) + poetry export --without=tests --without=docs --without=dev > $TEMP_FILE + poetry run liccheck -r $TEMP_FILE -R licence-check.txt + cat licence-check.txt diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml new file mode 100644 index 00000000..2b8e1aae --- /dev/null +++ b/.github/workflows/deploy.yaml @@ -0,0 +1,33 @@ +name: Deploy + +on: + release: + types: [published] + +defaults: + run: + shell: bash + +jobs: + deploy-pypi: + name: Deploy to PyPI + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - uses: ./.github/actions/setup + with: + python-version: "3.9" + venv-id: "deploy" + poetry-dependency-install-flags: "--all-extras" + - name: Run tests + run: | + poetry run pytest -r a src tests --doctest-modules + - name: Publish to PyPI + env: + PYPI_TOKEN: "${{ secrets.PYPI_TOKEN }}" + run: | + poetry config pypi-token.pypi $PYPI_TOKEN + poetry publish --build --no-interaction diff --git a/.github/workflows/install.yaml b/.github/workflows/install.yaml new file mode 100644 index 00000000..0e873927 --- /dev/null +++ b/.github/workflows/install.yaml @@ -0,0 +1,30 @@ +name: Install + +on: + schedule: + # * is a special character in YAML so you have to quote this string + - cron: '0 0 * * 3' + +jobs: + test-pypi-install: + runs-on: "${{ matrix.os }}" + strategy: + fail-fast: false + matrix: + os: ["ubuntu-latest", "macos-latest", "windows-latest"] + python-version: [ "3.9", "3.10", "3.11" ] + steps: + - name: Set up Python "${{ matrix.python-version }}" + id: setup-python + uses: actions/setup-python@v4 + with: + python-version: "${{ matrix.python-version }}" + - name: Install + run: | + pip install --upgrade pip + pip install openscm-runner + - name: Checkout repository + uses: actions/checkout@v3 + - name: Test installation (${{ matrix.os }} Python ${{ matrix.python-version }}) + run: | + python scripts/test-install.py diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 00000000..d81afaac --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,47 @@ +name: Release + +on: + push: + tags: ['v*'] + +defaults: + run: + shell: bash + +jobs: + draft-release: + name: Create draft release + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - uses: ./.github/actions/setup + with: + python-version: "3.9" + venv-id: "release" + poetry-dependency-install-flags: "--all-extras" + - name: Add version to environment + run: | + PROJECT_VERSION=$(poetry version --short) + echo "PROJECT_VERSION=$PROJECT_VERSION" >> $GITHUB_ENV + - name: Run tests + run: | + poetry run pytest -r a -v src tests --doctest-modules + - name: Build package + run: | + poetry build --no-interaction + - name: Generate Release Notes + run: | + git log $(git describe --tags --abbrev=0 HEAD^)..HEAD --pretty='format:* %h %s' --no-merges >> ".github/release_template.md" + - name: Create Release Draft + uses: softprops/action-gh-release@v1 + with: + body_path: ".github/release_template.md" + draft: true + files: | + dist/openscm_runner-${{ env.PROJECT_VERSION }}-py3-none-any.whl + dist/openscm_runner-${{ env.PROJECT_VERSION }}.tar.gz + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/test-conda-install.yml b/.github/workflows/test-conda-install.yml deleted file mode 100644 index 9e2d79d0..00000000 --- a/.github/workflows/test-conda-install.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: Test conda install -on: - schedule: - # * is a special character in YAML so you have to quote this string - - cron: '0 0 * * 3' - -jobs: - test-installation: - name: Test conda install (${{ matrix.python-version }}, ${{ matrix.os }}) - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: ["ubuntu-latest", "macos-latest", "windows-latest"] - python-version: [3.7, 3.8, 3.9, "3.10", 3.11] - - steps: - - name: Setup conda - uses: conda-incubator/setup-miniconda@v2.0.1 - with: - auto-update-conda: true - python-version: ${{ matrix.python-version }} - activate-environment: test - - name: Conda info - shell: bash -l {0} - run: conda info - - name: Install package - shell: bash -l {0} - run: conda install -c conda-forge openscm-runner - - name: Checkout repository - uses: actions/checkout@v2 - - name: Test installation - shell: bash -l {0} - run: | - which python - python scripts/test_install.py diff --git a/.github/workflows/test-pypi-install.yml b/.github/workflows/test-pypi-install.yml deleted file mode 100644 index b0fcb6d6..00000000 --- a/.github/workflows/test-pypi-install.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Test PyPI install -on: - schedule: - # * is a special character in YAML so you have to quote this string - - cron: '0 0 * * 3' - -jobs: - test-installation: - - runs-on: ubuntu-latest - strategy: - matrix: - python-version: [3.7, 3.8, 3.9, "3.10", 3.11] - - steps: - - name: Setup python - uses: actions/setup-python@v1 - with: - python-version: ${{ matrix.python-version }} - - name: Install package - # install basic first, then install pre-releases afterwards so we don't - # pick up pre-releases of dependencies (e.g. pandas) - run: | - pip install --upgrade pip - pip install openscm-runner - pip install openscm-runner --pre - - name: Checkout repository - uses: actions/checkout@v2 - - name: Test installation - run: | - python scripts/test_install.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..2e3e88b8 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,42 @@ +# See https://pre-commit.com for more information +ci: + autofix_prs: false + autoupdate_schedule: quarterly + autoupdate_branch: pre-commit-autoupdate + +# See https://pre-commit.com/hooks.html for more hooks +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: 'v4.5.0' + hooks: + - id: check-added-large-files + - id: check-ast + - id: check-case-conflict + - id: check-json + - id: check-merge-conflict + - id: check-symlinks + - id: check-yaml + - id: debug-statements + - id: detect-private-key + - id: end-of-file-fixer + - id: fix-byte-order-marker + - id: mixed-line-ending + - id: trailing-whitespace + - repo: local + hooks: + # Prevent committing .rej files + - id: forbidden-files + name: forbidden files + entry: found Copier update rejection files; review them and remove them + language: fail + files: "\\.rej$" + - repo: https://github.com/charliermarsh/ruff-pre-commit + rev: 'v0.1.8' + hooks: + - id: ruff + args: [ --fix, --exit-non-zero-on-fix ] + - id: ruff-format + - repo: https://github.com/python-poetry/poetry + rev: '1.7.0' + hooks: + - id: poetry-check diff --git a/README.md b/README.md index b5ed198b..7e799fc8 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ TODO: - Change notebooks into papermill style - Update notebook tests - add PHONY to help in copier -- add test pypi and test conda install in copier +- add conda support via copier somewhere (might not need to be too complicated though as the only thing you really need to test is installation, the rest is just handled by conda-forge) - add AUTHORS in copier - check if version and release in docs/source/conf.py do anything - convert docs from rst to md @@ -16,6 +16,9 @@ TODO: - note that this removes support for Python \< 3.9 - Remove README.rst - Change to using pytest-regressions for handling expected values +- add feature request issue template to copier +- add feature-request label to both GitHub and GitLab orgs (if they don't exist, otherwise update feature request template to match existing name) +- convert CHANGELOG to directory style + + diff --git a/docs/source/development.md b/docs/source/development.md new file mode 100644 index 00000000..8667d82d --- /dev/null +++ b/docs/source/development.md @@ -0,0 +1,55 @@ +(development-reference)= +# Development + +Notes for developers. If you want to get involved, please do! + +## Language + +We use British English for our development. +We do this for consistency with the broader work context of our lead developers. + +## Versioning + +This package follows the version format described in [PEP440](https://peps.python.org/pep-0440/) and +[Semantic Versioning](https://semver.org/) to describe how the version should change depending on the updates to the +code base. Our commit messages are written using written to follow the +[conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) standard which makes it easy to find the +commits that matter when traversing through the commit history. + +(releasing-reference)= +## Releasing + +Releasing is semi-automated via a CI job. The CI job requires the type of version bump that will be performed to be +manually specified. See the poetry docs for the [list of available bump rules](https://python-poetry.org/docs/cli/#version). + +### Standard process + +The steps required are the following: + + +1. Bump the version: manually trigger the "bump" workflow from the main branch + (see here: https://github.com/openscm/openscm-runner/actions/workflows/bump.yaml). + A valid "bump_rule" (see https://python-poetry.org/docs/cli/#version) will need to be specified. + This will then trigger a draft release. + +1. Edit the draft release which has been created + (see here: + https://github.com/openscm/openscm-runner/releases). + Once you are happy with the release (removed placeholders, added key + announcements etc.) then hit 'Publish release'. This triggers a release to + PyPI (which you can then add to the release if you want). + + +1. That's it, release done, make noise on social media of choice, do whatever + else + +1. Enjoy the newly available version + +## Read the Docs + +Our documentation is hosted by +[Read the Docs (RtD)](https://www.readthedocs.org/), a service for which we are +very grateful. The RtD configuration can be found in the `.readthedocs.yaml` +file in the root of this repository. The docs are automatically +deployed at +[openscm-runner.readthedocs.io](https://openscm-runner.readthedocs.io/en/latest/). diff --git a/docs/source/index.md b/docs/source/index.md new file mode 100644 index 00000000..945e7fa4 --- /dev/null +++ b/docs/source/index.md @@ -0,0 +1,42 @@ +% OpenSCM-Runner documentation master file +% This was based on a sphinx-quickstart from Mon May 1 20:20:44 2023. +% If you're having issues with sphinx, you may need to regenerate this doc. +% You can adapt this file completely to your liking, but it should at least +% contain the root `toctree` directive. + +# OpenSCM-Runner + +```{include} ../../README.md +:start-after: +:end-before: +``` + +## Installation + +```{include} ../../README.md +:start-after: +:end-before: +``` + +### For developers + +```{include} ../../README.md +:start-after: +:end-before: +``` + +```{toctree} +:caption: Contents +:maxdepth: 2 +notebooks +development +api/openscm_runner +changelog +``` + +Index +----- + +- :ref:`genindex` +- :ref:`modindex` +- :ref:`search` diff --git a/docs/source/notebooks.md b/docs/source/notebooks.md new file mode 100644 index 00000000..54b20bc1 --- /dev/null +++ b/docs/source/notebooks.md @@ -0,0 +1,21 @@ +(notebooks-reference)= +# Notebooks + +Here we provide various examples of how to use OpenSCM-Runner. +They are derived from +[jupyter notebooks](https://docs.jupyter.org/en/latest/start/index.html), +but are saved using [jupytext](https://jupytext.readthedocs.io/en/latest/) +to keep our repository slim and make it easier to track changes. + +## Basic demos + +```{toctree} +:caption: Contents +:maxdepth: 1 +notebooks/basic-demo.py +``` + +## Notebook execution info + +```{nb-exec-table} +``` diff --git a/docs/source/notebooks/basic-demo.py b/docs/source/notebooks/basic-demo.py new file mode 100644 index 00000000..5f52dcba --- /dev/null +++ b/docs/source/notebooks/basic-demo.py @@ -0,0 +1,24 @@ +# --- +# jupyter: +# jupytext: +# text_representation: +# extension: .py +# format_name: percent +# format_version: '1.3' +# jupytext_version: 1.14.5 +# kernelspec: +# display_name: Python 3 (ipykernel) +# language: python +# name: python3 +# --- + +# %% [markdown] +# # Basic demo +# +# This notebook gives a basic demonstration of how to use OpenSCM-Runner. + +# %% +import openscm_runner + +# %% +print(f"You are using openscm_runner version {openscm_runner.__version__}") diff --git a/scripts/test-install.py b/scripts/test-install.py new file mode 100644 index 00000000..e090b550 --- /dev/null +++ b/scripts/test-install.py @@ -0,0 +1,52 @@ +""" +Test that all of our modules can be imported + +Also test that associated constants are set correctly + +Thanks https://stackoverflow.com/a/25562415/10473080 +""" +import importlib +import pkgutil +from pathlib import Path + +import openscm_runner + + +def import_submodules(package_name: str) -> None: + """ + Test import of submodules + """ + package = importlib.import_module(package_name) + + for _, name, is_pkg in pkgutil.walk_packages(package.__path__): + full_name = package.__name__ + "." + name + importlib.import_module(full_name) + if is_pkg: + import_submodules(full_name) + + +import_submodules("openscm_runner") + +# make sure csvs etc. are included +openscm_runner_root = Path(openscm_runner.__file__) + +assert ( + openscm_runner_root / "adapters/fair_adapter/natural-emissions-and-forcing.csv" +).exists() + +assert ( + openscm_runner_root / "adapters/ciceroscm_adapter/utils_templates/gases_v1RCMIP.txt" +).exists() + + +assert ( + openscm_runner_root + / "adapters/ciceroscm_adapter/utils_templates/run_dir/scm_vCH4fb_bfx" +).exists() + +assert ( + openscm_runner_root + / "adapters/ciceroscm_adapter/utils_templates/run_dir/input_RF/RFSUN/solar_IPCC.txt" +).exists() + +print(openscm_runner.__version__) diff --git a/scripts/test_install.py b/scripts/test_install.py deleted file mode 100644 index a0cdd1d7..00000000 --- a/scripts/test_install.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -Test that all of our modules can be imported - -Thanks https://stackoverflow.com/a/25562415/10473080 -""" -import importlib -import os.path -import pkgutil - -import openscm_runner -import openscm_runner.adapters.fair_adapter.fair_adapter - - -def import_submodules(package_name): - package = importlib.import_module(package_name) - - for _, name, is_pkg in pkgutil.walk_packages(package.__path__): - full_name = package.__name__ + "." + name - print(full_name) - importlib.import_module(full_name) - if is_pkg: - import_submodules(full_name) - - -import_submodules("openscm_runner") - -# make sure csvs etc. are included -openscm_runner_root = os.path.dirname(openscm_runner.__file__) -assert os.path.isfile( - os.path.join( - openscm_runner_root, "adapters/fair_adapter/natural-emissions-and-forcing.csv" - ) -) -assert os.path.isfile( - os.path.join( - openscm_runner_root, - "adapters/ciceroscm_adapter/utils_templates/gases_v1RCMIP.txt", - ) -) -assert os.path.isfile( - os.path.join( - openscm_runner_root, - "adapters/ciceroscm_adapter/utils_templates/run_dir/scm_vCH4fb_bfx", - ) -) -assert os.path.isfile( - os.path.join( - openscm_runner_root, - "adapters/ciceroscm_adapter/utils_templates/run_dir/input_RF/RFSUN/solar_IPCC.txt", - ) -) - -print(openscm_runner.__version__) From dcfe6fad0ac48eede8f1172bd14da12a6f5e19c9 Mon Sep 17 00:00:00 2001 From: Zebedee Nicholls Date: Tue, 9 Jan 2024 17:23:40 +0100 Subject: [PATCH 03/61] Add gitkeep etc --- src/openscm_runner/py.typed | 0 stubs/.gitkeep | 0 tests/integration/.gitkeep | 0 tests/regression/.gitkeep | 0 tests/test-data/.gitkeep | 0 tests/unit/.gitkeep | 0 6 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/openscm_runner/py.typed create mode 100644 stubs/.gitkeep create mode 100644 tests/integration/.gitkeep create mode 100644 tests/regression/.gitkeep create mode 100644 tests/test-data/.gitkeep create mode 100644 tests/unit/.gitkeep diff --git a/src/openscm_runner/py.typed b/src/openscm_runner/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/stubs/.gitkeep b/stubs/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/tests/integration/.gitkeep b/tests/integration/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/tests/regression/.gitkeep b/tests/regression/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/tests/test-data/.gitkeep b/tests/test-data/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/tests/unit/.gitkeep b/tests/unit/.gitkeep new file mode 100644 index 00000000..e69de29b From f9a7931938028d637fb7fa20aba8bb550ca1b4ea Mon Sep 17 00:00:00 2001 From: Zebedee Nicholls Date: Tue, 9 Jan 2024 16:42:24 +0000 Subject: [PATCH 04/61] Start fixing test errors --- pyproject.toml | 4 +-- src/openscm_runner/settings.py | 10 +++++-- tests/integration/test_fair1X.py | 51 +++++++++++++++++--------------- tests/unit/test_installation.py | 11 ++++--- tests/unit/test_run.py | 6 ++-- 5 files changed, 46 insertions(+), 36 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 789023b0..ed98a6dd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -95,9 +95,6 @@ select = [ "RUF", # ruff specifics "UP", # pyupgrade "S", # flake8-bandit - # pandas support via pandas-vet. In some cases we will want to disable - # this because it can lead to too many false positives. - "PD", ] unfixable = [ "PD002", # Disable autofix for inplace as this often introduces bugs @@ -105,6 +102,7 @@ unfixable = [ ignore = [ "D200", # One-line docstring should fit on one line with quotes "D400", # First line should end with a period + "PD", # Pandas' suggestions: ruff gets confused with scmdata's API ] line-length = 88 diff --git a/src/openscm_runner/settings.py b/src/openscm_runner/settings.py index 2ada7bd1..87bad078 100644 --- a/src/openscm_runner/settings.py +++ b/src/openscm_runner/settings.py @@ -1,4 +1,6 @@ """ +Settings handling + Rather than hard-coding constants, configuration can be source from 2 different sources: @@ -31,8 +33,12 @@ class ConfigLoader: .. code:: python >>> config = ConfigLoader() - >>> config['VALUE'] - >>> config.get("VALUE", None) + >>> config["VALUE"] + Traceback (most recent call last): + ... + KeyError: 'VALUE' + >>> config.get("VALUE", "some_default") + 'some_default' """ def __init__(self): diff --git a/tests/integration/test_fair1X.py b/tests/integration/test_fair1X.py index 31bc9d83..a482e92a 100644 --- a/tests/integration/test_fair1X.py +++ b/tests/integration/test_fair1X.py @@ -5,7 +5,7 @@ import pytest from scmdata import ScmRun -from openscm_runner import run +import openscm_runner.run from openscm_runner.adapters import FAIR from openscm_runner.testing import _AdapterTester from openscm_runner.utils import calculate_quantiles @@ -13,7 +13,7 @@ class TestFairAdapter(_AdapterTester): @pytest.mark.parametrize("nworkers", (1, 4)) - def test_run( + def test_run( # noqa: PLR0913 self, test_scenarios, monkeypatch, @@ -27,8 +27,8 @@ def test_run( "expected_fair1X_test_run_output.json", ) - monkeypatch.setenv("FAIR_WORKER_NUMBER", "{}".format(nworkers)) - res = run( + monkeypatch.setenv("FAIR_WORKER_NUMBER", f"{nworkers}") + res = openscm_runner.run.run( climate_models_cfgs={ "FaIR": [ {}, @@ -53,9 +53,10 @@ def test_run( assert isinstance(res, ScmRun) assert res["run_id"].min() == 0 assert res["run_id"].max() == 8 - assert res.get_unique_meta( - "climate_model", no_duplicates=True - ) == "FaIRv{}".format(FAIR.get_version()) + assert ( + res.get_unique_meta("climate_model", no_duplicates=True) + == f"FaIRv{FAIR.get_version()}" + ) assert set(res.get_unique_meta("variable")) == set( [ @@ -82,18 +83,18 @@ def test_run( def test_variable_naming(self, test_scenarios): missing_from_fair = ( "Effective Radiative Forcing|Aerosols|Direct Effect|BC|MAGICC AFOLU", - "Effective Radiative Forcing|Aerosols|Direct Effect|BC|MAGICC Fossil and Industrial", + "Effective Radiative Forcing|Aerosols|Direct Effect|BC|MAGICC Fossil and Industrial", # noqa: E501 "Effective Radiative Forcing|Aerosols|Direct Effect|OC|MAGICC AFOLU", - "Effective Radiative Forcing|Aerosols|Direct Effect|OC|MAGICC Fossil and Industrial", + "Effective Radiative Forcing|Aerosols|Direct Effect|OC|MAGICC Fossil and Industrial", # noqa: E501 "Effective Radiative Forcing|Aerosols|Direct Effect|SOx|MAGICC AFOLU", - "Effective Radiative Forcing|Aerosols|Direct Effect|SOx|MAGICC Fossil and Industrial", + "Effective Radiative Forcing|Aerosols|Direct Effect|SOx|MAGICC Fossil and Industrial", # noqa: E501 "Net Atmosphere to Ocean Flux|CO2", "Net Atmosphere to Land Flux|CO2", ) common_variables = [ c for c in self._common_variables if c not in missing_from_fair ] - res = run( + res = openscm_runner.run.run( climate_models_cfgs={"FaIR": ({"startyear": 1750},)}, scenarios=test_scenarios.filter(scenario="ssp126"), output_variables=common_variables, @@ -105,7 +106,7 @@ def test_variable_naming(self, test_scenarios): def test_fair_ocean_factors(test_scenarios): - res_default_factors = run( + res_default_factors = openscm_runner.run.run( climate_models_cfgs={"FaIR": [{}]}, scenarios=test_scenarios.filter(scenario=["ssp585"]), output_variables=( @@ -115,7 +116,7 @@ def test_fair_ocean_factors(test_scenarios): ), ) - res_custom_factors = run( + res_custom_factors = openscm_runner.run.run( climate_models_cfgs={ "FaIR": [ { @@ -149,23 +150,24 @@ def test_fair_ocean_factors(test_scenarios): def test_startyear(test_scenarios, test_scenarios_2600): - # we can't run different start years in the same ensemble as output files will differ in shape. - # There is a separate test to ensure this does raise an error. - res_1850 = run( + # we can't run different start years in the same ensemble as output files + # will differ in shape. There is a separate test to ensure this does raise + # an error. + res_1850 = openscm_runner.run.run( climate_models_cfgs={"FaIR": [{"startyear": 1850}]}, scenarios=test_scenarios.filter(scenario=["ssp245"]), output_variables=("Surface Air Temperature Change",), out_config=None, ) - res_1750 = run( + res_1750 = openscm_runner.run.run( climate_models_cfgs={"FaIR": [{"startyear": 1750}]}, scenarios=test_scenarios.filter(scenario=["ssp245"]), output_variables=("Surface Air Temperature Change",), out_config=None, ) - res_default = run( + res_default = openscm_runner.run.run( climate_models_cfgs={"FaIR": [{}]}, scenarios=test_scenarios.filter(scenario=["ssp245"]), output_variables=("Surface Air Temperature Change",), @@ -194,7 +196,7 @@ def test_startyear(test_scenarios, test_scenarios_2600): assert gsat2100_start1750 == gsat2100_startdefault with pytest.raises(ValueError): - run( + openscm_runner.run.run( climate_models_cfgs={"FaIR": [{"startyear": 1650}]}, scenarios=test_scenarios.filter(scenario=["ssp245"]), output_variables=("Surface Air Temperature Change",), @@ -202,7 +204,7 @@ def test_startyear(test_scenarios, test_scenarios_2600): ) with pytest.raises(ValueError): - run( + openscm_runner.run.run( climate_models_cfgs={"FaIR": [{}]}, scenarios=test_scenarios_2600.filter(scenario=["ssp245"]), output_variables=("Surface Air Temperature Change",), @@ -210,7 +212,7 @@ def test_startyear(test_scenarios, test_scenarios_2600): ) with pytest.raises(ValueError): - run( + openscm_runner.run.run( climate_models_cfgs={"FaIR": [{"startyear": 1750}, {"startyear": 1850}]}, scenarios=test_scenarios.filter(scenario=["ssp245"]), output_variables=("Surface Air Temperature Change",), @@ -278,7 +280,7 @@ def test_forcing_categories(test_scenarios): "Effective Radiative Forcing", ] - res = run( + res = openscm_runner.run.run( climate_models_cfgs={"FaIR": [{}]}, scenarios=test_scenarios.filter(scenario=["ssp245"]), output_variables=tuple(forcing_categories), @@ -398,7 +400,7 @@ def test_forcing_categories(test_scenarios): npt.assert_allclose( forcing["Effective Radiative Forcing|Aerosols|Direct Effect|SOx"] + forcing[ - "Effective Radiative Forcing|Aerosols|Direct Effect|Secondary Organic Aerosol" + "Effective Radiative Forcing|Aerosols|Direct Effect|Secondary Organic Aerosol" # noqa: E501 ] + forcing["Effective Radiative Forcing|Aerosols|Direct Effect|Nitrate"] + forcing["Effective Radiative Forcing|Aerosols|Direct Effect|BC"] @@ -406,7 +408,8 @@ def test_forcing_categories(test_scenarios): forcing["Effective Radiative Forcing|Aerosols|Direct Effect"], ) - # If up to here is fine, then we only need to check previouly defined aggregates against "super-aggregates" + # If up to here is fine, then we only need to check previouly defined + # aggregates against "super-aggregates" npt.assert_allclose( forcing["Effective Radiative Forcing|Aerosols|Direct Effect"] + forcing["Effective Radiative Forcing|Aerosols|Indirect Effect"], diff --git a/tests/unit/test_installation.py b/tests/unit/test_installation.py index 7358b8ad..083e5413 100644 --- a/tests/unit/test_installation.py +++ b/tests/unit/test_installation.py @@ -2,7 +2,7 @@ import pytest -from openscm_runner import run +import openscm_runner.run @patch("openscm_runner.adapters.fair_adapter.fair_adapter.fair", None) @@ -10,7 +10,7 @@ def test_no_fair(): with pytest.raises( ImportError, match="fair is not installed. Run 'pip install fair'" ): - run( + openscm_runner.run.run( climate_models_cfgs={"fair": ["config list"]}, scenarios="not used", ) @@ -20,9 +20,12 @@ def test_no_fair(): def test_no_pymagicc(): with pytest.raises( ImportError, - match="pymagicc is not installed. Run 'conda install pymagicc' or 'pip install pymagicc'", + match=( + "pymagicc is not installed. " + "Run 'conda install pymagicc' or 'pip install pymagicc'" + ), ): - run( + openscm_runner.run.run( climate_models_cfgs={"MAGICC7": ["config list"]}, scenarios="not used", ) diff --git a/tests/unit/test_run.py b/tests/unit/test_run.py index e05982e9..02c8549d 100644 --- a/tests/unit/test_run.py +++ b/tests/unit/test_run.py @@ -2,7 +2,7 @@ import pytest -from openscm_runner import run +import openscm_runner.run def test_run_out_config_conflict_error(): @@ -12,7 +12,7 @@ def test_run_out_config_conflict_error(): ) with pytest.raises(NotImplementedError): with pytest.warns(UserWarning, match=error_msg): - run( + openscm_runner.run.run( climate_models_cfgs={"model_a": ["config list"]}, scenarios="not used", out_config={"another model": ("hi",)}, @@ -25,7 +25,7 @@ def test_run_out_config_type_error(): "climate_model: 'model_a'" ) with pytest.raises(TypeError, match=error_msg): - run( + openscm_runner.run.run( climate_models_cfgs={"model_a": ["config list"]}, scenarios="not used", out_config={"model_a": "hi"}, From baa8d68934653f94497d53193050369bb6c64322 Mon Sep 17 00:00:00 2001 From: Zebedee Nicholls Date: Tue, 9 Jan 2024 16:46:33 +0000 Subject: [PATCH 05/61] Clean up TODOs --- README.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 7e799fc8..8d8b9046 100644 --- a/README.md +++ b/README.md @@ -2,23 +2,21 @@ TODO: +- get rid of |CO2| throughout +- note that this removes support for Python \< 3.9 +- Remove README.rst +- convert CHANGELOG to directory style +- convert docs from rst to md - TODO: work out how to handle package data - Change notebooks into papermill style - Update notebook tests +- Change to using pytest-regressions for handling expected values - add PHONY to help in copier - add conda support via copier somewhere (might not need to be too complicated though as the only thing you really need to test is installation, the rest is just handled by conda-forge) - add AUTHORS in copier -- check if version and release in docs/source/conf.py do anything -- convert docs from rst to md -- work out what pygments_style in docs/source/conf.py does - add sidebar back into docs in copier -- get rid of |CO2| throughout -- note that this removes support for Python \< 3.9 -- Remove README.rst -- Change to using pytest-regressions for handling expected values - add feature request issue template to copier - add feature-request label to both GitHub and GitLab orgs (if they don't exist, otherwise update feature request template to match existing name) -- convert CHANGELOG to directory style -Thin wrapper to run emissions scenarios with simple climate models +OpenSCM-Runner provides a unified API for running emissions scenarios with different simple climate models. [![CI](https://github.com/openscm/openscm-runner/actions/workflows/ci.yaml/badge.svg?branch=main)](https://github.com/openscm/openscm-runner/actions/workflows/ci.yaml) [![Coverage](https://codecov.io/gh/openscm/openscm-runner/branch/main/graph/badge.svg)](https://codecov.io/gh/openscm/openscm-runner) @@ -63,6 +64,21 @@ Additional dependencies can be installed using # To add notebook dependencies pip install openscm-runner[notebooks] +# To add dependencies for all models +pip install openscm-runner[models] + +# To add dependencies for MAGICC +pip install openscm-runner[magicc] + +# To add dependencies for FaIR +pip install openscm-runner[fair] + +# CICERO-SCM's Fortran binary requires no additional dependencies to be +# installed + +# To add dependencies for CICERO-SCM's Python port +pip install openscm-runner[ciceroscmpy] + # If you are installing with conda, we recommend # installing the extras by hand because there is no stable # solution yet (issue here: https://github.com/conda/conda/issues/7502) diff --git a/README.rst b/README.rst deleted file mode 100644 index cbda6bef..00000000 --- a/README.rst +++ /dev/null @@ -1,136 +0,0 @@ -OpenSCM Runner -============== - -+-------------------+----------------+--------+ -| Repository health | |CI CD| | |Docs| | -+-------------------+----------------+--------+ - -+------+------------------+----------------+------------------+ -| Pypi | |PyPI Install| | |PyPI| | |PyPI Version| | -+------+------------------+----------------+------------------+ - -+-------+-----------------+-------------------+-----------------+ -| Conda | |conda install| | |conda platforms| | |conda version| | -+-------+-----------------+-------------------+-----------------+ - -+-----------------+----------------+---------------+-----------+ -| Other info | |Contributors| | |Last Commit| | |License| | -+-----------------+----------------+---------------+-----------+ - -.. sec-begin-links - -.. |CI CD| image:: https://github.com/openscm/openscm-runner/workflows/OpenSCM-Runner%20CI-CD/badge.svg - :target: https://github.com/openscm/openscm-runner/actions?query=workflow%3A%22OpenSCM-Runner+CI-CD%22 -.. |Docs| image:: https://readthedocs.org/projects/openscm-runner/badge/?version=latest - :target: https://openscm-runner.readthedocs.io/en/latest/?badge=latest -.. |PyPI Install| image:: https://github.com/openscm/openscm-runner/workflows/Test%20PyPI%20install/badge.svg - :target: https://github.com/openscm/openscm-runner/actions?query=workflow%3A%22Test+PyPI+install%22 -.. |PyPI| image:: https://img.shields.io/pypi/pyversions/openscm-runner.svg - :target: https://pypi.org/project/openscm-runner/ -.. |PyPI Version| image:: https://img.shields.io/pypi/v/openscm-runner.svg - :target: https://pypi.org/project/openscm-runner/ -.. |conda install| image:: https://github.com/openscm/openscm-runner/workflows/Test%20conda%20install/badge.svg - :target: https://github.com/openscm/openscm-runner/actions?query=workflow%3A%22Test+conda+install%22 -.. |conda platforms| image:: https://img.shields.io/conda/pn/conda-forge/openscm-runner.svg - :target: https://anaconda.org/conda-forge/openscm-runner -.. |conda version| image:: https://img.shields.io/conda/vn/conda-forge/openscm-runner.svg - :target: https://anaconda.org/conda-forge/openscm-runner -.. |Contributors| image:: https://img.shields.io/github/contributors/openscm/openscm-runner.svg - :target: https://github.com/openscm/openscm-runner/graphs/contributors -.. |Last Commit| image:: https://img.shields.io/github/last-commit/openscm/openscm-runner.svg - :target: https://github.com/openscm/openscm-runner/commits/master -.. |License| image:: https://img.shields.io/github/license/openscm/openscm-runner.svg - :target: https://github.com/openscm/openscm-runner/blob/master/LICENSE - -.. sec-end-links - - -Brief summary -+++++++++++++ - -.. sec-begin-long-description -.. sec-begin-index - -OpenSCM-Runner is a thin wrapper to run simple climate models with a unified interface. -At present, it supports emissions driven runs only. -This wrapper is implemented whilst `OpenSCM `_ is still a work in progress. - -.. sec-end-index - -License -------- - -.. sec-begin-license - -OpenSCM-Runner is free software under a BSD 3-Clause License, see -`LICENSE `_. - -.. sec-end-license -.. sec-end-long-description - -.. sec-begin-installation - -Installation ------------- - -OpenSCM-Runner can be installed with conda - -.. code:: bash - - conda install -c conda-forge openscm-runner - -Note that the above only installs base dependencies. To install all the requirements for MAGICC, use the below - -.. code:: bash - - # MAGICC - conda install -c conda-forge openscm-runner pymagicc - -To install all the requirements for FaIR, use the below - -.. code:: bash - - # FaIR - conda install -c conda-forge -c chrisroadmap openscm-runner fair - -OpenSCM-Runner can also be installed with pip - -.. code:: bash - - pip install openscm-runner - -To install the dependencies required by all models known to OpenSCM-Runner, add additional dependencies using - -.. code:: bash - - pip install openscm-runner[models] - - -To only install the dependencies required by a specific model, use one of the following instead - -.. code:: bash - - # MAGICC - pip install openscm-runner[magicc] - # FaIR - pip install openscm-runner[fair] - -If you also want to run the example notebooks install additional -dependencies using - -.. code:: bash - - pip install openscm-runner[notebooks] - -.. sec-end-installation - -Documentation -------------- - -Documentation can be found at our `documentation pages `_ -(we are thankful to `Read the Docs `_ for hosting us). - -Contributing ------------- - -Please see the `Development section of the docs `_. From ab3e5d17577c9a3524ea0978ecd9acc079c3c072 Mon Sep 17 00:00:00 2001 From: Zebedee Nicholls Date: Sun, 14 Jan 2024 15:41:58 +0000 Subject: [PATCH 08/61] Change CHANGELOG --- CHANGELOG.rst | 302 ------------------------------- README.md | 2 - docs/source/changelog.md | 217 +++++++++++++++++++++- docs/source/changelog.rst | 1 - scripts/rewrite-rst-changelog.py | 60 ++++++ 5 files changed, 276 insertions(+), 306 deletions(-) delete mode 100644 CHANGELOG.rst delete mode 100644 docs/source/changelog.rst create mode 100644 scripts/rewrite-rst-changelog.py diff --git a/CHANGELOG.rst b/CHANGELOG.rst deleted file mode 100644 index 9b839424..00000000 --- a/CHANGELOG.rst +++ /dev/null @@ -1,302 +0,0 @@ -Changelog -========= - -All notable changes to this project will be documented in this file. - -The format is based on `Keep a Changelog `_, and this project adheres to `Semantic Versioning `_. - -The changes listed in this file are categorised as follows: - - - Added: new features - - Changed: changes in existing functionality - - Deprecated: soon-to-be removed features - - Removed: now removed features - - Fixed: any bug fixes - - Security: in case of vulnerabilities. - -Master ------- - -v0.12.1 - 2023-05-15 --------------------- - -Added -~~~~~ - -- (`#83 `_) Added support for Python v3.10 and v3.11 - -Changed -~~~~~~~ - -- (`#83 `_) Fix failing CI. ``fair`` is now pinned to < 2 - -v0.12.0 - 2023-05-12 --------------------- - -Changed -~~~~~~~ - -- (`#81 `_) Replaced the deprecated ``np.float`` for the builtin ``float`` (Thanks @jkikstra) -- (`#80 `_) MAGICC adapter uses ``run/openscm-runner`` directory to store SCEN files instead of `run` - -v0.11.0 - 2022-08-18 --------------------- - -Added -~~~~~ - -- (`#78 `_) CICERO-SCM python implementation adapter -- (`#74 `_) Run tests on macOS as part of CI -- (`#72 `_) Add notebook showing how to run MAGICC - -Changed -~~~~~~~ - -- (`#79 `_) Move ``_AdapterTester`` to ``openscm_runner.testing`` -- (`#77 `_) Use environment for running CI so forks can access secrets too -- (`#71 `_) Run MAGICC as part of CI by using MAGICC binary downloaded from `magicc.org `_ -- (`#70 `_) Updated the integration tests to use MAGICC v7.5.3 which is publicly available. -- (`#66 `_) Log MAGICC7 errors more prominently. -- (`#68 `_) MAGICC7 adapter: automatically create a temporary directory when MAGICC_WORKER_ROOT_DIR is not specified. -- (`#69 `_) Updated dependency ``black`` to ``v22.3.0`` and pin ``isort`` and ``pylint`` for consistent pull requests - - -v0.10.0 - 2022-03-15 --------------------- - -Added -~~~~~ - -- (`#63 `_) Added a windows binary for cicero-scm so it can also be run on Windows -- (`#64 `_) Allow for the registration of adapters at runtime. Adapters now require a unique ``model_name`` - -v0.9.3 - 2022-01-19 -------------------- - -Fixed -~~~~~ - -- (`#57 `_) Updated CICERO-SCM fortran binary which confused OHC and OHC down to 700 meters in output and added missing components to radiative imbalance. - -v0.9.2 - 2021-12-23 -------------------- - -Added -~~~~~ - -- (`#59 `_) Conda install instructions - - -Changed -~~~~~~~ - -- (`#58 `_) Update README for FaIR conda install - -Fixed -~~~~~ - -- (`#61 `_) Packaging now uses setuptools-scm and hence includes all required files in source distributions (which should also fix the conda distribution) - -v0.9.1 - 2021-09-23 -------------------- - -Fixed -~~~~~ - -- (`#52 `_) Fixed CICERO-SCM bugs with converting halon units and handling of very long scenario names - -v0.9.0 - 2021-09-07 -------------------- - -Changed -~~~~~~~ - -- (`#55 `_) Require openscm-units >= 0.5.0 - -v0.8.1 - 2021-08-13 -------------------- - -Changed -~~~~~~~ - -- (`#54 `_) Made model dependencies optionally installable (allows conda package to be made) - -v0.7.2 - 2021-07-22 -------------------- - -Changed -~~~~~~~ - -- (`#53 `_) Loosened requirements and updated CI to run jobs in parallel - -v0.7.1 - 2021-07-09 -------------------- - -Added -~~~~~ - -- Include LICENSE, CHANGELOG and README in distribution - -v0.7.0 - 2021-07-09 -------------------- - -Added -~~~~~ - -- (`#24 `_) Adapter for the CICERO-SCM model (https://doi.org/10.1088/1748-9326/aa5b0a), see ``openscm_runner.adapters.CICEROSCM`` - -v0.6.0 - 2021-04-13 -------------------- - -Changed -~~~~~~~ - -- (`#50 `_) Changed FaIR heat uptake units to be "W/m^2" rather than "ZJ/yr" -- (`#47 `_) Moved ``openscm_runner.adapters.magicc7._parallel_process`` to ``openscm_runner.adapters.utils._parallel_process`` -- (`#47 `_) Added CI for Python3.9 and dropped required code coverage to 90%. -- (`#46 `_) Use `pytest markers `_ for marking tests which rely on MAGICC rather than hack fixture solution -- (`#45 `_) Update regression tests so they can be more easily updated -- (`#44 `_) Updated tests to using MAGICCv7.5.1 - -v0.5.1 - 2021-02-27 -------------------- - -Changed -~~~~~~~ - -- (`#43 `_) Add ability to run FaIR in parallel - -Fixed -~~~~~ - -- (`#40 `_) Report correct index from FaIR as the anthropogenic total ERF - -v0.5.0 - 2021-02-24 -------------------- - -Changed -~~~~~~~ - -- (`#41 `_) Use consistent setting across all progress bars -- (`#38 `_) Updated scmdata requirements to handle change to openscm-units -- (`#31 `_) Unified key variable naming across MAGICC and FaIR - -Fixed -~~~~~ - -- (`#39 `_) Include parameter name in the warning message emitted when MAGICC's output config doesn't match the input config specified via OpenSCM-Runner -- (`#36 `_) Hotfix CI after pandas 1.1.5 broke pylint -- (`#37 `_) Ensure FaIR ignores emissions input in scenarios not handled by FaIR, e.g. total CO2 - -v0.4.4 - 2020-11-12 -------------------- - -Added -~~~~~ - -- (`#27 `_) Test that installation includes required package data - -Fixed -~~~~~ - -- (`#28 `_) Minor smoothing for going from climate-assessment to openscm-runner to FaIR 1.6 - -v0.4.3 - 2020-10-14 -------------------- - -Fixed -~~~~~ - -- (`#26 `_) Include csv files needed for running FaIR 1.6 with CMIP6 setup - -v0.4.2 - 2020-10-13 -------------------- - -Changed -~~~~~~~ - -- (`#21 `_) Added flexible start date for FaIR and FaIR's scmdata to emissions converter - -v0.4.1 - 2020-10-06 -------------------- - -Added -~~~~~ - -- (`#23 `_) Test that MAGICC's carbon cycle output can be used with MAGICCv7.4.2. -- (`#22 `_) ``out_config`` argument to :func:`openscm_runner.run`, which allows the user to specify model configuration to include in the output's metadata. - -v0.4.0 - 2020-09-24 -------------------- - -Added -~~~~~ - -- (`#18 `_) Flexible end date for FaIR -- (`#17 `_) Support for scmdata >= 0.7.1 - -Changed -~~~~~~~ - -- (`#19 `_) Configuration is now handled using ``openscm_runner.settings`` providing support for environment variables and dotenv files - -Fixed -~~~~~ - -- (`#20 `_) Update bandit configuration - -v0.3.1 - 2020-09-03 -------------------- - -Changed -~~~~~~~ - -- (`#14 `_) Added in direct aerosol forcing by species in FaIR - -v0.3.0 - 2020-08-26 -------------------- - -Changed -~~~~~~~ - -- (`#13 `_) Renamed ``openscm_runner.adapters.fair`` to ``openscm_runner.adapters.fair_adapter`` and ``openscm_runner.adapters.fair.fair`` to ``openscm_runner.adapters.fair_adapter.fair_adapter`` to avoid a namespace collision with the source ``fair`` package - -v0.2.0 - 2020-08-25 -------------------- - -Added -~~~~~ - -- (`#12 `_) FaIR 1.6.0 adapter - -Fixed -~~~~~ - -- (`#11 `_) MAGICC adapter so passed in emissions are followed (previously non-CO2 always followed SSP245) - -v0.1.2 - 2020-07-31 -------------------- - -Changed -~~~~~~~ - -- (`#10 `_) Upgrade to ``scmdata>=0.6.2`` so that package can be installed - -v0.1.1 - 2020-07-22 -------------------- - -Changed -~~~~~~~ - -- (`#9 `_) Remove unnecessary conversion to IamDataFrame when running MAGICC7 and clarify :meth:`adapters.base._Adapter.run` interface - -v0.1.0 - 2020-07-07 -------------------- - -Added -~~~~~ - -- (`#7 `_) Hotfix requirements and tests -- (`#2 `_) Add MAGICC7 adapter (also provides basis for all other adapters) -- (`#4 `_) Hot fix initial setup -- (`#1 `_) Setup repository diff --git a/README.md b/README.md index 8a3b8493..7b3ca0a5 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,6 @@ TODO: -- Remove README.rst -- convert CHANGELOG to directory style - convert docs from rst to md - TODO: work out how to handle package data - Change notebooks into papermill style diff --git a/docs/source/changelog.md b/docs/source/changelog.md index ce40395e..5ee3f6d3 100644 --- a/docs/source/changelog.md +++ b/docs/source/changelog.md @@ -5,7 +5,6 @@ Versions follow [Semantic Versioning](https://semver.org/) (`.. + +## openscm-runner v0.12.1 (2023-05-15) + +### Features + +- Added support for Python v3.10 and v3.11 ([#83](https://github.com/openscm/openscm-runner/pulls/83)) + +### Improvements + +- Fix failing CI. `fair` is now pinned to \< 2 ([#83](https://github.com/openscm/openscm-runner/pulls/83)) + +## openscm-runner v0.12.0 (2023-05-12) + +### Improvements + +- Replaced the deprecated `np.float` for the builtin `float` (Thanks @jkikstra) ([#81](https://github.com/openscm/openscm-runner/pulls/81)) +- MAGICC adapter uses `run/openscm-runner` directory to store SCEN files instead of `run` ([#80](https://github.com/openscm/openscm-runner/pulls/80)) + +## openscm-runner v0.11.0 (2022-08-18) + +### Features + +- CICERO-SCM python implementation adapter ([#78](https://github.com/openscm/openscm-runner/pulls/78)) +- Run tests on macOS as part of CI ([#74](https://github.com/openscm/openscm-runner/pulls/74)) +- Add notebook showing how to run MAGICC ([#72](https://github.com/openscm/openscm-runner/pulls/72)) + +### Improvements + +- Move `_AdapterTester` to `openscm_runner.testing` ([#79](https://github.com/openscm/openscm-runner/pulls/79)) +- Use environment for running CI so forks can access secrets too ([#77](https://github.com/openscm/openscm-runner/pulls/77)) +- Run MAGICC as part of CI by using MAGICC binary downloaded from `magicc.org `\_ ([#71](https://github.com/openscm/openscm-runner/pulls/71)) +- Updated the integration tests to use MAGICC v7.5.3 which is publicly available. ([#70](https://github.com/openscm/openscm-runner/pulls/70)) +- Log MAGICC7 errors more prominently. ([#66](https://github.com/openscm/openscm-runner/pulls/66)) +- MAGICC7 adapter: automatically create a temporary directory when MAGICC_WORKER_ROOT_DIR is not specified. ([#68](https://github.com/openscm/openscm-runner/pulls/68)) +- Updated dependency `black` to `v22.3.0` and pin `isort` and `pylint` for consistent pull requests ([#69](https://github.com/openscm/openscm-runner/pulls/69)) + +## openscm-runner v0.10.0 (2022-03-15) + +### Features + +- Added a windows binary for cicero-scm so it can also be run on Windows ([#63](https://github.com/openscm/openscm-runner/pulls/63)) +- Allow for the registration of adapters at runtime. Adapters now require a unique `model_name` ([#64](https://github.com/openscm/openscm-runner/pulls/64)) + +## openscm-runner v0.9.3 (2022-01-19) + +### Bug Fixes + +- Updated CICERO-SCM fortran binary which confused OHC and OHC down to 700 meters in output and added missing components to radiative imbalance. ([#57](https://github.com/openscm/openscm-runner/pulls/57)) + +## openscm-runner v0.9.2 (2021-12-23) + +### Features + +- Conda install instructions ([#59](https://github.com/openscm/openscm-runner/pulls/59)) + +### Improvements + +- Update README for FaIR conda install ([#58](https://github.com/openscm/openscm-runner/pulls/58)) + +### Bug Fixes + +- Packaging now uses setuptools-scm and hence includes all required files in source distributions (which should also fix the conda distribution) ([#61](https://github.com/openscm/openscm-runner/pulls/61)) + +## openscm-runner v0.9.1 (2021-09-23) + +### Bug Fixes + +- Fixed CICERO-SCM bugs with converting halon units and handling of very long scenario names ([#52](https://github.com/openscm/openscm-runner/pulls/52)) + +## openscm-runner v0.9.0 (2021-09-07) + +### Improvements + +- Require openscm-units >= 0.5.0 ([#55](https://github.com/openscm/openscm-runner/pulls/55)) + +## openscm-runner v0.8.1 (2021-08-13) + +### Improvements + +- Made model dependencies optionally installable (allows conda package to be made) ([#54](https://github.com/openscm/openscm-runner/pulls/54)) + +## openscm-runner v0.7.2 (2021-07-22) + +### Improvements + +- Loosened requirements and updated CI to run jobs in parallel ([#53](https://github.com/openscm/openscm-runner/pulls/53)) + +## openscm-runner v0.7.1 (2021-07-09) + +## openscm-runner v0.7.0 (2021-07-09) + +### Features + +- Adapter for the CICERO-SCM model (https://doi.org/10.1088/1748-9326/aa5b0a), see `openscm_runner.adapters.CICEROSCM` ([#24](https://github.com/openscm/openscm-runner/pulls/24)) + +## openscm-runner v0.6.0 (2021-04-13) + +### Improvements + +- Changed FaIR heat uptake units to be "W/m^2" rather than "ZJ/yr" ([#50](https://github.com/openscm/openscm-runner/pulls/50)) +- Moved `openscm_runner.adapters.magicc7._parallel_process` to `openscm_runner.adapters.utils._parallel_process` ([#47](https://github.com/openscm/openscm-runner/pulls/47)) +- Added CI for Python3.9 and dropped required code coverage to 90%. ([#47](https://github.com/openscm/openscm-runner/pulls/47)) +- Use `pytest markers `\_ for marking tests which rely on MAGICC rather than hack fixture solution ([#46](https://github.com/openscm/openscm-runner/pulls/46)) +- Update regression tests so they can be more easily updated ([#45](https://github.com/openscm/openscm-runner/pulls/45)) +- Updated tests to using MAGICCv7.5.1 ([#44](https://github.com/openscm/openscm-runner/pulls/44)) + +## openscm-runner v0.5.1 (2021-02-27) + +### Improvements + +- Add ability to run FaIR in parallel ([#43](https://github.com/openscm/openscm-runner/pulls/43)) + +### Bug Fixes + +- Report correct index from FaIR as the anthropogenic total ERF ([#40](https://github.com/openscm/openscm-runner/pulls/40)) + +## openscm-runner v0.5.0 (2021-02-24) + +### Improvements + +- Use consistent setting across all progress bars ([#41](https://github.com/openscm/openscm-runner/pulls/41)) +- Updated scmdata requirements to handle change to openscm-units ([#38](https://github.com/openscm/openscm-runner/pulls/38)) +- Unified key variable naming across MAGICC and FaIR ([#31](https://github.com/openscm/openscm-runner/pulls/31)) + +### Bug Fixes + +- Include parameter name in the warning message emitted when MAGICC's output config doesn't match the input config specified via OpenSCM-Runner ([#39](https://github.com/openscm/openscm-runner/pulls/39)) +- Hotfix CI after pandas 1.1.5 broke pylint ([#36](https://github.com/openscm/openscm-runner/pulls/36)) +- Ensure FaIR ignores emissions input in scenarios not handled by FaIR, e.g. total CO2 ([#37](https://github.com/openscm/openscm-runner/pulls/37)) + +## openscm-runner v0.4.4 (2020-11-12) + +### Features + +- Test that installation includes required package data ([#27](https://github.com/openscm/openscm-runner/pulls/27)) + +### Bug Fixes + +- Minor smoothing for going from climate-assessment to openscm-runner to FaIR 1.6 ([#28](https://github.com/openscm/openscm-runner/pulls/28)) + +## openscm-runner v0.4.3 (2020-10-14) + +### Bug Fixes + +- Include csv files needed for running FaIR 1.6 with CMIP6 setup ([#26](https://github.com/openscm/openscm-runner/pulls/26)) + +## openscm-runner v0.4.2 (2020-10-13) + +### Improvements + +- Added flexible start date for FaIR and FaIR's scmdata to emissions converter ([#21](https://github.com/openscm/openscm-runner/pulls/21)) + +## openscm-runner v0.4.1 (2020-10-06) + +### Features + +- Test that MAGICC's carbon cycle output can be used with MAGICCv7.4.2. ([#23](https://github.com/openscm/openscm-runner/pulls/23)) +- `out_config` argument to :func:`openscm_runner.run`, which allows the user to specify model configuration to include in the output's metadata. ([#22](https://github.com/openscm/openscm-runner/pulls/22)) + +## openscm-runner v0.4.0 (2020-09-24) + +### Features + +- Flexible end date for FaIR ([#18](https://github.com/openscm/openscm-runner/pulls/18)) +- Support for scmdata >= 0.7.1 ([#17](https://github.com/openscm/openscm-runner/pulls/17)) + +### Improvements + +- Configuration is now handled using `openscm_runner.settings` providing support for environment variables and dotenv files ([#19](https://github.com/openscm/openscm-runner/pulls/19)) + +### Bug Fixes + +- Update bandit configuration ([#20](https://github.com/openscm/openscm-runner/pulls/20)) + +## openscm-runner v0.3.1 (2020-09-03) + +### Improvements + +- Added in direct aerosol forcing by species in FaIR ([#14](https://github.com/openscm/openscm-runner/pulls/14)) + +## openscm-runner v0.3.0 (2020-08-26) + +### Improvements + +- Renamed `openscm_runner.adapters.fair` to `openscm_runner.adapters.fair_adapter` and `openscm_runner.adapters.fair.fair` to `openscm_runner.adapters.fair_adapter.fair_adapter` to avoid a namespace collision with the source `fair` package ([#13](https://github.com/openscm/openscm-runner/pulls/13)) + +## openscm-runner v0.2.0 (2020-08-25) + +### Features + +- FaIR 1.6.0 adapter ([#12](https://github.com/openscm/openscm-runner/pulls/12)) + +### Bug Fixes + +- MAGICC adapter so passed in emissions are followed (previously non-CO2 always followed SSP245) ([#11](https://github.com/openscm/openscm-runner/pulls/11)) + +## openscm-runner v0.1.2 (2020-07-31) + +### Improvements + +- Upgrade to `scmdata>=0.6.2` so that package can be installed ([#10](https://github.com/openscm/openscm-runner/pulls/10)) + +## openscm-runner v0.1.1 (2020-07-22) + +### Improvements + +- Remove unnecessary conversion to IamDataFrame when running MAGICC7 and clarify :meth:`adapters.base._Adapter.run` interface ([#9](https://github.com/openscm/openscm-runner/pulls/9)) + +## openscm-runner v0.1.0 (2020-07-07) + +### Features + +- Hotfix requirements and tests ([#7](https://github.com/openscm/openscm-runner/pulls/7)) +- Add MAGICC7 adapter (also provides basis for all other adapters) ([#2](https://github.com/openscm/openscm-runner/pulls/2)) +- Hot fix initial setup ([#4](https://github.com/openscm/openscm-runner/pulls/4)) +- Setup repository ([#1](https://github.com/openscm/openscm-runner/pulls/1)) diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst deleted file mode 100644 index 09929fe4..00000000 --- a/docs/source/changelog.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../../CHANGELOG.rst diff --git a/scripts/rewrite-rst-changelog.py b/scripts/rewrite-rst-changelog.py new file mode 100644 index 00000000..83d69dfc --- /dev/null +++ b/scripts/rewrite-rst-changelog.py @@ -0,0 +1,60 @@ +""" +Re-write previous CHANGELOG.rst into lines required by docs/source/changelog.md +""" +from __future__ import annotations + +import re + +section_header_map = { + "Added": "Features", + "Changed": "Improvements", + "Fixed": "Bug Fixes", +} + + +def main() -> None: + """ + Re-write the CHANGELOG + """ + with open("CHANGELOG.rst") as fh: + contents = fh.read() + + lines = tuple(contents.splitlines()) + for i, line in enumerate(lines): + if not line: + continue + + if line.startswith("v0."): + version, date = line.split(" - ") + new_header = f"## openscm-runner {version} ({date})" + print() + print(new_header) + print() + continue + + if all(c == "~" for c in line): + section_header_original = lines[i - 1] + section_name = section_header_map[section_header_original] + section_header = f"### {section_name}" + print() + print(section_header) + print() + continue + + if line.startswith("- "): + match = re.match( + r"- \(`#(?P\d+)\s.*\) (?P.*)", + line, + ) + try: + pr_number = match.group("pr_number") + except AttributeError: + continue + + desc = match.group("desc") + new_line = f"- {desc} ([#{pr_number}](https://github.com/openscm/openscm-runner/pulls/{pr_number}))" + print(new_line) + + +if __name__ == "__main__": + main() From c8f64b69c518b187a39f7546131086332fc71423 Mon Sep 17 00:00:00 2001 From: Zebedee Nicholls Date: Sun, 14 Jan 2024 15:50:39 +0000 Subject: [PATCH 09/61] Convert docs from rst to md --- README.md | 13 +- docs/source/api/openscm_runner.operations.rst | 13 -- docs/source/api/openscm_runner.rst | 1 - docs/source/development.rst | 177 ------------------ docs/source/index.rst | 44 ----- docs/source/installation.rst | 3 - docs/source/run.rst | 6 - docs/source/settings.rst | 46 ----- docs/source/usage.rst | 7 - docs/source/utils.rst | 6 - 10 files changed, 12 insertions(+), 304 deletions(-) delete mode 100644 docs/source/api/openscm_runner.operations.rst delete mode 100644 docs/source/development.rst delete mode 100644 docs/source/index.rst delete mode 100644 docs/source/installation.rst delete mode 100644 docs/source/run.rst delete mode 100644 docs/source/settings.rst delete mode 100644 docs/source/usage.rst delete mode 100644 docs/source/utils.rst diff --git a/README.md b/README.md index 7b3ca0a5..2c4520e1 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ TODO: -- convert docs from rst to md - TODO: work out how to handle package data - Change notebooks into papermill style - Update notebook tests @@ -14,6 +13,18 @@ TODO: - add sidebar back into docs in copier - add feature request issue template to copier - add feature-request label to both GitHub and GitLab orgs (if they don't exist, otherwise update feature request template to match existing name) +- add contributor docs about how to contribute in different ways to copier, e.g. + - tutorials + - docs + - bug reports + - bug fixes + - feature requests + - pull requests +- add contributor info re workflows + - only push to your own branches (semi-enforced by GitHub's forking workflow but a good reminder) + - tools we use + - small MRs +- other learnings from the basic copier setup into copier