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

Unit Tests #6

Merged
merged 12 commits into from
Apr 23, 2024
Merged
44 changes: 44 additions & 0 deletions .github/workflows/pull_request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,47 @@ jobs:
compilers: ''
doc_target: 'sphinx'
secrets: inherit

# PluginPlayer needs pluginplay_examples, which means PluginPlays test have to
# be built. This means that CTest will run both PluginPlayer's and
# PluginPlay's tests, which is not desired. For now, I'm running this job to
# test PluginPlayer using ctest -R to limit the tests.
# TODO: Either refactor the test to not need pluginplay_examples, refactor
# PluginPlay so that pluginplay_examples can be build without the tests,
# or refactor the common workflow to allow for regex specification.
test_library:
needs: Common-Pull-Request
runs-on: ubuntu-latest
container:
image: ghcr.io/nwchemex/nwx_buildenv:latest
credentials:
username: ${{ github.actor }}
password: ${{ secrets.CONTAINER_REPO_TOKEN }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set ownership
run: |
# Fix for git not liking owner of the checkout dir
chown -R $(id -u):$(id -g) $PWD
- name: Install requirements
run: |
pip install -r requirements.txt
shell: bash
- name: Build and Test
env:
CMAIZE_GITHUB_TOKEN: ${{secrets.CMAIZE_GITHUB_TOKEN}}
run: |
toolchain=/toolchains/nwx_gcc-11.cmake
echo 'set(CMAIZE_GITHUB_TOKEN '${CMAIZE_GITHUB_TOKEN}')' >> $toolchain

cmake -Bbuild -H. -GNinja \
-DCMAKE_INSTALL_PREFIX=./install \
-DCMAKE_TOOLCHAIN_FILE="${toolchain}"

cmake --build build --parallel

cd build
OMPI_ALLOW_RUN_AS_ROOT=1 OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1 ctest -VV -R pluginplayer
shell: bash
81 changes: 81 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# 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(pluginplayer_version "${CMAKE_CURRENT_LIST_DIR}")
project(pluginplayer VERSION "${pluginplayer_version}" LANGUAGES CXX)

include(nwx_versions)
include(get_cmaize)
include(nwx_cxx_api_docs)

### Files and Paths ###
set(python_src_directory "${CMAKE_CURRENT_LIST_DIR}/src/")

# # 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?"
)

### Tests need PluginPlay examples ##
if("${BUILD_TESTING}")
set(PP_BUILD_TARGETS pluginplay pluginplay_examples)
set(PP_FIND_TARGETS nwx::pluginplay nwx::pluginplay_depends)
set(PP_BUILD_TESTS ON)
else()
set(PP_BUILD_TARGETS pluginplay)
set(PP_FIND_TARGETS nwx::pluginplay)
set(PP_BUILD_TESTS OFF)
endif()

## Build FriendZone's dependencies ##
cmaize_find_or_build_dependency(
pluginplay
URL github.com/NWChemEx/PluginPlay
VERSION ${NWX_PLUGINPLAY_VERSION}
BUILD_TARGET ${PP_BUILD_TARGETS}
FIND_TARGET ${PP_FIND_TARGETS}
CMAKE_ARGS BUILD_TESTING=${PP_BUILD_TESTS}
BUILD_PYBIND11_PYBINDINGS=ON
)

#TOOD: Replace cmaize_add_library when it supports Python
add_library(${PROJECT_NAME} INTERFACE)
target_link_libraries(${PROJECT_NAME} INTERFACE pluginplay)

if("${BUILD_TESTING}")
include(CTest)
include(nwx_pybind11)
set(PYTHON_TEST_DIR "${CMAKE_CURRENT_LIST_DIR}/tests")

nwx_pybind11_tests(
py_${PROJECT_NAME}
"${PYTHON_TEST_DIR}/test_pluginplayer.py"
SUBMODULES pluginplay_examples pluginplay parallelzone
)
endif()

install(
DIRECTORY "${python_src_directory}/pluginplayer"
DESTINATION "${NWX_MODULE_DIRECTORY}"
)
31 changes: 31 additions & 0 deletions cmake/get_nwx_cmake.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# 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()
4 changes: 2 additions & 2 deletions src/pluginplayer/node_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,8 @@ def link_submod(self, instance):
key_name = list(node.submod_dict.keys())[key_number]
plugin_number = int(instance.id.split()[2])
submodule_number = int(instance.id.split()[3])
submodule_name = self.saved_plugins[plugin_number].modules[
submodule_number]
submodule_name = self.plugin_player.plugin_manager.saved_plugins[
plugin_number].modules[submodule_number]

