bolt 0.11.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bolt might be problematic. Click here for more details.

Files changed (165) hide show
  1. checksums.yaml +4 -4
  2. data/lib/bolt/cli.rb +127 -31
  3. data/lib/bolt/config.rb +39 -6
  4. data/lib/bolt/execution_result.rb +109 -0
  5. data/lib/bolt/executor.rb +4 -1
  6. data/lib/bolt/node.rb +6 -1
  7. data/lib/bolt/node/orch.rb +20 -2
  8. data/lib/bolt/node/winrm.rb +22 -10
  9. data/lib/bolt/node_uri.rb +5 -7
  10. data/lib/bolt/outputter/human.rb +60 -1
  11. data/lib/bolt/outputter/json.rb +11 -0
  12. data/lib/bolt/target.rb +32 -0
  13. data/lib/bolt/version.rb +1 -1
  14. data/modules/boltlib/lib/puppet/datatypes/executionresult.rb +30 -0
  15. data/modules/boltlib/lib/puppet/datatypes/target.rb +12 -0
  16. data/modules/boltlib/lib/puppet/functions/file_upload.rb +3 -3
  17. data/modules/boltlib/lib/puppet/functions/run_command.rb +3 -3
  18. data/modules/boltlib/lib/puppet/functions/run_script.rb +3 -3
  19. data/modules/boltlib/lib/puppet/functions/run_task.rb +10 -2
  20. data/vendored/puppet/lib/puppet/application/describe.rb +0 -1
  21. data/vendored/puppet/lib/puppet/configurer.rb +1 -1
  22. data/vendored/puppet/lib/puppet/configurer/plugin_handler.rb +15 -9
  23. data/vendored/puppet/lib/puppet/datatypes.rb +213 -0
  24. data/vendored/puppet/lib/puppet/datatypes/error.rb +19 -0
  25. data/vendored/puppet/lib/puppet/datatypes/impl/error.rb +42 -0
  26. data/vendored/puppet/lib/puppet/error.rb +1 -1
  27. data/vendored/puppet/lib/puppet/face/catalog.rb +1 -1
  28. data/vendored/puppet/lib/puppet/face/epp.rb +3 -3
  29. data/vendored/puppet/lib/puppet/face/help.rb +12 -14
  30. data/vendored/puppet/lib/puppet/face/man.rb +1 -0
  31. data/vendored/puppet/lib/puppet/face/module/search.rb +1 -1
  32. data/vendored/puppet/lib/puppet/face/node.rb +1 -0
  33. data/vendored/puppet/lib/puppet/face/parser.rb +0 -1
  34. data/vendored/puppet/lib/puppet/face/status.rb +1 -0
  35. data/vendored/puppet/lib/puppet/feature/base.rb +1 -1
  36. data/vendored/puppet/lib/puppet/file_bucket/dipper.rb +0 -1
  37. data/vendored/puppet/lib/puppet/file_system/uniquefile.rb +2 -2
  38. data/vendored/puppet/lib/puppet/forge/errors.rb +21 -29
  39. data/vendored/puppet/lib/puppet/functions.rb +64 -84
  40. data/vendored/puppet/lib/puppet/functions/defined.rb +0 -3
  41. data/vendored/puppet/lib/puppet/functions/find_file.rb +0 -1
  42. data/vendored/puppet/lib/puppet/functions/map.rb +0 -1
  43. data/vendored/puppet/lib/puppet/functions/regsubst.rb +1 -1
  44. data/vendored/puppet/lib/puppet/graph/simple_graph.rb +6 -10
  45. data/vendored/puppet/lib/puppet/indirector/catalog/compiler.rb +37 -25
  46. data/vendored/puppet/lib/puppet/indirector/file_server.rb +1 -1
  47. data/vendored/puppet/lib/puppet/indirector/indirection.rb +0 -2
  48. data/vendored/puppet/lib/puppet/indirector/rest.rb +9 -8
  49. data/vendored/puppet/lib/puppet/info_service/class_information_service.rb +1 -1
  50. data/vendored/puppet/lib/puppet/interface/option_manager.rb +1 -1
  51. data/vendored/puppet/lib/puppet/loaders.rb +1 -0
  52. data/vendored/puppet/lib/puppet/module.rb +6 -2
  53. data/vendored/puppet/lib/puppet/module_tool/applications/unpacker.rb +1 -1
  54. data/vendored/puppet/lib/puppet/module_tool/errors/installer.rb +29 -41
  55. data/vendored/puppet/lib/puppet/module_tool/errors/shared.rb +63 -138
  56. data/vendored/puppet/lib/puppet/module_tool/errors/uninstaller.rb +15 -37
  57. data/vendored/puppet/lib/puppet/module_tool/errors/upgrader.rb +18 -30
  58. data/vendored/puppet/lib/puppet/module_tool/installed_modules.rb +1 -1
  59. data/vendored/puppet/lib/puppet/module_tool/metadata.rb +0 -1
  60. data/vendored/puppet/lib/puppet/network/http/api/indirected_routes.rb +1 -1
  61. data/vendored/puppet/lib/puppet/network/rights.rb +1 -1
  62. data/vendored/puppet/lib/puppet/node.rb +1 -1
  63. data/vendored/puppet/lib/puppet/node/environment.rb +1 -1
  64. data/vendored/puppet/lib/puppet/parameter/value_collection.rb +4 -17
  65. data/vendored/puppet/lib/puppet/parser/compiler.rb +1 -0
  66. data/vendored/puppet/lib/puppet/parser/functions.rb +0 -1
  67. data/vendored/puppet/lib/puppet/parser/functions/scanf.rb +1 -1
  68. data/vendored/puppet/lib/puppet/parser/scope.rb +4 -3
  69. data/vendored/puppet/lib/puppet/parser/script_compiler.rb +1 -0
  70. data/vendored/puppet/lib/puppet/parser/templatewrapper.rb +3 -2
  71. data/vendored/puppet/lib/puppet/parser/type_loader.rb +1 -1
  72. data/vendored/puppet/lib/puppet/pops.rb +1 -0
  73. data/vendored/puppet/lib/puppet/pops/evaluator/access_operator.rb +3 -2
  74. data/vendored/puppet/lib/puppet/pops/evaluator/closure.rb +1 -1
  75. data/vendored/puppet/lib/puppet/pops/evaluator/evaluator_impl.rb +2 -2
  76. data/vendored/puppet/lib/puppet/pops/functions/dispatch.rb +6 -5
  77. data/vendored/puppet/lib/puppet/pops/functions/function.rb +2 -2
  78. data/vendored/puppet/lib/puppet/pops/loader/loader.rb +1 -1
  79. data/vendored/puppet/lib/puppet/pops/loader/loader_paths.rb +40 -4
  80. data/vendored/puppet/lib/puppet/pops/loader/module_loaders.rb +6 -2
  81. data/vendored/puppet/lib/puppet/pops/loader/puppet_resource_type_impl_instantiator.rb +8 -8
  82. data/vendored/puppet/lib/puppet/pops/loader/ruby_data_type_instantiator.rb +40 -0
  83. data/vendored/puppet/lib/puppet/pops/loader/static_loader.rb +6 -26
  84. data/vendored/puppet/lib/puppet/pops/loaders.rb +11 -2
  85. data/vendored/puppet/lib/puppet/pops/lookup/data_dig_function_provider.rb +1 -1
  86. data/vendored/puppet/lib/puppet/pops/lookup/lookup_adapter.rb +4 -14
  87. data/vendored/puppet/lib/puppet/pops/model/model_tree_dumper.rb +1 -1
  88. data/vendored/puppet/lib/puppet/pops/parser/code_merger.rb +2 -2
  89. data/vendored/puppet/lib/puppet/pops/parser/eparser.rb +1471 -1501
  90. data/vendored/puppet/lib/puppet/pops/parser/epp_support.rb +0 -2
  91. data/vendored/puppet/lib/puppet/pops/parser/evaluating_parser.rb +1 -1
  92. data/vendored/puppet/lib/puppet/pops/parser/interpolation_support.rb +1 -1
  93. data/vendored/puppet/lib/puppet/pops/parser/lexer2.rb +2 -26
  94. data/vendored/puppet/lib/puppet/pops/parser/locator.rb +5 -7
  95. data/vendored/puppet/lib/puppet/pops/parser/parser_support.rb +2 -2
  96. data/vendored/puppet/lib/puppet/pops/parser/slurp_support.rb +0 -3
  97. data/vendored/puppet/lib/puppet/pops/pcore.rb +0 -11
  98. data/vendored/puppet/lib/puppet/pops/serialization/object.rb +3 -4
  99. data/vendored/puppet/lib/puppet/pops/serialization/to_data_converter.rb +1 -1
  100. data/vendored/puppet/lib/puppet/pops/time/timespan.rb +1 -1
  101. data/vendored/puppet/lib/puppet/pops/types/iterable.rb +14 -7
  102. data/vendored/puppet/lib/puppet/pops/types/p_object_type.rb +38 -7
  103. data/vendored/puppet/lib/puppet/pops/types/p_object_type_extension.rb +21 -22
  104. data/vendored/puppet/lib/puppet/pops/types/p_sem_ver_range_type.rb +0 -1
  105. data/vendored/puppet/lib/puppet/pops/types/p_type_set_type.rb +0 -1
  106. data/vendored/puppet/lib/puppet/pops/types/p_uri_type.rb +0 -1
  107. data/vendored/puppet/lib/puppet/pops/types/puppet_object.rb +1 -1
  108. data/vendored/puppet/lib/puppet/pops/types/string_converter.rb +5 -1
  109. data/vendored/puppet/lib/puppet/pops/types/type_calculator.rb +5 -1
  110. data/vendored/puppet/lib/puppet/pops/types/type_factory.rb +1 -5
  111. data/vendored/puppet/lib/puppet/pops/types/type_formatter.rb +21 -0
  112. data/vendored/puppet/lib/puppet/pops/types/types.rb +2 -7
  113. data/vendored/puppet/lib/puppet/pops/validation/checker4_0.rb +1 -3
  114. data/vendored/puppet/lib/puppet/property.rb +1 -1
  115. data/vendored/puppet/lib/puppet/provider/augeas/augeas.rb +3 -4
  116. data/vendored/puppet/lib/puppet/provider/exec.rb +0 -2
  117. data/vendored/puppet/lib/puppet/provider/nameservice.rb +6 -1
  118. data/vendored/puppet/lib/puppet/provider/nameservice/directoryservice.rb +3 -3
  119. data/vendored/puppet/lib/puppet/provider/package/appdmg.rb +0 -1
  120. data/vendored/puppet/lib/puppet/provider/package/apple.rb +0 -1
  121. data/vendored/puppet/lib/puppet/provider/package/macports.rb +2 -2
  122. data/vendored/puppet/lib/puppet/provider/package/pkgdmg.rb +0 -1
  123. data/vendored/puppet/lib/puppet/provider/package/portage.rb +0 -1
  124. data/vendored/puppet/lib/puppet/provider/package/zypper.rb +2 -2
  125. data/vendored/puppet/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb +2 -2
  126. data/vendored/puppet/lib/puppet/provider/service/init.rb +1 -0
  127. data/vendored/puppet/lib/puppet/provider/service/launchd.rb +3 -3
  128. data/vendored/puppet/lib/puppet/provider/user/aix.rb +1 -1
  129. data/vendored/puppet/lib/puppet/provider/user/openbsd.rb +1 -1
  130. data/vendored/puppet/lib/puppet/provider/user/pw.rb +1 -1
  131. data/vendored/puppet/lib/puppet/provider/yumrepo/inifile.rb +2 -4
  132. data/vendored/puppet/lib/puppet/provider/zfs/zfs.rb +1 -1
  133. data/vendored/puppet/lib/puppet/provider/zpool/zpool.rb +1 -1
  134. data/vendored/puppet/lib/puppet/reference/type.rb +0 -1
  135. data/vendored/puppet/lib/puppet/resource.rb +1 -2
  136. data/vendored/puppet/lib/puppet/resource/status.rb +0 -1
  137. data/vendored/puppet/lib/puppet/resource/type.rb +3 -3
  138. data/vendored/puppet/lib/puppet/resource/type_collection.rb +1 -1
  139. data/vendored/puppet/lib/puppet/settings/environment_conf.rb +0 -1
  140. data/vendored/puppet/lib/puppet/ssl/host.rb +1 -1
  141. data/vendored/puppet/lib/puppet/syntax_checkers/base64.rb +1 -1
  142. data/vendored/puppet/lib/puppet/transaction/persistence.rb +1 -1
  143. data/vendored/puppet/lib/puppet/type.rb +17 -4
  144. data/vendored/puppet/lib/puppet/type/file.rb +3 -3
  145. data/vendored/puppet/lib/puppet/type/mount.rb +9 -0
  146. data/vendored/puppet/lib/puppet/type/schedule.rb +25 -13
  147. data/vendored/puppet/lib/puppet/type/tidy.rb +2 -2
  148. data/vendored/puppet/lib/puppet/type/user.rb +1 -1
  149. data/vendored/puppet/lib/puppet/util.rb +19 -14
  150. data/vendored/puppet/lib/puppet/util/filetype.rb +2 -2
  151. data/vendored/puppet/lib/puppet/util/json_lockfile.rb +1 -1
  152. data/vendored/puppet/lib/puppet/util/log.rb +5 -3
  153. data/vendored/puppet/lib/puppet/util/log/destinations.rb +0 -1
  154. data/vendored/puppet/lib/puppet/util/monkey_patches.rb +1 -1
  155. data/vendored/puppet/lib/puppet/util/network_device/config.rb +2 -2
  156. data/vendored/puppet/lib/puppet/util/plist.rb +6 -4
  157. data/vendored/puppet/lib/puppet/util/rdoc/generators/puppet_generator.rb +1 -1
  158. data/vendored/puppet/lib/puppet/util/rdoc/parser/puppet_parser_rdoc2.rb +1 -1
  159. data/vendored/puppet/lib/puppet/util/storage.rb +2 -2
  160. data/vendored/puppet/lib/puppet/util/windows/registry.rb +2 -2
  161. data/vendored/puppet/lib/puppet/util/windows/sid.rb +0 -2
  162. data/vendored/puppet/lib/puppet/version.rb +1 -1
  163. data/vendored/puppet/lib/puppet_pal.rb +30 -17
  164. metadata +28 -7
  165. data/vendored/puppet/lib/puppet/pops/types/execution_result.rb +0 -137
