Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic cli interface to scripts #5

Merged
merged 1 commit into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
24 changes: 24 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# This workflow builds and checks the package for release
name: Build

on:
pull_request:
branches: [main]

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.10"
- run: pip install tox

- name: Test build integrity
run: tox -e build
env:
# Use the CPU only version of torch when building/running the code
PIP_EXTRA_INDEX_URL: https://download.pytorch.org/whl/cpu
21 changes: 21 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Lint

on:
pull_request:
branches: [main]

jobs:
lint:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.10"
- run: pip install tox

- name: Lint the code
run: tox -e lint
68 changes: 25 additions & 43 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,57 +4,39 @@ on:
push:
branches: [main]
pull_request:
# Run for all PRs
# Check all PR

jobs:
tests:
runs-on: ${{ matrix.os }}
name: Test on ${{ matrix.os }}
strategy:
matrix:
include:
- os: ubuntu-20.04
- os: ubuntu-22.04
python-version: "3.8"
- os: ubuntu-22.04
python-version: "3.11"
- os: macos-11
python-version: "3.11"
- os: windows-2019
steps:
- uses: actions/checkout@v3

- name: setup Python
uses: actions/setup-python@v4
with:
python-version: "3.10"

- name: install tests dependencies
run: |
python -m pip install --upgrade pip
python -m pip install tox
python-version: "3.11"

- name: run Python tests
run: python -m tox
env:
PIP_EXTRA_INDEX_URL: https://download.pytorch.org/whl/cpu

# check that we can build Python wheels on any Python version
python-build:
runs-on: ubuntu-20.04
name: check Python build
strategy:
matrix:
python-version: ['3.7', '3.11']
steps:
- uses: actions/checkout@v3

- name: set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- name: install python dependencies
run: |
python -m pip install --upgrade pip
python -m pip install tox wheel

- name: python build tests
run: tox -e build-python
env:
PIP_EXTRA_INDEX_URL: https://download.pytorch.org/whl/cpu
- uses: actions/checkout@v3

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- run: pip install tox

- name: run Python tests
run: tox -e tests
env:
# Use the CPU only version of torch when building/running the code
PIP_EXTRA_INDEX_URL: https://download.pytorch.org/whl/cpu

- name: Upload codecoverage
uses: codecov/codecov-action@v3
with:
files: ./tests/coverage.xml
Empty file removed bin/__init__.py
Empty file.
1 change: 0 additions & 1 deletion bin/eval-metatensor-model.py

This file was deleted.

1 change: 0 additions & 1 deletion bin/export-metatensor-model.py

This file was deleted.

1 change: 0 additions & 1 deletion bin/train-metatensor-model.py

This file was deleted.

4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ repository = "https://github.com/lab-cosmo/metatensor-models"
# changelog = "TODO"

[project.scripts]
maicos = "maicos.__main__:main"
metatensor_models = "metatensor_models.__main__:main"

### ======================================================================== ###

Expand All @@ -59,7 +59,7 @@ soap-bpnn = [
]

[tool.setuptools.packages.find]
where = ["src", "bin"]
where = ["src"]

[tool.setuptools.dynamic]
version = {attr = "metatensor_models.__version__"}
Expand Down
2 changes: 1 addition & 1 deletion src/metatensor_models/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.0.0-dev"
__version__ = "2023.11.29"
72 changes: 72 additions & 0 deletions src/metatensor_models/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
"""The main entry point for the metatensor model interface."""
import argparse
import sys

from . import __version__
from .scripts import evaluate, export, train


def main():
ap = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter,
)

ap.add_argument(
"--version",
action="version",
version=f"metatensor_models {__version__}",
)

ap.add_argument(
"--debug",
action="store_true",
help="Run with debug options.",
)

ap.add_argument(
"--logfile", dest="logfile", action="store", help="Logfile (optional)"
)

subparser = ap.add_subparsers(help="sub-command help")
evaluate_parser = subparser.add_parser(
"evaluate",
help=evaluate.__doc__,
description="evaluate",
formatter_class=argparse.RawDescriptionHelpFormatter,
)
evaluate_parser.set_defaults(callable="evaluate")

