Skip to content

Conversation

@jmarrec
Copy link
Collaborator

@jmarrec jmarrec commented Mar 21, 2025

Pull request overview

Pull Request Author

  • Model API Changes / Additions
  • Any new or modified fields have been implemented in the EnergyPlus ForwardTranslator (and ReverseTranslator as appropriate)
  • Model API methods are tested (in src/model/test)
  • EnergyPlus ForwardTranslator Tests (in src/energyplus/Test)
  • If a new object or method, added a test in NREL/OpenStudio-resources: Add Link
  • If needed, added VersionTranslation rules for the objects (src/osversion/VersionTranslator.cpp)
  • Verified that C# bindings built fine on Windows, partial classes used as needed, etc.
  • All new and existing tests passes
  • If methods have been deprecated, update rest of code to use the new methods

Labels:

  • If change to an IDD file, add the label IDDChange
  • If breaking existing API, add the label APIChange
  • If deemed ready, add label Pull Request - Ready for CI so that CI builds your PR

Review Checklist

This will not be exhaustively relevant to every PR.

  • Perform a Code Review on GitHub
  • Code Style, strip trailing whitespace, etc.
  • All related changes have been implemented: model changes, model tests, FT changes, FT tests, VersionTranslation, OS App
  • Labeling is ok
  • If defect, verify by running develop branch and reproducing defect, then running PR and reproducing fix
  • If feature, test running new feature, try creative ways to break it
  • CI status: all green or justified

jmarrec added 5 commits March 21, 2025 11:43
I often do this via startup scripts in ruby (.pryrc) /python (.ipython startup), but it could be useful for anyone.
Caveat: it doesn't know if he's the last field or not, so using a comma constantly
* set the CMP0177 which appears safe
* swig_target already depends on the wrapper so It shouldn't be needed
@jmarrec jmarrec added Developer Issue Pull Request - Ready for CI This pull request if finalized and is ready for continuous integration verification prior to merge. labels Mar 21, 2025
@jmarrec jmarrec requested a review from kbenne March 21, 2025 11:36
@jmarrec jmarrec self-assigned this Mar 21, 2025
@jmarrec
Copy link
Collaborator Author

jmarrec commented Mar 21, 2025

Let me demo the initializeFields using Ruby, so it's clearer for anyone reading it:

Initialize the fields, don't fill defaults

[1] OS-build3(main)> i = OpenStudio::IdfObject.new("ShadowCalculation".to_IddObjectType)
=> #<OpenStudio::IdfObject:0x00007b9c9adbf328 @__swigtype__="_p_openstudio__IdfObject">
[2] OS-build3(main)> puts i
ShadowCalculation,
  ,                                       !- Shading Calculation Method
  ;                                       !- Shading Calculation Update Frequency Method

=> nil
[3] OS-build3(main)> i.initializeFields
=> nil
[4] OS-build3(main)> puts i
ShadowCalculation,
  ,                                       !- Shading Calculation Method
  ,                                       !- Shading Calculation Update Frequency Method
  ,                                       !- Shading Calculation Update Frequency
  ,                                       !- Maximum Figures in Shadow Overlap Calculations
  ,                                       !- Polygon Clipping Algorithm
  ,                                       !- Pixel Counting Resolution
  ,                                       !- Sky Diffuse Modeling Algorithm
  ,                                       !- Output External Shading Calculation Results
  ,                                       !- Disable Self-Shading Within Shading Zone Groups
  ;                                       !- Disable Self-Shading From Shading Zone Groups to Other Zones

Initialize fields with the IDD defaults brought in

i = OpenStudio::IdfObject.new("ShadowCalculation".to_IddObjectType); i.initializeFields(true); puts i
ShadowCalculation,
  PolygonClipping,                        !- Shading Calculation Method
  Periodic,                               !- Shading Calculation Update Frequency Method
  20,                                     !- Shading Calculation Update Frequency
  15000,                                  !- Maximum Figures in Shadow Overlap Calculations
  SutherlandHodgman,                      !- Polygon Clipping Algorithm
  512,                                    !- Pixel Counting Resolution
  SimpleSkyDiffuseModeling,               !- Sky Diffuse Modeling Algorithm
  No,                                     !- Output External Shading Calculation Results
  No,                                     !- Disable Self-Shading Within Shading Zone Groups
  No;                                     !- Disable Self-Shading From Shading Zone Groups to Other Zones

It also works with extensible groups

