openstudio-workflow 1.0.0.pat1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/README.md +16 -68
  4. data/Rakefile +9 -9
  5. data/bin/openstudio_cli +786 -0
  6. data/lib/openstudio/workflow/adapters/input/local.rb +97 -0
  7. data/lib/openstudio/workflow/adapters/output/local.rb +90 -0
  8. data/lib/openstudio/workflow/adapters/output/socket.rb +70 -0
  9. data/lib/openstudio/workflow/{jobs/run_preflight/run_preflight.rb → adapters/output/web.rb} +37 -19
  10. data/lib/openstudio/workflow/{adapter.rb → adapters/output_adapter.rb} +53 -51
  11. data/lib/openstudio/workflow/job.rb +22 -0
  12. data/lib/openstudio/workflow/jobs/{run_energyplus → resources}/monthly_report.idf +0 -0
  13. data/lib/openstudio/workflow/jobs/run_energyplus.rb +49 -0
  14. data/lib/openstudio/workflow/jobs/run_ep_measures.rb +55 -0
  15. data/lib/openstudio/workflow/jobs/run_initialization.rb +136 -0
  16. data/lib/openstudio/workflow/jobs/run_os_measures.rb +59 -0
  17. data/lib/openstudio/workflow/jobs/run_postprocess.rb +53 -0
  18. data/lib/openstudio/workflow/jobs/run_preprocess.rb +81 -0
  19. data/lib/openstudio/workflow/jobs/run_reporting_measures.rb +86 -0
  20. data/lib/openstudio/workflow/jobs/run_translation.rb +49 -0
  21. data/lib/openstudio/workflow/multi_delegator.rb +1 -3
  22. data/lib/openstudio/workflow/registry.rb +137 -0
  23. data/lib/openstudio/workflow/run.rb +182 -221
  24. data/lib/openstudio/workflow/time_logger.rb +1 -1
  25. data/lib/openstudio/workflow/util/energyplus.rb +564 -0
  26. data/lib/openstudio/workflow/util/io.rb +33 -0
  27. data/lib/openstudio/workflow/util/measure.rb +520 -0
  28. data/lib/openstudio/workflow/util/model.rb +100 -0
  29. data/lib/openstudio/workflow/util/post_process.rb +177 -0
  30. data/lib/openstudio/workflow/util/weather_file.rb +108 -0
  31. data/lib/openstudio/workflow/util.rb +14 -0
  32. data/lib/openstudio/workflow/version.rb +1 -1
  33. data/lib/openstudio/workflow_json.rb +399 -0
  34. data/lib/openstudio/workflow_runner.rb +213 -0
  35. data/lib/openstudio-workflow.rb +13 -118
  36. metadata +45 -85
  37. data/lib/openstudio/extended_runner.rb +0 -105
  38. data/lib/openstudio/workflow/adapters/local.rb +0 -101
  39. data/lib/openstudio/workflow/adapters/mongo.rb +0 -227
  40. data/lib/openstudio/workflow/jobs/lib/apply_measures.rb +0 -253
  41. data/lib/openstudio/workflow/jobs/run_energyplus/run_energyplus.rb +0 -314
  42. data/lib/openstudio/workflow/jobs/run_openstudio/run_openstudio.rb +0 -230
  43. data/lib/openstudio/workflow/jobs/run_postprocess/run_postprocess.rb +0 -110
  44. data/lib/openstudio/workflow/jobs/run_reporting_measures/run_reporting_measures.rb +0 -471
  45. data/lib/openstudio/workflow/jobs/run_runmanager/run_runmanager.rb +0 -247
  46. data/lib/openstudio/workflow/jobs/run_xml/run_xml.rb +0 -279