@@ -201,8 +201,6 @@ module EppSupport
201
201
  if s.end_with? "<%"
202
202
  @mode = :error
203
203
  @issue = Issues::EPP_UNBALANCED_EXPRESSION
204
- else
205
- mode = :epp
206
204
  end
207
205
  return s
208
206
 
@@ -80,7 +80,7 @@ class EvaluatingParser
80
80
  end
81
81
 
82
82
  def convert_to_3x(object, scope)
83
- val = evaluator.convert(object, scope, nil)
83
+ evaluator.convert(object, scope, nil)
84
84
  end
85
85
 
86
86
  def validate(parse_result)
@@ -221,7 +221,7 @@ module Puppet::Pops::Parser::InterpolationSupport
221
221
 
222
222
  def transform_to_variable(token)
223
223
  token_name = token[0]
224
- if [:NUMBER, :NAME, :WORD].include?(token_name) || self.class::KEYWORD_NAMES[token_name]
224
+ if [:NUMBER, :NAME, :WORD].include?(token_name) || self.class::KEYWORD_NAMES[token_name] || @taskm_keywords[token_name]
225
225
  t = token[1]
226
226
  ta = t.token_array
227
227
  [:VARIABLE, self.class::TokenValue.new([:VARIABLE, ta[1], ta[2]], t.offset, t.locator)]