[6] OS-build3(main)> i = OpenStudio::IdfObject.new("Output_Table_Annual".to_IddObjectType); i.pushExtensibleGroup; puts i
Output:Table:Annual,
  ,                                       !- Name
  ,                                       !- Filter
  ,                                       !- Schedule Name
  ,                                       !- Variable or Meter or EMS Variable or Field Name 1
  ,                                       !- Aggregation Type for Variable or Meter 1
  ;                                       !- Digits After Decimal 1

[7] OS-build3(main)> i.initializeFields(true); puts i
Output:Table:Annual,
  ,                                       !- Name
  ,                                       !- Filter
  ,                                       !- Schedule Name
  ,                                       !- Variable or Meter or EMS Variable or Field Name 1
  ,                                       !- Aggregation Type for Variable or Meter 1
  2;                                      !- Digits After Decimal 1

Of course, works with ModelObject too

[9] OS-build3(main)> m = Model.new
=> #<OpenStudio::Model::Model:0x00007b9c9aa746f0 @__swigtype__="_p_openstudio__model__Model">
[10] OS-build3(main)> sc = m.getShadowCalculation
=> #<OpenStudio::Model::ShadowCalculation:0x00007b9c9aa0b830 @__swigtype__="_p_openstudio__model__ShadowCalculation">
[11] OS-build3(main)> puts sc
OS:ShadowCalculation,
  {02a8ca08-782c-4c18-855c-35b9754e3982}, !- Handle
  PolygonClipping,                        !- Shading Calculation Method
  ,                                       !- Shading Calculation Update Frequency Method
  20,                                     !- Shading Calculation Update Frequency
  15000,                                  !- Maximum Figures in Shadow Overlap Calculations
  ,                                       !- Polygon Clipping Algorithm
  512,                                    !- Pixel Counting Resolution
  ,                                       !- Sky Diffuse Modeling Algorithm
  No,                                     !- Output External Shading Calculation Results
  No,                                     !- Disable Self-Shading Within Shading Zone Groups
  No;                                     !- Disable Self-Shading From Shading Zone Groups to Other Zones

=> nil
[12] OS-build3(main)> sc.initializeFields(true)
=> nil
[13] OS-build3(main)> puts sc
OS:ShadowCalculation,
  {02a8ca08-782c-4c18-855c-35b9754e3982}, !- Handle
  PolygonClipping,                        !- Shading Calculation Method
  Periodic,                               !- Shading Calculation Update Frequency Method
  20,                                     !- Shading Calculation Update Frequency
  15000,                                  !- Maximum Figures in Shadow Overlap Calculations
  SutherlandHodgman,                      !- Polygon Clipping Algorithm
  512,                                    !- Pixel Counting Resolution
  SimpleSkyDiffuseModeling,               !- Sky Diffuse Modeling Algorithm
  No,                                     !- Output External Shading Calculation Results
  No,                                     !- Disable Self-Shading Within Shading Zone Groups
  No;                                     !- Disable Self-Shading From Shading Zone Groups to Other Zones


if(BUILD_TESTING)
CREATE_TEST_TARGETS(${target_name} "${${target_name}_test_src}" openstudiolib openstudio_model_resources openstudio_energyplus_resources fmt::fmt)
CREATE_TEST_TARGETS(${target_name} "${${target_name}_test_src}" openstudio_utilities openstudio_model_resources openstudio_energyplus_resources fmt::fmt)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Such a 10x engineer

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well the build of the utilities tests will be 10x I suppose!

Comment on lines +141 to +142
/** \relates IddField */
UTILITIES_API std::ostream& operator<<(std::ostream& os, const IddField& iddField);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Allow printing IddField!

Comment on lines +96 to +102
%extend openstudio::IddField {
std::string __str__() const {
std::ostringstream os;
os << *self;
return os.str();
}
};
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeehaw, it's available in swig! My life is much easier!

Before:

puts iddObject.getField(0).get()
#<OpenStudio::IddField:0x0000793aec6f2840>

After:

puts iddObject.getField(0).get()
  A1, \field Handle
       \type handle
       \required-field

Yeah it works with vectors too.

before:

i = OpenStudio::IdfObject.new("Output_Table_Annual".to_IddObjectType); puts i.iddObject.extensibleGroup
#<OpenStudio::IddField:0x0000793aecb83490>
#<OpenStudio::IddField:0x0000793aecb83468>
#<OpenStudio::IddField:0x0000793aecb833f0>

After:

i = OpenStudio::IdfObject.new("Output_Table_Annual".to_IddObjectType); puts i.iddObject.extensibleGroup
  A4, \field Variable or Meter or EMS Variable or Field Name
       \note contain the name of a variable (see Output:Variable and eplusout.rdd), meter (see Output:Meter
       \note and eplusout.mdd), or EMS Internal Variable Name or IDF Object Field name. This value is shown
       \note using the aggregation method specified.
       \type external-list
       \begin-extensible
       \external-list autoRDDvariableMeter
  A5, \field Aggregation Type for Variable or Meter
       \note The method of aggregation for the selected variable or meter
   [...]

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now you're a 10x engineer for sure!