export_parser = subparser.add_parser(
"export",
help=export.__doc__,
description="export",
formatter_class=argparse.RawDescriptionHelpFormatter,
)
export_parser.set_defaults(callable="export")
train_parser = subparser.add_parser(
"train",
help=train.__doc__,
description="train",
formatter_class=argparse.RawDescriptionHelpFormatter,
)
train_parser.set_defaults(callable="train")

if len(sys.argv) < 2:
ap.error("A subcommand is required.")

# Be case insensitive for the subcommand
sys.argv[1] = sys.argv[1].lower()

args = ap.parse_args(sys.argv[1:])

if args.callable == "evaluate":
evaluate()
elif args.callable == "export":
export()
elif args.callable == "train":
train()


if __name__ == "__main__":
main()
5 changes: 5 additions & 0 deletions src/metatensor_models/scripts/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .evaluate import evaluate
from .export import export
from .train import train

__all__ = ["evaluate", "export", "train"]
3 changes: 3 additions & 0 deletions src/metatensor_models/scripts/evaluate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
def evaluate():
"""evaluate a model"""
print("Run evaluate...")
3 changes: 3 additions & 0 deletions src/metatensor_models/scripts/export.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
def export():
"""export a model"""
print("Run exort...")
3 changes: 3 additions & 0 deletions src/metatensor_models/scripts/train.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
def train():
"""train a model"""
print("Run train...")
30 changes: 30 additions & 0 deletions tests/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import subprocess
import sys

import pytest

from metatensor_models.scripts import __all__ as available_scripts


class Test_parse_args(object):
"""Tests for argument parsing."""

def test_required_args(self):
"""Test required arguments."""
with pytest.raises(subprocess.CalledProcessError):
subprocess.check_call(["metatensor_models"])

def test_wrong_module(self):
"""Test wrong module."""
with pytest.raises(subprocess.CalledProcessError):
subprocess.check_call(["metatensor_models", "foo"])

@pytest.mark.parametrize("module", tuple(available_scripts))
def test_available_modules(self, module):
"""Test available modules."""
subprocess.check_call(["metatensor_models", module, "--help"])

@pytest.mark.parametrize("args", ("version", "help"))
def test_extra_options(self, args):
"""Test extra options."""
subprocess.check_call(["metatensor_models", "--" + args])
42 changes: 13 additions & 29 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ passenv = *
lint_folders = "{toxinidir}/src"

[testenv:lint]
# this environement lints the Python code with flake8 (code linter), black (code
# formatter), and isort (sorting of imports)
description = Run linters and type checks
package = skip
deps =
flake8
Expand All @@ -29,9 +28,7 @@ commands =
isort --check-only --diff {[testenv]lint_folders}

[testenv:format]
# this environement abuses tox to do actual formatting
#
# Users can run `tox -e format` to run formatting on all files
description = Abuse tox to do actual formatting on all files.
package = skip
deps =
black
Expand All @@ -51,34 +48,21 @@ deps =
commands =
pytest --import-mode=append {posargs}

[testenv:soap-bpnn]
passenv = *
deps =
pytest

commands =
echo "success"

[testenv:build-python]
# this environement makes sure one can build sdist and wheels for Python
[testenv:build]
description = builds the package and checks integrity
usedevelop = true
deps =
setuptools
wheel
cmake
twine
build

allowlist_externals =
bash

check-manifest
twine
allowlist_externals = bash
commands_pre =
bash -c "if [ -e {toxinidir}/dist/*tar.gz ]; then unlink {toxinidir}/dist/*.whl; fi"
bash -c "if [ -e {toxinidir}/dist/*tar.gz ]; then unlink {toxinidir}/dist/*.tar.gz; fi"
commands =
# check building sdist and wheels from a checkout
python -m build
twine check dist/*.tar.gz
twine check dist/*.whl

# check building wheels from the sdist
bash -c "python -m pip wheel --verbose dist/metatensor_models-*.tar.gz -w dist/test"
twine check dist/*.tar.gz dist/*.whl
check-manifest {toxinidir}

[flake8]
# longer lines for compatibility with other linters
Expand Down