@@ -143,31 +143,9 @@ class Lexer2
143
143
  KEYWORDS.each {|k,v| v[1].freeze; v.freeze }
144
144
  KEYWORDS.freeze
145
145
 
146
- # We maintain two different tables of tokens for the constructs
147
- # introduced by 'tasks & plans'. Which ones we use is decided in
148
- # +initvars+; by selecting one or the other variant, we select whether we
149
- # hit the --tasks code paths
150
- TASK_MANAGEMENT_TOKENS = {
151
- :with_tasks => {
152
- 'plan' => [:PLAN, 'plan', 4]
153
- },
154
- :without_tasks => {
155
- 'plan' => [:PLAN_R, 'plan', 4]
156
- }
157
- }
158
-
159
- TASK_MANAGEMENT_TOKENS.each do |_, variant|
160
- variant.each { |_,v| v[1].freeze; v.freeze }
161
- variant.freeze
162
- end
163
- TASK_MANAGEMENT_TOKENS.freeze
164
-
165
146
  # Reverse lookup of keyword name to string
166
147
  KEYWORD_NAMES = {}
167
148
  KEYWORDS.each {|k, v| KEYWORD_NAMES[v[0]] = k }
168
- TASK_MANAGEMENT_TOKENS.each do |_, variant|
169
- variant.each { |k,v| KEYWORD_NAMES[v[0]] = k }
170
- end
171
149
  KEYWORD_NAMES.freeze
