-
Notifications
You must be signed in to change notification settings - Fork 193
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add native support for measure argument methods in OsLib_HelperMethods, try 2 #5135
Conversation
CI Results for d30c867:
|
if (hasValue()) { | ||
root["value"] = valueAsBool(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm very puzzled why I didn't do hasValue() orginally... I can't recall if this is a mistake or if I had a reason.
ANyways, we should ladder the ifs
if (hasValue()) {
...
} else if (hasDefaultValue()) {
...
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OH. Nevermind. I didn't see we're writing to two different keys, value
and default_value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right ok, I was just mimic'ing this
OpenStudio/ruby/engine/measure_manager.rb
Lines 370 to 427 in d30c867
def get_arguments_from_measure(measure_dir, measure) | |
result = [] | |
begin | |
# this type was not wrapped with SWIG until OS 1.11.2 | |
measure.arguments.each do |argument| | |
type = argument.type | |
arg = {} | |
arg[:name] = argument.name | |
arg[:display_name] = argument.displayName | |
arg[:description] = argument.description.to_s | |
arg[:type] = argument.type | |
arg[:required] = argument.required | |
arg[:model_dependent] = argument.modelDependent | |
case type | |
when 'Boolean' | |
if argument.defaultValue.is_initialized | |
default_value = argument.defaultValue.get | |
arg[:default_value] = (default_value.downcase == "true") | |
end | |
when 'Double' | |
arg[:units] = argument.units.get if argument.units.is_initialized | |
arg[:default_value] = argument.defaultValue.get.to_f if argument.defaultValue.is_initialized | |
arg[:min_value] = argument.minValue.get.to_f if argument.minValue.is_initialized | |
arg[:max_value] = argument.maxValue.get.to_f if argument.maxValue.is_initialized | |
when 'Integer' | |
arg[:units] = argument.units.get if argument.units.is_initialized | |
arg[:default_value] = argument.defaultValue.get.to_i if argument.defaultValue.is_initialized | |
arg[:min_value] = argument.minValue.get.to_i if argument.minValue.is_initialized | |
arg[:max_value] = argument.maxValue.get.to_i if argument.maxValue.is_initialized | |
when 'String' | |
arg[:default_value] = argument.defaultValue.get if argument.defaultValue.is_initialized | |
when 'Choice' | |
arg[:default_value] = argument.defaultValue.get if argument.defaultValue.is_initialized | |
arg[:choice_values] = [] | |
argument.choiceValues.each {|value| arg[:choice_values] << value} | |
arg[:choice_display_names] = [] | |
argument.choiceDisplayNames.each {|value| arg[:choice_display_names] << value} | |
when 'Path' | |
arg[:default_value] = argument.defaultValue.get if argument.defaultValue.is_initialized | |
end | |
result << arg | |
end | |
rescue | |
info = get_measure_info(measure_dir, measure, "", OpenStudio::Model::OptionalModel.new, OpenStudio::OptionalWorkspace.new) | |
return get_arguments_from_measure_info(info) | |
end | |
return force_encoding(result, 'utf-8') | |
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, this seems just fine to me.
When using a BCLMeasure to inspect arguments, the JSON is unchanged because the OSArgument does not have a value.
src/measure/test/OSRunner_GTest.cpp
Outdated
EXPECT_EQ(1.0, d); | ||
|
||
double d2 = runner.getDoubleArgumentValue(requiredDoubleArgument2.name(), argumentMap); | ||
EXPECT_EQ(234892384234.39485923845834534, d2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EXPECT_EQ(234892384234.39485923845834534, d2); | |
EXPECT_DOUBLE_EQ(234892384234.39485923845834534, d2); |
optionalChoiceArgument2.setValue(openstudio::toString(boiler2.handle())); | ||
argumentVector.push_back(optionalChoiceArgument2); | ||
|
||
std::map<std::string, OSArgument> argumentMap = convertOSArgumentVectorToMap(argumentVector); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should emplace an extra arg in there for testing purposes
src/measure/OSRunner.cpp
Outdated
@@ -784,6 +786,68 @@ namespace measure { | |||
return result; | |||
} | |||
|
|||
Json::Value OSRunner::getArgumentValues(std::vector<OSArgument>& script_arguments, const std::map<std::string, OSArgument>& user_arguments) { | |||
Json::Value argument_values; | |||
std::string name; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
scoping. declare it as const std::string name inside the loop, it's safer
src/measure/OSRunner.cpp
Outdated
@@ -17,6 +17,8 @@ | |||
#include "../utilities/core/Assert.hpp" | |||
#include "../utilities/core/PathHelpers.hpp" | |||
|
|||
#include <boost/lexical_cast.hpp> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
?
@@ -784,6 +786,68 @@ namespace measure { | |||
return result; | |||
} | |||
|
|||
Json::Value OSRunner::getArgumentValues(std::vector<OSArgument>& script_arguments, const std::map<std::string, OSArgument>& user_arguments) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But I think it should be different. What I think it should do is, to also handle optionals:
for each measure_arg in script_arguments:
if user_argument includes it, and it has a value:
use it
else if the **measure_arg** has default value:
use that, because the user_arguments could theoretically have had default_value modifications
else: empty
if (hasValue()) { | ||
root["value"] = openstudio::toString(valueAsPath()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The more I think about it, the more convinced I become that we should just have some convenience functions in OSArgument
Json::Value valueAsJSON() const;
Json::Value defaultValueAsJSON() const;
Json::Value domainAsJSON() const;
They should be exposed to the bindings, and would convert nicely to Ruby/Python type. Maybe we even go crazy and call them just value()
/ defaultValue
Also, I think the crazyness we go through when passing arguments to the run method has to go. We should be able to just pass a ruby hash to it, instead of sprinkling every damn measure test with some nastinesss like
OpenStudio/src/utilities/bcl/templates/ModelMeasure/tests/model_measure_test.rb
Lines 42 to 55 in b809318
argument_map = OpenStudio::Measure.convertOSArgumentVectorToMap(arguments) | |
# create hash of argument values | |
args_hash = {} | |
args_hash['space_name'] = '' | |
# populate argument with specified hash value if specified | |
arguments.each do |arg| | |
temp_arg_var = arg.clone | |
if args_hash.key?(arg.name) | |
assert(temp_arg_var.setValue(args_hash[arg.name])) | |
end | |
argument_map[arg.name] = temp_arg_var | |
end |
src/measure/OSRunner.cpp
Outdated
return argument_values; | ||
} | ||
|
||
Json::Value OSRunner::getPastStepValuesForMeasure(const std::string& measure_name) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I'm still confused about the difference between the getPastStepValuesForMeasure and getPastStepValuesForName, but I'll figure that out.
- The above is mostyl due to how unreadable both methods are. The flow logic places an unnecessarily high cognitive burden on the reader. I'll revamp
- Both of these should be marked const.
- Generally speaking, the entire existing OSRunner class is completely messed up as far as const-correctness and staticness of methods that can be (like getOptionalXXXArgument), but I'm wary of changing this since it's an ABI break
@@ -784,6 +786,68 @@ namespace measure { | |||
return result; | |||
} | |||
|
|||
Json::Value OSRunner::getArgumentValues(std::vector<OSArgument>& script_arguments, const std::map<std::string, OSArgument>& user_arguments) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be static actually.
…S >= 10.14 supports it, and E+ is 10.15 minimum anyways
…static as it should
* Try to align getPastStepValuesForName on check_upstream_measure_for_arg in what it picks for measure name * getPastStepValuesForMeasure: allow matching on either the WorkflowStep's measureDirName or name, or the WorkflowStepResult's measureName * Scope the test blocks for readability and avoiding side effects (less chances of making a mistake)
…rn defaultValue if value not set
…true * Move logic to Variant::isTruish to determine if a variant is trueish (whether that's bool true, str = "true", int != 0, double != 0.0 * Add a OSRunner::prepareForMeasureRun() that takes no arg, protected, and friend OSWorkflow so we can use it without the penatly of instantiating an OSMeasure * In Apply Measure, when __SKIP__, correctly call prepareForMEasureRun before incrementing the step. And do load the BCLMeasure to write the resultInfo like the workflow-gem was doing
…ap<string, int> as swig template globally I kinda like the usability ``` OpenStudio::StepResult.getLookupMap => std::map<std::string,int,std::less< std::string >,std::allocator< std::pair< std::string const,int > > > {"FAIL"=>1,"NA"=>-1,"NOTAPPLICABLE"=>-1,"PASS"=>0,"SKIP"=>-2,"SKIPPED"=>-2,"SUCCESS"=>0} OpenStudio::StepResult.getLookupMap.to_h => {"FAIL"=>1, "NA"=>-1, "NOTAPPLICABLE"=>-1, "PASS"=>0, "SKIP"=>-2, "SKIPPED"=>-2, "SUCCESS"=>0} ``` python ``` In [16]: openstudio.StepResult.getLookupMap().asdict() Out[16]: {'FAIL': 1, 'NA': -1, 'NOTAPPLICABLE': -1, 'PASS': 0, 'SKIP': -2, 'SKIPPED': -2, 'SUCCESS': 0} ```
``` object = OpenStudio::Measure::OSArgument.makeChoiceArgument('object', {'handle1' => 'choice1', 'handle2' => 'choice2'}, true, true) object.choiceValues => ["handle1", "handle2"] object.choiceValueDisplayNames => ["choice1", "choice2"] ```
Pull request overview
Add methods that return
Json::Value
:runner.getArgumentValues(script_arguments, user_arguments)
runner.getPastStepValuesForMeasure(measure_name)
runner.getPastStepValuesForName(step_name)
Pull Request Author
src/model/test
)src/energyplus/Test
)src/osversion/VersionTranslator.cpp
)Labels:
IDDChange
APIChange
Pull Request - Ready for CI
so that CI builds your PRReview Checklist
This will not be exhaustively relevant to every PR.