Last active
May 13, 2020 04:16
-
-
Save justinstoller/89fe0c392e4c5d7940b2ad9a6f3867dc to your computer and use it in GitHub Desktop.
Potential 2018.1 patches to aid JRuby 1.7 vs 9k performance disparity
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Steps are to: | |
# 1. Use `wget` to download the raw content of one of the two included changesets | |
# 2. Use `patch` to install | |
# | |
# Patches can be optionally reverted with `patch` by adding the `--reverse` flag | |
# The two patches in this gist are mutually exclusive (full-changeset.patch is a superset of the unasserted-iterables.patch). | |
# The PR corresponding to the unasserted-iterables.patch is here: | |
# https://github.com/puppetlabs/puppet/pull/8150 | |
# The full-changeset.patch includes the above plus the contents of these PRs (as of 12 May): | |
# https://github.com/puppetlabs/puppet/pull/8151 | |
# https://github.com/puppetlabs/puppet/pull/8152 | |
# https://github.com/puppetlabs/puppet/pull/8154 | |
# https://github.com/puppetlabs/puppet/pull/8155 | |
# | |
$ wget https://gist.githubusercontent.com/justinstoller/89fe0c392e4c5d7940b2ad9a6f3867dc/raw/bd5ab68159b148ccd410bdcea754683c3e6cd029/full-changeset.patch | |
Resolving gist.githubusercontent.com (gist.githubusercontent.com)... 151.101.128.133, 151.101.192.133, 151.101.0.133, ... | |
Connecting to gist.githubusercontent.com (gist.githubusercontent.com)|151.101.128.133|:443... connected. | |
HTTP request sent, awaiting response... 200 OK | |
Length: 29405 (29K) [text/plain] | |
Saving to: ‘full-changeset.patch’ | |
100%[======================================================================================================================>] 29,405 --.-K/s in 0.004s | |
$ patch --backup --directory /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/ --strip 2 < full-changeset.patch | |
patching file puppet/functions/reverse_each.rb | |
patching file puppet/functions/step.rb | |
patching file puppet/node/environment.rb | |
patching file puppet/parser/functions.rb | |
patching file puppet/parser/resource.rb | |
patching file puppet/parser/resource/param.rb | |
patching file puppet/pops/adaptable.rb | |
patching file puppet/pops/adapters.rb | |
patching file puppet/pops/evaluator/evaluator_impl.rb | |
patching file puppet/pops/evaluator/runtime3_resource_support.rb | |
patching file puppet/pops/evaluator/runtime3_support.rb | |
patching file puppet/pops/model/ast.rb | |
patching file puppet/pops/types/iterable.rb | |
patching file puppet/pops/validation/checker4_0.rb | |
patching file puppet/resource.rb | |
patching file puppet/util/autoload.rb | |
$ systemctl restart pe-puppetserver | |
================================ | |
or | |
================================ | |
$ wget https://gist.githubusercontent.com/justinstoller/89fe0c392e4c5d7940b2ad9a6f3867dc/raw/93ee92c363f3e2f8fe9ff9d28553530c57b73a59/unasserted-iterables.patch | |
Resolving gist.githubusercontent.com (gist.githubusercontent.com)... 151.101.64.133, 151.101.128.133, 151.101.0.133, ... | |
Connecting to gist.githubusercontent.com (gist.githubusercontent.com)|151.101.64.133|:443... connected. | |
HTTP request sent, awaiting response... 200 OK | |
Length: 3515 (3.4K) [text/plain] | |
Saving to: ‘unasserted-iterables.patch’ | |
100%[======================================================================================================================>] 3,515 --.-K/s in 0s | |
$ patch --backup --directory /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/ --strip 2 < unasserted-iterables.patch | |
patching file puppet/functions/reverse_each.rb | |
patching file puppet/functions/step.rb | |
patching file puppet/pops/types/iterable.rb | |
$ systemctl restart pe-puppetserver | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/lib/puppet/functions/reverse_each.rb b/lib/puppet/functions/reverse_each.rb | |
index fb81a99..3b0c907 100644 | |
--- a/lib/puppet/functions/reverse_each.rb | |
+++ b/lib/puppet/functions/reverse_each.rb | |
@@ -84,7 +84,7 @@ Puppet::Functions.create_function(:reverse_each) do | |
def reverse_each(iterable) | |
# produces an Iterable | |
- Puppet::Pops::Types::Iterable.asserted_iterable(self, iterable).reverse_each | |
+ Puppet::Pops::Types::Iterable.asserted_iterable(self, iterable, true).reverse_each | |
end | |
def reverse_each_block(iterable, &block) | |
diff --git a/lib/puppet/functions/step.rb b/lib/puppet/functions/step.rb | |
index 8860149..d6e1ad1 100644 | |
--- a/lib/puppet/functions/step.rb | |
+++ b/lib/puppet/functions/step.rb | |
@@ -88,7 +88,7 @@ Puppet::Functions.create_function(:step) do | |
def step(iterable, step) | |
# produces an Iterable | |
- Puppet::Pops::Types::Iterable.asserted_iterable(self, iterable).step(step) | |
+ Puppet::Pops::Types::Iterable.asserted_iterable(self, iterable, true).step(step) | |
end | |
def step_block(iterable, step, &block) | |
diff --git a/lib/puppet/node/environment.rb b/lib/puppet/node/environment.rb | |
index d0e9238..745c99e 100644 | |
--- a/lib/puppet/node/environment.rb | |
+++ b/lib/puppet/node/environment.rb | |
@@ -285,7 +285,7 @@ class Puppet::Node::Environment | |
# @param name [String] The module name | |
# @return [Puppet::Module, nil] The module if found, else nil | |
def module(name) | |
- modules.find {|mod| mod.name == name} | |
+ modules_by_name[name] | |
end | |
# Locate a module instance by the full forge name (EG authorname/module) | |
@@ -340,6 +340,11 @@ class Puppet::Node::Environment | |
@modules | |
end | |
+ # @api private | |
+ def modules_by_name | |
+ @modules_by_name ||= Hash[modules.map { |mod| [mod.name, mod] }] | |
+ end | |
+ | |
# Generate a warning if the given directory in a module path entry is named `lib`. | |
# | |
# @api private | |
diff --git a/lib/puppet/parser/functions.rb b/lib/puppet/parser/functions.rb | |
index 6c695f5..804eb6a 100644 | |
--- a/lib/puppet/parser/functions.rb | |
+++ b/lib/puppet/parser/functions.rb | |
@@ -44,15 +44,10 @@ module Puppet::Parser::Functions | |
# @api private | |
class AnonymousModuleAdapter < Puppet::Pops::Adaptable::Adapter | |
attr_accessor :module | |
- end | |
- # Get the module that functions are mixed into corresponding to an | |
- # environment | |
- # | |
- # @api private | |
- def self.environment_module(env) | |
- AnonymousModuleAdapter.adapt(env) do |a| | |
- a.module ||= Module.new do | |
+ def self.create_adapter(o) | |
+ a = super(o) | |
+ a.module = Module.new do | |
@metadata = {} | |
def self.all_function_info | |
@@ -67,7 +62,16 @@ module Puppet::Parser::Functions | |
@metadata[name] = info | |
end | |
end | |
- end.module | |
+ a | |
+ end | |
+ end | |
+ | |
+ # Get the module that functions are mixed into corresponding to an | |
+ # environment | |
+ # | |
+ # @api private | |
+ def self.environment_module(env) | |
+ AnonymousModuleAdapter.adapt(env).module | |
end | |
# Create a new Puppet DSL function. | |
diff --git a/lib/puppet/parser/resource.rb b/lib/puppet/parser/resource.rb | |
index 6f29de2..3bb7e73 100644 | |
--- a/lib/puppet/parser/resource.rb | |
+++ b/lib/puppet/parser/resource.rb | |
@@ -14,7 +14,6 @@ class Puppet::Parser::Resource < Puppet::Resource | |
attr_accessor :source, :scope, :collector_id | |
attr_accessor :virtual, :override, :translated, :catalog, :evaluated | |
- attr_accessor :file, :line | |
attr_reader :exported, :parameters | |
diff --git a/lib/puppet/parser/resource/param.rb b/lib/puppet/parser/resource/param.rb | |
index 3f55581..6aacb84 100644 | |
--- a/lib/puppet/parser/resource/param.rb | |
+++ b/lib/puppet/parser/resource/param.rb | |
@@ -4,7 +4,7 @@ class Puppet::Parser::Resource::Param | |
include Puppet::Util::Errors | |
include Puppet::Util::MethodHelper | |
- attr_accessor :name, :value, :source, :add, :file, :line | |
+ attr_accessor :name, :value, :source, :add, :ast_node | |
def initialize(hash) | |
set_options(hash) | |
@@ -12,6 +12,22 @@ class Puppet::Parser::Resource::Param | |
@name = @name.intern | |
end | |
+ def line | |
+ @line ||= @ast_node && @ast_node.line | |
+ end | |
+ | |
+ def line=(lineno) | |
+ @line = lineno | |
+ end | |
+ | |
+ def file | |
+ @file ||= @ast_node && @ast_node.file | |
+ end | |
+ | |
+ def file=(filepath) | |
+ @file = filepath | |
+ end | |
+ | |
def line_to_i | |
line ? Integer(line) : nil | |
end | |
diff --git a/lib/puppet/pops/adaptable.rb b/lib/puppet/pops/adaptable.rb | |
index 3072d54..a11c89a 100644 | |
--- a/lib/puppet/pops/adaptable.rb | |
+++ b/lib/puppet/pops/adaptable.rb | |
@@ -69,11 +69,7 @@ module Adaptable | |
# | |
def self.get(o) | |
attr_name = self_attr_name | |
- if o.instance_variable_defined?(attr_name) | |
- o.instance_variable_get(attr_name) | |
- else | |
- nil | |
- end | |
+ o.instance_variable_get(attr_name) | |
end | |
# Returns an existing adapter for the given object, or creates a new adapter if the | |
@@ -94,17 +90,16 @@ module Adaptable | |
# | |
def self.adapt(o, &block) | |
attr_name = self_attr_name | |
- adapter = if o.instance_variable_defined?(attr_name) && value = o.instance_variable_get(attr_name) | |
+ adapter = if value = o.instance_variable_get(attr_name) | |
value | |
else | |
associate_adapter(create_adapter(o), o) | |
end | |
if block_given? | |
- case block.arity | |
- when 1 | |
- block.call(adapter) | |
- else | |
- block.call(adapter, o) | |
+ if block.arity == 1 | |
+ block.call(adapter) | |
+ else | |
+ block.call(adapter, o) | |
end | |
end | |
adapter | |
@@ -130,8 +125,7 @@ module Adaptable | |
def self.adapt_new(o, &block) | |
adapter = associate_adapter(create_adapter(o), o) | |
if block_given? | |
- case block.arity | |
- when 1 | |
+ if block.arity == 1 | |
block.call(adapter) | |
else | |
block.call(adapter, o) | |
diff --git a/lib/puppet/pops/adapters.rb b/lib/puppet/pops/adapters.rb | |
index 3e6d20c..aba4ab2 100644 | |
--- a/lib/puppet/pops/adapters.rb | |
+++ b/lib/puppet/pops/adapters.rb | |
@@ -85,6 +85,13 @@ module Adapters | |
class PathsAndNameCacheAdapter < Puppet::Pops::Adaptable::Adapter | |
attr_accessor :cache, :paths | |
+ | |
+ def self.create_adapter(env) | |
+ a = super(env) | |
+ a.paths = env.modulepath.map { |p| Pathname.new(p) } | |
+ a.cache = {} | |
+ a | |
+ end | |
end | |
# Attempts to find the module that `instance` originates from by looking at it's {SourcePosAdapter} and | |
@@ -103,10 +110,7 @@ module Adapters | |
def self.loader_name_by_source(environment, instance, file) | |
file = instance.file if file.nil? | |
return nil if file.nil? || EMPTY_STRING == file | |
- pn_adapter = PathsAndNameCacheAdapter.adapt(environment) do |a| | |
- a.paths ||= environment.modulepath.map { |p| Pathname.new(p) } | |
- a.cache ||= {} | |
- end | |
+ pn_adapter = PathsAndNameCacheAdapter.adapt(environment) | |
dir = File.dirname(file) | |
pn_adapter.cache.fetch(dir) do |key| | |
mod = find_module_for_dir(environment, pn_adapter.paths, dir) | |
@@ -128,7 +132,7 @@ module Adapters | |
end | |
if relative_path.length > 1 | |
mod = environment.module(relative_path[0]) | |
- return mod unless mod.nil? | |
+ return mod | |
end | |
end | |
nil | |
diff --git a/lib/puppet/pops/evaluator/evaluator_impl.rb b/lib/puppet/pops/evaluator/evaluator_impl.rb | |
index c154ba1..9bb9282 100644 | |
--- a/lib/puppet/pops/evaluator/evaluator_impl.rb | |
+++ b/lib/puppet/pops/evaluator/evaluator_impl.rb | |
@@ -50,9 +50,6 @@ class EvaluatorImpl | |
# @api private | |
def static_initialize | |
@@eval_visitor ||= Visitor.new(self, "eval", 1, 1) | |
- @@lvalue_visitor ||= Visitor.new(self, "lvalue", 1, 1) | |
- @@assign_visitor ||= Visitor.new(self, "assign", 3, 3) | |
- @@string_visitor ||= Visitor.new(self, "string", 1, 1) | |
@@type_calculator ||= Types::TypeCalculator.singleton | |
@@ -137,7 +134,15 @@ class EvaluatorImpl | |
# @api private | |
# | |
def assign(target, value, o, scope) | |
- @@assign_visitor.visit_this_3(self, target, value, o, scope) | |
+ if target.is_a?(String) | |
+ assign_String(target, value, o, scope) | |
+ elsif target.is_a?(Array) | |
+ assign_Array(target, value, o, scope) | |
+ elsif target.is_a?(Numeric) | |
+ fail(Issues::ILLEGAL_NUMERIC_ASSIGNMENT, o.left_expr, {:varname => n.to_s}) | |
+ else | |
+ fail(Issues::ILLEGAL_ASSIGNMENT, o) | |
+ end | |
end | |
# Computes a value that can be used as the LHS in an assignment. | |
@@ -147,7 +152,17 @@ class EvaluatorImpl | |
# @api private | |
# | |
def lvalue(o, scope) | |
- @@lvalue_visitor.visit_this_1(self, o, scope) | |
+ if o.is_a?(Model::VariableExpression) | |
+ if o.expr.instance_of?(Model::QualifiedName) | |
+ o.expr.value | |
+ else | |
+ evaluate(o.expr, scope) | |
+ end | |
+ elsif o.is_a?(Model::LiteralList) | |
+ o.values.map {|x| lvalue(x, scope) } | |
+ else | |
+ fail(Issues::ILLEGAL_ASSIGNMENT, o) | |
+ end | |
end | |
# Produces a String representation of the given object _o_ as used in interpolation. | |
@@ -157,9 +172,26 @@ class EvaluatorImpl | |
# @api public | |
# | |
def string(o, scope) | |
- @@string_visitor.visit_this_1(self, o, scope) | |
+ if o.instance_of?(String) | |
+ o | |
+ elsif o.instance_of?(Symbol) | |
+ if :undef == o # optimized comparison 1.44 vs 1.95 | |
+ EMPTY_STRING | |
+ else | |
+ o.to_s | |
+ end | |
+ elsif o.instance_of?(Regexp) | |
+ Types::PRegexpType.regexp_to_s_with_delimiters(o) | |
+ elsif o.instance_of?(Array) | |
+ "[#{o.map {|e| string(e, scope)}.join(COMMA_SEPARATOR)}]" | |
+ elsif o.instance_of?(Hash) | |
+ "{#{o.map {|k,v| "#{string(k, scope)} => #{string(v, scope)}"}.join(COMMA_SEPARATOR)}}" | |
+ else | |
+ o.to_s | |
+ end | |
end | |
+ | |
# Evaluate a BlockExpression in a new scope with variables bound to the | |
# given values. | |
# | |
@@ -189,22 +221,6 @@ class EvaluatorImpl | |
protected | |
- def lvalue_VariableExpression(o, scope) | |
- # evaluate the name | |
- evaluate(o.expr, scope) | |
- end | |
- | |
- # Catches all illegal lvalues | |
- # | |
- def lvalue_Object(o, scope) | |
- fail(Issues::ILLEGAL_ASSIGNMENT, o) | |
- end | |
- | |
- # An array is assignable if all entries are lvalues | |
- def lvalue_LiteralList(o, scope) | |
- o.values.map {|x| lvalue(x, scope) } | |
- end | |
- | |
# Assign value to named variable. | |
# The '$' sign is never part of the name. | |
# @example In Puppet DSL | |
@@ -223,16 +239,6 @@ class EvaluatorImpl | |
value | |
end | |
- def assign_Numeric(n, value, o, scope) | |
- fail(Issues::ILLEGAL_NUMERIC_ASSIGNMENT, o.left_expr, {:varname => n.to_s}) | |
- end | |
- | |
- # Catches all illegal assignment (e.g. 1 = 2, {'a'=>1} = 2, etc) | |
- # | |
- def assign_Object(name, value, o, scope) | |
- fail(Issues::ILLEGAL_ASSIGNMENT, o) | |
- end | |
- | |
def assign_Array(lvalues, values, o, scope) | |
if values.is_a?(Hash) | |
lvalues.map do |lval| | |
@@ -842,7 +848,11 @@ class EvaluatorImpl | |
# Store evaluated parameters in a hash associated with the body, but do not yet create resource | |
# since the entry containing :defaults may appear later | |
body_to_params[body] = body.operations.reduce({}) do |param_memo, op| | |
- params = evaluate(op, scope) | |
+ params = if op.instance_of?(Model::AttributeOperation) | |
+ eval_AttributeOperation(op, scope) | |
+ else | |
+ evaluate(op, scope) | |
+ end | |
params = [params] unless params.is_a?(Array) | |
params.each do |p| | |
if param_memo.include? p.name | |
@@ -875,7 +885,18 @@ class EvaluatorImpl | |
# Produces 3x parameter | |
def eval_AttributeOperation(o, scope) | |
- create_resource_parameter(o, scope, o.attribute_name, evaluate(o.value_expr, scope), o.operator) | |
+ value_expr = o.value_expr | |
+ value = if value_expr.instance_of?(Model::VariableExpression) | |
+ eval_VariableExpression(value_expr, scope) | |
+ elsif value_expr.instance_of?(Model::LiteralString) | |
+ value_expr.value | |
+ elsif value_expr.instance_of?(Model::ConcatenatedString) | |
+ eval_ConcatenatedString(value_expr, scope) | |
+ else | |
+ evaluate(value_expr, scope) | |
+ end | |
+ | |
+ create_resource_parameter(o, scope, o.attribute_name, value, o.operator) | |
end | |
def eval_AttributesOperation(o, scope) | |
@@ -1051,7 +1072,11 @@ class EvaluatorImpl | |
# Evaluator is not too fussy about what constitutes a name as long as the result | |
# is a String and a valid variable name | |
# | |
- name = evaluate(o.expr, scope) | |
+ name = if o.expr.instance_of?(Model::QualifiedName) | |
+ o.expr.value | |
+ else | |
+ evaluate(o.expr, scope) | |
+ end | |
# Should be caught by validation, but make this explicit here as well, or mysterious evaluation issues | |
# may occur for some evaluation use cases. | |
@@ -1067,7 +1092,17 @@ class EvaluatorImpl | |
# Evaluates double quoted strings that may contain interpolation | |
# | |
def eval_ConcatenatedString o, scope | |
- o.segments.collect {|expr| string(evaluate(expr, scope), scope)}.join | |
+ o.segments.collect do |expr| | |
+ string( | |
+ if expr.instance_of?(Model::LiteralString) | |
+ expr.value | |
+ elsif expr.instance_of?(Model::TextExpression) | |
+ eval_TextExpression(expr, scope) | |
+ else | |
+ evaluate(expr, scope) | |
+ end, | |
+ scope) | |
+ end.join | |
end | |
@@ -1085,38 +1120,16 @@ class EvaluatorImpl | |
if o.expr.is_a?(Model::QualifiedName) | |
string(get_variable_value(o.expr.value, o, scope), scope) | |
else | |
- string(evaluate(o.expr, scope), scope) | |
- end | |
- end | |
- | |
- def string_Object(o, scope) | |
- o.to_s | |
- end | |
- | |
- def string_Symbol(o, scope) | |
- if :undef == o # optimized comparison 1.44 vs 1.95 | |
- EMPTY_STRING | |
- else | |
- o.to_s | |
+ string( | |
+ if o.expr.instance_of?(Model::VariableExpression) | |
+ eval_VariableExpression(o.expr, scope) | |
+ else | |
+ evaluate(o.expr, scope) | |
+ end, | |
+ scope) | |
end | |
end | |
- def string_Array(o, scope) | |
- "[#{o.map {|e| string(e, scope)}.join(COMMA_SEPARATOR)}]" | |
- end | |
- | |
- def string_Hash(o, scope) | |
- "{#{o.map {|k,v| "#{string(k, scope)} => #{string(v, scope)}"}.join(COMMA_SEPARATOR)}}" | |
- end | |
- | |
- def string_Regexp(o, scope) | |
- Types::PRegexpType.regexp_to_s_with_delimiters(o) | |
- end | |
- | |
- def string_PAnyType(o, scope) | |
- o.to_s | |
- end | |
- | |
# Produces concatenation / merge of x and y. | |
# | |
# When x is an Array, y of type produces: | |
@@ -1267,7 +1280,13 @@ class EvaluatorImpl | |
if x.is_a?(Model::UnfoldExpression) | |
result.concat(evaluate(x, scope)) | |
else | |
- result << evaluate(x, scope) | |
+ result << if x.instance_of?(Model::LiteralString) | |
+ x.value | |
+ elsif x.instance_of?(Model::VariableExpression) | |
+ eval_VariableExpression(x, scope) | |
+ else | |
+ evaluate(x, scope) | |
+ end | |
end | |
end | |
result | |
diff --git a/lib/puppet/pops/evaluator/runtime3_resource_support.rb b/lib/puppet/pops/evaluator/runtime3_resource_support.rb | |
index b271924..4818072 100644 | |
--- a/lib/puppet/pops/evaluator/runtime3_resource_support.rb | |
+++ b/lib/puppet/pops/evaluator/runtime3_resource_support.rb | |
@@ -5,7 +5,7 @@ module Evaluator | |
module Runtime3ResourceSupport | |
CLASS_STRING = 'class'.freeze | |
- def self.create_resources(file, line, scope, virtual, exported, type_name, resource_titles, evaluated_parameters) | |
+ def self.create_resources(file, line, scope, virtual, exported, type_name, resource_titles, evaluated_parameters, ast_node = nil) | |
env = scope.environment | |
# loader = Adapters::LoaderAdapter.loader_for_model_object(o, scope) | |
@@ -31,22 +31,28 @@ module Runtime3ResourceSupport | |
raise ArgumentError, _("Unknown resource type: '%{type}'") % { type: type_name } | |
end | |
+ resource_attributes = { | |
+ :parameters => evaluated_parameters, | |
+ :exported => exported, | |
+ :virtual => virtual, | |
+ # WTF is this? Which source is this? The file? The name of the context ? | |
+ :source => scope.source, | |
+ :scope => scope, | |
+ :strict => true | |
+ } | |
+ | |
+ if ast_node | |
+ resource_attributes[:ast_node] = ast_node | |
+ else | |
+ resource_attributes[:file] = file | |
+ resource_attributes[:line] = line | |
+ end | |
+ | |
# Build a resource for each title - use the resolved *type* as opposed to a reference | |
# as this makes the created resource retain the type instance. | |
# | |
resource_titles.map do |resource_title| | |
- resource = Puppet::Parser::Resource.new( | |
- resolved_type, resource_title, | |
- :parameters => evaluated_parameters, | |
- :file => file, | |
- :line => line, | |
- :exported => exported, | |
- :virtual => virtual, | |
- # WTF is this? Which source is this? The file? The name of the context ? | |
- :source => scope.source, | |
- :scope => scope, | |
- :strict => true | |
- ) | |
+ resource = Puppet::Parser::Resource.new(resolved_type, resource_title, resource_attributes) | |
# If this resource type supports inheritance (e.g. 'class') the parent chain must be walked | |
# This impl delegates to the resource type to figure out what is needed. | |
@@ -114,4 +120,4 @@ module Runtime3ResourceSupport | |
end | |
end | |
-end | |
\ No newline at end of file | |
+end | |
diff --git a/lib/puppet/pops/evaluator/runtime3_support.rb b/lib/puppet/pops/evaluator/runtime3_support.rb | |
index 8a81768..01f4ba3 100644 | |
--- a/lib/puppet/pops/evaluator/runtime3_support.rb | |
+++ b/lib/puppet/pops/evaluator/runtime3_support.rb | |
@@ -318,11 +318,11 @@ module Runtime3Support | |
# The o is used for source reference | |
def create_resource_parameter(o, scope, name, value, operator) | |
- file, line = extract_file_line(o) | |
Puppet::Parser::Resource::Param.new( | |
:name => name, | |
:value => convert(value, scope, nil), # converted to 3x since 4x supports additional objects / types | |
- :source => scope.source, :line => line, :file => file, | |
+ :source => scope.source, | |
+ :ast_node => o, | |
:add => operator == '+>' | |
) | |
end | |
@@ -332,13 +332,7 @@ module Runtime3Support | |
end | |
def create_resources(o, scope, virtual, exported, type_name, resource_titles, evaluated_parameters) | |
- # Not 100% accurate as this is the resource expression location and each title is processed separately | |
- # The titles are however the result of evaluation and they have no location at this point (an array | |
- # of positions for the source expressions are required for this to work). | |
- # TODO: Revisit and possible improve the accuracy. | |
- # | |
- file, line = extract_file_line(o) | |
- Runtime3ResourceSupport.create_resources(file, line, scope, virtual, exported, type_name, resource_titles, evaluated_parameters) | |
+ Runtime3ResourceSupport.create_resources(nil, nil, scope, virtual, exported, type_name, resource_titles, evaluated_parameters, o) | |
end | |
# Defines default parameters for a type with the given name. | |
@@ -362,12 +356,6 @@ module Runtime3Support | |
# evaluated parameters are applied to all. | |
# | |
def create_resource_overrides(o, scope, evaluated_resources, evaluated_parameters) | |
- # Not 100% accurate as this is the resource expression location and each title is processed separately | |
- # The titles are however the result of evaluation and they have no location at this point (an array | |
- # of positions for the source expressions are required for this to work. | |
- # TODO: Revisit and possible improve the accuracy. | |
- # | |
- file, line = extract_file_line(o) | |
# A *=> results in an array of arrays | |
evaluated_parameters = evaluated_parameters.flatten | |
evaluated_resources.each do |r| | |
@@ -378,8 +366,7 @@ module Runtime3Support | |
resource = Puppet::Parser::Resource.new( | |
t, r.title, { | |
:parameters => evaluated_parameters, | |
- :file => file, | |
- :line => line, | |
+ :ast_node => o, | |
# WTF is this? Which source is this? The file? The name of the context ? | |
:source => scope.source, | |
:scope => scope | |
diff --git a/lib/puppet/pops/model/ast.rb b/lib/puppet/pops/model/ast.rb | |
index a4093c9..fecdea5 100644 | |
--- a/lib/puppet/pops/model/ast.rb | |
+++ b/lib/puppet/pops/model/ast.rb | |
@@ -104,11 +104,11 @@ class Positioned < PopsObject | |
end | |
def line | |
- @locator.line_for_offset(@offset) | |
+ @located_line ||= @locator.line_for_offset(@offset) | |
end | |
def pos | |
- @locator.pos_on_line(@offset) | |
+ @located_pos ||= @locator.pos_on_line(@offset) | |
end | |
def initialize(locator, offset, length) | |
diff --git a/lib/puppet/pops/types/iterable.rb b/lib/puppet/pops/types/iterable.rb | |
index 2c7a385..cf22923 100644 | |
--- a/lib/puppet/pops/types/iterable.rb | |
+++ b/lib/puppet/pops/types/iterable.rb | |
@@ -27,9 +27,9 @@ module Puppet::Pops::Types | |
# @return [Iterable,nil] The produced `Iterable` | |
# @raise [ArgumentError] In case an `Iterable` cannot be produced | |
# @api public | |
- def self.asserted_iterable(caller, obj) | |
- iter = self.on(obj) | |
- raise ArgumentError, "#{caller.class}(): wrong argument type (#{obj.class}; is not Iterable." if iter.nil? | |
+ def self.asserted_iterable(my_caller, obj, infer_elements = false) | |
+ iter = self.on(obj, nil, infer_elements) | |
+ raise ArgumentError, "#{my_caller.class}(): wrong argument type (#{obj.class}; is not Iterable." if iter.nil? | |
iter | |
end | |
@@ -52,7 +52,7 @@ module Puppet::Pops::Types | |
# @return [Iterable,nil] The produced `Iterable` or `nil` if it couldn't be produced | |
# | |
# @api public | |
- def self.on(o, element_type = nil) | |
+ def self.on(o, element_type = nil, infer_elements = true) | |
case o | |
when IteratorProducer | |
o.iterator | |
@@ -64,7 +64,7 @@ module Puppet::Pops::Types | |
if o.empty? | |
Iterator.new(PUnitType::DEFAULT, o.each) | |
else | |
- if element_type.nil? | |
+ if element_type.nil? && infer_elements | |
tc = TypeCalculator.singleton | |
element_type = PVariantType.maybe_create(o.map {|e| tc.infer_set(e) }) | |
end | |
@@ -75,7 +75,7 @@ module Puppet::Pops::Types | |
if o.empty? | |
HashIterator.new(PHashType::DEFAULT_KEY_PAIR_TUPLE, o.each) | |
else | |
- if element_type.nil? | |
+ if element_type.nil? && infer_elements | |
tc = TypeCalculator.singleton | |
element_type = PTupleType.new([ | |
PVariantType.maybe_create(o.keys.map {|e| tc.infer_set(e) }), | |
@@ -202,6 +202,26 @@ module Puppet::Pops::Types | |
@enumeration.send(name, *arguments, &block) | |
end | |
+ def next | |
+ @enumeration.next | |
+ end | |
+ | |
+ def map(*args, &block) | |
+ @enumeration.map(*args, &block) | |
+ end | |
+ | |
+ def reduce(*args, &block) | |
+ @enumeration.reduce(*args, &block) | |
+ end | |
+ | |
+ def all?(&block) | |
+ @enumeration.all?(&block) | |
+ end | |
+ | |
+ def any?(&block) | |
+ @enumeration.any?(&block) | |
+ end | |
+ | |
def step(step, &block) | |
raise ArgumentError if step <= 0 | |
r = self | |
diff --git a/lib/puppet/pops/validation/checker4_0.rb b/lib/puppet/pops/validation/checker4_0.rb | |
index 578d4f8..13c1179 100644 | |
--- a/lib/puppet/pops/validation/checker4_0.rb | |
+++ b/lib/puppet/pops/validation/checker4_0.rb | |
@@ -575,36 +575,40 @@ class Checker4_0 < Evaluator::LiteralEvaluator | |
# @api private | |
class Puppet::Util::FileNamespaceAdapter < Puppet::Pops::Adaptable::Adapter | |
attr_accessor :file_to_namespace | |
+ | |
+ def self.create_adapter(env) | |
+ a = super(env) | |
+ a.file_to_namespace = {} | |
+ a | |
+ end | |
end | |
def namespace_for_file(file) | |
env = Puppet.lookup(:current_environment) | |
return NO_NAMESPACE if env.nil? | |
- Puppet::Util::FileNamespaceAdapter.adapt(env) do |adapter| | |
- adapter.file_to_namespace ||= {} | |
+ adapter = Puppet::Util::FileNamespaceAdapter.adapt(env) | |
- file_namespace = adapter.file_to_namespace[file] | |
- return file_namespace unless file_namespace.nil? # No cache entry, so we do the calculation | |
+ file_namespace = adapter.file_to_namespace[file] | |
+ return file_namespace unless file_namespace.nil? # No cache entry, so we do the calculation | |
- path = Pathname.new(file) | |
+ path = Pathname.new(file) | |
- return adapter.file_to_namespace[file] = NO_NAMESPACE if path.extname != ".pp" | |
+ return adapter.file_to_namespace[file] = NO_NAMESPACE if path.extname != ".pp" | |
- path = path.expand_path | |
+ path = path.expand_path | |
- return adapter.file_to_namespace[file] = NO_NAMESPACE if initial_manifest?(path, env.manifest) | |
+ return adapter.file_to_namespace[file] = NO_NAMESPACE if initial_manifest?(path, env.manifest) | |
- #All auto-loaded files from modules come from a module search path dir | |
- relative_path = get_module_relative_path(path, env.full_modulepath) | |
+ #All auto-loaded files from modules come from a module search path dir | |
+ relative_path = get_module_relative_path(path, env.full_modulepath) | |
- return adapter.file_to_namespace[file] = NO_NAMESPACE if relative_path == NO_PATH | |
+ return adapter.file_to_namespace[file] = NO_NAMESPACE if relative_path == NO_PATH | |
- #If a file comes from a module, but isn't in the right place, always error | |
- names = dir_to_names(relative_path) | |
+ #If a file comes from a module, but isn't in the right place, always error | |
+ names = dir_to_names(relative_path) | |
- return adapter.file_to_namespace[file] = (names == BAD_MODULE_FILE ? BAD_MODULE_FILE : names.join("::").freeze) | |
- end | |
+ return adapter.file_to_namespace[file] = (names == BAD_MODULE_FILE ? BAD_MODULE_FILE : names.join("::").freeze) | |
end | |
def initial_manifest?(path, manifest_setting) | |
diff --git a/lib/puppet/resource.rb b/lib/puppet/resource.rb | |
index 6924c09..db15b21 100644 | |
--- a/lib/puppet/resource.rb | |
+++ b/lib/puppet/resource.rb | |
@@ -11,7 +11,7 @@ class Puppet::Resource | |
include Puppet::Util::PsychSupport | |
include Enumerable | |
- attr_accessor :file, :line, :catalog, :exported, :virtual, :strict | |
+ attr_accessor :catalog, :exported, :virtual, :strict, :ast_node | |
attr_reader :type, :title, :parameters, :rich_data_enabled | |
# @!attribute [rw] sensitive_parameters | |
@@ -66,12 +66,32 @@ class Puppet::Resource | |
tag(*tags) | |
end | |
+ if data[:ast_node] | |
+ self.ast_node = data[:ast_node] | |
+ end | |
+ | |
ATTRIBUTES.each do |a| | |
value = data[a.to_s] | |
send("#{a}=", value) unless value.nil? | |
end | |
end | |
+ def file | |
+ @file ||= @ast_node && @ast_node.file | |
+ end | |
+ | |
+ def file=(filepath) | |
+ @file = filepath | |
+ end | |
+ | |
+ def line | |
+ @line ||= @ast_node && @ast_node.line | |
+ end | |
+ | |
+ def line=(lineno) | |
+ @line = lineno | |
+ end | |
+ | |
def inspect | |
"#{@type}[#{@title}]#{to_hash.inspect}" | |
end | |
@@ -224,8 +244,11 @@ class Puppet::Resource | |
if type.is_a?(Puppet::Resource) | |
# Copy constructor. Let's avoid munging, extracting, tagging, etc | |
src = type | |
- self.file = src.file | |
- self.line = src.line | |
+ self.ast_node = src.ast_node | |
+ unless ast_node | |
+ self.file = src.file | |
+ self.line = src.line | |
+ end | |
self.exported = src.exported | |
self.virtual = src.virtual | |
self.set_tags(src) | |
@@ -658,7 +681,7 @@ class Puppet::Resource | |
type.title_patterns.each { |regexp, symbols_and_lambdas| | |
if captures = regexp.match(title.to_s) | |
symbols_and_lambdas.zip(captures[1..-1]).each do |symbol_and_lambda,capture| | |
- symbol, proc = symbol_and_lambda | |
+ symbol, procedure = symbol_and_lambda | |
# Many types pass "identity" as the proc; we might as well give | |
# them a shortcut to delivering that without the extra cost. | |
# | |
@@ -667,8 +690,8 @@ class Puppet::Resource | |
# | |
# This was worth about 8MB of memory allocation saved in my | |
# testing, so is worth the complexity for the API. | |
- if proc then | |
- h[symbol] = proc.call(capture) | |
+ if procedure then | |
+ h[symbol] = procedure.call(capture) | |
else | |
h[symbol] = capture | |
end | |
diff --git a/lib/puppet/util/autoload.rb b/lib/puppet/util/autoload.rb | |
index 7778c8d..66bbe20 100644 | |
--- a/lib/puppet/util/autoload.rb | |
+++ b/lib/puppet/util/autoload.rb | |
@@ -10,6 +10,14 @@ require 'puppet/pops/adaptable' | |
# @api private | |
class Puppet::Util::ModuleDirectoriesAdapter < Puppet::Pops::Adaptable::Adapter | |
attr_accessor :directories | |
+ | |
+ def self.create_adapter(env) | |
+ a = super(env) | |
+ a.directories = env.modulepath.flat_map do |dir| | |
+ Dir.glob(File.join(dir, '*', 'lib')) | |
+ end | |
+ a | |
+ end | |
end | |
# Autoload paths, either based on names or all at once. | |
@@ -132,13 +140,7 @@ class Puppet::Util::Autoload | |
if env | |
# if the app defaults have been initialized then it should be safe to access the module path setting. | |
- Puppet::Util::ModuleDirectoriesAdapter.adapt(env) do |a| | |
- a.directories ||= env.modulepath.collect do |dir| | |
- Dir.entries(dir).reject { |f| f =~ /^\./ }.collect { |f| File.join(dir, f, "lib") } | |
- end.flatten.find_all do |d| | |
- FileTest.directory?(d) | |
- end | |
- end.directories | |
+ Puppet::Util::ModuleDirectoriesAdapter.adapt(env).directories | |
else | |
[] | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/lib/puppet/functions/reverse_each.rb b/lib/puppet/functions/reverse_each.rb | |
index fb81a99..3b0c907 100644 | |
--- a/lib/puppet/functions/reverse_each.rb | |
+++ b/lib/puppet/functions/reverse_each.rb | |
@@ -84,7 +84,7 @@ Puppet::Functions.create_function(:reverse_each) do | |
def reverse_each(iterable) | |
# produces an Iterable | |
- Puppet::Pops::Types::Iterable.asserted_iterable(self, iterable).reverse_each | |
+ Puppet::Pops::Types::Iterable.asserted_iterable(self, iterable, true).reverse_each | |
end | |
def reverse_each_block(iterable, &block) | |
diff --git a/lib/puppet/functions/step.rb b/lib/puppet/functions/step.rb | |
index 8860149..d6e1ad1 100644 | |
--- a/lib/puppet/functions/step.rb | |
+++ b/lib/puppet/functions/step.rb | |
@@ -88,7 +88,7 @@ Puppet::Functions.create_function(:step) do | |
def step(iterable, step) | |
# produces an Iterable | |
- Puppet::Pops::Types::Iterable.asserted_iterable(self, iterable).step(step) | |
+ Puppet::Pops::Types::Iterable.asserted_iterable(self, iterable, true).step(step) | |
end | |
def step_block(iterable, step, &block) | |
diff --git a/lib/puppet/pops/types/iterable.rb b/lib/puppet/pops/types/iterable.rb | |
index 2c7a385..cf22923 100644 | |
--- a/lib/puppet/pops/types/iterable.rb | |
+++ b/lib/puppet/pops/types/iterable.rb | |
@@ -27,9 +27,9 @@ module Puppet::Pops::Types | |
# @return [Iterable,nil] The produced `Iterable` | |
# @raise [ArgumentError] In case an `Iterable` cannot be produced | |
# @api public | |
- def self.asserted_iterable(caller, obj) | |
- iter = self.on(obj) | |
- raise ArgumentError, "#{caller.class}(): wrong argument type (#{obj.class}; is not Iterable." if iter.nil? | |
+ def self.asserted_iterable(my_caller, obj, infer_elements = false) | |
+ iter = self.on(obj, nil, infer_elements) | |
+ raise ArgumentError, "#{my_caller.class}(): wrong argument type (#{obj.class}; is not Iterable." if iter.nil? | |
iter | |
end | |
@@ -52,7 +52,7 @@ module Puppet::Pops::Types | |
# @return [Iterable,nil] The produced `Iterable` or `nil` if it couldn't be produced | |
# | |
# @api public | |
- def self.on(o, element_type = nil) | |
+ def self.on(o, element_type = nil, infer_elements = true) | |
case o | |
when IteratorProducer | |
o.iterator | |
@@ -64,7 +64,7 @@ module Puppet::Pops::Types | |
if o.empty? | |
Iterator.new(PUnitType::DEFAULT, o.each) | |
else | |
- if element_type.nil? | |
+ if element_type.nil? && infer_elements | |
tc = TypeCalculator.singleton | |
element_type = PVariantType.maybe_create(o.map {|e| tc.infer_set(e) }) | |
end | |
@@ -75,7 +75,7 @@ module Puppet::Pops::Types | |
if o.empty? | |
HashIterator.new(PHashType::DEFAULT_KEY_PAIR_TUPLE, o.each) | |
else | |
- if element_type.nil? | |
+ if element_type.nil? && infer_elements | |
tc = TypeCalculator.singleton | |
element_type = PTupleType.new([ | |
PVariantType.maybe_create(o.keys.map {|e| tc.infer_set(e) }), | |
@@ -202,6 +202,26 @@ module Puppet::Pops::Types | |
@enumeration.send(name, *arguments, &block) | |
end | |
+ def next | |
+ @enumeration.next | |
+ end | |
+ | |
+ def map(*args, &block) | |
+ @enumeration.map(*args, &block) | |
+ end | |
+ | |
+ def reduce(*args, &block) | |
+ @enumeration.reduce(*args, &block) | |
+ end | |
+ | |
+ def all?(&block) | |
+ @enumeration.all?(&block) | |
+ end | |
+ | |
+ def any?(&block) | |
+ @enumeration.any?(&block) | |
+ end | |
+ | |
def step(step, &block) | |
raise ArgumentError if step <= 0 | |
r = self |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment