Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
1850972
Add core & engines for yaml compiling
dwhswenson Mar 21, 2021
4392e41
Remove named_obj param in engines, topologies
dwhswenson Mar 21, 2021
2a81273
CVs and tests (without named_objs)
dwhswenson Mar 21, 2021
3be9450
volumes and partial tests for volumes
dwhswenson Mar 21, 2021
dfbf36c
Moved tests over to testing dir
dwhswenson Mar 21, 2021
e1a778f
remove named objs; still seems to work
dwhswenson Mar 24, 2021
b3edf04
Seems to work up to networks now!
dwhswenson Mar 24, 2021
2ed6990
Seems to work through TPS schemes!
dwhswenson Mar 25, 2021
3c45b87
steps toward parsing simulations
dwhswenson Mar 26, 2021
248cef0
Add compile command
dwhswenson Apr 8, 2021
10ce9d2
Merge branch 'main' into sim-setup
dwhswenson Apr 10, 2021
0657882
Merge branch 'wizard' into sim-setup
dwhswenson Jun 18, 2021
45e77d6
long forgotten stash with lots of useful stuff
dwhswenson Jul 24, 2021
728083c
add tests/parsing/__init__.py
dwhswenson Jul 24, 2021
87029dd
tests for volumes combinations
dwhswenson Jul 24, 2021
ef1f086
fix for location of MDTrajTopology
dwhswenson Jul 24, 2021
55c2dbd
improvements to testing
dwhswenson Jul 24, 2021
e3ecd1e
Add tests for shooting
dwhswenson Jul 25, 2021
b6254ec
fix shooting tests
dwhswenson Jul 25, 2021
3597dd6
first steps toward autodocumenting yaml structures
dwhswenson Jul 26, 2021
1b2bab0
add json schema support to MDTraj CV
dwhswenson Jul 26, 2021
28d37f7
start using new parameters in volumes
dwhswenson Jul 27, 2021
1181edc
Merge branch 'main' of github.com:openpathsampling/openpathsampling-c…
dwhswenson Jul 27, 2021
76da8bc
mock => unittest.mock
dwhswenson Jul 27, 2021
345b77c
Some more refactoring of sim-setup
dwhswenson Jul 27, 2021
f703605
switched everything over to parameter/builder
dwhswenson Jul 27, 2021
548b389
remove now-unused classes
dwhswenson Jul 27, 2021
8f9fe2e
Start switch to plugins
dwhswenson Jul 29, 2021
379e5f1
add plugins files
dwhswenson Jul 29, 2021
e513680
Start toward registering parsing via plugins
dwhswenson Aug 10, 2021
bdb1ab9
proof of principle for plugin registration
dwhswenson Aug 10, 2021
f31b1c9
more updates to use the new plugin model
dwhswenson Aug 10, 2021
d4b3f29
remove old parsing from engines, cvs, volumes
dwhswenson Aug 11, 2021
c8bf0c3
add tests/parsing/utils
dwhswenson Aug 11, 2021
8163cfe
Remove old parsers: networks, schemes, strategies
dwhswenson Aug 11, 2021
769d3f7
skeleton of root_parser tests
dwhswenson Aug 13, 2021
1cd4885
some root parser tests
dwhswenson Aug 13, 2021
eb78804
more tests for root_parser
dwhswenson Aug 13, 2021
59b890c
Some docstrings and tests for core
dwhswenson Sep 5, 2021
656a22e
Merge branch 'main' of github.com:openpathsampling/openpathsampling-c…
dwhswenson Sep 5, 2021
cb69db6
(most) tests for InstanceBuilder
dwhswenson Sep 5, 2021
eab9b4a
more tests in parsing core
dwhswenson Sep 5, 2021
2bd0eea
tests for helpers in compile command
dwhswenson Sep 5, 2021
f7cc88c
steps toward testing compile command
dwhswenson Sep 6, 2021
b64ea30
major refactor of root_paser
dwhswenson Sep 7, 2021
d77b8aa
Major rename: parsing => compiling
dwhswenson Sep 7, 2021
030679c
more tests for root_compiler
dwhswenson Sep 7, 2021
4b7dd7c
more cleanup to get tests running
dwhswenson Sep 7, 2021
ddc6a17
add test/commands/utils
dwhswenson Sep 7, 2021
ffbf6c5
cleanup; start to tests move scheme compiling
dwhswenson Sep 7, 2021
1b6f505
Fix the error_on_duplicate issue
dwhswenson Sep 8, 2021
ad714d9
fix other problem with duplication
dwhswenson Sep 8, 2021
1e531ba
more tests for compiling.schemes
dwhswenson Sep 8, 2021
71719d5
more testing/coverage
dwhswenson Sep 8, 2021
2f9dc3d
remove unneeded options for InputError
dwhswenson Sep 8, 2021
fdbd7a4
fix typo
dwhswenson Sep 8, 2021
43fec22
Renamings
dwhswenson Sep 8, 2021
4e74899
Rename: compiler_name => category
dwhswenson Sep 8, 2021
0318227
refactor for reusable get_installed_plugins
dwhswenson Sep 8, 2021
3daa542
add docs/compiling.rst
dwhswenson Sep 8, 2021
7fce8a5
compiling/__init__; and always error on duplicate
dwhswenson Sep 9, 2021
9d61206
Apply suggestions from code review
dwhswenson Sep 23, 2021
823ef0c
Update paths_cli/tests/compiling/test_volumes.py
dwhswenson Sep 23, 2021
454ff28
some fixes from review
dwhswenson Sep 23, 2021
571d283
redo reload modules after test
dwhswenson Sep 24, 2021
8904fd3
complete skipped tests in compiling/test_core
dwhswenson Sep 25, 2021
fb518ba
finish skipped tests in test_root_compiler
dwhswenson Sep 25, 2021
e463087
add compat.openmm to handle OpenMM imports
dwhswenson Sep 26, 2021
2dad4d8
fix name of unit when None
dwhswenson Sep 26, 2021
0b106e6
fix skiptest
dwhswenson Sep 26, 2021
ff4bc78
use custom_eval_int_strict_pos
dwhswenson Sep 26, 2021
63a0f33
bring coverage back to 100%
dwhswenson Sep 26, 2021
3fd2509
don't use endswith on possible None
dwhswenson Sep 26, 2021
854137c
cleanup per review comments
dwhswenson Sep 27, 2021
a43b2c0
Update paths_cli/compiling/core.py
dwhswenson Sep 27, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.
19 changes: 5 additions & 14 deletions paths_cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

