diff --git a/.github/workflows/merge.yaml b/.github/workflows/merge.yaml index 37236af..20437ef 100644 --- a/.github/workflows/merge.yaml +++ b/.github/workflows/merge.yaml @@ -28,6 +28,24 @@ jobs: deploy_nwx_docs: uses: NWChemEx/.github/.github/workflows/deploy_nwx_docs.yaml@master with: - doc_target: "friendzone_cxx_api" - generate_module_docs: true + doc_target: "Sphinx" secrets: inherit + + # No platform_matrix / cibw_build needed: FriendZone is pure Python, so + # build_pypi_dist's plain path (cibw_build left unset) applies -- a single + # platform-independent sdist+wheel, same shape as NWXCMake's own working + # merge.yaml. + deploy_to_pypi: + needs: tag-commit + runs-on: ubuntu-latest + permissions: + id-token: write + steps: + - name: Build PyPI Distribution + uses: NWChemEx/.github/.github/actions/build_pypi_dist@master + with: + + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: dist/ diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml index 51a975b..b0dcec3 100644 --- a/.github/workflows/nightly.yaml +++ b/.github/workflows/nightly.yaml @@ -14,13 +14,16 @@ # name: Nightly Workflow +# Re-runs the same build/test jobs pull_request.yaml runs, on a schedule, to +# catch breakage that originates outside the repo (upstream dependency +# releases, refreshed GitHub runner images) rather than from a code change. +# Both callers share test_python_build.yaml, so there is nothing to keep in +# sync by hand. on: schedule: - cron: "0 6 * * *" # Every day at 06:00 UTC (00:00 CST) jobs: - test_library: - uses: NWChemEx/.github/.github/workflows/test_nwx_library.yaml@master - with: - compilers: '["gcc-14", "clang-18"]' + test_python_build: + uses: ./.github/workflows/test_python_build.yaml diff --git a/.github/workflows/pull_request.yaml b/.github/workflows/pull_request.yaml index ce1669a..5abd8c9 100644 --- a/.github/workflows/pull_request.yaml +++ b/.github/workflows/pull_request.yaml @@ -27,9 +27,9 @@ jobs: test_nwx_docs: uses: NWChemEx/.github/.github/workflows/test_nwx_docs.yaml@master with: - doc_target: "friendzone_cxx_api" + doc_target: "Sphinx" - test_library: - uses: NWChemEx/.github/.github/workflows/test_nwx_library.yaml@master - with: - compilers: '["gcc-14", "clang-18"]' + # Shared with nightly.yaml -- see that file's comments for why this repo + # doesn't use the shared test_nwx_cmake_build/test_nwx_pip_build workflows. + test_python_build: + uses: ./.github/workflows/test_python_build.yaml diff --git a/.github/workflows/test_python_build.yaml b/.github/workflows/test_python_build.yaml new file mode 100644 index 0000000..72a4ba1 --- /dev/null +++ b/.github/workflows/test_python_build.yaml @@ -0,0 +1,103 @@ +# Copyright 2026 NWChemEx-Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +name: Test Python Build +# Builds FriendZone's distribution and runs its test suite. pull_request.yaml +# and nightly.yaml both need exactly these jobs, so they live here instead of +# being duplicated in each. +# +# This is a repo-local reusable workflow rather than one of the shared +# NWChemEx/.github ones because FriendZone is pure Python (no CMakeLists.txt): +# test_nwx_cmake_build/test_nwx_pip_build both drive a scikit-build-core CMake +# build and don't apply. It isn't a composite action because the duplication +# includes the job's matrix and runs-on, which an action can't own. +# +# Callers reference it as `uses: ./.github/workflows/test_python_build.yaml`, +# which resolves at the caller's own commit -- so a PR that edits this file +# tests the edited version. + +on: + workflow_call: + +jobs: + # Dry-run of the actual sdist/wheel build (not just an editable install via + # test_python below) -- catches e.g. files missing from the sdist manifest + # that an editable install wouldn't. Matches NWXCMake's own pull_request.yaml. + test_pypi_deploy: + runs-on: ubuntu-latest + steps: + - name: Build PyPI Distribution + uses: NWChemEx/.github/.github/actions/build_pypi_dist@master + + # FriendZone is pure Python (no CMakeLists.txt), so there's nothing to + # compile and the compiler axis of the shared dev matrix is meaningless + # here -- just a lean OS-only matrix. setup_nwx_dev_env still runs (via its + # unconditional MPI/Boost install) because nwchemex-simde's prebuilt wheel + # dynamically links against libmpi at import time, and bare GitHub runners + # have no MPI by default. + test_python: + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Checkout Source + uses: actions/checkout@v4 + with: + fetch-depth: 0 + # Pinned to 3.12, not "3.x" (whatever's newest, e.g. 3.14 today): + # nwchemex-simde and its own transitive deps are only published as + # prebuilt wheels for cp312 (platform_matrix.yaml's release_matrix). + # Under a newer ambient Python, pip falls back to building those from + # source, which succeeds (setup_nwx_dev_env provides MPI/Boost/etc.) + # but produces a binary missing the rpath-bundled shared libs that + # cibuildwheel+delocate/auditwheel normally provide for the real + # published wheel, so it fails to import at runtime. + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + - name: Setup NWX Dev Environment + uses: NWChemEx/.github/.github/actions/setup_nwx_dev_env@master + with: + compiler: gcc-14 + needs_nwchem: "true" + - name: Sanity-check NWChem Is On PATH + shell: bash + run: which nwchem + - name: Install + shell: bash + run: | + # molssi/ase are optional friends (extra deps only needed if the + # corresponding external program is present); install them + # explicitly here since needs_nwchem above means this job now has + # a real NWChem to exercise both wrapper paths against, rather + # than everything just no-op'ing via is_molssi_enabled()/ + # is_ase_enabled(). + pip install -e ".[dev,molssi,ase]" + - name: Test Python + shell: bash + run: | + set +e + pytest -v + pytest_exit=$? + set -e + + if [ "$pytest_exit" -eq 5 ]; then + echo "::error::zero pytest tests were found." + exit 1 + fi + exit "$pytest_exit" diff --git a/.gitignore b/.gitignore index 23c79ec..e87a55f 100644 --- a/.gitignore +++ b/.gitignore @@ -80,3 +80,6 @@ uuid.db # This is a generated file # src/python/friendzone/friends.py + +# Automatically installed in dev mode +.pre-commit-config.yaml diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index c05c26a..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright 2022 NWChemEx-Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -cmake_minimum_required(VERSION 3.14) - -#Downloads common CMake modules used throughout NWChemEx -include(cmake/get_nwx_cmake.cmake) - -#Sets the version to whatever git thinks it is -include(get_version_from_git) -get_version_from_git(friendzone_version "${CMAKE_CURRENT_LIST_DIR}") -project(friendzone VERSION "${friendzone_version}" LANGUAGES CXX) -set(CMAKE_CXX_STANDARD 20) - -include(get_cmaize) -include(nwx_cxx_api_docs) - -### Files and Paths ### -set(python_src_directory "${CMAKE_CURRENT_LIST_DIR}/src/python") - -# # Doxygen docs -nwx_cxx_api_docs("${CMAKE_CURRENT_SOURCE_DIR}/src" "${CMAKE_CURRENT_SOURCE_DIR}/include") - -### Options ### -cmaize_option_list( - BUILD_TESTING OFF "Should we build the tests?" - BUILD_PYBIND11_PYBINDINGS ON "Use Pybind11 to build Python bindings?" - ENABLE_NWCHEM ON "Should we build support for friend: NWChem ?" - ENABLE_MOLSSI ON "Build support for the MolSSI interface?" - ENABLE_ASE ON "Build support for the Atomic Simulation Environment?" -) - -## Build FriendZone's dependencies ## -cmaize_find_or_build_dependency( - simde - URL github.com/NWChemEx/SimDE - BUILD_TARGET simde - FIND_TARGET nwx::simde - CMAKE_ARGS BUILD_TESTING=OFF - BUILD_PYBIND11_PYBINDINGS=${BUILD_PYBIND11_PYBINDINGS} -) - -## Get the CMake utilities for this project ## -set( - CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${PROJECT_SOURCE_DIR}/cmake" - CACHE STRING "" FORCE -) - -## Find friends ## -include(ase) -include(molssi) -include(nwchem) - -#TOOD: Replace cmaize_add_library when it supports Python -add_library(${PROJECT_NAME} INTERFACE) -target_link_libraries(${PROJECT_NAME} INTERFACE simde) - -if("${BUILD_TESTING}") - include(CTest) - include(nwx_pybind11) - set(PYTHON_TEST_DIR "${CMAKE_CURRENT_LIST_DIR}/tests/python") - - nwx_pybind11_tests( - py_${PROJECT_NAME} - "${PYTHON_TEST_DIR}/unit_tests/test_friendzone.py" - SUBMODULES simde chemist pluginplay parallelzone tensorwrapper - ) -endif() - -install( - DIRECTORY "${python_src_directory}/friendzone" - DESTINATION "${NWX_MODULE_DIRECTORY}" -) diff --git a/cmake/ase.cmake b/cmake/ase.cmake deleted file mode 100644 index 99d97ab..0000000 --- a/cmake/ase.cmake +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright 2024 NWChemEx-Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -include_guard() - -if("${BUILD_PYBIND11_PYBINDINGS}") - include(python/python) - - #[[[ Determines if ASE is installed. - # - # At present FriendZone can not install - #]] - function(find_ase) - assert_python_module("ase") - message(STATUS "Found ASE: ${ASE_FOUND}") - endfunction() - - if("${ENABLE_ASE}") - find_ase() - endif() -endif() diff --git a/cmake/get_nwx_cmake.cmake b/cmake/get_nwx_cmake.cmake deleted file mode 100644 index c99674d..0000000 --- a/cmake/get_nwx_cmake.cmake +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2024 NWChemEx-Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -include_guard() - -macro(get_nwx_cmake) - include(FetchContent) - FetchContent_Declare( - nwx_cmake - GIT_REPOSITORY https://github.com/NWChemEx/NWXCMake - ) - FetchContent_MakeAvailable(nwx_cmake) - set( - CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${nwx_cmake_SOURCE_DIR}/cmake" - CACHE STRING "" - FORCE - ) -endmacro() - -get_nwx_cmake() diff --git a/cmake/molssi.cmake b/cmake/molssi.cmake deleted file mode 100644 index 3341ee5..0000000 --- a/cmake/molssi.cmake +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright 2023 NWChemEx-Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -include_guard() - -if("${BUILD_PYBIND11_PYBINDINGS}") - include(python/python) - - #[[[ Determines if the MolSSI Python interface are installed. - # - # At present FriendZone can not install - #]] - function(find_molssi) - assert_python_module("qcelemental") - message(STATUS "Found qcelemental: ${QCELEMENTAL_FOUND}") - assert_python_module("qcengine") - message(STATUS "Found qcengine: ${QCENGINE_FOUND}") - assert_python_module("networkx") - message(STATUS "Found networkx: ${NETWORKX_FOUND}") - endfunction() - - if("${ENABLE_MOLSSI}") - find_molssi() - endif() -endif() diff --git a/cmake/nwchem.cmake b/cmake/nwchem.cmake deleted file mode 100644 index 26f1879..0000000 --- a/cmake/nwchem.cmake +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2023 NWChemEx-Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -include_guard() - -if("${BUILD_PYBIND11_PYBINDINGS}") - #[[[ Determines if NWChem and the necessary Python interface are installed. - # - # At present FriendZone can not install - #]] - function(find_nwchem) - find_program(NWCHEM_FOUND nwchem REQUIRED) - message(STATUS "Found nwchem: ${NWCHEM_FOUND}") - endfunction() - - if("${ENABLE_NWCHEM}") - find_nwchem() - endif() -endif() diff --git a/cmake/python/find_python.cmake b/cmake/python/find_python.cmake deleted file mode 100644 index 5a378f7..0000000 --- a/cmake/python/find_python.cmake +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright 2023 NWChemEx-Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -include_guard() - -#[[[ Wraps the process of finding the Python interpreter. -# -# At the moment this is a thin wrapper around find_package with our preffered -# options. -#]] -function(find_python) - find_package(Python COMPONENTS Interpreter QUIET REQUIRED) - message(STATUS "Found Python: ${Python_EXECUTABLE}") -endfunction() - -find_python() diff --git a/cmake/python/find_python_module.cmake b/cmake/python/find_python_module.cmake deleted file mode 100644 index 426584e..0000000 --- a/cmake/python/find_python_module.cmake +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright 2023 NWChemEx-Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -include_guard() - -#[[[ Attempts to find a Python module, returns whether it was found or not. -# -# This function will invoke the pip module through the Python interpreter and -# see if the specified module appears in the list of installed modules. The -# result of this inquiry is then returned -# -# :param was_found: Used to return the result -# :type was_found: *bool -# :param module_name: The name of the Python module to look for. -# :type module_name: str -#]] -function(find_python_module fpm_was_found fpm_module_name) - execute_process( - COMMAND "${Python_EXECUTABLE}" "-m" "pip" "list" - COMMAND grep -w "${fpm_module_name}" - OUTPUT_VARIABLE _fpm_modules - ) - if("${_fpm_modules}" STREQUAL "") - set("${fpm_was_found}" FALSE PARENT_SCOPE) - else() - set("${fpm_was_found}" TRUE PARENT_SCOPE) - endif() -endfunction() - -#[[[ Raises a fatal error if a Python module is not installed. -# -# This function is a thin wrapper around ``find_python_module`` that asserts -# that the return value of ``find_python_module`` is TRUE. If the value -# returned from ``find_python_module`` is not TRUE this function will raise -# a fatal error. -# -# :param module_name: The name of the Python module which must be installed. -# :type module_name: str -#]] -function(assert_python_module apm_module_name) - find_python_module(_apm_was_found "${apm_module_name}") - if(NOT "${_apm_was_found}") - message( - FATAL_ERROR - "Unable to locate Python module: ${apm_module_name}" - ) - endif() -endfunction() diff --git a/cmake/python/python.cmake b/cmake/python/python.cmake deleted file mode 100644 index 9a4b7f8..0000000 --- a/cmake/python/python.cmake +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright 2023 NWChemEx-Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -include_guard() -include(python/find_python) -include(python/find_python_module) diff --git a/docs/source/conf.py b/docs/source/conf.py index 34aa938..63124e2 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -173,7 +173,7 @@ # -- Extension configuration ------------------------------------------------- autoapi_dirs = [ - "../../src", + "../../python", # '../../tests', ] autoapi_add_toctree_entry = False diff --git a/pyproject.toml b/pyproject.toml index 7e50ebe..3fafe29 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,35 +12,18 @@ # See the License for the specific language governing permissions and # limitations under the License. -# This file defines the pip-installable Python package. - [build-system] -requires = ["setuptools>=46.1.0", "setuptools_scm[toml]>=5"] +requires = ["setuptools>=64", "setuptools-scm>=8"] build-backend = "setuptools.build_meta" -[tool.setuptools_scm] -# For smarter version schemes and other configuration options, -# check out https://github.com/pypa/setuptools_scm -version_scheme = "no-guess-dev" - -# To create a pip-installable package that uses CMake in the backend, -# scikit-build-core is used as the build backend, recommended by Pybind11. -# -# scikit-build-core: https://scikit-build-core.readthedocs.io/en/latest/ -# Pybind11 scikit-build-core example: https://github.com/pybind/scikit_build_example -# [build-system] -# requires = ["scikit-build-core>=0.11", "pybind11>=3.0"] -# build-backend = "scikit_build_core.build" - - [project] -name = "friendzone" -license = "Apache-2.0" -license-files = ["LICENSE"] +name = "nwchemex-friendzone" description = "Provides SimDE compatible APIs so that NWChemEx can play nicely with its friends." readme = "README.md" +license = "Apache-2.0" +license-files = ["LICENSE"] authors = [ - { name = "zachcran", email = "zachcran@iastate.edu" }, + { name = "zachcran", email = "zachcran@iastate.edu" }, { name = "jwaldrop107", email = "jwaldrop@ameslab.gov" }, ] requires-python = ">=3.10" @@ -52,40 +35,36 @@ classifiers = [ "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", - "Private :: Do Not Upload", ] -# Dynamic project attributes -# -# Set the project version dynamically according to git tags. -# Git tag version info: https://github.com/pypa/setuptools-scm/blob/fb261332d9b46aa5a258042d85baa5aa7b9f4fa2/README.rst#default-versioning-scheme dynamic = ["version"] -# NOTE: Invisible dependency for now until Python bindings at SimDE are -# packaged properly and available here -# dependencies = ["simde"] - +dependencies = ["nwchemex-simde>=0.0.77"] -[tool.setuptools] -# Cannot automatically find the friendzone namespace so we set it here -package-dir = { "" = "src/python" } - -# Optional dependencies represent optional features that can be enabled -# during installation -# Example: pip install friendzone[ase] [project.optional-dependencies] -ase = ["ase"] +ase = ["ase"] molssi = ["qcengine", "qcelemental", "networkx"] +test = ["pytest", "numpy"] +dev = ["nwchemex-friendzone[test]", "tox", "pre-commit"] + +# Python source lives under python/ (analogous to cxx/ in C++ repos). +[tool.setuptools.packages.find] +where = ["python"] -# Dependency groups are optional dependencies that are not intented to appear -# after packaging, usually used to help with testing or development -# Example: pip install --group dev -[dependency-groups] -test = ["pytest"] -dev = [{ include-group = "test" }, "tox", "pre-commit"] +[tool.setuptools_scm] +fallback_version = "0.0.0" [tool.pytest.ini_options] minversion = "8.0" addopts = ["-ra", "--showlocals", "--strict-markers", "--strict-config"] xfail_strict = true log_cli_level = "INFO" -filterwarnings = ["error", "ignore::pytest.PytestCacheWarning"] +filterwarnings = [ + "error", + "ignore::pytest.PytestCacheWarning", + # ase's own Atoms.new_array (ase/atoms.py) still does `a.shape = (-1,) + # + shape` on an empty array, which numpy >=2.5 deprecates in favor of + # np.reshape. Unrelated to anything NWChemEx-side; ase's own bug, not + # ours to fix -- ignore rather than let it hard-fail every ASE-backed + # friend test. + "ignore:Setting the shape on a NumPy array has been deprecated:DeprecationWarning:ase\\..*", +] testpaths = ["tests"] diff --git a/src/python/friendzone/__init__.py b/python/friendzone/__init__.py similarity index 100% rename from src/python/friendzone/__init__.py rename to python/friendzone/__init__.py diff --git a/src/python/friendzone/friends.py b/python/friendzone/friends.py similarity index 100% rename from src/python/friendzone/friends.py rename to python/friendzone/friends.py diff --git a/src/python/friendzone/nwx2ase/__init__.py b/python/friendzone/nwx2ase/__init__.py similarity index 100% rename from src/python/friendzone/nwx2ase/__init__.py rename to python/friendzone/nwx2ase/__init__.py diff --git a/src/python/friendzone/nwx2ase/chemical_system_conversions.py b/python/friendzone/nwx2ase/chemical_system_conversions.py similarity index 100% rename from src/python/friendzone/nwx2ase/chemical_system_conversions.py rename to python/friendzone/nwx2ase/chemical_system_conversions.py diff --git a/src/python/friendzone/nwx2ase/nwchem_via_ase.py b/python/friendzone/nwx2ase/nwchem_via_ase.py similarity index 100% rename from src/python/friendzone/nwx2ase/nwchem_via_ase.py rename to python/friendzone/nwx2ase/nwchem_via_ase.py diff --git a/src/python/friendzone/nwx2molssi/__init__.py b/python/friendzone/nwx2molssi/__init__.py similarity index 100% rename from src/python/friendzone/nwx2molssi/__init__.py rename to python/friendzone/nwx2molssi/__init__.py diff --git a/src/python/friendzone/nwx2molssi/call_qcengine.py b/python/friendzone/nwx2molssi/call_qcengine.py similarity index 100% rename from src/python/friendzone/nwx2molssi/call_qcengine.py rename to python/friendzone/nwx2molssi/call_qcengine.py diff --git a/src/python/friendzone/nwx2molssi/chemical_system_conversions.py b/python/friendzone/nwx2molssi/chemical_system_conversions.py similarity index 100% rename from src/python/friendzone/nwx2molssi/chemical_system_conversions.py rename to python/friendzone/nwx2molssi/chemical_system_conversions.py diff --git a/src/python/friendzone/nwx2molssi/nwchem_via_molssi.py b/python/friendzone/nwx2molssi/nwchem_via_molssi.py similarity index 98% rename from src/python/friendzone/nwx2molssi/nwchem_via_molssi.py rename to python/friendzone/nwx2molssi/nwchem_via_molssi.py index 124b250..ef82619 100644 --- a/src/python/friendzone/nwx2molssi/nwchem_via_molssi.py +++ b/python/friendzone/nwx2molssi/nwchem_via_molssi.py @@ -124,7 +124,7 @@ def load_nwchem_via_molssi_modules(mm): """ if is_nwchem_enabled(): for method in ["SCF", "B3LYP", "MP2", "CCSD", "CCSD(T)"]: - egy_key = "nwchem" + " : " + method + egy_key = "NWChem" + " : " + method grad_key = egy_key + " Gradient" mm.add_module(egy_key, QCEngineEnergy()) mm.add_module(grad_key, QCEngineGradient()) diff --git a/src/python/friendzone/nwx2molssi/system_via_molssi.py b/python/friendzone/nwx2molssi/system_via_molssi.py similarity index 100% rename from src/python/friendzone/nwx2molssi/system_via_molssi.py rename to python/friendzone/nwx2molssi/system_via_molssi.py diff --git a/src/python/friendzone/utils/__init__.py b/python/friendzone/utils/__init__.py similarity index 100% rename from src/python/friendzone/utils/__init__.py rename to python/friendzone/utils/__init__.py diff --git a/src/python/friendzone/utils/unwrap_inputs.py b/python/friendzone/utils/unwrap_inputs.py similarity index 100% rename from src/python/friendzone/utils/unwrap_inputs.py rename to python/friendzone/utils/unwrap_inputs.py diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 1fd6065..0000000 --- a/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -ase -networkx -pydantic>=1.10.13 -qcengine diff --git a/tests/python/conftest.py b/tests/python/conftest.py new file mode 100644 index 0000000..d9c5a96 --- /dev/null +++ b/tests/python/conftest.py @@ -0,0 +1,35 @@ +# +# Copyright 2026 NWChemEx-Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import parallelzone as pz +import pytest + + +@pytest.fixture(scope="session", autouse=True) +def _session_runtime_view(): + """ + Holds a single RuntimeView for the whole pytest session. + + MPI may only be initialized/finalized once per process. The first + RuntimeView constructed owns that responsibility; individual test + modules construct their own RuntimeView per test (e.g. in setUp), + which is safe only as long as this session-scoped instance is still + alive to keep MPI initialized in between. Without this, pytest would + run each test module independently and MPI would be finalized after + the first module's tests finished, breaking every module after it. + """ + rv = pz.runtime.RuntimeView() + yield rv diff --git a/tests/python/unit_tests/test_friendzone.py b/tests/python/unit_tests/test_friendzone.py deleted file mode 100644 index 980b434..0000000 --- a/tests/python/unit_tests/test_friendzone.py +++ /dev/null @@ -1,35 +0,0 @@ -# -# Copyright 2023 NWChemEx-Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -import os -import sys -import unittest - -import parallelzone as pz - -if __name__ == "__main__": - rv = pz.runtime.RuntimeView() - - my_dir = os.path.dirname(os.path.realpath(__file__)) - root_dir = os.path.dirname(os.path.dirname(os.path.dirname(my_dir))) - src_dir = os.path.join(root_dir, "src", "python") - sys.path.append(src_dir) - - loader = unittest.TestLoader() - tests = loader.discover(my_dir) - testrunner = unittest.runner.TextTestRunner() - ret = not testrunner.run(tests).wasSuccessful() - sys.exit(ret)