Skip to content

Commit

Permalink
(PUP-6694) Add RichData type
Browse files Browse the repository at this point in the history
This commit adds `RichData` and `RichDataKey` to the list of built-in type
aliases. It also moves the `Puppet::LookupValue` and `Puppet::LookupKey`
to this list and makes `Puppet::LookupValue` an alias for `RichData` and
`Puppet::LookupKey` an alias for `RichDataKey`.
  • Loading branch information
thallgren committed Apr 27, 2017
1 parent b0231ea commit 0a195ef
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 27 deletions.
12 changes: 9 additions & 3 deletions lib/puppet/pops/loader/static_loader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,20 @@ class StaticLoader < Loader
BUILTIN_TYPE_NAMES_LC = Set.new(BUILTIN_TYPE_NAMES.map { |n| n.downcase }).freeze

BUILTIN_ALIASES = {
'Data' => 'Variant[ScalarData,Undef,Hash[String,Data],Array[Data]]'
'Data' => 'Variant[ScalarData,Undef,Hash[String,Data],Array[Data]]',
'RichDataKey' => 'Variant[String,Numeric]',
'RichData' => 'Variant[Scalar,SemVerRange,Binary,Sensitive,Type,TypeSet,Undef,Hash[RichDataKey,RichData],Array[RichData]]',

# Backward compatible aliases.
'Puppet::LookupKey' => 'RichDataKey',
'Puppet::LookupValue' => 'RichData'
}.freeze

attr_reader :loaded
def initialize
@loaded = {}
create_built_in_types()
create_resource_type_references()
create_built_in_types
create_resource_type_references
register_aliases
end

Expand Down
21 changes: 3 additions & 18 deletions lib/puppet/pops/lookup/data_provider.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,9 @@ def self.value_type
end

def self.register_types(loader)
(@key_type, @value_type) = Pcore::register_aliases({
# The Pcore type for all keys and subkeys in a data hash.
'Puppet::LookupKey' => 'Variant[String,Numeric]',

# The Pcore type for all values and sub-values in a data hash. The
# type is self-recursive to enforce the same constraint on values contained
# in arrays and hashes
'Puppet::LookupValue' => <<-PUPPET
Variant[
Scalar,
Undef,
Sensitive,
Type,
Hash[Puppet::LookupKey, Puppet::LookupValue],
Array[Puppet::LookupValue]
]
PUPPET
}, Pcore::RUNTIME_NAME_AUTHORITY, loader)
tp = Types::TypeParser.singleton
@key_type = tp.parse('RichDataKey', loader)
@value_type = tp.parse('RichData', loader)
end

# Performs a lookup with an endless recursion check.
Expand Down
9 changes: 9 additions & 0 deletions lib/puppet/pops/types/type_calculator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,10 @@ def common_type(t1, t2)
return PType.new(common_type(t1.type, t2.type))
end

if common_rich_data?(t1,t2)
return TypeFactory.rich_data
end

# If both are Runtime types
if t1.is_a?(PRuntimeType) && t2.is_a?(PRuntimeType)
if t1.runtime == t2.runtime && t1.runtime_type_name == t2.runtime_type_name
Expand Down Expand Up @@ -760,6 +764,11 @@ def to_s

private

def common_rich_data?(t1, t2)
d = TypeFactory.rich_data
d.assignable?(t1) && d.assignable?(t2)
end

def common_data?(t1, t2)
d = TypeFactory.data
d.assignable?(t1) && d.assignable?(t2)
Expand Down
7 changes: 7 additions & 0 deletions lib/puppet/pops/types/type_factory.rb
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,13 @@ def self.data
@data_t ||= TypeParser.singleton.parse('Data', Loaders.static_loader)
end

# Produces the RichData type
# @api public
#
def self.rich_data
@rich_data_t ||= TypeParser.singleton.parse('RichData', Loaders.static_loader)
end

# Creates an instance of the Undef type
# @api public
def self.undef
Expand Down
2 changes: 1 addition & 1 deletion spec/unit/functions/lookup_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2513,7 +2513,7 @@ def lookup(key, scope, order_override, resolution_type, context)

it 'fails and reports error' do
expect{lookup('mod_a::a')}.to raise_error(
"Return type of 'lookup_key' function named 'mod_a::pp_lookup_key' is incorrect, expects a value of type Undef, Scalar, Sensitive, Type, Hash, or Array, got Runtime")
"Return type of 'lookup_key' function named 'mod_a::pp_lookup_key' is incorrect, expects a RichData value, got Runtime")
end
end
end
Expand Down
26 changes: 21 additions & 5 deletions spec/unit/pops/types/type_calculator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -293,23 +293,23 @@ def types
expect(t.values).to eq(['a', 'b', 'c'])
end

it 'with fixnum and float values translates to PArrayType[PNumericType]' do
it 'with integer and float values translates to PArrayType[PNumericType]' do
expect(calculator.infer([1,2.0]).element_type.class).to eq(PNumericType)
end

it 'with fixnum and string values translates to PArrayType[PScalarDataType]' do
it 'with integer and string values translates to PArrayType[PScalarDataType]' do
expect(calculator.infer([1,'two']).element_type.class).to eq(PScalarDataType)
end

it 'with float and string values translates to PArrayType[PScalarDataType]' do
expect(calculator.infer([1.0,'two']).element_type.class).to eq(PScalarDataType)
end

it 'with fixnum, float, and string values translates to PArrayType[PScalarDataType]' do
it 'with integer, float, and string values translates to PArrayType[PScalarDataType]' do
expect(calculator.infer([1, 2.0,'two']).element_type.class).to eq(PScalarDataType)
end

it 'with fixnum and regexp values translates to PArrayType[PScalarType]' do
it 'with integer and regexp values translates to PArrayType[PScalarType]' do
expect(calculator.infer([1, /two/]).element_type.class).to eq(PScalarType)
end

Expand All @@ -321,10 +321,26 @@ def types
expect(calculator.infer(['one', :two]).element_type.class).to eq(PAnyType)
end

it 'with fixnum and nil values translates to PArrayType[PIntegerType]' do
it 'with integer and nil values translates to PArrayType[PIntegerType]' do
expect(calculator.infer([1, nil]).element_type.class).to eq(PIntegerType)
end

it 'with integer value, and array of string values, translates to Array[Data]' do
expect(calculator.infer([1, ['two']]).element_type.name).to eq('Data')
end

it 'with integer value, and hash of string => string values, translates to Array[Data]' do
expect(calculator.infer([1, {'two' => 'three'} ]).element_type.name).to eq('Data')
end

it 'with integer value, and hash of integer => string values, translates to Array[RichData]' do
expect(calculator.infer([1, {2 => 'three'} ]).element_type.name).to eq('RichData')
end

it 'with integer, regexp, and binary values translates to Array[RichData]' do
expect(calculator.infer([1, /two/, PBinaryType::Binary.from_string('three')]).element_type.name).to eq('RichData')
end

it 'with arrays of string values translates to PArrayType[PArrayType[PStringType]]' do
et = calculator.infer([['first', 'array'], ['second','array']])
expect(et.class).to eq(PArrayType)
Expand Down

0 comments on commit 0a195ef

Please sign in to comment.