Skip to content

Commit

Permalink
Merge pull request #79 from openpathsampling/release-0.3
Browse files Browse the repository at this point in the history
Release 0.3
  • Loading branch information
dwhswenson authored Jun 12, 2024
2 parents f2d68e2 + 5b341e5 commit ff1e719
Show file tree
Hide file tree
Showing 127 changed files with 8,764 additions and 259 deletions.
2 changes: 1 addition & 1 deletion .coveragerc
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
[report]
omit =
*/paths_cli/tests/*
*/paths_cli/_installed_version.py
*/paths_cli/version.py
exclude_lines =
no-cov
def __repr__
raise NotImplementedError
__name__ == "__main__":
4 changes: 3 additions & 1 deletion .github/workflows/autorelease-default-env.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
INSTALL_AUTORELEASE="python -m pip install autorelease==0.2.6"
# Vendored from Autorelease 0.5.1
# Update by updating Autorelease and running `autorelease vendor actions`
INSTALL_AUTORELEASE="python -m pip install autorelease==0.5.1"
if [ -f autorelease-env.sh ]; then
source autorelease-env.sh
fi
Expand Down
11 changes: 9 additions & 2 deletions .github/workflows/autorelease-deploy.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
name: Autorelease
# Vendored from Autorelease 0.5.1
# Update by updating Autorelease and running `autorelease vendor actions`
name: "Autorelease Deploy"
on:
release:
types: [published]

jobs:
deploy_pypi:
if: ${{ github.repository == 'openpathsampling/openpathsampling-cli' }}
runs-on: ubuntu-latest
name: "Deploy to PyPI"
steps:
Expand All @@ -17,7 +20,11 @@ jobs:
if [ -f "autorelease-env.sh" ]; then
cat autorelease-env.sh >> $GITHUB_ENV
fi
eval $INSTALL_AUTORELEASE
if [ -f "./.autorelease/install-autorelease" ]; then
source ./.autorelease/install-autorelease
else
eval $INSTALL_AUTORELEASE
fi
name: "Install autorelease"
- run: |
python -m pip install twine wheel
Expand Down
13 changes: 11 additions & 2 deletions .github/workflows/autorelease-gh-rel.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
name: Autorelease
# Vendored from Autorelease 0.5.1
# Update by updating Autorelease and running `autorelease vendor actions`
name: "Autorelease Release"
on:
push:
branches:
# TODO: this should come from yaml conf
- stable

jobs:
release-gh:
if: ${{ github.repository == 'openpathsampling/openpathsampling-cli' }}
runs-on: ubuntu-latest
name: "Cut release"
steps:
Expand All @@ -18,7 +22,11 @@ jobs:
if [ -f "autorelease-env.sh" ]; then
cat autorelease-env.sh >> $GITHUB_ENV
fi
eval $INSTALL_AUTORELEASE
if [ -f "./.autorelease/install-autorelease" ]; then
source ./.autorelease/install-autorelease
else
eval $INSTALL_AUTORELEASE
fi
name: "Install autorelease"
- run: |
VERSION=`python setup.py --version`
Expand All @@ -27,3 +35,4 @@ jobs:
autorelease-release --project $PROJECT --version $VERSION --token $AUTORELEASE_TOKEN
env:
AUTORELEASE_TOKEN: ${{ secrets.AUTORELEASE_TOKEN }}
name: "Cut release"
31 changes: 25 additions & 6 deletions .github/workflows/autorelease-prep.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
name: "Autorelease"
# Vendored from Autorelease 0.5.1
# Update by updating Autorelease and running `autorelease vendor actions`
name: "Autorelease testpypi"
on:
pull_request:
branches:
# TODO: this should come from yaml conf
- stable

defaults:
Expand All @@ -10,6 +13,7 @@ defaults:

jobs:
deploy_testpypi:
if: ${{ github.repository == 'openpathsampling/openpathsampling-cli' }}
runs-on: ubuntu-latest
name: "Deployment test"
steps:
Expand All @@ -22,10 +26,14 @@ jobs:
if [ -f "autorelease-env.sh" ]; then
cat autorelease-env.sh >> $GITHUB_ENV
fi
eval $INSTALL_AUTORELEASE
if [ -f "./.autorelease/install-autorelease" ]; then
source ./.autorelease/install-autorelease
else
eval $INSTALL_AUTORELEASE
fi
name: "Install autorelease"
- run: |
python -m pip install twine wheel
python -m pip install twine wheel setuptools
name: "Install release tools"
- run: |
bump-dev-version
Expand All @@ -41,6 +49,7 @@ jobs:
repository_url: https://test.pypi.org/legacy/
name: "Deploy to testpypi"
test_testpypi:
if: ${{ github.repository == 'openpathsampling/openpathsampling-cli' }}
runs-on: ubuntu-latest
name: "Test deployed"
needs: deploy_testpypi
Expand All @@ -54,7 +63,17 @@ jobs:
if [ -f "autorelease-env.sh" ]; then
cat autorelease-env.sh >> $GITHUB_ENV
fi
eval $INSTALL_AUTORELEASE
if [ -f "./.autorelease/install-autorelease" ]; then
source ./.autorelease/install-autorelease
else
eval $INSTALL_AUTORELEASE
fi
name: "Install autorelease"
- run: test-testpypi