172
150
 
173
151
  PATTERN_WS = %r{[[:blank:]\r]+}
@@ -535,7 +513,6 @@ class Lexer2
535
513
  scn.pos = before
536
514
  invalid_number = scn.peek(after - before) unless invalid_number
537
515
  end
538
- length = scn.pos - before
539
516
  assert_numeric(invalid_number, before)
540
517
  scn.pos = before + 1
541
518
  lex_error(Issues::ILLEGAL_NUMBER, {:value => invalid_number})
@@ -545,7 +522,6 @@ class Lexer2
545
522
  ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
546
523
  'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '_'].each do |c|
547
524
  @selector[c] = lambda do
548
-
549
525
  scn = @scanner
550
526
  before = scn.pos
551
527
  value = scn.scan(PATTERN_BARE_WORD)
@@ -685,8 +661,8 @@ class Lexer2
685
661
  :after => nil,
686
662
  :line_lexical_start => 0
687
663
  }
688
- taskm_mode = Puppet[:tasks] ? :with_tasks : :without_tasks
689
- @taskm_keywords = TASK_MANAGEMENT_TOKENS[taskm_mode]
664
+ # Use of --tasks introduces the new keyword 'plan'
665
+ @taskm_keywords = Puppet[:tasks] ? { 'plan' => [:PLAN, 'plan', 4] }.freeze : EMPTY_HASH
690
666
  end