Comment on lines +266 to +267
// Helper to initialize all fields (if the object currently displays less than numFields), optionally filling the default for a given object
void initializeFields(bool fill_default = false);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should (or does) every newly constructed ModelObject do this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it doesn't. if resizesToMinField instead, which is an annoyance to me, but is conservative on space

Comment on lines +927 to +963
void IdfObject_Impl::initializeFields(bool fill_default) {
const unsigned n = numFields();
const unsigned iddN = m_iddObject.numFields();
bool resized = false;
if (n < iddN) {
resized = true;
m_fields.resize(iddN);
}
if (!fill_default) {
if (resized) {
this->onChange.nano_emit();
}
return;
}

// Instead of allocating m_diffs, then calling emitChangeSignals which will try to see if there's a name change,
// I know there isn't going to be **any** name changes here, so let's be quicker
bool dataChange = false;

for (unsigned int index = 0; index < std::max(n, iddN); ++index) {
if (m_fields[index].empty()) {
OptionalIddField iddField = m_iddObject.getField(index);
if (iddField && iddField->properties().stringDefault) {
m_fields[index] = *(iddField->properties().stringDefault);
dataChange = true;
// m_diffs.push_back(IdfObjectDiff(index, boost::none, m_fields[index] ));
}
}
}

if (dataChange) {
this->onDataChange.nano_emit();
this->onChange.nano_emit();
} else if (resized) {
this->onChange.nano_emit();
}
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementation. It's perhaps a bit hard to follow at first glance, but this is low-level, so what did you expect?

static_assert(std::is_nothrow_swappable<IdfObject>{});
}

TEST_F(IdfFixture, IdfObject_initializeFields) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wrote a test

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

of course you did.

Comment on lines +62 to +64
if(POLICY CMP0177)
cmake_policy(SET CMP0177 NEW) # ``install()`` ``DESTINATION`` paths are normalized.
endif()
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I read the documentation on this policy. It sounds subtle. Are you making this change to silence a warning or is there a specific issue with the install commands that you are trying to fix? Just curious for my own understanding.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just shush it. my understanding is that the change is a bug fix really