- name: "Install testpypi version"
run: install-testpypi
- name: "Test testpypi version"
run: |
if [ -f "autorelease-env.sh" ]; then
cat autorelease-env.sh >> $GITHUB_ENV
fi
test-testpypi
25 changes: 19 additions & 6 deletions .github/workflows/test-suite.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,28 @@ jobs:
strategy:
matrix:
CONDA_PY:
- 3.9
- 3.8
- 3.7
- 3.6
- "3.12"
- "3.11"
- "3.10"
INTEGRATIONS: [""]
include:
- CONDA_PY: "3.12"
INTEGRATIONS: 'all-optionals'

steps:
- uses: actions/checkout@v2
with:
fetch-depth: 2
- uses: actions/setup-python@v2
- uses: conda-incubator/setup-miniconda@v2
with:
auto-update-conda: true
python-version: ${{ matrix.CONDA_PY }}
- name: "Install testing tools"
run: python -m pip install -r ./devtools/tests_require.txt
- name: "Install integrations"
if: matrix.INTEGRATIONS == 'all-optionals'
run: conda install -c conda-forge -y openmm openmmtools mdtraj
- name: "Install"
run: |
conda install pip
Expand All @@ -57,8 +65,13 @@ jobs:
fi
python autorelease_check.py --branch $BRANCH --even ${EVENT}
- name: "Unit tests"
env:
PY_COLORS: "1"
run: |
python -c "import paths_cli"
py.test -vv --cov --cov-report xml:cov.xml
- name: "Report coverage"
run: bash <(curl -s https://codecov.io/bash)
- uses: codecov/codecov-action@v4
with:
files: ./cov.xml
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2019 David W.H. Swenson
Copyright (c) 2019-2024 David W.H. Swenson and contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[![Tests](https://github.com/openpathsampling/openpathsampling-cli/workflows/Tests/badge.svg)](https://github.com/openpathsampling/openpathsampling-cli/actions?query=workflow%3ATests)
[![Tests](https://github.com/openpathsampling/openpathsampling-cli/actions/workflows/test-suite.yml/badge.svg)](https://github.com/openpathsampling/openpathsampling-cli/actions/workflows/test-suite.yml)
[![Documentation Status](https://readthedocs.org/projects/openpathsampling-cli/badge/?version=latest)](https://openpathsampling-cli.readthedocs.io/en/latest/?badge=latest)
[![Coverage Status](https://codecov.io/gh/openpathsampling/openpathsampling-cli/branch/master/graph/badge.svg)](https://codecov.io/gh/openpathsampling/openpathsampling-cli)
[![Maintainability](https://api.codeclimate.com/v1/badges/0d1ee29e1a05cfcdc01a/maintainability)](https://codeclimate.com/github/openpathsampling/openpathsampling-cli/maintainability)
Expand Down
2 changes: 1 addition & 1 deletion autorelease-env.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
INSTALL_AUTORELEASE="python -m pip install autorelease==0.2.3 nose sqlalchemy dill"
INSTALL_AUTORELEASE="python -m pip install autorelease==0.5 nose sqlalchemy dill"
PACKAGE_IMPORT_NAME=paths_cli
43 changes: 43 additions & 0 deletions docs/compiling.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@

Compiling
=========

Let's start with an overview of terminology.:

* **Compiling**: The process of converting input in a text format,
such as YAML or JSON, into OPS objects. Here we're focused on non-Python
alternatives to using the standard Python interpreter to compile objects.
* **Category**: The base category of object to be created (engine, CV,
volume, etc.)
* **Builder**: We will refer to a builder function, which creates an
instance of a specific

Everything is created with plugins. There are two types of plugins used in
the ``compiling`` subpackage:

* ``InstanceCompilerPlugin``: This is what you'll normally work with. These
convert the input text to an instance of a specific OPS object (for
example, an ``OpenMMEngine`` or an ``MDTrajFunctionCV``. In general, you
do not create subclasses of ``InstanceCompilerPlugin`` -- there are
subclasses specialized to engines (``EngineCompilerPlugin``), to CVs
(``CVCompilerPlugin``), etc. You create *instances* of those subclasses.
You write your builder function, and wrap in with in an instance of an
``InstanceCompilerPlugin``.
* ``CategoryPlugin``: These manage the plugins associated with a given
features. Contributors will almost never need to create one of these.
The only case in which you would need to create one of these is if you're
creating a new *category* of object, i.e., something like an engine where
users will have multiple options at the command line.

Other useful classes defined in the ``compiling`` subpackage include:

* ``Builder``: The ``Builder`` class is a convenience for creating builder
functions. It takes either a callable or a string as input, where a string
is treated as a path to an object to import at runtime. It also allows
takes parameters ``remapper`` and ``after_build``, which are callables
that act on the input dictionary before object creation (``remapper``) and
on the created object after object creations (``after_build``).
* ``CategoryCompiler``: This class manages plugins for a given category, as
well as tracking named objects of that type. These are created
automatically when plugins are registered; users do not need to create
these.
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
import packaging.version

project = 'OpenPathSampling CLI'
copyright = '2019-2020, David W.H. Swenson'
copyright = '2019-2022, David W.H. Swenson and contributors'
author = 'David W.H. Swenson'

# The full version, including alpha/beta/rc tags
Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ wrappers around well-tested OPS code.
plugins
parameters
workflows
wizard
full_cli
api/index

52 changes: 30 additions & 22 deletions docs/plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,33 @@ There are two possible ways to distribute plugins (file plugins and
namespace plugins), but a given plugin script could be distributed either
way.

Writing a plugin script
-----------------------

An OPS plugin is simply a Python module that follows a few rules.

* It must define a variable ``CLI`` that is the main CLI function is
assigned to.
* It must define a variable ``SECTION`` to determine where to show it in
help (what kind of command it is). Valid values are ``"Simulation"``,
``"Analysis"``, ``"Miscellaneous"``, or ``"Workflow"``. If ``SECTION`` is
defined but doesn't have one of these values, it won't show in
``openpathsampling --help``, but might still be usable. If your command
doesn't show in the help, carefully check your spelling of the ``SECTION``
variable.
* The main CLI function must be decorated as a ``click.command``.
* (If distributed as a file plugin) It must be possible to ``exec`` it in an
empty namespace (mainly, this can mean no relative imports).
Writing a command plugin
------------------------

To write an OPS command plugin, you simply need to create an instance of
:class:`paths_cli.OPSCommandPlugin` and to install the module in a location
where the CLI knows to look for it. The input parameters to
``OPSCommandPlugin`` are:

* ``command``: This is the main CLI function for the subcommand. It must be
decorated as a ``click.command``.
* ``section``: This is a string to determine where to show it in help (what
kind of command it is). Valid values are ``"Simulation"``,
``"Analysis"``, ``"Miscellaneous"``, or ``"Workflow"``. If ``section``
doesn't have one of these values, it won't show in ``openpathsampling
--help``, but might still be usable. If your command doesn't show in the
help, carefully check your spelling of the ``section`` variable.
* ``requires_ops`` (optional, default ``(1, 0)``): Minimum allowed version
of OpenPathSampling. Note that this is currently informational only, and
has no effect on functionality.
* ``requires_cli`` (optional, default ``(0, 3)``): Minimum allowed version
of the OpenPathSampling CLI. Note that this is currently informational
only, and has no effect on functionality.


If you distribute your plugin as a file-based plugin, be aware that it must
be possible to ``exec`` it in an empty namespace (mainly, this can mean no
relative imports).

As a suggestion, I (DWHS) tend to structure my plugins as follows:

Expand All @@ -41,16 +51,15 @@ As a suggestion, I (DWHS) tend to structure my plugins as follows:
...
return final_status, simulation
CLI = plugin
SECTION = "MySection"
PLUGIN = OPSCommandPlugin(command=plugin, section="MySection")
The basic idea is that there's a ``plugin_main`` function that is based on
pure OPS, using only inputs that OPS can immediately understand (no need to
process the command line). This is easy to develop/test with OPS. Then
there's a wrapper function whose sole purpose is to convert the command line
parameters to something OPS can understand (using the ``get`` method). This
wrapper is the ``CLI`` variable. Give it an allowed ``SECTION``, and the
plugin is ready!
wrapper is the ``command`` in you ``OPSCommandPlugin``. Also provide an
allowed ``section``, and the plugin is ready!

The result is that plugins are astonishingly easy to develop, once you have
the scientific code implemented in a library. This structure also makes it
Expand Down Expand Up @@ -95,4 +104,3 @@ namespace.
.. _native namespace packages:
https://packaging.python.org/guides/packaging-namespace-packages/#native-namespace-packages


8 changes: 8 additions & 0 deletions docs/wizard.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.. _wizard:

Writing tools for the Wizard
============================

The Wizard API is still rapidly in flux, and we don't recommend developing
custom Wizard tools at this time. However, once its API is more stable, the
Wizard will be extendable by outside developers.
10 changes: 10 additions & 0 deletions example_plugins/one_pot_tps.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import click
from paths_cli import OPSCommandPlugin
from paths_cli.parameters import (INPUT_FILE, OUTPUT_FILE, ENGINE, STATES,
N_STEPS_MC, INIT_SNAP)
from paths_cli.commands.visit_all import visit_all_main
Expand Down Expand Up @@ -44,6 +45,15 @@ def one_pot_tps_main(output_storage, states, engine, engine_hot,
equil_multiplier, equil_extra)
return pathsampling_main(output_storage, scheme, equil_set, nsteps)

# these lines enable this plugin to support OPS CLI < 0.3
CLI = one_pot_tps
SECTION = "Workflow"
REQUIRES_OPS = (1, 2)

# these lines enable this plugin to support OPS CLI >= 0.3
PLUGIN = OPSCommandPlugin(
command=one_pot_tps,
section="Workflow",
requires_ops=(1, 2),
requires_cli=(0, 3)
)
Loading

0 comments on commit ff1e719

Please sign in to comment.