691
667
 
692
668
  # Scans all of the content and returns it in an array
@@ -164,8 +164,6 @@ class Locator
164
164
  class AbstractLocator < Locator
165
165
  attr_accessor :line_index
166
166
  attr_accessor :string
167
- attr_accessor :prev_offset
168
- attr_accessor :prev_line
169
167
  attr_reader :string
170
168
  attr_reader :file
171
169
 
@@ -255,19 +253,19 @@ class Locator
255
253
 
256
254
  # Returns the line number (first line is 1) for the given offset
257
255
  def line_for_offset(offset)
258
- if prev_offset == offset
256
+ if @prev_offset == offset
259
257
  # use cache
260
- return prev_line
258
+ return @prev_line
261
259
  end
262
260
  if line_nbr = ary_bsearch_i(line_index, offset)
263
261
  # cache
264
- prev_offset = offset
265
- prev_line = line_nbr
262
+ @prev_offset = offset
263
+ @prev_line = line_nbr
266
264
  return line_nbr
267
265
  end
268
266
  # If not found it is after last
269
267
  # clear cache
270
- prev_offset = prev_line = nil
268
+ @prev_offset = @prev_line = nil
271
269
  return line_index.size
272
270
  end
273
271
  end
@@ -121,7 +121,7 @@ class Parser
121
121
  file = lexer.file
122
122
  end
123
123
  file = nil unless file.is_a?(String) && !file.empty?
124
- raise Puppet::ParseErrorWithIssue.new(error, file, line, pos, nil, issue_code = Issues::SYNTAX_ERROR.issue_code)
124
+ raise Puppet::ParseErrorWithIssue.new(error, file, line, pos, nil, Issues::SYNTAX_ERROR.issue_code)
125
125
  end
126
126
 
127
127
  # Parses a String of pp DSL code.
@@ -219,7 +219,7 @@ class Parser
219
219
  # Create a synthetic NOOP token at EOF offset with 0 size. The lexer does not produce an EOF token that is
220
220
  # visible to the grammar rules. Creating this token is mainly to reuse the positioning logic as it
221
221
  # expects a token decorated with location information.
222
- token_sym, token = @lexer.emit_completed([:NOOP,'',0], locator.string.bytesize)
222
+ _, token = @lexer.emit_completed([:NOOP,'',0], locator.string.bytesize)
223
223
  loc(no_op, token)
224
224
  # Program with a Noop
225
225
  program = Factory.PROGRAM(no_op, [], locator)
@@ -45,9 +45,6 @@ module SlurpSupport
45
45
  # Copy from old lexer - can do much better
46
46
  def slurp_uqstring
47
47
  scn = @scanner
48
- last = scn.matched
49
- ignore = true
50
-
51
48
  str = slurp(scn, @lexing_context[:uq_slurp_pattern], @lexing_context[:escapes], :ignore_invalid_escapes)
52
49
 
53
50
  # Terminator may be a single char '$', two characters '${', or empty string '' at the end of intput.
@@ -40,17 +40,6 @@ module Pcore
40
40
  add_alias('Pcore::QRef', TYPE_QUALIFIED_REFERENCE, loader)
41
41
 
42
42
  if Puppet[:tasks]