from .plugin_management import (FilePluginLoader, NamespacePluginLoader,
OPSCommandPlugin)
from .utils import get_installed_plugins

CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])

Expand All @@ -26,20 +27,10 @@ class OpenPathSamplingCLI(click.MultiCommand):
def __init__(self, *args, **kwargs):
# the logic here is all about loading the plugins
commands = str(pathlib.Path(__file__).parent.resolve() / 'commands')
def app_dir_plugins(posix):
return str(pathlib.Path(
click.get_app_dir("OpenPathSampling", force_posix=posix)
).resolve() / 'cli-plugins')

self.plugin_loaders = [
FilePluginLoader(commands, OPSCommandPlugin),
FilePluginLoader(app_dir_plugins(posix=False), OPSCommandPlugin),
FilePluginLoader(app_dir_plugins(posix=True), OPSCommandPlugin),
NamespacePluginLoader('paths_cli_plugins', OPSCommandPlugin)
]

plugins = sum([loader() for loader in self.plugin_loaders], [])

plugins = get_installed_plugins(
default_loader=FilePluginLoader(commands, OPSCommandPlugin),
plugin_types=OPSCommandPlugin
)
self._get_command = {}
self._sections = collections.defaultdict(list)
self.plugins = []
Expand Down
89 changes: 89 additions & 0 deletions paths_cli/commands/compile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import click

