diff --git a/.github/dependabot.yml b/.github/dependabot.yml index bf7c985..e385fc2 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,11 +1,16 @@ -# Set update schedule for GitHub Actions +# Set update schedule for GitHub Actions and Python packages version: 2 updates: + # Check for updates to GitHub Actions every week - package-ecosystem: "github-actions" directory: "/" schedule: - # Check for updates to GitHub Actions every week interval: "weekly" + # Check for updates to pip packages every week + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/buildtest.yml b/.github/workflows/buildtest.yml index 99474b3..fb7432c 100644 --- a/.github/workflows/buildtest.yml +++ b/.github/workflows/buildtest.yml @@ -14,7 +14,7 @@ on: jobs: test: - name: Test and Deploy (${{ matrix.config.stormpyImg }}) + name: Build and Test (${{ matrix.config.stormpyImg }}) runs-on: ubuntu-latest strategy: matrix: @@ -27,35 +27,11 @@ jobs: - name: Git clone uses: actions/checkout@v5 - name: Build from Dockerfile - run: docker build -t movesrwth/stormpy-starter . --build-arg STORMPY_BASE=movesrwth/stormpy:${{ matrix.config.stormpyImg }} + run: docker build -t stormchecker/stormpy-starter . --build-arg STORMPY_BASE=movesrwth/stormpy:${{ matrix.config.stormpyImg }} - name: Run Docker - run: docker run -d -it --name ci -p 8888:8888 movesrwth/stormpy-starter - - name: Run and check output of example commands + run: docker run -d -it --name ci -p 8888:8888 stormchecker/stormpy-starter + - name: Run tests run: | - docker exec ci bash -c "python stormpy_starter/check.py --model examples/die.pm --property examples/die.pctl | grep 'no'" - docker exec ci bash -c "python stormpy_starter/check.py --model examples/die.pm --property examples/die2.pctl | grep 'yes'" + docker exec ci bash -c "pip install .[test]; pytest" - name: Run notebook run: docker exec ci bash -c "pip install papermill && papermill stormpy_starter.ipynb" - - notify: - name: Email notification - runs-on: ubuntu-latest - needs: [test] - # Only run in main repo and even if previous step failed - if: github.repository_owner == 'moves-rwth' && always() - steps: - - uses: technote-space/workflow-conclusion-action@v3 - - uses: dawidd6/action-send-mail@v6 - with: - server_address: ${{ secrets.STORM_CI_MAIL_SERVER }} - server_port: 587 - username: ${{ secrets.STORM_CI_MAIL_USERNAME }} - password: ${{ secrets.STORM_CI_MAIL_PASSWORD }} - subject: "[You broke it] CI run failed for ${{ github.repository }}" - body: - "CI job of ${{ github.repository }} has failed for commit ${{ github.sha }}.\n\ - The error type is: ${{ env.WORKFLOW_CONCLUSION }}.\n\n\ - For more information, see https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" - to: ${{ secrets.STORM_CI_MAIL_RECIPIENTS }} - from: Github Actions - if: env.WORKFLOW_CONCLUSION != 'success' # notify only if failure diff --git a/.github/workflows/formatapply.yml b/.github/workflows/formatapply.yml new file mode 100644 index 0000000..6a06bee --- /dev/null +++ b/.github/workflows/formatapply.yml @@ -0,0 +1,39 @@ +name: Apply code format + +on: + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v5 + - uses: psf/black@stable + with: + options: "" + src: "." + jupyter: true + - name: Commit Formatting + run: | + git config user.name 'Auto Format' + git config user.email 'test@test' + if [ -z "$(git status --porcelain)" ] + then + echo "Code did not change" + else + git commit -am "Applied code formatting" + git rev-parse HEAD >> .git-blame-ignore-revs + git commit -am "Add code formatting commit to .git-blame-ignore-revs" + fi + - name: Create Pull Request + id: cpr + uses: peter-evans/create-pull-request@v7 + with: + branch: ci/apply-code-format + delete-branch: true + title: 'Code formatting' + body: | + Auto-generated pull request triggered by the `apply-code-format` workflow. + - Manually close and reopen this PR to trigger the CI. + - Make sure to **merge** (and not rebase) this PR so that the added commit hash in `.git-blame-ignore-revs` remains valid. diff --git a/.github/workflows/formatcheck.yml b/.github/workflows/formatcheck.yml new file mode 100644 index 0000000..6bcecde --- /dev/null +++ b/.github/workflows/formatcheck.yml @@ -0,0 +1,18 @@ +name: Check code format + +on: + push: + pull_request: + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v5 + - uses: psf/black@stable + with: + options: "--check --diff --color" + src: "." + jupyter: true diff --git a/Dockerfile b/Dockerfile index 39c5f82..9e2203c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,14 @@ # Run Docker container for Jupyter notebook +################################### +# The Docker image can be built by executing: +# docker build -t yourusername/stormpy-starter . +# A different stormpy base image can be set from the commandline with: +# --build-arg STORMPY_BASE= + +# Set stormpy base image ARG STORMPY_BASE=movesrwth/stormpy:stable FROM $STORMPY_BASE -MAINTAINER Matthias Volk +LABEL org.opencontainers.image.authors="dev@stormchecker.org" ########## diff --git a/README.md b/README.md index 945c139..02f960a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # storm-project-starter-python Starter project for the Python API of Storm via Stormpy -[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/moves-rwth/storm-project-starter-python/master?filepath=stormpy_starter.ipynb) +[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/stormchecker/storm-project-starter-python/master?filepath=stormpy_starter.ipynb) ## Getting started Before starting, make sure that Storm and stormpy are installed. If not, see the [documentation](https://moves-rwth.github.io/stormpy/installation.html) for details on how to install stormpy. @@ -9,7 +9,7 @@ Before starting, make sure that Storm and stormpy are installed. If not, see the First, install the Python package. If you use a virtual environment, make sure to use it. To install the starter package, execute ``` -python setup.py develop +pip install . ``` Then, run the script using @@ -27,17 +27,17 @@ The answer should be yes. ## Try out in browser via Jupyterlab You can also try out the starter project in your browser by using Jupyterlab. -You can use this [Binder link](https://mybinder.org/v2/gh/moves-rwth/storm-project-starter-python/master?filepath=stormpy_starter.ipynb) which starts an interactive Jupyter notebook. +You can use this [Binder link](https://mybinder.org/v2/gh/stormchecker/storm-project-starter-python/master?filepath=stormpy_starter.ipynb) which starts an interactive Jupyter notebook. ### Running Jupyter locally. You can also start the Jupyterlab locally using [Docker](https://www.docker.com/). First, build the Docker container with ``` -docker build -t movesrwth/stormpy-starter . +docker build -t stormchecker/stormpy-starter . ``` Then start the Docker container with the following command: ``` -docker run -it --rm -p 8888:8888 movesrwth/stormpy-starter jupyter notebook --NotebookApp.default_url=/lab/ --ip=0.0.0.0 --port=8888 +docker run -it --rm -p 8888:8888 stormchecker/stormpy-starter jupyter notebook --NotebookApp.default_url=/lab/ --ip=0.0.0.0 --port=8888 ``` You can find the URL to the notebook in the output. diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..f141088 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,60 @@ +[build-system] +requires = ["hatchling >= 1.26"] +build-backend = "hatchling.build" + +[project] +name = "storm-project-starter-python" +description = "Starter project for the Python API of Storm via Stormpy" +version = "0.1" +readme = "README.md" +license.file = "LICENSE" +authors = [ + { name = "S. Junges", email = "sebastian.junges@ru.nl" }, + { name = "M. Volk", email = "m.volk@tue.nl" } +] +requires-python = ">=3.9" +dependencies = [ + "stormpy>=1.10", +] +classifiers = [ + 'Intended Audience :: Science/Research', + 'Topic :: Scientific/Engineering', + 'Topic :: Software Development :: Libraries :: Python Modules', +] + +[project.urls] +Homepage = "https://github.com/stormchecker/storm-project-starter-python" + +[project.optional-dependencies] +dev = [ + # Formatting + "black[jupyter]", +] +test = [ + "pytest", + "nbval", +] + +[tool.hatch.build.targets.wheel] +only-include = ["stormpy_starter"] + +[tool.black] +line-length = 160 + +[tool.pytest.ini_options] +minversion = "6.0" +addopts = "--nbval" +#testpaths = [ +# "tests", +# "examples", +# "doc", +#] +#python_files = [ +# "test*.py", +# "examples/*.py", +#] +#python_functions = [ +# "*_test", +# "test_*", +# "example_*", +#] diff --git a/setup.py b/setup.py deleted file mode 100644 index 6f85c50..0000000 --- a/setup.py +++ /dev/null @@ -1,25 +0,0 @@ -import os -from setuptools import setup - -# Get the long description from the README file -with open(os.path.join(os.path.abspath(os.path.dirname(__file__)), 'README.md')) as f: - long_description = f.read() - -setup( - name="storm-project-starter-python", - version="0.1", - author="M. Volk", - author_email="matthias.volk@cs.rwth-aachen.de", - maintainer="S. Junges", - maintainer_email="sebastian.junges@cs.rwth-aachen.de", - url="https://github.com/moves-rwth/storm-project-starter-python", - description="Starter project for the Python API of Storm via Stormpy", - long_description=long_description, - long_description_content_type='text/markdown', - - packages=["stormpy_starter"], - install_requires=[ - "stormpy>=1.3.0" - ], - python_requires='>=3', -) diff --git a/stormpy_starter/check.py b/stormpy_starter/check.py index dfd9681..ac91f4e 100644 --- a/stormpy_starter/check.py +++ b/stormpy_starter/check.py @@ -12,10 +12,10 @@ def check(path_to_model, property_str): def main(): - parser = argparse.ArgumentParser(description='Starter project for stormpy.') + parser = argparse.ArgumentParser(description="Starter project for stormpy.") - parser.add_argument('--model', '-m', help='Model file', required=True) - parser.add_argument('--property', '-p', help='Property', required=True) + parser.add_argument("--model", "-m", help="Model file", required=True) + parser.add_argument("--property", "-p", help="Property", required=True) args = parser.parse_args() # Call function diff --git a/tests/test_starter.py b/tests/test_starter.py new file mode 100644 index 0000000..a2ec3fd --- /dev/null +++ b/tests/test_starter.py @@ -0,0 +1,11 @@ +from stormpy_starter import check + + +def test_prop1(): + answer = check.check("examples/die.pm", "examples/die.pctl") + assert not answer + + +def test_prop2(): + answer = check.check("examples/die.pm", "examples/die2.pctl") + assert answer