43
- require_relative 'types/execution_result'
44
-
45
- add_object_type('Target', <<-PUPPET, loader)
46
- {
47
- attributes => {
48
- host => String[1],
49
- options => { type => Hash[String[1], Data], value => {} }
50
- }
51
- }
52
- PUPPET
53
-
54
43
  add_object_type('Task', <<-PUPPET, loader)
55
44
  {
56
45
  attributes => {
@@ -9,8 +9,7 @@ module Serialization
9
9
  class ObjectReader
10
10
  include InstanceReader
11
11
 
12
- def read(impl_class, value_count, deserializer)
13
- type = impl_class._pcore_type
12
+ def read(type, impl_class, value_count, deserializer)
14
13
  (names, types, required_count) = type.parameter_info(impl_class)
15
14
  max = names.size
16
15
  unless value_count >= required_count && value_count <= max
@@ -25,7 +24,7 @@ class ObjectReader
25
24
  Types::TypeAsserter.assert_instance_of(nil, ptype, arg) { "#{type.name}[#{names[index]}]" } unless arg == :default
26
25
  else
27
26
  attr = type[names[index]]
28
- raise Serialization::SerializationError, _("Missing default value for %{type_name}[%{name}]") % { type_name: type.name, name: names[index] } unless attr.value?
27
+ raise Serialization::SerializationError, _("Missing default value for %{type_name}[%{name}]") % { type_name: type.name, name: names[index] } unless attr && attr.value?
29
28
  args << attr.value
30
29
  end
31
30
  end
@@ -43,7 +42,7 @@ class ObjectWriter
43
42
 
44
43
  def write(type, value, serializer)
45
44
  impl_class = value.class
46
- (names, types, required_count) = type.parameter_info(impl_class)
45
+ (names, _, required_count) = type.parameter_info(impl_class)
47
46
  args = names.map { |name| value.send(name) }
48
47
 
49
48
  # Pop optional arguments that are default
@@ -252,7 +252,7 @@ module Serialization
252
252
  end
253
253
  else
254
254
  process(value) do
255
- (names, types, required_count) = pcore_type.parameter_info(value.class)
255
+ (names, _, required_count) = pcore_type.parameter_info(value.class)
256
256
  args = names.map { |name| value.send(name) }
257
257
 
258
258
  # Pop optional arguments that are default
@@ -259,7 +259,7 @@ module Time
259
259
  add_unless_zero(result, KEY_NANOSECONDS, n % 1000)
260
260
  n /= 1000
261
261
  add_unless_zero(result, KEY_MICROSECONDS, n % 1000)
262
- add_unless_zero(result, KEY_MILLISECONDS, n /= 1000)
262
+ add_unless_zero(result, KEY_MILLISECONDS, n / 1000)
263
263
  end
264
264
  result[KEY_NEGATIVE] = true if negative?
265
265
  end
@@ -48,10 +48,11 @@ module Puppet::Pops::Types
48
48
  # The value `nil` is returned for all other objects.
49
49
  #
50
50
  # @param o [Object] The object to produce an `Iterable` for
51
+ # @param element_type [PAnyType] the element type for the iterator. Optional (inferred if not provided)
51
52
  # @return [Iterable,nil] The produced `Iterable` or `nil` if it couldn't be produced
52
53
  #
53
54
  # @api public
54
- def self.on(o)
55
+ def self.on(o, element_type = nil)
55
56
  case o
56
57
  when IteratorProducer
57
58
  o.iterator
@@ -63,18 +64,24 @@ module Puppet::Pops::Types
63
64
  if o.empty?
64
65
  Iterator.new(PUnitType::DEFAULT, o.each)
65
66
  else
66
- tc = TypeCalculator.singleton
67
- Iterator.new(PVariantType.maybe_create(o.map {|e| tc.infer_set(e) }), o.each)
67
+ if element_type.nil?
68
+ tc = TypeCalculator.singleton
69
+ element_type = PVariantType.maybe_create(o.map {|e| tc.infer_set(e) })
70
+ end
71
+ Iterator.new(element_type, o.each)
68
72
  end
69
73
  when Hash
70
74
  # Each element is a two element [key, value] tuple.
71
75
  if o.empty?
72
76
  HashIterator.new(PHashType::DEFAULT_KEY_PAIR_TUPLE, o.each)
73
77
  else
74
- tc = TypeCalculator.singleton
75
- HashIterator.new(PTupleType.new([
76
- PVariantType.maybe_create(o.keys.map {|e| tc.infer_set(e) }),
77
- PVariantType.maybe_create(o.values.map {|e| tc.infer_set(e) })], PHashType::KEY_PAIR_TUPLE_SIZE), o.each_pair)
78
+ if element_type.nil?
79
+ tc = TypeCalculator.singleton
80
+ element_type = PTupleType.new([
81
+ PVariantType.maybe_create(o.keys.map {|e| tc.infer_set(e) }),
82
+ PVariantType.maybe_create(o.values.map {|e| tc.infer_set(e) })], PHashType::KEY_PAIR_TUPLE_SIZE)
83
+ end
84
+ HashIterator.new(element_type, o.each_pair)
78
85
  end
79
86
  when Integer
80
87
  if o == 0
@@ -457,7 +457,7 @@ class PObjectType < PMetaType
457
457
  # @return [Object] the created instance
458
458
  # @api private
459
459
  def read(value_count, deserializer)
460
- reader.read(implementation_class, value_count, deserializer)
460
+ reader.read(self, implementation_class, value_count, deserializer)
461
461
  end
462
462
 
463
463
  # Write an instance of this type using a serializer
@@ -471,15 +471,11 @@ class PObjectType < PMetaType
471
471
  # @api private
472
472
  def create_new_function
473
473
  impl_class = implementation_class
474
- class_name = impl_class.name || "Anonymous Ruby class for #{name}"
475
474
 
476
475
  (param_names, param_types, required_param_count) = parameter_info(impl_class)
477
476
 
478
477
  # Create the callable with a size that reflects the required and optional parameters
479
- param_types << required_param_count
480
- param_types << param_names.size
481
-
482
- create_type = TypeFactory.callable(*param_types)
478
+ create_type = TypeFactory.callable(*param_types, required_param_count, param_names.size)
483
479
  from_hash_type = TypeFactory.callable(init_hash_type, 1, 1)
484
480
 
485
481
  # Create and return a #new_XXX function where the dispatchers are added programmatically.
@@ -527,6 +523,7 @@ class PObjectType < PMetaType
527
523
  if impl_name.nil?
528
524
  # Use generator to create a default implementation
529
525
  @implementation_class = RubyGenerator.new.create_class(self)
526
+ @implementation_class.class_eval(&@implementation_override) if instance_variable_defined?(:@implementation_override)
530
527
  else
531
528
  # Can the mapping be loaded?
532
529
  class_name = impl_name[0]
@@ -547,10 +544,42 @@ class PObjectType < PMetaType
547
544
  @implementation_class = cls
548
545
  end
549
546
 
547
+ # The block passed to this method will be passed in a call to `#class_eval` on the dynamically generated
548
+ # class for this data type. It's indended use is to complement or redefine the generated methods and
549
+ # attribute readers.
550
+ #
551
+ # The method is normally called with the block passed to `#implementation` when a data type is defined using
552
+ # {Puppet::DataTypes::create_type}.
553
+ #
554
+ # @api private
555
+ def implementation_override=(block)
556
+ if !@implementation_class.nil? || instance_variable_defined?(:@implementation_override)
557
+ raise ArgumentError, "attempt to redefine implementation override for #{label}"
558
+ end
559
+ @implementation_override = block
560
+ end
561
+
562
+ def extract_init_hash(o)
563
+ return o._pcore_init_hash if o.respond_to?(:_pcore_init_hash)
564
+
565
+ result = {}
566
+ pic = parameter_info(o.class)
567
+ attrs = attributes(true)
568
+ pic[0].each do |name|
569
+ v = o.send(name)
570
+ result[name] = v unless attrs[name].default_value?(v)
571
+ end
572
+ result
573
+ end
574
+
550
575
  # @api private
551
576
  # @return [(Array<String>, Array<PAnyType>, Integer)] array of parameter names, array of parameter types, and a count reflecting the required number of parameters
552
577
  def parameter_info(impl_class)
553
578
  # Create a types and a names array where optional entries ends up last
579
+ @parameter_info ||= {}
580
+ pic = @parameter_info[impl_class]
581
+ return pic if pic
582
+
554
583
  opt_types = []
555
584
  opt_names = []
556
585
  non_opt_types = []
@@ -602,7 +631,9 @@ class PObjectType < PMetaType
602
631
  end
603
632
  end
604
633
 
605
- [param_names, param_types, non_opt_types.size]
634
+ pic = [param_names.freeze, param_types.freeze, non_opt_types.size].freeze
635
+ @parameter_info[impl_class] = pic
636
+ pic
606
637
  end
607
638
 
608
639
  # @api private
@@ -28,6 +28,23 @@ class PObjectTypeExtension < PAnyType
28
28
  impl_class.new(base_type, init_parameters)
29
29
  end
30
30
 
31
+ # Creates an array of type parameters from the attributes of the given instance that matches the
32
+ # type parameters by name. Type parameters for which there is no matching attribute
33
+ # will have `nil` in their corresponding position on the array. The array is then passed
34
+ # as the `init_parameters` argument in a call to `create`
35
+ #
36
+ # @return [PObjectTypeExtension] the created extension
37
+ # @api private
38
+ def self.create_from_instance(base_type, instance)
39
+ type_parameters = base_type.type_parameters(true)
40
+ attrs = base_type.attributes(true)
41
+ params = type_parameters.keys.map do |pn|
42
+ attr = attrs[pn]
43
+ attr.nil? ? nil : instance.send(pn)
44
+ end
45
+ create(base_type, params)
46
+ end
47
+
31
48
  def [](name)
32
49
  @base_type[name]
33
50
  end
@@ -38,15 +55,10 @@ class PObjectTypeExtension < PAnyType
38
55
  raise Puppet::ParseError, _('The %{label}-Type cannot be parameterized using []') % { label: base_type.label } if pts.empty?
39
56
  @base_type = base_type
40
57
 
41
- named_args = false
42
- if init_parameters.is_a?(PuppetObject)
43
- init_parameters = parameters_from_instance(init_parameters, pts)
44
- else
45
- named_args = init_parameters.size == 1 && init_parameters[0].is_a?(Hash)
46
- if named_args
47
- # Catch case when first parameter is an assignable Hash
48
- named_args = pts.size >= 1 && !pts.values[0].type.instance?(init_parameters[0])
49
- end
58
+ named_args = init_parameters.size == 1 && init_parameters[0].is_a?(Hash)
59
+ if named_args
60
+ # Catch case when first parameter is an assignable Hash
61
+ named_args = pts.size >= 1 && !pts.values[0].type.instance?(init_parameters[0])
50
62
  end
51
63
 
52
64
  by_name = {}
@@ -143,19 +155,6 @@ class PObjectTypeExtension < PAnyType
143
155
 
144
156
  protected
145
157
 
146
- # Creates an array of type parameters from the attributes that matches the
147
- # type parameters by name. Type parameters for which there is no matching attribute
148
- # will have `nil` in their corresponding position on the array.
149
- #
150
- # @return [Array] array of values from instance that maps to type parameters
151
- def parameters_from_instance(instance, type_parameters)
152
- attrs = @base_type.attributes(true)
153
- type_parameters.keys.map do |pn|
154
- attr = attrs[pn]
155
- attr.nil? ? nil : instance.send(pn)
156
- end
157
- end
158
-
159
158
  # Checks that the given `param_values` hash contains all keys present in the `parameters` of
160
159
  # this instance and that each keyed value is a match for the given parameter. The match is done
161
160
  # using case expression semantics.
@@ -107,7 +107,6 @@ class PSemVerRangeType < PAnyType
107
107
  end
108
108
 
109
109
  def self.new_function(type)
110
- range_expr = "\\A#{range_pattern}\\Z"
111
110
  @new_function ||= Puppet::Functions.create_loaded_function(:new_VersionRange, type.loader) do
112
111
  local_types do
113
112
  type 'SemVerRangeString = String[1]'
@@ -227,7 +227,6 @@ class PTypeSetType < PMetaType
227
227
  def name_for(t, default_name)
228
228
  key = @types.key(t)
229
229
  if key.nil?
230
- qname = t.name
231
230
  if @references.empty?
232
231
  default_name
233
232
  else
@@ -151,7 +151,6 @@ class PURIType < PAnyType
151
151
  def _assignable?(o, guard = nil)
152
152
  return false unless o.class == self.class
153
153
  return true if @parameters.nil?
154
- params = @parameters
155
154
  o_params = o.parameters || EMPTY_HASH
156
155
 
157
156
  eval = Parser::EvaluatingParser.singleton.evaluator
@@ -15,7 +15,7 @@ module PuppetObject
15
15
  # Create a parameterized type based on the values of this instance that
16
16
  # contains a parameter value for each type parameter that matches an
17
17
  # attribute by name and type of value
18
- @_cached_ptype = PObjectTypeExtension.create(t, self)
18
+ @_cached_ptype = PObjectTypeExtension.create_from_instance(t, self)
19
19
  end
20
20
  t = @_cached_ptype
21
21
  end