@@ -0,0 +1,786 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ######################################################################
4
+ # Copyright (c) 2008-2016, Alliance for Sustainable Energy.
5
+ # All rights reserved.
6
+ #
7
+ # This library is free software; you can redistribute it and/or
8
+ # modify it under the terms of the GNU Lesser General Public
9
+ # License as published by the Free Software Foundation; either
10
+ # version 2.1 of the License, or (at your option) any later version.
11
+ #
12
+ # This library is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ # Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public
18
+ # License along with this library; if not, write to the Free Software
19
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
+ ######################################################################
21
+
22
+ Signal.trap('INT') { abort }
23
+
24
+ require 'openstudio-workflow'
25
+ require 'optparse'
26
+ require 'irb'
27
+ require 'json'
28
+ include OpenStudio::Workflow::Util::IO
29
+ include OpenStudio::Workflow::Util::Directory
30
+
31
+ $logger = Logger.new(STDOUT)
32
+ $logger.level = Logger::WARN
33
+
34
+ # This is the code chunk to allow for an embedded IRB shell. From Jason Roelofs, found on StackOverflow
35
+ module IRB # :nodoc:
36
+ def self.start_session(binding)
37
+ unless @__initialized
38
+ args = ARGV
39
+ ARGV.replace(ARGV.dup)
40
+ IRB.setup(nil)
41
+ ARGV.replace(args)
42
+ @__initialized = true
43
+ end
44
+
45
+ workspace = WorkSpace.new(binding)
46
+
47
+ irb = Irb.new(workspace)
48
+
49
+ @CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
50
+ @CONF[:MAIN_CONTEXT] = irb.context
51
+
52
+ catch(:IRB_EXIT) do
53
+ irb.eval_input
54
+ end
55
+ end
56
+ end
57
+
58
+ # This is the save puts to use to catch EPIPE. Uses `puts` on the given IO object and safely ignores any Errno::EPIPE
59
+ #
60
+ # @param [String] message Message to output
61
+ # @param [Hash] opts Options hash
62
+ #
63
+ def safe_puts(message = nil, opts = nil)
64
+ message ||= ''
65
+ opts = {
66
+ io: $stdout,
67
+ printer: :puts
68
+ }.merge(opts || {})
69
+
70
+ begin
71
+ opts[:io].send(opts[:printer], message)
72
+ rescue Errno::EPIPE
73
+ # This is what makes this a `safe` puts
74
+ return
75
+ end
76
+ end
77
+
78
+ # This is a convenience method that properly handles duping the originally argv array so that it is not destroyed. This
79
+ # method will also automatically detect "-h" and "--help" and print help. And if any invalid options are detected, the
80
+ # help will be printed, as well
81
+ #
82
+ # @param [Object, nil] opts An instance of OptionParse to parse against, defaults to a new OptionParse instance
83
+ # @param [Array, nil] argv The argv input to be parsed, defaults to $argv
84
+ # @return[Array, nil] If this method returns `nil`, then you should assume that help was printed and parsing failed
85
+ #
86
+ def parse_options(opts = nil, argv = nil)
87
+ # Creating a shallow copy of the arguments so the OptionParser
88
+ # doesn't destroy the originals.
89
+ argv ||= $argv.dup
90
+
91
+ # Default opts to a blank optionparser if none is given
92
+ opts ||= OptionParser.new
93
+
94
+ # Add the help option, which must be on every command.
95
+ opts.on_tail('-h', '--help', 'Print this help') do
96
+ safe_puts(opts.help)
97
+ return nil
98
+ end
99
+
100
+ opts.parse!(argv)
101
+ return argv
102
+ rescue OptionParser::InvalidOption, OptionParser::MissingArgument
103
+ raise "Error: Invalid CLI option, #{opts.help.chomp}"
104
+ end
105
+
106
+ # This method will split the argv given into three parts: the flags to this command, the subcommand, and the flags to
107
+ # the subcommand. For example:
108
+ # -v status -h -v
109
+ # The above would yield 3 parts:
110
+ # ["-v"]
111
+ # "status"
112
+ # ["-h", "-v"]
113
+ # These parts are useful because the first is a list of arguments given to the current command, the second is a
114
+ # subcommand, and the third are the commands given to the subcommand
115
+ #
116
+ # @param [Array] argv The input to be split
117
+ # @return [Array] The split command as [main arguments, sub command, sub command arguments]
118
+ #
119
+ def split_main_and_subcommand(argv)
120
+ # Initialize return variables
121
+ main_args = nil
122
+ sub_command = nil
123
+ sub_args = []
124
+
125
+ # We split the arguments into two: One set containing any flags before a word, and then the rest. The rest are what
126
+ # get actually sent on to the subcommand
127
+ argv.each_index do |i|
128
+ unless argv[i].start_with?('-')
129
+ # We found the beginning of the sub command. Split the
130
+ # args up.
131
+ main_args = argv[0, i]
132
+ sub_command = argv[i]
133
+ sub_args = argv[i + 1, argv.length - i + 1]
134
+
135
+ # Break so we don't find the next non flag and shift our main args
136
+ break
137
+ end
138
+ end
139
+
140
+ # Handle the case that argv was empty or didn't contain any subcommand
141
+ main_args = argv.dup if main_args.nil?
142
+
143
+ [main_args, sub_command, sub_args]
144
+ end
145
+
146
+ # This CLI class processes the input args and invokes the proper command class
147
+ class CLI
148
+ # This constant maps subcommands to classes in this CLI and stores meta-data on them
149
+ COMMAND_LIST = {
150
+ run: [proc { ::Run }, { primary: true, working: true }],
151
+ apply_measure: [proc { ::ApplyMeasure }, { primary: true, working: false }],
152
+ gem_list: [proc { ::GemList }, { primary: true, working: true }],
153
+ gem_install: [proc { ::InstallGem }, { primary: false, working: true }],
154
+ measure: [proc { ::Measure }, { primary: true, working: false }],
155
+ e: [proc { ::ExecuteRubyScript }, { primary: false, working: true }],
156
+ i: [proc { ::InteractiveRubyShell }, { primary: false, working: true }],
157
+ openstudio_version: [proc { ::OpenStudioVersion }, { primary: true, working: true }],
158
+ energyplus_version: [proc { ::EnergyPlusVersion }, { primary: true, working: true }],
159
+ ruby_version: [proc { ::RubyVersion }, { primary: false, working: true }],
160
+ list_commands: [proc { ::ListCommands }, { primary: true, working: true }]
161
+ }.freeze
162
+
163
+ # This method instantiates the global variables $main_args, $sub_command, and $sub_args
164
+ #
165
+ # @param [Array] argv The arguments passed through the CLI
166
+ # @return [Object] An instance of the CLI class with initialized globals
167
+ #
168
+ def initialize(argv)
169
+ $main_args, $sub_command, $sub_args = split_main_and_subcommand(argv)
170
+
171
+ $logger.info("CLI Parsed Inputs: #{$main_args.inspect} #{$sub_command.inspect} #{$sub_args.inspect}")
172
+ end
173
+
174
+ # Checks to see if it should print the main help, and if not parses the subcommand into a class and executes it
175
+ def execute
176
+ $logger.debug "Main arguments are #{$main_args}"
177
+ $logger.debug "Sub-command is #{$sub_command}"
178
+ $logger.debug "Sub-arguments are #{$sub_args}"
179
+ if $main_args.include?('-h') || $main_args.include?('--help')
180
+ # Help is next in short-circuiting everything. Print
181
+ # the help and exit.
182
+ help
183
+ return 0
184
+ end
185
+
186
+ # If we reached this far then we must have a subcommand. If not,
187
+ # then we also just print the help and exit.
188
+ command_plugin = nil
189
+ if $sub_command
190
+ command_plugin = COMMAND_LIST[$sub_command.to_sym]
191
+ end
192
+
193
+ if !command_plugin || !$sub_command
194
+ help
195
+ return 1
196
+ end
197
+
198
+ command_class = command_plugin[0].call
199
+ $logger.debug("Invoking command class: #{command_class} #{$sub_args.inspect}")
200
+
201
+ # Initialize and execute the command class, returning the exit status.
202
+ result = 0
203
+ begin
204
+ result = command_class.new.execute($sub_args)
205
+ rescue Interrupt
206
+ $logger.error '?'
207
+ result = 1
208
+ end
209
+
210
+ result = 0 unless result.is_a?(Fixnum)
211
+ result
212
+ end
213
+
214
+ # Prints out the help text for the CLI
215
+ #
216
+ # @param [Boolean] list_all If set to true, the help prints all commands, however it otherwise only prints those
217
+ # marked as primary in #COMMAND_LIST
218
+ # @return [void]
219
+ # @see #COMMAND_LIST #::ListCommands
220
+ #
221
+ def help(list_all = false)
222
+ opts = OptionParser.new do |o|
223
+ o.banner = 'Usage: openstudio_cli [options] <command> [<args>]'
224
+ o.separator ''
225
+ o.on('-h', '--help', 'Print this help.')
226
+ o.on('--verbose', 'Print the full log to STDOUT')
227
+ o.on('--gem_path PATH', 'Path to use for installing gems to and loading gems from')
228
+ o.separator ''
229
+ o.separator 'Common commands:'
230
+
231
+ # Add the available subcommands as separators in order to print them
232
+ # out as well.
233
+ commands = {}
234
+ longest = 0
235
+ COMMAND_LIST.each do |key, data|
236
+ # Skip non-primary commands. These only show up in extended
237
+ # help output.
238
+ next unless list_all || data[1][:primary]
239
+
240
+ key = key.to_s
241
+ klass = data[0].call
242
+ commands[key] = klass.synopsis
243
+ longest = key.length if key.length > longest
244
+ end
245
+
246
+ commands.keys.sort.each do |key|
247
+ o.separator " #{key.ljust(longest + 2)} #{commands[key]}"
248
+ end
249
+
250
+ o.separator ''
251
+ o.separator 'For help on any individual command run `openstudio_cli COMMAND -h`'
252
+ unless list_all
253
+ o.separator ''
254
+ o.separator 'Additional subcommands are available, but are either more advanced'
255
+ o.separator 'or not commonly used. To see all subcommands, run the command'
256
+ o.separator '`openstudio_cli list_commands`.'
257
+ end
258
+ end
259
+
260
+ safe_puts opts.help
261
+ end
262
+ end
263
+
264
+ # Class to execute part or all of an OSW workflow
265
+ class Run
266
+ # Provides text for the main help functionality
267
+ def self.synopsis
268
+ 'Executes an OpenStudio Workflow file'
269
+ end
270
+
271
+ # Executes the standard, or one of two custom, workflows using the workflow-gem
272
+ #
273
+ # @param [Array] sub_argv Options passed to the run subcommand from the user input
274
+ # @return [Fixnum] Return status
275
+ #
276
+ def execute(sub_argv)
277
+ options = {}
278
+ options[:debug] = false
279
+ options[:no_simulation] = false
280
+ options[:workflow] = './workflow.osw'
281
+ options[:post_process] = false
282
+
283
+ opts = OptionParser.new do |o|
284
+ o.banner = 'Usage: openstudio_cli run [options]'
285
+ o.separator ''
286
+ o.separator 'Options:'
287
+ o.separator ''
288
+
289
+ o.on('-w', '--workflow [FILE]', 'Specify the FILE path to the workflow to run') do |workflow|
290
+ options[:workflow] = workflow
291
+ end
292
+ o.on('-m', '--measures_only', 'Only run the OpenStudio and EnergyPlus measures') do
293
+ options[:no_simulation] = true
294
+ end
295
+ o.on('-p', '--postprocess_only', 'Only run the reporting measures') do
296
+ options[:post_process] = true
297
+ end
298
+ o.on('--debug', 'Includes additional outputs for debugging failing workflows and does not clean up the run directory') do |f|
299
+ options[:debug] = f
300
+ end
301
+ end
302
+
303
+ # Parse the options
304
+ argv = parse_options(opts, sub_argv)
305
+ return 0 if argv.nil?
306
+ unless argv == []
307
+ $logger.error 'Extra arguments passed to the run command. Please refer to the help documentation.'
308
+ return 1
309
+ end
310
+ $logger.debug("Run command: #{argv.inspect} #{options.inspect}")
311
+
312
+ if options[:post_process] && options[:no_simulation]
313
+ $logger.error 'Both the -m and -p flags were set, which is an invalid combination.'
314
+ return 1
315
+ end
316
+
317
+ osw_path = options[:workflow]
318
+ osw_path = File.absolute_path(File.join(Dir.pwd, osw_path)) unless Pathname.new(osw_path).absolute?
319
+ $logger.debug "Path for the OSW: #{osw_path}"
320
+
321
+ adapter_options = { workflow_filename: File.basename(osw_path) }
322
+ input_adapter = OpenStudio::Workflow.load_input_adapter 'local', adapter_options
323
+ adapter_options[:output_directory] = input_adapter.run_directory File.dirname(osw_path)
324
+ output_adapter = OpenStudio::Workflow.load_output_adapter 'local', adapter_options
325
+ run_options = options[:debug] ? { debug: true, cleanup: false } : {}
326
+ if options[:no_simulation]
327
+ run_options[:jobs] = [
328
+ { state: :queued, next_state: :initialization, options: { initial: true } },
329
+ { state: :initialization, next_state: :os_measures, job: :RunInitialization,
330
+ file: 'openstudio/workflow/jobs/run_initialization.rb', options: {} },
331
+ { state: :os_measures, next_state: :translator, job: :RunOpenStudioMeasures,
332
+ file: 'openstudio/workflow/jobs/run_os_measures.rb', options: {} },
333
+ { state: :translator, next_state: :ep_measures, job: :RunTranslation,
334
+ file: 'openstudio/workflow/jobs/run_translation.rb', options: {} },
335
+ { state: :ep_measures, next_state: :finished, job: :RunEnergyPlusMeasures,
336
+ file: 'openstudio/workflow/jobs/run_ep_measures.rb', options: {} },
337
+ { state: :finished },
338
+ { state: :errored }
339
+ ]
340
+ elsif options[:post_process]
341
+ run_options[:jobs] = [
342
+ { state: :queued, next_state: :initialization, options: { initial: true } },
343
+ { state: :initialization, next_state: :reporting_measures, job: :RunInitialization,
344
+ file: 'openstudio/workflow/jobs/run_initialization.rb', options: {} },
345
+ { state: :reporting_measures, next_state: :postprocess, job: :RunReportingMeasures,
346
+ file: 'openstudio/workflow/jobs/run_reporting_measures.rb', options: {} },
347
+ { state: :postprocess, next_state: :finished, job: :RunPostprocess,
348
+ file: 'openstudio/workflow/jobs/run_postprocess.rb', options: {} },
349
+ { state: :finished },
350
+ { state: :errored }
351
+ ]
352
+ run_options[:load_simulation_osm] = true
353
+ run_options[:load_simulation_idf] = true
354
+ run_options[:load_simulation_sql] = true
355
+ run_options[:preserve_run_dir] = true
356
+ end
357
+ k = OpenStudio::Workflow::Run.new input_adapter, output_adapter, File.dirname(osw_path), run_options
358
+ k.run
359
+
360
+ 0
361
+ end
362
+ end
363
+
364
+ # Class to apply an OpenStudio, EnergyPlus, or Reporting measure
365
+ # @abstract
366
+ class ApplyMeasure
367
+ # Provides text for the main help functionality
368
+ def self.synopsis
369
+ 'Applies an OpenStudio, EnergyPlus, or Reporting measure'
370
+ end
371
+
372
+ # Executes a single measure using an undefined interface
373
+ #
374
+ # @param [Array] sub_argv Options passed to the apply_measures subcommand from the user input
375
+ # @return [Fixnum] Return status
376
+ # @abstract
377
+ #
378
+ def execute(sub_argv)
379
+ # options = {}
380
+ # options[:debug] = false
381
+
382
+ # opts = OptionParser.new do |o|
383
+ # o.banner = 'Usage: openstudio_cli apply_measure'
384
+ # o.separator ''
385
+ # o.separator 'Options:'
386
+ # o.separator ''
387
+ # end
388
+
389
+ $logger.error 'This interface has yet to be defined.'
390
+
391
+ # Parse the options
392
+ argv = parse_options(opts, sub_argv)
393
+ return 1 unless argv
394
+ # $logger.debug("ApplyMeasure command: #{argv.inspect} #{options.inspect}")
395
+
396
+ 1
397
+ end
398
+ end
399
+
400
+ # Class to list the gems used by the CLI
401
+ class GemList
402
+ # Provides text for the main help functionality
403
+ def self.synopsis
404
+ 'Lists the set gems available to openstudio_cli'
405
+ end
406
+
407
+ # Alters the environment variable used to define the gem install location
408
+ #
409
+ # @param [Array] sub_argv Options passed to the gem_install subcommand from the user input
410
+ # @return [Fixnum] Return status
411
+ #
412
+ def execute(sub_argv)
413
+ require 'rubygems'
414
+ require 'rubygems/gem_runner'
415
+
416
+ # Parse the options
417
+ opts = OptionParser.new do |o|
418
+ o.banner = 'Usage: openstudio_cli gem_list'
419
+ end
420
+ argv = parse_options(opts, sub_argv)
421
+ unless argv == []
422
+ $logger.error 'Extra arguments passed to the gem_list command. Please refer to the help documentation.'
423
+ return 1
424
+ end
425
+
426
+ begin
427
+ Gem::GemRunner.new.run ['list']
428
+ rescue => e
429
+ $logger.error "Error listing gems: #{e.message} in #{e.backtrace.join("\n")}"
430
+ exit e.exit_code
431
+ end
432
+
433
+ 0
434
+ end
435
+ end
436
+
437
+ # Class to install gems using the RubyGems functionality
438
+ class InstallGem
439
+ # Provides text for the main help functionality
440
+ def self.synopsis
441
+ 'Installs a Gem using the embedded ruby'
442
+ end
443
+
444
+ # Executes the RubyGems gem install process, using the RubyGems options
445
+ #
446
+ # @param [Array] sub_argv Options passed to the gem_install subcommand from the user input
447
+ # @return [Fixnum] Return status
448
+ #
449
+ def execute(sub_argv)
450
+ require 'rubygems'
451
+ require 'rubygems/gem_runner'
452
+
453
+ # Parse the options
454
+ argv = sub_argv.unshift('install')
455
+ if argv.include? '--install-dir'
456
+ $logger.error 'The rubygems option --install-dir is not supported. Please use the --gem_path option'
457
+ return 1
458
+ else
459
+ argv.push '--install-dir'
460
+ argv.push ENV['GEM_PATH']
461
+ end
462
+ $logger.debug "GemInstall command: #{argv.inspect}"
463
+ $logger.debug "Invoking the GemRunner with argv: #{argv}"
464
+
465
+ begin
466
+ Gem::GemRunner.new.run argv
467
+ rescue => e
468
+ $logger.error "Error installing gem: #{e.message} in #{e.backtrace.join("\n")}"
469
+ exit e.exit_code
470
+ end
471
+
472
+ $logger.info 'The gem was successfully installed'
473
+
474
+ 0
475
+ end
476
+ end
477
+
478
+ # Class to update measures and compute arguments
479
+ class Measure
480
+ # Provides text for the main help functionality
481
+ def self.synopsis
482
+ 'Updates measures and compute arguments'
483
+ end
484
+
485
+ # Executes code to update and compute arguments for measures
486
+ #
487
+ # @param [Array] sub_argv Options passed to the e subcommand from the user input
488
+ # @return [Fixnum] Return status
489
+ # @todo (macumber) Add in the OpenStudio code to execute on measures
490
+ #
491
+ def execute(sub_argv)
492
+ options = {}
493
+ options[:check_for_update] = false
494
+ options[:update] = false
495
+ options[:compute_arguments] = nil
496
+
497
+ opts = OptionParser.new do |o|
498
+ o.banner = 'Usage: openstudio_cli measure [options] DIRECTORY'
499
+ o.separator ''
500
+ o.separator 'Options:'
501
+ o.separator ''
502
+
503
+ o.on('-c', '--check_for_updates', 'Check to see if the measure needs to be updated') do
504
+ options[:check_for_update] = workflow
505
+ end
506
+ o.on('-u', '--update', 'Update the measure.xml') do
507
+ options[:update] = true
508
+ end
509
+ o.on('-a', '--compute_arguments [MODEL]', 'Compute arguments for the given model') do |model_file|
510
+ options[:compute_arguments] = model_file
511
+ end
512
+ end
513
+
514
+ # Parse the options
515
+ argv = parse_options(opts, sub_argv)
516
+ $logger.error 'No directory provided' if argv == []
517
+ return 1 if argv == []
518
+ directory = argv[0]
519
+
520
+ $logger.debug("Measure command: #{argv.inspect} #{options.inspect}")
521
+ $logger.debug("Directory to examine is #{directory}")
522
+
523
+ $logger.error 'Code to be added here to operate on measures'
524
+
525
+ 1
526
+ end
527
+ end
528
+
529
+ # Class to execute a ruby script
530
+ class ExecuteRubyScript
531
+ # Provides text for the main help functionality
532
+ def self.synopsis
533
+ 'Executes a ruby file'
534
+ end
535
+
536
+ # Executes an arbitrary ruby script
537
+ #
538
+ # @param [Array] sub_argv Options passed to the e subcommand from the user input
539
+ # @return [Fixnum] Return status
540
+ #
541
+ def execute(sub_argv)
542
+ options = {}
543
+
544
+ opts = OptionParser.new do |o|
545
+ o.banner = 'Usage: openstudio_cli e [file]'
546
+ end
547
+
548
+ # Parse the options
549
+ argv = parse_options(opts, sub_argv)
550
+ return 0 if argv.nil?
551
+ return 1 unless argv
552
+ $logger.debug("ExecuteRubyScript command: #{argv.inspect} #{options.inspect}")
553
+ file_path = argv.shift.to_s
554
+ file_path = File.absolute_path(File.join(Dir.pwd, file_path)) unless Pathname.new(file_path).absolute?
555
+ $logger.debug "Path for the file to run: #{file_path}"
556
+
557
+ unless argv == []
558
+ $logger.error 'Extra arguments passed to the e command. Please refer to the help documentation.'
559
+ return 1
560
+ end
561
+
562
+ unless File.exist? file_path
563
+ $logger.error "Unable to find the file #{file_path} on the filesystem"
564
+ return 1
565
+ end
566
+
567
+ require file_path
568
+
569
+ 0
570
+ end
571
+ end
572
+
573
+ # Class to put the user into an irb shell
574
+ class InteractiveRubyShell
575
+ # Provides text for the main help functionality
576
+ def self.synopsis
577
+ 'Provides an interactive ruby shell'
578
+ end
579
+
580
+ # Executes the commands to get into an IRB prompt
581
+ #
582
+ # @param [Array] sub_argv Options passed to the i subcommand from the user input
583
+ # @return [Fixnum] Return status
584
+ #
585
+ def execute(sub_argv)
586
+ options = {}
587
+
588
+ opts = OptionParser.new do |o|
589
+ o.banner = 'Usage: openstudio_cli i'
590
+ end
591
+
592
+ # Parse the options
593
+ argv = parse_options(opts, sub_argv)
594
+ $logger.debug("InteractiveRubyShell command: #{argv.inspect} #{options.inspect}")
595
+ return 0 if argv.nil?
596
+
597
+ unless argv == []
598
+ $logger.error 'Extra arguments passed to the i command.'
599
+ return 1
600
+ end
601
+
602
+ IRB.start_session(binding)
603
+
604
+ 0
605
+ end
606
+ end
607
+
608
+ # Class to return the packaged OpenStudio version
609
+ class OpenStudioVersion
610
+ # Provides text for the main help functionality
611
+ def self.synopsis
612
+ 'Returns the OpenStudio version used by the CLI'
613
+ end
614
+
615
+ # Executes the OpenStudio commands to return the OpenStudio version
616
+ #
617
+ # @param [Array] sub_argv Options passed to the energyplus_version subcommand from the user input
618
+ # @return [Fixnum] Return status
619
+ #
620
+ def execute(sub_argv)
621
+ options = {}
622
+
623
+ opts = OptionParser.new do |o|
624
+ o.banner = 'Usage: openstudio_cli openstudio_version'
625
+ end
626
+
627
+ # Parse the options
628
+ argv = parse_options(opts, sub_argv)
629
+ $logger.debug("OpenStudioVersion command: #{argv.inspect} #{options.inspect}")
630
+ return 0 if argv.nil?
631
+
632
+ unless argv == []
633
+ $logger.error 'Extra arguments passed to the openstudio_version command.'
634
+ return 1
635
+ end
636
+
637
+ safe_puts OpenStudio.openStudioLongVersion
638
+
639
+ 0
640
+ end
641
+ end
642
+
643
+ # Class to return the EnergyPlus version
644
+ class EnergyPlusVersion
645
+ # Provides text for the main help functionality
646
+ def self.synopsis
647
+ 'Returns the EnergyPlus version used by the CLI'
648
+ end
649
+
650
+ # Executes the OpenStudio command to return the EnergyPlus version
651
+ #
652
+ # @param [Array] sub_argv Options passed to the openstudio_version subcommand from the user input
653
+ # @return [Fixnum] Return status
654
+ #
655
+ def execute(sub_argv)
656
+ options = {}
657
+
658
+ opts = OptionParser.new do |o|
659
+ o.banner = 'Usage: openstudio_cli energyplus_version'
660
+ end
661
+
662
+ # Parse the options
663
+ argv = parse_options(opts, sub_argv)
664
+ $logger.debug("EnergyPlusVersion command: #{argv.inspect} #{options.inspect}")
665
+ return 0 if argv.nil?
666
+
667
+ unless argv == []
668
+ $logger.error 'Arguments passed to the energyplus_version command.'
669
+ return 1
670
+ end
671
+
672
+ safe_puts OpenStudio.energyPlusVersion
673
+
674
+ 0
675
+ end
676
+ end
677
+
678
+ # Class to return the ruby version used by the packaged CLI
679
+ class RubyVersion
680
+ # Provides text for the main help functionality
681
+ def self.synopsis
682
+ 'Returns the Ruby version used by the CLI'
683
+ end
684
+
685
+ # Evaluates the RUBY_VERSION constant and returns it
686
+ #
687
+ # @param [Array] sub_argv Options passed to the ruby_version subcommand from the user input
688
+ # @return [Fixnum] Return status
689
+ #
690
+ def execute(sub_argv)
691
+ options = {}
692
+
693
+ opts = OptionParser.new do |o|
694
+ o.banner = 'Usage: openstudio_cli ruby_version'
695
+ end
696
+
697
+ # Parse the options
698
+ argv = parse_options(opts, sub_argv)
699
+ $logger.debug("RubyVersion command: #{argv.inspect} #{options.inspect}")
700
+ return 0 if argv.nil?
701
+
702
+ unless argv == []
703
+ $logger.error 'Arguments passed to the ruby_version command.'
704
+ return 1
705
+ end
706
+
707
+ safe_puts RUBY_VERSION
708
+
709
+ 0
710
+ end
711
+ end
712
+
713
+ # Class to return the full set of possible commands for the CLI
714
+ class ListCommands
715
+ # Provides text for the main help functionality
716
+ def self.synopsis
717
+ 'Lists the entire set of available commands for openstudio_cli'
718
+ end
719
+
720
+ # Executes the standard help method with the list_all attribute set to true
721
+ #
722
+ # @param [Array] sub_argv Options passed to the list_all subcommand from the user input
723
+ # @return [Fixnum] Return status
724
+ # @see #::CLI.help
725
+ #
726
+ def execute(sub_argv)
727
+ options = {}
728
+
729
+ opts = OptionParser.new do |o|
730
+ o.banner = 'Usage: openstudio_cli list_commands'
731
+ end
732
+
733
+ # Parse the options
734
+ argv = parse_options(opts, sub_argv)
735
+ $logger.debug("ListCommands command: #{argv.inspect} #{options.inspect}")
736
+ return 0 if argv.nil?
737
+
738
+ unless argv == []
739
+ $logger.error 'Arguments passed to the list_commands command.'
740
+ return 1
741
+ end
742
+
743
+ $logger.debug 'Creating a new CLI instance and calling help with list_all enabled'
744
+ ::CLI.new([]).help(true)
745
+
746
+ 0
747
+ end
748
+ end
749
+
750
+ # Set the logger level to DEBUG if the arguments include --verbose
751
+ $argv = ARGV.dup
752
+ if $argv.include? '--verbose'
753
+ $logger.level = Logger::DEBUG
754
+ $argv.delete '--verbose'
755
+ $logger.debug 'Set Logger log level to DEBUG'
756
+ end
757
+ $logger.debug "Input ARGV is #{$argv}"
758
+
759
+ # Operate on the gem_path option to set the gem search path
760
+ if $argv.include? '--gem_path'
761
+ $logger.info 'Setting gem path'
762
+ option_index = $argv.index '--gem_path'
763
+ path_index = option_index + 1
764
+ new_home = $argv[path_index]
765
+ $argv.slice! path_index
766
+ $argv.slice! $argv.index '--gem_path'
767
+ current_home = ENV['OPENSTUDIO_GEM_PATH']
768
+ $logger.warn "Overwriting previous OPENSTUDIO_GEM_PATH of #{current_home} to #{new_home} for this command" if current_home
769
+ $logger.info "No current gem path set in OPENSTUDIO_GEM_PATH, setting to #{new_home}" unless current_home
770
+ ENV['OPENSTUDIO_GEM_PATH'] = new_home
771
+ end
772
+
773
+ # Configure Gems to load the correct Gem files
774
+ # @see http://rubygems.rubyforge.org/rubygems-update/Gem.html
775
+ local_dir = ENV['OPENSTUDIO_GEM_PATH'] ? ENV['OPENSTUDIO_GEM_PATH'] : "~/OpenStudio/v#{OpenStudio.openStudioVersion}"
776
+ local_dir = File.absolute_path(local_dir)
777
+ ENV['GEM_PATH'] = OpenStudio::Workflow::Util::IO.is_windows? ? local_dir.tr('/', '\\') : local_dir
778
+ $logger.debug "Set environment variable GEM_PATH to #{ENV['GEM_PATH']}"
779
+ ENV['GEM_HOME'] = OpenStudio::Workflow::Util::IO.is_windows? ? '\\' : '/'
780
+ $logger.debug "Set environment variable GEM_HOME to #{ENV['GEM_HOME']}"
781
+ Gem.clear_paths
782
+ $logger.debug 'Reset Gem paths; openstudio_cli associated gems should load correctly'
783
+
784
+ # Execute the CLI interface, and exit with the proper error code
785
+ $logger.info "Executing argv: #{$argv}"
786
+ CLI.new($argv).execute