diff --git a/.cruft.json b/.cruft.json index e8bbc46a..e37ace13 100644 --- a/.cruft.json +++ b/.cruft.json @@ -1,6 +1,6 @@ { "template": "git@github.com:FAIRmat-NFDI/pynxtools-plugin-template.git", - "commit": "519f503945368a21d0c44125c0f34cf0d5f46e10", + "commit": "616d3dc6584cb0f19e85310a083c7a87857c6b8d", "checkout": null, "context": { "cookiecutter": { @@ -11,18 +11,25 @@ "reader_class": "SPMReader", "author_name": "The NOMAD authors", "author_email": "fairmat@physik.hu-berlin.de", + "github_username": "", + "organization_name": "fairmat-nfdi", "license": "Apache Software License 2.0", "zenodo_record": "17390485", - "vscode_settings": false, + "vscode_settings": true, "include_nomad_app": true, "include_nomad_example_upload": true, + "include_north_tools": true, + "north_tool_name": "spm", "__package_name": "pynxtools-spm", "__module_name": "pynxtools_spm", "__nomad_example": "spm_example_upload_entry_point", - "__nomad_app": "", - "_copy_without_render": ["*.html"], + "__nomad_app": "spm_app_entry_point", + "__north_tool_EP_name": "north_tool", + "_copy_without_render": [ + "*.html" + ], "_template": "git@github.com:FAIRmat-NFDI/pynxtools-plugin-template.git", - "_commit": "519f503945368a21d0c44125c0f34cf0d5f46e10" + "_commit": "616d3dc6584cb0f19e85310a083c7a87857c6b8d" } }, "directory": null diff --git a/.cspell/custom-dictionary.txt b/.cspell/custom-dictionary.txt index a8909535..016c1fa7 100644 --- a/.cspell/custom-dictionary.txt +++ b/.cspell/custom-dictionary.txt @@ -104,3 +104,7 @@ ureg valinit valtext Yichen +FAIRmat +fairmat +jovyan +ipynb \ No newline at end of file diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..40d1ef96 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,94 @@ +# Git +.gitignore +.gitattributes + +# Python +__pycache__ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +.pytest_cache/ + +# Virtual Environments +.venv +venv/ +ENV/ +env/ +.venv/ + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ +.DS_Store +.project +.pydevproject +.settings/ +*.sublime-project +*.sublime-workspace + +# CI/CD +.github/ +.gitlab-ci.yml +.travis.yml +.circleci/ + +# Testing +.coverage +.coverage.* +htmlcov/ +.tox/ +.hypothesis/ +pytest.ini +.pytest_cache/ + +# Documentation +docs/_build/ +site/ +.mkdocs.yml +mkdocs.yml + +# Docker +Dockerfile* +.dockerignore +docker/ + +# Node (if used) +node_modules/ +npm-debug.log +package-lock.json + +# Misc +*.md +LICENSE +MANIFEST.in +*.tar.gz +*.zip +.tmp/ +.cache/ + +# IDE configuration files +.editorconfig +.env +.env.local diff --git a/.github/workflows/cruft_update.yml b/.github/workflows/cruft_update.yml index f4cb152b..f931761e 100644 --- a/.github/workflows/cruft_update.yml +++ b/.github/workflows/cruft_update.yml @@ -15,20 +15,7 @@ env: jobs: update: runs-on: ubuntu-latest - strategy: - fail-fast: true - matrix: - include: - - add-paths: . - body: Use this to merge the changes to this repository. - branch: cruft/update - commit-message: "chore: accept new Cruft update" - title: New updates detected with Cruft - - add-paths: .cruft.json - body: Use this to reject the changes in this repository. - branch: cruft/reject - commit-message: "chore: reject new Cruft update" - title: Reject new updates detected with Cruft + steps: - uses: actions/checkout@v4 @@ -52,7 +39,6 @@ jobs: else echo "No .cruft.json file" fi - echo "has_changes=$CHANGES" >> "$GITHUB_OUTPUT" - name: Run update if available @@ -62,20 +48,29 @@ jobs: git config --global user.name "GitHub" cruft update --skip-apply-ask --refresh-private-variables - # git restore --staged . + + # -------------------------------------------------------- + # HARD BLOCK: never allow workflow updates from Cruft + # -------------------------------------------------------- + git restore --staged .github/workflows || true + git restore .github/workflows || true - name: Create pull request if: steps.check.outputs.has_changes == '1' uses: peter-evans/create-pull-request@v4 with: token: ${{ secrets.GITHUB_TOKEN }} - add-paths: ${{ matrix.add-paths }} - commit-message: ${{ matrix.commit-message }} - branch: ${{ matrix.branch }} + add-paths: . + commit-message: "chore: accept new Cruft update" + branch: cruft/update delete-branch: true branch-suffix: timestamp - title: ${{ matrix.title }} + title: New updates detected with Cruft body: | - This is an autogenerated PR. ${{ matrix.body }} + This is an autogenerated PR. + + [Cruft](https://cruft.github.io/cruft/) has detected updates from the + Cookiecutter repository. - [Cruft](https://cruft.github.io/cruft/) has detected updates from the Cookiecutter repository. + Changes to `.github/workflows` are intentionally excluded + from automated updates and must be applied manually. diff --git a/.github/workflows/nomad-requirements.yml b/.github/workflows/nomad-requirements.yml index 48be2e26..02104a86 100644 --- a/.github/workflows/nomad-requirements.yml +++ b/.github/workflows/nomad-requirements.yml @@ -39,8 +39,8 @@ jobs: - name: Generate (dev-)requirements.txt from modified pyproject.toml working-directory: ./nomad run: | - uv pip compile --universal -p ${{ env.python-version }} --annotation-style=line --extra=infrastructure --extra=parsing --output-file=requirements.txt pyproject.toml - uv pip compile --universal -p ${{ env.python-version }} --annotation-style=line --extra=dev --extra=infrastructure --extra=parsing --output-file=requirements-dev.txt requirements.txt pyproject.toml + uv pip compile --universal -p ${{ env.python-version }} --annotation-style=line --extra=infrastructure --output-file=requirements.txt pyproject.toml + uv pip compile --universal -p ${{ env.python-version }} --annotation-style=line --extra=dev --extra=infrastructure --output-file=requirements-dev.txt requirements.txt pyproject.toml uv pip compile --universal -p ${{ env.python-version }} --annotation-style=line --output-file=requirements-plugins.txt --unsafe-package nomad-lab -c requirements-dev.txt test_plugins.txt - name: Install NOMAD dependencies with pynxtools from current branch working-directory: ./nomad diff --git a/.github/workflows/publish-north.yaml b/.github/workflows/publish-north.yaml new file mode 100644 index 00000000..128efdab --- /dev/null +++ b/.github/workflows/publish-north.yaml @@ -0,0 +1,125 @@ +name: Build and publish docker images +on: + push: + branches: + - main + tags: + - "v*.*.*" + pull_request: + branches: + - main + +env: + REGISTRY: ghcr.io + UV_VERSION: 0.9 + PYTHON_VERSION: 3.12 + JUPYTER_VERSION: 2025-12-31 + NORTH_TOOL_DIR: src/pynxtools_spm/nomad/north_tools/spm + TEST_DATA_DIR: tests/data/north_tools/spm + TEST_NOTEBOOKS: CommandLine.ipynb + +permissions: + packages: write + contents: read + attestations: write + id-token: write + +jobs: + build: + name: Build Jupyter Image + runs-on: ubuntu-latest + outputs: + tags: ${{ steps.meta.outputs.tags }} # list + labels: ${{ steps.meta.outputs.labels }} # list + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.head_ref || github.ref_name }} + fetch-depth: 0 + show-progress: true + submodules: true + + # Replace driver `Docker' by `Docker-container` to support cache export/import + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + # https://github.com/docker/metadata-action + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ github.repository }} + # set latest tag for main branch and tags + # https://github.com/docker/metadata-action?tab=readme-ov-file#image-name-and-tag-sanitization + tags: | + type=ref,event=tag + type=ref,event=pr,prefix=pr- + type=raw,value=main,enable=${{ github.ref == format('refs/heads/{0}', 'main') }} + flavor: | + latest=auto + + # https://docs.docker.com/build/ci/github-actions/share-image-jobs/ + # https://github.com/docker/build-push-action + - name: Build and export to Jupyter image + uses: docker/build-push-action@v6 + with: + context: . + file: ${{ env.NORTH_TOOL_DIR }}/Dockerfile + build-args: | + UV_VERSION=${{ env.UV_VERSION }} + JUPYTER_TAG=${{ env.JUPYTER_VERSION }} + cache-from: type=gha + cache-to: type=gha,mode=max + push: false + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + outputs: type=docker,dest=${{ runner.temp }}/jupyter.tar.gz + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: jupyter-image + path: ${{ runner.temp }}/jupyter.tar.gz + test_and_push_image: + name: Test Jupyter Image + needs: build + runs-on: ubuntu-latest + # https://docs.docker.com/build/ci/github-actions/share-image-jobs/ + steps: + - name: Setup Repository + uses: actions/checkout@v4 + - name: Download artifact + uses: actions/download-artifact@v4 + with: + name: jupyter-image + path: ${{ runner.temp }} + pattern: "!*.dockerbuild" # warning at https://github.com/docker/build-push-action?tab=readme-ov-file + + - name: Load and test in Jupyter container + run: | + docker load -i ${{ runner.temp }}/jupyter.tar.gz + + RAW_TAGS="${{ needs.build.outputs.tags }}" + echo "Raw tags: $RAW_TAGS" + FIRST_TAG=$(echo "$RAW_TAGS" | tr -s '[:space:]' '\n' | grep -v '^$' | head -n 1) + echo "Using tag: $FIRST_TAG" + + for nb in ${{ env.TEST_NOTEBOOKS }}; do + echo "Running notebook: $nb" + docker run \ + --mount type=bind,src=./${{ env.TEST_DATA_DIR }},dst="/home/jovyan/north_test" \ + --rm "$FIRST_TAG" \ + /bin/bash -c "jupyter execute \$HOME/north_test/$nb" + done + + - uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Push Jupyter Image + run: | + RAW_TAGS="${{ needs.build.outputs.tags }}" + for TAG in $RAW_TAGS; do + echo "Pushing tag: $TAG" + docker push "$TAG" + done \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f688409b..c7e6ea8e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,4 +6,28 @@ repos: # Run the linter. - id: ruff # Run the formatter. - - id: ruff-format \ No newline at end of file + - id: ruff-format + + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.7.1 + hooks: + - id: mypy # static type checking + + - repo: https://github.com/asottile/pyupgrade + rev: v2.37.3 + hooks: + - id: pyupgrade + args: [--py36-plus] # modernizes syntax for Python 3.6+ + + - repo: https://github.com/kynan/nbstripout + rev: 0.6.0 + hooks: + - id: nbstripout # removes notebook outputs before committing + + - repo: https://github.com/streetsidesoftware/cspell-cli + rev: v6.31.1 + hooks: + - id: cspell # spellchecking + pass_filenames: false + args: + - --config \ No newline at end of file diff --git a/README.md b/README.md index b266907a..0c00f0c0 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ . -This `pynxtools` plugin was generated with [`cookiecutter`](https://github.com/cookiecutter/cookiecutter) using the [`pynxtools-plugin-template`](https://github.com/FAIRmat-NFDI/`pynxtools-plugin-template) template. +This `pynxtools` plugin was generated with [`cookiecutter`](https://github.com/cookiecutter/cookiecutter) using the [`pynxtools-plugin-template`](https://github.com/FAIRmat-NFDI/pynxtools-plugin-template) template. ## Installation diff --git a/pyproject.toml b/pyproject.toml index c581cd0a..2f62f5e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,7 +40,8 @@ dev = [ "mypy", "ruff>=0.14.0", "pytest", - "pre-commit" + "pre-commit", + "cruft", ] docs = [ @@ -51,6 +52,12 @@ docs = [ "mkdocs-macros-plugin", "mkdocs-simple-hooks", ] +north = [ + "jupyterlab-h5web", + "jupyterlab", + "ipywidgets", +] +nomad = ["nomad-lab[infrastructure]>=1.4.1rc2"] [project.entry-points."pynxtools.reader"] spm = "pynxtools_spm.reader:SPMReader" @@ -60,6 +67,7 @@ sts_example = "pynxtools_spm.nomad.entrypoints:sts_example" stm_example = "pynxtools_spm.nomad.entrypoints:stm_example" afm_example = "pynxtools_spm.nomad.entrypoints:afm_example" spm_app = "pynxtools_spm.nomad.apps:spm_app" +spm = "pynxtools_spm.nomad.north_tools.spm:north_tool" [tool.setuptools.packages.find] @@ -70,7 +78,7 @@ version_scheme = "no-guess-dev" local_scheme = "node-and-date" [tool.ruff] -include = ["src/pynxtools_spm/*.py", "tests/*.py"] +include = ["src/pynxtools_spm/**/*.py", "tests/**/*.py"] lint.select = [ "E", # pycodestyle "W", # pycodestyle diff --git a/scripts/generate_reference_files.sh b/scripts/generate_reference_files.sh index 227d707b..c6a2c123 100755 --- a/scripts/generate_reference_files.sh +++ b/scripts/generate_reference_files.sh @@ -2,7 +2,7 @@ function update_ref_file { local FOLDER=$1 local NXDL=$2 - cd $FOLDER + cd "$FOLDER" if [[ "$FOLDER" == "." ]]; then FOLDER="test" fi diff --git a/src/pynxtools_spm/nomad/README.md b/src/pynxtools_spm/nomad/README.md deleted file mode 100644 index 3ad108f8..00000000 --- a/src/pynxtools_spm/nomad/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# NOMAD integration - -This module is for integrating pynxtools-spm into [NOMAD](https://nomad-lab.eu/) as a plugin. diff --git a/src/pynxtools_spm/nomad/north_tools/__init__.py b/src/pynxtools_spm/nomad/north_tools/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/pynxtools_spm/nomad/north_tools/spm/Dockerfile b/src/pynxtools_spm/nomad/north_tools/spm/Dockerfile new file mode 100644 index 00000000..cb8e3222 --- /dev/null +++ b/src/pynxtools_spm/nomad/north_tools/spm/Dockerfile @@ -0,0 +1,77 @@ +ARG JUPYTER_TAG=2025-12-31 +ARG BASE_JUPYTER=quay.io/jupyter/base-notebook +ARG UV_VERSION=0.9 +ARG PLUGIN_NAME=pynxtools-spm + +FROM ghcr.io/astral-sh/uv:${UV_VERSION} AS uv_stage + +FROM ${BASE_JUPYTER}:${JUPYTER_TAG} AS base_notebook +# https://github.com/hadolint/hadolint/wiki/DL4006 +# https://github.com/koalaman/shellcheck/wiki/SC3014 +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +COPY --from=uv_stage /uv /uvx /bin/ + +USER root + +# Define environment variables +# With pre-existing NB_USER="jovyan" and NB_UID=100, NB_GID=1000 +ENV HOME=/home/${NB_USER} +ENV CONDA_DIR=/opt/conda + +ARG PLUGIN_NAME + +RUN apt-get update \ + && apt-get install --yes --quiet --no-install-recommends \ + libmagic1 \ + file \ + build-essential \ + curl \ + zip \ + unzip \ + git + +# By default base-notebook:2025-10-20 has node 18 +# But, node > 20 is required for jupyterlab >= 4.4.10 +# Add NodeSource APT repo for Debian-base distributions repository +RUN curl -fsSL https://deb.nodesource.com/setup_24.x | bash - + +# Install Node.js from the Debian-based distributions repository +RUN apt-get install nodejs -y \ + && npm install -g configurable-http-proxy@^4.2.0 \ + # clean cache and logs + && rm -rf /var/lib/apt/lists/* /var/log/* /var/tmp/* ~/.npm + +USER ${NB_USER} + +# uv env +ENV UV_PROJECT_ENVIRONMENT=${CONDA_DIR} \ + UV_LINK_MODE=copy \ + UV_NO_CACHE=1 \ + # Use python from conda which is default for base-notebook + # so that uv pip and pip refer to the same python + # If needed one can create another venv with 'uv venv' + UV_SYSTEM_PYTHON=1 + +COPY --chown=${NB_USER}:${NB_GID} . ${HOME}/${PLUGIN_NAME} + +WORKDIR ${HOME}/${PLUGIN_NAME} + +# https://docs.astral.sh/uv/guides/integration/docker/#intermediate-layers +# Install dependencies +RUN --mount=type=cache,target=/root/.cache/uv \ + uv pip install ".[north]" + # uv pip install . --group north --constraint requirements.txt + +WORKDIR ${HOME} +RUN rm -rf ${HOME}/${PLUGIN_NAME} + +RUN jupyter lab build --dev-build=False --minimize=False && \ + fix-permissions "/home/${NB_USER}" \ + && fix-permissions "${CONDA_DIR}" + +WORKDIR ${HOME} + +EXPOSE 8888 + +RUN touch ${HOME}/.hushlogin \ No newline at end of file diff --git a/src/pynxtools_spm/nomad/north_tools/spm/README.md b/src/pynxtools_spm/nomad/north_tools/spm/README.md new file mode 100644 index 00000000..759d5bf0 --- /dev/null +++ b/src/pynxtools_spm/nomad/north_tools/spm/README.md @@ -0,0 +1,32 @@ +# pynxtools-spm - NORTH Jupyter tool + +This directory contains the NORTH tool configuration and Docker file for programmatic creation of a Jupyter-based NOMAD NORTH tool. + +## Quick start + +The spm NORTH tool provides a containerized JupyterLab environment for interactive analysis with the pynxtools-spm plugin. + +## Building and testing + +Build the Docker image locally from package root: + +```bash +docker build -f src/pynxtools_spm/north_tools/spm/Dockerfile \ + -t ghcr.io/fairmat-nfdi/pynxtools-spm:latest . +``` + +Test the image: + +```bash +docker run -p 8888:8888 ghcr.io/fairmat-nfdi/pynxtools-spm:latest +``` + +Access JupyterLab at `http://localhost:8888`. + +## Documentation + +For comprehensive guidance, see the main docs and the single source of truth for NORTHTool and NorthToolEntryPoint. These resources cover entry point configuration, image structure, and dependency management. + +- [NOMAD NORTH tools](https://fairmat-nfdi.github.io/nomad-docs/howto/plugins/types/north_tools.html) +- [Reference for NorthToolEntryPoint](https://fairmat-nfdi.github.io/nomad-docs/reference/plugins.html#northtoolentrypoint) +- [Reference for NORTHTool](https://fairmat-nfdi.github.io/nomad-docs/howto/plugins/types/north_tools.html#north-tool-entry-point) \ No newline at end of file diff --git a/src/pynxtools_spm/nomad/north_tools/spm/__init__.py b/src/pynxtools_spm/nomad/north_tools/spm/__init__.py new file mode 100644 index 00000000..8d2f4ab8 --- /dev/null +++ b/src/pynxtools_spm/nomad/north_tools/spm/__init__.py @@ -0,0 +1,21 @@ +from nomad.config.models.north import NORTHTool +from nomad.config.models.plugins import NorthToolEntryPoint + +tool = NORTHTool( + short_description="Jupyter Notebook server in NOMAD NORTH for NOMAD and pynxtools plugin pynxtools-spm.", + image="ghcr.io/fairmat-nfdi/pynxtools-spm/jupyter:latest", + description="Jupyter Notebook server in NOMAD NORTH for NOMAD and pynxtools plugin pynxtools-spm.", + external_mounts=[], + file_extensions=["ipynb", "nxs"], + icon="logo/jupyter.svg", + image_pull_policy="Always", + default_url="/lab", + maintainer=[{"email": "fairmat@physik.hu-berlin.de", "name": "The NOMAD authors"}], + mount_path="/home/jovyan", + path_prefix="lab/tree", + privileged=False, + with_path=True, + display_name="spm", +) + +north_tool = NorthToolEntryPoint(id_url_safe="pynxtools_spm_spm", north_tool=tool) diff --git a/src/pynxtools_spm/nxformatters/base_formatter.py b/src/pynxtools_spm/nxformatters/base_formatter.py index ad7bdc19..3a2250e0 100644 --- a/src/pynxtools_spm/nxformatters/base_formatter.py +++ b/src/pynxtools_spm/nxformatters/base_formatter.py @@ -377,7 +377,7 @@ def _resolve_link_in_config(self, val: str, path: str = "/"): """ if val.startswith("@default_link:"): - val = val.split("@default_link:")[-1] + val = val.rsplit("@default_link:", maxsplit=1)[-1] classes = val.split("/")[1:] pattern = "" @@ -671,7 +671,9 @@ def _handle_special_fields(self): r"active_channel$": str, r"model/@version$": str, r"/model$": str, - r"lockin_amplifier/(demodulated|modulation)_signal$": lambda input: input.lower(), + r"lockin_amplifier/(demodulated|modulation)_signal$": lambda input: ( + input.lower() + ), r"lockin_amplifier/(hp|lp){1,}_filter_orderN\[\1_filter_order_[\w]*\]$": ( lambda input: input if isinstance(input, (int, float)) else "" ), diff --git a/src/pynxtools_spm/nxformatters/helpers.py b/src/pynxtools_spm/nxformatters/helpers.py index 7a03d347..72dcb2db 100644 --- a/src/pynxtools_spm/nxformatters/helpers.py +++ b/src/pynxtools_spm/nxformatters/helpers.py @@ -267,7 +267,7 @@ def get_actual_from_variadic_name(name: str) -> str: str The actual name. """ - return name.split("[")[-1].split("]")[0] + return name.rsplit("[", maxsplit=1)[-1].split("]", maxsplit=1)[0] def flatten_nested_list(list_dt: Union[list, tuple, Any]): diff --git a/tests/data/north_tools/spm/CommandLine.ipynb b/tests/data/north_tools/spm/CommandLine.ipynb new file mode 100644 index 00000000..55d834bf --- /dev/null +++ b/tests/data/north_tools/spm/CommandLine.ipynb @@ -0,0 +1,89 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "4adab3e0-b913-4a6f-a434-1427094b0c0d", + "metadata": {}, + "source": [ + "# Jupyter Notebook as a Placeholder for NOMAD north tool hub\n", + "\n", + "This Notebook mainly runs a few commands for testing purpose. As plugin developer you can remove the entire content of the file or rename the file or delete the file and create a new one according to your requirements.\n", + "If you rename or relocate the file, please update the corresponding file path in the north publish CI/CD workflow (or search the project directory for this notebook name)." + ] + }, + { + "cell_type": "markdown", + "id": "74918766-45d2-41ad-89ce-04ef1ee30b6d", + "metadata": {}, + "source": [ + "## Prints the available python library in this environment using uv" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3b8decdf-657c-447c-8173-33ecc528bc7c", + "metadata": {}, + "outputs": [], + "source": [ + "!uv pip list" + ] + }, + { + "cell_type": "markdown", + "id": "9be891f7", + "metadata": {}, + "source": [ + "## Prints the available python library in this environment using pip, it gives the same result as the previous command." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ee57dfba", + "metadata": {}, + "outputs": [], + "source": [ + "!pip list" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "56505869", + "metadata": {}, + "outputs": [], + "source": [ + "# installation of build-essential\n", + "! make --version\n", + "! gcc --version\n", + "! g++ --version\n", + "\n", + "! git --version\n", + "! nodejs --version\n", + "! npm --version" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/tests/test_nomad_north_tools.py b/tests/test_nomad_north_tools.py new file mode 100644 index 00000000..27211591 --- /dev/null +++ b/tests/test_nomad_north_tools.py @@ -0,0 +1,23 @@ +"""Tests for the NOMAD NORTH tool.""" + +import pytest + +try: + import nomad # noqa: F401 +except ImportError: + pytest.skip( + "Skipping NOMAD NORTH tool tests because nomad-lab is not installed", + allow_module_level=True, + ) + + +def test_importing_north_tool(): + # this will raise an exception if pydantic model validation fails for the north tool + from pynxtools_spm.nomad.north_tools.spm import ( + north_tool, + ) + + assert ( + north_tool.id_url_safe == "pynxtools_spm_spm" + or north_tool.id == "nomad-north-spm" + ), "NORTHtool entry point has incorrect id or id_url_safe" diff --git a/tests/test_reader.py b/tests/test_reader.py index f05bd25e..76075410 100644 --- a/tests/test_reader.py +++ b/tests/test_reader.py @@ -9,10 +9,10 @@ module_dir = os.path.dirname(os.path.abspath(__file__)) -ignore_lines: list = [ +ignore_lines: list[str] = [ "DEBUG - value: 20", ] -ignore_sections: dict = {} +ignore_sections: dict[str, list[str]] = {} @pytest.mark.parametrize(