From 2eb43d1941338b0629925d1f9f872b2dfd5318d2 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Mon, 2 Dec 2024 13:53:10 -0700 Subject: [PATCH 01/17] Add pythonplugin:searchpaths object to idd. --- resources/model/OpenStudio.idd | 47 ++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/resources/model/OpenStudio.idd b/resources/model/OpenStudio.idd index edffc20040..3a6a323995 100644 --- a/resources/model/OpenStudio.idd +++ b/resources/model/OpenStudio.idd @@ -38660,6 +38660,53 @@ OS:EnergyManagementSystem:ConstructionIndexVariable, \group Python Plugin System +OS:PythonPlugin:SearchPaths, + \memo Add directories to the search path for Python plugin modules + \memo The directory containing the EnergyPlus executable file is + \memo automatically added so that the Python interpreter can find the + \memo packaged up pyenergyplus Python package. + \memo By default, the current working directory and input file directory + \memo are also added to the search path. However, this object allows + \memo modifying this behavior. With this object, searching these directories + \memo can be disabled, and users can add supplemental search paths + \memo that point to libraries of plugin scripts. + \unique-object + \min-fields 3 + \extensible:1 + A1, \field Handle + \type handle + \required-field + A2, \field Add Current Working Directory to Search Path + \note Adding the current working directory allows Python to find + \note plugin scripts in the current directory. + \note required-field disabled as it has a default + \type choice + \key Yes + \key No + \required-field + A3, \field Add Input File Directory to Search Path + \note Enabling this will allow Python to find plugin scripts in the + \note same directory as the running input file, even if that is not + \note the current working directory. + \note required-field disabled as it has a default + \type choice + \key Yes + \key No + \required-field + A4, \field Add epin Environment Variable to Search Path + \note The "epin" environment variable is set by some EnergyPlus interfaces + \note in order to let EnergyPlus find external files in special locations. + \note If this is enabled, and that variable is set, the value of the variable + \note will be added to the Python search path. + \type choice + \key Yes + \key No + \required-field + A5; \field Search Path 1 + \type alpha + \begin-extensible + \retaincase + OS:PythonPlugin:Instance, \memo A single plugin to be executed during the simulation, which can contain multiple calling points \memo for the same class instance by overriding multiple calling point methods. From 541c80e389d3e9f3b234f551253a4b6ac00ce60f Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Wed, 4 Dec 2024 15:13:00 -0700 Subject: [PATCH 02/17] Generate pythonpluginsearchpaths class with script. --- ...orwardTranslatePythonPluginSearchPaths.cpp | 86 +++++++++++ ...everseTranslatePythonPluginSearchPaths.cpp | 90 ++++++++++++ .../Test/PythonPluginSearchPaths_GTest.cpp | 95 ++++++++++++ src/model/PythonPluginSearchPaths.cpp | 139 ++++++++++++++++++ src/model/PythonPluginSearchPaths.hpp | 117 +++++++++++++++ src/model/PythonPluginSearchPaths_Impl.hpp | 109 ++++++++++++++ .../test/PythonPluginSearchPaths_GTest.cpp | 63 ++++++++ 7 files changed, 699 insertions(+) create mode 100644 src/energyplus/ForwardTranslator/ForwardTranslatePythonPluginSearchPaths.cpp create mode 100644 src/energyplus/ReverseTranslator/ReverseTranslatePythonPluginSearchPaths.cpp create mode 100644 src/energyplus/Test/PythonPluginSearchPaths_GTest.cpp create mode 100644 src/model/PythonPluginSearchPaths.cpp create mode 100644 src/model/PythonPluginSearchPaths.hpp create mode 100644 src/model/PythonPluginSearchPaths_Impl.hpp create mode 100644 src/model/test/PythonPluginSearchPaths_GTest.cpp diff --git a/src/energyplus/ForwardTranslator/ForwardTranslatePythonPluginSearchPaths.cpp b/src/energyplus/ForwardTranslator/ForwardTranslatePythonPluginSearchPaths.cpp new file mode 100644 index 0000000000..3e6be35a4f --- /dev/null +++ b/src/energyplus/ForwardTranslator/ForwardTranslatePythonPluginSearchPaths.cpp @@ -0,0 +1,86 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) 2008-2023, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +* following conditions are met: +* +* (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following +* disclaimer. +* +* (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided with the distribution. +* +* (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products +* derived from this software without specific prior written permission from the respective party. +* +* (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works +* may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior +* written permission from Alliance for Sustainable Energy, LLC. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED +* STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +***********************************************************************************************************************/ + +#include "../ForwardTranslator.hpp" +#include "../../model/Model.hpp" + +#include "../../model/PythonPluginSearchPaths.hpp" + +#include +#include + +using namespace openstudio::model; + +namespace openstudio { + +namespace energyplus { + + boost::optional ForwardTranslator::translatePythonPluginSearchPaths( model::PythonPluginSearchPaths& modelObject ) { + + // Instantiate an IdfObject of the class to store the values + IdfObject idfObject = createRegisterAndNameIdfObject(openstudio::IddObjectType::PythonPlugin_SearchPaths, modelObject); + // If it doesn't have a name, or if you aren't sure you are going to want to return it + // IdfObject idfObject(openstudio::IddObjectType::PythonPlugin_SearchPaths); + // m_idfObjects.push_back(idfObject); + + // TODO: Note JM 2018-10-17 + // You are responsible for implementing any additional logic based on choice fields, etc. + // The ForwardTranslator generator script is meant to facilitate your work, not get you 100% of the way + + // TODO: If you keep createRegisterAndNameIdfObject above, you don't need this. + // But in some cases, you'll want to handle failure without pushing to the map + // Name + idfObject.setName(modelObject.nameString()); + + // Add Current Working Directory to Search Path: Optional Boolean + if (modelObject.addCurrentWorkingDirectorytoSearchPath()) { + idfObject.setString(PythonPlugin_SearchPathsFields::AddCurrentWorkingDirectorytoSearchPath, "Yes"); + } else { + idfObject.setString(PythonPlugin_SearchPathsFields::AddCurrentWorkingDirectorytoSearchPath, "No"); + } + + // Add Input File Directory to Search Path: Optional Boolean + if (modelObject.addInputFileDirectorytoSearchPath()) { + idfObject.setString(PythonPlugin_SearchPathsFields::AddInputFileDirectorytoSearchPath, "Yes"); + } else { + idfObject.setString(PythonPlugin_SearchPathsFields::AddInputFileDirectorytoSearchPath, "No"); + } + + // Add epin Environment Variable to Search Path: Optional Boolean + if (modelObject.addepinEnvironmentVariabletoSearchPath()) { + idfObject.setString(PythonPlugin_SearchPathsFields::AddepinEnvironmentVariabletoSearchPath, "Yes"); + } else { + idfObject.setString(PythonPlugin_SearchPathsFields::AddepinEnvironmentVariabletoSearchPath, "No"); + } + + return idfObject; + } // End of translate function + +} // end namespace energyplus +} // end namespace openstudio diff --git a/src/energyplus/ReverseTranslator/ReverseTranslatePythonPluginSearchPaths.cpp b/src/energyplus/ReverseTranslator/ReverseTranslatePythonPluginSearchPaths.cpp new file mode 100644 index 0000000000..108f5d024c --- /dev/null +++ b/src/energyplus/ReverseTranslator/ReverseTranslatePythonPluginSearchPaths.cpp @@ -0,0 +1,90 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) 2008-2023, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +* following conditions are met: +* +* (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following +* disclaimer. +* +* (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided with the distribution. +* +* (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products +* derived from this software without specific prior written permission from the respective party. +* +* (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works +* may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior +* written permission from Alliance for Sustainable Energy, LLC. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED +* STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +***********************************************************************************************************************/ + +#include "../ReverseTranslator.hpp" + +#include "../../model/PythonPluginSearchPaths.hpp" + +#include +#include + +using namespace openstudio::model; + +namespace openstudio { + +namespace energyplus { + + boost::optional ReverseTranslator::translatePythonPluginSearchPaths(const WorkspaceObject & workspaceObject) { + + // Instantiate an object of the class to store the values, + // but we don't return it until we know it's ok + // TODO: check constructor, it might need other objects + openstudio::model::PythonPluginSearchPaths modelObject(m_model); + + // TODO: Note JM 2018-10-17 + // You are responsible for implementing any additional logic based on choice fields, etc. + // The ReverseTranslator generator script is meant to facilitate your work, not get you 100% of the way + + // Name + if (boost::optional name_ = workspaceObject.name()) { + modelObject.setName(name_.get()); + } + + // Add Current Working Directory to Search Path: Optional Boolean + if (boost::optional addCurrentWorkingDirectorytoSearchPath_ = getString(PythonPlugin_SearchPathsFields::AddCurrentWorkingDirectorytoSearchPath, true)) { + if(istringEqual("Yes", addCurrentWorkingDirectorytoSearchPath_.get())) { + modelObject.setAddCurrentWorkingDirectorytoSearchPath(true); + } else { + modelObject.setAddCurrentWorkingDirectorytoSearchPath(false); + } + } + + // Add Input File Directory to Search Path: Optional Boolean + if (boost::optional addInputFileDirectorytoSearchPath_ = getString(PythonPlugin_SearchPathsFields::AddInputFileDirectorytoSearchPath, true)) { + if(istringEqual("Yes", addInputFileDirectorytoSearchPath_.get())) { + modelObject.setAddInputFileDirectorytoSearchPath(true); + } else { + modelObject.setAddInputFileDirectorytoSearchPath(false); + } + } + + // Add epin Environment Variable to Search Path: Optional Boolean + if (boost::optional addepinEnvironmentVariabletoSearchPath_ = getString(PythonPlugin_SearchPathsFields::AddepinEnvironmentVariabletoSearchPath, true)) { + if(istringEqual("Yes", addepinEnvironmentVariabletoSearchPath_.get())) { + modelObject.setAddepinEnvironmentVariabletoSearchPath(true); + } else { + modelObject.setAddepinEnvironmentVariabletoSearchPath(false); + } + } + + return modelObject; + } // End of translate function + +} // end namespace energyplus +} // end namespace openstudio diff --git a/src/energyplus/Test/PythonPluginSearchPaths_GTest.cpp b/src/energyplus/Test/PythonPluginSearchPaths_GTest.cpp new file mode 100644 index 0000000000..71cd758e16 --- /dev/null +++ b/src/energyplus/Test/PythonPluginSearchPaths_GTest.cpp @@ -0,0 +1,95 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) 2008-2023, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +* following conditions are met: +* +* (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following +* disclaimer. +* +* (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided with the distribution. +* +* (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products +* derived from this software without specific prior written permission from the respective party. +* +* (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works +* may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior +* written permission from Alliance for Sustainable Energy, LLC. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED +* STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +***********************************************************************************************************************/ + +#include +#include "EnergyPlusFixture.hpp" + +#include "../ForwardTranslator.hpp" +#include "../ReverseTranslator.hpp" + +#include "../../model/PythonPluginSearchPaths.hpp" +#include "../../model/PythonPluginSearchPaths_Impl.hpp" + +#include "../../utilities/idf/Workspace.hpp" +#include "../../utilities/idf/IdfObject.hpp" +#include "../../utilities/idf/WorkspaceObject.hpp" +// E+ FieldEnums +#include +#include +#include +using namespace openstudio::energyplus; +using namespace openstudio::model; +using namespace openstudio; + +TEST_F(EnergyPlusFixture, ForwardTranslator_PythonPluginSearchPaths) { + + ForwardTranslator ft; + + Model m; + // TODO: Check regular Ctor arguments + PythonPluginSearchPaths pythonPluginSearchPaths(m); + // TODO: Or if a UniqueModelObject (and make sure _Impl is included) + // PythonPluginSearchPaths pythonPluginSearchPaths = m.getUniqueModelObject(); + + pythonPluginSearchPaths.setName("My PythonPluginSearchPaths"); + EXPECT_TRUE(pythonPluginSearchPaths.setAddCurrentWorkingDirectorytoSearchPath(false)); // Opposite from IDD default + EXPECT_TRUE(pythonPluginSearchPaths.setAddInputFileDirectorytoSearchPath(false)); // Opposite from IDD default + EXPECT_TRUE(pythonPluginSearchPaths.setAddepinEnvironmentVariabletoSearchPath(false)); // Opposite from IDD default + + + // TODO: you're responsible for creating all other objects needed so this object actually gets ForwardTranslated + + const Workspace w = ft.translateModel(m); + const auto idfObjs = w.getObjectsByType(IddObjectType::PythonPlugin_SearchPaths); + ASSERT_EQ(1u, idfObjs.size()); + + const auto& idfObject = idfObjs.front(); + EXPECT_EQ("No", idfObject.getString(PythonPlugin_SearchPathsFields::AddCurrentWorkingDirectorytoSearchPath).get()); EXPECT_EQ("No", idfObject.getString(PythonPlugin_SearchPathsFields::AddInputFileDirectorytoSearchPath).get()); EXPECT_EQ("No", idfObject.getString(PythonPlugin_SearchPathsFields::AddepinEnvironmentVariabletoSearchPath).get()); +} +TEST_F(EnergyPlusFixture, ReverseTranslator_PythonPluginSearchPaths) { + + ReverseTranslator rt; + + Workspace w(StrictnessLevel::Minimal, IddFileType::EnergyPlus); + + auto woPPSP = w.addObject(IdfObject(IddObjectType::PythonPlugin_SearchPaths)).get(); + + woPPSP.setName("My PythonPluginSearchPaths"); + EXPECT_TRUE(woPPSP.setString(PythonPlugin_SearchPathsFields::AddCurrentWorkingDirectorytoSearchPath, "No")); // Opposite from IDD default + EXPECT_TRUE(woPPSP.setString(PythonPlugin_SearchPathsFields::AddInputFileDirectorytoSearchPath, "No")); // Opposite from IDD default + EXPECT_TRUE(woPPSP.setString(PythonPlugin_SearchPathsFields::AddepinEnvironmentVariabletoSearchPath, "No")); // Opposite from IDD default + + + const Model m = rt.translateWorkspace(w); + const auto modelObjects = m.getConcreteModelObjects(); + ASSERT_EQ(1u, modelObjects.size()); + + const auto& modelObject = modelObjects.front(); + EXPECT_FALSE(modelObject.addCurrentWorkingDirectorytoSearchPath()); EXPECT_FALSE(modelObject.addInputFileDirectorytoSearchPath()); EXPECT_FALSE(modelObject.addepinEnvironmentVariabletoSearchPath()); +} diff --git a/src/model/PythonPluginSearchPaths.cpp b/src/model/PythonPluginSearchPaths.cpp new file mode 100644 index 0000000000..3c1df08fd4 --- /dev/null +++ b/src/model/PythonPluginSearchPaths.cpp @@ -0,0 +1,139 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) 2008-2023, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +* following conditions are met: +* +* (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following +* disclaimer. +* +* (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided with the distribution. +* +* (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products +* derived from this software without specific prior written permission from the respective party. +* +* (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works +* may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior +* written permission from Alliance for Sustainable Energy, LLC. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED +* STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +***********************************************************************************************************************/ + +#include "PythonPluginSearchPaths.hpp" +#include "PythonPluginSearchPaths_Impl.hpp" + +#include "../utilities/core/Assert.hpp" + +#include +#include + +namespace openstudio { +namespace model { + + namespace detail { + + PythonPluginSearchPaths_Impl::PythonPluginSearchPaths_Impl(const IdfObject& idfObject, + Model_Impl* model, bool keepHandle) + : ParentObject_Impl(idfObject, model, keepHandle) { + OS_ASSERT(idfObject.iddObject().type() == PythonPluginSearchPaths::iddObjectType()); + } + + PythonPluginSearchPaths_Impl::PythonPluginSearchPaths_Impl(const openstudio::detail::WorkspaceObject_Impl& other, + Model_Impl* model, bool keepHandle) + : ParentObject_Impl(other, model, keepHandle) { + OS_ASSERT(other.iddObject().type() == PythonPluginSearchPaths::iddObjectType()); + } + + PythonPluginSearchPaths_Impl::PythonPluginSearchPaths_Impl(const PythonPluginSearchPaths_Impl& other, + Model_Impl* model, bool keepHandle) + : ParentObject_Impl(other, model, keepHandle) {} + + const std::vector& PythonPluginSearchPaths_Impl::outputVariableNames() const { + static std::vector result; + if (result.empty()){ + } + return result; + } + + IddObjectType PythonPluginSearchPaths_Impl::iddObjectType() const { + return PythonPluginSearchPaths::iddObjectType(); + } + + bool PythonPluginSearchPaths_Impl::addCurrentWorkingDirectorytoSearchPath() const { + return getBooleanFieldValue(OS_PythonPlugin_SearchPathsFields::AddCurrentWorkingDirectorytoSearchPath); + } + + bool PythonPluginSearchPaths_Impl::addInputFileDirectorytoSearchPath() const { + return getBooleanFieldValue(OS_PythonPlugin_SearchPathsFields::AddInputFileDirectorytoSearchPath); + } + + bool PythonPluginSearchPaths_Impl::addepinEnvironmentVariabletoSearchPath() const { + return getBooleanFieldValue(OS_PythonPlugin_SearchPathsFields::AddepinEnvironmentVariabletoSearchPath); + } + + bool PythonPluginSearchPaths_Impl::setAddCurrentWorkingDirectorytoSearchPath(bool addCurrentWorkingDirectorytoSearchPath) { + const bool result = setBooleanFieldValue(OS_PythonPlugin_SearchPathsFields::AddCurrentWorkingDirectorytoSearchPath, addCurrentWorkingDirectorytoSearchPath); + OS_ASSERT(result); + return result; + } + + bool PythonPluginSearchPaths_Impl::setAddInputFileDirectorytoSearchPath(bool addInputFileDirectorytoSearchPath) { + const bool result = setBooleanFieldValue(OS_PythonPlugin_SearchPathsFields::AddInputFileDirectorytoSearchPath, addInputFileDirectorytoSearchPath); + OS_ASSERT(result); + return result; + } + + bool PythonPluginSearchPaths_Impl::setAddepinEnvironmentVariabletoSearchPath(bool addepinEnvironmentVariabletoSearchPath) { + const bool result = setBooleanFieldValue(OS_PythonPlugin_SearchPathsFields::AddepinEnvironmentVariabletoSearchPath, addepinEnvironmentVariabletoSearchPath); + OS_ASSERT(result); + return result; + } + + } // namespace detail + + IddObjectType PythonPluginSearchPaths::iddObjectType() { + return {IddObjectType::OS_PythonPlugin_SearchPaths}; + } + + bool PythonPluginSearchPaths::addCurrentWorkingDirectorytoSearchPath() const { + return getImpl()->addCurrentWorkingDirectorytoSearchPath(); + } + + bool PythonPluginSearchPaths::addInputFileDirectorytoSearchPath() const { + return getImpl()->addInputFileDirectorytoSearchPath(); + } + + bool PythonPluginSearchPaths::addepinEnvironmentVariabletoSearchPath() const { + return getImpl()->addepinEnvironmentVariabletoSearchPath(); + } + + bool PythonPluginSearchPaths::setAddCurrentWorkingDirectorytoSearchPath(bool addCurrentWorkingDirectorytoSearchPath) { + return getImpl()->setAddCurrentWorkingDirectorytoSearchPath(addCurrentWorkingDirectorytoSearchPath); + } + + bool PythonPluginSearchPaths::setAddInputFileDirectorytoSearchPath(bool addInputFileDirectorytoSearchPath) { + return getImpl()->setAddInputFileDirectorytoSearchPath(addInputFileDirectorytoSearchPath); + } + + bool PythonPluginSearchPaths::setAddepinEnvironmentVariabletoSearchPath(bool addepinEnvironmentVariabletoSearchPath) { + return getImpl()->setAddepinEnvironmentVariabletoSearchPath(addepinEnvironmentVariabletoSearchPath); + } + + /// @cond + PythonPluginSearchPaths::PythonPluginSearchPaths( + std::shared_ptr impl) + : ParentObject(std::move(impl)) {} + PythonPluginSearchPaths::PythonPluginSearchPaths(Model& model) + : ParentObject(PythonPluginSearchPaths::iddObjectType(), model) {} + /// @endcond + +} // namespace model +} // namespace openstudio diff --git a/src/model/PythonPluginSearchPaths.hpp b/src/model/PythonPluginSearchPaths.hpp new file mode 100644 index 0000000000..79f94f7bb1 --- /dev/null +++ b/src/model/PythonPluginSearchPaths.hpp @@ -0,0 +1,117 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) 2008-2023, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +* following conditions are met: +* +* (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following +* disclaimer. +* +* (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided with the distribution. +* +* (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products +* derived from this software without specific prior written permission from the respective party. +* +* (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works +* may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior +* written permission from Alliance for Sustainable Energy, LLC. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED +* STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +***********************************************************************************************************************/ + +#ifndef MODEL_PYTHONPLUGINSEARCHPATHS_HPP +#define MODEL_PYTHONPLUGINSEARCHPATHS_HPP + +#include +#include "ParentObject.hpp" + +namespace openstudio { +namespace model { + + namespace detail { + + class PythonPluginSearchPaths_Impl; + + } // namespace detail + + /** PythonPluginSearchPaths is a ParentObject that wraps the OpenStudio IDD object 'OS:PythonPlugin:SearchPaths'. */ + class MODEL_API PythonPluginSearchPaths : public ParentObject + { + public: + /** @name Constructors and Destructors */ + //@{ + + virtual ~PythonPluginSearchPaths() = default; + // Default the copy and move operators because the virtual dtor is explicit + PythonPluginSearchPaths(const PythonPluginSearchPaths& other) = default; + PythonPluginSearchPaths(PythonPluginSearchPaths&& other) = default; + PythonPluginSearchPaths& operator=(const PythonPluginSearchPaths&) = default; + PythonPluginSearchPaths& operator=(PythonPluginSearchPaths&&) = default; + + //@} + + static IddObjectType iddObjectType(); + + /** @name Getters */ + //@{ + + bool addCurrentWorkingDirectorytoSearchPath() const; + + bool addInputFileDirectorytoSearchPath() const; + + bool addepinEnvironmentVariabletoSearchPath() const; + + // TODO: Handle this object's extensible fields. + + //@} + /** @name Setters */ + //@{ + + bool setAddCurrentWorkingDirectorytoSearchPath(bool addCurrentWorkingDirectorytoSearchPath); + + bool setAddInputFileDirectorytoSearchPath(bool addInputFileDirectorytoSearchPath); + + bool setAddepinEnvironmentVariabletoSearchPath(bool addepinEnvironmentVariabletoSearchPath); + + // TODO: Handle this object's extensible fields. + + //@} + /** @name Other */ + //@{ + + //@} + protected: + /// @cond + using ImplType = detail::PythonPluginSearchPaths_Impl; + + explicit PythonPluginSearchPaths(std::shared_ptr impl); + + friend class detail::PythonPluginSearchPaths_Impl; + friend class Model; + friend class IdfObject; + friend class openstudio::detail::IdfObject_Impl; + explicit PythonPluginSearchPaths(Model& model); + + /// @endcond + private: + REGISTER_LOGGER("openstudio.model.PythonPluginSearchPaths"); + }; + + /** \relates PythonPluginSearchPaths*/ + using OptionalPythonPluginSearchPaths = boost::optional; + + /** \relates PythonPluginSearchPaths*/ + using PythonPluginSearchPathsVector = std::vector; + +} // namespace model +} // namespace openstudio + +#endif // MODEL_PYTHONPLUGINSEARCHPATHS_HPP diff --git a/src/model/PythonPluginSearchPaths_Impl.hpp b/src/model/PythonPluginSearchPaths_Impl.hpp new file mode 100644 index 0000000000..9c6dbeef44 --- /dev/null +++ b/src/model/PythonPluginSearchPaths_Impl.hpp @@ -0,0 +1,109 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) 2008-2023, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +* following conditions are met: +* +* (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following +* disclaimer. +* +* (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided with the distribution. +* +* (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products +* derived from this software without specific prior written permission from the respective party. +* +* (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works +* may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior +* written permission from Alliance for Sustainable Energy, LLC. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED +* STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +***********************************************************************************************************************/ + +#ifndef MODEL_PYTHONPLUGINSEARCHPATHS_IMPL_HPP +#define MODEL_PYTHONPLUGINSEARCHPATHS_IMPL_HPP + +#include +#include "ParentObject_Impl.hpp" + +namespace openstudio { +namespace model { + + namespace detail { + + /** PythonPluginSearchPaths_Impl is a ParentObject_Impl that is the implementation class for PythonPluginSearchPaths.*/ + class MODEL_API PythonPluginSearchPaths_Impl : public ParentObject_Impl + { + public: + /** @name Constructors and Destructors */ + //@{ + + PythonPluginSearchPaths_Impl(const IdfObject& idfObject, + Model_Impl* model, + bool keepHandle); + + PythonPluginSearchPaths_Impl(const openstudio::detail::WorkspaceObject_Impl& other, + Model_Impl* model, + bool keepHandle); + + PythonPluginSearchPaths_Impl(const PythonPluginSearchPaths_Impl& other, + Model_Impl* model, + bool keepHandle); + + virtual ~PythonPluginSearchPaths_Impl() = default; + + //@} + /** @name Virtual Methods */ + //@{ + + virtual const std::vector& outputVariableNames() const override; + + virtual IddObjectType iddObjectType() const override; + + //@} + /** @name Getters */ + //@{ + + bool addCurrentWorkingDirectorytoSearchPath() const; + + bool addInputFileDirectorytoSearchPath() const; + + bool addepinEnvironmentVariabletoSearchPath() const; + + // TODO: Handle this object's extensible fields. + + //@} + /** @name Setters */ + //@{ + + bool setAddCurrentWorkingDirectorytoSearchPath(bool addCurrentWorkingDirectorytoSearchPath); + + bool setAddInputFileDirectorytoSearchPath(bool addInputFileDirectorytoSearchPath); + + bool setAddepinEnvironmentVariabletoSearchPath(bool addepinEnvironmentVariabletoSearchPath); + + // TODO: Handle this object's extensible fields. + + //@} + /** @name Other */ + //@{ + + //@} + protected: + private: + REGISTER_LOGGER("openstudio.model.PythonPluginSearchPaths"); + }; + + } // namespace detail + +} // namespace model +} // namespace openstudio + +#endif // MODEL_PYTHONPLUGINSEARCHPATHS_IMPL_HPP diff --git a/src/model/test/PythonPluginSearchPaths_GTest.cpp b/src/model/test/PythonPluginSearchPaths_GTest.cpp new file mode 100644 index 0000000000..e385fe6ff1 --- /dev/null +++ b/src/model/test/PythonPluginSearchPaths_GTest.cpp @@ -0,0 +1,63 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) 2008-2023, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +* following conditions are met: +* +* (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following +* disclaimer. +* +* (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided with the distribution. +* +* (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products +* derived from this software without specific prior written permission from the respective party. +* +* (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works +* may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior +* written permission from Alliance for Sustainable Energy, LLC. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED +* STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +***********************************************************************************************************************/ + +#include "ModelFixture.hpp" + +#include "../PythonPluginSearchPaths.hpp" +#include "../PythonPluginSearchPaths_Impl.hpp" + +using namespace openstudio; +using namespace openstudio::model; + +TEST_F(ModelFixture, PythonPluginSearchPaths_GettersSetters) { + Model m; + // TODO: Check regular Ctor arguments + PythonPluginSearchPaths pythonPluginSearchPaths(m); + // TODO: Or if a UniqueModelObject (and make sure _Impl is included) + // PythonPluginSearchPaths pythonPluginSearchPaths = m.getUniqueModelObject(); + + // Add Current Working Directory to Search Path: Required Boolean + EXPECT_TRUE(pythonPluginSearchPaths.setAddCurrentWorkingDirectorytoSearchPath(true)); + EXPECT_TRUE(pythonPluginSearchPaths.addCurrentWorkingDirectorytoSearchPath()); + EXPECT_TRUE(pythonPluginSearchPaths.setAddCurrentWorkingDirectorytoSearchPath(false)); + EXPECT_FALSE(pythonPluginSearchPaths.addCurrentWorkingDirectorytoSearchPath()); + + // Add Input File Directory to Search Path: Required Boolean + EXPECT_TRUE(pythonPluginSearchPaths.setAddInputFileDirectorytoSearchPath(true)); + EXPECT_TRUE(pythonPluginSearchPaths.addInputFileDirectorytoSearchPath()); + EXPECT_TRUE(pythonPluginSearchPaths.setAddInputFileDirectorytoSearchPath(false)); + EXPECT_FALSE(pythonPluginSearchPaths.addInputFileDirectorytoSearchPath()); + + // Add epin Environment Variable to Search Path: Required Boolean + EXPECT_TRUE(pythonPluginSearchPaths.setAddepinEnvironmentVariabletoSearchPath(true)); + EXPECT_TRUE(pythonPluginSearchPaths.addepinEnvironmentVariabletoSearchPath()); + EXPECT_TRUE(pythonPluginSearchPaths.setAddepinEnvironmentVariabletoSearchPath(false)); + EXPECT_FALSE(pythonPluginSearchPaths.addepinEnvironmentVariabletoSearchPath()); + +} From 47c4068d6ef4731016d2508a596fc8b3a2ac7236 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Wed, 4 Dec 2024 15:37:25 -0700 Subject: [PATCH 03/17] Fill out extensible methods. --- src/model/PythonPluginSearchPaths.cpp | 65 ++++++++++++++++++++++ src/model/PythonPluginSearchPaths.hpp | 8 ++- src/model/PythonPluginSearchPaths_Impl.hpp | 8 ++- 3 files changed, 77 insertions(+), 4 deletions(-) diff --git a/src/model/PythonPluginSearchPaths.cpp b/src/model/PythonPluginSearchPaths.cpp index 3c1df08fd4..a543601874 100644 --- a/src/model/PythonPluginSearchPaths.cpp +++ b/src/model/PythonPluginSearchPaths.cpp @@ -30,6 +30,7 @@ #include "PythonPluginSearchPaths.hpp" #include "PythonPluginSearchPaths_Impl.hpp" +#include "../utilities/idf/WorkspaceExtensibleGroup.hpp" #include "../utilities/core/Assert.hpp" #include @@ -79,6 +80,16 @@ namespace model { return getBooleanFieldValue(OS_PythonPlugin_SearchPathsFields::AddepinEnvironmentVariabletoSearchPath); } + std::vector PythonPluginSearchPaths_Impl::searchPaths() const { + std::vector result; + for (const auto& eg : extensibleGroups()) { + auto _s = eg.getString(OS_PythonPlugin_SearchPathsExtensibleFields::SearchPath); + OS_ASSERT(_s); + result.push_back(_s.get()); + } + return result; + } + bool PythonPluginSearchPaths_Impl::setAddCurrentWorkingDirectorytoSearchPath(bool addCurrentWorkingDirectorytoSearchPath) { const bool result = setBooleanFieldValue(OS_PythonPlugin_SearchPathsFields::AddCurrentWorkingDirectorytoSearchPath, addCurrentWorkingDirectorytoSearchPath); OS_ASSERT(result); @@ -97,6 +108,44 @@ namespace model { return result; } + bool PythonPluginSearchPaths_Impl::addSearchPath(const std::string& searchPath) { + std::vector existingSearchPaths = this->searchPaths(); + if (std::find_if(existingSearchPaths.begin(), existingSearchPaths.end(), [&searchPath](const std::string& s) { return openstudio::istringEqual(s, searchPath); }) + != existingSearchPaths.end()) { + LOG(Info, "Not adding search path '" << searchPath << "' to PythonPlugin:SearchPaths since it is already present"); + // Return true anyways, it's a success + return true; + } + + auto eg = getObject().pushExtensibleGroup().cast(); + bool result = eg.setString(OS_PythonPlugin_SearchPathsExtensibleFields::SearchPath, searchPath); + if (!result) { + getObject().eraseExtensibleGroup(eg.groupIndex()); + } + + return result; + } + + bool PythonPluginSearchPaths_Impl::setSearchPaths(const std::vector& searchPaths) { + bool result = true; + + clearSearchPaths(); + + for (const auto& s : searchPaths) { + bool thisResult = addSearchPath(s); + if (!thisResult) { + LOG(Warn, "Couldn't add search path " << s << " to PythonPlugin:SearchPaths, skipping and continuing."); + result = false; + } + } + + return result; + } + + void PythonPluginSearchPaths_Impl::clearSearchPaths() { + clearExtensibleGroups(); + } + } // namespace detail IddObjectType PythonPluginSearchPaths::iddObjectType() { @@ -115,6 +164,10 @@ namespace model { return getImpl()->addepinEnvironmentVariabletoSearchPath(); } + std::vector PythonPluginSearchPaths::searchPaths() const { + return getImpl()->searchPaths(); + } + bool PythonPluginSearchPaths::setAddCurrentWorkingDirectorytoSearchPath(bool addCurrentWorkingDirectorytoSearchPath) { return getImpl()->setAddCurrentWorkingDirectorytoSearchPath(addCurrentWorkingDirectorytoSearchPath); } @@ -127,6 +180,18 @@ namespace model { return getImpl()->setAddepinEnvironmentVariabletoSearchPath(addepinEnvironmentVariabletoSearchPath); } + bool PythonPluginSearchPaths::addSearchPath(const std::string& searchPath) { + return getImpl()->addSearchPath(searchPath); + } + + bool PythonPluginSearchPaths::setSearchPaths(const std::vector& searchPaths) { + return getImpl()->setSearchPaths(searchPaths); + } + + void PythonPluginSearchPaths::clearSearchPaths() { + getImpl()->clearSearchPaths(); + } + /// @cond PythonPluginSearchPaths::PythonPluginSearchPaths( std::shared_ptr impl) diff --git a/src/model/PythonPluginSearchPaths.hpp b/src/model/PythonPluginSearchPaths.hpp index 79f94f7bb1..1019da076d 100644 --- a/src/model/PythonPluginSearchPaths.hpp +++ b/src/model/PythonPluginSearchPaths.hpp @@ -69,7 +69,7 @@ namespace model { bool addepinEnvironmentVariabletoSearchPath() const; - // TODO: Handle this object's extensible fields. + std::vector searchPaths() const; //@} /** @name Setters */ @@ -81,7 +81,11 @@ namespace model { bool setAddepinEnvironmentVariabletoSearchPath(bool addepinEnvironmentVariabletoSearchPath); - // TODO: Handle this object's extensible fields. + bool addSearchPath(const std::string& searchPath); + + bool setSearchPaths(const std::vector& searchPaths); + + void clearSearchPaths(); //@} /** @name Other */ diff --git a/src/model/PythonPluginSearchPaths_Impl.hpp b/src/model/PythonPluginSearchPaths_Impl.hpp index 9c6dbeef44..d18009bd6b 100644 --- a/src/model/PythonPluginSearchPaths_Impl.hpp +++ b/src/model/PythonPluginSearchPaths_Impl.hpp @@ -77,7 +77,7 @@ namespace model { bool addepinEnvironmentVariabletoSearchPath() const; - // TODO: Handle this object's extensible fields. + std::vector searchPaths() const; //@} /** @name Setters */ @@ -89,7 +89,11 @@ namespace model { bool setAddepinEnvironmentVariabletoSearchPath(bool addepinEnvironmentVariabletoSearchPath); - // TODO: Handle this object's extensible fields. + bool addSearchPath(const std::string& searchPath); + + bool setSearchPaths(const std::vector& searchPaths); + + void clearSearchPaths(); //@} /** @name Other */ From d136297b0d7d551de05036ac0f4f1944cbb281c0 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Wed, 4 Dec 2024 15:37:42 -0700 Subject: [PATCH 04/17] Formatting. --- ...orwardTranslatePythonPluginSearchPaths.cpp | 2 +- ...everseTranslatePythonPluginSearchPaths.cpp | 17 ++++++---- .../Test/PythonPluginSearchPaths_GTest.cpp | 14 ++++---- src/model/PythonPluginSearchPaths.cpp | 33 +++++++++---------- src/model/PythonPluginSearchPaths.hpp | 4 +-- src/model/PythonPluginSearchPaths_Impl.hpp | 18 ++++------ .../test/PythonPluginSearchPaths_GTest.cpp | 1 - 7 files changed, 43 insertions(+), 46 deletions(-) diff --git a/src/energyplus/ForwardTranslator/ForwardTranslatePythonPluginSearchPaths.cpp b/src/energyplus/ForwardTranslator/ForwardTranslatePythonPluginSearchPaths.cpp index 3e6be35a4f..45dffc2945 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslatePythonPluginSearchPaths.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslatePythonPluginSearchPaths.cpp @@ -41,7 +41,7 @@ namespace openstudio { namespace energyplus { - boost::optional ForwardTranslator::translatePythonPluginSearchPaths( model::PythonPluginSearchPaths& modelObject ) { + boost::optional ForwardTranslator::translatePythonPluginSearchPaths(model::PythonPluginSearchPaths& modelObject) { // Instantiate an IdfObject of the class to store the values IdfObject idfObject = createRegisterAndNameIdfObject(openstudio::IddObjectType::PythonPlugin_SearchPaths, modelObject); diff --git a/src/energyplus/ReverseTranslator/ReverseTranslatePythonPluginSearchPaths.cpp b/src/energyplus/ReverseTranslator/ReverseTranslatePythonPluginSearchPaths.cpp index 108f5d024c..bccf0be924 100644 --- a/src/energyplus/ReverseTranslator/ReverseTranslatePythonPluginSearchPaths.cpp +++ b/src/energyplus/ReverseTranslator/ReverseTranslatePythonPluginSearchPaths.cpp @@ -40,7 +40,7 @@ namespace openstudio { namespace energyplus { - boost::optional ReverseTranslator::translatePythonPluginSearchPaths(const WorkspaceObject & workspaceObject) { + boost::optional ReverseTranslator::translatePythonPluginSearchPaths(const WorkspaceObject& workspaceObject) { // Instantiate an object of the class to store the values, // but we don't return it until we know it's ok @@ -57,8 +57,9 @@ namespace energyplus { } // Add Current Working Directory to Search Path: Optional Boolean - if (boost::optional addCurrentWorkingDirectorytoSearchPath_ = getString(PythonPlugin_SearchPathsFields::AddCurrentWorkingDirectorytoSearchPath, true)) { - if(istringEqual("Yes", addCurrentWorkingDirectorytoSearchPath_.get())) { + if (boost::optional addCurrentWorkingDirectorytoSearchPath_ = + getString(PythonPlugin_SearchPathsFields::AddCurrentWorkingDirectorytoSearchPath, true)) { + if (istringEqual("Yes", addCurrentWorkingDirectorytoSearchPath_.get())) { modelObject.setAddCurrentWorkingDirectorytoSearchPath(true); } else { modelObject.setAddCurrentWorkingDirectorytoSearchPath(false); @@ -66,8 +67,9 @@ namespace energyplus { } // Add Input File Directory to Search Path: Optional Boolean - if (boost::optional addInputFileDirectorytoSearchPath_ = getString(PythonPlugin_SearchPathsFields::AddInputFileDirectorytoSearchPath, true)) { - if(istringEqual("Yes", addInputFileDirectorytoSearchPath_.get())) { + if (boost::optional addInputFileDirectorytoSearchPath_ = + getString(PythonPlugin_SearchPathsFields::AddInputFileDirectorytoSearchPath, true)) { + if (istringEqual("Yes", addInputFileDirectorytoSearchPath_.get())) { modelObject.setAddInputFileDirectorytoSearchPath(true); } else { modelObject.setAddInputFileDirectorytoSearchPath(false); @@ -75,8 +77,9 @@ namespace energyplus { } // Add epin Environment Variable to Search Path: Optional Boolean - if (boost::optional addepinEnvironmentVariabletoSearchPath_ = getString(PythonPlugin_SearchPathsFields::AddepinEnvironmentVariabletoSearchPath, true)) { - if(istringEqual("Yes", addepinEnvironmentVariabletoSearchPath_.get())) { + if (boost::optional addepinEnvironmentVariabletoSearchPath_ = + getString(PythonPlugin_SearchPathsFields::AddepinEnvironmentVariabletoSearchPath, true)) { + if (istringEqual("Yes", addepinEnvironmentVariabletoSearchPath_.get())) { modelObject.setAddepinEnvironmentVariabletoSearchPath(true); } else { modelObject.setAddepinEnvironmentVariabletoSearchPath(false); diff --git a/src/energyplus/Test/PythonPluginSearchPaths_GTest.cpp b/src/energyplus/Test/PythonPluginSearchPaths_GTest.cpp index 71cd758e16..d61ccf0842 100644 --- a/src/energyplus/Test/PythonPluginSearchPaths_GTest.cpp +++ b/src/energyplus/Test/PythonPluginSearchPaths_GTest.cpp @@ -59,10 +59,9 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_PythonPluginSearchPaths) { pythonPluginSearchPaths.setName("My PythonPluginSearchPaths"); EXPECT_TRUE(pythonPluginSearchPaths.setAddCurrentWorkingDirectorytoSearchPath(false)); // Opposite from IDD default - EXPECT_TRUE(pythonPluginSearchPaths.setAddInputFileDirectorytoSearchPath(false)); // Opposite from IDD default + EXPECT_TRUE(pythonPluginSearchPaths.setAddInputFileDirectorytoSearchPath(false)); // Opposite from IDD default EXPECT_TRUE(pythonPluginSearchPaths.setAddepinEnvironmentVariabletoSearchPath(false)); // Opposite from IDD default - // TODO: you're responsible for creating all other objects needed so this object actually gets ForwardTranslated const Workspace w = ft.translateModel(m); @@ -70,7 +69,9 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_PythonPluginSearchPaths) { ASSERT_EQ(1u, idfObjs.size()); const auto& idfObject = idfObjs.front(); - EXPECT_EQ("No", idfObject.getString(PythonPlugin_SearchPathsFields::AddCurrentWorkingDirectorytoSearchPath).get()); EXPECT_EQ("No", idfObject.getString(PythonPlugin_SearchPathsFields::AddInputFileDirectorytoSearchPath).get()); EXPECT_EQ("No", idfObject.getString(PythonPlugin_SearchPathsFields::AddepinEnvironmentVariabletoSearchPath).get()); + EXPECT_EQ("No", idfObject.getString(PythonPlugin_SearchPathsFields::AddCurrentWorkingDirectorytoSearchPath).get()); + EXPECT_EQ("No", idfObject.getString(PythonPlugin_SearchPathsFields::AddInputFileDirectorytoSearchPath).get()); + EXPECT_EQ("No", idfObject.getString(PythonPlugin_SearchPathsFields::AddepinEnvironmentVariabletoSearchPath).get()); } TEST_F(EnergyPlusFixture, ReverseTranslator_PythonPluginSearchPaths) { @@ -82,14 +83,15 @@ TEST_F(EnergyPlusFixture, ReverseTranslator_PythonPluginSearchPaths) { woPPSP.setName("My PythonPluginSearchPaths"); EXPECT_TRUE(woPPSP.setString(PythonPlugin_SearchPathsFields::AddCurrentWorkingDirectorytoSearchPath, "No")); // Opposite from IDD default - EXPECT_TRUE(woPPSP.setString(PythonPlugin_SearchPathsFields::AddInputFileDirectorytoSearchPath, "No")); // Opposite from IDD default + EXPECT_TRUE(woPPSP.setString(PythonPlugin_SearchPathsFields::AddInputFileDirectorytoSearchPath, "No")); // Opposite from IDD default EXPECT_TRUE(woPPSP.setString(PythonPlugin_SearchPathsFields::AddepinEnvironmentVariabletoSearchPath, "No")); // Opposite from IDD default - const Model m = rt.translateWorkspace(w); const auto modelObjects = m.getConcreteModelObjects(); ASSERT_EQ(1u, modelObjects.size()); const auto& modelObject = modelObjects.front(); - EXPECT_FALSE(modelObject.addCurrentWorkingDirectorytoSearchPath()); EXPECT_FALSE(modelObject.addInputFileDirectorytoSearchPath()); EXPECT_FALSE(modelObject.addepinEnvironmentVariabletoSearchPath()); + EXPECT_FALSE(modelObject.addCurrentWorkingDirectorytoSearchPath()); + EXPECT_FALSE(modelObject.addInputFileDirectorytoSearchPath()); + EXPECT_FALSE(modelObject.addepinEnvironmentVariabletoSearchPath()); } diff --git a/src/model/PythonPluginSearchPaths.cpp b/src/model/PythonPluginSearchPaths.cpp index a543601874..2bd7cf8283 100644 --- a/src/model/PythonPluginSearchPaths.cpp +++ b/src/model/PythonPluginSearchPaths.cpp @@ -41,25 +41,23 @@ namespace model { namespace detail { - PythonPluginSearchPaths_Impl::PythonPluginSearchPaths_Impl(const IdfObject& idfObject, - Model_Impl* model, bool keepHandle) + PythonPluginSearchPaths_Impl::PythonPluginSearchPaths_Impl(const IdfObject& idfObject, Model_Impl* model, bool keepHandle) : ParentObject_Impl(idfObject, model, keepHandle) { OS_ASSERT(idfObject.iddObject().type() == PythonPluginSearchPaths::iddObjectType()); } - PythonPluginSearchPaths_Impl::PythonPluginSearchPaths_Impl(const openstudio::detail::WorkspaceObject_Impl& other, - Model_Impl* model, bool keepHandle) + PythonPluginSearchPaths_Impl::PythonPluginSearchPaths_Impl(const openstudio::detail::WorkspaceObject_Impl& other, Model_Impl* model, + bool keepHandle) : ParentObject_Impl(other, model, keepHandle) { OS_ASSERT(other.iddObject().type() == PythonPluginSearchPaths::iddObjectType()); } - PythonPluginSearchPaths_Impl::PythonPluginSearchPaths_Impl(const PythonPluginSearchPaths_Impl& other, - Model_Impl* model, bool keepHandle) - : ParentObject_Impl(other, model, keepHandle) {} + PythonPluginSearchPaths_Impl::PythonPluginSearchPaths_Impl(const PythonPluginSearchPaths_Impl& other, Model_Impl* model, bool keepHandle) + : ParentObject_Impl(other, model, keepHandle) {} const std::vector& PythonPluginSearchPaths_Impl::outputVariableNames() const { static std::vector result; - if (result.empty()){ + if (result.empty()) { } return result; } @@ -91,26 +89,30 @@ namespace model { } bool PythonPluginSearchPaths_Impl::setAddCurrentWorkingDirectorytoSearchPath(bool addCurrentWorkingDirectorytoSearchPath) { - const bool result = setBooleanFieldValue(OS_PythonPlugin_SearchPathsFields::AddCurrentWorkingDirectorytoSearchPath, addCurrentWorkingDirectorytoSearchPath); + const bool result = + setBooleanFieldValue(OS_PythonPlugin_SearchPathsFields::AddCurrentWorkingDirectorytoSearchPath, addCurrentWorkingDirectorytoSearchPath); OS_ASSERT(result); return result; } bool PythonPluginSearchPaths_Impl::setAddInputFileDirectorytoSearchPath(bool addInputFileDirectorytoSearchPath) { - const bool result = setBooleanFieldValue(OS_PythonPlugin_SearchPathsFields::AddInputFileDirectorytoSearchPath, addInputFileDirectorytoSearchPath); + const bool result = + setBooleanFieldValue(OS_PythonPlugin_SearchPathsFields::AddInputFileDirectorytoSearchPath, addInputFileDirectorytoSearchPath); OS_ASSERT(result); return result; } bool PythonPluginSearchPaths_Impl::setAddepinEnvironmentVariabletoSearchPath(bool addepinEnvironmentVariabletoSearchPath) { - const bool result = setBooleanFieldValue(OS_PythonPlugin_SearchPathsFields::AddepinEnvironmentVariabletoSearchPath, addepinEnvironmentVariabletoSearchPath); + const bool result = + setBooleanFieldValue(OS_PythonPlugin_SearchPathsFields::AddepinEnvironmentVariabletoSearchPath, addepinEnvironmentVariabletoSearchPath); OS_ASSERT(result); return result; } bool PythonPluginSearchPaths_Impl::addSearchPath(const std::string& searchPath) { std::vector existingSearchPaths = this->searchPaths(); - if (std::find_if(existingSearchPaths.begin(), existingSearchPaths.end(), [&searchPath](const std::string& s) { return openstudio::istringEqual(s, searchPath); }) + if (std::find_if(existingSearchPaths.begin(), existingSearchPaths.end(), + [&searchPath](const std::string& s) { return openstudio::istringEqual(s, searchPath); }) != existingSearchPaths.end()) { LOG(Info, "Not adding search path '" << searchPath << "' to PythonPlugin:SearchPaths since it is already present"); // Return true anyways, it's a success @@ -193,11 +195,8 @@ namespace model { } /// @cond - PythonPluginSearchPaths::PythonPluginSearchPaths( - std::shared_ptr impl) - : ParentObject(std::move(impl)) {} - PythonPluginSearchPaths::PythonPluginSearchPaths(Model& model) - : ParentObject(PythonPluginSearchPaths::iddObjectType(), model) {} + PythonPluginSearchPaths::PythonPluginSearchPaths(std::shared_ptr impl) : ParentObject(std::move(impl)) {} + PythonPluginSearchPaths::PythonPluginSearchPaths(Model& model) : ParentObject(PythonPluginSearchPaths::iddObjectType(), model) {} /// @endcond } // namespace model diff --git a/src/model/PythonPluginSearchPaths.hpp b/src/model/PythonPluginSearchPaths.hpp index 1019da076d..8d5d9e536e 100644 --- a/src/model/PythonPluginSearchPaths.hpp +++ b/src/model/PythonPluginSearchPaths.hpp @@ -70,7 +70,7 @@ namespace model { bool addepinEnvironmentVariabletoSearchPath() const; std::vector searchPaths() const; - + //@} /** @name Setters */ //@{ @@ -82,7 +82,7 @@ namespace model { bool setAddepinEnvironmentVariabletoSearchPath(bool addepinEnvironmentVariabletoSearchPath); bool addSearchPath(const std::string& searchPath); - + bool setSearchPaths(const std::vector& searchPaths); void clearSearchPaths(); diff --git a/src/model/PythonPluginSearchPaths_Impl.hpp b/src/model/PythonPluginSearchPaths_Impl.hpp index d18009bd6b..3c436e86bb 100644 --- a/src/model/PythonPluginSearchPaths_Impl.hpp +++ b/src/model/PythonPluginSearchPaths_Impl.hpp @@ -38,24 +38,18 @@ namespace model { namespace detail { - /** PythonPluginSearchPaths_Impl is a ParentObject_Impl that is the implementation class for PythonPluginSearchPaths.*/ + /** PythonPluginSearchPaths_Impl is a ParentObject_Impl that is the implementation class for PythonPluginSearchPaths.*/ class MODEL_API PythonPluginSearchPaths_Impl : public ParentObject_Impl { public: /** @name Constructors and Destructors */ //@{ - PythonPluginSearchPaths_Impl(const IdfObject& idfObject, - Model_Impl* model, - bool keepHandle); + PythonPluginSearchPaths_Impl(const IdfObject& idfObject, Model_Impl* model, bool keepHandle); - PythonPluginSearchPaths_Impl(const openstudio::detail::WorkspaceObject_Impl& other, - Model_Impl* model, - bool keepHandle); + PythonPluginSearchPaths_Impl(const openstudio::detail::WorkspaceObject_Impl& other, Model_Impl* model, bool keepHandle); - PythonPluginSearchPaths_Impl(const PythonPluginSearchPaths_Impl& other, - Model_Impl* model, - bool keepHandle); + PythonPluginSearchPaths_Impl(const PythonPluginSearchPaths_Impl& other, Model_Impl* model, bool keepHandle); virtual ~PythonPluginSearchPaths_Impl() = default; @@ -78,7 +72,7 @@ namespace model { bool addepinEnvironmentVariabletoSearchPath() const; std::vector searchPaths() const; - + //@} /** @name Setters */ //@{ @@ -90,7 +84,7 @@ namespace model { bool setAddepinEnvironmentVariabletoSearchPath(bool addepinEnvironmentVariabletoSearchPath); bool addSearchPath(const std::string& searchPath); - + bool setSearchPaths(const std::vector& searchPaths); void clearSearchPaths(); diff --git a/src/model/test/PythonPluginSearchPaths_GTest.cpp b/src/model/test/PythonPluginSearchPaths_GTest.cpp index e385fe6ff1..6fe9238526 100644 --- a/src/model/test/PythonPluginSearchPaths_GTest.cpp +++ b/src/model/test/PythonPluginSearchPaths_GTest.cpp @@ -59,5 +59,4 @@ TEST_F(ModelFixture, PythonPluginSearchPaths_GettersSetters) { EXPECT_TRUE(pythonPluginSearchPaths.addepinEnvironmentVariabletoSearchPath()); EXPECT_TRUE(pythonPluginSearchPaths.setAddepinEnvironmentVariabletoSearchPath(false)); EXPECT_FALSE(pythonPluginSearchPaths.addepinEnvironmentVariabletoSearchPath()); - } From fe3461a6a267fb2cb1418bae2d73971663ee6988 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Wed, 4 Dec 2024 21:05:41 -0700 Subject: [PATCH 05/17] Update cmakelists, model files, partial classes, etc. --- src/energyplus/CMakeLists.txt | 2 + ...everseTranslatePythonPluginSearchPaths.cpp | 93 ------------------- src/model/CMakeLists.txt | 4 + src/model/ConcreteModelObjects.hpp | 2 + src/model/Model.cpp | 36 +++++++ src/model/Model.hpp | 8 ++ src/model/ModelCore.i | 5 +- src/model/ModelResources.i | 10 ++ src/model/ModelSimulation.i | 1 - src/model/Model_Impl.hpp | 7 ++ src/model/test/Model_GTest.cpp | 8 ++ src/model/test/UniqueModelObject_GTest.cpp | 27 ++++++ 12 files changed, 108 insertions(+), 95 deletions(-) delete mode 100644 src/energyplus/ReverseTranslator/ReverseTranslatePythonPluginSearchPaths.cpp diff --git a/src/energyplus/CMakeLists.txt b/src/energyplus/CMakeLists.txt index 48aa9f11c1..2f8488943f 100644 --- a/src/energyplus/CMakeLists.txt +++ b/src/energyplus/CMakeLists.txt @@ -302,6 +302,7 @@ set(${target_name}_src ForwardTranslator/ForwardTranslatePythonPluginVariable.cpp ForwardTranslator/ForwardTranslatePythonPluginTrendVariable.cpp ForwardTranslator/ForwardTranslatePythonPluginOutputVariable.cpp + ForwardTranslator/ForwardTranslatePythonPluginSearchPaths.cpp ForwardTranslator/ForwardTranslateRefractionExtinctionGlazing.cpp ForwardTranslator/ForwardTranslateRefrigerationAirChiller.cpp ForwardTranslator/ForwardTranslateRefrigerationCase.cpp @@ -791,6 +792,7 @@ set(${target_name}_test_src Test/PythonPluginVariable_GTest.cpp Test/PythonPluginOutputVariable_GTest.cpp Test/PythonPluginTrendVariable_GTest.cpp + Test/PythonPluginSearchPaths_GTest.cpp Test/RunPeriod_GTest.cpp Test/RunPeriodControlDaylightSavingTime_GTest.cpp Test/RunPeriodControlSpecialDays_GTest.cpp diff --git a/src/energyplus/ReverseTranslator/ReverseTranslatePythonPluginSearchPaths.cpp b/src/energyplus/ReverseTranslator/ReverseTranslatePythonPluginSearchPaths.cpp deleted file mode 100644 index bccf0be924..0000000000 --- a/src/energyplus/ReverseTranslator/ReverseTranslatePythonPluginSearchPaths.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/*********************************************************************************************************************** -* OpenStudio(R), Copyright (c) 2008-2023, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the -* following conditions are met: -* -* (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following -* disclaimer. -* -* (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following -* disclaimer in the documentation and/or other materials provided with the distribution. -* -* (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products -* derived from this software without specific prior written permission from the respective party. -* -* (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works -* may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior -* written permission from Alliance for Sustainable Energy, LLC. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED -* STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -***********************************************************************************************************************/ - -#include "../ReverseTranslator.hpp" - -#include "../../model/PythonPluginSearchPaths.hpp" - -#include -#include - -using namespace openstudio::model; - -namespace openstudio { - -namespace energyplus { - - boost::optional ReverseTranslator::translatePythonPluginSearchPaths(const WorkspaceObject& workspaceObject) { - - // Instantiate an object of the class to store the values, - // but we don't return it until we know it's ok - // TODO: check constructor, it might need other objects - openstudio::model::PythonPluginSearchPaths modelObject(m_model); - - // TODO: Note JM 2018-10-17 - // You are responsible for implementing any additional logic based on choice fields, etc. - // The ReverseTranslator generator script is meant to facilitate your work, not get you 100% of the way - - // Name - if (boost::optional name_ = workspaceObject.name()) { - modelObject.setName(name_.get()); - } - - // Add Current Working Directory to Search Path: Optional Boolean - if (boost::optional addCurrentWorkingDirectorytoSearchPath_ = - getString(PythonPlugin_SearchPathsFields::AddCurrentWorkingDirectorytoSearchPath, true)) { - if (istringEqual("Yes", addCurrentWorkingDirectorytoSearchPath_.get())) { - modelObject.setAddCurrentWorkingDirectorytoSearchPath(true); - } else { - modelObject.setAddCurrentWorkingDirectorytoSearchPath(false); - } - } - - // Add Input File Directory to Search Path: Optional Boolean - if (boost::optional addInputFileDirectorytoSearchPath_ = - getString(PythonPlugin_SearchPathsFields::AddInputFileDirectorytoSearchPath, true)) { - if (istringEqual("Yes", addInputFileDirectorytoSearchPath_.get())) { - modelObject.setAddInputFileDirectorytoSearchPath(true); - } else { - modelObject.setAddInputFileDirectorytoSearchPath(false); - } - } - - // Add epin Environment Variable to Search Path: Optional Boolean - if (boost::optional addepinEnvironmentVariabletoSearchPath_ = - getString(PythonPlugin_SearchPathsFields::AddepinEnvironmentVariabletoSearchPath, true)) { - if (istringEqual("Yes", addepinEnvironmentVariabletoSearchPath_.get())) { - modelObject.setAddepinEnvironmentVariabletoSearchPath(true); - } else { - modelObject.setAddepinEnvironmentVariabletoSearchPath(false); - } - } - - return modelObject; - } // End of translate function - -} // end namespace energyplus -} // end namespace openstudio diff --git a/src/model/CMakeLists.txt b/src/model/CMakeLists.txt index 9a26b0c54c..8477362fea 100644 --- a/src/model/CMakeLists.txt +++ b/src/model/CMakeLists.txt @@ -1228,6 +1228,9 @@ set(${target_name}_src PythonPluginOutputVariable.hpp PythonPluginOutputVariable_Impl.hpp PythonPluginOutputVariable.cpp + PythonPluginSearchPaths.hpp + PythonPluginSearchPaths_Impl.hpp + PythonPluginSearchPaths.cpp RadianceParameters.hpp RadianceParameters_Impl.hpp RadianceParameters.cpp @@ -2221,6 +2224,7 @@ set(${target_name}_test_src test/PythonPluginVariable_GTest.cpp test/PythonPluginTrendVariable_GTest.cpp test/PythonPluginOutputVariable_GTest.cpp + test/PythonPluginSearchPaths_GTest.cpp test/RadianceParameters_GTest.cpp test/RefractionExtinctionGlazing_GTest.cpp test/RefrigerationAirChiller_GTest.cpp diff --git a/src/model/ConcreteModelObjects.hpp b/src/model/ConcreteModelObjects.hpp index c71eaadc27..9d36231578 100644 --- a/src/model/ConcreteModelObjects.hpp +++ b/src/model/ConcreteModelObjects.hpp @@ -374,6 +374,7 @@ #include "PythonPluginVariable.hpp" #include "PythonPluginTrendVariable.hpp" #include "PythonPluginOutputVariable.hpp" +#include "PythonPluginSearchPaths.hpp" #include "RadianceParameters.hpp" #include "RefractionExtinctionGlazing.hpp" #include "RefrigerationAirChiller.hpp" @@ -927,6 +928,7 @@ #include "PythonPluginVariable_Impl.hpp" #include "PythonPluginTrendVariable_Impl.hpp" #include "PythonPluginOutputVariable_Impl.hpp" +#include "PythonPluginSearchPaths_Impl.hpp" #include "RadianceParameters_Impl.hpp" #include "RefractionExtinctionGlazing_Impl.hpp" #include "RefrigerationAirChiller_Impl.hpp" diff --git a/src/model/Model.cpp b/src/model/Model.cpp index 73b8c11fb1..75d57bf3ea 100644 --- a/src/model/Model.cpp +++ b/src/model/Model.cpp @@ -936,6 +936,22 @@ namespace model { return m_cachedExternalInterface; } + boost::optional Model_Impl::pythonPluginSearchPaths() const { + if (m_cachedPythonPluginSearchPaths) { + return m_cachedPythonPluginSearchPaths; + } + + boost::optional result = this->model().getOptionalUniqueModelObject(); + if (result) { + m_cachedPythonPluginSearchPaths = result; + result->getImpl() + ->PythonPluginSearchPaths_Impl::onRemoveFromWorkspace.connect( + const_cast(this)); + } + + return m_cachedPythonPluginSearchPaths; + } + boost::optional Model_Impl::calendarYear() const { if (!m_cachedYearDescription) { m_cachedYearDescription = this->model().getUniqueModelObject(); @@ -1544,6 +1560,7 @@ namespace model { clearCachedClimateZones(dummy); clearCachedEnvironmentalImpactFactors(dummy); clearCachedExternalInterface(dummy); + clearCachedPythonPluginSearchPaths(dummy); } void Model_Impl::clearCachedBuilding(const Handle&) { @@ -1730,6 +1747,10 @@ namespace model { m_cachedExternalInterface.reset(); } + void Model_Impl::clearCachedPythonPluginSearchPaths(const Handle&) { + m_cachedPythonPluginSearchPaths.reset(); + } + void Model_Impl::autosize() { for (auto& optModelObj : objects()) { if (auto modelObj = optModelObj.optionalCast()) { // HVACComponent @@ -2064,6 +2085,10 @@ namespace model { return getImpl()->externalInterface(); } + boost::optional Model::pythonPluginSearchPaths() const { + return getImpl()->pythonPluginSearchPaths(); + } + boost::optional Model::calendarYear() const { return getImpl()->calendarYear(); } @@ -3808,6 +3833,15 @@ namespace model { } } + template <> + PythonPluginSearchPaths Model::getUniqueModelObject() { + if (boost::optional _b = pythonPluginSearchPaths()) { + return _b.get(); + } else { + return PythonPluginSearchPaths(*this); + } + } + std::shared_ptr detail::Model_Impl::ModelObjectCreator::getNew(Model_Impl* model, const IdfObject& obj, bool keepHandle) const { auto typeToCreate = obj.iddObject().type(); @@ -4204,6 +4238,7 @@ namespace model { REGISTER_CONSTRUCTOR(PythonPluginVariable); REGISTER_CONSTRUCTOR(PythonPluginTrendVariable); REGISTER_CONSTRUCTOR(PythonPluginOutputVariable); + REGISTER_CONSTRUCTOR(PythonPluginSearchPaths); REGISTER_CONSTRUCTOR(RadianceParameters); REGISTER_CONSTRUCTOR(RefractionExtinctionGlazing); REGISTER_CONSTRUCTOR(RefrigerationAirChiller); @@ -4777,6 +4812,7 @@ namespace model { REGISTER_COPYCONSTRUCTORS(PythonPluginVariable); REGISTER_COPYCONSTRUCTORS(PythonPluginTrendVariable); REGISTER_COPYCONSTRUCTORS(PythonPluginOutputVariable); + REGISTER_COPYCONSTRUCTORS(PythonPluginSearchPaths); REGISTER_COPYCONSTRUCTORS(RadianceParameters); REGISTER_COPYCONSTRUCTORS(RefractionExtinctionGlazing); REGISTER_COPYCONSTRUCTORS(RefrigerationAirChiller); diff --git a/src/model/Model.hpp b/src/model/Model.hpp index 9732ac54fb..5a69b71061 100644 --- a/src/model/Model.hpp +++ b/src/model/Model.hpp @@ -76,6 +76,7 @@ namespace model { class Schedule; class Node; class SpaceType; + class PythonPluginSearchPaths; namespace detail { class Model_Impl; @@ -316,6 +317,10 @@ namespace model { * object which can be significantly faster than calling getOptionalUniqueModelObject(). */ boost::optional externalInterface() const; + /** Get the PythonPluginSearchPaths object if there is one, this implementation uses a cached reference to the PythonPluginSearchPaths + * object which can be significantly faster than calling getOptionalUniqueModelObject(). */ + boost::optional pythonPluginSearchPaths() const; + /** Get or create the YearDescription object if there is one, then call method from YearDescription. */ // DLM: this is due to issues exporting the model::YearDescription object because of name conflict with utilities::YearDescription. boost::optional calendarYear() const; @@ -829,6 +834,9 @@ namespace model { template <> MODEL_API ExternalInterface Model::getUniqueModelObject(); + template <> + MODEL_API PythonPluginSearchPaths Model::getUniqueModelObject(); + } // namespace model } // namespace openstudio diff --git a/src/model/ModelCore.i b/src/model/ModelCore.i index 262c154dff..11e0a07787 100644 --- a/src/model/ModelCore.i +++ b/src/model/ModelCore.i @@ -74,9 +74,12 @@ // Ignore hvac objects for now, add back in with partial classes in ModelHVAC.i %ignore openstudio::model::Model::outdoorAirNode; - // Ignore hvac objects for now, add back in with partial classes in ModelAirflow.i + // Ignore airflow objects for now, add back in with partial classes in ModelAirflow.i %ignore openstudio::model::Model::airflowNetworkSimulationControl; + // Ignore resources objects for now, add back in with partial classes in ModelResources.i + %ignore openstudio::model::Model::pythonPluginSearchPaths; + // EnergyManagementSystemActuator: depends on Space (ModelGeometry.i), %ignore openstudio::model::EnergyManagementSystemActuator::EnergyManagementSystemActuator(const ModelObject& modelObject, const std::string& actuatedComponentType, diff --git a/src/model/ModelResources.i b/src/model/ModelResources.i index 475039e094..af70e0167c 100644 --- a/src/model/ModelResources.i +++ b/src/model/ModelResources.i @@ -105,6 +105,7 @@ MODELOBJECT_TEMPLATES(PythonPluginInstance); MODELOBJECT_TEMPLATES(PythonPluginVariable); MODELOBJECT_TEMPLATES(PythonPluginTrendVariable); MODELOBJECT_TEMPLATES(PythonPluginOutputVariable); +UNIQUEMODELOBJECT_TEMPLATES(PythonPluginSearchPaths); MODELOBJECT_TEMPLATES(ScheduleVariableInterval); MODELOBJECT_TEMPLATES(ScheduleCompact); MODELOBJECT_TEMPLATES(ScheduleConstant); @@ -206,6 +207,7 @@ SWIG_MODELOBJECT(PythonPluginInstance, 1); SWIG_MODELOBJECT(PythonPluginVariable, 1); SWIG_MODELOBJECT(PythonPluginTrendVariable, 1); SWIG_MODELOBJECT(PythonPluginOutputVariable, 1); +SWIG_UNIQUEMODELOBJECT(PythonPluginSearchPaths); SWIG_MODELOBJECT(ExternalFile, 1); SWIG_MODELOBJECT(ScheduleFixedInterval, 1); SWIG_MODELOBJECT(ScheduleVariableInterval, 1); @@ -311,6 +313,10 @@ SWIG_MODELOBJECT(HeatExchangerDesiccantBalancedFlowPerformanceDataType1, 1); return ems_curve.setCurveOrTableObject(curve); } + boost::optional pythonPluginSearchPaths(const openstudio::model::Model& model) { + return model.pythonPluginSearchPaths(); + } + } } } @@ -333,6 +339,10 @@ SWIG_MODELOBJECT(HeatExchangerDesiccantBalancedFlowPerformanceDataType1, 1); : this(model) { this.setCurveOrTableObject(curve); } + + public OptionalPythonPluginSearchPaths pythonPluginSearchPaths() { + return OpenStudio.OpenStudioModelResources.pythonPluginSearchPaths(this); + } } %} #endif diff --git a/src/model/ModelSimulation.i b/src/model/ModelSimulation.i index ac25115699..b67615c894 100644 --- a/src/model/ModelSimulation.i +++ b/src/model/ModelSimulation.i @@ -175,7 +175,6 @@ SWIG_UNIQUEMODELOBJECT(PerformancePrecisionTradeoffs); return model.runPeriod(); } - boost::optional climateZones(const openstudio::model::Model& model) { return model.climateZones(); } diff --git a/src/model/Model_Impl.hpp b/src/model/Model_Impl.hpp index bb0ab20adb..3e6186b133 100644 --- a/src/model/Model_Impl.hpp +++ b/src/model/Model_Impl.hpp @@ -54,6 +54,7 @@ #include "ClimateZones.hpp" #include "EnvironmentalImpactFactors.hpp" #include "ExternalInterface.hpp" +#include "PythonPluginSearchPaths.hpp" #include "../nano/nano_signal_slot.hpp" // Signal-Slot replacement @@ -335,6 +336,10 @@ namespace model { * object which can be significantly faster than calling getOptionalUniqueModelObject(). */ boost::optional externalInterface() const; + /** Get the PythonPluginSearchPaths object if there is one, this implementation uses a cached reference to the PythonPluginSearchPaths + * object which can be significantly faster than calling getOptionalUniqueModelObject(). */ + boost::optional pythonPluginSearchPaths() const; + /** Get or create the YearDescription object if there is one, then call method from YearDescription. */ // DLM: this is due to issues exporting the model::YearDescription object because of name conflict with utilities::YearDescription. boost::optional calendarYear() const; @@ -508,6 +513,7 @@ namespace model { mutable boost::optional m_cachedClimateZones; mutable boost::optional m_cachedEnvironmentalImpactFactors; mutable boost::optional m_cachedExternalInterface; + mutable boost::optional m_cachedPythonPluginSearchPaths; // private slots: void clearCachedData(); @@ -557,6 +563,7 @@ namespace model { void clearCachedClimateZones(const Handle& handle); void clearCachedEnvironmentalImpactFactors(const Handle& handle); void clearCachedExternalInterface(const Handle& handle); + void clearCachedPythonPluginSearchPaths(const Handle& handle); using CopyConstructorFunction = std::function( Model_Impl*, const std::shared_ptr&, bool)>; diff --git a/src/model/test/Model_GTest.cpp b/src/model/test/Model_GTest.cpp index bb50bd8f0f..e468c2ff32 100644 --- a/src/model/test/Model_GTest.cpp +++ b/src/model/test/Model_GTest.cpp @@ -128,6 +128,8 @@ #include "../EnvironmentalImpactFactors_Impl.hpp" #include "../ExternalInterface.hpp" #include "../ExternalInterface_Impl.hpp" +#include "../PythonPluginSearchPaths.hpp" +#include "../PythonPluginSearchPaths_Impl.hpp" #include "../../utilities/core/PathHelpers.hpp" #include "../../utilities/data/TimeSeries.hpp" @@ -1161,6 +1163,12 @@ TEST_F(ModelFixture, UniqueModelObjectCachedGetters) { auto externalInterface = m.getUniqueModelObject(); EXPECT_TRUE(m.getOptionalUniqueModelObject()); EXPECT_EQ(++i, m.getModelObjects().size()); + + EXPECT_FALSE(m.getOptionalUniqueModelObject()); + EXPECT_EQ(i, m.getModelObjects().size()); + auto pythonPluginSearchPaths = m.getUniqueModelObject(); + EXPECT_TRUE(m.getOptionalUniqueModelObject()); + EXPECT_EQ(++i, m.getModelObjects().size()); } TEST_F(ModelFixture, Model_load) { diff --git a/src/model/test/UniqueModelObject_GTest.cpp b/src/model/test/UniqueModelObject_GTest.cpp index c8ca196778..0c2e6c9aa7 100644 --- a/src/model/test/UniqueModelObject_GTest.cpp +++ b/src/model/test/UniqueModelObject_GTest.cpp @@ -54,6 +54,8 @@ #include "../OutputConstructions_Impl.hpp" #include "../PerformancePrecisionTradeoffs.hpp" #include "../PerformancePrecisionTradeoffs_Impl.hpp" +#include "../PythonPluginSearchPaths.hpp" +#include "../PythonPluginSearchPaths_Impl.hpp" #include "../RadianceParameters.hpp" #include "../RadianceParameters_Impl.hpp" #include "../RunPeriod.hpp" @@ -625,6 +627,31 @@ TEST_F(ModelFixture, PerformancePrecisionTradeoffs_UniqueModelObject_Clone) { EXPECT_EQ("! Custom Object", performancePrecisionTradeoffsClone2.comment()); } +TEST_F(ModelFixture, PythonPluginSearchPaths_UniqueModelObject_Clone) { + // create a model to use + Model model; + + // Get the Unique ModelObject + EXPECT_FALSE(model.getOptionalUniqueModelObject()); + auto pythonPluginSearchPaths = model.getUniqueModelObject(); + EXPECT_TRUE(model.getOptionalUniqueModelObject()); + // We use a comment to see if cloning to another model works + pythonPluginSearchPaths.setComment("Custom Object"); + + // clone it into the same model + auto pythonPluginSearchPathsClone = pythonPluginSearchPaths.clone(model).cast(); + // UniqueModelObject: should be the same as the original + EXPECT_EQ(pythonPluginSearchPaths, pythonPluginSearchPathsClone); + EXPECT_EQ("! Custom Object", pythonPluginSearchPathsClone.comment()); + + // clone it into a different model + Model model2; + EXPECT_FALSE(model2.getOptionalUniqueModelObject()); + auto pythonPluginSearchPathsClone2 = pythonPluginSearchPaths.clone(model2).cast(); + EXPECT_TRUE(model2.getOptionalUniqueModelObject()); + EXPECT_EQ("! Custom Object", pythonPluginSearchPathsClone2.comment()); +} + TEST_F(ModelFixture, RadianceParameters_UniqueModelObject_Clone) { // create a model to use Model model; From 29a3f012ec530023567118f9c8d45d3e0c228bda Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Thu, 5 Dec 2024 11:18:48 -0700 Subject: [PATCH 06/17] Update ft hpp and cpp. --- src/energyplus/ForwardTranslator.cpp | 6 ++++++ src/energyplus/ForwardTranslator.hpp | 3 +++ 2 files changed, 9 insertions(+) diff --git a/src/energyplus/ForwardTranslator.cpp b/src/energyplus/ForwardTranslator.cpp index 93b639954d..60cd6517c5 100644 --- a/src/energyplus/ForwardTranslator.cpp +++ b/src/energyplus/ForwardTranslator.cpp @@ -2433,6 +2433,11 @@ namespace energyplus { retVal = translatePythonPluginOutputVariable(obj); break; } + case openstudio::IddObjectType::OS_PythonPlugin_SearchPaths: { + auto obj = modelObject.cast(); + retVal = translatePythonPluginSearchPaths(obj); + break; + } case openstudio::IddObjectType::OS_RadianceParameters: { // no-op break; @@ -3606,6 +3611,7 @@ namespace energyplus { IddObjectType::OS_PythonPlugin_Variable, IddObjectType::OS_PythonPlugin_TrendVariable, IddObjectType::OS_PythonPlugin_OutputVariable, + IddObjectType::OS_PythonPlugin_SearchPaths, }; return result; diff --git a/src/energyplus/ForwardTranslator.hpp b/src/energyplus/ForwardTranslator.hpp index 976de7e606..b14c46dabe 100644 --- a/src/energyplus/ForwardTranslator.hpp +++ b/src/energyplus/ForwardTranslator.hpp @@ -337,6 +337,7 @@ namespace model { class PythonPluginVariable; class PythonPluginTrendVariable; class PythonPluginOutputVariable; + class PythonPluginSearchPaths; class RefractionExtinctionGlazing; class RefrigerationAirChiller; class RefrigerationCase; @@ -1256,6 +1257,8 @@ namespace energyplus { boost::optional translatePythonPluginOutputVariable(model::PythonPluginOutputVariable& modelObject); + boost::optional translatePythonPluginSearchPaths(model::PythonPluginSearchPaths& modelObject); + boost::optional translateRefractionExtinctionGlazing(model::RefractionExtinctionGlazing& modelObject); boost::optional translateRefrigerationAirChiller(model::RefrigerationAirChiller& modelObject); From e5e4b072cfde11e1eb1358a41e3903529d88caab Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Thu, 5 Dec 2024 14:25:33 -0700 Subject: [PATCH 07/17] Fix model test ctor and fill out extensible field tests. --- src/model/PythonPluginSearchPaths.cpp | 1 + .../test/PythonPluginSearchPaths_GTest.cpp | 32 ++++++++++++++++--- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/model/PythonPluginSearchPaths.cpp b/src/model/PythonPluginSearchPaths.cpp index 2bd7cf8283..633c173f3f 100644 --- a/src/model/PythonPluginSearchPaths.cpp +++ b/src/model/PythonPluginSearchPaths.cpp @@ -197,6 +197,7 @@ namespace model { /// @cond PythonPluginSearchPaths::PythonPluginSearchPaths(std::shared_ptr impl) : ParentObject(std::move(impl)) {} PythonPluginSearchPaths::PythonPluginSearchPaths(Model& model) : ParentObject(PythonPluginSearchPaths::iddObjectType(), model) {} + /// @endcond } // namespace model diff --git a/src/model/test/PythonPluginSearchPaths_GTest.cpp b/src/model/test/PythonPluginSearchPaths_GTest.cpp index 6fe9238526..887911e58d 100644 --- a/src/model/test/PythonPluginSearchPaths_GTest.cpp +++ b/src/model/test/PythonPluginSearchPaths_GTest.cpp @@ -27,6 +27,8 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***********************************************************************************************************************/ +#include + #include "ModelFixture.hpp" #include "../PythonPluginSearchPaths.hpp" @@ -37,10 +39,7 @@ using namespace openstudio::model; TEST_F(ModelFixture, PythonPluginSearchPaths_GettersSetters) { Model m; - // TODO: Check regular Ctor arguments - PythonPluginSearchPaths pythonPluginSearchPaths(m); - // TODO: Or if a UniqueModelObject (and make sure _Impl is included) - // PythonPluginSearchPaths pythonPluginSearchPaths = m.getUniqueModelObject(); + PythonPluginSearchPaths pythonPluginSearchPaths = m.getUniqueModelObject(); // Add Current Working Directory to Search Path: Required Boolean EXPECT_TRUE(pythonPluginSearchPaths.setAddCurrentWorkingDirectorytoSearchPath(true)); @@ -59,4 +58,29 @@ TEST_F(ModelFixture, PythonPluginSearchPaths_GettersSetters) { EXPECT_TRUE(pythonPluginSearchPaths.addepinEnvironmentVariabletoSearchPath()); EXPECT_TRUE(pythonPluginSearchPaths.setAddepinEnvironmentVariabletoSearchPath(false)); EXPECT_FALSE(pythonPluginSearchPaths.addepinEnvironmentVariabletoSearchPath()); + + // Search Paths + EXPECT_TRUE(pythonPluginSearchPaths.searchPaths().empty()); + + EXPECT_TRUE(pythonPluginSearchPaths.addSearchPath("/example/search/path/1")); + ASSERT_EQ(1u, pythonPluginSearchPaths.searchPaths().size()); + EXPECT_EQ("/example/search/path/1", pythonPluginSearchPaths.searchPaths()[0]); + + EXPECT_TRUE(pythonPluginSearchPaths.addSearchPath("/example/search/path/1")); + ASSERT_EQ(1u, pythonPluginSearchPaths.searchPaths().size()); + EXPECT_TRUE(pythonPluginSearchPaths.addSearchPath("/example/search/path/2")); + ASSERT_EQ(2u, pythonPluginSearchPaths.searchPaths().size()); + EXPECT_EQ("/example/search/path/1", pythonPluginSearchPaths.searchPaths()[0]); + EXPECT_EQ("/example/search/path/2", pythonPluginSearchPaths.searchPaths()[1]); + + std::vector searchPaths({"path/3", "path/4"}); + EXPECT_TRUE(pythonPluginSearchPaths.setSearchPaths(searchPaths)); + ASSERT_EQ(4u, pythonPluginSearchPaths.searchPaths().size()); + EXPECT_EQ("/example/search/path/1", pythonPluginSearchPaths.searchPaths()[0]); + EXPECT_EQ("/example/search/path/2", pythonPluginSearchPaths.searchPaths()[1]); + EXPECT_EQ("path/3", pythonPluginSearchPaths.searchPaths()[2]); + EXPECT_EQ("path/4", pythonPluginSearchPaths.searchPaths()[3]); + + pythonPluginSearchPaths.clearSearchPaths(); + EXPECT_EQ(0u, pythonPluginSearchPaths.searchPaths().size()); } From 274602362afd4abb2964895d83a0590c977c70ee Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Thu, 5 Dec 2024 15:06:26 -0700 Subject: [PATCH 08/17] Fix and update the ft test. --- .../Test/PythonPluginSearchPaths_GTest.cpp | 58 +++++++++---------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/src/energyplus/Test/PythonPluginSearchPaths_GTest.cpp b/src/energyplus/Test/PythonPluginSearchPaths_GTest.cpp index d61ccf0842..1ad089fc55 100644 --- a/src/energyplus/Test/PythonPluginSearchPaths_GTest.cpp +++ b/src/energyplus/Test/PythonPluginSearchPaths_GTest.cpp @@ -31,14 +31,16 @@ #include "EnergyPlusFixture.hpp" #include "../ForwardTranslator.hpp" -#include "../ReverseTranslator.hpp" +#include "../../model/Model.hpp" #include "../../model/PythonPluginSearchPaths.hpp" #include "../../model/PythonPluginSearchPaths_Impl.hpp" #include "../../utilities/idf/Workspace.hpp" #include "../../utilities/idf/IdfObject.hpp" #include "../../utilities/idf/WorkspaceObject.hpp" +#include "../../utilities/idf/IdfExtensibleGroup.hpp" +#include "../../utilities/idf/WorkspaceExtensibleGroup.hpp" // E+ FieldEnums #include #include @@ -52,46 +54,40 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_PythonPluginSearchPaths) { ForwardTranslator ft; Model m; - // TODO: Check regular Ctor arguments - PythonPluginSearchPaths pythonPluginSearchPaths(m); - // TODO: Or if a UniqueModelObject (and make sure _Impl is included) - // PythonPluginSearchPaths pythonPluginSearchPaths = m.getUniqueModelObject(); + PythonPluginSearchPaths pythonPluginSearchPaths = m.getUniqueModelObject(); pythonPluginSearchPaths.setName("My PythonPluginSearchPaths"); EXPECT_TRUE(pythonPluginSearchPaths.setAddCurrentWorkingDirectorytoSearchPath(false)); // Opposite from IDD default EXPECT_TRUE(pythonPluginSearchPaths.setAddInputFileDirectorytoSearchPath(false)); // Opposite from IDD default EXPECT_TRUE(pythonPluginSearchPaths.setAddepinEnvironmentVariabletoSearchPath(false)); // Opposite from IDD default - // TODO: you're responsible for creating all other objects needed so this object actually gets ForwardTranslated + EXPECT_TRUE(pythonPluginSearchPaths.searchPaths().empty()); + // No search paths; not translated + { + const Workspace w = ft.translateModel(m); - const Workspace w = ft.translateModel(m); - const auto idfObjs = w.getObjectsByType(IddObjectType::PythonPlugin_SearchPaths); - ASSERT_EQ(1u, idfObjs.size()); + const auto idfObjs = w.getObjectsByType(IddObjectType::PythonPlugin_SearchPaths); + ASSERT_EQ(0u, idfObjs.size()); + } - const auto& idfObject = idfObjs.front(); - EXPECT_EQ("No", idfObject.getString(PythonPlugin_SearchPathsFields::AddCurrentWorkingDirectorytoSearchPath).get()); - EXPECT_EQ("No", idfObject.getString(PythonPlugin_SearchPathsFields::AddInputFileDirectorytoSearchPath).get()); - EXPECT_EQ("No", idfObject.getString(PythonPlugin_SearchPathsFields::AddepinEnvironmentVariabletoSearchPath).get()); -} -TEST_F(EnergyPlusFixture, ReverseTranslator_PythonPluginSearchPaths) { - - ReverseTranslator rt; - - Workspace w(StrictnessLevel::Minimal, IddFileType::EnergyPlus); + { + std::vector searchPaths({"/path/to/lib1", "/path/to/lib2"}); + EXPECT_TRUE(pythonPluginSearchPaths.setSearchPaths(searchPaths)); + EXPECT_EQ(2u, pythonPluginSearchPaths.searchPaths().size()); - auto woPPSP = w.addObject(IdfObject(IddObjectType::PythonPlugin_SearchPaths)).get(); + const Workspace w = ft.translateModel(m); - woPPSP.setName("My PythonPluginSearchPaths"); - EXPECT_TRUE(woPPSP.setString(PythonPlugin_SearchPathsFields::AddCurrentWorkingDirectorytoSearchPath, "No")); // Opposite from IDD default - EXPECT_TRUE(woPPSP.setString(PythonPlugin_SearchPathsFields::AddInputFileDirectorytoSearchPath, "No")); // Opposite from IDD default - EXPECT_TRUE(woPPSP.setString(PythonPlugin_SearchPathsFields::AddepinEnvironmentVariabletoSearchPath, "No")); // Opposite from IDD default + const auto idfObjs = w.getObjectsByType(IddObjectType::PythonPlugin_SearchPaths); + ASSERT_EQ(1u, idfObjs.size()); - const Model m = rt.translateWorkspace(w); - const auto modelObjects = m.getConcreteModelObjects(); - ASSERT_EQ(1u, modelObjects.size()); + const auto& idfObject = idfObjs.front(); + EXPECT_EQ("No", idfObject.getString(PythonPlugin_SearchPathsFields::AddCurrentWorkingDirectorytoSearchPath).get()); + EXPECT_EQ("No", idfObject.getString(PythonPlugin_SearchPathsFields::AddInputFileDirectorytoSearchPath).get()); + EXPECT_EQ("No", idfObject.getString(PythonPlugin_SearchPathsFields::AddepinEnvironmentVariabletoSearchPath).get()); - const auto& modelObject = modelObjects.front(); - EXPECT_FALSE(modelObject.addCurrentWorkingDirectorytoSearchPath()); - EXPECT_FALSE(modelObject.addInputFileDirectorytoSearchPath()); - EXPECT_FALSE(modelObject.addepinEnvironmentVariabletoSearchPath()); + ASSERT_EQ(2u, idfObject.extensibleGroups().size()); + for (int i = 0; i < 2; ++i) { + EXPECT_EQ(searchPaths[i], idfObject.extensibleGroups()[i].getString(PythonPlugin_SearchPathsExtensibleFields::SearchPath).get()); + } + } } From 51ceb0f511d8808a52f96f2b510291e9fd3da954 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Thu, 5 Dec 2024 20:40:42 -0700 Subject: [PATCH 09/17] Clean up ft and add extensible groups. --- ...orwardTranslatePythonPluginSearchPaths.cpp | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/energyplus/ForwardTranslator/ForwardTranslatePythonPluginSearchPaths.cpp b/src/energyplus/ForwardTranslator/ForwardTranslatePythonPluginSearchPaths.cpp index 45dffc2945..6e1be37bb4 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslatePythonPluginSearchPaths.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslatePythonPluginSearchPaths.cpp @@ -32,9 +32,13 @@ #include "../../model/PythonPluginSearchPaths.hpp" +#include "../../utilities/idf/IdfExtensibleGroup.hpp" + #include #include +constexpr static auto pythonSearchPathsName = "Python Plugin Search Paths"; + using namespace openstudio::model; namespace openstudio { @@ -43,20 +47,14 @@ namespace energyplus { boost::optional ForwardTranslator::translatePythonPluginSearchPaths(model::PythonPluginSearchPaths& modelObject) { - // Instantiate an IdfObject of the class to store the values - IdfObject idfObject = createRegisterAndNameIdfObject(openstudio::IddObjectType::PythonPlugin_SearchPaths, modelObject); - // If it doesn't have a name, or if you aren't sure you are going to want to return it - // IdfObject idfObject(openstudio::IddObjectType::PythonPlugin_SearchPaths); - // m_idfObjects.push_back(idfObject); + auto searchPaths = modelObject.searchPaths(); + if (searchPaths.empty()) { + return boost::none; + } - // TODO: Note JM 2018-10-17 - // You are responsible for implementing any additional logic based on choice fields, etc. - // The ForwardTranslator generator script is meant to facilitate your work, not get you 100% of the way + IdfObject idfObject = createAndRegisterIdfObject(openstudio::IddObjectType::PythonPlugin_SearchPaths, modelObject); - // TODO: If you keep createRegisterAndNameIdfObject above, you don't need this. - // But in some cases, you'll want to handle failure without pushing to the map - // Name - idfObject.setName(modelObject.nameString()); + idfObject.setName(pythonSearchPathsName); // Add Current Working Directory to Search Path: Optional Boolean if (modelObject.addCurrentWorkingDirectorytoSearchPath()) { @@ -79,6 +77,12 @@ namespace energyplus { idfObject.setString(PythonPlugin_SearchPathsFields::AddepinEnvironmentVariabletoSearchPath, "No"); } + // Search Path + for (const std::string& searchPath : modelObject.searchPaths()) { + IdfExtensibleGroup eg = idfObject.pushExtensibleGroup(); + eg.setString(PythonPlugin_SearchPathsExtensibleFields::SearchPath, searchPath); + } + return idfObject; } // End of translate function From 12e5f327cfd1ebe52148c08c6833e25c20eb18df Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Thu, 5 Dec 2024 20:41:11 -0700 Subject: [PATCH 10/17] Move searchpaths ft before instance ft. --- src/energyplus/ForwardTranslator.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/energyplus/ForwardTranslator.cpp b/src/energyplus/ForwardTranslator.cpp index 60cd6517c5..10432603e3 100644 --- a/src/energyplus/ForwardTranslator.cpp +++ b/src/energyplus/ForwardTranslator.cpp @@ -3607,11 +3607,12 @@ namespace energyplus { IddObjectType::OS_ExternalInterface_FunctionalMockupUnitImport_To_Schedule, IddObjectType::OS_ExternalInterface_FunctionalMockupUnitImport_To_Variable, + IddObjectType:: + OS_PythonPlugin_SearchPaths, // this FT intentionally happens before PythonPlugin_Instance so that we can't end up with two PythonPlugin_SearchPaths objects IddObjectType::OS_PythonPlugin_Instance, IddObjectType::OS_PythonPlugin_Variable, IddObjectType::OS_PythonPlugin_TrendVariable, IddObjectType::OS_PythonPlugin_OutputVariable, - IddObjectType::OS_PythonPlugin_SearchPaths, }; return result; From 1ac5bb6c12feb3bb50dc2d00424ac95c331c26ad Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Thu, 5 Dec 2024 20:41:23 -0700 Subject: [PATCH 11/17] Update model and ft tests. --- .../Test/PythonPluginSearchPaths_GTest.cpp | 42 ++++++++++++++++++- .../test/PythonPluginSearchPaths_GTest.cpp | 11 +++-- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/energyplus/Test/PythonPluginSearchPaths_GTest.cpp b/src/energyplus/Test/PythonPluginSearchPaths_GTest.cpp index 1ad089fc55..c5c1e2c150 100644 --- a/src/energyplus/Test/PythonPluginSearchPaths_GTest.cpp +++ b/src/energyplus/Test/PythonPluginSearchPaths_GTest.cpp @@ -35,16 +35,24 @@ #include "../../model/Model.hpp" #include "../../model/PythonPluginSearchPaths.hpp" #include "../../model/PythonPluginSearchPaths_Impl.hpp" +#include "../../model/ExternalFile.hpp" +#include "../../model/ExternalFile_Impl.hpp" +#include "../../model/PythonPluginInstance.hpp" +#include "../../model/PythonPluginInstance_Impl.hpp" #include "../../utilities/idf/Workspace.hpp" #include "../../utilities/idf/IdfObject.hpp" #include "../../utilities/idf/WorkspaceObject.hpp" #include "../../utilities/idf/IdfExtensibleGroup.hpp" #include "../../utilities/idf/WorkspaceExtensibleGroup.hpp" +#include "../../utilities/core/PathHelpers.hpp" // E+ FieldEnums #include #include #include + +#include + using namespace openstudio::energyplus; using namespace openstudio::model; using namespace openstudio; @@ -73,7 +81,7 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_PythonPluginSearchPaths) { { std::vector searchPaths({"/path/to/lib1", "/path/to/lib2"}); EXPECT_TRUE(pythonPluginSearchPaths.setSearchPaths(searchPaths)); - EXPECT_EQ(2u, pythonPluginSearchPaths.searchPaths().size()); + EXPECT_EQ(2u, pythonPluginSearchPaths.searchPaths().size()); const Workspace w = ft.translateModel(m); @@ -90,4 +98,36 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_PythonPluginSearchPaths) { EXPECT_EQ(searchPaths[i], idfObject.extensibleGroups()[i].getString(PythonPlugin_SearchPathsExtensibleFields::SearchPath).get()); } } + + { + openstudio::path p = resourcesPath() / toPath("model/PythonPluginThermochromicWindow.py"); + ASSERT_TRUE(exists(p)); + + boost::optional externalfile = ExternalFile::getExternalFile(m, openstudio::toString(p)); + ASSERT_TRUE(externalfile) << "Path doesn't exist: '" << p << "'"; + + PythonPluginInstance pythonPluginInstance(*externalfile, "ZN_1_wall_south_Window_1_Control"); + + std::vector searchPaths({"/path/to/lib1", "/path/to/lib2"}); + EXPECT_TRUE(pythonPluginSearchPaths.setSearchPaths(searchPaths)); + EXPECT_EQ(2u, pythonPluginSearchPaths.searchPaths().size()); + + const Workspace w = ft.translateModel(m); + + const auto idfObjs = w.getObjectsByType(IddObjectType::PythonPlugin_SearchPaths); + ASSERT_EQ(1u, idfObjs.size()); + + const auto& idfObject = idfObjs.front(); + EXPECT_EQ("No", idfObject.getString(PythonPlugin_SearchPathsFields::AddCurrentWorkingDirectorytoSearchPath).get()); + EXPECT_EQ("No", idfObject.getString(PythonPlugin_SearchPathsFields::AddInputFileDirectorytoSearchPath).get()); + EXPECT_EQ("No", idfObject.getString(PythonPlugin_SearchPathsFields::AddepinEnvironmentVariabletoSearchPath).get()); + + ASSERT_EQ(3u, idfObject.extensibleGroups().size()); + for (int i = 0; i < 2; ++i) { + EXPECT_EQ(searchPaths[i], idfObject.extensibleGroups()[i].getString(PythonPlugin_SearchPathsExtensibleFields::SearchPath).get()); + } + // since PythonPlugin_Instance is translated after PythonPlugin_SearchPaths, this search path is appended to the existing search paths + EXPECT_EQ(openstudio::toString(externalfile->filePath().parent_path()), + idfObject.extensibleGroups()[2].getString(PythonPlugin_SearchPathsExtensibleFields::SearchPath).get()); + } } diff --git a/src/model/test/PythonPluginSearchPaths_GTest.cpp b/src/model/test/PythonPluginSearchPaths_GTest.cpp index 887911e58d..e09200a76a 100644 --- a/src/model/test/PythonPluginSearchPaths_GTest.cpp +++ b/src/model/test/PythonPluginSearchPaths_GTest.cpp @@ -73,13 +73,12 @@ TEST_F(ModelFixture, PythonPluginSearchPaths_GettersSetters) { EXPECT_EQ("/example/search/path/1", pythonPluginSearchPaths.searchPaths()[0]); EXPECT_EQ("/example/search/path/2", pythonPluginSearchPaths.searchPaths()[1]); - std::vector searchPaths({"path/3", "path/4"}); + std::vector searchPaths({"path/3", "path/4", "path/5", "path/5"}); EXPECT_TRUE(pythonPluginSearchPaths.setSearchPaths(searchPaths)); - ASSERT_EQ(4u, pythonPluginSearchPaths.searchPaths().size()); - EXPECT_EQ("/example/search/path/1", pythonPluginSearchPaths.searchPaths()[0]); - EXPECT_EQ("/example/search/path/2", pythonPluginSearchPaths.searchPaths()[1]); - EXPECT_EQ("path/3", pythonPluginSearchPaths.searchPaths()[2]); - EXPECT_EQ("path/4", pythonPluginSearchPaths.searchPaths()[3]); + ASSERT_EQ(3u, pythonPluginSearchPaths.searchPaths().size()); + EXPECT_EQ("path/3", pythonPluginSearchPaths.searchPaths()[0]); + EXPECT_EQ("path/4", pythonPluginSearchPaths.searchPaths()[1]); + EXPECT_EQ("path/5", pythonPluginSearchPaths.searchPaths()[2]); pythonPluginSearchPaths.clearSearchPaths(); EXPECT_EQ(0u, pythonPluginSearchPaths.searchPaths().size()); From 991022bd0a9c710c1e1dc47901433b440f585617 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Thu, 12 Dec 2024 09:12:17 -0700 Subject: [PATCH 12/17] Add override to destructor. --- src/model/PythonPluginSearchPaths.hpp | 2 +- src/model/PythonPluginSearchPaths_Impl.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/model/PythonPluginSearchPaths.hpp b/src/model/PythonPluginSearchPaths.hpp index 8d5d9e536e..d29b3a4305 100644 --- a/src/model/PythonPluginSearchPaths.hpp +++ b/src/model/PythonPluginSearchPaths.hpp @@ -49,7 +49,7 @@ namespace model { /** @name Constructors and Destructors */ //@{ - virtual ~PythonPluginSearchPaths() = default; + virtual ~PythonPluginSearchPaths() override = default; // Default the copy and move operators because the virtual dtor is explicit PythonPluginSearchPaths(const PythonPluginSearchPaths& other) = default; PythonPluginSearchPaths(PythonPluginSearchPaths&& other) = default; diff --git a/src/model/PythonPluginSearchPaths_Impl.hpp b/src/model/PythonPluginSearchPaths_Impl.hpp index 3c436e86bb..a619aafbc6 100644 --- a/src/model/PythonPluginSearchPaths_Impl.hpp +++ b/src/model/PythonPluginSearchPaths_Impl.hpp @@ -51,7 +51,7 @@ namespace model { PythonPluginSearchPaths_Impl(const PythonPluginSearchPaths_Impl& other, Model_Impl* model, bool keepHandle); - virtual ~PythonPluginSearchPaths_Impl() = default; + virtual ~PythonPluginSearchPaths_Impl() override = default; //@} /** @name Virtual Methods */ From d05a5aa9373025f9fccedcbf7bbf0e1e9b7f94ff Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Thu, 12 Dec 2024 09:47:39 -0700 Subject: [PATCH 13/17] Update ctor to set required fields. --- .../Test/PythonPluginSearchPaths_GTest.cpp | 36 +++++++++++++++++-- src/model/PythonPluginSearchPaths.cpp | 6 +++- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/energyplus/Test/PythonPluginSearchPaths_GTest.cpp b/src/energyplus/Test/PythonPluginSearchPaths_GTest.cpp index c5c1e2c150..2fd2f666c1 100644 --- a/src/energyplus/Test/PythonPluginSearchPaths_GTest.cpp +++ b/src/energyplus/Test/PythonPluginSearchPaths_GTest.cpp @@ -65,13 +65,14 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_PythonPluginSearchPaths) { PythonPluginSearchPaths pythonPluginSearchPaths = m.getUniqueModelObject(); pythonPluginSearchPaths.setName("My PythonPluginSearchPaths"); - EXPECT_TRUE(pythonPluginSearchPaths.setAddCurrentWorkingDirectorytoSearchPath(false)); // Opposite from IDD default - EXPECT_TRUE(pythonPluginSearchPaths.setAddInputFileDirectorytoSearchPath(false)); // Opposite from IDD default - EXPECT_TRUE(pythonPluginSearchPaths.setAddepinEnvironmentVariabletoSearchPath(false)); // Opposite from IDD default EXPECT_TRUE(pythonPluginSearchPaths.searchPaths().empty()); // No search paths; not translated { + EXPECT_TRUE(pythonPluginSearchPaths.setAddCurrentWorkingDirectorytoSearchPath(false)); // Opposite from IDD default + EXPECT_TRUE(pythonPluginSearchPaths.setAddInputFileDirectorytoSearchPath(false)); // Opposite from IDD default + EXPECT_TRUE(pythonPluginSearchPaths.setAddepinEnvironmentVariabletoSearchPath(false)); // Opposite from IDD default + const Workspace w = ft.translateModel(m); const auto idfObjs = w.getObjectsByType(IddObjectType::PythonPlugin_SearchPaths); @@ -88,6 +89,31 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_PythonPluginSearchPaths) { const auto idfObjs = w.getObjectsByType(IddObjectType::PythonPlugin_SearchPaths); ASSERT_EQ(1u, idfObjs.size()); + const auto& idfObject = idfObjs.front(); + EXPECT_EQ("Yes", idfObject.getString(PythonPlugin_SearchPathsFields::AddCurrentWorkingDirectorytoSearchPath).get()); + EXPECT_EQ("Yes", idfObject.getString(PythonPlugin_SearchPathsFields::AddInputFileDirectorytoSearchPath).get()); + EXPECT_EQ("Yes", idfObject.getString(PythonPlugin_SearchPathsFields::AddepinEnvironmentVariabletoSearchPath).get()); + + ASSERT_EQ(2u, idfObject.extensibleGroups().size()); + for (int i = 0; i < 2; ++i) { + EXPECT_EQ(searchPaths[i], idfObject.extensibleGroups()[i].getString(PythonPlugin_SearchPathsExtensibleFields::SearchPath).get()); + } + } + + { + EXPECT_TRUE(pythonPluginSearchPaths.setAddCurrentWorkingDirectorytoSearchPath(false)); // Opposite from IDD default + EXPECT_TRUE(pythonPluginSearchPaths.setAddInputFileDirectorytoSearchPath(false)); // Opposite from IDD default + EXPECT_TRUE(pythonPluginSearchPaths.setAddepinEnvironmentVariabletoSearchPath(false)); // Opposite from IDD default + + std::vector searchPaths({"/path/to/lib1", "/path/to/lib2"}); + EXPECT_TRUE(pythonPluginSearchPaths.setSearchPaths(searchPaths)); + EXPECT_EQ(2u, pythonPluginSearchPaths.searchPaths().size()); + + const Workspace w = ft.translateModel(m); + + const auto idfObjs = w.getObjectsByType(IddObjectType::PythonPlugin_SearchPaths); + ASSERT_EQ(1u, idfObjs.size()); + const auto& idfObject = idfObjs.front(); EXPECT_EQ("No", idfObject.getString(PythonPlugin_SearchPathsFields::AddCurrentWorkingDirectorytoSearchPath).get()); EXPECT_EQ("No", idfObject.getString(PythonPlugin_SearchPathsFields::AddInputFileDirectorytoSearchPath).get()); @@ -100,6 +126,10 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_PythonPluginSearchPaths) { } { + EXPECT_TRUE(pythonPluginSearchPaths.setAddCurrentWorkingDirectorytoSearchPath(false)); // Opposite from IDD default + EXPECT_TRUE(pythonPluginSearchPaths.setAddInputFileDirectorytoSearchPath(false)); // Opposite from IDD default + EXPECT_TRUE(pythonPluginSearchPaths.setAddepinEnvironmentVariabletoSearchPath(false)); // Opposite from IDD default + openstudio::path p = resourcesPath() / toPath("model/PythonPluginThermochromicWindow.py"); ASSERT_TRUE(exists(p)); diff --git a/src/model/PythonPluginSearchPaths.cpp b/src/model/PythonPluginSearchPaths.cpp index 633c173f3f..6b76ee58dc 100644 --- a/src/model/PythonPluginSearchPaths.cpp +++ b/src/model/PythonPluginSearchPaths.cpp @@ -196,7 +196,11 @@ namespace model { /// @cond PythonPluginSearchPaths::PythonPluginSearchPaths(std::shared_ptr impl) : ParentObject(std::move(impl)) {} - PythonPluginSearchPaths::PythonPluginSearchPaths(Model& model) : ParentObject(PythonPluginSearchPaths::iddObjectType(), model) {} + PythonPluginSearchPaths::PythonPluginSearchPaths(Model& model) : ParentObject(PythonPluginSearchPaths::iddObjectType(), model) { + setAddCurrentWorkingDirectorytoSearchPath(true); + setAddInputFileDirectorytoSearchPath(true); + setAddepinEnvironmentVariabletoSearchPath(true); + } /// @endcond From deeb88fe2b19c0c5fa9bf782a81e1cc39fc137ba Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Fri, 13 Dec 2024 13:53:20 -0700 Subject: [PATCH 14/17] Update ft test. --- src/energyplus/Test/PythonPluginSearchPaths_GTest.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/energyplus/Test/PythonPluginSearchPaths_GTest.cpp b/src/energyplus/Test/PythonPluginSearchPaths_GTest.cpp index 2fd2f666c1..9cf134d64a 100644 --- a/src/energyplus/Test/PythonPluginSearchPaths_GTest.cpp +++ b/src/energyplus/Test/PythonPluginSearchPaths_GTest.cpp @@ -80,6 +80,10 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_PythonPluginSearchPaths) { } { + EXPECT_TRUE(pythonPluginSearchPaths.setAddCurrentWorkingDirectorytoSearchPath(true)); + EXPECT_TRUE(pythonPluginSearchPaths.setAddInputFileDirectorytoSearchPath(true)); + EXPECT_TRUE(pythonPluginSearchPaths.setAddepinEnvironmentVariabletoSearchPath(true)); + std::vector searchPaths({"/path/to/lib1", "/path/to/lib2"}); EXPECT_TRUE(pythonPluginSearchPaths.setSearchPaths(searchPaths)); EXPECT_EQ(2u, pythonPluginSearchPaths.searchPaths().size()); From a24430a9155d69bd82d8296d68e342cfcf5eee8e Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Thu, 19 Dec 2024 12:59:40 +0100 Subject: [PATCH 15/17] Make it be a ModelObject, it's got no business being a ParentObject --- src/model/PythonPluginSearchPaths.cpp | 10 +++++----- src/model/PythonPluginSearchPaths.hpp | 6 +++--- src/model/PythonPluginSearchPaths_Impl.hpp | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/model/PythonPluginSearchPaths.cpp b/src/model/PythonPluginSearchPaths.cpp index 6b76ee58dc..4b13b08ed6 100644 --- a/src/model/PythonPluginSearchPaths.cpp +++ b/src/model/PythonPluginSearchPaths.cpp @@ -42,18 +42,18 @@ namespace model { namespace detail { PythonPluginSearchPaths_Impl::PythonPluginSearchPaths_Impl(const IdfObject& idfObject, Model_Impl* model, bool keepHandle) - : ParentObject_Impl(idfObject, model, keepHandle) { + : ModelObject_Impl(idfObject, model, keepHandle) { OS_ASSERT(idfObject.iddObject().type() == PythonPluginSearchPaths::iddObjectType()); } PythonPluginSearchPaths_Impl::PythonPluginSearchPaths_Impl(const openstudio::detail::WorkspaceObject_Impl& other, Model_Impl* model, bool keepHandle) - : ParentObject_Impl(other, model, keepHandle) { + : ModelObject_Impl(other, model, keepHandle) { OS_ASSERT(other.iddObject().type() == PythonPluginSearchPaths::iddObjectType()); } PythonPluginSearchPaths_Impl::PythonPluginSearchPaths_Impl(const PythonPluginSearchPaths_Impl& other, Model_Impl* model, bool keepHandle) - : ParentObject_Impl(other, model, keepHandle) {} + : ModelObject_Impl(other, model, keepHandle) {} const std::vector& PythonPluginSearchPaths_Impl::outputVariableNames() const { static std::vector result; @@ -195,8 +195,8 @@ namespace model { } /// @cond - PythonPluginSearchPaths::PythonPluginSearchPaths(std::shared_ptr impl) : ParentObject(std::move(impl)) {} - PythonPluginSearchPaths::PythonPluginSearchPaths(Model& model) : ParentObject(PythonPluginSearchPaths::iddObjectType(), model) { + PythonPluginSearchPaths::PythonPluginSearchPaths(std::shared_ptr impl) : ModelObject(std::move(impl)) {} + PythonPluginSearchPaths::PythonPluginSearchPaths(Model& model) : ModelObject(PythonPluginSearchPaths::iddObjectType(), model) { setAddCurrentWorkingDirectorytoSearchPath(true); setAddInputFileDirectorytoSearchPath(true); setAddepinEnvironmentVariabletoSearchPath(true); diff --git a/src/model/PythonPluginSearchPaths.hpp b/src/model/PythonPluginSearchPaths.hpp index d29b3a4305..0e43f616c4 100644 --- a/src/model/PythonPluginSearchPaths.hpp +++ b/src/model/PythonPluginSearchPaths.hpp @@ -31,7 +31,7 @@ #define MODEL_PYTHONPLUGINSEARCHPATHS_HPP #include -#include "ParentObject.hpp" +#include "ModelObject.hpp" namespace openstudio { namespace model { @@ -42,8 +42,8 @@ namespace model { } // namespace detail - /** PythonPluginSearchPaths is a ParentObject that wraps the OpenStudio IDD object 'OS:PythonPlugin:SearchPaths'. */ - class MODEL_API PythonPluginSearchPaths : public ParentObject + /** PythonPluginSearchPaths is a ModelObject that wraps the OpenStudio IDD object 'OS:PythonPlugin:SearchPaths'. */ + class MODEL_API PythonPluginSearchPaths : public ModelObject { public: /** @name Constructors and Destructors */ diff --git a/src/model/PythonPluginSearchPaths_Impl.hpp b/src/model/PythonPluginSearchPaths_Impl.hpp index a619aafbc6..21551c4780 100644 --- a/src/model/PythonPluginSearchPaths_Impl.hpp +++ b/src/model/PythonPluginSearchPaths_Impl.hpp @@ -31,15 +31,15 @@ #define MODEL_PYTHONPLUGINSEARCHPATHS_IMPL_HPP #include -#include "ParentObject_Impl.hpp" +#include "ModelObject_Impl.hpp" namespace openstudio { namespace model { namespace detail { - /** PythonPluginSearchPaths_Impl is a ParentObject_Impl that is the implementation class for PythonPluginSearchPaths.*/ - class MODEL_API PythonPluginSearchPaths_Impl : public ParentObject_Impl + /** PythonPluginSearchPaths_Impl is a ModelObject_Impl that is the implementation class for PythonPluginSearchPaths.*/ + class MODEL_API PythonPluginSearchPaths_Impl : public ModelObject_Impl { public: /** @name Constructors and Destructors */ From 7f1cac23f4374b401927ebd102ae552bf97b010a Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Thu, 19 Dec 2024 13:00:25 +0100 Subject: [PATCH 16/17] Make the implementation use openstudio::path, keeping a std::string addSearchPath/setSearchPaths for convenience --- ...orwardTranslatePythonPluginSearchPaths.cpp | 4 +- src/model/PythonPluginSearchPaths.cpp | 38 ++++++++++++------- src/model/PythonPluginSearchPaths.hpp | 9 ++++- src/model/PythonPluginSearchPaths_Impl.hpp | 7 ++-- 4 files changed, 38 insertions(+), 20 deletions(-) diff --git a/src/energyplus/ForwardTranslator/ForwardTranslatePythonPluginSearchPaths.cpp b/src/energyplus/ForwardTranslator/ForwardTranslatePythonPluginSearchPaths.cpp index 6e1be37bb4..dce66cea4f 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslatePythonPluginSearchPaths.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslatePythonPluginSearchPaths.cpp @@ -78,9 +78,9 @@ namespace energyplus { } // Search Path - for (const std::string& searchPath : modelObject.searchPaths()) { + for (const openstudio::path& searchPath : modelObject.searchPaths()) { IdfExtensibleGroup eg = idfObject.pushExtensibleGroup(); - eg.setString(PythonPlugin_SearchPathsExtensibleFields::SearchPath, searchPath); + eg.setString(PythonPlugin_SearchPathsExtensibleFields::SearchPath, searchPath.generic_string()); } return idfObject; diff --git a/src/model/PythonPluginSearchPaths.cpp b/src/model/PythonPluginSearchPaths.cpp index 4b13b08ed6..d88f5763ee 100644 --- a/src/model/PythonPluginSearchPaths.cpp +++ b/src/model/PythonPluginSearchPaths.cpp @@ -32,10 +32,13 @@ #include "../utilities/idf/WorkspaceExtensibleGroup.hpp" #include "../utilities/core/Assert.hpp" +#include "../utilities/core/Path.hpp" #include #include +#include + namespace openstudio { namespace model { @@ -78,12 +81,12 @@ namespace model { return getBooleanFieldValue(OS_PythonPlugin_SearchPathsFields::AddepinEnvironmentVariabletoSearchPath); } - std::vector PythonPluginSearchPaths_Impl::searchPaths() const { - std::vector result; + std::vector PythonPluginSearchPaths_Impl::searchPaths() const { + std::vector result; for (const auto& eg : extensibleGroups()) { auto _s = eg.getString(OS_PythonPlugin_SearchPathsExtensibleFields::SearchPath); OS_ASSERT(_s); - result.push_back(_s.get()); + result.push_back(openstudio::toPath(_s.get())); } return result; } @@ -109,18 +112,16 @@ namespace model { return result; } - bool PythonPluginSearchPaths_Impl::addSearchPath(const std::string& searchPath) { - std::vector existingSearchPaths = this->searchPaths(); - if (std::find_if(existingSearchPaths.begin(), existingSearchPaths.end(), - [&searchPath](const std::string& s) { return openstudio::istringEqual(s, searchPath); }) - != existingSearchPaths.end()) { + bool PythonPluginSearchPaths_Impl::addSearchPath(const openstudio::path& searchPath) { + std::vector existingSearchPaths = this->searchPaths(); + if (std::find(existingSearchPaths.begin(), existingSearchPaths.end(), searchPath) != existingSearchPaths.end()) { LOG(Info, "Not adding search path '" << searchPath << "' to PythonPlugin:SearchPaths since it is already present"); // Return true anyways, it's a success return true; } auto eg = getObject().pushExtensibleGroup().cast(); - bool result = eg.setString(OS_PythonPlugin_SearchPathsExtensibleFields::SearchPath, searchPath); + bool result = eg.setString(OS_PythonPlugin_SearchPathsExtensibleFields::SearchPath, searchPath.generic_string()); if (!result) { getObject().eraseExtensibleGroup(eg.groupIndex()); } @@ -128,7 +129,7 @@ namespace model { return result; } - bool PythonPluginSearchPaths_Impl::setSearchPaths(const std::vector& searchPaths) { + bool PythonPluginSearchPaths_Impl::setSearchPaths(const std::vector& searchPaths) { bool result = true; clearSearchPaths(); @@ -166,7 +167,7 @@ namespace model { return getImpl()->addepinEnvironmentVariabletoSearchPath(); } - std::vector PythonPluginSearchPaths::searchPaths() const { + std::vector PythonPluginSearchPaths::searchPaths() const { return getImpl()->searchPaths(); } @@ -182,14 +183,25 @@ namespace model { return getImpl()->setAddepinEnvironmentVariabletoSearchPath(addepinEnvironmentVariabletoSearchPath); } - bool PythonPluginSearchPaths::addSearchPath(const std::string& searchPath) { + bool PythonPluginSearchPaths::addSearchPath(const openstudio::path& searchPath) { return getImpl()->addSearchPath(searchPath); } - bool PythonPluginSearchPaths::setSearchPaths(const std::vector& searchPaths) { + bool PythonPluginSearchPaths::setSearchPaths(const std::vector& searchPaths) { return getImpl()->setSearchPaths(searchPaths); } + bool PythonPluginSearchPaths::addSearchPath(const std::string& searchPath) { + return getImpl()->addSearchPath(openstudio::toPath(searchPath)); + } + + bool PythonPluginSearchPaths::setSearchPaths(const std::vector& searchPaths) { + std::vector paths; + paths.reserve(searchPaths.size()); + std::transform(searchPaths.cbegin(), searchPaths.cend(), std::back_inserter(paths), [](const std::string& s) { return openstudio::toPath(s); }); + return getImpl()->setSearchPaths(paths); + } + void PythonPluginSearchPaths::clearSearchPaths() { getImpl()->clearSearchPaths(); } diff --git a/src/model/PythonPluginSearchPaths.hpp b/src/model/PythonPluginSearchPaths.hpp index 0e43f616c4..3edb0275f3 100644 --- a/src/model/PythonPluginSearchPaths.hpp +++ b/src/model/PythonPluginSearchPaths.hpp @@ -33,6 +33,8 @@ #include #include "ModelObject.hpp" +#include "../utilities/core/Filesystem.hpp" + namespace openstudio { namespace model { @@ -69,7 +71,7 @@ namespace model { bool addepinEnvironmentVariabletoSearchPath() const; - std::vector searchPaths() const; + std::vector searchPaths() const; //@} /** @name Setters */ @@ -81,8 +83,11 @@ namespace model { bool setAddepinEnvironmentVariabletoSearchPath(bool addepinEnvironmentVariabletoSearchPath); - bool addSearchPath(const std::string& searchPath); + bool addSearchPath(const openstudio::path& searchPath); + bool setSearchPaths(const std::vector& searchPaths); + // Convenience, forwards to the openstudio::path equivalent + bool addSearchPath(const std::string& searchPath); bool setSearchPaths(const std::vector& searchPaths); void clearSearchPaths(); diff --git a/src/model/PythonPluginSearchPaths_Impl.hpp b/src/model/PythonPluginSearchPaths_Impl.hpp index 21551c4780..5afa04eedb 100644 --- a/src/model/PythonPluginSearchPaths_Impl.hpp +++ b/src/model/PythonPluginSearchPaths_Impl.hpp @@ -32,6 +32,7 @@ #include #include "ModelObject_Impl.hpp" +#include "../utilities/core/Filesystem.hpp" namespace openstudio { namespace model { @@ -71,7 +72,7 @@ namespace model { bool addepinEnvironmentVariabletoSearchPath() const; - std::vector searchPaths() const; + std::vector searchPaths() const; //@} /** @name Setters */ @@ -83,9 +84,9 @@ namespace model { bool setAddepinEnvironmentVariabletoSearchPath(bool addepinEnvironmentVariabletoSearchPath); - bool addSearchPath(const std::string& searchPath); + bool addSearchPath(const openstudio::path& searchPath); - bool setSearchPaths(const std::vector& searchPaths); + bool setSearchPaths(const std::vector& searchPaths); void clearSearchPaths(); From 187352f477bfd68ee7e4c957d792228cbc13f849 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Thu, 19 Dec 2024 14:25:18 +0100 Subject: [PATCH 17/17] Overloaded fs::path and std::string addSearchPath call is ambigous, so remove the std::string one --- src/model/PythonPluginSearchPaths.cpp | 6 ------ src/model/PythonPluginSearchPaths.hpp | 1 - 2 files changed, 7 deletions(-) diff --git a/src/model/PythonPluginSearchPaths.cpp b/src/model/PythonPluginSearchPaths.cpp index d88f5763ee..9d3cf29a81 100644 --- a/src/model/PythonPluginSearchPaths.cpp +++ b/src/model/PythonPluginSearchPaths.cpp @@ -60,8 +60,6 @@ namespace model { const std::vector& PythonPluginSearchPaths_Impl::outputVariableNames() const { static std::vector result; - if (result.empty()) { - } return result; } @@ -191,10 +189,6 @@ namespace model { return getImpl()->setSearchPaths(searchPaths); } - bool PythonPluginSearchPaths::addSearchPath(const std::string& searchPath) { - return getImpl()->addSearchPath(openstudio::toPath(searchPath)); - } - bool PythonPluginSearchPaths::setSearchPaths(const std::vector& searchPaths) { std::vector paths; paths.reserve(searchPaths.size()); diff --git a/src/model/PythonPluginSearchPaths.hpp b/src/model/PythonPluginSearchPaths.hpp index 3edb0275f3..a4125abf12 100644 --- a/src/model/PythonPluginSearchPaths.hpp +++ b/src/model/PythonPluginSearchPaths.hpp @@ -87,7 +87,6 @@ namespace model { bool setSearchPaths(const std::vector& searchPaths); // Convenience, forwards to the openstudio::path equivalent - bool addSearchPath(const std::string& searchPath); bool setSearchPaths(const std::vector& searchPaths); void clearSearchPaths();