Comment on lines 380 to 385
add_custom_command(TARGET ${swig_target}
POST_BUILD
# OUTPUT "${PYTHON_GENERATED_SRC}"
# OUTPUT "${COPY_PYTHON_GENERATED_SRC}"
COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${PYTHON_GENERATED_SRC}" "${COPY_PYTHON_GENERATED_SRC}"
DEPENDS "${PYTHON_GENERATED_SRC}"
# DEPENDS "${PYTHON_GENERATED_SRC}"
)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the add_custom_command(TARGET version does not allow DEPENDS.

But that target depends on a byproduct of another previous custom command which generates this one too, so it's fine.

set(SWIG_WRAPPER "python_${NAME}_wrap.cxx")
set(SWIG_WRAPPER_FULL_PATH "${CMAKE_CURRENT_BINARY_DIR}/${SWIG_WRAPPER}")
set(PYTHON_GENERATED_SRC_DIR "${PROJECT_BINARY_DIR}/python_wrapper/generated_sources/")
file(MAKE_DIRECTORY ${PYTHON_GENERATED_SRC_DIR})
set(PYTHON_GENERATED_SRC "${PYTHON_GENERATED_SRC_DIR}/${LOWER_NAME}.py")
set(PYTHON_AUTODOC "")
if(BUILD_DOCUMENTATION)
set(PYTHON_AUTODOC -features autodoc=1)
endif()
# The -py3 flag is now deprecated as Python 3 is the default the version used is Python 3
set(SWIG_PYTHON_3_FLAGS "-relativeimport")
add_custom_command(
OUTPUT "${SWIG_WRAPPER_FULL_PATH}" "${PYTHON_GENERATED_SRC}"
COMMAND ${CMAKE_COMMAND} -E env SWIG_DIR="${SWIG_DIR}"
"${SWIG_EXECUTABLE}"
"-python" ${SWIG_PYTHON_3_FLAGS} "-c++" ${PYTHON_AUTODOC}
-outdir ${PYTHON_GENERATED_SRC_DIR} "-I${PROJECT_SOURCE_DIR}/src" "-I${PROJECT_BINARY_DIR}/src"
-module "${MODULE_NAME}"
-o "${SWIG_WRAPPER_FULL_PATH}"
"${SWIG_DEFINES}" ${SWIG_COMMON} ${KEY_I_FILE}
DEPENDS ${this_depends}
)
set_source_files_properties(${SWIG_WRAPPER_FULL_PATH} PROPERTIES GENERATED TRUE)
set_source_files_properties(${PYTHON_GENERATED_SRC} PROPERTIES GENERATED TRUE)
#add_custom_target(${SWIG_TARGET}
# DEPENDS ${SWIG_WRAPPER_FULL_PATH}
#)
add_library(
${swig_target}
MODULE
${SWIG_WRAPPER}
)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems fine to me. POST_BUILD is the key I think.

…e utilities one but change it to be the path of the test exe
Comment on lines +186 to +195
openstudio::path expectedOpenstudioModulePath = getApplicationBuildDirectory() / toPath("Products/openstudio_utilities_tests");
# elif _DEBUG
openstudio::path expectedOpenstudioModulePath = getApplicationBuildDirectory() / toPath("Products/Debug/openstudiolib.dll");
openstudio::path expectedOpenstudioModulePath = getApplicationBuildDirectory() / toPath("Products/Debug/openstudio_utilities_tests.exe");
# else
openstudio::path expectedOpenstudioModulePath = getApplicationBuildDirectory() / toPath("Products/Release/openstudiolib.dll");
openstudio::path expectedOpenstudioModulePath = getApplicationBuildDirectory() / toPath("Products/Release/openstudio_utilities_tests.exe");
# endif
#elif __APPLE__
openstudio::path expectedOpenstudioModulePath = getApplicationBuildDirectory() / toPath("Products/libopenstudiolib.dylib");
openstudio::path expectedOpenstudioModulePath = getApplicationBuildDirectory() / toPath("Products/openstudio_utilities_tests");
#else
openstudio::path expectedOpenstudioModulePath = getApplicationBuildDirectory() / toPath("Products/libopenstudiolib.so");
openstudio::path expectedOpenstudioModulePath = getApplicationBuildDirectory() / toPath("Products/openstudio_utilities_tests");
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modify this utilities tests now that it doesn't link to openstudiolib.

Comment on lines +14 to +33
TEST(ApplicationPathHelpers, Simple_test_forThisModule) {
path openstudioModulePath = getOpenStudioModule();
EXPECT_TRUE(exists(openstudioModulePath));
// The expected path is the utilities one, but resolved for symlinks (we don't want to hardcode the version eg openstudio_utilities_tests-2.8.0)
#if defined(_WIN32)
# if defined(NINJA)
openstudio::path expectedOpenstudioModulePath = getApplicationBuildDirectory() / toPath("Products/openstudiolib.dll");
# elif _DEBUG
openstudio::path expectedOpenstudioModulePath = getApplicationBuildDirectory() / toPath("Products/Debug/openstudiolib.dll");
# else
openstudio::path expectedOpenstudioModulePath = getApplicationBuildDirectory() / toPath("Products/Release/openstudiolib.dll");
# endif
#elif __APPLE__
openstudio::path expectedOpenstudioModulePath = getApplicationBuildDirectory() / toPath("Products/libopenstudiolib.dylib");
#else
openstudio::path expectedOpenstudioModulePath = getApplicationBuildDirectory() / toPath("Products/libopenstudiolib.so");
#endif
expectedOpenstudioModulePath = completeAndNormalize(expectedOpenstudioModulePath);
EXPECT_EQ(toString(expectedOpenstudioModulePath), toString(openstudioModulePath));
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to keep the test with openstudiolib.so though. Instead of strapping it in openstudio_model_tests I created a new test exe... not sure if wise. @kbenne please

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This kind of stuff is a pain. So many configurations and contexts to consider. I think it seems fine to create a new test executable.

These tests assert truth in the dev/testing environment. Sadly it doesn't assert truth in the end user installed situation, so the value of seems less than ideal. Also, with the amount of logic for the various build configs it seems a bit brittle. Having said that, at least we'll know if it breaks. :)

Comment on lines +79 to +85
set(openstudiolib_test_src
test/ApplicationPathHelpers_GTest.cpp
)

if(BUILD_TESTING)
CREATE_TEST_TARGETS(openstudiolib "${openstudiolib_test_src}" openstudiolib openstudio_model_resources openstudio_energyplus_resources)
endif()
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New test target

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, I'll be interested to see what kind of tests this contains as I progress through these changes.

Comment on lines +62 to +64
if(POLICY CMP0177)
cmake_policy(SET CMP0177 NEW) # ``install()`` ``DESTINATION`` paths are normalized.
endif()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I read the documentation on this policy. It sounds subtle. Are you making this change to silence a warning or is there a specific issue with the install commands that you are trying to fix? Just curious for my own understanding.

add_custom_command(TARGET ${swig_target}
POST_BUILD
# OUTPUT "${PYTHON_GENERATED_SRC}"
# OUTPUT "${COPY_PYTHON_GENERATED_SRC}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is commented out, so is this intended as a form of documentation, making it clear what the command does?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess so

Comment on lines 380 to 385
add_custom_command(TARGET ${swig_target}
POST_BUILD
# OUTPUT "${PYTHON_GENERATED_SRC}"
# OUTPUT "${COPY_PYTHON_GENERATED_SRC}"
COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${PYTHON_GENERATED_SRC}" "${COPY_PYTHON_GENERATED_SRC}"
DEPENDS "${PYTHON_GENERATED_SRC}"
# DEPENDS "${PYTHON_GENERATED_SRC}"
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems fine to me. POST_BUILD is the key I think.

Comment on lines +79 to +85
set(openstudiolib_test_src
test/ApplicationPathHelpers_GTest.cpp
)

if(BUILD_TESTING)
CREATE_TEST_TARGETS(openstudiolib "${openstudiolib_test_src}" openstudiolib openstudio_model_resources openstudio_energyplus_resources)
endif()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, I'll be interested to see what kind of tests this contains as I progress through these changes.

Comment on lines +14 to +33
TEST(ApplicationPathHelpers, Simple_test_forThisModule) {
path openstudioModulePath = getOpenStudioModule();
EXPECT_TRUE(exists(openstudioModulePath));
// The expected path is the utilities one, but resolved for symlinks (we don't want to hardcode the version eg openstudio_utilities_tests-2.8.0)
#if defined(_WIN32)
# if defined(NINJA)
openstudio::path expectedOpenstudioModulePath = getApplicationBuildDirectory() / toPath("Products/openstudiolib.dll");
# elif _DEBUG
openstudio::path expectedOpenstudioModulePath = getApplicationBuildDirectory() / toPath("Products/Debug/openstudiolib.dll");
# else
openstudio::path expectedOpenstudioModulePath = getApplicationBuildDirectory() / toPath("Products/Release/openstudiolib.dll");
# endif
#elif __APPLE__
openstudio::path expectedOpenstudioModulePath = getApplicationBuildDirectory() / toPath("Products/libopenstudiolib.dylib");
#else
openstudio::path expectedOpenstudioModulePath = getApplicationBuildDirectory() / toPath("Products/libopenstudiolib.so");
#endif
expectedOpenstudioModulePath = completeAndNormalize(expectedOpenstudioModulePath);
EXPECT_EQ(toString(expectedOpenstudioModulePath), toString(openstudioModulePath));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This kind of stuff is a pain. So many configurations and contexts to consider. I think it seems fine to create a new test executable.

These tests assert truth in the dev/testing environment. Sadly it doesn't assert truth in the end user installed situation, so the value of seems less than ideal. Also, with the amount of logic for the various build configs it seems a bit brittle. Having said that, at least we'll know if it breaks. :)


if(BUILD_TESTING)
CREATE_TEST_TARGETS(${target_name} "${${target_name}_test_src}" openstudiolib openstudio_model_resources openstudio_energyplus_resources fmt::fmt)
CREATE_TEST_TARGETS(${target_name} "${${target_name}_test_src}" openstudio_utilities openstudio_model_resources openstudio_energyplus_resources fmt::fmt)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well the build of the utilities tests will be 10x I suppose!

Comment on lines +96 to +102
%extend openstudio::IddField {
std::string __str__() const {
std::ostringstream os;
os << *self;
return os.str();
}
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now you're a 10x engineer for sure!

Comment on lines +266 to +267
// Helper to initialize all fields (if the object currently displays less than numFields), optionally filling the default for a given object
void initializeFields(bool fill_default = false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should (or does) every newly constructed ModelObject do this?

static_assert(std::is_nothrow_swappable<IdfObject>{});
}

TEST_F(IdfFixture, IdfObject_initializeFields) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

of course you did.

@kbenne kbenne merged commit 095ede6 into develop Mar 21, 2025
4 of 6 checks passed
@kbenne kbenne deleted the InitializeFields branch March 21, 2025 16:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Developer Issue Pull Request - Ready for CI This pull request if finalized and is ready for continuous integration verification prior to merge.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Lots of new CMake warnings openstudio_utilities_tests shouldn't need to depend on openstudiolib

4 participants