try:
self.plugin_player.mm.change_submod(module_name, key_name,
Expand Down
5 changes: 4 additions & 1 deletion src/pluginplayer/node_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from kivy.uix.image import Image
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput


class DraggableImageButton(ButtonBehavior, BoxLayout):
Expand Down Expand Up @@ -199,7 +200,9 @@ def __init__(self, module, module_name):
self.module_widget = None

#holds the widget of the custom declaration of the currently selected input
self.custom_declaration_widget = None
self.custom_declaration_widget = TextInput(hint_text="ex: Force()",
size_hint_x=3 / 5,
multiline=False)

#show the mapping of inputs, outputs and submodules used for running the tree
self.input_map = []
Expand Down
9 changes: 4 additions & 5 deletions src/pluginplayer/node_widget_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,13 +219,12 @@ def view_config(self, instance):

#create an entry to declare a property type
custom_ptype = BoxLayout(orientation='horizontal', spacing=0)
text_entry = TextInput(hint_text="ex: Force()",
size_hint_x=3 / 5,
multiline=False)

if node.custom_declaration_widget.parent:
node.custom_declaration_widget.parent.remove_widget(
node.custom_declaration_widget)
#add text entry to the node's properties
node.custom_declaration_widget = text_entry
custom_ptype.add_widget(text_entry)
custom_ptype.add_widget(node.custom_declaration_widget)

#add button to set the property type
custom_entry_button = Button(
Expand Down
46 changes: 41 additions & 5 deletions src/pluginplayer/plugin_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@

#helper classes for a PluginPlayer interface
import pluginplay as pp
from plugin_manager import PluginManager
from tree_manager import TreeManager
from node_widget_manager import NodeWidgetManager
from node_manager import NodeManager
from utility_manager import UtilityManager
from pluginplayer.plugin_manager import PluginManager
from pluginplayer.tree_manager import TreeManager
from pluginplayer.node_widget_manager import NodeWidgetManager
from pluginplayer.node_manager import NodeManager
from pluginplayer.utility_manager import UtilityManager

#kivy helpers
from kivy.app import App
Expand All @@ -48,13 +48,40 @@ class PluginPlayer(App):
:rtype: kivy.app.App
"""

def test_setup(self):
Ethan5026 marked this conversation as resolved.
Show resolved Hide resolved
"""Initializes the helpers and instance variables for the PluginPlayer class for testing
"""
self.popup = Popup()

#The app's module manager
self.mm = pp.ModuleManager()

#saved tree containing the nodes and modules to be ran
self.nodes = []

#helper class handling addition/removal of nodes, deleting/running the tree
self.tree_manager = TreeManager(self)

#helper class handling the widget building for the node configuration
self.node_widget_manager = NodeWidgetManager(self)

#helper class handling the linking of inputs, submods, property types between modules
self.node_manager = NodeManager(self)

#helper class handling the loading, deleting, and viewing of plugins and their modules
self.plugin_manager = PluginManager(self)

#helper class handling browsing, imported class types, and importing new classes
self.utility_manager = UtilityManager()

#build the main window from the kv file
def build(self):
"""Builds the main window from the plugin_player_setup.kv file, and creates instances of helper classes to alter the imported plugins and tree structure.

:return: The built Kivy application
:rtype: kivy.app.App
"""

self.popup = Popup()

#The app's module manager
Expand All @@ -78,6 +105,9 @@ def build(self):
#helper class handling browsing, imported class types, and importing new classes
self.utility_manager = UtilityManager()

#string array holding the filepaths of resized images
self.resized_images = []

#build the main application from the kivy script file
build = Builder.load_file('plugin_player_setup.kv')

Expand Down Expand Up @@ -146,6 +176,12 @@ def create_image(self, filepath, new_filepath, size):
image = PILImage.open(filepath)
resized_image = image.resize(size)
resized_image.save(new_filepath)
self.resized_images.append(new_filepath)

def on_stop(self):
Ethan5026 marked this conversation as resolved.
Show resolved Hide resolved
for filepath in self.resized_images:
if os.path.exists(filepath):
os.remove(filepath)


if __name__ == "__main__":
Expand Down
11 changes: 7 additions & 4 deletions src/pluginplayer/tree_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@
"""

#helper widget classes for a draggable widget representing a module
from node_widget import DraggableImageButton, DraggableWidget, ModuleNode
from pluginplayer.node_widget import DraggableImageButton
from pluginplayer.node_widget import DraggableWidget
from pluginplayer.node_widget import ModuleNode

#kivy helpers
from kivy.uix.button import Button
Expand All @@ -49,6 +51,7 @@ def __init__(self, plugin_player):
:type plugin_player: PluginPlayer
"""
self.plugin_player = plugin_player
self.saved_outputs = []

def delete_tree(self):
"""Delete the entire tree, its edges, and nodes.
Expand Down Expand Up @@ -340,9 +343,9 @@ def run_tree(self):
self.plugin_player.add_message(run_order)

#set up the array for saving ouputs
saved_outputs = []
self.saved_outputs = []
for i in range(len(run_order)):
saved_outputs.append([])
self.saved_outputs.append([])

#run each node
for run_node in dfs_result:
Expand Down Expand Up @@ -384,7 +387,7 @@ def run_tree(self):
self.plugin_player.add_message(
f"{run_node.module_name}({nodes.index(run_node)}) Output: {output}"
)
saved_outputs[nodes.index(run_node)].append(output)
self.saved_outputs[nodes.index(run_node)].append(output)
except Exception as e:
self.plugin_player.add_message(
f"Could not run {run_node.module_name}({nodes.index(run_node)}): {e}"
Expand Down
14 changes: 8 additions & 6 deletions src/pluginplayer/utility_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ def __init__(self):
"""Initialization of the UtilityManager class
"""
self.imported_classes = []
self.custom_declaration_widget = TextInput(
hint_text="from _____ import _____",
multiline=False,
size_hint_x=9 / 10)

def browse(self, plugin_player):
"""Browse for a new file from the file system and place in entry box
Expand Down Expand Up @@ -131,13 +135,11 @@ def class_types(self, instance, plugin_player):
size_hint_y=None,
height=35,
spacing=0)
new_type_entry = TextInput(hint_text="from _____ import _____",
multiline=False,
size_hint_x=9 / 10)
new_type.add_widget(new_type_entry)

#set as global to pull from it when its submitted
self.custom_declaration_widget = new_type_entry
if self.custom_declaration_widget.parent:
self.custom_declaration_widget.parent.remove_widget(
self.custom_declaration_widget)
new_type.add_widget(self.custom_declaration_widget)

#add an import button
add_button = Button(text="Import",
Expand Down
Loading
Loading