from paths_cli.compiling.root_compiler import do_compile, register_plugins
from paths_cli.parameters import OUTPUT_FILE
from paths_cli.errors import MissingIntegrationError
from paths_cli import OPSCommandPlugin
from paths_cli.compiling.plugins import (
CategoryPlugin, InstanceCompilerPlugin
)
from paths_cli.plugin_management import NamespacePluginLoader
import importlib
from paths_cli.utils import get_installed_plugins
from paths_cli.commands.contents import report_all_tables

# this is just to handle a nicer error
def import_module(module_name, format_type=None, install=None):
try:
mod = importlib.import_module(module_name)
except ImportError:
if format_type is None:
format_type = module_name

msg = f"Unable to find a compiler for {format_type} on your system."
if install is not None:
msg += f" Please install {install} to use this format."

raise MissingIntegrationError(msg)
return mod

def load_yaml(f):
yaml = import_module('yaml', format_type="YAML", install="PyYAML")
return yaml.load(f.read(), Loader=yaml.FullLoader)

def load_json(f):
json = import_module('json') # this should never fail... std lib!
return json.loads(f.read())

# This is why we can't use TOML:
# https://github.com/toml-lang/toml/issues/553#issuecomment-444814690
# Conflicts with rules preventing mixed types in arrays. This seems to have
# relaxed in TOML 1.0, but the toml package doesn't support the 1.0
# standard. We'll add toml in once the package supports the standard.

EXTENSIONS = {
'yaml': load_yaml,
'yml': load_yaml,
'json': load_json,
'jsn': load_json,
# 'toml': load_toml,
}

def select_loader(filename):
ext = filename.split('.')[-1]
try:
return EXTENSIONS[ext]
except KeyError:
raise RuntimeError(f"Unknown file extension: {ext}")

@click.command(
'compile',
)
@click.argument('input_file')
@OUTPUT_FILE.clicked(required=True)
def compile_(input_file, output_file):
loader = select_loader(input_file)
with open(input_file, mode='r') as f:
dct = loader(f)

plugin_types = (InstanceCompilerPlugin, CategoryPlugin)
plugins = get_installed_plugins(
default_loader=NamespacePluginLoader('paths_cli.compiling',
plugin_types),
plugin_types=plugin_types
)
register_plugins(plugins)

objs = do_compile(dct)
print(f"Saving {len(objs)} user-specified objects to {output_file}....")
storage = OUTPUT_FILE.get(output_file)
storage.save(objs)
report_all_tables(storage)


PLUGIN = OPSCommandPlugin(
command=compile_,
section="Debug",
requires_ops=(1, 0),
requires_cli=(0, 3)
)
4 changes: 4 additions & 0 deletions paths_cli/commands/contents.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
'Snapshots': 'snapshots'
}

import logging
logger = logging.getLogger(__name__)

@click.command(
'contents',
short_help="list named objects from an OPS storage file",
Expand Down Expand Up @@ -49,6 +52,7 @@ def contents(input_file, table):

def get_section_string(label, store):
attr = NAME_TO_ATTR.get(label, label.lower())
logger.debug(f"Working on {attr}")
if attr in UNNAMED_SECTIONS:
string = get_unnamed_section_string(label, store)
elif attr in ['tag', 'tags']:
Expand Down
18 changes: 18 additions & 0 deletions paths_cli/compat/openmm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# should be able to remove this try block when we drop OpenMM < 7.6
try:
import openmm as mm
from openmm import unit
except ImportError:
try:
from simtk import openmm as mm
from simtk import unit # -no-cov-
except ImportError:
HAS_OPENMM = False
mm = None
unit = None
else: # -no-cov-
HAS_OPENMM = True
else:
HAS_OPENMM = True


12 changes: 12 additions & 0 deletions paths_cli/compiling/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from .core import Parameter, Builder, InstanceCompilerPlugin
from .root_compiler import (clean_input_key, compiler_for, register_plugins,
do_compile)

from .plugins import CategoryPlugin
from .errors import InputError

# OPS-specific
from .plugins import (
EngineCompilerPlugin, CVCompilerPlugin, VolumeCompilerPlugin,
NetworkCompilerPlugin, SchemeCompilerPlugin, StrategyCompilerPlugin,
)
Loading