puppet 4.0.0 → 4.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/ext/build_defaults.yaml +8 -35
- data/ext/debian/puppet.default +0 -5
- data/ext/debian/puppet.init +1 -15
- data/lib/hiera/puppet_function.rb +15 -4
- data/lib/puppet/application/agent.rb +5 -0
- data/lib/puppet/application/apply.rb +23 -2
- data/lib/puppet/application/device.rb +8 -3
- data/lib/puppet/application/master.rb +16 -5
- data/lib/puppet/configurer.rb +7 -5
- data/lib/puppet/defaults.rb +18 -0
- data/lib/puppet/environments.rb +1 -1
- data/lib/puppet/error.rb +27 -1
- data/lib/puppet/file_serving/metadata.rb +13 -8
- data/lib/puppet/file_serving/terminus_helper.rb +7 -8
- data/lib/puppet/file_system.rb +13 -0
- data/lib/puppet/file_system/file_impl.rb +4 -0
- data/lib/puppet/file_system/memory_impl.rb +4 -0
- data/lib/puppet/file_system/windows.rb +8 -0
- data/lib/puppet/functions.rb +33 -3
- data/lib/puppet/functions/defined.rb +130 -0
- data/lib/puppet/functions/regsubst.rb +1 -1
- data/lib/puppet/functions/split.rb +1 -1
- data/lib/puppet/indirector/catalog/compiler.rb +1 -1
- data/lib/puppet/indirector/facts/facter.rb +11 -0
- data/lib/puppet/loaders.rb +1 -0
- data/lib/puppet/node.rb +17 -1
- data/lib/puppet/node/environment.rb +4 -0
- data/lib/puppet/parser/ast/pops_bridge.rb +4 -0
- data/lib/puppet/parser/compiler.rb +9 -0
- data/lib/puppet/parser/functions/defined.rb +25 -1
- data/lib/puppet/parser/functions/file.rb +3 -1
- data/lib/puppet/parser/scope.rb +11 -2
- data/lib/puppet/parser/templatewrapper.rb +2 -1
- data/lib/puppet/pops.rb +4 -0
- data/lib/puppet/pops/evaluator/access_operator.rb +25 -5
- data/lib/puppet/pops/evaluator/closure.rb +28 -2
- data/lib/puppet/pops/evaluator/collector_transformer.rb +1 -11
- data/lib/puppet/pops/evaluator/collectors/catalog_collector.rb +4 -0
- data/lib/puppet/pops/evaluator/collectors/exported_collector.rb +4 -0
- data/lib/puppet/pops/evaluator/compare_operator.rb +43 -0
- data/lib/puppet/pops/evaluator/epp_evaluator.rb +7 -2
- data/lib/puppet/pops/evaluator/evaluator_impl.rb +48 -14
- data/lib/puppet/pops/evaluator/runtime3_support.rb +10 -5
- data/lib/puppet/pops/functions/dispatch.rb +6 -1
- data/lib/puppet/pops/functions/dispatcher.rb +7 -1
- data/lib/puppet/pops/issue_reporter.rb +42 -16
- data/lib/puppet/pops/issues.rb +116 -2
- data/lib/puppet/pops/loader/loader.rb +11 -0
- data/lib/puppet/pops/loader/loader_paths.rb +67 -6
- data/lib/puppet/pops/loader/module_loaders.rb +19 -8
- data/lib/puppet/pops/loader/puppet_function_instantiator.rb +78 -0
- data/lib/puppet/pops/loaders.rb +6 -4
- data/lib/puppet/pops/migration/migration_checker.rb +54 -0
- data/lib/puppet/pops/model/factory.rb +5 -1
- data/lib/puppet/pops/model/model_label_provider.rb +2 -0
- data/lib/puppet/pops/model/model_meta.rb +5 -1
- data/lib/puppet/pops/parser/egrammar.ra +9 -10
- data/lib/puppet/pops/parser/eparser.rb +1061 -1047
- data/lib/puppet/pops/parser/epp_support.rb +18 -9
- data/lib/puppet/pops/parser/evaluating_parser.rb +7 -1
- data/lib/puppet/pops/parser/heredoc_support.rb +12 -11
- data/lib/puppet/pops/parser/interpolation_support.rb +7 -1
- data/lib/puppet/pops/parser/lexer2.rb +29 -12
- data/lib/puppet/pops/parser/lexer_support.rb +52 -23
- data/lib/puppet/pops/parser/parser_support.rb +11 -14
- data/lib/puppet/pops/parser/slurp_support.rb +22 -6
- data/lib/puppet/pops/types/type_calculator.rb +156 -55
- data/lib/puppet/pops/types/type_factory.rb +66 -13
- data/lib/puppet/pops/types/type_parser.rb +22 -13
- data/lib/puppet/pops/types/types.rb +23 -4
- data/lib/puppet/pops/types/types_meta.rb +13 -2
- data/lib/puppet/pops/validation.rb +25 -2
- data/lib/puppet/pops/validation/checker4_0.rb +63 -31
- data/lib/puppet/provider/group/windows_adsi.rb +8 -4
- data/lib/puppet/provider/mount/parsed.rb +145 -2
- data/lib/puppet/provider/package/apt.rb +1 -1
- data/lib/puppet/provider/package/pip.rb +11 -2
- data/lib/puppet/provider/package/pkgng.rb +134 -0
- data/lib/puppet/provider/package/portage.rb +1 -1
- data/lib/puppet/provider/package/ports.rb +0 -3
- data/lib/puppet/provider/package/windows/exe_package.rb +0 -1
- data/lib/puppet/provider/package/windows/msi_package.rb +0 -1
- data/lib/puppet/provider/package/zypper.rb +50 -15
- data/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb +32 -7
- data/lib/puppet/provider/service/debian.rb +1 -1
- data/lib/puppet/provider/service/init.rb +7 -0
- data/lib/puppet/provider/user/openbsd.rb +1 -0
- data/lib/puppet/provider/user/windows_adsi.rb +45 -2
- data/lib/puppet/reference/indirection.rb +1 -1
- data/lib/puppet/resource.rb +1 -1
- data/lib/puppet/resource/catalog.rb +0 -4
- data/lib/puppet/settings.rb +19 -0
- data/lib/puppet/type/file.rb +1 -0
- data/lib/puppet/type/file/ensure.rb +1 -1
- data/lib/puppet/type/mount.rb +9 -1
- data/lib/puppet/type/scheduled_task.rb +13 -0
- data/lib/puppet/type/tidy.rb +3 -1
- data/lib/puppet/type/user.rb +32 -0
- data/lib/puppet/type/yumrepo.rb +5 -5
- data/lib/puppet/util/log.rb +50 -8
- data/lib/puppet/util/log/destinations.rb +23 -2
- data/lib/puppet/util/logging.rb +37 -1
- data/lib/puppet/util/run_mode.rb +1 -14
- data/lib/puppet/util/windows/adsi.rb +130 -58
- data/lib/puppet/version.rb +1 -1
- data/man/man5/puppet.conf.5 +48 -6
- data/man/man8/extlookup2hiera.8 +1 -1
- data/man/man8/puppet-agent.8 +4 -1
- data/man/man8/puppet-apply.8 +4 -1
- data/man/man8/puppet-ca.8 +1 -1
- data/man/man8/puppet-catalog.8 +1 -1
- data/man/man8/puppet-cert.8 +1 -1
- data/man/man8/puppet-certificate.8 +1 -1
- data/man/man8/puppet-certificate_request.8 +1 -1
- data/man/man8/puppet-certificate_revocation_list.8 +1 -1
- data/man/man8/puppet-config.8 +1 -1
- data/man/man8/puppet-describe.8 +1 -1
- data/man/man8/puppet-device.8 +6 -3
- data/man/man8/puppet-doc.8 +1 -1
- data/man/man8/puppet-epp.8 +1 -1
- data/man/man8/puppet-facts.8 +1 -1
- data/man/man8/puppet-file.8 +1 -1
- data/man/man8/puppet-filebucket.8 +1 -1
- data/man/man8/puppet-help.8 +1 -1
- data/man/man8/puppet-inspect.8 +1 -1
- data/man/man8/puppet-key.8 +1 -1
- data/man/man8/puppet-man.8 +1 -1
- data/man/man8/puppet-master.8 +4 -1
- data/man/man8/puppet-module.8 +1 -1
- data/man/man8/puppet-node.8 +1 -1
- data/man/man8/puppet-parser.8 +1 -1
- data/man/man8/puppet-plugin.8 +1 -1
- data/man/man8/puppet-report.8 +1 -1
- data/man/man8/puppet-resource.8 +1 -1
- data/man/man8/puppet-resource_type.8 +1 -1
- data/man/man8/puppet-status.8 +1 -1
- data/man/man8/puppet.8 +1 -1
- data/spec/fixtures/unit/data_providers/environments/production/lib/puppet/functions/environment/data.rb +3 -1
- data/spec/fixtures/unit/data_providers/environments/production/modules/xyz/functions/data.pp +6 -0
- data/spec/fixtures/unit/data_providers/environments/production/modules/xyz/lib/puppet/bindings/xyz/default.rb +9 -0
- data/spec/fixtures/unit/data_providers/environments/production/modules/xyz/manifests/init.pp +9 -0
- data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/user/functions/puppetcalled.pp +3 -0
- data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/user/functions/puppetcaller.pp +3 -0
- data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/user/functions/puppetcaller4.pp +3 -0
- data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/user/lib/puppet/functions/user/callingpuppet.rb +5 -0
- data/spec/fixtures/unit/pops/loaders/loaders/module_no_lib/modules/modulea/functions/hello.pp +3 -0
- data/spec/fixtures/unit/pops/loaders/loaders/module_no_lib/modules/modulea/manifests/init.pp +3 -0
- data/spec/fixtures/unit/pops/loaders/loaders/module_no_lib/modules/modulea/metadata.json +10 -0
- data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/functions/hello.pp +3 -0
- data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/functions/subspace/hello.pp +3 -0
- data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/metadata.json +1 -10
- data/spec/fixtures/unit/provider/mount/parsed/aix.filesystems +93 -85
- data/spec/fixtures/unit/provider/mount/parsed/aix.mount +11 -7
- data/spec/fixtures/unit/provider/package/pkgng/pkg.info +8 -0
- data/spec/fixtures/unit/provider/package/pkgng/pkg.query +1 -0
- data/spec/fixtures/unit/provider/package/pkgng/pkg.query_absent +1 -0
- data/spec/fixtures/unit/provider/package/pkgng/pkg.version +3 -0
- data/spec/fixtures/unit/provider/package/zypper/zypper-list-updates-empty.out +3 -0
- data/spec/integration/application/apply_spec.rb +49 -0
- data/spec/integration/faces/plugin_spec.rb +0 -4
- data/spec/integration/indirector/facts/facter_spec.rb +59 -0
- data/spec/integration/parser/compiler_spec.rb +850 -0
- data/spec/integration/parser/resource_expressions_spec.rb +3 -0
- data/spec/integration/parser/scope_spec.rb +26 -5
- data/spec/integration/transaction_spec.rb +1 -1
- data/spec/integration/type/file_spec.rb +318 -41
- data/spec/integration/util/windows/security_spec.rb +14 -5
- data/spec/lib/matchers/resource.rb +22 -1
- data/spec/lib/puppet_spec/matchers.rb +6 -4
- data/spec/unit/application/master_spec.rb +33 -7
- data/spec/unit/data_providers/function_data_provider_spec.rb +10 -1
- data/spec/unit/file_serving/metadata_spec.rb +1 -1
- data/spec/unit/file_serving/terminus_helper_spec.rb +2 -3
- data/spec/unit/file_system_spec.rb +38 -0
- data/spec/unit/functions/defined_spec.rb +289 -0
- data/spec/unit/functions/hiera_spec.rb +8 -6
- data/spec/unit/functions/regsubst_spec.rb +4 -0
- data/spec/unit/functions/split_spec.rb +8 -0
- data/spec/unit/functions4_spec.rb +97 -2
- data/spec/unit/indirector/facts/facter_spec.rb +7 -0
- data/spec/unit/node_spec.rb +6 -0
- data/spec/unit/parser/functions/file_spec.rb +7 -1
- data/spec/unit/parser/functions/template_spec.rb +1 -1
- data/spec/unit/parser/scope_spec.rb +2 -2
- data/spec/unit/parser/templatewrapper_spec.rb +1 -1
- data/spec/unit/pops/evaluator/access_ops_spec.rb +19 -0
- data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +84 -18
- data/spec/unit/pops/evaluator/variables_spec.rb +1 -1
- data/spec/unit/pops/issues_spec.rb +16 -16
- data/spec/unit/pops/loaders/loaders_spec.rb +106 -48
- data/spec/unit/pops/migration_spec.rb +53 -0
- data/spec/unit/pops/parser/lexer2_spec.rb +142 -1
- data/spec/unit/pops/parser/parse_heredoc_spec.rb +26 -0
- data/spec/unit/pops/types/type_calculator_spec.rb +205 -12
- data/spec/unit/pops/validation_spec.rb +66 -0
- data/spec/unit/pops/validator/validator_spec.rb +1 -1
- data/spec/unit/provider/group/windows_adsi_spec.rb +57 -9
- data/spec/unit/provider/mount/parsed_spec.rb +31 -5
- data/spec/unit/provider/package/apt_spec.rb +5 -0
- data/spec/unit/provider/package/pip_spec.rb +9 -0
- data/spec/unit/provider/package/pkgng_spec.rb +172 -0
- data/spec/unit/provider/package/windows/exe_package_spec.rb +0 -1
- data/spec/unit/provider/package/windows/msi_package_spec.rb +0 -1
- data/spec/unit/provider/package/zypper_spec.rb +50 -19
- data/spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb +312 -70
- data/spec/unit/provider/service/base_spec.rb +38 -27
- data/spec/unit/provider/service/debian_spec.rb +8 -0
- data/spec/unit/provider/service/freebsd_spec.rb +1 -0
- data/spec/unit/provider/service/gentoo_spec.rb +1 -0
- data/spec/unit/provider/service/init_spec.rb +18 -0
- data/spec/unit/provider/service/openbsd_spec.rb +1 -0
- data/spec/unit/provider/service/redhat_spec.rb +1 -0
- data/spec/unit/provider/user/windows_adsi_spec.rb +134 -5
- data/spec/unit/settings_spec.rb +11 -0
- data/spec/unit/util/log_spec.rb +113 -0
- data/spec/unit/util/windows/adsi_spec.rb +135 -41
- data/spec/unit/util/windows/sid_spec.rb +0 -10
- metadata +48 -2
@@ -7,10 +7,13 @@
|
|
7
7
|
# TODO: More detailed performance analysis of excessive character escaping and interpolation.
|
8
8
|
#
|
9
9
|
module Puppet::Pops::Parser::SlurpSupport
|
10
|
+
include Puppet::Pops::Parser::LexerSupport
|
10
11
|
|
11
12
|
SLURP_SQ_PATTERN = /(?:[^\\]|^|[^\\])(?:[\\]{2})*[']/
|
12
13
|
SLURP_DQ_PATTERN = /(?:[^\\]|^|[^\\])(?:[\\]{2})*(["]|[$]\{?)/
|
13
14
|
SLURP_UQ_PATTERN = /(?:[^\\]|^|[^\\])(?:[\\]{2})*([$]\{?|\z)/
|
15
|
+
# unquoted, no escapes
|
16
|
+
SLURP_UQNE_PATTERN = /(\$\{?|\z)/m
|
14
17
|
SLURP_ALL_PATTERN = /.*(\z)/m
|
15
18
|
SQ_ESCAPES = %w{ \\ ' }
|
16
19
|
DQ_ESCAPES = %w{ \\ $ ' " r n t s u}+["\r\n", "\n"]
|
@@ -19,7 +22,8 @@ module Puppet::Pops::Parser::SlurpSupport
|
|
19
22
|
def slurp_sqstring
|
20
23
|
# skip the leading '
|
21
24
|
@scanner.pos += 1
|
22
|
-
str = slurp(@scanner, SLURP_SQ_PATTERN, SQ_ESCAPES, :ignore_invalid_escapes)
|
25
|
+
str = slurp(@scanner, SLURP_SQ_PATTERN, SQ_ESCAPES, :ignore_invalid_escapes)
|
26
|
+
lex_error(Puppet::Pops::Issues::UNCLOSED_QUOTE, :after => "\"'\"", :followed_by => followed_by) unless str
|
23
27
|
str[0..-2] # strip closing "'" from result
|
24
28
|
end
|
25
29
|
|
@@ -28,7 +32,7 @@ module Puppet::Pops::Parser::SlurpSupport
|
|
28
32
|
last = scn.matched
|
29
33
|
str = slurp(scn, SLURP_DQ_PATTERN, DQ_ESCAPES, false)
|
30
34
|
unless str
|
31
|
-
lex_error(
|
35
|
+
lex_error(Puppet::Pops::Issues::UNCLOSED_QUOTE, :after => format_quote(last), :followed_by => followed_by)
|
32
36
|
end
|
33
37
|
|
34
38
|
# Terminator may be a single char '"', '$', or two characters '${' group match 1 (scn[1]) from the last slurp holds this
|
@@ -41,6 +45,7 @@ module Puppet::Pops::Parser::SlurpSupport
|
|
41
45
|
scn = @scanner
|
42
46
|
last = scn.matched
|
43
47
|
ignore = true
|
48
|
+
|
44
49
|
str = slurp(scn, @lexing_context[:uq_slurp_pattern], @lexing_context[:escapes], :ignore_invalid_escapes)
|
45
50
|
|
46
51
|
# Terminator may be a single char '$', two characters '${', or empty string '' at the end of intput.
|
@@ -65,11 +70,12 @@ module Puppet::Pops::Parser::SlurpSupport
|
|
65
70
|
# Process unicode escapes first as they require getting 4 hex digits
|
66
71
|
# If later a \u is found it is warned not to be a unicode escape
|
67
72
|
if escapes.include?('u')
|
68
|
-
str.gsub!(/\\u([\da-fA-F]{4})/m) {
|
69
|
-
[$1.hex].pack("U")
|
73
|
+
str.gsub!(/\\u(?:([\da-fA-F]{4})|\{([\da-fA-F]{1,6})\})/m) {
|
74
|
+
[($1 || $2).hex].pack("U")
|
70
75
|
}
|
71
76
|
end
|
72
77
|
|
78
|
+
begin
|
73
79
|
str.gsub!(/\\([^\r\n]|(?:\r?\n))/m) {
|
74
80
|
ch = $1
|
75
81
|
if escapes.include? ch
|
@@ -79,17 +85,27 @@ module Puppet::Pops::Parser::SlurpSupport
|
|
79
85
|
when 't' ; "\t"
|
80
86
|
when 's' ; " "
|
81
87
|
when 'u'
|
82
|
-
Puppet
|
88
|
+
lex_warning(Puppet::Pops::Issues::ILLEGAL_UNICODE_ESCAPE)
|
83
89
|
"\\u"
|
84
90
|
when "\n" ; ''
|
85
91
|
when "\r\n"; ''
|
86
92
|
else ch
|
87
93
|
end
|
88
94
|
else
|
89
|
-
Puppet
|
95
|
+
lex_warning(Puppet::Pops::Issues::UNRECOGNIZED_ESCAPE, :ch => ch) unless ignore_invalid_escapes
|
90
96
|
"\\#{ch}"
|
91
97
|
end
|
92
98
|
}
|
99
|
+
rescue ArgumentError => e
|
100
|
+
# A invalid byte sequence may be the result of faulty input as well, but that could not possibly
|
101
|
+
# have reached this far... Unfortunately there is no more specific error and a match on message is
|
102
|
+
# required to differentiate from other internal problems.
|
103
|
+
if e.message =~ /invalid byte sequence/
|
104
|
+
lex_error(Puppet::Pops::Issues::ILLEGAL_UNICODE_ESCAPE)
|
105
|
+
else
|
106
|
+
raise e
|
107
|
+
end
|
108
|
+
end
|
93
109
|
str
|
94
110
|
end
|
95
111
|
end
|
@@ -268,14 +268,21 @@ class Puppet::Pops::Types::TypeCalculator
|
|
268
268
|
if t2.is_a?(Class)
|
269
269
|
t2 = type(t2)
|
270
270
|
end
|
271
|
+
t2_class = t2.class
|
272
|
+
|
271
273
|
# Unit can be assigned to anything
|
272
|
-
return true if
|
274
|
+
return true if t2_class == Types::PUnitType
|
273
275
|
|
274
|
-
if
|
276
|
+
if t2_class == Types::PVariantType
|
275
277
|
# Assignable if all contained types are assignable
|
276
278
|
t2.types.all? { |vt| @@assignable_visitor.visit_this_1(self, t, vt) }
|
277
279
|
else
|
278
|
-
|
280
|
+
# Turn NotUndef[T] into T when T is not assignable from Undef
|
281
|
+
if t2_class == Types::PNotUndefType && !(t2.type.nil? || assignable?(t2.type, @nil_t))
|
282
|
+
assignable?(t, t2.type)
|
283
|
+
else
|
284
|
+
@@assignable_visitor.visit_this_1(self, t, t2)
|
285
|
+
end
|
279
286
|
end
|
280
287
|
end
|
281
288
|
|
@@ -353,10 +360,23 @@ class Puppet::Pops::Types::TypeCalculator
|
|
353
360
|
# do nothing, there is nothing to change for most types
|
354
361
|
end
|
355
362
|
|
363
|
+
# @return [Boolean] true if the given argument is contained in a struct element key
|
364
|
+
def is_struct_element_key?(o)
|
365
|
+
c = o.eContainer
|
366
|
+
if c.is_a?(Types::POptionalType)
|
367
|
+
o = c
|
368
|
+
c = c.eContainer
|
369
|
+
end
|
370
|
+
c.is_a?(Types::PStructElement) && c.key_type.equal?(o)
|
371
|
+
end
|
372
|
+
private :is_struct_element_key?
|
373
|
+
|
356
374
|
def generalize_PStringType(o)
|
357
|
-
|
358
|
-
o
|
359
|
-
|
375
|
+
# Skip generalization if the string is contained in a PStructElement key.
|
376
|
+
unless is_struct_element_key?(o)
|
377
|
+
o.values = []
|
378
|
+
o.size_type = nil
|
379
|
+
end
|
360
380
|
end
|
361
381
|
|
362
382
|
def generalize_PCollectionType(o)
|
@@ -433,8 +453,13 @@ class Puppet::Pops::Types::TypeCalculator
|
|
433
453
|
def instance_of_PStringType(t, o)
|
434
454
|
return false unless o.is_a?(String)
|
435
455
|
# true if size compliant
|
436
|
-
size_t = t.size_type
|
437
|
-
instance_of_PIntegerType(size_t, o.size)
|
456
|
+
size_t = t.size_type
|
457
|
+
if size_t.nil? || instance_of_PIntegerType(size_t, o.size)
|
458
|
+
values = t.values
|
459
|
+
values.empty? || values.include?(o)
|
460
|
+
else
|
461
|
+
false
|
462
|
+
end
|
438
463
|
end
|
439
464
|
|
440
465
|
def instance_of_PTupleType(t, o)
|
@@ -451,9 +476,18 @@ class Puppet::Pops::Types::TypeCalculator
|
|
451
476
|
|
452
477
|
def instance_of_PStructType(t, o)
|
453
478
|
return false unless o.is_a?(Hash)
|
454
|
-
|
455
|
-
|
456
|
-
|
479
|
+
matched = 0
|
480
|
+
t.elements.all? do |e|
|
481
|
+
key = e.name
|
482
|
+
v = o[key]
|
483
|
+
if v.nil? && !o.include?(key)
|
484
|
+
# Entry is missing. Only OK when key is optional
|
485
|
+
assignable?(e.key_type, @nil_t)
|
486
|
+
else
|
487
|
+
matched += 1
|
488
|
+
instance_of(e.value_type, v)
|
489
|
+
end
|
490
|
+
end && matched == o.size
|
457
491
|
end
|
458
492
|
|
459
493
|
def instance_of_PHashType(t, o)
|
@@ -470,6 +504,10 @@ class Puppet::Pops::Types::TypeCalculator
|
|
470
504
|
instance_of(@data_variant_t, o)
|
471
505
|
end
|
472
506
|
|
507
|
+
def instance_of_PNotUndefType(t, o)
|
508
|
+
!(o.nil? || o == :undef) && (t.type.nil? || instance_of(t.type, o))
|
509
|
+
end
|
510
|
+
|
473
511
|
def instance_of_PUndefType(t, o)
|
474
512
|
o.nil? || o == :undef
|
475
513
|
end
|
@@ -597,7 +635,8 @@ class Puppet::Pops::Types::TypeCalculator
|
|
597
635
|
|
598
636
|
if t1.is_a?(Types::PStringType) && t2.is_a?(Types::PStringType)
|
599
637
|
t = Types::PStringType.new()
|
600
|
-
t.values = t1.values | t2.values
|
638
|
+
t.values = t1.values | t2.values unless t1.values.empty? || t2.values.empty?
|
639
|
+
t.size_type = common_type(t1.size_type, t2.size_type) unless t1.size_type.nil? || t2.size_type.nil?
|
601
640
|
return t
|
602
641
|
end
|
603
642
|
|
@@ -919,27 +958,23 @@ class Puppet::Pops::Types::TypeCalculator
|
|
919
958
|
type.key_type = Types::PUndefType.new
|
920
959
|
type.element_type = Types::PUndefType.new
|
921
960
|
type.size_type = size_as_type(o)
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
type.key_type = unwrap_single_variant(ktype)
|
930
|
-
type.element_type = unwrap_single_variant(etype)
|
931
|
-
type.size_type = size_as_type(o)
|
932
|
-
else
|
933
|
-
elements = []
|
934
|
-
o.each_pair do |k,v|
|
935
|
-
element = Types::PStructElement.new
|
936
|
-
element.name = k
|
937
|
-
element.type = infer_set(v)
|
938
|
-
elements << element
|
939
|
-
end
|
940
|
-
type = Types::PStructType.new
|
941
|
-
type.elements = elements
|
961
|
+
elsif o.keys.all? {|k| instance_of_PStringType(@non_empty_string_t, k) }
|
962
|
+
type = Types::PStructType.new
|
963
|
+
type.elements = o.map do |k,v|
|
964
|
+
element = Types::PStructElement.new
|
965
|
+
element.key_type = infer_String(k)
|
966
|
+
element.value_type = infer_set(v)
|
967
|
+
element
|
942
968
|
end
|
969
|
+
else
|
970
|
+
type = Types::PHashType.new
|
971
|
+
ktype = Types::PVariantType.new
|
972
|
+
ktype.types = o.keys.map {|k| infer_set(k) }
|
973
|
+
etype = Types::PVariantType.new
|
974
|
+
etype.types = o.values.map {|e| infer_set(e) }
|
975
|
+
type.key_type = unwrap_single_variant(ktype)
|
976
|
+
type.element_type = unwrap_single_variant(etype)
|
977
|
+
type.size_type = size_as_type(o)
|
943
978
|
end
|
944
979
|
type
|
945
980
|
end
|
@@ -963,6 +998,11 @@ class Puppet::Pops::Types::TypeCalculator
|
|
963
998
|
t2.is_a?(Types::PAnyType)
|
964
999
|
end
|
965
1000
|
|
1001
|
+
# @api private
|
1002
|
+
def assignable_PNotUndefType(t, t2)
|
1003
|
+
!assignable?(t2, @nil_t) && (t.type.nil? || assignable?(t.type, t2))
|
1004
|
+
end
|
1005
|
+
|
966
1006
|
# @api private
|
967
1007
|
def assignable_PUndefType(t, t2)
|
968
1008
|
# Only undef/nil is assignable to nil type
|
@@ -1103,6 +1143,17 @@ class Puppet::Pops::Types::TypeCalculator
|
|
1103
1143
|
end
|
1104
1144
|
end
|
1105
1145
|
|
1146
|
+
# @api private
|
1147
|
+
def self.is_kind_of_optional?(t, optional = true)
|
1148
|
+
case t
|
1149
|
+
when Types::POptionalType
|
1150
|
+
true
|
1151
|
+
when Types::PVariantType
|
1152
|
+
t.types.all? {|t2| is_kind_of_optional?(t2, optional) }
|
1153
|
+
else
|
1154
|
+
false
|
1155
|
+
end
|
1156
|
+
end
|
1106
1157
|
|
1107
1158
|
def callable_PArrayType(args_array, callable_t)
|
1108
1159
|
return false unless assignable?(callable_t.param_types, args_array)
|
@@ -1186,22 +1237,34 @@ class Puppet::Pops::Types::TypeCalculator
|
|
1186
1237
|
#
|
1187
1238
|
def assignable_PStructType(t, t2)
|
1188
1239
|
if t2.is_a?(Types::PStructType)
|
1189
|
-
h = t.hashed_elements
|
1190
1240
|
h2 = t2.hashed_elements
|
1191
|
-
|
1241
|
+
matched = 0
|
1242
|
+
t.elements.all? do |e1|
|
1243
|
+
e2 = h2[e1.name]
|
1244
|
+
if e2.nil?
|
1245
|
+
assignable?(e1.key_type, @nil_t)
|
1246
|
+
else
|
1247
|
+
matched += 1
|
1248
|
+
assignable?(e1.key_type, e2.key_type) && assignable?(e1.value_type, e2.value_type)
|
1249
|
+
end
|
1250
|
+
end && matched == h2.size
|
1192
1251
|
elsif t2.is_a?(Types::PHashType)
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1252
|
+
required = 0
|
1253
|
+
required_elements_assignable = t.elements.all? do |e|
|
1254
|
+
if assignable?(e.key_type, @nil_t)
|
1255
|
+
true
|
1256
|
+
else
|
1257
|
+
required += 1
|
1258
|
+
assignable?(e.value_type, t2.element_type)
|
1259
|
+
end
|
1260
|
+
end
|
1261
|
+
if required_elements_assignable
|
1262
|
+
size_t2 = t2.size_type || @collection_default_size_t
|
1263
|
+
size_t = Types::PIntegerType.new
|
1264
|
+
size_t.from = required
|
1265
|
+
size_t.to = t.elements.size
|
1266
|
+
assignable_PIntegerType(size_t, size_t2)
|
1267
|
+
end
|
1205
1268
|
else
|
1206
1269
|
false
|
1207
1270
|
end
|
@@ -1210,8 +1273,9 @@ class Puppet::Pops::Types::TypeCalculator
|
|
1210
1273
|
# @api private
|
1211
1274
|
def assignable_POptionalType(t, t2)
|
1212
1275
|
return true if t2.is_a?(Types::PUndefType)
|
1276
|
+
return true if t.optional_type.nil?
|
1213
1277
|
if t2.is_a?(Types::POptionalType)
|
1214
|
-
assignable?(t.optional_type, t2.optional_type)
|
1278
|
+
assignable?(t.optional_type, t2.optional_type || @t)
|
1215
1279
|
else
|
1216
1280
|
assignable?(t.optional_type, t2)
|
1217
1281
|
end
|
@@ -1381,11 +1445,11 @@ class Puppet::Pops::Types::TypeCalculator
|
|
1381
1445
|
# @api private
|
1382
1446
|
def assignable_PArrayType(t, t2)
|
1383
1447
|
if t2.is_a?(Types::PArrayType)
|
1384
|
-
return false unless assignable?(t.element_type, t2.element_type)
|
1448
|
+
return false unless t.element_type.nil? || assignable?(t.element_type, t2.element_type || @t)
|
1385
1449
|
assignable_PCollectionType(t, t2)
|
1386
1450
|
|
1387
1451
|
elsif t2.is_a?(Types::PTupleType)
|
1388
|
-
return false unless t2.types.all? {|t2_element| assignable?(t.element_type, t2_element) }
|
1452
|
+
return false unless t.element_type.nil? || t2.types.all? {|t2_element| assignable?(t.element_type, t2_element) }
|
1389
1453
|
t2_regular = t2.types[0..-2]
|
1390
1454
|
t2_ranged = t2.types[-1]
|
1391
1455
|
t2_from, t2_to = size_range(t2.size_type)
|
@@ -1423,7 +1487,8 @@ class Puppet::Pops::Types::TypeCalculator
|
|
1423
1487
|
case t2
|
1424
1488
|
when Types::PHashType
|
1425
1489
|
return true if (t.size_type.nil? || t.size_type.from == 0) && t2.is_the_empty_hash?
|
1426
|
-
return false unless
|
1490
|
+
return false unless t.key_type.nil? || assignable?(t.key_type, t2.key_type || @t)
|
1491
|
+
return false unless t.element_type.nil? || assignable?(t.element_type, t2.element_type || @t)
|
1427
1492
|
assignable_PCollectionType(t, t2)
|
1428
1493
|
when Types::PStructType
|
1429
1494
|
# hash must accept String as key type
|
@@ -1435,7 +1500,7 @@ class Puppet::Pops::Types::TypeCalculator
|
|
1435
1500
|
key_type = t.key_type
|
1436
1501
|
element_type = t.element_type
|
1437
1502
|
( struct_size >= min && struct_size <= max &&
|
1438
|
-
t2.elements.all? {|e| instance_of(key_type, e.name) && assignable?(element_type, e.
|
1503
|
+
t2.elements.all? {|e| (key_type.nil? || instance_of(key_type, e.name)) && (element_type.nil? || assignable?(element_type, e.value_type)) })
|
1439
1504
|
else
|
1440
1505
|
false
|
1441
1506
|
end
|
@@ -1467,7 +1532,15 @@ class Puppet::Pops::Types::TypeCalculator
|
|
1467
1532
|
# Data is assignable by other Data and by Array[Data] and Hash[Scalar, Data]
|
1468
1533
|
# @api private
|
1469
1534
|
def assignable_PDataType(t, t2)
|
1470
|
-
|
1535
|
+
# We cannot put the NotUndefType[Data] in the @data_variant_t since that causes an endless recursion
|
1536
|
+
case t2
|
1537
|
+
when Types::PDataType
|
1538
|
+
true
|
1539
|
+
when Types::PNotUndefType
|
1540
|
+
assignable?(t, t2.type || @t)
|
1541
|
+
else
|
1542
|
+
assignable?(@data_variant_t, t2)
|
1543
|
+
end
|
1471
1544
|
end
|
1472
1545
|
|
1473
1546
|
# Assignable if t2's has the same runtime and the runtime name resolves to
|
@@ -1638,7 +1711,16 @@ class Puppet::Pops::Types::TypeCalculator
|
|
1638
1711
|
end
|
1639
1712
|
|
1640
1713
|
def string_PStructElement(t)
|
1641
|
-
|
1714
|
+
k = t.key_type
|
1715
|
+
value_optional = assignable?(t.value_type, @nil_t)
|
1716
|
+
key_string =
|
1717
|
+
if k.is_a?(Types::POptionalType)
|
1718
|
+
# Output as literal String
|
1719
|
+
value_optional ? "'#{t.name}'" : string(k)
|
1720
|
+
else
|
1721
|
+
value_optional ? "NotUndef['#{t.name}']" : "'#{t.name}'"
|
1722
|
+
end
|
1723
|
+
"#{key_string}=>#{string(t.value_type)}"
|
1642
1724
|
end
|
1643
1725
|
|
1644
1726
|
# @api private
|
@@ -1704,11 +1786,30 @@ class Puppet::Pops::Types::TypeCalculator
|
|
1704
1786
|
end
|
1705
1787
|
end
|
1706
1788
|
|
1789
|
+
# @api private
|
1790
|
+
def string_PNotUndefType(t)
|
1791
|
+
contained_type = t.type
|
1792
|
+
if contained_type.nil? || contained_type.class == Puppet::Pops::Types::PAnyType
|
1793
|
+
'NotUndef'
|
1794
|
+
else
|
1795
|
+
if contained_type.is_a?(Puppet::Pops::Types::PStringType) && contained_type.values.size == 1
|
1796
|
+
"NotUndef['#{contained_type.values[0]}']"
|
1797
|
+
else
|
1798
|
+
"NotUndef[#{string(contained_type)}]"
|
1799
|
+
end
|
1800
|
+
end
|
1801
|
+
end
|
1802
|
+
|
1707
1803
|
def string_POptionalType(t)
|
1708
|
-
|
1804
|
+
optional_type = t.optional_type
|
1805
|
+
if optional_type.nil?
|
1709
1806
|
"Optional"
|
1710
1807
|
else
|
1711
|
-
|
1808
|
+
if optional_type.is_a?(Puppet::Pops::Types::PStringType) && optional_type.values.size == 1
|
1809
|
+
"Optional['#{optional_type.values[0]}']"
|
1810
|
+
else
|
1811
|
+
"Optional[#{string(optional_type)}]"
|
1812
|
+
end
|
1712
1813
|
end
|
1713
1814
|
end
|
1714
1815
|
|
@@ -2,9 +2,9 @@
|
|
2
2
|
# @api public
|
3
3
|
#
|
4
4
|
module Puppet::Pops::Types::TypeFactory
|
5
|
-
@type_calculator = Puppet::Pops::Types::TypeCalculator.new()
|
6
|
-
|
7
5
|
Types = Puppet::Pops::Types
|
6
|
+
@type_calculator = Types::TypeCalculator.singleton
|
7
|
+
@undef_t = Types::PUndefType.new
|
8
8
|
|
9
9
|
# Produces the Integer type
|
10
10
|
# @api public
|
@@ -66,9 +66,17 @@ module Puppet::Pops::Types::TypeFactory
|
|
66
66
|
end
|
67
67
|
|
68
68
|
# Produces the Optional type, i.e. a short hand for Variant[T, Undef]
|
69
|
+
# If the given 'optional_type' argument is a String, then it will be
|
70
|
+
# converted into a String type that represents that string.
|
71
|
+
#
|
72
|
+
# @param optional_type [String,PAnyType,nil] the optional type
|
73
|
+
# @return [POptionalType] the created type
|
74
|
+
#
|
75
|
+
# @api public
|
76
|
+
#
|
69
77
|
def self.optional(optional_type = nil)
|
70
78
|
t = Types::POptionalType.new
|
71
|
-
t.optional_type = type_of(optional_type)
|
79
|
+
t.optional_type = optional_type.is_a?(String) ? string(optional_type) : type_of(optional_type)
|
72
80
|
t
|
73
81
|
end
|
74
82
|
|
@@ -91,19 +99,48 @@ module Puppet::Pops::Types::TypeFactory
|
|
91
99
|
end
|
92
100
|
|
93
101
|
# Produces the Struct type, either a non parameterized instance representing
|
94
|
-
# all structs (i.e. all hashes) or a hash with
|
95
|
-
#
|
96
|
-
#
|
102
|
+
# all structs (i.e. all hashes) or a hash with entries where the key is
|
103
|
+
# either a literal String, an Enum with one entry, or a String representing exactly one value.
|
104
|
+
# The key type may also be wrapped in a NotUndef or an Optional.
|
97
105
|
#
|
98
|
-
|
106
|
+
# The value can be a ruby class, a String (interpreted as the name of a ruby class) or
|
107
|
+
# a Type.
|
108
|
+
#
|
109
|
+
# @param hash [Hash<Object, Object>] key => value hash
|
110
|
+
# @return [PStructType] the created Struct type
|
111
|
+
#
|
112
|
+
def self.struct(hash = {})
|
113
|
+
tc = @type_calculator
|
99
114
|
t = Types::PStructType.new
|
100
|
-
t.elements =
|
101
|
-
|
102
|
-
|
103
|
-
|
115
|
+
t.elements = hash.map do |key_type, value_type|
|
116
|
+
value_type = type_of(value_type)
|
117
|
+
raise ArgumentError, 'Struct element value_type must be a Type' unless value_type.is_a?(Types::PAnyType)
|
118
|
+
|
119
|
+
# TODO: Should have stricter name rule
|
120
|
+
if key_type.is_a?(String)
|
121
|
+
raise ArgumentError, 'Struct element key cannot be an empty String' if key_type.empty?
|
122
|
+
key_type = string(key_type)
|
123
|
+
# Must make key optional if the value can be Undef
|
124
|
+
key_type = optional(key_type) if tc.assignable?(value_type, @undef_t)
|
125
|
+
else
|
126
|
+
# assert that the key type is one of String[1], NotUndef[String[1]] and Optional[String[1]]
|
127
|
+
case key_type
|
128
|
+
when Types::PNotUndefType
|
129
|
+
# We can loose the NotUndef wrapper here since String[1] isn't optional anyway
|
130
|
+
key_type = key_type.type
|
131
|
+
s = key_type
|
132
|
+
when Types::POptionalType
|
133
|
+
s = key_type.optional_type
|
134
|
+
else
|
135
|
+
s = key_type
|
136
|
+
end
|
137
|
+
unless (s.is_a?(Puppet::Pops::Types::PStringType) || s.is_a?(Puppet::Pops::Types::PEnumType)) && s.values.size == 1 && !s.values[0].empty?
|
138
|
+
raise ArgumentError, 'Unable to extract a non-empty literal string from Struct member key type' if key_type.empty?
|
139
|
+
end
|
104
140
|
end
|
105
|
-
elem
|
106
|
-
elem.
|
141
|
+
elem = Types::PStructElement.new
|
142
|
+
elem.key_type = key_type
|
143
|
+
elem.value_type = value_type
|
107
144
|
elem
|
108
145
|
end
|
109
146
|
t
|
@@ -351,6 +388,22 @@ module Puppet::Pops::Types::TypeFactory
|
|
351
388
|
type
|
352
389
|
end
|
353
390
|
|
391
|
+
# Produces a type for NotUndef[T]
|
392
|
+
# The given 'inst_type' can be a string in which case it will be converted into
|
393
|
+
# the type String[inst_type].
|
394
|
+
#
|
395
|
+
# @param inst_type [Type,String] the type to qualify
|
396
|
+
# @return [Puppet::Pops::Types::PNotUndefType] the NotUndef type
|
397
|
+
#
|
398
|
+
# @api public
|
399
|
+
#
|
400
|
+
def self.not_undef(inst_type = nil)
|
401
|
+
type = Types::PNotUndefType.new()
|
402
|
+
inst_type = string(inst_type) if inst_type.is_a?(String)
|
403
|
+
type.type = inst_type
|
404
|
+
type
|
405
|
+
end
|
406
|
+
|
354
407
|
# Produces a type for Type[T]
|
355
408
|
# @api public
|
356
409
|
#
|